Skip to content

Commit

Permalink
[fix] DTB Analyser to calculate regs' offset correctly
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
Manami Mori committed Jul 11, 2023
1 parent ef9178e commit 2645f0d
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 73 deletions.
109 changes: 37 additions & 72 deletions src/hypervisor_bootloader/src/dtb.rs
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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(());
Expand Down Expand Up @@ -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],
Expand Down Expand Up @@ -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)?;
Expand All @@ -264,6 +257,8 @@ impl DtbNode {
pointer: &mut usize,
is_name_matched: bool,
) -> Result<Option<Self>, ()> {
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) } {
Expand All @@ -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()));
}
Expand All @@ -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()));
}
Expand Down Expand Up @@ -374,6 +353,8 @@ impl DtbNode {
pointer: &mut usize,
) -> Result<Option<(Self, usize)>, ()> {
let mut compatible_index: Option<usize> = 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);
Expand Down Expand Up @@ -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)));
}
Expand All @@ -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)));
}
Expand Down
1 change: 0 additions & 1 deletion src/hypervisor_bootloader/src/serial_port.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ fn try_to_get_serial_info_from_dtb(dtb_address: usize) -> Option<SerialPortInfo>
}

let address = node.get_offset();
println!("Found MesonGxUart at {:#X}", address);
return Some(SerialPortInfo {
physical_address: address,
virtual_address: address,
Expand Down

0 comments on commit 2645f0d

Please sign in to comment.