Skip to content

Commit

Permalink
td-shim: Migrate the bin directory
Browse files Browse the repository at this point in the history
Signed-off-by: haowx <weix.hao.intel.com>
  • Loading branch information
haowx committed Mar 21, 2022
1 parent fa964f6 commit 314d1c6
Show file tree
Hide file tree
Showing 25 changed files with 2,869 additions and 8 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
Cargo.lock
target/
*.bin
*.obj
# afl fuzz
out
*.profraw
# Intellj working directory
.idea
Expand Down
7 changes: 0 additions & 7 deletions td-shim/.gitignore

This file was deleted.

4 changes: 4 additions & 0 deletions td-shim/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ edition = "2018"
# add build process
build = "build.rs"

[[bin]]
name = "td-shim"
required-features = ["main"]

[build-dependencies]
anyhow = "1.0.55"
cc = { git = "https://github.com/jyao1/cc-rs.git", branch = "uefi_support" }
Expand Down
177 changes: 177 additions & 0 deletions td-shim/src/bin/td-shim/acpi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
// Copyright (c) 2021 Intel Corporation
// Copyright (c) 2022 Alibaba Cloud
//
// SPDX-License-Identifier: BSD-2-Clause-Patent
extern crate alloc;

use alloc::vec::Vec;
use td_shim::acpi::{calculate_checksum, Rsdp, Xsdt};

use super::*;

#[derive(Default)]
pub struct AcpiTables<'a> {
acpi_memory: &'a mut [u8],
pa: u64,
size: usize,
fadt: Option<(usize, usize)>, // FADT offset in acpi memory
dsdt: Option<usize>, // DSDT offset in acpi memory
table_offset: Vec<usize>,
}

