continue
Some checks failed
ci / Check build (push) Has been cancelled
ci / Check formatting (push) Has been cancelled
ci / Check Documentation Build (push) Has been cancelled
ci / Clippy (push) Has been cancelled
ci / Check build (pull_request) Has been cancelled
ci / Check formatting (pull_request) Has been cancelled
ci / Check Documentation Build (pull_request) Has been cancelled
ci / Clippy (pull_request) Has been cancelled

This commit is contained in:
2025-09-01 11:30:03 +02:00
parent f61e5e282f
commit 2e868b609e
20 changed files with 1208 additions and 316 deletions

View File

@@ -9,9 +9,14 @@ members = [
"examples/embassy",
"examples/zedboard",
"zynq-mmu",
"zedboard-fsbl", "zedboard-bsp",
"zedboard-fsbl",
"zedboard-bsp",
"zynq-boot-image",
]
exclude = [
"zynq-boot-image/tester",
]
exclude = ["experiments"]
# cargo build/run --release
[profile.release]

View File

@@ -19,7 +19,7 @@ zynq7000-embassy = { path = "../../zynq7000-embassy" }
dht-sensor = { git = "https://github.com/michaelbeaumont/dht-sensor.git", rev = "10319bdeae9ace3bb0fc79a15da2869c5bf50f52", features = ["async"] }
static_cell = "2"
critical-section = "1"
heapless = "0.8"
heapless = "0.9"
embedded-io = "0.6"
embedded-hal = "1"
fugit = "0.3"
@@ -30,7 +30,7 @@ embassy-executor = { git = "https://github.com/us-irs/embassy.git", branch = "co
"executor-thread",
]}
# TODO: Remove generic-queue-16 feature as soon as upstream executor is used again.
embassy-time = { version = "0.4", features = ["tick-hz-1_000_000", "generic-queue-16"] }
embassy-time = { version = "0.5", features = ["tick-hz-1_000_000", "generic-queue-16"] }
[profile.release]
codegen-units = 1

View File

@@ -20,8 +20,8 @@ zedboard-bsp = { path = "../../zedboard-bsp" }
num_enum = { version = "0.7", default-features = false }
l3gd20 = { git = "https://github.com/us-irs/l3gd20.git", branch = "add-async-if" }
embedded-io = "0.6"
bitbybit = "1.3"
arbitrary-int = "1.3"
bitbybit = "1.4"
arbitrary-int = "2"
embedded-io-async = "0.6"
critical-section = "1"
static_cell = "2"
@@ -37,10 +37,10 @@ embassy-executor = { git = "https://github.com/us-irs/embassy.git", branch = "co
"executor-thread",
]}
# TODO: Remove generic-queue-16 feature as soon as upstream executor is used again.
embassy-time = { version = "0.4", features = ["tick-hz-1_000_000", "generic-queue-16"] }
embassy-time = { version = "0.5", features = ["tick-hz-1_000_000", "generic-queue-16"] }
embassy-net = { version = "0.7", features = ["dhcpv4", "packet-trace", "medium-ethernet", "icmp", "tcp", "udp"] }
embassy-sync = { version = "0.7" }
heapless = "0.8"
heapless = "0.9"
axi-uartlite = { git = "https://egit.irs.uni-stuttgart.de/rust/axi-uartlite.git" }
axi-uart16550 = { git = "https://egit.irs.uni-stuttgart.de/rust/axi-uart16550.git" }

View File

@@ -5,7 +5,7 @@ edition = "2024"
[dependencies]
zynq7000-hal = { path = "../zynq7000-hal" }
bitbybit = "1.3"
arbitrary-int = "1.3"
bitbybit = "1.4"
arbitrary-int = "2"
num_enum = { version = "0.7", default-features = false }
thiserror = { version = "2", default-features = false }

View File

@@ -17,4 +17,4 @@ embedded-io = "0.6"
embedded-hal = "1"
fugit = "0.3"
log = "0.4"
arbitrary-int = "1.3"
arbitrary-int = "2"

View File

@@ -0,0 +1,7 @@
[package]
name = "zynq-boot-image"
version = "0.1.0"
edition = "2024"
[dependencies]
thiserror = { version = "2", default-features = false }

384
zynq-boot-image/src/lib.rs Normal file
View File

