Last active
March 10, 2022 07:29
-
-
Save nihalpasham/10fbf200c270bbde0fbd0bc7815a960e to your computer and use it in GitHub Desktop.
Snippet to create flattened dtb nodes and properties
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[derive(Debug)] | |
#[repr(C)] | |
/// Constructs a device-tree `node`, given a name and buffer. The buffer must be adequately sized. | |
pub struct RawNodeConstructor<'a> { | |
fdt_begin_node: u32, | |
node_name: &'a [u8], | |
} | |
impl<'a> RawNodeConstructor<'a> { | |
pub fn make_raw_node(buf: &'a mut [u8], name: &'a str) -> Result<Self> { | |
// calculate `raw node size and count` in bytes. size includes null + padding bytes | |
let mut node_size_in_bytes; | |
let mut count; | |
let name_len = name.as_bytes().len(); | |
match (TOKEN_SIZE + name_len) % 2 == 0 { | |
true => { | |
// if even | |
node_size_in_bytes = | |
(TOKEN_SIZE + name_len) + ((TOKEN_SIZE + name_len) % 4); | |
count = TOKEN_SIZE + name_len; | |
} | |
false => { | |
// if odd | |
node_size_in_bytes = | |
(TOKEN_SIZE + name_len) + ((TOKEN_SIZE + name_len + 2) % 4); | |
count = TOKEN_SIZE + name_len + 2; | |
} | |
} | |
if buf.len() < node_size_in_bytes { | |
return Err(Error::BufferTooSmall); | |
} | |
// construct raw node | |
let node_name = name.as_bytes(); | |
println!("count: {}", count); | |
if count % 4 == 0 { | |
let padding = [0; 4]; // node names are always null terminated | |
buf[..name_len].copy_from_slice(node_name); | |
buf[name_len..name_len + 4].copy_from_slice(&padding[..]); | |
Ok(RawNodeConstructor { | |
fdt_begin_node: TOK_BEGIN_NODE, | |
node_name: &buf[..name_len + 4], | |
}) | |
} else { | |
let padding = count % 4; | |
let max_padding_bytes = [0; 4]; // max padding is 3 bytes | |
buf[..name_len].copy_from_slice(node_name); | |
buf[name_len..name_len + padding] | |
.copy_from_slice(&max_padding_bytes[..padding]); | |
Ok(RawNodeConstructor { | |
fdt_begin_node: TOK_BEGIN_NODE, | |
node_name: &buf[..name_len + padding], | |
}) | |
} | |
} | |
} | |
#[derive(Debug)] | |
#[repr(C)] | |
/// Constructs a device-tree `property`, given a buffer, a property value and an offset into the | |
/// device-tree `strings-block`. The buffer must be adequately sized. | |
pub struct RawPropertyConstructor<'a> { | |
fdt_prop: u32, | |
prop_len: u32, | |
name_off: u32, | |
prop_val: &'a [u8], | |
} | |
impl<'a> RawPropertyConstructor<'a> { | |
pub fn make_raw_property( | |
buf: &'a mut [u8], | |
prop_name_offset: usize, | |
prop_val: &'a str, | |
) -> Result<Self> { | |
// calculate `raw property size and count` in bytes. size includes null + padding bytes | |
let mut prop_size_in_bytes; | |
let mut count; | |
let prop_val_len = prop_val.as_bytes().len(); | |
match (TOKEN_SIZE * 3 + prop_val_len) % 2 == 0 { | |
true => { | |
// if even | |
prop_size_in_bytes = (TOKEN_SIZE * 3 + prop_val_len) | |
+ ((TOKEN_SIZE * 3 + prop_val_len) % 4); | |
count = (TOKEN_SIZE * 3) + prop_val.len(); | |
} | |
false => { | |
// if odd | |
prop_size_in_bytes = (TOKEN_SIZE * 3 + prop_val_len) | |
+ ((TOKEN_SIZE * 3 + prop_val_len + 2) % 4); | |
count = (TOKEN_SIZE * 3) + prop_val.len() + 2; | |
} | |
} | |
if buf.len() < prop_size_in_bytes { | |
return Err(Error::BufferTooSmall); | |
} | |
// construct raw property | |
if count % 4 == 0 { | |
let padding = [0; 4]; // property values are always null terminated | |
buf[..prop_val_len].copy_from_slice(prop_val.as_bytes()); | |
buf[prop_val_len..prop_val_len + 4].copy_from_slice(&padding[..]); | |
Ok(RawPropertyConstructor { | |
fdt_prop: TOK_PROPERTY, | |
prop_len: prop_val.len() as u32, | |
name_off: prop_name_offset as u32, | |
prop_val: &buf[..prop_val_len + 4], | |
}) | |
} else { | |
let padding = count % 4; | |
let max_padding_bytes = [0; 4]; // max padding is 3 bytes | |
buf[..prop_val_len].copy_from_slice(prop_val.as_bytes()); | |
buf[prop_val_len..prop_val_len + padding] | |
.copy_from_slice(&max_padding_bytes[..padding]); | |
Ok(RawPropertyConstructor { | |
fdt_prop: TOK_PROPERTY, | |
prop_len: prop_val.len() as u32, | |
name_off: prop_name_offset as u32, | |
prop_val: &buf[..prop_val_len + padding], | |
}) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@imrank03