From 2645f0df7b6201c8ddf41ab5403e03377fce3c72 Mon Sep 17 00:00:00 2001 From: Manami Mori Date: Tue, 11 Jul 2023 16:09:45 +0900 Subject: [PATCH] [fix] DTB Analyser to calculate regs' offset correctly When the dtb like a below comes, former DTB Analyser will not calculate offset correctly. This commit fix it. ``` bus { regs = <0x00 0x80000 0x00 0x10000>; #address-cells = <0x02>; #size-cells = <0x02>; /* size-cells changed after "regs" */ serial { regs = <0x100 0x100>; #address-cells = <0x01>; /* address-cells changed after "regs" */ #size-cells = <0x01>; /* size-cells changed after "regs" */ } } ``` Signed-off-by: Manami Mori --- src/hypervisor_bootloader/src/dtb.rs | 109 +++++++------------ src/hypervisor_bootloader/src/serial_port.rs | 1 - 2 files changed, 37 insertions(+), 73 deletions(-) diff --git a/src/hypervisor_bootloader/src/dtb.rs b/src/hypervisor_bootloader/src/dtb.rs index 8079890..e5da827 100644 --- a/src/hypervisor_bootloader/src/dtb.rs +++ b/src/hypervisor_bootloader/src/dtb.rs @@ -1,4 +1,5 @@ // Copyright (c) 2022 RIKEN +// Copyright (c) 2023 National Institute of Advanced Industrial Science and Technology (AIST) // All rights reserved. // // This software is released under the MIT License. @@ -76,11 +77,6 @@ impl DtbNode { fn skip_padding(pointer: &mut usize) -> Result<(), ()> { while (*pointer & (TOKEN_SIZE - 1)) != 0 { - if unsafe { *(*pointer as *const u8) } != 0 { - println!("Warning: Expected zero paddings, but found {:#X}", unsafe { - *(*pointer as *const u8) - }); - } *pointer += 1; } return Ok(()); @@ -153,6 +149,18 @@ impl DtbNode { return Ok(()); } + fn add_offset(&mut self, mut regs: usize, regs_len: u32) { + if regs_len == (self.address_cells + self.size_cells) * TOKEN_SIZE as u32 { + let mut address_cells = 0usize; + for _ in 0..self.address_cells { + address_cells <<= u32::BITS; + address_cells |= u32::from_be(unsafe { *(regs as *const u32) }) as usize; + regs += TOKEN_SIZE; + } + self.address_offset += address_cells as usize; + } + } + fn search_pointer_to_property( &mut self, target_prop_name: &[u8], @@ -230,26 +238,11 @@ impl DtbNode { } *pointer += TOKEN_SIZE; - // TODO: delete println!("NodeName") and improve code to do both of matching the name and - // skipping left words if the name is not matched. - let name_base = *pointer; + let is_name_matched = Self::match_name(*pointer, node_name); + while unsafe { *(*pointer as *const u8) } != 0 { *pointer += 1; } - let name_len = *pointer - name_base; - - println!( - "NodeName: {}", - unsafe { - core::str::from_utf8(core::slice::from_raw_parts( - name_base as *const u8, - name_len, - )) - } - .unwrap_or("???") - ); - let is_name_matched = Self::match_name(name_base, node_name); - *pointer += 1; Self::skip_padding(pointer)?; @@ -264,6 +257,8 @@ impl DtbNode { pointer: &mut usize, is_name_matched: bool, ) -> Result, ()> { + let mut regs: usize = 0; + let mut regs_len: u32 = 0; while unsafe { *(*pointer as *const u32) } != FDT_END_NODE { assert_eq!(*pointer & (TOKEN_SIZE - 1), 0); match unsafe { *(*pointer as *const u32) } { @@ -280,37 +275,18 @@ impl DtbNode { } else if Self::match_string(prop_name, PROP_SIZE_CELLS) { self.size_cells = u32::from_be(unsafe { *(*pointer as *const u32) }); } else if Self::match_string(prop_name, PROP_REG) { - println!( - "Reg: {:#X} {:#X}, Size: {:#X}", - u32::from_be(unsafe { *(*pointer as *const u32) }), - u32::from_be(unsafe { *((*pointer + 4) as *const u32) }), - self.address_cells - ); - let mut p = *pointer; - let mut address_cells = 0usize; - for _ in 0..self.address_cells { - address_cells <<= u32::BITS; - address_cells |= u32::from_be(unsafe { *(p as *const u32) }) as usize; - p += TOKEN_SIZE; - } - self.address_offset += address_cells as usize; - println!("AddressOffset: {:#X}", self.address_offset); - if property_len - != (self.address_cells + self.size_cells) * TOKEN_SIZE as u32 - { - println!( - "Expected {} bytes for reg, but found {} bytes", - (self.address_cells + self.size_cells) * TOKEN_SIZE as u32, - property_len - ); - return Err(()); - } + regs = *pointer; + regs_len = property_len; } *pointer += property_len as usize; Self::skip_padding(pointer)?; } FDT_BEGIN_NODE => { + if regs != 0 { + self.add_offset(regs, regs_len); + regs = 0; + } if is_name_matched { return Ok(Some(self.clone())); } @@ -333,6 +309,9 @@ impl DtbNode { } Self::skip_nop(pointer); } + if regs != 0 { + self.add_offset(regs, regs_len); + } if is_name_matched { return Ok(Some(self.clone())); } @@ -374,6 +353,8 @@ impl DtbNode { pointer: &mut usize, ) -> Result, ()> { let mut compatible_index: Option = None; + let mut regs: usize = 0; + let mut regs_len: u32 = 0; while unsafe { *(*pointer as *const u32) } != FDT_END_NODE { assert_eq!(*pointer & (TOKEN_SIZE - 1), 0); @@ -405,36 +386,17 @@ impl DtbNode { } else if Self::match_string(prop_name, PROP_SIZE_CELLS) { self.size_cells = u32::from_be(unsafe { *(*pointer as *const u32) }); } else if Self::match_string(prop_name, PROP_REG) { - println!( - "Reg: {:#X} {:#X}, Size: {:#X}", - u32::from_be(unsafe { *(*pointer as *const u32) }), - u32::from_be(unsafe { *((*pointer + 4) as *const u32) }), - self.address_cells - ); - let mut p = *pointer; - let mut address_cells = 0usize; - for _ in 0..self.address_cells { - address_cells <<= u32::BITS; - address_cells |= u32::from_be(unsafe { *(p as *const u32) }) as usize; - p += TOKEN_SIZE; - } - self.address_offset += address_cells as usize; - println!("AddressOffset: {:#X}", self.address_offset); - if property_len - != (self.address_cells + self.size_cells) * TOKEN_SIZE as u32 - { - println!( - "Expected {} bytes for reg, but found {} bytes", - (self.address_cells + self.size_cells) * TOKEN_SIZE as u32, - property_len - ); - /* Some devices contains the dtb which does not match the specifications... */ - } + regs = *pointer; + regs_len = property_len; } *pointer += property_len as usize; Self::skip_padding(pointer)?; } FDT_BEGIN_NODE => { + if regs != 0 { + self.add_offset(regs, regs_len); + regs = 0; + } if let Some(index) = compatible_index { return Ok(Some((self.clone(), index))); } @@ -458,6 +420,9 @@ impl DtbNode { } Self::skip_nop(pointer); } + if regs != 0 { + self.add_offset(regs, regs_len); + } if let Some(index) = compatible_index { return Ok(Some((self.clone(), index))); } diff --git a/src/hypervisor_bootloader/src/serial_port.rs b/src/hypervisor_bootloader/src/serial_port.rs index b46830c..c979285 100644 --- a/src/hypervisor_bootloader/src/serial_port.rs +++ b/src/hypervisor_bootloader/src/serial_port.rs @@ -65,7 +65,6 @@ fn try_to_get_serial_info_from_dtb(dtb_address: usize) -> Option } let address = node.get_offset(); - println!("Found MesonGxUart at {:#X}", address); return Some(SerialPortInfo { physical_address: address, virtual_address: address,