@@ -0,0 +1,384 @@
#![no_std]
use core::str::Utf8Error;
/// ASCII 'XLNX'
pub const IMAGE_ID_U32: u32 = 0x584C4E58;
/// This is the fixed size of the boot header.
pub const FIXED_BOOT_HEADER_SIZE: usize = 0xA0;
pub struct BootHeader<'a> {
//base_addr: usize,
// Snapshot of the boot header and following data (at least fixed header size)
data: &'a [u8],
}
impl<'a> BootHeader<'a> {
pub const FIXED_SIZED_PART: usize = FIXED_BOOT_HEADER_SIZE;
/// Create a new boot header parser structure without performing any additional checks.
pub const fn new_unchecked(data: &'a [u8]) -> Self {
BootHeader { data }
}
/// Create a new boot header parser structure while also performing any additonal checks.
///
/// The passed buffer must have a minimal size of [Self::FIXED_SIZED_PART].
/// This constructor calls [Self::check_image_id_validity] and [Self::verify_header_checksum]
/// to verify whether the boot header structure is actually valid.
pub fn new(data: &'a [u8]) -> Option<Self> {
if data.len() < Self::FIXED_SIZED_PART {
return None;
}
let header = BootHeader { data };
if !header.check_image_id_validity() || !header.verify_header_checksum() {
return None;
}
Some(header)
}
#[inline]
fn read_u32_le(&self, offset: usize) -> u32 {
let bytes = &self.data[offset..offset + 4];
u32::from_le_bytes(bytes.try_into().unwrap())
}
#[inline]
pub fn image_id(&self) -> u32 {
self.read_u32_le(0x24)
}
/// Check whether the image ID has the mandatory [IMAGE_ID_U32] value.
#[inline]
pub fn check_image_id_validity(&self) -> bool {
self.image_id() == IMAGE_ID_U32
}
#[inline]
pub fn source_offset(&self) -> usize {
self.read_u32_le(0x30) as usize
}
// The boot image metadata is all the data up to the first partition of the FSBL.
//
// This information can be used to copy all relevant information for image and partition
// parsing into RAM. This includes the image header table, the image headers and the
// partition headers.
//#[inline]
//pub fn boot_image_metadata_len(&self) -> usize {
//self.source_offset() - self.base_addr
//}
#[inline]
pub fn header_checksum(&self) -> u32 {
self.read_u32_le(0x48)
}
#[inline]
pub fn image_header_table_offset(&self) -> usize {
self.read_u32_le(0x98) as usize
}
pub fn image_header_table(&self) -> Option<ImageHeaderTable<'a>> {
let offset = self.image_header_table_offset();
if offset + ImageHeaderTable::SIZE > self.data.len() {
return None;
}
Some(
ImageHeaderTable::new(
&self.data[self.image_header_table_offset()
..self.image_header_table_offset() + ImageHeaderTable::SIZE],
)
.unwrap(),
)
}
pub fn image_header_iterator(&self) -> Option<ImageHeaderIterator<'a>> {
let first_header_offset = self.image_header_table()?.first_image_header_offset()?;
ImageHeaderIterator::new(self.data, first_header_offset)
}
#[inline]
pub fn partition_header_table_offset(&self) -> usize {
self.read_u32_le(0x9C) as usize
}
#[inline]
pub fn verify_header_checksum(&self) -> bool {
let checksum = self.header_checksum();
let mut sum = 0u32;
let mut ofs = 0x20;
while ofs < 0x48 {
sum = sum.wrapping_add(self.read_u32_le(ofs));
ofs += 4;
}
!sum == checksum
}
}
pub struct ImageHeaderTable<'a> {
data: &'a [u8],
}
impl<'a> ImageHeaderTable<'a> {
pub const SIZE: usize = 0x18;
pub const fn new(data: &'a [u8]) -> Option<Self> {
if data.len() != Self::SIZE {
return None;
}
Some(ImageHeaderTable { data })
}
#[inline]
fn read_u32_le(&self, offset: usize) -> u32 {
let bytes = &self.data[offset..offset + 4];
u32::from_le_bytes(bytes.try_into().unwrap())
}
#[inline]
pub fn count_of_headers(&self) -> usize {
self.read_u32_le(0x04) as usize
}
/// Returns [None] if the number of words times 4 exeeds [u32::MAX].
#[inline]
pub fn first_image_header_offset(&self) -> Option<usize> {
self.read_u32_le(0x0C).checked_mul(4).map(|v| v as usize)
}
/// Returns [None] if the number of words times 4 exeeds [u32::MAX].
#[inline]
pub fn first_partition_header_offset(&self) -> Option<usize> {
self.read_u32_le(0x08).checked_mul(4).map(|v| v as usize)
}
}
pub struct ImageHeaderIterator<'a> {
data: &'a [u8],
current_header_offset: usize,
}
impl<'a> ImageHeaderIterator<'a> {
#[inline]
pub const fn new(data: &'a [u8], first_header_offset: usize) -> Option<Self> {
if first_header_offset + ImageHeader::MIN_SIZE > data.len() {
return None;
}
Some(ImageHeaderIterator {
data,
current_header_offset: first_header_offset,
})
}
}
impl<'a> Iterator for ImageHeaderIterator<'a> {
type Item = ImageHeader<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.current_header_offset == 0 {
return None;
}
let next_image_header = ImageHeader::new(&self.data[self.current_header_offset..])?;
self.current_header_offset = next_image_header.next_image_header_offset()?;
Some(next_image_header)
}
}
pub struct ImageHeader<'a> {
header_data: &'a [u8],
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
#[error("buffer too small")]
pub struct BufferTooSmallError;
#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
pub enum NameParsingError {
#[error("ut8 error")]
Utf8(#[from] Utf8Error),
#[error("buffer too small")]
BufferTooSmall(#[from] BufferTooSmallError),
}
impl<'a> ImageHeader<'a> {
pub const MIN_SIZE: usize = 0x1C;
#[inline]
pub fn new(data: &'a [u8]) -> Option<Self> {
if data.len() < Self::MIN_SIZE {
return None;
}
let mut current_offset = 0x14;
let mut prev_word =
u32::from_le_bytes(data[current_offset..current_offset + 4].try_into().unwrap());
current_offset += 4;
// TODO: Upper bound.
loop {
if current_offset + 4 > data.len() {
return None;
}
let current_word =
u32::from_le_bytes(data[current_offset..current_offset + 4].try_into().unwrap());
current_offset += 4;
if current_word == 0xffff_ffff || prev_word == 0x0000_0000 {
break;
}
prev_word = current_word;
}
Some(ImageHeader {
header_data: &data[0..current_offset],
})
}
#[allow(clippy::len_without_is_empty)]
pub fn len(&self) -> usize {
self.header_data.len()
}
#[inline]
fn read_u32_le(&self, offset: usize) -> u32 {
let bytes = &self.header_data[offset..offset + 4];
u32::from_le_bytes(bytes.try_into().unwrap())
}
pub fn partition_header_iterator(&self, data: &'a [u8]) -> Option<PartitionHeaderIterator<'a>> {
let first_partition_header = self.first_partition_header_offset()?;
Some(PartitionHeaderIterator {
data,
current_partition_header_addr: first_partition_header,
current_partition_index: 0,
num_of_partitions: self.partition_count(),
})
}
#[inline]
pub fn next_image_header_offset(&self) -> Option<usize> {
self.read_u32_le(0x00).checked_mul(4).map(|v| v as usize)
}
#[inline]
pub fn partition_count(&self) -> usize {
self.read_u32_le(0x0C) as usize
}
pub fn first_partition_header_offset(&self) -> Option<usize> {
self.read_u32_le(0x04).checked_mul(4).map(|v| v as usize)
}
pub fn image_name_copied(&self, buf: &mut [u8]) -> Result<usize, BufferTooSmallError> {
let mut current_offset = 0x10;
let mut current_buf_idx = 0;
let mut null_byte_found = false;
loop {
let next_bytes = &self.header_data[current_offset..current_offset + 4];
for &byte in next_bytes.iter().rev() {
if byte == 0 {
null_byte_found = true;
break;
}
if current_buf_idx >= buf.len() {
return Err(BufferTooSmallError);
}
buf[current_buf_idx] = byte;
current_buf_idx += 1;
}
if null_byte_found {
break;
}
current_offset += 4;
}
Ok(current_buf_idx)
}
pub fn image_name<'b>(&self, buf: &'b mut [u8]) -> Result<&'b str, NameParsingError> {
let name_len = self.image_name_copied(buf)?;
core::str::from_utf8(&buf[0..name_len]).map_err(NameParsingError::from)
}
}
pub struct PartitionHeaderIterator<'a> {
data: &'a [u8],
current_partition_header_addr: usize,
current_partition_index: usize,
num_of_partitions: usize,
}
impl<'a> Iterator for PartitionHeaderIterator<'a> {
type Item = PartitionHeader<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.current_partition_index >= self.num_of_partitions {
return None;
}
if self.current_partition_header_addr + PartitionHeader::SIZE > self.data.len() {
return None;
}
let header = PartitionHeader::new(
&self.data[self.current_partition_header_addr
..self.current_partition_header_addr + PartitionHeader::SIZE],
)
.ok()?;
self.current_partition_index += 1;
self.current_partition_header_addr += 0x40;
Some(header)
}
}
pub struct PartitionHeader<'a> {
header_data: &'a [u8],
}
impl<'a> PartitionHeader<'a> {
pub const SIZE: usize = 0x40;
// TODO: Checksum check.
#[inline]
pub const fn new(header_data: &'a [u8]) -> Result<Self, BufferTooSmallError> {
if header_data.len() < Self::SIZE {
return Err(BufferTooSmallError);
}
Ok(PartitionHeader { header_data })
}
#[inline]
fn read_u32_le(&self, offset: usize) -> u32 {
let bytes = &self.header_data[offset..offset + 4];
u32::from_le_bytes(bytes.try_into().unwrap())
}
#[inline]
pub fn encrypted_partition_length(&self) -> u32 {
self.read_u32_le(0x00)
}
#[inline]
pub fn unencrypted_partition_length(&self) -> u32 {
self.read_u32_le(0x04)
}
#[inline]
pub fn total_partition_length(&self) -> Option<usize> {
self.read_u32_le(0x08).checked_mul(4).map(|v| v as usize)
}
#[inline]
pub fn destination_load_address(&self) -> u32 {
self.read_u32_le(0x0C)
}
#[inline]
pub fn destination_exec_address(&self) -> u32 {
self.read_u32_le(0x10)
}
#[inline]
pub fn section_count(&self) -> usize {
self.read_u32_le(0x1C) as usize
}
#[inline]
pub fn data_offset(&self) -> Option<usize> {
self.read_u32_le(0x14).checked_mul(4).map(|v| v as usize)
}
}