impl<'a> AcpiTables<'a> {
pub fn new(td_acpi_mem: &'a mut [u8], pa: u64) -> Self {
AcpiTables {
acpi_memory: td_acpi_mem,
pa,
..Default::default()
}
}

pub fn finish(&mut self) -> u64 {
let mut xsdt = Xsdt::new();

// The Fixed ACPI Description Table (FADT) should always be the first table in XSDT.
if let Some((fadt_off, fadt_len)) = self.fadt {
// Safe because DSDT is loaded in acpi_memory which is below 4G
let dsdt = self
.dsdt
.as_ref()
.map(|v| self.offset_to_address(*v))
.unwrap_or_default() as u32;
let fadt = &mut self.acpi_memory[fadt_off..fadt_off + fadt_len];
// The Differentiated System Description Table (DSDT) is referred by the FADT table.
if dsdt != 0 {
// The DSDT field of FADT [40..44]
dsdt.write_to(&mut fadt[40..44]);
}

// Update FADT checksum
fadt[9] = 0;
fadt[9] = calculate_checksum(fadt);
xsdt.add_table(self.offset_to_address(fadt_off));
}

for offset in &self.table_offset {
xsdt.add_table(self.offset_to_address(*offset));
}

let xsdt_addr = self.offset_to_address(self.size);
xsdt.checksum();
xsdt.write_to(&mut self.acpi_memory[self.size..self.size + size_of::<Xsdt>()]);
self.size += size_of::<Xsdt>();

let rsdp_addr = self.offset_to_address(self.size);
let rsdp = Rsdp::new(xsdt_addr);
rsdp.write_to(&mut self.acpi_memory[self.size..self.size + size_of::<Rsdp>()]);
self.size += size_of::<Rsdp>();

rsdp_addr as u64
}

pub fn install(&mut self, table: &[u8]) {
// Also reserve space for Xsdt and Rsdp
let total_size = self.size + table.len() + size_of::<Xsdt>() + size_of::<Rsdp>();
if self.acpi_memory.len() < total_size {
log::error!(
"ACPI content size exceeds limit 0x{:X}",
self.acpi_memory.len(),
);
return;
} else if table.len() < size_of::<GenericSdtHeader>() {
log::error!("ACPI table with length 0x{:X} is invalid", table.len());
return;
}

// Safe because we have checked buffer size.
let header = GenericSdtHeader::read_from(&table[..size_of::<GenericSdtHeader>()]).unwrap();
if header.length as usize > table.len() {
log::error!(
"invalid ACPI table, header length {} is bigger than data length {}",
header.length as usize,
table.len()
);
return;
}

if &header.signature == b"FACP" {
// We will write to the `dsdt` fields at [40-44)
if header.length < 44 {
log::error!("invalid ACPI FADT table");
return;
}
self.fadt = Some((self.size, header.length as usize));
} else if &header.signature == b"DSDT" {
self.dsdt = Some(self.size);
} else {
for offset in &self.table_offset {
// Safe because it's reading data from our own buffer.
let table_header = GenericSdtHeader::read_from(
&self.acpi_memory[*offset..*offset + size_of::<GenericSdtHeader>()],
)
.unwrap();
if table_header.signature == header.signature {
log::info!(
"ACPI: {} has been installed, use first\n",
core::str::from_utf8(&header.signature).unwrap_or_default()
);
return;
}
}
self.table_offset.push(self.size);
}

self.acpi_memory[self.size..self.size + table.len()].copy_from_slice(table);
self.size += table.len();
}

fn offset_to_address(&self, offset: usize) -> u64 {
self.pa + offset as u64
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_acpi_tables() {
let mut buff = [0u8; 500];
let mut tables = AcpiTables::new(&mut buff, 0x100000);

assert_eq!(tables.offset_to_address(0x1000), 0x101000);
assert_eq!(tables.size, 0);

tables.install(&[]);
assert_eq!(tables.size, 0);
tables.install(&[0u8]);
assert_eq!(tables.size, 0);
tables.install(&[0u8; 269]);
assert_eq!(tables.size, 0);

let hdr = GenericSdtHeader::new(b"FACP", 44, 2);
let mut buf = [0u8; 44];
buf[0..size_of::<GenericSdtHeader>()].copy_from_slice(hdr.as_bytes());
tables.install(&buf);
assert_eq!(tables.fadt, Some((0, 44)));
assert_eq!(tables.size, 44);

let hdr = GenericSdtHeader::new(b"DSDT", size_of::<GenericSdtHeader>() as u32, 2);
tables.install(hdr.as_bytes());
assert_eq!(tables.size, 44 + size_of::<GenericSdtHeader>());

let hdr = GenericSdtHeader::new(b"TEST", size_of::<GenericSdtHeader>() as u32, 2);
tables.install(hdr.as_bytes());
assert_eq!(tables.size, 44 + 2 * size_of::<GenericSdtHeader>());

let hdr = GenericSdtHeader::new(b"TEST", size_of::<GenericSdtHeader>() as u32, 2);
tables.install(hdr.as_bytes());
assert_eq!(tables.size, 44 + 2 * size_of::<GenericSdtHeader>());

let addr = tables.finish();
assert_eq!(
addr,
0x100000 + 240 + 2 * size_of::<GenericSdtHeader>() as u64
);
}
}
90 changes: 90 additions & 0 deletions td-shim/src/bin/td-shim/asm/ap_loop.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Copyright (c) 2022 Intel Corporation
# SPDX-License-Identifier: BSD-2-Clause-Patent

.set TDVMCALL_EXPOSE_REGS_MASK, 0xffec
.set TDVMCALL, 0x0
.set INSTRUCTION_CPUID, 0xa

.set CommandOffset, 0
.set ApicIdOffset, 0x4
.set WakeupVectorOffset, 0x8

.set MpProtectedModeWakeupCommandNoop, 0
.set MpProtectedModeWakeupCommandWakeup, 1
.set MpProtectedModeWakeupCommandSleep, 2

.set MailboxApicIdInvalid, 0xffffffff
.set MailboxApicIdBroadcast, 0xfffffffe

.section .text
#---------------------------------------------------------------------
# ap_relocated_func_size (
# size: *mut u64, // rcx
# );
#---------------------------------------------------------------------
.global ap_relocated_func_size
ap_relocated_func_size:
push rax
push rbx
lea rax, .ap_relocated_func_end
lea rbx, ap_relocated_func
sub rax, rbx
mov qword ptr[rcx], rax
pop rbx
pop rax
ret

#--------------------------------------------------------------------
# ap_relocated_vector
#
# rbx: Relocated mailbox address
# rbp: vCpuId
#--------------------------------------------------------------------
.global ap_relocated_func
ap_relocated_func:
#
# Get the APIC ID via TDVMCALL
mov rax, TDVMCALL
mov rcx, TDVMCALL_EXPOSE_REGS_MASK
mov r10, 0
mov r11, INSTRUCTION_CPUID
mov r12, 0xb
mov r13, 0
# TDVMCALL
.byte 0x66, 0x0f, 0x01, 0xcc
test rax, rax
jnz .panic
#
# r8 will hold the APIC ID of current AP
mov r8, r15

.check_apicid:
#
# Determine if this is a broadcast or directly for my apic-id, if not, ignore
cmp dword ptr[rbx + ApicIdOffset], MailboxApicIdBroadcast
je .check_command
cmp dword ptr[rbx + ApicIdOffset], r8d
jne .check_apicid

.check_command:
mov eax, dword ptr[rbx + CommandOffset]
cmp eax, MpProtectedModeWakeupCommandNoop
je .check_apicid

cmp eax, MpProtectedModeWakeupCommandWakeup
je .wakeup

jmp .check_apicid

.wakeup:
#
# BSP sets these variables before unblocking APs
mov rax, 0
mov eax, dword ptr[rbx + WakeupVectorOffset]
nop
jmp rax

.panic:
ud2

.ap_relocated_func_end:
11 changes: 11 additions & 0 deletions td-shim/src/bin/td-shim/asm/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) 2020-2022 Intel Corporation
//
// SPDX-License-Identifier: BSD-2-Clause-Patent
global_asm!(include_str!("switch_stack.asm"));
global_asm!(include_str!("msr64.asm"));
global_asm!(include_str!("ap_loop.asm"));

extern "win64" {
pub fn ap_relocated_func_size(size: *mut u64);
pub fn ap_relocated_func();
}
26 changes: 26 additions & 0 deletions td-shim/src/bin/td-shim/asm/msr64.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright (c) 2021 Intel Corporation
# SPDX-License-Identifier: BSD-2-Clause-Patent

.section .text
# asm_read_msr64(
# index: u32, // rcx
# );
.global asm_read_msr64
asm_read_msr64:

rdmsr
shl rdx, 0x20
or rax, rdx
ret

# asm_write_msr64(
# index: u32, // rcx
# value: u64, // rdx
# );
.global asm_write_msr64
asm_write_msr64:

mov rax, rdx
shr rdx, 0x20
wrmsr
ret
22 changes: 22 additions & 0 deletions td-shim/src/bin/td-shim/asm/switch_stack.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright (c) 2020 Intel Corporation
# SPDX-License-Identifier: BSD-2-Clause-Patent

.section .text

# switch_stack_call(
# entry_point: usize, // rcx
# stack_top: usize, // rdx
# P1: usize, // r8
# P2: usize // r9
# );
.global switch_stack_call
switch_stack_call:
sub rdx,0x20
mov rsp,rdx
mov rax,rcx
mov rcx,r8
mov rdx,r9
call rax
int3
jmp switch_stack_call
ret
Loading

0 comments on commit 314d1c6

Please sign in to comment.