Skip to content

Commit

Permalink
Add flex support + fixes for release compilation mode.
Browse files Browse the repository at this point in the history
  • Loading branch information
agrojean-ledger committed May 3, 2024
1 parent ea35188 commit 3e2ed8b
Show file tree
Hide file tree
Showing 14 changed files with 1,595 additions and 93 deletions.
6 changes: 4 additions & 2 deletions ledger_device_sdk/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ fn main() -> Result<(), Box<dyn Error>> {
NanoSPlus,
NanoX,
Stax,
Flex,
}
use Device::*;

Expand All @@ -16,8 +17,9 @@ fn main() -> Result<(), Box<dyn Error>> {
"nanosplus" => NanoSPlus,
"nanox" => NanoX,
"stax" => Stax,
"flex" => Flex,
target_name => panic!(
"invalid target `{target_name}`, expected one of `nanos`, `nanox`, `nanosplus` or `stax`. Run with `-Z build-std=core --target=./<target name>.json`"
"invalid target `{target_name}`, expected one of `nanos`, `nanox`, `nanosplus`, `stax` or `flex`. Run with `-Z build-std=core --target=./<target name>.json`"
),
};

Expand All @@ -32,7 +34,7 @@ fn main() -> Result<(), Box<dyn Error>> {
let linkerscript = match device {
NanoS => "nanos_layout.ld",
NanoX => "nanox_layout.ld",
NanoSPlus | Stax => "nanosplus_layout.ld",
NanoSPlus | Stax | Flex => "nanosplus_layout.ld",
};
std::fs::copy(linkerscript, out_dir.join(linkerscript))?;
std::fs::copy("link.ld", out_dir.join("link.ld"))?;
Expand Down
29 changes: 29 additions & 0 deletions ledger_device_sdk/flex.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"abi": "eabi",
"arch": "arm",
"c-enum-min-bits": 8,
"data-layout": "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
"emit-debug-gdb-scripts": false,
"executables": true,
"frame-pointer": "always",
"linker": "rust-lld",
"linker-flavor": "ld.lld",
"llvm-target": "thumbv8m.main-none-eabi",
"max-atomic-width": 32,
"panic-strategy": "abort",
"pre-link-args": {
"ld.lld": [
"-Tnanosplus_layout.ld",
"-Tlink.ld"
],
"ld": [
"-Tnanosplus_layout.ld",
"-Tlink.ld"
]
},
"relocation-model": "ropi-rwpi",
"singlethread": true,
"target-pointer-width": "32",
"os": "flex",
"target-family": [ "bolos" ]
}
10 changes: 5 additions & 5 deletions ledger_device_sdk/src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ pub enum Event<T> {
/// APDU event
Command(T),
/// Button press or release event
#[cfg(not(target_os = "stax"))]
#[cfg(not(any(target_os = "stax", target_os = "flex")))]
Button(ButtonEvent),
#[cfg(target_os = "stax")]
#[cfg(any(target_os = "stax", target_os = "flex"))]
TouchEvent,
/// Ticker
Ticker,
Expand Down Expand Up @@ -376,7 +376,7 @@ impl Comm {
// If this is an APDU, return with the "received command" event
// Any other event (usb, xfer, ticker) is silently handled
match seph::Events::from(tag) {
#[cfg(not(target_os = "stax"))]
#[cfg(not(any(target_os = "stax", target_os = "flex")))]
seph::Events::ButtonPush => {
let button_info = spi_buffer[3] >> 1;
if let Some(btn_evt) = get_button_event(&mut self.buttons, button_info) {
Expand All @@ -399,14 +399,14 @@ impl Comm {
seph::Events::BleReceive => ble::receive(&mut self.apdu_buffer, spi_buffer),

seph::Events::TickerEvent => {
#[cfg(target_os = "stax")]
#[cfg(any(target_os = "stax", target_os = "flex"))]
unsafe {
ux_process_ticker_event();
}
return Some(Event::Ticker);
}

#[cfg(target_os = "stax")]
#[cfg(any(target_os = "stax", target_os = "flex"))]
seph::Events::ScreenTouch => unsafe {
ux_process_finger_event(spi_buffer.as_mut_ptr());
return Some(Event::TouchEvent);
Expand Down
4 changes: 2 additions & 2 deletions ledger_device_sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ pub mod seph;

pub mod testing;

#[cfg(target_os = "stax")]
#[cfg(any(target_os = "stax", target_os = "flex"))]
pub mod nbgl;
#[cfg(not(target_os = "stax"))]
#[cfg(not(any(target_os = "stax", target_os = "flex")))]
pub mod ui;

pub mod uxapp;
Expand Down
128 changes: 64 additions & 64 deletions ledger_device_sdk/src/nbgl.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::io::{ApduHeader, Comm, Event, Reply};
use crate::testing::debug_print;
use const_zero::const_zero;
use core::cell::RefCell;
use core::ffi::{c_char, CStr};
Expand Down Expand Up @@ -100,6 +101,10 @@ impl<const SIZE: usize> CStringHelper<SIZE> {
}
}

pub fn flush(&self) {
*self.next.borrow_mut() = 0; // Reset the next index to 0
}

pub fn to_cstring<'a>(&'a self, s: &str) -> Result<&'a CStr, ()> {
let size = s.len();
let mut buffer = self.buffer.borrow_mut();
Expand Down Expand Up @@ -128,38 +133,57 @@ impl<const SIZE: usize> CStringHelper<SIZE> {
}
}

const INFO_FIELDS: [*const c_char; 2] = [
"Version\0".as_ptr() as *const c_char,
"Developer\0".as_ptr() as *const c_char,
];

pub struct NbglHome<'a> {
app_name: &'a str,
info_contents: [&'a str; 2],
app_name: *const c_char,
icon: *const nbgl_icon_details_t,
glyph: Option<&'a NbglGlyph<'a>>,
info_contents: [*const c_char; 2],
info_list: nbgl_contentInfoList_t,
c_string_helper: CStringHelper<128>,
}

impl<'a> NbglHome<'a> {
pub fn new(comm: &mut Comm) -> NbglHome {
pub fn new(comm: &mut Comm) -> NbglHome<'a> {
unsafe {
COMM_REF = Some(transmute(comm));
}
NbglHome {
app_name: "Rust App",
info_contents: ["0.0.0", "Ledger"],
app_name: "Rust App\0".as_ptr() as *const c_char,
icon: core::ptr::null(),
glyph: None,
info_contents: [
"0.0.0\0".as_ptr() as *const c_char,
"Ledger\0".as_ptr() as *const c_char,
],
info_list: nbgl_contentInfoList_t {
infoTypes: core::ptr::null(),
infoContents: core::ptr::null(),
nbInfos: 0,
},
c_string_helper: CStringHelper::<128>::new(),
}
}

pub fn app_name(self, app_name: &'a str) -> NbglHome<'a> {
NbglHome { app_name, ..self }
}

pub fn glyph(self, icon: &'a NbglGlyph) -> NbglHome<'a> {
pub fn glyph(self, glyph: &'a NbglGlyph) -> NbglHome<'a> {
NbglHome {
glyph: Some(icon),
glyph: Some(glyph),
..self
}
}

pub fn info_contents(self, version: &'a str, author: &'a str) -> NbglHome<'a> {
pub fn infos(self, app_name: &str, version: &str, author: &str) -> NbglHome<'a> {
self.c_string_helper.flush();
NbglHome {
info_contents: [version, author],
app_name: self.c_string_helper.to_cstring(app_name).unwrap().as_ptr() as *const c_char,
info_contents: [
self.c_string_helper.to_cstring(version).unwrap().as_ptr() as *const c_char,
self.c_string_helper.to_cstring(author).unwrap().as_ptr() as *const c_char,
],
..self
}
}
Expand All @@ -168,47 +192,22 @@ impl<'a> NbglHome<'a> {
where
Reply: From<<T as TryFrom<ApduHeader>>::Error>,
{
let icon = if let Some(glyph) = self.glyph {
&glyph.into() as *const nbgl_icon_details_t
} else {
core::ptr::null() as *const nbgl_icon_details_t
};

let helper: CStringHelper<128> = CStringHelper::new();
let c_ver = helper.to_cstring(&self.info_contents[0]).unwrap();
let c_dev = helper.to_cstring(&self.info_contents[1]).unwrap();
let c_app_name = helper.to_cstring(&self.app_name).unwrap();

unsafe {
let info_list: nbgl_contentInfoList_t = nbgl_contentInfoList_t {
infoTypes: [
"Version\0".as_ptr() as *const c_char,
"Developer\0".as_ptr() as *const c_char,
]
.as_ptr(),
infoContents: [
c_ver.as_ptr() as *const c_char,
c_dev.as_ptr() as *const c_char,
]
.as_ptr(),
nbInfos: 2,
};
self.info_list.infoTypes = INFO_FIELDS.as_ptr() as *const *const c_char;
self.info_list.infoContents = self.info_contents.as_ptr() as *const *const c_char;
self.info_list.nbInfos = 2;

let setting_contents: nbgl_genericContents_t = nbgl_genericContents_t {
callbackCallNeeded: false,
__bindgen_anon_1: nbgl_genericContents_t__bindgen_ty_1 {
contentsList: core::ptr::null(),
},
nbContents: 0,
};
loop {
if self.glyph.is_some() {
self.icon = &self.glyph.unwrap().into() as *const nbgl_icon_details_t;
}
match ledger_secure_sdk_sys::ux_sync_homeAndSettings(
c_app_name.as_ptr() as *const c_char,
icon,
self.app_name,
self.icon as *const nbgl_icon_details_t,
core::ptr::null(),
INIT_HOME_PAGE as u8,
&setting_contents as *const nbgl_genericContents_t,
&info_list as *const nbgl_contentInfoList_t,
core::ptr::null(),
&self.info_list as *const nbgl_contentInfoList_t,
core::ptr::null(),
) {
ledger_secure_sdk_sys::UX_SYNC_RET_APDU_RECEIVED => {
Expand Down Expand Up @@ -236,6 +235,7 @@ pub struct NbglReview<
subtitle: &'a str,
finish_title: &'a str,
glyph: Option<&'a NbglGlyph<'a>>,
icon: *const nbgl_icon_details_t,
tag_value_array: [nbgl_layoutTagValue_t; MAX_FIELD_NUMBER],
c_string_helper: CStringHelper<STRING_BUFFER_SIZE>,
}
Expand All @@ -249,6 +249,7 @@ impl<'a, const MAX_FIELD_NUMBER: usize, const STRING_BUFFER_SIZE: usize>
subtitle: "To send CRAB",
finish_title: "Sign transaction",
glyph: None,
icon: core::ptr::null(),
tag_value_array: [nbgl_layoutTagValue_t::default(); MAX_FIELD_NUMBER],
c_string_helper: CStringHelper::<STRING_BUFFER_SIZE>::new(),
}
Expand Down Expand Up @@ -285,6 +286,9 @@ impl<'a, const MAX_FIELD_NUMBER: usize, const STRING_BUFFER_SIZE: usize>
panic!("Too many fields for this review instance.");
}

// Flush the internal buffer of the CStringHelper.
self.c_string_helper.flush();

// Fill the tag_value_array with the fields converted to nbgl_layoutTagValue_t
// with proper c strings (ending with \0).
for (i, field) in fields.iter().enumerate() {
Expand Down Expand Up @@ -312,23 +316,20 @@ impl<'a, const MAX_FIELD_NUMBER: usize, const STRING_BUFFER_SIZE: usize>
wrapping: false,
};

// Convert the glyph into a nbgl_icon_details_t or set it to null.
let icon = if let Some(glyph) = self.glyph {
&glyph.into() as *const nbgl_icon_details_t
} else {
core::ptr::null() as *const nbgl_icon_details_t
};

// Convert the title, subtitle and finish_title into c strings.
let c_title = self.c_string_helper.to_cstring(self.title).unwrap();
let c_subtitle = self.c_string_helper.to_cstring(self.subtitle).unwrap();
let c_finish_title = self.c_string_helper.to_cstring(self.finish_title).unwrap();

if self.glyph.is_some() {
self.icon = &self.glyph.unwrap().into() as *const nbgl_icon_details_t;
}

// Show the review on the device.
let sync_ret = ledger_secure_sdk_sys::ux_sync_review(
TYPE_TRANSACTION,
&tag_value_list as *const nbgl_layoutTagValueList_t,
icon,
self.icon,
c_title.as_ptr() as *const c_char,
c_subtitle.as_ptr() as *const c_char,
c_finish_title.as_ptr() as *const c_char,
Expand All @@ -350,6 +351,7 @@ impl<'a, const MAX_FIELD_NUMBER: usize, const STRING_BUFFER_SIZE: usize>
}

pub struct NbglAddressConfirm<'a> {
icon: *const nbgl_icon_details_t,
glyph: Option<&'a NbglGlyph<'a>>,
verify_str: &'a str,
}
Expand All @@ -358,6 +360,7 @@ impl<'a> NbglAddressConfirm<'a> {
pub fn new() -> NbglAddressConfirm<'a> {
NbglAddressConfirm {
verify_str: "Verify address",
icon: core::ptr::null(),
glyph: None,
}
}
Expand All @@ -375,23 +378,20 @@ impl<'a> NbglAddressConfirm<'a> {

pub fn show(&mut self, address: &str) -> bool {
unsafe {
// Convert the glyph into a nbgl_icon_details_t or set it to null.
let icon = if let Some(glyph) = self.glyph {
&glyph.into() as *const nbgl_icon_details_t
} else {
core::ptr::null() as *const nbgl_icon_details_t
};

// Create CStringHelper instance and convert the address and verify_str into c strings.
let c_string_helper = CStringHelper::<128>::new();
let c_addr_str = c_string_helper.to_cstring(address).unwrap();
let c_verif_str = c_string_helper.to_cstring(self.verify_str).unwrap();

if self.glyph.is_some() {
self.icon = &self.glyph.unwrap().into() as *const nbgl_icon_details_t;
}

// Show the address confirmation on the device.
let sync_ret = ux_sync_addressReview(
c_addr_str.as_ptr() as *const c_char,
core::ptr::null(),
icon,
self.icon,
c_verif_str.as_ptr() as *const c_char,
core::ptr::null(),
);
Expand Down
2 changes: 1 addition & 1 deletion ledger_device_sdk/src/nvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ macro_rules! atomic_storage {
atomic_storage!(64);
#[cfg(target_os = "nanox")]
atomic_storage!(256);
#[cfg(any(target_os = "nanosplus", target_os = "stax"))]
#[cfg(any(target_os = "nanosplus", target_os = "stax", target_os = "flex"))]
atomic_storage!(512);

pub enum AtomicStorageElem {
Expand Down
Loading

0 comments on commit 3e2ed8b

Please sign in to comment.