Alioth Code Coverage

acpi.rs0.00%

1// Copyright 2024 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::mem::{offset_of, size_of};
16
17use zerocopy::{Immutable, IntoBytes};
18
19use crate::device::fw_cfg::{FILE_NAME_SIZE, FwCfgContent, FwCfgItem, create_file_name};
20use crate::firmware::acpi::AcpiTable;
21use crate::firmware::acpi::bindings::{AcpiTableHeader, AcpiTableRsdp};
22
23pub const COMMAND_ALLOCATE: u32 = 0x1;
24pub const COMMAND_ADD_POINTER: u32 = 0x2;
25pub const COMMAND_ADD_CHECKSUM: u32 = 0x3;
26
27pub const ALLOC_ZONE_HIGH: u8 = 0x1;
28pub const ALLOC_ZONE_FSEG: u8 = 0x2;
29
30pub const FW_CFG_FILENAME_TABLE_LOADER: &str = "etc/table-loader";
31pub const FW_CFG_FILENAME_RSDP: &str = "acpi/rsdp";
32pub const FW_CFG_FILENAME_ACPI_TABLES: &str = "acpi/tables";
33
34#[repr(C, align(4))]
35#[derive(Debug, IntoBytes, Immutable)]
36pub struct Allocate {
37 command: u32,
38 file: [u8; FILE_NAME_SIZE],
39 align: u32,
40 zone: u8,
41 _pad: [u8; 63],
42}
43
44#[repr(C, align(4))]
45#[derive(Debug, IntoBytes, Immutable)]
46pub struct AddPointer {
47 command: u32,
48 dst: [u8; FILE_NAME_SIZE],
49 src: [u8; FILE_NAME_SIZE],
50 offset: u32,
51 size: u8,
52 _pad: [u8; 7],
53}
54
55#[repr(C, align(4))]
56#[derive(Debug, IntoBytes, Immutable)]
57pub struct AddChecksum {
58 command: u32,
59 file: [u8; FILE_NAME_SIZE],
60 offset: u32,
61 start: u32,
62 len: u32,
63 _pad: [u8; 56],
64}
65
66fn create_intra_pointer(name: &str, offset: usize, size: u8) -> AddPointer {
67 AddPointer {
68 command: COMMAND_ADD_POINTER,
69 dst: create_file_name(name),
70 src: create_file_name(name),
71 offset: offset as u32,
72 size,
73 _pad: [0; 7],
74 }
75}
76
77fn create_acpi_table_checksum(offset: usize, len: usize) -> AddChecksum {
78 AddChecksum {
79 command: COMMAND_ADD_CHECKSUM,
80 file: create_file_name(FW_CFG_FILENAME_ACPI_TABLES),
81 offset: (offset + offset_of!(AcpiTableHeader, checksum)) as u32,
82 start: offset as u32,
83 len: len as u32,
84 _pad: [0; 56],
85 }
86}
87
88pub fn create_acpi_loader(mut acpi_table: AcpiTable) -> [FwCfgItem; 3] {
89 acpi_table.relocate(0);
90 let mut table_loader_bytes: Vec<u8> = Vec::new();
91 let allocate_rsdp = Allocate {
92 command: COMMAND_ALLOCATE,
93 file: create_file_name(FW_CFG_FILENAME_RSDP),
94 align: 4,
95 zone: ALLOC_ZONE_FSEG,
96 _pad: [0; 63],
97 };
98 table_loader_bytes.extend(allocate_rsdp.as_bytes());
99
100 let allocate_tables = Allocate {
101 command: COMMAND_ALLOCATE,
102 file: create_file_name(FW_CFG_FILENAME_ACPI_TABLES),
103 align: 4,
104 zone: ALLOC_ZONE_HIGH,
105 _pad: [0; 63],
106 };
107 table_loader_bytes.extend(allocate_tables.as_bytes());
108
109 for pinter_offset in acpi_table.pointers().iter() {
110 let pinter = create_intra_pointer(FW_CFG_FILENAME_ACPI_TABLES, *pinter_offset, 8);
111 table_loader_bytes.extend(pinter.as_bytes());
112 }
113 for (offset, len) in acpi_table.checksums().iter() {
114 let checksum = create_acpi_table_checksum(*offset, *len);
115 table_loader_bytes.extend(checksum.as_bytes());
116 }
117 let pointer_rsdp_to_xsdt = AddPointer {
118 command: COMMAND_ADD_POINTER,
119 dst: create_file_name(FW_CFG_FILENAME_RSDP),
120 src: create_file_name(FW_CFG_FILENAME_ACPI_TABLES),
121 offset: offset_of!(AcpiTableRsdp, xsdt_physical_address) as u32,
122 size: 8,
123 _pad: [0; 7],
124 };
125 table_loader_bytes.extend(pointer_rsdp_to_xsdt.as_bytes());
126 let checksum_rsdp = AddChecksum {
127 command: COMMAND_ADD_CHECKSUM,
128 file: create_file_name(FW_CFG_FILENAME_RSDP),
129 offset: offset_of!(AcpiTableRsdp, checksum) as u32,
130 start: 0,
131 len: offset_of!(AcpiTableRsdp, length) as u32,
132 _pad: [0; 56],
133 };
134 let checksum_rsdp_ext = AddChecksum {
135 command: COMMAND_ADD_CHECKSUM,
136 file: create_file_name(FW_CFG_FILENAME_RSDP),
137 offset: offset_of!(AcpiTableRsdp, extended_checksum) as u32,
138 start: 0,
139 len: size_of::<AcpiTableRsdp>() as u32,
140 _pad: [0; 56],
141 };
142 table_loader_bytes.extend(checksum_rsdp.as_bytes());
143 table_loader_bytes.extend(checksum_rsdp_ext.as_bytes());
144
145 let table_loader = FwCfgItem {
146 name: FW_CFG_FILENAME_TABLE_LOADER.to_owned(),
147 content: FwCfgContent::Bytes(table_loader_bytes),
148 };
149 let (rsdp, tables) = acpi_table.take();
150 let acpi_rsdp = FwCfgItem {
151 name: FW_CFG_FILENAME_RSDP.to_owned(),
152 content: FwCfgContent::Bytes(rsdp.as_bytes().to_owned()),
153 };
154 let apci_tables = FwCfgItem {
155 name: FW_CFG_FILENAME_ACPI_TABLES.to_owned(),
156 content: FwCfgContent::Bytes(tables),
157 };
158 [table_loader, acpi_rsdp, apci_tables]
159}
160
161#[cfg(test)]
162#[path = "acpi_test.rs"]
163mod tests;
164