Skip to content

Commit

Permalink
Add support for Bonus Data to host flash
Browse files Browse the repository at this point in the history
  • Loading branch information
mkeeter committed Jan 27, 2025
1 parent 2a2232f commit 11bfc51
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 3 deletions.
88 changes: 86 additions & 2 deletions drv/cosmo-hf/src/hf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ task_slot!(HASH, hash_driver);

/// We break the 128 MiB flash chip into 2x 32 MiB slots, to match Gimlet
///
/// The upper 64 MiB are unused (which is good, because it's a separate die and
/// requires special handling).
/// The upper 64 MiB are used for Bonus Data.
const SLOT_SIZE_BYTES: u32 = 1024 * 1024 * 32;
const BONUS_SIZE_BYTES: u32 = 1024 * 1024 * 64;

pub struct ServerImpl {
pub drv: FlashDriver,
Expand Down Expand Up @@ -86,6 +86,21 @@ impl ServerImpl {
}
}

/// Converts a relative address to an absolute address in bonus space
fn bonus_addr(offset: u32, len: u32) -> Result<FlashAddr, HfError> {
if offset
.checked_add(len)
.is_some_and(|a| a < BONUS_SIZE_BYTES)
{
let addr = offset
.checked_add(2 * SLOT_SIZE_BYTES)
.ok_or(HfError::BadAddress)?;
Ok(FlashAddr(addr))
} else {
Err(HfError::BadAddress)
}
}

/// Converts a relative address to an absolute address in a device slot
fn flash_addr_for(
offset: u32,
Expand Down Expand Up @@ -324,6 +339,49 @@ impl idl::InOrderHostFlashImpl for ServerImpl {
Ok(())
}

/// Writes a page to the bonus region of flash
fn bonus_page_program(
&mut self,
_: &RecvMessage,
addr: u32,
data: LenLimit<Leased<R, [u8]>, PAGE_SIZE_BYTES>,
) -> Result<(), RequestError<HfError>> {
// TODO check mux state?
self.drv
.flash_write(
Self::bonus_addr(addr, data.len() as u32)?,
&mut LeaseBufReader::<_, 32>::from(data.into_inner()),
)
.map_err(|()| RequestError::went_away())
}

/// Reads a page from the bonus region of flash
fn bonus_read(
&mut self,
_: &RecvMessage,
addr: u32,
dest: LenLimit<Leased<W, [u8]>, PAGE_SIZE_BYTES>,
) -> Result<(), RequestError<HfError>> {
// TODO check mux state?
self.drv
.flash_read(
Self::bonus_addr(addr, dest.len() as u32)?,
&mut LeaseBufWriter::<_, 32>::from(dest.into_inner()),
)
.map_err(|_| RequestError::went_away())
}

/// Erases a 64 KiB sector in the bonus flash device
fn bonus_sector_erase(
&mut self,
_: &RecvMessage,
addr: u32,
) -> Result<(), RequestError<HfError>> {
// TODO check mux state?
self.drv.flash_sector_erase(Self::bonus_addr(addr, 0)?);
Ok(())
}

fn get_mux(
&mut self,
_: &RecvMessage,
Expand Down Expand Up @@ -525,6 +583,32 @@ impl idl::InOrderHostFlashImpl for FailServer {
Err(self.err.into())
}

fn bonus_page_program(
&mut self,
_: &RecvMessage,
_addr: u32,
_data: LenLimit<Leased<R, [u8]>, PAGE_SIZE_BYTES>,
) -> Result<(), RequestError<HfError>> {
Err(self.err.into())
}

fn bonus_read(
&mut self,
_: &RecvMessage,
_offset: u32,
_dest: LenLimit<Leased<W, [u8]>, PAGE_SIZE_BYTES>,
) -> Result<(), RequestError<HfError>> {
Err(self.err.into())
}

fn bonus_sector_erase(
&mut self,
_: &RecvMessage,
_addr: u32,
) -> Result<(), RequestError<HfError>> {
Err(self.err.into())
}

fn get_mux(
&mut self,
_: &RecvMessage,
Expand Down
2 changes: 1 addition & 1 deletion drv/cosmo-hf/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

//! Minimal driver for FMC-attached NOR flash, implementing the `hf` API
//!
//! The NOR flash chip is a W25Q01JVZEIQ, which is a 1 GiB NOR flash. It is
//! The NOR flash chip is a W25Q01JVZEIQ, which is a 1 GBit NOR flash. It is
//! connected to the FPGA over SPI / QSPI.
//!
//! # References
Expand Down
26 changes: 26 additions & 0 deletions drv/gimlet-hf-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,15 @@ impl idl::InOrderHostFlashImpl for ServerImpl {
Ok(())
}

fn bonus_page_program(
&mut self,
_: &RecvMessage,
_addr: u32,
_data: LenLimit<Leased<R, [u8]>, PAGE_SIZE_BYTES>,
) -> Result<(), RequestError<HfError>> {
Err(HfError::BadAddress.into())
}

fn read(
&mut self,
_: &RecvMessage,
Expand All @@ -517,6 +526,15 @@ impl idl::InOrderHostFlashImpl for ServerImpl {
Ok(())
}

fn bonus_read(
&mut self,
_: &RecvMessage,
_addr: u32,
_dest: LenLimit<Leased<W, [u8]>, PAGE_SIZE_BYTES>,
) -> Result<(), RequestError<HfError>> {
Err(HfError::BadAddress.into())
}

fn sector_erase(
&mut self,
_: &RecvMessage,
Expand All @@ -526,6 +544,14 @@ impl idl::InOrderHostFlashImpl for ServerImpl {
self.sector_erase(addr, protect).map_err(RequestError::from)
}

fn bonus_sector_erase(
&mut self,
_: &RecvMessage,
_addr: u32,
) -> Result<(), RequestError<HfError>> {
Err(HfError::BadAddress.into())
}

fn get_mux(
&mut self,
_: &RecvMessage,
Expand Down
36 changes: 36 additions & 0 deletions idl/hf.idol
Original file line number Diff line number Diff line change
Expand Up @@ -155,5 +155,41 @@ Interface(
err: CLike("HfError"),
),
),
"bonus_page_program": (
description: "programs a page into the bonus region of host flash",
args: {
"address": "u32",
},
leases: {
"data": (type: "[u8]", read: true, max_len: Some(256)),
},
reply: Result(
ok: "()",
err: CLike("HfError"),
),
),
"bonus_read": (
description: "reads from the bonus region of host flash",
args: {
"address": "u32",
},
leases: {
"data": (type: "[u8]", write: true, max_len: Some(256)),
},
reply: Result(
ok: "()",
err: CLike("HfError"),
),
),
"bonus_sector_erase": (
description: "erases a 64 KiB sector from the bonus region of host flash",
args: {
"address": "u32",
},
reply: Result(
ok: "()",
err: CLike("HfError"),
),
),
},
)

0 comments on commit 11bfc51

Please sign in to comment.