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