From f4f5fcc06dc7c1c1f32387e29e7f74ad02f45d28 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Sat, 30 May 2026 15:43:44 -0700 Subject: [PATCH] devices: add TPM CRB regression tests Cover the short CRB register accesses and data-buffer boundary conditions used by Windows Server 2025. Assisted-by: Copilot:GPT-5.5 Signed-off-by: Wei Liu --- devices/src/tpm.rs | 73 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/devices/src/tpm.rs b/devices/src/tpm.rs index 3dd2868ff..d2fd55071 100644 --- a/devices/src/tpm.rs +++ b/devices/src/tpm.rs @@ -238,6 +238,13 @@ fn read_reg_value(value: u32, offset: u32) -> u32 { value >> (byte_offset * 8) } +#[cfg(test)] +fn read_reg(regs: &[u32; TPM_CRB_R_MAX], offset: u32) -> u32 { + let reg_offset = (offset & !0x3) as usize; + + read_reg_value(regs[reg_offset], offset) +} + fn complete_request(regs: &mut [u32; TPM_CRB_R_MAX], success: bool) { regs[CRB_CTRL_START as usize] &= !CRB_START_INVOKE; if !success { @@ -595,4 +602,70 @@ mod unit_tests { assert_eq!(regs[CRB_CTRL_CMD_SIZE_REG as usize], 0x1234_aa78); } + + #[test] + fn test_update_reg_preserves_untouched_byte_lanes() { + let mut regs: [u32; TPM_CRB_R_MAX] = [0; TPM_CRB_R_MAX]; + regs[CRB_CTRL_CMD_LADDR as usize] = 0x1122_3344; + + update_reg(&mut regs, CRB_CTRL_CMD_LADDR + 1, &[0xaa, 0xbb]); + + assert_eq!(regs[CRB_CTRL_CMD_LADDR as usize], 0x11bb_aa44); + } + + #[test] + fn test_read_reg_partial_read_uses_byte_offset() { + let mut regs: [u32; TPM_CRB_R_MAX] = [0; TPM_CRB_R_MAX]; + regs[CRB_CTRL_CMD_SIZE_REG as usize] = 0x1234_5678; + + assert_eq!(read_reg(®s, CRB_CTRL_CMD_SIZE_REG + 1) as u8, 0x56); + assert_eq!(read_reg(®s, CRB_CTRL_CMD_SIZE_REG + 2) as u16, 0x1234); + assert_eq!(read_reg_value(0x1, CRB_LOC_STATE + 1) as u8, 0); + } + + #[test] + fn test_complete_request_preserves_reserved_bits() { + let mut regs: [u32; TPM_CRB_R_MAX] = [0; TPM_CRB_R_MAX]; + regs[CRB_CTRL_START as usize] = 0xffff_fffe | CRB_START_INVOKE; + + complete_request(&mut regs, true); + + assert_eq!(regs[CRB_CTRL_START as usize], 0xffff_fffe); + } + + #[test] + fn test_complete_request_sets_error_status_on_failure() { + let mut regs: [u32; TPM_CRB_R_MAX] = [0; TPM_CRB_R_MAX]; + regs[CRB_CTRL_START as usize] = CRB_START_INVOKE; + + complete_request(&mut regs, false); + + assert_eq!(regs[CRB_CTRL_START as usize], 0); + assert_eq!( + get_reg_field(®s, CrbRegister::CtrlSts(CtrlStsFields::TpmSts)), + 1 + ); + } + + #[test] + fn test_data_buffer_range_accepts_exact_end_access() { + let start = (TPM_CRB_BUFFER_MAX - 4)..TPM_CRB_BUFFER_MAX; + + assert_eq!( + data_buffer_range( + CRB_DATA_BUFFER + TPM_CRB_BUFFER_MAX as u32 - 4, + 4, + TPM_CRB_BUFFER_MAX + ), + Some(start) + ); + assert_eq!( + data_buffer_range( + CRB_DATA_BUFFER + TPM_CRB_BUFFER_MAX as u32 - 3, + 4, + TPM_CRB_BUFFER_MAX + ), + None + ); + } }