acpi.rs0.00%
1
// Copyright 2024 Google LLC2
//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 at6
//7
// https://www.apache.org/licenses/LICENSE-2.08
//9
// Unless required by applicable law or agreed to in writing, software10
// 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 and13
// limitations under the License.14
15
use std::mem::{offset_of, size_of};16
17
use zerocopy::{Immutable, IntoBytes};18
19
use crate::device::fw_cfg::{FILE_NAME_SIZE, FwCfgContent, FwCfgItem, create_file_name};20
use crate::firmware::acpi::AcpiTable;21
use crate::firmware::acpi::bindings::{AcpiTableHeader, AcpiTableRsdp};22
23
pub const COMMAND_ALLOCATE: u32 = 0x1;24
pub const COMMAND_ADD_POINTER: u32 = 0x2;25
pub const COMMAND_ADD_CHECKSUM: u32 = 0x3;26
27
pub const ALLOC_ZONE_HIGH: u8 = 0x1;28
pub const ALLOC_ZONE_FSEG: u8 = 0x2;29
30
pub const FW_CFG_FILENAME_TABLE_LOADER: &str = "etc/table-loader";31
pub const FW_CFG_FILENAME_RSDP: &str = "acpi/rsdp";32
pub const FW_CFG_FILENAME_ACPI_TABLES: &str = "acpi/tables";33
34
#[repr(C, align(4))]35
#[derive(Debug, IntoBytes, Immutable)]36
pub 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)]46
pub 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)]57
pub 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
66
fn 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
77
fn 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
88
pub 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"]164
mod tests;165