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
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"]163
mod tests;164