memory_spi: move SPI memory constants to Rust
What changed, and why it matters
This commit is a routine code reorganization: it moves constants that describe where Bluetooth firmware is stored in SPI memory from C header files into Rust source files. The values themselves (32 KB max firmware size, two slots at addresses 0x00 and 0x8000, 4096-byte erase sectors) are unchanged. The change adds compile-time checks to ensure the Rust and C definitions stay consistent. There is no security bug being fixed here.
No security action required. Treat as normal refactoring/constant relocation.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch relocates SPI memory layout constants (MEMORY_SPI_ERASE_GRANULARITY, MEMORY_SPI_BLE_FIRMWARE_MAX_SIZE, MEMORY_SPI_BLE_FIRMWARE_1_ADDR, MEMORY_SPI_BLE_FIRMWARE_2_ADDR) from src/memory/memory_spi.h into the Rust crate bitbox02-rust-c so they can be exported back to C via cbindgen. It also defines BLE_FIRMWARE_MAX_SIZE in bitbox-hal and BLE_FIRMWARE_1_ADDR/BLE_FIRMWARE_2_ADDR in bitbox02::spi_mem, replacing previous re-exports from bitbox02-sys. Static assertions in bitbox02-rust-c enforce equality between the C-exported numeric literals and the Rust HAL constants, and enforce sector alignment of the two firmware addresses. The bluetooth.rs upgrade handler now uses hal_memory::BLE_FIRMWARE_MAX_SIZE instead of bitbox02::spi_mem::BLE_FIRMWARE_MAX_SIZE, but the numeric value is identical.
Changed components
src/memory/memory_spi.hsrc/rust/bitbox-hal/src/memory.rssrc/rust/bitbox02-rust-c/src/lib.rssrc/rust/bitbox02-rust/src/hww/api/bluetooth.rssrc/rust/bitbox02-sys/build.rssrc/rust/bitbox02/src/spi_mem.rsInspect captured patch +43 / −28
diff --git a/src/factorysetup.c b/src/factorysetup.c
index 3d28539..0190e50 100644
--- a/src/factorysetup.c
+++ b/src/factorysetup.c
@@ -13,7 +13,6 @@
#include "memory/memory_spi.h"
#include "memory/spi_mem.h"
#include "platform_init.h"
-#include "rust/rust.h"
#include "screen.h"
#include "securechip/securechip.h"
#include "uart.h"
@@ -21,6 +20,7 @@
#include "usb/usb_packet.h"
#include "usb/usb_processing.h"
#include "utils_ringbuffer.h"
+#include <rust/rust.h>
#include <ui/oled/oled.h>
#define BUFFER_SIZE_DOWN 1024
diff --git a/src/memory/memory_spi.h b/src/memory/memory_spi.h
index 77c733f..b9529c1 100644
--- a/src/memory/memory_spi.h
+++ b/src/memory/memory_spi.h
@@ -9,21 +9,6 @@
#include <compiler_util.h>
-#define MEMORY_SPI_ERASE_GRANULARITY 4096
-
-// BLE firmware max size is 32kB.
-#define MEMORY_SPI_BLE_FIRMWARE_MAX_SIZE (32 * 1024)
-// The first 64kB are reserved for storing BLE firmwares, so we can safely upgrade.
-#define MEMORY_SPI_BLE_FIRMWARE_1_ADDR 0x00
-#define MEMORY_SPI_BLE_FIRMWARE_2_ADDR MEMORY_SPI_BLE_FIRMWARE_MAX_SIZE
-
-#if (MEMORY_SPI_BLE_FIRMWARE_1_ADDR % MEMORY_SPI_ERASE_GRANULARITY)
- #error "Address must be aligned to an erase sector"
-#endif
-#if (MEMORY_SPI_BLE_FIRMWARE_2_ADDR % MEMORY_SPI_ERASE_GRANULARITY)
- #error "Address must be aligned to an erase sector"
-#endif
-
/**
* Retrieve the BLE firmware and associated size and checksum from the SPI memory chip. It takes
* into account the currently active firmware area, and verifies that it matches the
diff --git a/src/rust/bitbox-hal/src/memory.rs b/src/rust/bitbox-hal/src/memory.rs
index 9953ef3..4ec3b37 100644
--- a/src/rust/bitbox-hal/src/memory.rs
+++ b/src/rust/bitbox-hal/src/memory.rs
@@ -8,6 +8,8 @@ pub const DEVICE_NAME_MAX_LEN: usize = 63;
/// Maximum multisig account name length in bytes, excluding the null terminator used in C
/// strings.
pub const MULTISIG_NAME_MAX_LEN: usize = 30;
+/// Maximum allowed BLE firmware size in bytes.
+pub const BLE_FIRMWARE_MAX_SIZE: usize = 32 * 1024;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum PasswordStretchAlgo {
diff --git a/src/rust/bitbox02-rust-c/Cargo.toml b/src/rust/bitbox02-rust-c/Cargo.toml
index bf8b311..fee9b07 100644
--- a/src/rust/bitbox02-rust-c/Cargo.toml
+++ b/src/rust/bitbox02-rust-c/Cargo.toml
@@ -10,7 +10,7 @@ license = "Apache-2.0"
[dependencies]
bitbox02-rust = { path = "../bitbox02-rust", optional = true }
bitbox-aes = { path = "../bitbox-aes", optional = true }
-bitbox02 = { path = "../bitbox02", optional = true }
+bitbox02 = { path = "../bitbox02" }
bitbox-hal = { path = "../bitbox-hal" }
bitbox02-noise = { path = "../bitbox02-noise", optional = true }
cortex-m = { workspace = true }
@@ -62,13 +62,12 @@ target-c-unit-tests = [
]
platform-bitbox02 = []
-platform-bitbox02plus = ["util/sha2", "bitbox02-noise", "bitbox02-rust", "bitbox02"]
+platform-bitbox02plus = ["util/sha2", "bitbox02-noise", "bitbox02-rust"]
bootloader = []
firmware = [
"bitbox02-rust",
"bitbox02-rust/firmware",
- "bitbox02",
"bitbox02-noise",
"util/sha2",
"util/firmware",
diff --git a/src/rust/bitbox02-rust-c/src/lib.rs b/src/rust/bitbox02-rust-c/src/lib.rs
index 6992c3c..0b4b9dc 100644
--- a/src/rust/bitbox02-rust-c/src/lib.rs
+++ b/src/rust/bitbox02-rust-c/src/lib.rs
@@ -72,6 +72,33 @@ const _: [(); bitbox_hal::memory::DEVICE_NAME_MAX_LEN + 1] =
const _: [(); bitbox_hal::memory::MULTISIG_NAME_MAX_LEN + 1] =
[(); MEMORY_MULTISIG_NAME_MAX_LEN_WITH_NULL as usize];
+// Keep these as numeric literals so cbindgen reliably exports them to C.
+// The static asserts below enforce consistency with other Rust constants.
+/// Erase sector size of SPI memory in bytes.
+const MEMORY_SPI_ERASE_GRANULARITY: u32 = 4096;
+// Keep this as a numeric literal so cbindgen reliably exports it to C.
+// The static assert below enforces consistency with the Rust HAL constant.
+/// Maximum size in bytes of a BLE firmware image.
+pub const MEMORY_SPI_BLE_FIRMWARE_MAX_SIZE: u32 = 32 * 1024;
+// Keep this as a numeric literal so cbindgen reliably exports it to C.
+/// Start address of BLE firmware slot 1 in SPI memory. Cannot change this as it defines the memory
+/// layout.
+pub const MEMORY_SPI_BLE_FIRMWARE_1_ADDR: u32 = 0x00;
+/// Start address of BLE firmware slot 2 in SPI memory. Cannot change this as it defines the memory
+/// layout.
+pub const MEMORY_SPI_BLE_FIRMWARE_2_ADDR: u32 = MEMORY_SPI_BLE_FIRMWARE_MAX_SIZE;
+
+const _: [(); bitbox_hal::memory::BLE_FIRMWARE_MAX_SIZE] =
+ [(); MEMORY_SPI_BLE_FIRMWARE_MAX_SIZE as usize];
+const _: [(); bitbox02::spi_mem::BLE_FIRMWARE_1_ADDR as usize] =
+ [(); MEMORY_SPI_BLE_FIRMWARE_1_ADDR as usize];
+const _: [(); bitbox02::spi_mem::BLE_FIRMWARE_2_ADDR as usize] =
+ [(); MEMORY_SPI_BLE_FIRMWARE_2_ADDR as usize];
+
+// Addresses must be aligned to an erase sector
+const _: [(); 0] = [(); (MEMORY_SPI_BLE_FIRMWARE_1_ADDR % MEMORY_SPI_ERASE_GRANULARITY) as usize];
+const _: [(); 0] = [(); (MEMORY_SPI_BLE_FIRMWARE_2_ADDR % MEMORY_SPI_ERASE_GRANULARITY) as usize];
+
// Whenever execution reaches somewhere it isn't supposed to rust code will "panic". Our panic
// handler will print the available information on the screen and over RTT. If we compile with
// `panic=abort` this code will never get executed.
diff --git a/src/rust/bitbox02-rust/src/hww/api/bluetooth.rs b/src/rust/bitbox02-rust/src/hww/api/bluetooth.rs
index 0479a74..e71faab 100644
--- a/src/rust/bitbox02-rust/src/hww/api/bluetooth.rs
+++ b/src/rust/bitbox02-rust/src/hww/api/bluetooth.rs
@@ -15,8 +15,6 @@ use crate::hal::{Memory, Ui, memory as hal_memory};
use alloc::vec::Vec;
-use bitbox02::spi_mem;
-
// See also bitbox-da14531-firmware.bin.sha256.
const ALLOWED_HASH: [u8; 32] =
hex!("1e4aa8364e935c0785e4f891208307d832f788172e4bf61621de6df9ec3c215f");
@@ -59,7 +57,9 @@ async fn _process_upgrade<M: Memory>(
request: &pb::BluetoothUpgradeInitRequest,
allowed_hash: &[u8; 32],
) -> Result<Response, Error> {
- if request.firmware_length == 0 || request.firmware_length > spi_mem::BLE_FIRMWARE_MAX_SIZE {
+ if request.firmware_length == 0
+ || request.firmware_length as usize > hal_memory::BLE_FIRMWARE_MAX_SIZE
+ {
return Err(Error::InvalidInput);
}
diff --git a/src/rust/bitbox02-sys/build.rs b/src/rust/bitbox02-sys/build.rs
index c618531..cd3c21b 100644
--- a/src/rust/bitbox02-sys/build.rs
+++ b/src/rust/bitbox02-sys/build.rs
@@ -24,9 +24,6 @@ const ALLOWLIST_VARS: &[&str] = &[
"MEMORY_PLATFORM_BITBOX02",
"MEMORY_SECURECHIP_TYPE_ATECC",
"MEMORY_SECURECHIP_TYPE_OPTIGA",
- "MEMORY_SPI_BLE_FIRMWARE_1_ADDR",
- "MEMORY_SPI_BLE_FIRMWARE_2_ADDR",
- "MEMORY_SPI_BLE_FIRMWARE_MAX_SIZE",
"SCREEN_HEIGHT",
"SCREEN_WIDTH",
"secfalse_u8",
diff --git a/src/rust/bitbox02/src/spi_mem.rs b/src/rust/bitbox02/src/spi_mem.rs
index 5e96c40..98a26b1 100644
--- a/src/rust/bitbox02/src/spi_mem.rs
+++ b/src/rust/bitbox02/src/spi_mem.rs
@@ -2,9 +2,14 @@
extern crate alloc;
-pub use bitbox02_sys::MEMORY_SPI_BLE_FIRMWARE_1_ADDR as BLE_FIRMWARE_1_ADDR;
-pub use bitbox02_sys::MEMORY_SPI_BLE_FIRMWARE_2_ADDR as BLE_FIRMWARE_2_ADDR;
-pub use bitbox02_sys::MEMORY_SPI_BLE_FIRMWARE_MAX_SIZE as BLE_FIRMWARE_MAX_SIZE;
+/// Start address of BLE firmware slot 1 in SPI memory. Cannot change this as it defines the memory
+/// layout.
+pub const BLE_FIRMWARE_1_ADDR: u32 = 0x00;
+
+/// Start address of BLE firmware slot 2 in SPI memory. Cannot change this as it defines the memory
+/// layout.
+pub const BLE_FIRMWARE_2_ADDR: u32 = bitbox_hal::memory::BLE_FIRMWARE_MAX_SIZE as u32;
+const _: [(); 32 * 1024] = [(); bitbox_hal::memory::BLE_FIRMWARE_MAX_SIZE];
use alloc::string::String;
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.