diff --git a/dts/sentry.dtsi b/dts/sentry.dtsi index 4f459175..dbb54857 100644 --- a/dts/sentry.dtsi +++ b/dts/sentry.dtsi @@ -22,7 +22,7 @@ }; idle_code: idle_code@800c000 { - reg = <0x800c000 0x300>; + reg = <0x800c000 0x400>; compatible = "outpost,memory-pool"; }; diff --git a/uapi/src/exchange.rs b/uapi/src/exchange.rs new file mode 100644 index 00000000..3305cc3e --- /dev/null +++ b/uapi/src/exchange.rs @@ -0,0 +1,189 @@ +// SPDX-FileCopyrightText: 2023 Ledger SAS +// SPDX-License-Identifier: Apache-2.0 + +use crate::systypes::shm::ShmInfo; +use crate::systypes::Status; +use core::ptr::*; + +const EXCHANGE_AREA_LEN: usize = 128; // TODO: replace by CONFIG-defined value + +/// The effective kernelspace/userspace exchange zone, set in a dedicated section +/// +#[unsafe(link_section = ".svcexchange")] +static mut EXCHANGE_AREA: [u8; EXCHANGE_AREA_LEN] = [0u8; EXCHANGE_AREA_LEN]; + +/// Trait of kernel-user exchangeable objects +/// +/// This trait written in order to support the notion of "kernel-exchangeable" +/// type. Any type that do support this trait can be delivered to (and/or received +/// from) the kernel. +/// +/// The effective implementation of this trait public functions are kept private, +/// and can't be implemented out of this very crate in order to ensure that only +/// this crate's declared types are exchangeable. +/// To ensure such a restriction, this trait is hosted by the current, crate-private, +/// module. +/// +/// As a consequence, don't try to implement that trait in any of the upper layers. +/// +pub trait SentryExchangeable { + /// Copy the current object to the kernel exchagne zone + fn to_kernel(&self) -> Result; + + /// set the current object using the data delivered by the kernel in the exchange zone + fn from_kernel(&mut self) -> Result; +} + +/// SentryExchangeable trait implementation for ShmInfo. +/// Shminfo is a typical structure which is returned by the kernel to the +/// userspace in order to delivers various SHM-related information to a given +/// task that is using the corresponding SHM. +/// +/// In test mode only, this structure can be written back to the Exchange Area. +/// In production mode, the application can't write such a content to the exchange +/// as the kernel as strictly no use of it. +/// +impl SentryExchangeable for crate::systypes::shm::ShmInfo { + #[allow(static_mut_refs)] + fn from_kernel(&mut self) -> Result { + unsafe { + core::ptr::copy_nonoverlapping( + EXCHANGE_AREA.as_ptr(), + addr_of_mut!(*self) as *mut u8, + core::mem::size_of::().min(EXCHANGE_AREA_LEN), + ); + } + Ok(Status::Ok) + } + + #[cfg(test)] + #[allow(static_mut_refs)] + fn to_kernel(&self) -> Result { + unsafe { + core::ptr::copy_nonoverlapping( + addr_of!(*self) as *const u8, + EXCHANGE_AREA.as_mut_ptr(), + core::mem::size_of::().min(EXCHANGE_AREA_LEN), + ); + } + Ok(Status::Ok) + } + + #[cfg(not(test))] + #[allow(static_mut_refs)] + fn to_kernel(&self) -> Result { + Err(Status::Invalid) + } +} + +impl SentryExchangeable for &mut [u8] { + #[allow(static_mut_refs)] + fn from_kernel(&mut self) -> Result { + unsafe { + core::ptr::copy_nonoverlapping( + EXCHANGE_AREA.as_ptr(), + self.as_mut_ptr(), + self.len().min(EXCHANGE_AREA_LEN), + ); + } + Ok(Status::Ok) + } + + #[allow(static_mut_refs)] + fn to_kernel(&self) -> Result { + unsafe { + core::ptr::copy_nonoverlapping( + self.as_ptr(), + EXCHANGE_AREA.as_mut_ptr(), + self.len().min(EXCHANGE_AREA_LEN), + ); + } + Ok(Status::Ok) + } +} + +impl SentryExchangeable for &[u8] { + #[allow(static_mut_refs)] + fn from_kernel(&mut self) -> Result { + Err(Status::Invalid) + } + + #[allow(static_mut_refs)] + fn to_kernel(&self) -> Result { + unsafe { + core::ptr::copy_nonoverlapping( + self.as_ptr(), + EXCHANGE_AREA.as_mut_ptr(), + self.len().min(EXCHANGE_AREA_LEN), + ); + } + Ok(Status::Ok) + } +} + +pub const fn length() -> usize { + EXCHANGE_AREA_LEN +} + +/// copy to kernel generic implementation +/// +/// This API is a generic implementation in order to allow userspace to kernelspace +/// exchange for any type that do implement the SentryExchangeable trait. +/// +/// # Example +/// +/// A basic usage would look like the following: +/// +/// ```ignore +/// let my_info: &[u8] = &[1,2,3,4]; +/// copy_to_kernel(my_info); +/// ``` +/// +pub fn copy_to_kernel(from: &T) -> Result +where + T: SentryExchangeable + ?Sized, +{ + from.to_kernel() +} + +pub fn copy_from_kernel(to: &mut T) -> Result +where + T: SentryExchangeable + ?Sized, +{ + to.from_kernel() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn back_to_back_shminfo() { + let src = ShmInfo { + handle: 2, + label: 42, + base: 0x123456, + len: 64, + perms: 0x1, + }; + let mut dst = ShmInfo { + handle: 0, + label: 0, + base: 0, + len: 0, + perms: 0, + }; + let _ = src.to_kernel(); + let _ = dst.from_kernel(); + assert_eq!(src, dst); + } + + #[test] + fn back_to_back_c_string() { + let src: &[u8] = &[42, 1, 3, 5, 12]; + let mut dst: &mut [u8] = &mut [0, 0, 0, 0, 0]; + assert_eq!(src.to_kernel(), Ok(Status::Ok)); + assert_eq!(dst.from_kernel(), Ok(Status::Ok)); + assert_eq!(src, dst); + } +} diff --git a/uapi/src/ffi_c.rs b/uapi/src/ffi_c.rs index 0b5b04c5..ad629ed7 100644 --- a/uapi/src/ffi_c.rs +++ b/uapi/src/ffi_c.rs @@ -1,63 +1,76 @@ // SPDX-FileCopyrightText: 2023 Ledger SAS // SPDX-License-Identifier: Apache-2.0 +use crate::exchange; use crate::systypes::*; +/// C interface to [`crate::syscall::get_process_handle`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_get_process_handle(process: TaskLabel) -> Status { crate::syscall::get_process_handle(process) } +/// C interface to [`crate::syscall::exit`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_exit(status: i32) -> Status { crate::syscall::exit(status) } +/// C interface to [`crate::syscall::get_shm_handle`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_get_shm_handle(shm: ShmLabel) -> Status { crate::syscall::get_shm_handle(shm) } +/// C interface to [`crate::syscall::get_dma_stream_handle`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_get_dma_stream_handle(stream: StreamLabel) -> Status { crate::syscall::get_dma_stream_handle(stream) } +/// C interface to [`crate::syscall::sched_yield`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_sched_yield() -> Status { crate::syscall::sched_yield() } +/// C interface to [`crate::syscall::sleep`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_sleep(duration_ms: SleepDuration, mode: SleepMode) -> Status { crate::syscall::sleep(duration_ms, mode) } +/// C interface to [`crate::syscall::start`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_start(process: TaskLabel) -> Status { crate::syscall::start(process) } +/// C interface to [`crate::syscall::map_dev`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_map_dev(dev: DeviceHandle) -> Status { crate::syscall::map_dev(dev as DeviceHandle) } +/// C interface to [`crate::syscall::map_shm`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_map_shm(shm: ShmHandle) -> Status { crate::syscall::map_shm(shm as ShmHandle) } +/// C interface to [`crate::syscall::unmap_dev`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_unmap_dev(dev: DeviceHandle) -> Status { crate::syscall::unmap_dev(dev as DeviceHandle) } +/// C interface to [`crate::syscall::unmap_shm`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_unmap_shm(shm: ShmHandle) -> Status { crate::syscall::unmap_shm(shm as ShmHandle) } +/// C interface to [`crate::syscall::shm_set_credential`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_shm_set_credential( shm: ShmHandle, @@ -67,132 +80,179 @@ pub extern "C" fn __sys_shm_set_credential( crate::syscall::shm_set_credential(shm, id, shm_perm) } +/// C interface to [`crate::syscall::send_ipc`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_send_ipc(target: TaskHandle, length: u8) -> Status { crate::syscall::send_ipc(target, length) } +/// C interface to [`crate::syscall::send_signal`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_send_signal(resource: u32, signal_type: Signal) -> Status { crate::syscall::send_signal(resource, signal_type) } +/// C interface to [`crate::syscall::gpio_get`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_gpio_get(resource: u32, io: u8) -> Status { crate::syscall::gpio_get(resource, io) } +/// C interface to [`crate::syscall::gpio_set`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_gpio_set(resource: u32, io: u8, val: bool) -> Status { crate::syscall::gpio_set(resource, io, val) } +/// C interface to [`crate::syscall::gpio_reset`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_gpio_reset(resource: u32, io: u8) -> Status { crate::syscall::gpio_reset(resource, io) } +/// C interface to [`crate::syscall::gpio_toggle`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_gpio_toggle(resource: u32, io: u8) -> Status { crate::syscall::gpio_toggle(resource, io) } +/// C interface to [`crate::syscall::gpio_configure`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_gpio_configure(resource: u32, io: u8) -> Status { crate::syscall::gpio_configure(resource, io) } +/// C interface to [`crate::syscall::get_device_handle`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_get_device_handle(devlabel: u8) -> Status { crate::syscall::get_device_handle(devlabel) } +/// C interface to [`crate::syscall::irq_acknowledge`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_irq_acknowledge(irq: u16) -> Status { crate::syscall::irq_acknowledge(irq) } +/// C interface to [`crate::syscall::irq_enable`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_irq_enable(irq: u16) -> Status { crate::syscall::irq_enable(irq) } +/// C interface to [`crate::syscall::irq_disable`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_irq_disable(irq: u16) -> Status { crate::syscall::irq_disable(irq) } +/// C interface to [`crate::syscall::wait_for_event`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_wait_for_event(mask: u8, timeout: i32) -> Status { crate::syscall::wait_for_event(mask, timeout) } +/// C interface to [`crate::syscall::pm_manage`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_pm_manage(mode: CPUSleep) -> Status { crate::syscall::pm_manage(mode) } +/// C interface to [`crate::syscall::alarm`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_alarm(timeout_ms: u32, flag: AlarmFlag) -> Status { crate::syscall::alarm(timeout_ms, flag) } +/// C interface to [`crate::syscall::log`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_log(length: usize) -> Status { crate::syscall::log(length) } +/// C interface to [`crate::syscall::get_random`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_get_random() -> Status { crate::syscall::get_random() } +/// C interface to [`crate::syscall::get_cycle`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_get_cycle(precision: Precision) -> Status { crate::syscall::get_cycle(precision) } +/// C interface to [`crate::syscall::pm_set_clock`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_pm_set_clock(clk_reg: u32, clkmsk: u32, val: u32) -> Status { crate::syscall::pm_set_clock(clk_reg, clkmsk, val) } +/// C interface to [`crate::syscall::dma_start_stream`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_dma_start_stream(dmah: StreamHandle) -> Status { crate::syscall::dma_start_stream(dmah) } +/// C interface to [`crate::syscall::dma_suspend_stream`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_dma_suspend_stream(dmah: StreamHandle) -> Status { crate::syscall::dma_suspend_stream(dmah) } +/// C interface to [`crate::syscall::dma_get_stream_status`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_dma_get_stream_status(dmah: StreamHandle) -> Status { crate::syscall::dma_get_stream_status(dmah) } +/// C interface to [`crate::syscall::shm_get_infos`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_shm_get_infos(shm: ShmHandle) -> Status { crate::syscall::shm_get_infos(shm) } +/// C interface to [`crate::syscall::dma_assign_stream`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_dma_assign_stream(dmah: StreamHandle) -> Status { crate::syscall::dma_assign_stream(dmah) } +/// C interface to [`crate::syscall::dma_unassign_stream`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_dma_unassign_stream(dmah: StreamHandle) -> Status { crate::syscall::dma_unassign_stream(dmah) } +/// C interface to [`crate::syscall::dma_get_stream_info`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_dma_get_stream_info(dmah: StreamHandle) -> Status { crate::syscall::dma_get_stream_info(dmah) } +/// C interface to [`crate::syscall::dma_resume_stream`] syscall Rust implementation #[no_mangle] pub extern "C" fn __sys_dma_resume_stream(dmah: StreamHandle) -> Status { crate::syscall::dma_resume_stream(dmah) } + +/// C interface to [`crate::copy_to_kernel`] Rust implementation +#[no_mangle] +pub extern "C" fn copy_from_user(from: *mut u8, length: usize) -> Status { + let u8_slice: &[u8] = unsafe { core::slice::from_raw_parts(from, length) }; + match exchange::copy_to_kernel(&u8_slice) { + Ok(_) => Status::Ok, + Err(err) => err, + } +} + +/// C interface to [`crate::copy_from_kernel`] Rust implementation +#[no_mangle] +pub extern "C" fn copy_to_user(to: *mut u8, length: usize) -> Status { + let mut u8_slice: &mut [u8] = + unsafe { core::slice::from_raw_parts_mut(to, length) as &mut [u8] }; + match exchange::copy_from_kernel(&mut u8_slice) { + Ok(_) => Status::Ok, + Err(err) => err, + } +} diff --git a/uapi/src/lib.rs b/uapi/src/lib.rs index 8218ead1..00f51d43 100644 --- a/uapi/src/lib.rs +++ b/uapi/src/lib.rs @@ -37,7 +37,7 @@ mod arch; /// pub mod ffi_c; -/// Sentry SVC_EXCHANGE area manipulation primitives +/// Sentry kernel exchange area manipulation primitives /// /// # Usage /// @@ -45,7 +45,7 @@ pub mod ffi_c; /// interface is used. Sentry kernel interactions should be, instead, made with /// an upper interface. /// -/// As the SVC_EXCHANGE area is a special userspace/kernelspace fixed size area +/// As the exchange area is a special userspace/kernelspace fixed size area /// made in order to exchange data between userspace and kernelspace without /// manipulating any pointer, this space has a particular meaning and usage, holding /// any type of content as a 'retention area' before and after system calls. @@ -62,7 +62,7 @@ pub mod ffi_c; /// if unsafe is used, there is no UB risk when manipulating the exchange area /// based on the Operating System architecture. /// -pub mod svc_exchange; +mod exchange; /// Sentry kernel low level syscall implementation /// @@ -101,5 +101,17 @@ pub mod syscall; /// pub mod systypes; +/// Copy a given generic type from the kernel exchange zone to the given mutable reference +pub use self::exchange::copy_from_kernel; + +/// Copy a given generic type to the kernel exchange zone from the given eference +pub use self::exchange::copy_to_kernel; + +/// Sentry exchangeable opaque trait, only defined for systypes defined types +/// +/// This trait is declared in order to allow the attribute checking but is not +/// exported as no upper layer type needs to implement it +pub use self::exchange::SentryExchangeable; + #[cfg(not(feature = "std"))] mod panic; diff --git a/uapi/src/meson.build b/uapi/src/meson.build index b330c3c7..fd12472c 100644 --- a/uapi/src/meson.build +++ b/uapi/src/meson.build @@ -8,7 +8,7 @@ uapi_libfile = files('lib.rs') # dependencies through meson introspect, we should add deps to inner modules uapi_modules = files([ 'panic.rs', - 'svc_exchange.rs', + 'exchange.rs', 'syscall.rs', 'systypes.rs', ]) diff --git a/uapi/src/svc_exchange.rs b/uapi/src/svc_exchange.rs deleted file mode 100644 index 7dcf4903..00000000 --- a/uapi/src/svc_exchange.rs +++ /dev/null @@ -1,159 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Ledger SAS -// SPDX-License-Identifier: Apache-2.0 - -use crate::systypes::{EraseMode, EraseType, Status}; -use core::ptr::addr_of_mut; - -/// SVC Exchange area len. TODO: to be kconfig-generated -pub const SVC_EXCH_AREA_LEN: usize = 128; // TODO: replace by CONFIG-defined value -/// SVC Exchange exchange header size -pub const SVC_EXCH_AREA_HEADER: usize = 8; // TODO: associated to types.h based header definition - -/// This SVC exchange area is always defined for all apps, so it is declared -/// here in UAPI.rs. `copy_from_user` and `copy_to_user` functions are provided -/// for easy access to this area. -#[cfg_attr(test, no_mangle)] -#[link_section = ".svcexchange"] -pub static mut SVC_EXCHANGE_AREA: [u8; SVC_EXCH_AREA_LEN] = [0u8; SVC_EXCH_AREA_LEN]; - -unsafe fn check_bounds(pointer: *const u8, length: usize) -> Result<(), ()> { - let svcexc = SVC_EXCHANGE_AREA.as_ptr(); - let svcexc_end = svcexc.add(SVC_EXCH_AREA_LEN); - - // buffer starts in the middle of the exchange area, abort - if pointer >= svcexc && pointer <= svcexc_end { - return Err(()); - } - - // buffer ends in the exchange area, abort - // Note: this is unlikely to happen if `svc_exchange` is always assumed to be at - // the beginning of RAM - let buffer_end = pointer.add(length); - if buffer_end >= svcexc && buffer_end <= svcexc_end { - return Err(()); - } - - // exchange area is contained within the buffer, abort - if pointer <= svcexc && buffer_end >= svcexc_end { - return Err(()); - } - - Ok(()) -} - -#[no_mangle] -pub unsafe extern "C" fn svcexchange_get_maxlen() -> usize { - return SVC_EXCH_AREA_LEN - SVC_EXCH_AREA_HEADER; -} - -/// Copy data to svc_exchange area -/// -/// # Safety -/// -/// Callers must ensure memory pointed to by `from` up to `from + length` belongs to -/// a valid variable. -#[no_mangle] -pub unsafe extern "C" fn copy_from_user(from: *const u8, length: usize) -> Status { - if check_bounds(from, length).is_err() { - return Status::Invalid; - } - core::ptr::copy_nonoverlapping( - from, - SVC_EXCHANGE_AREA.as_mut_ptr(), - length.min(SVC_EXCH_AREA_LEN), - ); - Status::Ok -} - -/// Copy data from svc_exchange area to user-controlled buffer -/// -/// # Safety -/// -/// Callers must ensure memory pointed to by `from` up to `from + length` belongs to -/// a valid variable. -/// SVC Exchange area content is not cleared after copy -#[no_mangle] -pub unsafe extern "C" fn copy_to_user(to: *mut u8, length: usize) -> Status { - if check_bounds(to, length).is_err() { - return Status::Invalid; - } - core::ptr::copy_nonoverlapping( - SVC_EXCHANGE_AREA.as_ptr(), - to, - length.min(SVC_EXCH_AREA_LEN), - ); - Status::Ok -} - -/// SVC Exchange area content cleaner -/// -/// The cleaning part can't be done in the copy_to_user impl as -/// userspace may copy svcechange() data with consecutive calls -/// (e.g. when reading the header first, then the overall content) -#[no_mangle] -pub extern "C" fn clean_svcexchange(erasetype: EraseType, mode: EraseMode) -> Status { - match erasetype { - EraseType::Zeroify => (), - _ => return Status::Invalid, - } - match mode { - EraseMode::UserErase => (), - _ => return Status::Invalid, - } - unsafe { - core::ptr::write_volatile( - addr_of_mut!(SVC_EXCHANGE_AREA) as *mut [u8; SVC_EXCH_AREA_LEN], - [0; SVC_EXCH_AREA_LEN], - ); - } - Status::Ok -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn back_to_back_copy() { - let string = [b'z'; 100]; - let mut res = [b'a'; 100]; - unsafe { - copy_from_user(string.as_ptr(), string.len()); - copy_to_user(res.as_mut_ptr(), string.len()); - } - assert_eq!(res, string); - } - - #[test] - fn truncated_copy() { - let string = [b'z'; 156]; - let mut res = [b'a'; 128]; - unsafe { - copy_from_user(string.as_ptr(), string.len()); - copy_to_user(res.as_mut_ptr(), string.len()); - } - assert_eq!(&res[..], &string[..128]); - } - - #[test] - fn invalid_src() { - unsafe { - assert_eq!( - copy_from_user(SVC_EXCHANGE_AREA.as_ptr(), 4), - Status::Invalid - ); - } - } - - #[test] - fn invalid_dest() { - let string = [b'z'; 4]; - unsafe { - copy_from_user(string.as_ptr(), string.len()); - assert_eq!( - copy_to_user(SVC_EXCHANGE_AREA.as_mut_ptr(), string.len()), - Status::Invalid - ); - } - } -} diff --git a/uapi/src/syscall.rs b/uapi/src/syscall.rs index 77fd4324..9e5e5fa6 100644 --- a/uapi/src/syscall.rs +++ b/uapi/src/syscall.rs @@ -1,7 +1,8 @@ // SPDX-FileCopyrightText: 2023 Ledger SAS // SPDX-License-Identifier: Apache-2.0 -use crate::{svc_exchange, systypes::*}; +use crate::exchange; +use crate::systypes::*; #[cfg(not(target_arch = "x86_64"))] use core::arch::asm; @@ -620,21 +621,6 @@ pub fn gpio_configure(resource: u32, io: u8) -> Status { /// requested device not in own by the caller, Status::Denied is returned. /// In these cases, the SVC_EXCHANGE area is not set. /// -/// # Example -/// -/// ```rust -/// use sentry_uapi::{syscall, svc_exchange::*, systypes::*}; -/// -/// fn get_handle() -> Result { -/// let devlabel : u8 = 0x42; -/// match syscall::get_device_handle(devlabel) { -/// Status::Ok => (), -/// any_err => return Err(any_err), -/// }; -/// let exch_area = unsafe { &mut SVC_EXCHANGE_AREA[..4] }; -/// Ok(u32::from_ne_bytes(exch_area.try_into().map_err(|_| Status::Invalid)?)) -/// } -/// ``` /// #[inline(always)] pub fn get_device_handle(devlabel: u8) -> Status { @@ -714,7 +700,7 @@ pub fn alarm(timeout_ms: u32, flag: AlarmFlag) -> Status { /// the UART. #[inline(always)] pub fn log(length: usize) -> Status { - if length > svc_exchange::SVC_EXCH_AREA_LEN { + if length > exchange::length() { Status::Invalid } else { syscall!(Syscall::Log, length as u32).into() diff --git a/uapi/src/systypes.rs b/uapi/src/systypes.rs index 3bf57451..15a56942 100644 --- a/uapi/src/systypes.rs +++ b/uapi/src/systypes.rs @@ -767,7 +767,7 @@ pub mod dev { pub ios: [IoInfo; 8usize], } #[test] - fn bindgen_test_layout_DevInfo() { + fn test_layout_devinfo() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( @@ -867,7 +867,7 @@ pub mod dev { pub mod shm { #[repr(C)] - #[derive(Debug, Copy, Clone)] + #[derive(PartialEq, Debug, Copy, Clone)] pub struct ShmInfo { pub handle: crate::systypes::ShmHandle, pub label: u32,