Skip to content

Commit

Permalink
Update RoT bootloader, a.k.a. stage0 (#1675)
Browse files Browse the repository at this point in the history
This PR has four commits to simplify reviewing.

- The first is Laura's macro to manipulate the HASHCRYPT interrupt
vector.
- 2nd is pre-main kernel changes to create a staging area for Bootleby
update and to validate the (now) four RoT flash banks and record those
results for use by update_server.
- 3rd are the API changes to support stage0 update including treating
the bootloader as a separate component with A (active) and B
(stage0next) banks.
  - last is the code in the RoT update_server to actually update stage0

Before merging this PR, Cargo.toml needs to be edited to reference the
gateway-message-service main branch.
Merging needs to be coordinated with an MGS merge.

Closes #1043, #1404, #1548, #1353,
  • Loading branch information
lzrd committed Apr 30, 2024
1 parent ab8d428 commit 0c001d4
Show file tree
Hide file tree
Showing 30 changed files with 2,319 additions and 597 deletions.
5 changes: 4 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion app/demo-stm32g0-nucleo/app-g031.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ board = "stm32g031-nucleo"

[kernel]
name = "demo-stm32g0-nucleo"
requires = {flash = 11104, ram = 1296}
requires = {flash = 11344, ram = 1296}
features = ["g031"]
stacksize = 640

Expand Down
4 changes: 1 addition & 3 deletions app/lpc55xpresso/app-sprot.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ fwid = true
[kernel]
name = "lpc55xpresso"
features = ["dice-self"]
requires = {flash = 53504, ram = 4096}
requires = {flash = 54128, ram = 4096}

[caboose]
region = "flash"
Expand Down Expand Up @@ -55,7 +55,6 @@ start = true
[tasks.update_server]
name = "lpc55-update-server"
priority = 3
max-sizes = {flash = 32768, ram = 4096}
stacksize = 3000
start = true
sections = {bootstate = "usbsram"}
Expand Down Expand Up @@ -182,7 +181,6 @@ task-slots = ["swd"]
[tasks.sprot]
name = "drv-lpc55-sprot-server"
priority = 6
max-sizes = {flash = 48512, ram = 32768}
uses = ["flexcomm8", "bootrom"]
features = ["spi0"]
start = true
Expand Down
4 changes: 2 additions & 2 deletions app/lpc55xpresso/app.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ fwid = true
[kernel]
name = "lpc55xpresso"
features = ["dump", "dice-self"]
requires = {flash = 54464, ram = 4096}
requires = {flash = 55040, ram = 4096}

[caboose]
region = "flash"
Expand Down Expand Up @@ -48,7 +48,7 @@ start = true
[tasks.update_server]
name = "lpc55-update-server"
priority = 3
max-sizes = {flash = 16384, ram = 4096}
max-sizes = {flash = 26720, ram = 16384}
stacksize = 2048
start = true
sections = {bootstate = "usbsram"}
Expand Down
7 changes: 4 additions & 3 deletions app/oxide-rot-1/app-dev.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ start = true
[tasks.update_server]
name = "lpc55-update-server"
priority = 3
max-sizes = {flash = 16384, ram = 4096, usbsram = 4096}
stacksize = 2560
max-sizes = {flash = 26080, ram = 17000, usbsram = 4096}
# TODO: Size this appropriately
stacksize = 8192
start = true
sections = {bootstate = "usbsram"}
uses = ["flash_controller", "hash_crypt"]
Expand All @@ -77,7 +78,7 @@ task-slots = ["syscon_driver"]
[tasks.sprot]
name = "drv-lpc55-sprot-server"
priority = 6
max-sizes = {flash = 51168, ram = 32768}
max-sizes = {flash = 54016, ram = 32768}
uses = ["flexcomm8", "bootrom"]
features = ["spi0", "sp-ctrl"]
start = true
Expand Down
5 changes: 2 additions & 3 deletions app/oxide-rot-1/app.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ fwid = true

[kernel]
name = "oxide-rot-1"
requires = {flash = 61124, ram = 2696}
requires = {flash = 61252, ram = 2720}
features = ["dice-mfg"]

[caboose]
Expand Down Expand Up @@ -40,8 +40,7 @@ start = true
[tasks.update_server]
name = "lpc55-update-server"
priority = 3
max-sizes = {flash = 16384, ram = 4096, usbsram = 4096}
stacksize = 2560
stacksize = 8192
start = true
sections = {bootstate = "usbsram"}
uses = ["flash_controller", "hash_crypt"]
Expand Down
8 changes: 4 additions & 4 deletions app/rot-carrier/app.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fwid = true
[kernel]
name = "rot-carrier"
features = ["dice-self"]
requires = {flash = 53600, ram = 4096}
requires = {flash = 54176, ram = 3876}

[caboose]
tasks = ["caboose_reader", "sprot"]
Expand Down Expand Up @@ -46,8 +46,8 @@ start = true
[tasks.update_server]
name = "lpc55-update-server"
priority = 3
max-sizes = {flash = 32768, ram = 4096, usbsram = 4096}
stacksize = 2560
# TODO size this appropriately
stacksize = 8192
start = true
sections = {bootstate = "usbsram"}
uses = ["flash_controller", "hash_crypt"]
Expand Down Expand Up @@ -108,7 +108,7 @@ task-slots = ["syscon_driver"]
[tasks.sprot]
name = "drv-lpc55-sprot-server"
priority = 6
max-sizes = {flash = 49728, ram = 32768}
max-sizes = {flash = 54000, ram = 32768}
uses = ["flexcomm8", "bootrom"]
features = ["spi0"]
start = true
Expand Down
17 changes: 16 additions & 1 deletion chips/lpc55/memory.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,25 @@ execute = true
[[flash]]
name = "stage0"
address = 0x00000000
size = 0x10000
size = 0x02000
read = true
execute = true

# Staging area for "stage0" updates.
#
# The largest stage0 image to date is about 6-ish KiB,
# while the current release is 4-ish KiB.
# That leaves at least 56 KiB of "stage0" unused.
# The Hubris pre-main kernel code checks "stage0next" at boot time
# When it is still possible to call the ROM-based signature verification
# routine.
[[flash]]
name = "stage0next"
address = 0x00002000
size = 0x02000
read = true
execute = false

[[flash]]
name = "dice-mfg"
address = 0x90000
Expand Down
114 changes: 108 additions & 6 deletions drv/lpc55-sprot-server/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use crate::Trace;
use attest_api::Attest;
use crc::{Crc, CRC_32_CKSUM};
use drv_lpc55_update_api::{RotPage, SlotId, Update};
use drv_lpc55_update_api::{RotComponent, RotPage, SlotId, Update};
use drv_sprot_api::{
AttestReq, AttestRsp, CabooseReq, CabooseRsp, DumpReq, ReqBody, Request,
Response, RotIoStats, RotPageRsp, RotState, RotStatus, RspBody,
Expand Down Expand Up @@ -48,11 +48,33 @@ pub struct StartupState {

/// Marker for data which should be copied after the packet is encoded
pub enum TrailingData<'a> {
Caboose { slot: SlotId, start: u32, size: u32 },
AttestCert { index: u32, offset: u32, size: u32 },
AttestLog { offset: u32, size: u32 },
Attest { nonce: &'a [u8], write_size: u32 },
RotPage { page: RotPage },
Caboose {
slot: SlotId,
start: u32,
size: u32,
},
AttestCert {
index: u32,
offset: u32,
size: u32,
},
AttestLog {
offset: u32,
size: u32,
},
Attest {
nonce: &'a [u8],
write_size: u32,
},
RotPage {
page: RotPage,
},
ComponentCaboose {
component: RotComponent,
slot: SlotId,
start: u32,
size: u32,
},
}

pub struct Handler {
Expand Down Expand Up @@ -117,6 +139,40 @@ impl<'a> Handler {
// In certain cases, handling the request has left us with trailing data
// that needs to be packed into the remaining packet space.
match trailer {
Some(TrailingData::ComponentCaboose {
component,
slot,
start,
size: blob_size,
}) => {
let blob_size: usize = blob_size.try_into().unwrap_lite();
if blob_size > drv_sprot_api::MAX_BLOB_SIZE {
// If there isn't enough room, then pack an error instead
Response::pack(
&Err(SprotError::Protocol(
SprotProtocolError::BadMessageLength,
)),
tx_buf,
)
} else {
let pack_result =
Response::pack_with_cb(&rsp_body, tx_buf, |buf| {
self.update
.component_read_raw_caboose(
component,
slot,
start,
&mut buf[..blob_size],
)
.map_err(|e| RspBody::Caboose(Err(e)))?;
Ok(blob_size)
});
match pack_result {
Ok(size) => size,
Err(e) => Response::pack(&Ok(e), tx_buf),
}
}
}
Some(TrailingData::Caboose {
slot,
start,
Expand Down Expand Up @@ -357,6 +413,33 @@ impl<'a> Handler {
Some(TrailingData::Caboose { slot, start, size }),
))
}
CabooseReq::ComponentSize { component, slot } => {
let rsp = self
.update
.component_caboose_size(component, slot)
.map(CabooseRsp::ComponentSize);
Ok((RspBody::Caboose(rsp), None))
}
CabooseReq::ComponentRead {
component,
slot,
start,
size,
} => {
// In this case, we're going to be sending back a variable
// amount of data in the trailing section of the packet. We
// don't know exactly where that data will be placed, so
// we'll return a marker here and copy it later.
Ok((
RspBody::Caboose(Ok(CabooseRsp::ComponentRead)),
Some(TrailingData::ComponentCaboose {
component,
slot,
start,
size,
}),
))
}
},
ReqBody::Update(UpdateReq::BootInfo) => {
let boot_info = self.update.rot_boot_info()?;
Expand Down Expand Up @@ -477,6 +560,25 @@ impl<'a> Handler {
#[cfg(not(feature = "sp-ctrl"))]
Err(SprotError::Protocol(SprotProtocolError::BadMessageType))
}
ReqBody::Update(UpdateReq::VersionedBootInfo { version }) => {
let versioned_boot_info =
self.update.versioned_rot_boot_info(version)?;
Ok((RspBody::Update(versioned_boot_info.into()), None))
}
ReqBody::Update(UpdateReq::ComponentPrep { component, slot }) => {
self.update.component_prep_image_update(component, slot)?;
Ok((RspBody::Ok, None))
}
ReqBody::Update(UpdateReq::ComponentSwitchDefaultImage {
component,
slot,
duration,
}) => {
self.update.component_switch_default_image(
component, slot, duration,
)?;
Ok((RspBody::Ok, None))
}
}
}
}
Expand Down

0 comments on commit 0c001d4

Please sign in to comment.