Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lpc55: Improve IFS and PRINCE setup #355

Merged
merged 4 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 22 additions & 16 deletions runners/embedded/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ struct Config {
#[derive(serde::Deserialize)]
struct Parameters {
flash_origin: u32,
#[serde(default)]
flash_end: Option<u32>,
filesystem_boundary: u32,
filesystem_end: u32,
}
Expand Down Expand Up @@ -106,29 +108,24 @@ fn generate_memory_x(outpath: &Path, template: &str, config: &Config) {
"#;

let template = std::fs::read_to_string(template).expect("cannot read memory.x template file");
let template = template.replace(
"##FLASH_LENGTH##",
&format!(
"{}",
(config.parameters.filesystem_boundary - config.parameters.flash_origin) >> 10
),
);

let template = template.replace(
"##FS_LENGTH##",
&format!(
"{}",
(config.parameters.filesystem_end - config.parameters.filesystem_boundary) >> 10
),
);
let flash_end = config
.parameters
.flash_end
.unwrap_or(config.parameters.filesystem_boundary);
let flash_len = flash_end - config.parameters.flash_origin;
let template = template.replace("##FLASH_LENGTH##", &format!("{flash_len:#X}"));

let fs_len = config.parameters.filesystem_end - config.parameters.filesystem_boundary;
let template = template.replace("##FS_LENGTH##", &format!("{fs_len:#X}"));

let template = template.replace(
"##FS_BASE##",
&format!("{:x}", config.parameters.filesystem_boundary),
&format!("{:#X}", config.parameters.filesystem_boundary),
);
let template = template.replace(
"##FLASH_BASE##",
&format!("{:x}", config.parameters.flash_origin),
&format!("{:#X}", config.parameters.flash_origin),
);

std::fs::write(outpath, [buildrs_caveat, &template].join("")).expect("cannot write memory.x");
Expand Down Expand Up @@ -221,6 +218,15 @@ fn main() -> Result<(), Box<dyn error::Error>> {
config.parameters.flash_origin,
usize
);
add_build_variable!(
&mut f,
"CONFIG_FLASH_END",
config
.parameters
.flash_end
.unwrap_or(config.parameters.filesystem_boundary),
usize
);

writeln!(&mut f, "}}").expect("Could not write build_constants.rs.");

Expand Down
4 changes: 2 additions & 2 deletions runners/embedded/ld/lpc55-memory-template.x
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
MEMORY
{

FLASH : ORIGIN = 0x##FLASH_BASE##, LENGTH = ##FLASH_LENGTH##K
FLASH : ORIGIN = ##FLASH_BASE##, LENGTH = ##FLASH_LENGTH##

FILESYSTEM : ORIGIN = 0x##FS_BASE##, LENGTH = ##FS_LENGTH##K
FILESYSTEM : ORIGIN = ##FS_BASE##, LENGTH = ##FS_LENGTH##

/* for use with standard link.x */
RAM : ORIGIN = 0x20000000, LENGTH = 272K
Expand Down
4 changes: 2 additions & 2 deletions runners/embedded/ld/nrf52-memory-template.x
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
MEMORY
{
/* NOTE K = KiBi = 1024 bytes */
FLASH : ORIGIN = 0x##FLASH_BASE##, LENGTH = ##FLASH_LENGTH##K
FILESYSTEM : ORIGIN = 0x##FS_BASE##, LENGTH = ##FS_LENGTH##K
FLASH : ORIGIN = ##FLASH_BASE##, LENGTH = ##FLASH_LENGTH##
FILESYSTEM : ORIGIN = ##FS_BASE##, LENGTH = ##FS_LENGTH##
RAM : ORIGIN = 0x20000000, LENGTH = 256K
}
3 changes: 2 additions & 1 deletion runners/embedded/profiles/lpc55.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ target = "thumbv8m.main-none-eabi"

[parameters]
flash_origin = 0x00000000
flash_end = 0x92000
filesystem_boundary = 0x93000
filesystem_end = 0x9D800
filesystem_end = 0x9DE00

[identifier]
usb_id_vendor = 0x20A0
Expand Down
4 changes: 2 additions & 2 deletions runners/embedded/src/soc_lpc55/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,8 +504,8 @@ impl Stage3 {
#[allow(unused_mut)]
let mut rng = rng.enabled(syscon);

let prince = prince.enabled(&mut rng);
prince.disable_all_region_2();
let mut prince = prince.enabled(&mut rng);
super::prince::disable(&mut prince);

let flash_gordon = FlashGordon::new(flash.enabled(syscon));

Expand Down
1 change: 1 addition & 0 deletions runners/embedded/src/soc_lpc55/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod clock_controller;
pub mod init;
pub mod monotonic;
pub mod nfc;
pub mod prince;
pub mod spi;
pub mod trussed;
pub mod types;
Expand Down
122 changes: 122 additions & 0 deletions runners/embedded/src/soc_lpc55/prince.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// Based on:
// https://github.com/lpc55/lpc55-hal/blob/25881c90026b3c7f175ccb5863399c1f18f9836c/src/drivers/flash.rs
// Authors: Conor Patrick, Nicolas Stalder
// License: Apache-2.0 or MIT

use littlefs2::{
driver::Storage,
io::{Error, Result},
};
use lpc55_hal::{
drivers::flash::{
littlefs_params::{self, BLOCK_SIZE},
FlashGordon,
},
peripherals::prince::{Prince, Region},
traits::flash::WriteErase,
typestates::init_state::Enabled,
};

use crate::types::build_constants::{
CONFIG_FILESYSTEM_BOUNDARY, CONFIG_FILESYSTEM_END, CONFIG_FLASH_END,
};

pub const FS_START: usize = CONFIG_FILESYSTEM_BOUNDARY;
pub const FS_END: usize = CONFIG_FILESYSTEM_END;
pub const BLOCK_COUNT: usize = (FS_END - FS_START) / BLOCK_SIZE;
const _FLASH_SIZE: usize = 631 * 1024 + 512;

const PRINCE_REGION2_START: usize = 0x80_000;
const PRINCE_SUBREGION_SIZE: usize = 8 * 1024;
const PRINCE_REGION2_ENABLE: u32 = {
let offset = FS_START - PRINCE_REGION2_START;
let subregion_count = offset / PRINCE_SUBREGION_SIZE;
0xffffffff << subregion_count
};
const PRINCE_REGION2_DISABLE: u32 = 0;

// Check that the FS is placed in PRINCE Region 2
const _: () = assert!(FS_START >= PRINCE_REGION2_START);
const _: () = assert!(FS_START < FS_END);
const _: () = assert!(FS_END <= _FLASH_SIZE);
// Check that the firmware does not overlap with the PRINCE subregions used for the FS
const _: () = assert!(
CONFIG_FLASH_END
<= PRINCE_REGION2_START
+ (FS_START - PRINCE_REGION2_START) / PRINCE_SUBREGION_SIZE * PRINCE_SUBREGION_SIZE
);
// Check that offset and size are multiples of the block size
const _: () = assert!(FS_START % BLOCK_SIZE == 0);
const _: () = assert!(FS_END % BLOCK_SIZE == 0);
// Check that flash region does NOT spill over the flash boundary
const _: () = assert!(FS_START + BLOCK_COUNT * BLOCK_SIZE <= _FLASH_SIZE);

pub fn enable(prince: &mut Prince<Enabled>) {
prince.set_region_enable(Region::Region2, PRINCE_REGION2_ENABLE);
}

pub fn disable(prince: &mut Prince<Enabled>) {
prince.set_region_enable(Region::Region2, PRINCE_REGION2_DISABLE);
}

pub fn with_enabled<T>(prince: &mut Prince<Enabled>, mut f: impl FnMut() -> T) -> T {
enable(prince);
let result = f();
disable(prince);
result
}

pub struct InternalFilesystem {
flash_gordon: FlashGordon,
prince: Prince<Enabled>,
}

impl InternalFilesystem {
pub fn new(flash_gordon: FlashGordon, prince: Prince<Enabled>) -> Self {
Self {
flash_gordon,
prince,
}
}
}

impl Storage for InternalFilesystem {
const READ_SIZE: usize = littlefs_params::READ_SIZE;
const WRITE_SIZE: usize = littlefs_params::WRITE_SIZE;
const BLOCK_SIZE: usize = BLOCK_SIZE;

const BLOCK_COUNT: usize = BLOCK_COUNT;
const BLOCK_CYCLES: isize = littlefs_params::BLOCK_CYCLES;

type CACHE_SIZE = littlefs_params::CACHE_SIZE;
type LOOKAHEAD_SIZE = littlefs_params::LOOKAHEAD_SIZE;

fn read(&mut self, off: usize, buf: &mut [u8]) -> Result<usize> {
with_enabled(&mut self.prince, || {
let flash: *const u8 = (FS_START + off) as *const u8;
for i in 0..buf.len() {
buf[i] = unsafe { *flash.offset(i as isize) };
}
});
Ok(buf.len())
}

fn write(&mut self, off: usize, data: &[u8]) -> Result<usize> {
let ret = self.prince.write_encrypted(|prince| {
with_enabled(prince, || self.flash_gordon.write(FS_START + off, data))
});
ret.map(|_| data.len()).map_err(|_| Error::Io)
}

fn erase(&mut self, off: usize, len: usize) -> Result<usize> {
assert_eq!(len % BLOCK_SIZE, 0);
let first_page = (FS_START + off) / BLOCK_SIZE;
let pages = len / BLOCK_SIZE;
for i in 0..pages {
self.flash_gordon
.erase_page(first_page + i)
.map_err(|_| Error::Io)?;
}
Ok(BLOCK_SIZE * pages)
}
}
12 changes: 6 additions & 6 deletions runners/embedded/src/soc_lpc55/types.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use super::board::{button::ThreeButtons, led::RgbLed};
use super::prince;
use super::spi::{FlashCs, Spi};
use super::trussed::UserInterface;
use crate::{flash::ExtFlashStorage, types::build_constants};
use crate::flash::ExtFlashStorage;
use apps::Variant;
use embedded_time::duration::Milliseconds;
use lpc55_hal::{
Expand All @@ -10,7 +11,6 @@ use lpc55_hal::{
raw,
traits::flash::WriteErase,
};
use trussed::types::LfsResult;
use utils::OptionalStorage;

//////////////////////////////////////////////////////////////////////////////
Expand All @@ -20,13 +20,13 @@ pub static mut DEVICE_UUID: [u8; 16] = [0u8; 16];

#[cfg(feature = "no-encrypted-storage")]
use lpc55_hal::littlefs2_filesystem;
#[cfg(not(feature = "no-encrypted-storage"))]
use lpc55_hal::littlefs2_prince_filesystem;
#[cfg(feature = "no-encrypted-storage")]
use trussed::types::LfsResult;

#[cfg(feature = "no-encrypted-storage")]
littlefs2_filesystem!(InternalFilesystem: (build_constants::CONFIG_FILESYSTEM_BOUNDARY));
littlefs2_filesystem!(InternalFilesystem: (prince::FS_START, prince::BLOCK_COUNT));
#[cfg(not(feature = "no-encrypted-storage"))]
littlefs2_prince_filesystem!(InternalFilesystem: (build_constants::CONFIG_FILESYSTEM_BOUNDARY));
pub use prince::InternalFilesystem;

type UsbPeripheral = lpc55_hal::peripherals::usbhs::EnabledUsbhsDevice;

Expand Down