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
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:
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" }
|
||||
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -17,4 +17,4 @@ embedded-io = "0.6"
|
||||
embedded-hal = "1"
|
||||
fugit = "0.3"
|
||||
log = "0.4"
|
||||
arbitrary-int = "1.3"
|
||||
arbitrary-int = "2"
|
||||
|
||||
7
zynq-boot-image/Cargo.toml
Normal file
7
zynq-boot-image/Cargo.toml
Normal 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
384
zynq-boot-image/src/lib.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
@@ -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
1
zynq-boot-image/tester/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/target
|
||||
709
zynq-boot-image/tester/Cargo.lock
generated
Normal file
709
zynq-boot-image/tester/Cargo.lock
generated
Normal 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",
|
||||
]
|
||||
8
zynq-boot-image/tester/Cargo.toml
Normal file
8
zynq-boot-image/tester/Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "tester"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
zynq-boot-image= { path = ".." }
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
75
zynq-boot-image/tester/src/main.rs
Normal file
75
zynq-boot-image/tester/src/main.rs
Normal 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()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ use zynq7000::{
|
||||
slcr::{BootModeRegister, BootPllConfig, LevelShifterRegister},
|
||||
};
|
||||
|
||||
pub mod boot_image;
|
||||
pub mod cache;
|
||||
pub mod clocks;
|
||||
pub mod ddr;
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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"] }
|
||||
|
||||
Reference in New Issue
Block a user