mirror of
https://github.com/jhbruhn/moonboot.git
synced 2025-03-15 01:55:50 +00:00
Improve documentation
This commit is contained in:
parent
ae46dc50dd
commit
ea8b062ad5
7 changed files with 89 additions and 57 deletions
|
@ -6,7 +6,8 @@ Rust environments.
|
||||||
This crate contains implementations, macros and build.rs helpers for:
|
This crate contains implementations, macros and build.rs helpers for:
|
||||||
* Partitioning of your memory into different sections
|
* Partitioning of your memory into different sections
|
||||||
* Exchange of the contents of those partitions via the bootloader
|
* Exchange of the contents of those partitions via the bootloader
|
||||||
* Signature-checking of the partitions contents with an algorithm of your choice
|
* Signature/Checksum-checking of the partitions contents with an algorithm of your choice, because it is
|
||||||
|
done in firmware, not in bootloader
|
||||||
* Automatic Linker Script generation based on a Section/Parition Description in Rust Code
|
* Automatic Linker Script generation based on a Section/Parition Description in Rust Code
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
|
@ -11,6 +11,9 @@ use crate::log;
|
||||||
|
|
||||||
#[cfg(feature = "defmt")]
|
#[cfg(feature = "defmt")]
|
||||||
use defmt::Format;
|
use defmt::Format;
|
||||||
|
|
||||||
|
|
||||||
|
/// Error occured during nemory access
|
||||||
#[cfg_attr(feature = "use-defmt", derive(Format))]
|
#[cfg_attr(feature = "use-defmt", derive(Format))]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum MemoryError {
|
enum MemoryError {
|
||||||
|
@ -22,7 +25,7 @@ enum MemoryError {
|
||||||
|
|
||||||
/// Use this from your bootloader application and call boot() to do the magic, reading the current
|
/// Use this from your bootloader application and call boot() to do the magic, reading the current
|
||||||
/// state via the State type and then jumping to the new image using the Jumper specified
|
/// state via the State type and then jumping to the new image using the Jumper specified
|
||||||
pub struct MoonshineBoot<
|
pub struct MoonbootBoot<
|
||||||
InternalMemory: Storage,
|
InternalMemory: Storage,
|
||||||
HardwareState: State,
|
HardwareState: State,
|
||||||
CPU: Processor, // TODO: Wrap these into a context struct like rubble?
|
CPU: Processor, // TODO: Wrap these into a context struct like rubble?
|
||||||
|
@ -39,7 +42,7 @@ impl<
|
||||||
HardwareState: State,
|
HardwareState: State,
|
||||||
CPU: Processor,
|
CPU: Processor,
|
||||||
const INTERNAL_PAGE_SIZE: usize,
|
const INTERNAL_PAGE_SIZE: usize,
|
||||||
> MoonshineBoot<InternalMemory, HardwareState, CPU, INTERNAL_PAGE_SIZE>
|
> MoonbootBoot<InternalMemory, HardwareState, CPU, INTERNAL_PAGE_SIZE>
|
||||||
{
|
{
|
||||||
/// create a new instance of the bootloader
|
/// create a new instance of the bootloader
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
@ -47,7 +50,7 @@ impl<
|
||||||
internal_memory: InternalMemory,
|
internal_memory: InternalMemory,
|
||||||
state: HardwareState,
|
state: HardwareState,
|
||||||
processor: CPU,
|
processor: CPU,
|
||||||
) -> MoonshineBoot<InternalMemory, HardwareState, CPU, INTERNAL_PAGE_SIZE> {
|
) -> MoonbootBoot<InternalMemory, HardwareState, CPU, INTERNAL_PAGE_SIZE> {
|
||||||
Self {
|
Self {
|
||||||
config,
|
config,
|
||||||
internal_memory,
|
internal_memory,
|
||||||
|
|
|
@ -9,15 +9,18 @@ use desse::{Desse, DesseSized};
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// Identifier for multiple memory instances. Currently only Internal memory is supported
|
||||||
#[cfg_attr(feature = "defmt", derive(Format))]
|
#[cfg_attr(feature = "defmt", derive(Format))]
|
||||||
#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(feature = "ram-state", derive(Desse, DesseSized))]
|
#[cfg_attr(feature = "ram-state", derive(Desse, DesseSized))]
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
pub enum MemoryUnit {
|
pub enum MemoryUnit {
|
||||||
|
/// On-chip memory of your SoC
|
||||||
Internal,
|
Internal,
|
||||||
// External(usize) // nth external unit
|
// External(usize) // nth external unit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Description of a memory bank in a specific memory unit
|
||||||
#[cfg_attr(feature = "defmt", derive(Format))]
|
#[cfg_attr(feature = "defmt", derive(Format))]
|
||||||
#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(feature = "ram-state", derive(Desse, DesseSized))]
|
#[cfg_attr(feature = "ram-state", derive(Desse, DesseSized))]
|
||||||
|
@ -32,16 +35,17 @@ pub struct Bank {
|
||||||
pub memory_unit: MemoryUnit,
|
pub memory_unit: MemoryUnit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Configuration of your SoCs partitioning
|
||||||
#[cfg_attr(feature = "defmt", derive(Format))]
|
#[cfg_attr(feature = "defmt", derive(Format))]
|
||||||
#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(feature = "ram-state", derive(Desse, DesseSized))]
|
#[cfg_attr(feature = "ram-state", derive(Desse, DesseSized))]
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// bank this bootloader jumps to
|
/// bank this bootloader jumps to, holds your main firmware
|
||||||
pub boot_bank: Bank,
|
pub boot_bank: Bank,
|
||||||
/// alternative bank we write the new firmware image to
|
/// alternative bank we write the new firmware image to, used as a memory only
|
||||||
pub update_bank: Bank,
|
pub update_bank: Bank,
|
||||||
/// bank the bootloader is contained in
|
/// bank the bootloader is contained in, switching between banks
|
||||||
pub bootloader_bank: Bank,
|
pub bootloader_bank: Bank,
|
||||||
// Initial Image is stored to this bank after first update, restore on failure
|
// Initial Image is stored to this bank after first update, restore on failure
|
||||||
// pub golden_bank: Bank,
|
// pub golden_bank: Bank,
|
||||||
|
@ -49,13 +53,17 @@ pub struct Config {
|
||||||
pub ram_bank: Bank,
|
pub ram_bank: Bank,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Configuration for linker scripts
|
||||||
#[cfg_attr(feature = "defmt", derive(Format))]
|
#[cfg_attr(feature = "defmt", derive(Format))]
|
||||||
#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(feature = "ram-state", derive(Desse, DesseSized))]
|
#[cfg_attr(feature = "ram-state", derive(Desse, DesseSized))]
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
pub struct LinkerConfig {
|
pub struct LinkerConfig {
|
||||||
|
/// Origin address of the internal non-volatile memory
|
||||||
pub flash_origin: Address,
|
pub flash_origin: Address,
|
||||||
|
/// Origin address of the internal RAM bank
|
||||||
pub ram_origin: Address,
|
pub ram_origin: Address,
|
||||||
// TODO enable via feature flag?
|
// TODO enable via feature flag?
|
||||||
|
/// Whether to store the shared state in RAM and thus reserve some RAM memory for that
|
||||||
pub has_ram_state: bool,
|
pub has_ram_state: bool,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,25 @@
|
||||||
use crate::Address;
|
use crate::Address;
|
||||||
|
|
||||||
// This trait executes an execution jump to the specified startign address.
|
/// This trait executes an execution jump to the specified startign address.
|
||||||
// The implementation is ISA-dependent.
|
/// The implementation is ISA-dependent.
|
||||||
pub trait Processor {
|
pub trait Processor {
|
||||||
|
/// Jump to the image stored at the specified address. Never returns because it either
|
||||||
|
/// successfully switches to a new application image, or fails which leads to some
|
||||||
|
/// Hardfault/Panic/Whatever the Processor does then
|
||||||
fn do_jump(&mut self, address: Address) -> !;
|
fn do_jump(&mut self, address: Address) -> !;
|
||||||
|
/// Setup the specified hardware config. Can be used to initialize an MPU for example.
|
||||||
fn setup(&mut self, config: &crate::hardware::Config);
|
fn setup(&mut self, config: &crate::hardware::Config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Implementation of a processor based on the cortex-m crate
|
||||||
#[cfg(feature = "cortex-m")]
|
#[cfg(feature = "cortex-m")]
|
||||||
mod cortex_m {
|
mod cortex_m {
|
||||||
use super::Processor;
|
use super::Processor;
|
||||||
|
/// cortex-m based [Processor]
|
||||||
pub struct CortexM {}
|
pub struct CortexM {}
|
||||||
|
|
||||||
impl CortexM {
|
impl CortexM {
|
||||||
|
/// Instantiate a new processor
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {}
|
Self {}
|
||||||
}
|
}
|
||||||
|
@ -35,5 +42,5 @@ mod cortex_m {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "cortex-m")]
|
#[cfg(feature = "cortex-m")]
|
||||||
// A Jumper implementation for use with cortex-m processors
|
/// A Jumper implementation for use with cortex-m processors
|
||||||
pub use cortex_m::CortexM;
|
pub use cortex_m::CortexM;
|
||||||
|
|
21
src/lib.rs
21
src/lib.rs
|
@ -6,24 +6,29 @@
|
||||||
//!This crate contains implementations, macros and build.rs helpers for:
|
//!This crate contains implementations, macros and build.rs helpers for:
|
||||||
//!* Partitioning of your memory into different sections
|
//!* Partitioning of your memory into different sections
|
||||||
//!* Exchange of the contents of those partitions via the bootloader
|
//!* Exchange of the contents of those partitions via the bootloader
|
||||||
//!* Signature-checking of the partitions contents with an algorithm of your choice
|
//!* Signature/Checksum-checking of the partitions contents with an algorithm of your choice, because it is
|
||||||
|
//!done in firmware, not in bootloader
|
||||||
//!* Automatic Linker Script generation based on a Section/Parition Description in Rust Code
|
//!* Automatic Linker Script generation based on a Section/Parition Description in Rust Code
|
||||||
|
|
||||||
|
mod boot;
|
||||||
/// Implementations for use in the bootloader
|
/// Implementations for use in the bootloader
|
||||||
pub mod boot;
|
pub use boot::MoonbootBoot;
|
||||||
|
|
||||||
|
mod manager;
|
||||||
|
/// Implementations for use in the firmware
|
||||||
|
pub use manager::MoonbootManager;
|
||||||
|
|
||||||
/// Common hardware abstractions and associated implementations
|
/// Common hardware abstractions and associated implementations
|
||||||
pub mod hardware;
|
pub mod hardware;
|
||||||
/// Implementations for use in the firmware
|
|
||||||
pub mod manager;
|
|
||||||
/// Shared state management between firmware and bootloader
|
/// Shared state management between firmware and bootloader
|
||||||
pub mod state;
|
pub mod state;
|
||||||
|
|
||||||
pub use embedded_storage;
|
pub use embedded_storage;
|
||||||
|
|
||||||
/// Because most of the time, ...
|
// Because most of the time, ...
|
||||||
pub use boot as left_boot;
|
//pub use boot::MoonbootBoot as LeftBoot;
|
||||||
/// ... there's two boots involved.
|
// ... there's two boots involved.
|
||||||
pub use manager as right_boot;
|
//pub use manager::MoonbootManager as RightBoot;
|
||||||
|
|
||||||
/// Address type in RAM or ROM
|
/// Address type in RAM or ROM
|
||||||
pub type Address = u32;
|
pub type Address = u32;
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::log;
|
||||||
|
|
||||||
/// Instantiate this in your application to enable mutation of the State specified in this and jump
|
/// Instantiate this in your application to enable mutation of the State specified in this and jump
|
||||||
/// to the bootloader to apply any updates.
|
/// to the bootloader to apply any updates.
|
||||||
pub struct MoonshineManager<
|
pub struct MoonbootManager<
|
||||||
InternalMemory: Storage,
|
InternalMemory: Storage,
|
||||||
HardwareState: State,
|
HardwareState: State,
|
||||||
CPU: Processor,
|
CPU: Processor,
|
||||||
|
@ -26,14 +26,14 @@ impl<
|
||||||
HardwareState: State,
|
HardwareState: State,
|
||||||
CPU: Processor,
|
CPU: Processor,
|
||||||
const INTERNAL_PAGE_SIZE: usize,
|
const INTERNAL_PAGE_SIZE: usize,
|
||||||
> MoonshineManager<InternalMemory, HardwareState, CPU, INTERNAL_PAGE_SIZE>
|
> MoonbootManager<InternalMemory, HardwareState, CPU, INTERNAL_PAGE_SIZE>
|
||||||
{
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
config: Config,
|
config: Config,
|
||||||
internal_memory: InternalMemory,
|
internal_memory: InternalMemory,
|
||||||
state: HardwareState,
|
state: HardwareState,
|
||||||
processor: CPU,
|
processor: CPU,
|
||||||
) -> MoonshineManager<InternalMemory, HardwareState, CPU, INTERNAL_PAGE_SIZE> {
|
) -> MoonbootManager<InternalMemory, HardwareState, CPU, INTERNAL_PAGE_SIZE> {
|
||||||
Self {
|
Self {
|
||||||
config,
|
config,
|
||||||
internal_memory,
|
internal_memory,
|
||||||
|
@ -125,13 +125,14 @@ impl<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Easily get read access to the update bank
|
||||||
impl<
|
impl<
|
||||||
InternalMemory: Storage,
|
InternalMemory: Storage,
|
||||||
HardwareState: State,
|
HardwareState: State,
|
||||||
CPU: Processor,
|
CPU: Processor,
|
||||||
const INTERNAL_PAGE_SIZE: usize,
|
const INTERNAL_PAGE_SIZE: usize,
|
||||||
> core::convert::AsRef<[u8]>
|
> core::convert::AsRef<[u8]>
|
||||||
for MoonshineManager<InternalMemory, HardwareState, CPU, INTERNAL_PAGE_SIZE>
|
for MoonbootManager<InternalMemory, HardwareState, CPU, INTERNAL_PAGE_SIZE>
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn as_ref(&self) -> &[u8] {
|
fn as_ref(&self) -> &[u8] {
|
||||||
|
@ -150,7 +151,7 @@ impl<
|
||||||
HardwareState: State,
|
HardwareState: State,
|
||||||
CPU: Processor,
|
CPU: Processor,
|
||||||
const INTERNAL_PAGE_SIZE: usize,
|
const INTERNAL_PAGE_SIZE: usize,
|
||||||
> ReadStorage for MoonshineManager<InternalMemory, HardwareState, CPU, INTERNAL_PAGE_SIZE>
|
> ReadStorage for MoonbootManager<InternalMemory, HardwareState, CPU, INTERNAL_PAGE_SIZE>
|
||||||
{
|
{
|
||||||
type Error = (); // TODO
|
type Error = (); // TODO
|
||||||
|
|
||||||
|
@ -181,7 +182,7 @@ impl<
|
||||||
HardwareState: State,
|
HardwareState: State,
|
||||||
CPU: Processor,
|
CPU: Processor,
|
||||||
const INTERNAL_PAGE_SIZE: usize,
|
const INTERNAL_PAGE_SIZE: usize,
|
||||||
> Storage for MoonshineManager<InternalMemory, HardwareState, CPU, INTERNAL_PAGE_SIZE>
|
> Storage for MoonbootManager<InternalMemory, HardwareState, CPU, INTERNAL_PAGE_SIZE>
|
||||||
{
|
{
|
||||||
fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
|
fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
|
||||||
let bank = self.config.update_bank; // For now we always write updates to this bank.
|
let bank = self.config.update_bank; // For now we always write updates to this bank.
|
||||||
|
|
73
src/state.rs
73
src/state.rs
|
@ -9,7 +9,7 @@ use desse::{Desse, DesseSized};
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
// Decision making for the bootloader
|
/// Decision making states for the bootloader
|
||||||
// TODO: Hash + Signature? Should be done on download I think! This way, the algorithms can be
|
// TODO: Hash + Signature? Should be done on download I think! This way, the algorithms can be
|
||||||
// exchanged via software updates easily
|
// exchanged via software updates easily
|
||||||
#[cfg_attr(feature = "use-defmt", derive(Format))]
|
#[cfg_attr(feature = "use-defmt", derive(Format))]
|
||||||
|
@ -35,54 +35,61 @@ pub enum Update {
|
||||||
#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(feature = "ram-state", derive(Desse, DesseSized))]
|
#[cfg_attr(feature = "ram-state", derive(Desse, DesseSized))]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
// Errors that can occur during update
|
/// Errors that can occur during update
|
||||||
pub enum UpdateError {
|
pub enum UpdateError {
|
||||||
// A wrong Image Index has been specified
|
/// A wrong Image Index has been specified
|
||||||
InvalidImageIndex,
|
InvalidImageIndex,
|
||||||
// Failed to exchange the new image with the old one
|
/// Failed to exchange the new image with the old one
|
||||||
ImageExchangeFailed,
|
ImageExchangeFailed,
|
||||||
// Something f'ed up the internal state
|
/// Something f'ed up the internal state
|
||||||
InvalidState,
|
InvalidState,
|
||||||
// The Signature provided does not match the PublicKey or Image.
|
/// The Signature provided does not match the PublicKey or Image.
|
||||||
InvalidSignature,
|
InvalidSignature,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the progress of the current exchange operation
|
/// Store the progress of the current exchange operation
|
||||||
#[cfg_attr(feature = "use-defmt", derive(Format))]
|
#[cfg_attr(feature = "use-defmt", derive(Format))]
|
||||||
#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(feature = "ram-state", derive(Desse, DesseSized))]
|
#[cfg_attr(feature = "ram-state", derive(Desse, DesseSized))]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct ExchangeProgress {
|
pub struct ExchangeProgress {
|
||||||
// Bank the update is coming from
|
/// Bank the update is coming from
|
||||||
pub(crate) a: Bank,
|
pub(crate) a: Bank,
|
||||||
// Bank the update is going to
|
/// Bank the update is going to
|
||||||
pub(crate) b: Bank,
|
pub(crate) b: Bank,
|
||||||
// Page the operation has last copied
|
/// Page the operation has last copied
|
||||||
pub(crate) page_index: u32,
|
pub(crate) page_index: u32,
|
||||||
// Whether this exchange resulted from a Request (false) or a Revert (true)
|
/// Whether this exchange resulted from a Request (false) or a Revert (true)
|
||||||
pub(crate) recovering: bool,
|
pub(crate) recovering: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Struct used to store the state of the bootloader situation in NVM
|
/// Struct used to store the state of the bootloader situation in NVM
|
||||||
#[cfg_attr(feature = "use-defmt", derive(Format))]
|
#[cfg_attr(feature = "use-defmt", derive(Format))]
|
||||||
#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(feature = "ram-state", derive(Desse, DesseSized))]
|
#[cfg_attr(feature = "ram-state", derive(Desse, DesseSized))]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MoonshineState {
|
pub struct MoonbootState {
|
||||||
// If set Request, an Update is requested. This will exchange the two images, set the update
|
/// If set Request, an Update is requested. This will exchange the two images, set the update
|
||||||
// state to Revert and start the application. The application then has to set this state to
|
/// state to Revert and start the application. The application then has to set this state to
|
||||||
// None and store it. If something went wrong and the boot attempt results in a restart of
|
/// None and store it. If something went wrong and the boot attempt results in a restart of
|
||||||
// the bootloader, the bootloader starts with this variable set to Revert and thus exchanges
|
/// the bootloader, the bootloader starts with this variable set to Revert and thus exchanges
|
||||||
// the two images again, doing a downgrade because of a failed boot
|
/// the two images again, doing a downgrade because of a failed boot
|
||||||
pub update: Update,
|
pub update: Update,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Hardware abstraction for the state storage. Can for example be stored on a flash bank, or in
|
||||||
|
/// RAM. As long as you don't want to perform update download, power cycle the device, and then
|
||||||
|
/// apply the update, storing it in volatile memory is fine.
|
||||||
pub trait State {
|
pub trait State {
|
||||||
fn read(&mut self) -> MoonshineState;
|
/// Read the shared state
|
||||||
fn write(&mut self, data: MoonshineState) -> Result<(), ()>;
|
fn read(&mut self) -> MoonbootState;
|
||||||
|
/// Write the new state to the shared state
|
||||||
|
fn write(&mut self, data: MoonbootState) -> Result<(), ()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const STATE_SERIALIZED_MAX_SIZE: usize = MoonshineState::SIZE;
|
/// Size of the serialized state
|
||||||
|
pub const STATE_SERIALIZED_MAX_SIZE: usize = MoonbootState::SIZE;
|
||||||
|
/// Type used to store the shared state CRC
|
||||||
pub type StateCrcType = u32;
|
pub type StateCrcType = u32;
|
||||||
const CRC: Crc<StateCrcType> = Crc::<StateCrcType>::new(&CRC_32_CKSUM);
|
const CRC: Crc<StateCrcType> = Crc::<StateCrcType>::new(&CRC_32_CKSUM);
|
||||||
|
|
||||||
|
@ -101,14 +108,14 @@ pub mod ram {
|
||||||
pub struct RamState;
|
pub struct RamState;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
static mut _moonshine_state_crc_start: StateCrcType;
|
static mut _moonboot_state_crc_start: StateCrcType;
|
||||||
static mut _moonshine_state_data_start: [u8; STATE_SERIALIZED_MAX_SIZE];
|
static mut _moonboot_state_data_start: [u8; STATE_SERIALIZED_MAX_SIZE];
|
||||||
// TODO: Move these as normal variables to linker sections via #[link] macro?
|
// TODO: Move these as normal variables to linker sections via #[link] macro?
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State for RamState {
|
impl State for RamState {
|
||||||
fn read(&mut self) -> MoonshineState {
|
fn read(&mut self) -> MoonbootState {
|
||||||
let crc = unsafe { _moonshine_state_crc_start };
|
let crc = unsafe { _moonboot_state_crc_start };
|
||||||
|
|
||||||
log::info!(
|
log::info!(
|
||||||
"Reading data with len: {}, CRC: {}",
|
"Reading data with len: {}, CRC: {}",
|
||||||
|
@ -116,36 +123,36 @@ pub mod ram {
|
||||||
crc
|
crc
|
||||||
);
|
);
|
||||||
|
|
||||||
let checksum = checksum(unsafe { &_moonshine_state_data_start });
|
let checksum = checksum(unsafe { &_moonboot_state_data_start });
|
||||||
if crc == checksum {
|
if crc == checksum {
|
||||||
let data =
|
let data =
|
||||||
MoonshineState::deserialize_from(unsafe { &_moonshine_state_data_start });
|
MoonbootState::deserialize_from(unsafe { &_moonboot_state_data_start });
|
||||||
log::trace!("CRC Match! {}: {:?}", crc, data);
|
log::trace!("CRC Match! {}: {:?}", crc, data);
|
||||||
return data;
|
return data;
|
||||||
} else {
|
} else {
|
||||||
log::trace!("CRC Mismatch! {} vs {}", crc, checksum);
|
log::trace!("CRC Mismatch! {} vs {}", crc, checksum);
|
||||||
}
|
}
|
||||||
|
|
||||||
MoonshineState {
|
MoonbootState {
|
||||||
update: Update::None,
|
update: Update::None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write(&mut self, data: MoonshineState) -> Result<(), ()> {
|
fn write(&mut self, data: MoonbootState) -> Result<(), ()> {
|
||||||
log::trace!("Writing data {:?}", data);
|
log::trace!("Writing data {:?}", data);
|
||||||
|
|
||||||
unsafe { _moonshine_state_data_start = data.serialize() };
|
unsafe { _moonboot_state_data_start = data.serialize() };
|
||||||
log::trace!("Written data: {:?}", unsafe {
|
log::trace!("Written data: {:?}", unsafe {
|
||||||
&_moonshine_state_data_start
|
&_moonboot_state_data_start
|
||||||
});
|
});
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
_moonshine_state_crc_start = checksum(&_moonshine_state_data_start);
|
_moonboot_state_crc_start = checksum(&_moonboot_state_data_start);
|
||||||
}
|
}
|
||||||
log::info!(
|
log::info!(
|
||||||
"Written len: {}, checksum: {}",
|
"Written len: {}, checksum: {}",
|
||||||
STATE_SERIALIZED_MAX_SIZE,
|
STATE_SERIALIZED_MAX_SIZE,
|
||||||
unsafe { _moonshine_state_crc_start }
|
unsafe { _moonboot_state_crc_start }
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Reference in a new issue