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 acpi_table.clear_checksums();
91 let mut table_loader_bytes: Vec<u8> = Vec::new();
92 let allocate_rsdp = Allocate {
93 command: COMMAND_ALLOCATE,
94 file: create_file_name(FW_CFG_FILENAME_RSDP),
95 align: 4,
96 zone: ALLOC_ZONE_FSEG,
97 _pad: [0; 63],
98 };
99 table_loader_bytes.extend(allocate_rsdp.as_bytes());
100
101 let allocate_tables = Allocate {
102 command: COMMAND_ALLOCATE,
103 file: create_file_name(FW_CFG_FILENAME_ACPI_TABLES),
104 align: 4,
105 zone: ALLOC_ZONE_HIGH,
106 _pad: [0; 63],
107 };
108 table_loader_bytes.extend(allocate_tables.as_bytes());
109
110 for pinter_offset in acpi_table.pointers().iter() {
111 let pinter = create_intra_pointer(FW_CFG_FILENAME_ACPI_TABLES, *pinter_offset, 8);
112 table_loader_bytes.extend(pinter.as_bytes());
113 }
114 for (offset, len) in acpi_table.checksums().iter() {
115 let checksum = create_acpi_table_checksum(*offset, *len);
116 table_loader_bytes.extend(checksum.as_bytes());
117 }
118 let pointer_rsdp_to_xsdt = AddPointer {
119 command: COMMAND_ADD_POINTER,
120 dst: create_file_name(FW_CFG_FILENAME_RSDP),
121 src: create_file_name(FW_CFG_FILENAME_ACPI_TABLES),
122 offset: offset_of!(AcpiTableRsdp, xsdt_physical_address) as u32,
123 size: 8,
124 _pad: [0; 7],
125 };
126 table_loader_bytes.extend(pointer_rsdp_to_xsdt.as_bytes());
127 let checksum_rsdp = AddChecksum {
128 command: COMMAND_ADD_CHECKSUM,
129 file: create_file_name(FW_CFG_FILENAME_RSDP),
130 offset: offset_of!(AcpiTableRsdp, checksum) as u32,
131 start: 0,
132 len: offset_of!(AcpiTableRsdp, length) as u32,
133 _pad: [0; 56],
134 };
135 let checksum_rsdp_ext = AddChecksum {
136 command: COMMAND_ADD_CHECKSUM,
137 file: create_file_name(FW_CFG_FILENAME_RSDP),
138 offset: offset_of!(AcpiTableRsdp, extended_checksum) as u32,
139 start: 0,
140 len: size_of::<AcpiTableRsdp>() as u32,
141 _pad: [0; 56],
142 };
143 table_loader_bytes.extend(checksum_rsdp.as_bytes());
144 table_loader_bytes.extend(checksum_rsdp_ext.as_bytes());
145
146 let table_loader = FwCfgItem {
147 name: FW_CFG_FILENAME_TABLE_LOADER.to_owned(),
148 content: FwCfgContent::Bytes(table_loader_bytes),
149 };
150 let (rsdp, tables) = acpi_table.take();
151 let acpi_rsdp = FwCfgItem {
152 name: FW_CFG_FILENAME_RSDP.to_owned(),
153 content: FwCfgContent::Bytes(rsdp.as_bytes().to_owned()),
154 };
155 let apci_tables = FwCfgItem {
156 name: FW_CFG_FILENAME_ACPI_TABLES.to_owned(),
157 content: FwCfgContent::Bytes(tables),
158 };
159 [table_loader, acpi_rsdp, apci_tables]
160}
161
162#[cfg(test)]
163#[path = "acpi_test.rs"]
164mod tests;
165