View File

@@ -2,5 +2,5 @@ all:
{
[bootloader] fsbl.elf
fpga.bit
[load=0x100000] application.elf
application.elf
}

1
zynq-boot-image/tester/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/target

709
zynq-boot-image/tester/Cargo.lock generated Normal file
View File

@@ -0,0 +1,709 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "anstream"
version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
[[package]]
name = "anstyle-parse"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a"
dependencies = [
"anstyle",
"once_cell_polyfill",
"windows-sys",
]
[[package]]
name = "arbitrary-int"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "825297538d77367557b912770ca3083f778a196054b3ee63b22673c4a3cae0a5"
[[package]]
name = "arbitrary-int"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c858caffa49edfc4ecc45a4bec37abd3e88041a2903816f10f990b7b41abc281"
[[package]]
name = "arm-targets"
version = "0.2.0"
source = "git+https://github.com/rust-embedded/cortex-ar.git?rev=79dba7000d2090d13823bfb783d9d64be8b778d2#79dba7000d2090d13823bfb783d9d64be8b778d2"
[[package]]
name = "bitbybit"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec187a89ab07e209270175faf9e07ceb2755d984954e58a2296e325ddece2762"
dependencies = [
"arbitrary-int 1.3.0",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cfg-if"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
[[package]]
name = "clap"
version = "4.5.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
[[package]]
name = "colorchoice"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
[[package]]
name = "cortex-ar"
version = "0.2.0"
source = "git+https://github.com/rust-embedded/cortex-ar.git?rev=79dba7000d2090d13823bfb783d9d64be8b778d2#79dba7000d2090d13823bfb783d9d64be8b778d2"
dependencies = [
"arbitrary-int 1.3.0",
"arm-targets",
"bitbybit",
"num_enum",
"thiserror",
]
[[package]]
name = "critical-section"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "delegate"
version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6178a82cf56c836a3ba61a7935cdb1c49bfaa6fa4327cd5bf554a503087de26b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "derive-mmio"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cb20d58c6618082f91e4f5bde31422e73dd59afeda16c61c94fd15adcf8812b"
dependencies = [
"derive-mmio-macro",
"rustversion",
]
[[package]]
name = "derive-mmio-macro"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b92bcaf79d5ee81fac0a867e95df6943cde5e42c82059a9ec93fc0c6cb8ae35a"
dependencies = [
"proc-macro-error2",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "embassy-net-driver"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524eb3c489760508f71360112bca70f6e53173e6fe48fc5f0efd0f5ab217751d"
[[package]]
name = "embassy-sync"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73974a3edbd0bd286759b3d483540f0ebef705919a5f56f4fc7709066f71689b"
dependencies = [
"cfg-if",
"critical-section",
"embedded-io-async",
"futures-core",
"futures-sink",
"heapless 0.8.0",
]
[[package]]
name = "embedded-dma"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "994f7e5b5cb23521c22304927195f236813053eb9c065dd2226a32ba64695446"
dependencies = [
"stable_deref_trait",
]
[[package]]
name = "embedded-hal"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89"
[[package]]
name = "embedded-hal-async"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884"
dependencies = [
"embedded-hal",
]
[[package]]
name = "embedded-hal-nb"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605"
dependencies = [
"embedded-hal",
"nb",
]
[[package]]
name = "embedded-io"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"
[[package]]
name = "embedded-io-async"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f"
dependencies = [
"embedded-io",
]
[[package]]
name = "fugit"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17186ad64927d5ac8f02c1e77ccefa08ccd9eaa314d5a4772278aa204a22f7e7"
dependencies = [
"gcd",
]
[[package]]
name = "futures-core"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
[[package]]
name = "futures-sink"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
[[package]]
name = "gcd"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a"
[[package]]
name = "hash32"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
dependencies = [
"byteorder",
]
[[package]]
name = "heapless"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
dependencies = [
"hash32",
"stable_deref_trait",
]
[[package]]
name = "heapless"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1edcd5a338e64688fbdcb7531a846cfd3476a54784dcb918a0844682bc7ada5"
dependencies = [
"hash32",
"stable_deref_trait",
]
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "libm"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
[[package]]
name = "log"
version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "managed"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d"
[[package]]
name = "nb"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d"
[[package]]
name = "num_enum"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a"
dependencies = [
"num_enum_derive",
"rustversion",
]
[[package]]
name = "num_enum_derive"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
dependencies = [
"critical-section",
"portable-atomic",
]
[[package]]
name = "once_cell_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "portable-atomic"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
[[package]]
name = "proc-macro-error-attr2"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
dependencies = [
"proc-macro2",
"quote",
]
[[package]]
name = "proc-macro-error2"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
dependencies = [
"proc-macro-error-attr2",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "proc-macro2"
version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "raw-slicee"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89d8fb5aaf355f81e39a4834840f68e809ee98c83f556dcfb8c16fd7004fe4dc"
dependencies = [
"embedded-dma",
]
[[package]]
name = "ringbuf"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe47b720588c8702e34b5979cb3271a8b1842c7cb6f57408efa70c779363488c"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "rustversion"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "smoltcp"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dad095989c1533c1c266d9b1e8d70a1329dd3723c3edac6d03bbd67e7bf6f4bb"
dependencies = [
"bitflags",
"byteorder",
"cfg-if",
"heapless 0.8.0",
"managed",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "static_cell"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0530892bb4fa575ee0da4b86f86c667132a94b74bb72160f58ee5a4afec74c23"
dependencies = [
"portable-atomic",
]
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tester"
version = "0.1.0"
dependencies = [
"clap",
"zynq7000-hal",
]
[[package]]
name = "thiserror"
version = "2.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "vcell"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
[[package]]
name = "windows-link"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
[[package]]
name = "windows-sys"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.53.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
dependencies = [
"windows-link",
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
[[package]]
name = "windows_aarch64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
[[package]]
name = "windows_i686_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
[[package]]
name = "windows_i686_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
[[package]]
name = "windows_i686_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
[[package]]
name = "windows_x86_64_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
[[package]]
name = "windows_x86_64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
[[package]]
name = "zynq-mmu"
version = "0.1.0"
dependencies = [
"cortex-ar",
"thiserror",
]
[[package]]
name = "zynq7000"
version = "0.1.0"
dependencies = [
"arbitrary-int 1.3.0",
"bitbybit",
"derive-mmio",
"once_cell",
"rustversion",
"static_assertions",
"thiserror",
]
[[package]]
name = "zynq7000-hal"
version = "0.1.0"
dependencies = [
"arbitrary-int 2.0.0",
"bitbybit",
"cortex-ar",
"critical-section",
"delegate",
"embassy-net-driver",
"embassy-sync",
"embedded-hal",
"embedded-hal-async",
"embedded-hal-nb",
"embedded-io",
"embedded-io-async",
"fugit",
"heapless 0.9.1",
"libm",
"log",
"nb",
"num_enum",
"paste",
"raw-slicee",
"ringbuf",
"smoltcp",
"static_assertions",
"static_cell",
"thiserror",
"vcell",
"zynq-mmu",
"zynq7000",
]

View File

@@ -0,0 +1,8 @@
[package]
name = "tester"
version = "0.1.0"
edition = "2024"
[dependencies]
zynq-boot-image= { path = ".." }
clap = { version = "4", features = ["derive"] }

View File

@@ -0,0 +1,75 @@
use std::{io::Read, path::Path};
use clap::Parser as _;
use zynq_boot_image::{BootHeader, FIXED_BOOT_HEADER_SIZE};
#[derive(clap::Parser, Debug)]
#[command(version, about)]
pub struct Cli {
/// Path to boot.bin file to test.
#[arg(short, long)]
path: String,
}
fn main() {
let cli = Cli::parse();
let boot_bin = Path::new(&cli.path);
if !boot_bin.exists() {
eprintln!("File not found: {}", boot_bin.display());
std::process::exit(1);
}
let mut boot_bin_file = std::fs::File::open(boot_bin).expect("failed to open boot.bin file");
let mut header_buf = Box::new([0u8; 8192]);
boot_bin_file
.read_exact(&mut header_buf[0..FIXED_BOOT_HEADER_SIZE])
.expect("failed to read boot header");
let mut boot_header = BootHeader::new(&header_buf[0..FIXED_BOOT_HEADER_SIZE])
.expect("failed to parse boot header");
let source_offset = boot_header.source_offset();
boot_bin_file
.read_exact(&mut header_buf[FIXED_BOOT_HEADER_SIZE..source_offset - FIXED_BOOT_HEADER_SIZE])
.expect("failed to read full boot binary metadata");
// Re-assign with newly read data.
boot_header = BootHeader::new_unchecked(&header_buf[0..source_offset]);
let image_header_table = boot_header
.image_header_table()
.expect("failed extracting image header table");
let image_headers = image_header_table.count_of_headers();
println!(
"Image headers: {}, first image header offset {}, first partition header offset {}",
image_headers,
image_header_table
.first_image_header_offset()
.expect("failed reading first image header offset"),
image_header_table
.first_partition_header_offset()
.expect("failed reading first partition header offset")
);
let image_header_iter = boot_header
.image_header_iterator()
.expect("failed extracting boot header iterator");
for (idx, image_header) in image_header_iter.enumerate() {
println!(
"Image header {} with partition count {}",
idx,
image_header.partition_count()
);
let mut test: [u8; 64] = [0; 64];
let image_name = image_header
.image_name(&mut test)
.expect("image name error");
println!("image name: {}", image_name);
let partition_iter = image_header
.partition_header_iterator(header_buf.as_slice())
.unwrap();
for partition in partition_iter {
println!(
"partition with size {} and load address {:#08x}, section count {}",
partition.total_partition_length().unwrap(),
partition.destination_load_address(),
partition.section_count()
);
}
}
}

View File

@@ -18,4 +18,4 @@ zynq7000-hal = { path = "../zynq7000-hal" }
# embassy-time-driver = { git = "https://github.com/embassy-rs/embassy.git", branch = "main", version = "0.2" }
# embassy-time-queue-utils = { git = "https://github.com/embassy-rs/embassy.git", branch = "main", version = "0.1" }
embassy-time-driver = "0.2"
embassy-time-queue-utils = "0.1"
embassy-time-queue-utils = "0.3"

View File

@@ -16,8 +16,8 @@ zynq7000 = { path = "../zynq7000" }
zynq-mmu = { path = "../zynq-mmu", version = "0.1.0" }
static_assertions = "1.1"
bitbybit = "1.3"
arbitrary-int = "1.3"
bitbybit = "1.4"
arbitrary-int = "2"
thiserror = { version = "2", default-features = false }
num_enum = { version = "0.7", default-features = false }
ringbuf = { version = "0.4.8", default-features = false }
@@ -25,7 +25,7 @@ embedded-hal-nb = "1"
embedded-io = "0.6"
embedded-hal = "1"
embedded-hal-async = "1"
heapless = "0.8"
heapless = "0.9"
static_cell = "2"
delegate = "0.13"
paste = "1"

View File

@@ -1,296 +0,0 @@
/// ASCII 'XLNX'
pub const IMAGE_ID_U32: u32 = 0x584C4E58;
/// This is the fixed size of the boot header.
pub const FIXED_BOOT_HEADER_SIZE: usize = 0xA0;
pub struct BootHeader {
base_addr: u32,
}
impl BootHeader {
/// # Safety
///
/// This function will perform volatile reads for image header table fields on the given base
/// address. You must ensure that the address contains a valid image header table.
/// At the very least, [FIXED_BOOT_HEADER_SIZE] bytes of the boot header must be readable at
/// the given address.
pub const unsafe fn new(base_addr: u32) -> Self {
BootHeader { base_addr }
}
#[inline]
pub fn image_id(&self) -> u32 {
unsafe { core::ptr::read_volatile((self.base_addr + 0x24) as *const _) }
}
/// Check whether the image ID has the mandatory [IMAGE_ID_U32] value.
#[inline]
pub fn check_image_id_validity(&self) -> bool {
self.image_id() == 0x854C4E58
}
#[inline]
pub fn source_offset(&self) -> u32 {
unsafe { core::ptr::read_volatile((self.base_addr + 0x30) as *const _) }
}
/// The boot image metadata is all the data up to the first partition of the FSBL.
///
/// This information can be used to copy all relevant information for image and partition
/// parsing into RAM. This includes the image header table, the image headers and the
/// partition headers.
#[inline]
pub fn boot_image_metadata_len(&self) -> u32 {
self.source_offset() - self.base_addr
}
#[inline]
pub fn header_checksum(&self) -> u32 {
unsafe { core::ptr::read_volatile((self.base_addr + 0x48) as *const _) }
}
#[inline]
pub fn image_header_table_offset(&self) -> u32 {
unsafe { core::ptr::read_volatile((self.base_addr + 0x98) as *const _) }
}
/// # Safety
///
/// This function is only safe to use when the image header table structure
/// was copied to the correct offset of the base address used to initialize
/// this boot header structure.
pub unsafe fn image_header_table(&self) -> ImageHeaderTable {
let offset = self.image_header_table_offset();
unsafe { ImageHeaderTable::new(self.base_addr + offset) }
}
#[inline]
pub fn partition_header_table_offset(&self) -> u32 {
unsafe { core::ptr::read_volatile((self.base_addr + 0x9C) as *const _) }
}
#[inline]
pub fn verify_header_checksum(&self) -> bool {
let checksum = unsafe { core::ptr::read_volatile((self.base_addr + 0x48) as *const _) };
let end_addr = 0x48;
let mut current_addr = 0x20;
let mut sum = 0u32;
while current_addr < end_addr {
sum = sum.wrapping_add(unsafe { core::ptr::read_volatile(current_addr as *const u32) });
current_addr += 4;
}
!sum == checksum
}
}
pub struct ImageHeaderTable {
base_addr: u32,
}
impl ImageHeaderTable {
/// # Safety
///
/// This function will perform volatile reads for image header table fields on the given base
/// address. You must ensure that the address contains a valid image header table.
///
/// This is a low-level function. It is recommended to use [BootHeader::image_header_table]
/// to retrieve the header table after checking boot header validity.
pub const unsafe fn new(base_addr: u32) -> Self {
ImageHeaderTable { base_addr }
}
pub fn image_header_iterator(&self) -> ImageHeaderIterator {
let first_image_header = self.first_image_header_offset();
ImageHeaderIterator {
current_image_header: first_image_header,
}
}
#[inline]
pub fn count_of_headers(&self) -> u32 {
unsafe { core::ptr::read_volatile((self.base_addr + 0x04) as *const _) }
}
#[inline]
pub fn first_partition_header(&self) -> u32 {
unsafe { core::ptr::read_volatile((self.base_addr + 0x08) as *const _) }
}
#[inline]
pub fn first_image_header_offset(&self) -> u32 {
let words = unsafe { core::ptr::read_volatile((self.base_addr + 0x0C) as *const u32) };
words * 4
}
/// You can also use [Self::image_header_iterator] to retrieve an iterator over all image
/// headers.
#[inline]
pub fn first_image_header(&self) -> ImageHeader {
unsafe { ImageHeader::new(self.base_addr + self.first_image_header_offset()) }
}
}
pub struct ImageHeaderIterator {
current_image_header: u32,
}
impl Iterator for ImageHeaderIterator {
type Item = ImageHeader;
fn next(&mut self) -> Option<Self::Item> {
let image_header = unsafe { ImageHeader::new(self.current_image_header) };
image_header.next_image_header()
}
}
pub struct ImageHeader {
base_addr: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
#[error("buffer too small")]
pub struct BufTooSmallError;
impl ImageHeader {
/// # Safety
///
/// This function will perform volatile reads for image header table fields on the given base
/// address. You must ensure that the address contains a valid image header table.
///
/// This is a low-level function. It is recommended to use
/// [ImageHeaderTable::image_header_iterator] to retrieve the image headers after checking
/// boot header validity.
#[inline]
pub const unsafe fn new(base_addr: u32) -> Self {
ImageHeader { base_addr }
}
#[inline]
pub fn next_image_header_offset(&self) -> u32 {
let next_image_header_words =
unsafe { core::ptr::read_volatile(self.base_addr as *const u32) };
next_image_header_words * 4
}
#[inline]
pub fn partition_count(&self) -> u32 {
unsafe { core::ptr::read_volatile((self.base_addr + 0x0C) as *const u32) }
}
pub fn first_partition_header_offset(&self) -> u32 {
let partition_header_word_offset =
unsafe { core::ptr::read_volatile((self.base_addr + 0x04) as *const u32) };
partition_header_word_offset * 4
}
pub fn partition_header_iterator(&self) -> PartitionHeaderIterator {
let first_partition_header = self.first_partition_header_offset();
PartitionHeaderIterator {
current_partition_header_addr: first_partition_header,
current_partition_index: 0,
num_of_partitions: self.partition_count(),
}
}
pub fn image_name_copied(&self, buf: &mut [u8]) -> Result<usize, BufTooSmallError> {
let mut current_addr = self.base_addr + 0x10;
let mut current_buf_idx = 0;
let mut null_byte_found = false;
loop {
let next_bytes = unsafe { core::slice::from_raw_parts(current_addr as *const u8, 4) };
for &byte in next_bytes.iter() {
if byte == 0 {
null_byte_found = true;
break;
}
if current_buf_idx >= buf.len() {
return Err(BufTooSmallError);
}
buf[current_buf_idx] = byte;
current_buf_idx += 1;
}
if null_byte_found {
break;
}
current_addr += 4;
}
Ok(current_buf_idx)
}
pub fn next_image_header(&self) -> Option<ImageHeader> {
if self.next_image_header_offset() == 0 {
None
} else {
Some(unsafe { ImageHeader::new(self.base_addr + self.next_image_header_offset()) })
}
}
}
pub struct PartitionHeaderIterator {
current_partition_header_addr: u32,
current_partition_index: u32,
num_of_partitions: u32,
}
impl Iterator for PartitionHeaderIterator {
type Item = PartitionHeader;
fn next(&mut self) -> Option<Self::Item> {
if self.current_partition_index >= self.num_of_partitions {
return None;
}
let header = unsafe { PartitionHeader::new(self.current_partition_index) };
self.current_partition_index += 1;
self.current_partition_header_addr += 0x40;
Some(header)
}
}
pub struct PartitionHeader {
base_addr: u32,
}
impl PartitionHeader {
/// # Safety
///
/// This function will perform volatile reads for partition header fields on the given base
/// address. You must ensure that the address contains a valid partition header.
///
/// This is a low-level function. It is recommended to use
/// [ImageHeader::partition_header_iterator] to retrieve the all partition headers for a given
/// image header.
#[inline]
pub const unsafe fn new(base_addr: u32) -> Self {
PartitionHeader { base_addr }
}
#[inline]
pub fn encrypted_partition_length(&self) -> u32 {
unsafe { core::ptr::read_volatile(self.base_addr as *const u32) }
}
#[inline]
pub fn unencrypted_partition_length(&self) -> u32 {
unsafe { core::ptr::read_volatile((self.base_addr + 0x04) as *const u32) }
}
#[inline]
pub fn total_partition_length(&self) -> u32 {
let total_words =
unsafe { core::ptr::read_volatile((self.base_addr + 0x08) as *const u32) };
total_words * 4
}
#[inline]
pub fn destination_load_address(&self) -> u32 {
unsafe { core::ptr::read_volatile((self.base_addr + 0x0C) as *const _) }
}
#[inline]
pub fn data_offset(&self) -> u32 {
let offset_words =
unsafe { core::ptr::read_volatile((self.base_addr + 0x0C) as *const u32) };
offset_words * 4
}
}

View File

@@ -18,7 +18,6 @@ use zynq7000::{
slcr::{BootModeRegister, BootPllConfig, LevelShifterRegister},
};
pub mod boot_image;
pub mod cache;
pub mod clocks;
pub mod ddr;

View File

@@ -13,7 +13,7 @@ categories = ["embedded", "no-std", "hardware-support"]
[dependencies]
cortex-a-rt = { version = "0.1", optional = true, features = ["vfp-dp"] }
cortex-ar = { version = "0.2", git = "https://github.com/rust-embedded/cortex-ar.git", rev = "79dba7000d2090d13823bfb783d9d64be8b778d2" }
arbitrary-int = "1.3"
arbitrary-int = "2"
zynq-mmu = { path = "../zynq-mmu", version = "0.1.0" }
[features]

View File

@@ -13,8 +13,8 @@ categories = ["embedded", "no-std", "hardware-support"]
[dependencies]
static_assertions = "1.1"
derive-mmio = { version = "0.6", default-features = false }
bitbybit = "1.3"
arbitrary-int = "1.3"
bitbybit = "1.4"
arbitrary-int = "2"
rustversion = "1"
thiserror = { version = "2", default-features = false }
once_cell = { version = "1", default-features = false, features = ["critical-section"] }