1 // Copyright 2024, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! This file provides one possible implementation of the sysdeps functions for libavb.
16 //! Global allocator is required.
17 
18 #![cfg_attr(not(test), no_std)]
19 
20 extern crate alloc;
21 use alloc::alloc::{alloc, dealloc};
22 use core::{
23     alloc::Layout,
24     cmp::{min, Ord},
25     ffi::CStr,
26     mem::size_of,
27     ptr::{null_mut, NonNull},
28 };
29 
30 /// `avb_malloc_()` requires allocation to be word aligned.
31 const AVB_MALLOC_ALIGNMENT: usize = 2;
32 
33 #[no_mangle]
avb_abort() -> !34 pub extern "C" fn avb_abort() -> ! {
35     panic!("avb_abort");
36 }
37 
38 #[no_mangle]
avb_malloc_(size: usize) -> *mut core::ffi::c_void39 pub extern "C" fn avb_malloc_(size: usize) -> *mut core::ffi::c_void {
40     (|| {
41         // Allocate extra to store the size value.
42         let size = size_of::<usize>().checked_add(size)?;
43         // SAFETY:
44         // *  On success, `alloc` guarantees to allocate enough memory.
45         // * `size.to_le_bytes().as_ptr()` is guaranteed valid memory.
46         // * Alignment is 1 for bytes copy.
47         unsafe {
48             let ptr =
49                 NonNull::new(alloc(Layout::from_size_align(size, AVB_MALLOC_ALIGNMENT).ok()?))?;
50             ptr.as_ptr().copy_from(size.to_le_bytes().as_ptr(), size_of::<usize>());
51             let ptr = ptr.as_ptr().add(size_of::<usize>());
52             Some(ptr)
53         }
54     })()
55     .unwrap_or(null_mut()) as _
56 }
57 
58 #[no_mangle]
avb_free(ptr: *mut core::ffi::c_void)59 pub extern "C" fn avb_free(ptr: *mut core::ffi::c_void) {
60     assert_ne!(ptr, null_mut());
61     let mut ptr = ptr as *mut u8;
62     let mut size_bytes = [0u8; size_of::<usize>()];
63     // SAFETY:
64     // * `ptr` is allocated by `avb_malloc_` and guarantees to have enough memory for a preceding
65     //   usize value and payload.
66     // * `size_bytes.as_mut_ptr()` is a valid memory location.
67     // * Alignment is 1 for bytes copy.
68     unsafe {
69         ptr = ptr.sub(size_of::<usize>());
70         ptr.copy_to(size_bytes.as_mut_ptr(), size_of::<usize>())
71     };
72     let size = usize::from_le_bytes(size_bytes);
73     // SAFETY: Call to global allocator.
74     unsafe { dealloc(ptr, Layout::from_size_align(size, AVB_MALLOC_ALIGNMENT).unwrap()) };
75 }
76 
77 #[no_mangle]
avb_strlen(s: *const core::ffi::c_char) -> usize78 pub extern "C" fn avb_strlen(s: *const core::ffi::c_char) -> usize {
79     // SAFETY: libavb guarantees to pass valid NULL-terminated strings to this function. The
80     // returned reference is only used to compute string length.
81     unsafe { CStr::from_ptr(s as *const _) }.to_bytes().len()
82 }
83 
84 #[no_mangle]
avb_div_by_10(dividend: *mut u64) -> u3285 pub extern "C" fn avb_div_by_10(dividend: *mut u64) -> u32 {
86     // SAFETY: libavb guarantees to pass valid pointer to u64 integer here
87     let val = unsafe { &mut *dividend };
88     let rem = *val % 10;
89     *val /= 10;
90     rem.try_into().unwrap()
91 }
92 
93 #[no_mangle]
avb_memcpy( dest: *mut core::ffi::c_void, src: *const core::ffi::c_void, n: usize, ) -> *mut core::ffi::c_void94 pub extern "C" fn avb_memcpy(
95     dest: *mut core::ffi::c_void,
96     src: *const core::ffi::c_void,
97     n: usize,
98 ) -> *mut core::ffi::c_void {
99     // SAFETY: libavb guarantees to pass valid pointers.
100     unsafe { (src.cast::<u8>()).copy_to(dest as *mut _, n) };
101     dest
102 }
103 
104 #[no_mangle]
avb_memcmp( src1: *const core::ffi::c_void, src2: *const core::ffi::c_void, n: usize, ) -> core::ffi::c_int105 pub extern "C" fn avb_memcmp(
106     src1: *const core::ffi::c_void,
107     src2: *const core::ffi::c_void,
108     n: usize,
109 ) -> core::ffi::c_int {
110     // SAFETY: libavb guarantees to pass valid pointers. References are only used within function.
111     let (lhs, rhs) = unsafe {
112         (
113             core::slice::from_raw_parts(src1 as *const u8, n),
114             core::slice::from_raw_parts(src2 as *const u8, n),
115         )
116     };
117     Ord::cmp(lhs, rhs) as i32
118 }
119 
120 #[no_mangle]
avb_strcmp( s1: *const core::ffi::c_char, s2: *const core::ffi::c_char, ) -> core::ffi::c_int121 pub extern "C" fn avb_strcmp(
122     s1: *const core::ffi::c_char,
123     s2: *const core::ffi::c_char,
124 ) -> core::ffi::c_int {
125     // SAFETY: libavb guarantees to pass valid NULL-terminated strings. References are only used
126     // within function.
127     let (lhs, rhs) = unsafe { (CStr::from_ptr(s1 as *const _), CStr::from_ptr(s2 as *const _)) };
128     Ord::cmp(lhs, rhs) as i32
129 }
130 
131 #[no_mangle]
avb_strncmp( s1: *const core::ffi::c_char, s2: *const core::ffi::c_char, n: usize, ) -> core::ffi::c_int132 pub extern "C" fn avb_strncmp(
133     s1: *const core::ffi::c_char,
134     s2: *const core::ffi::c_char,
135     n: usize,
136 ) -> core::ffi::c_int {
137     // SAFETY: libavb guarantees to pass valid NULL-terminated strings. References are only used
138     // within function.
139     let (lhs, rhs) = unsafe { (CStr::from_ptr(s1 as *const _), CStr::from_ptr(s2 as *const _)) };
140     let cmp_size = min(min(lhs.to_bytes().len(), rhs.to_bytes().len()), n);
141     Ord::cmp(&lhs.to_bytes()[..cmp_size], &rhs.to_bytes()[..cmp_size]) as i32
142 }
143 
144 #[no_mangle]
avb_memset( dest: *mut core::ffi::c_void, c: core::ffi::c_int, n: usize, ) -> *mut core::ffi::c_void145 pub extern "C" fn avb_memset(
146     dest: *mut core::ffi::c_void,
147     c: core::ffi::c_int,
148     n: usize,
149 ) -> *mut core::ffi::c_void {
150     // SAFETY: libavb guarantees to pass valid buffer. Reference is only used within function.
151     let arr = unsafe { core::slice::from_raw_parts_mut(dest as *mut u8, n) };
152     arr.fill(c as u8);
153     dest
154 }
155