1*5225e6b1SAndroid Build Coastguard Worker // Copyright 2024, The Android Open Source Project
2*5225e6b1SAndroid Build Coastguard Worker //
3*5225e6b1SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*5225e6b1SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*5225e6b1SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*5225e6b1SAndroid Build Coastguard Worker //
7*5225e6b1SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*5225e6b1SAndroid Build Coastguard Worker //
9*5225e6b1SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*5225e6b1SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*5225e6b1SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*5225e6b1SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*5225e6b1SAndroid Build Coastguard Worker // limitations under the License.
14*5225e6b1SAndroid Build Coastguard Worker
15*5225e6b1SAndroid Build Coastguard Worker //! This file provides C interface wrappers of libabr APIs.
16*5225e6b1SAndroid Build Coastguard Worker
17*5225e6b1SAndroid Build Coastguard Worker #![cfg_attr(not(test), no_std)]
18*5225e6b1SAndroid Build Coastguard Worker
19*5225e6b1SAndroid Build Coastguard Worker use abr::{
20*5225e6b1SAndroid Build Coastguard Worker get_and_clear_one_shot_flag, get_boot_slot, get_slot_info, get_slot_last_marked_active,
21*5225e6b1SAndroid Build Coastguard Worker mark_slot_active, mark_slot_successful, mark_slot_unbootable, set_one_shot_bootloader,
22*5225e6b1SAndroid Build Coastguard Worker set_one_shot_recovery, AbrData, AbrSlotData, Ops, SlotIndex, SlotInfo as AbrSlotInfo,
23*5225e6b1SAndroid Build Coastguard Worker SlotState, ABR_DATA_SIZE,
24*5225e6b1SAndroid Build Coastguard Worker };
25*5225e6b1SAndroid Build Coastguard Worker use core::{
26*5225e6b1SAndroid Build Coastguard Worker ffi::{c_char, c_uint, c_void},
27*5225e6b1SAndroid Build Coastguard Worker fmt::Write,
28*5225e6b1SAndroid Build Coastguard Worker };
29*5225e6b1SAndroid Build Coastguard Worker use liberror::{Error, Result};
30*5225e6b1SAndroid Build Coastguard Worker
31*5225e6b1SAndroid Build Coastguard Worker pub mod utils;
32*5225e6b1SAndroid Build Coastguard Worker
33*5225e6b1SAndroid Build Coastguard Worker pub const ABR_RESULT_OK: c_uint = 0;
34*5225e6b1SAndroid Build Coastguard Worker pub const ABR_RESULT_ERR_IO: c_uint = 1;
35*5225e6b1SAndroid Build Coastguard Worker pub const ABR_RESULT_ERR_INVALID_DATA: c_uint = 2;
36*5225e6b1SAndroid Build Coastguard Worker pub const ABR_RESULT_ERR_UNSUPPORTED_VERSION: c_uint = 3;
37*5225e6b1SAndroid Build Coastguard Worker
38*5225e6b1SAndroid Build Coastguard Worker // ABR system dependencies.
39*5225e6b1SAndroid Build Coastguard Worker //
40*5225e6b1SAndroid Build Coastguard Worker // These correspond to the definitions in Fuchsia upstream header
41*5225e6b1SAndroid Build Coastguard Worker // "src/firmware/lib/abr/include/lib/abr/sysdeps.h", which will eventually migrate over.
42*5225e6b1SAndroid Build Coastguard Worker extern "C" {
43*5225e6b1SAndroid Build Coastguard Worker /// Prints out a NULL-terminated string.
AbrPrint(message: *const c_char)44*5225e6b1SAndroid Build Coastguard Worker pub fn AbrPrint(message: *const c_char);
45*5225e6b1SAndroid Build Coastguard Worker
46*5225e6b1SAndroid Build Coastguard Worker /// Aborts the program or reboots the device if |abort| is not implemented.
AbrAbort()47*5225e6b1SAndroid Build Coastguard Worker pub fn AbrAbort();
48*5225e6b1SAndroid Build Coastguard Worker }
49*5225e6b1SAndroid Build Coastguard Worker
50*5225e6b1SAndroid Build Coastguard Worker /// A helper to print an ASCII character via `AbrPrint()`.
abr_print_ascii_char(ch: u8)51*5225e6b1SAndroid Build Coastguard Worker fn abr_print_ascii_char(ch: u8) {
52*5225e6b1SAndroid Build Coastguard Worker let s = [ch, 0];
53*5225e6b1SAndroid Build Coastguard Worker // SAFETY:
54*5225e6b1SAndroid Build Coastguard Worker // * `s` is a valid buffer
55*5225e6b1SAndroid Build Coastguard Worker // * `s` is for input only and will not be retained by the function.
56*5225e6b1SAndroid Build Coastguard Worker unsafe { AbrPrint(s.as_ptr() as _) }
57*5225e6b1SAndroid Build Coastguard Worker }
58*5225e6b1SAndroid Build Coastguard Worker
59*5225e6b1SAndroid Build Coastguard Worker /// A helper structure that implements formatted write using `AbrPrint()`.
60*5225e6b1SAndroid Build Coastguard Worker struct AbrPrintSysdeps {}
61*5225e6b1SAndroid Build Coastguard Worker
62*5225e6b1SAndroid Build Coastguard Worker impl Write for AbrPrintSysdeps {
write_str(&mut self, s: &str) -> core::fmt::Result63*5225e6b1SAndroid Build Coastguard Worker fn write_str(&mut self, s: &str) -> core::fmt::Result {
64*5225e6b1SAndroid Build Coastguard Worker if s.is_ascii() {
65*5225e6b1SAndroid Build Coastguard Worker s.as_bytes().iter().for_each(|v| abr_print_ascii_char(*v));
66*5225e6b1SAndroid Build Coastguard Worker }
67*5225e6b1SAndroid Build Coastguard Worker Ok(())
68*5225e6b1SAndroid Build Coastguard Worker }
69*5225e6b1SAndroid Build Coastguard Worker }
70*5225e6b1SAndroid Build Coastguard Worker
71*5225e6b1SAndroid Build Coastguard Worker /// A panic handler is needed when building as a static library. We simply call into
72*5225e6b1SAndroid Build Coastguard Worker /// the AbrAbort() system dependency.
73*5225e6b1SAndroid Build Coastguard Worker #[cfg(not(test))]
74*5225e6b1SAndroid Build Coastguard Worker #[panic_handler]
panic(panic: &core::panic::PanicInfo<'_>) -> !75*5225e6b1SAndroid Build Coastguard Worker fn panic(panic: &core::panic::PanicInfo<'_>) -> ! {
76*5225e6b1SAndroid Build Coastguard Worker write!(AbrPrintSysdeps {}, "libabr panics! {}", panic).unwrap();
77*5225e6b1SAndroid Build Coastguard Worker // SAFETY: Call to external C function. The function simply aborts/reboots the system.
78*5225e6b1SAndroid Build Coastguard Worker unsafe { AbrAbort() };
79*5225e6b1SAndroid Build Coastguard Worker unreachable!()
80*5225e6b1SAndroid Build Coastguard Worker }
81*5225e6b1SAndroid Build Coastguard Worker
82*5225e6b1SAndroid Build Coastguard Worker /// This corresponds to the `AbrOps` C definition in Fuchsia upstream header
83*5225e6b1SAndroid Build Coastguard Worker /// "src/firmware/lib/abr/include/lib/abr/ops.h", which will eventually migrate over.
84*5225e6b1SAndroid Build Coastguard Worker ///
85*5225e6b1SAndroid Build Coastguard Worker /// typedef struct AbrOps {
86*5225e6b1SAndroid Build Coastguard Worker /// void* context;
87*5225e6b1SAndroid Build Coastguard Worker /// bool (*read_abr_metadata)(void* context, size_t size, uint8_t* buffer);
88*5225e6b1SAndroid Build Coastguard Worker /// bool (*write_abr_metadata)(void* context, const uint8_t* buffer, size_t size);
89*5225e6b1SAndroid Build Coastguard Worker /// bool (*read_abr_metadata_custom)(void* context, AbrSlotData* a_slot_data,
90*5225e6b1SAndroid Build Coastguard Worker /// AbrSlotData* b_slot_data, uint8_t* one_shot_flags);
91*5225e6b1SAndroid Build Coastguard Worker /// bool (*write_abr_metadata_custom)(void* context, const AbrSlotData* a_slot_data,
92*5225e6b1SAndroid Build Coastguard Worker /// const AbrSlotData* b_slot_data, uint8_t one_shot_flags);
93*5225e6b1SAndroid Build Coastguard Worker /// } AbrOps;
94*5225e6b1SAndroid Build Coastguard Worker #[repr(C)]
95*5225e6b1SAndroid Build Coastguard Worker #[derive(Debug, Copy, Clone)]
96*5225e6b1SAndroid Build Coastguard Worker pub struct AbrOps {
97*5225e6b1SAndroid Build Coastguard Worker pub context: *mut c_void,
98*5225e6b1SAndroid Build Coastguard Worker pub read_abr_metadata:
99*5225e6b1SAndroid Build Coastguard Worker Option<unsafe extern "C" fn(context: *mut c_void, size: usize, buffer: *mut u8) -> bool>,
100*5225e6b1SAndroid Build Coastguard Worker pub write_abr_metadata:
101*5225e6b1SAndroid Build Coastguard Worker Option<unsafe extern "C" fn(context: *mut c_void, buffer: *const u8, size: usize) -> bool>,
102*5225e6b1SAndroid Build Coastguard Worker pub read_abr_metadata_custom: Option<
103*5225e6b1SAndroid Build Coastguard Worker unsafe extern "C" fn(
104*5225e6b1SAndroid Build Coastguard Worker context: *mut c_void,
105*5225e6b1SAndroid Build Coastguard Worker a_slot_data: *mut AbrSlotData,
106*5225e6b1SAndroid Build Coastguard Worker b_slot_data: *mut AbrSlotData,
107*5225e6b1SAndroid Build Coastguard Worker one_shot_flags: *mut u8,
108*5225e6b1SAndroid Build Coastguard Worker ) -> bool,
109*5225e6b1SAndroid Build Coastguard Worker >,
110*5225e6b1SAndroid Build Coastguard Worker pub write_abr_metadata_custom: Option<
111*5225e6b1SAndroid Build Coastguard Worker unsafe extern "C" fn(
112*5225e6b1SAndroid Build Coastguard Worker context: *mut c_void,
113*5225e6b1SAndroid Build Coastguard Worker a_slot_data: *const AbrSlotData,
114*5225e6b1SAndroid Build Coastguard Worker b_slot_data: *const AbrSlotData,
115*5225e6b1SAndroid Build Coastguard Worker one_shot_flags: u8,
116*5225e6b1SAndroid Build Coastguard Worker ) -> bool,
117*5225e6b1SAndroid Build Coastguard Worker >,
118*5225e6b1SAndroid Build Coastguard Worker }
119*5225e6b1SAndroid Build Coastguard Worker
120*5225e6b1SAndroid Build Coastguard Worker /// `AbrOpsSafe` wraps a reference to `AbrOps` and is created by an unsafe constructor that
121*5225e6b1SAndroid Build Coastguard Worker /// establishes necessary safety invariants on `AbrOps`.
122*5225e6b1SAndroid Build Coastguard Worker struct AbrOpsSafe<'a> {
123*5225e6b1SAndroid Build Coastguard Worker ops: &'a AbrOps,
124*5225e6b1SAndroid Build Coastguard Worker log: AbrPrintSysdeps,
125*5225e6b1SAndroid Build Coastguard Worker }
126*5225e6b1SAndroid Build Coastguard Worker
127*5225e6b1SAndroid Build Coastguard Worker impl<'a> AbrOpsSafe<'a> {
128*5225e6b1SAndroid Build Coastguard Worker /// Creates a new instance from a reference to `AbrOps`.
129*5225e6b1SAndroid Build Coastguard Worker ///
130*5225e6b1SAndroid Build Coastguard Worker /// # Safety
131*5225e6b1SAndroid Build Coastguard Worker ///
132*5225e6b1SAndroid Build Coastguard Worker /// * Caller must make sure that `ops.context` is either not used, or points to a valid and
133*5225e6b1SAndroid Build Coastguard Worker /// correct type of value needed by `ops.read_abr_metadata`, `ops.write_abr_metadata`,
134*5225e6b1SAndroid Build Coastguard Worker /// `ops.read_abr_metadata_custom` and `ops.write_abr_metadata_custom`.
new(ops: &'a AbrOps) -> Self135*5225e6b1SAndroid Build Coastguard Worker unsafe fn new(ops: &'a AbrOps) -> Self {
136*5225e6b1SAndroid Build Coastguard Worker Self { ops, log: AbrPrintSysdeps {} }
137*5225e6b1SAndroid Build Coastguard Worker }
138*5225e6b1SAndroid Build Coastguard Worker }
139*5225e6b1SAndroid Build Coastguard Worker
140*5225e6b1SAndroid Build Coastguard Worker type AbrSlotIndex = c_uint;
141*5225e6b1SAndroid Build Coastguard Worker
142*5225e6b1SAndroid Build Coastguard Worker impl Ops for AbrOpsSafe<'_> {
read_abr_metadata(&mut self, out: &mut [u8]) -> Result<()>143*5225e6b1SAndroid Build Coastguard Worker fn read_abr_metadata(&mut self, out: &mut [u8]) -> Result<()> {
144*5225e6b1SAndroid Build Coastguard Worker if let Some(f) = self.ops.read_abr_metadata.as_ref() {
145*5225e6b1SAndroid Build Coastguard Worker // SAFETY:
146*5225e6b1SAndroid Build Coastguard Worker // * By safety requirement of `AbrOpsSafe::new()`, `self.ops.context` is either unused,
147*5225e6b1SAndroid Build Coastguard Worker // or a valid pointer to a correct type of object used by
148*5225e6b1SAndroid Build Coastguard Worker // `self.ops.write_abr_metadata`.
149*5225e6b1SAndroid Build Coastguard Worker // * `out` is a valid buffer
150*5225e6b1SAndroid Build Coastguard Worker // * `out` is for reading data only and will not be retained by the function.
151*5225e6b1SAndroid Build Coastguard Worker match unsafe { f(self.ops.context, out.len(), out.as_mut_ptr() as _) } {
152*5225e6b1SAndroid Build Coastguard Worker false => Err(Error::Other(Some("read_abr_metadata() failed"))),
153*5225e6b1SAndroid Build Coastguard Worker _ => Ok(()),
154*5225e6b1SAndroid Build Coastguard Worker }
155*5225e6b1SAndroid Build Coastguard Worker } else if let Some(f) = self.ops.read_abr_metadata_custom.as_ref() {
156*5225e6b1SAndroid Build Coastguard Worker let mut data: AbrData = Default::default();
157*5225e6b1SAndroid Build Coastguard Worker // SAFETY:
158*5225e6b1SAndroid Build Coastguard Worker // * By safety requirement of `AbrOpsSafe::new()`, `self.ops.context` is either unused,
159*5225e6b1SAndroid Build Coastguard Worker // or a valid pointer to a correct type of object used by
160*5225e6b1SAndroid Build Coastguard Worker // `self.ops.read_abr_metadata_custom`.
161*5225e6b1SAndroid Build Coastguard Worker // * Pointers to `slot_a`, `slot_b` and `one_shot_flags` are a valid memory locations.
162*5225e6b1SAndroid Build Coastguard Worker // * `slot_a`, `slot_b` and `one_shot_flags` are for output and will not be retained by
163*5225e6b1SAndroid Build Coastguard Worker // the function.
164*5225e6b1SAndroid Build Coastguard Worker match unsafe {
165*5225e6b1SAndroid Build Coastguard Worker f(
166*5225e6b1SAndroid Build Coastguard Worker self.ops.context,
167*5225e6b1SAndroid Build Coastguard Worker &mut data.slot_data[SlotIndex::A as usize],
168*5225e6b1SAndroid Build Coastguard Worker &mut data.slot_data[SlotIndex::B as usize],
169*5225e6b1SAndroid Build Coastguard Worker &mut data.one_shot_flags,
170*5225e6b1SAndroid Build Coastguard Worker )
171*5225e6b1SAndroid Build Coastguard Worker } {
172*5225e6b1SAndroid Build Coastguard Worker false => Err(Error::Other(Some("read_abr_metadata_custom() failed"))),
173*5225e6b1SAndroid Build Coastguard Worker _ => Ok(out[..ABR_DATA_SIZE].clone_from_slice(&data.serialize())),
174*5225e6b1SAndroid Build Coastguard Worker }
175*5225e6b1SAndroid Build Coastguard Worker } else {
176*5225e6b1SAndroid Build Coastguard Worker Err(Error::NotImplemented)
177*5225e6b1SAndroid Build Coastguard Worker }
178*5225e6b1SAndroid Build Coastguard Worker }
179*5225e6b1SAndroid Build Coastguard Worker
write_abr_metadata(&mut self, data: &mut [u8]) -> Result<()>180*5225e6b1SAndroid Build Coastguard Worker fn write_abr_metadata(&mut self, data: &mut [u8]) -> Result<()> {
181*5225e6b1SAndroid Build Coastguard Worker if let Some(f) = self.ops.write_abr_metadata.as_ref() {
182*5225e6b1SAndroid Build Coastguard Worker // SAFETY:
183*5225e6b1SAndroid Build Coastguard Worker // * By safety requirement of `AbrOpsSafe::new()`, `self.ops.context` is either unused,
184*5225e6b1SAndroid Build Coastguard Worker // or a valid pointer to a correct type of object used by
185*5225e6b1SAndroid Build Coastguard Worker // `self.ops.write_abr_metadata`.
186*5225e6b1SAndroid Build Coastguard Worker // * `data` is a valid buffer.
187*5225e6b1SAndroid Build Coastguard Worker // * `data` is for input only and will not be retained by the function.
188*5225e6b1SAndroid Build Coastguard Worker match unsafe { f(self.ops.context, data.as_ptr() as _, data.len()) } {
189*5225e6b1SAndroid Build Coastguard Worker false => Err(Error::Other(Some("write_abr_metadata() failed"))),
190*5225e6b1SAndroid Build Coastguard Worker _ => Ok(()),
191*5225e6b1SAndroid Build Coastguard Worker }
192*5225e6b1SAndroid Build Coastguard Worker } else if let Some(f) = self.ops.write_abr_metadata_custom.as_ref() {
193*5225e6b1SAndroid Build Coastguard Worker let mut abr_data = [0u8; ABR_DATA_SIZE];
194*5225e6b1SAndroid Build Coastguard Worker abr_data.clone_from_slice(
195*5225e6b1SAndroid Build Coastguard Worker data.get(..ABR_DATA_SIZE).ok_or(Error::BufferTooSmall(Some(ABR_DATA_SIZE)))?,
196*5225e6b1SAndroid Build Coastguard Worker );
197*5225e6b1SAndroid Build Coastguard Worker let abr_data = AbrData::deserialize(&mut abr_data).unwrap();
198*5225e6b1SAndroid Build Coastguard Worker // SAFETY:
199*5225e6b1SAndroid Build Coastguard Worker // * By safety requirement of `AbrOpsSafe::new()`, `self.ops.context` is either unused,
200*5225e6b1SAndroid Build Coastguard Worker // or a valid pointer to a correct type of object used by
201*5225e6b1SAndroid Build Coastguard Worker // `self.ops.write_abr_metadata_custom`.
202*5225e6b1SAndroid Build Coastguard Worker // * Pointers to `slot_a` and `slot_b` are a valid memory locations.
203*5225e6b1SAndroid Build Coastguard Worker // * `slot_a` and `slot_b` are for input and will not be retained by the function.
204*5225e6b1SAndroid Build Coastguard Worker match unsafe {
205*5225e6b1SAndroid Build Coastguard Worker f(
206*5225e6b1SAndroid Build Coastguard Worker self.ops.context,
207*5225e6b1SAndroid Build Coastguard Worker &abr_data.slot_data[SlotIndex::A as usize],
208*5225e6b1SAndroid Build Coastguard Worker &abr_data.slot_data[SlotIndex::B as usize],
209*5225e6b1SAndroid Build Coastguard Worker abr_data.one_shot_flags,
210*5225e6b1SAndroid Build Coastguard Worker )
211*5225e6b1SAndroid Build Coastguard Worker } {
212*5225e6b1SAndroid Build Coastguard Worker false => Err(Error::Other(Some("read_abr_metadata_custom() failed"))),
213*5225e6b1SAndroid Build Coastguard Worker _ => Ok(()),
214*5225e6b1SAndroid Build Coastguard Worker }
215*5225e6b1SAndroid Build Coastguard Worker } else {
216*5225e6b1SAndroid Build Coastguard Worker Err(Error::NotImplemented)
217*5225e6b1SAndroid Build Coastguard Worker }
218*5225e6b1SAndroid Build Coastguard Worker }
219*5225e6b1SAndroid Build Coastguard Worker
console(&mut self) -> Option<&mut dyn core::fmt::Write>220*5225e6b1SAndroid Build Coastguard Worker fn console(&mut self) -> Option<&mut dyn core::fmt::Write> {
221*5225e6b1SAndroid Build Coastguard Worker Some(&mut self.log)
222*5225e6b1SAndroid Build Coastguard Worker }
223*5225e6b1SAndroid Build Coastguard Worker }
224*5225e6b1SAndroid Build Coastguard Worker
225*5225e6b1SAndroid Build Coastguard Worker /// A helper that extracts the return value and maps the result to an integer A/B/R result code.
unpack_result<T: Into<O>, O>(res: Result<T>, val: &mut O) -> c_uint226*5225e6b1SAndroid Build Coastguard Worker fn unpack_result<T: Into<O>, O>(res: Result<T>, val: &mut O) -> c_uint {
227*5225e6b1SAndroid Build Coastguard Worker match res {
228*5225e6b1SAndroid Build Coastguard Worker Err(e) => match e {
229*5225e6b1SAndroid Build Coastguard Worker Error::BadMagic | Error::BadChecksum | Error::InvalidInput => {
230*5225e6b1SAndroid Build Coastguard Worker ABR_RESULT_ERR_INVALID_DATA
231*5225e6b1SAndroid Build Coastguard Worker }
232*5225e6b1SAndroid Build Coastguard Worker Error::UnsupportedVersion => ABR_RESULT_ERR_UNSUPPORTED_VERSION,
233*5225e6b1SAndroid Build Coastguard Worker _ => ABR_RESULT_ERR_IO,
234*5225e6b1SAndroid Build Coastguard Worker },
235*5225e6b1SAndroid Build Coastguard Worker Ok(v) => {
236*5225e6b1SAndroid Build Coastguard Worker *val = v.into();
237*5225e6b1SAndroid Build Coastguard Worker ABR_RESULT_OK
238*5225e6b1SAndroid Build Coastguard Worker }
239*5225e6b1SAndroid Build Coastguard Worker }
240*5225e6b1SAndroid Build Coastguard Worker }
241*5225e6b1SAndroid Build Coastguard Worker
242*5225e6b1SAndroid Build Coastguard Worker /// C interface wrapper of `abr::get_boot_slot()`
243*5225e6b1SAndroid Build Coastguard Worker ///
244*5225e6b1SAndroid Build Coastguard Worker /// # Safety
245*5225e6b1SAndroid Build Coastguard Worker ///
246*5225e6b1SAndroid Build Coastguard Worker /// * Caller must make sure to pass a valid pointer for `abr_ops`.
247*5225e6b1SAndroid Build Coastguard Worker /// * Caller must make sure that `abr_ops.context` is either not used, or points to a valid and
248*5225e6b1SAndroid Build Coastguard Worker /// correct type of value needed by `abr_ops.read_abr_metadata` and `abr_ops.write_abr_metadata`.
249*5225e6b1SAndroid Build Coastguard Worker /// * Caller must make sure to pass either a NULL or valid pointer for `is_slot_marked_successful`.
250*5225e6b1SAndroid Build Coastguard Worker #[no_mangle]
251*5225e6b1SAndroid Build Coastguard Worker #[allow(non_snake_case)]
AbrGetBootSlot( abr_ops: *const AbrOps, update_metadata: bool, is_slot_marked_successful: *mut bool, ) -> AbrSlotIndex252*5225e6b1SAndroid Build Coastguard Worker pub unsafe extern "C" fn AbrGetBootSlot(
253*5225e6b1SAndroid Build Coastguard Worker abr_ops: *const AbrOps,
254*5225e6b1SAndroid Build Coastguard Worker update_metadata: bool,
255*5225e6b1SAndroid Build Coastguard Worker is_slot_marked_successful: *mut bool,
256*5225e6b1SAndroid Build Coastguard Worker ) -> AbrSlotIndex {
257*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `abr_ops` to be a valid pointer.
258*5225e6b1SAndroid Build Coastguard Worker let abr_ops = unsafe { abr_ops.as_ref() }.unwrap();
259*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `abr_ops.context` to be valid for `AbrOpsSafe::new`.
260*5225e6b1SAndroid Build Coastguard Worker let mut abr_ops = unsafe { AbrOpsSafe::new(abr_ops) };
261*5225e6b1SAndroid Build Coastguard Worker
262*5225e6b1SAndroid Build Coastguard Worker let (slot_index, successful) = get_boot_slot(&mut abr_ops, update_metadata);
263*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `out_slot` to be a valid pointer or `NULL`.
264*5225e6b1SAndroid Build Coastguard Worker match unsafe { is_slot_marked_successful.as_mut() } {
265*5225e6b1SAndroid Build Coastguard Worker Some(v) => *v = successful,
266*5225e6b1SAndroid Build Coastguard Worker _ => {}
267*5225e6b1SAndroid Build Coastguard Worker };
268*5225e6b1SAndroid Build Coastguard Worker slot_index.into()
269*5225e6b1SAndroid Build Coastguard Worker }
270*5225e6b1SAndroid Build Coastguard Worker
271*5225e6b1SAndroid Build Coastguard Worker // NULL terminated strings for slot suffixes.
272*5225e6b1SAndroid Build Coastguard Worker const SLOT_A_SUFFIX: &[u8] = b"_a\0";
273*5225e6b1SAndroid Build Coastguard Worker const SLOT_B_SUFFIX: &[u8] = b"_b\0";
274*5225e6b1SAndroid Build Coastguard Worker const SLOT_R_SUFFIX: &[u8] = b"_r\0";
275*5225e6b1SAndroid Build Coastguard Worker const SLOT_SUFFIX_INVALID: &[u8] = b"\0";
276*5225e6b1SAndroid Build Coastguard Worker
277*5225e6b1SAndroid Build Coastguard Worker /// C interface for getting slot suffix.
278*5225e6b1SAndroid Build Coastguard Worker #[no_mangle]
279*5225e6b1SAndroid Build Coastguard Worker #[allow(non_snake_case)]
AbrGetSlotSuffix(slot_index: AbrSlotIndex) -> *const c_char280*5225e6b1SAndroid Build Coastguard Worker pub extern "C" fn AbrGetSlotSuffix(slot_index: AbrSlotIndex) -> *const c_char {
281*5225e6b1SAndroid Build Coastguard Worker match slot_index.try_into() {
282*5225e6b1SAndroid Build Coastguard Worker Ok(SlotIndex::A) => &SLOT_A_SUFFIX,
283*5225e6b1SAndroid Build Coastguard Worker Ok(SlotIndex::B) => &SLOT_B_SUFFIX,
284*5225e6b1SAndroid Build Coastguard Worker Ok(SlotIndex::R) => &SLOT_R_SUFFIX,
285*5225e6b1SAndroid Build Coastguard Worker Err(_) => &SLOT_SUFFIX_INVALID,
286*5225e6b1SAndroid Build Coastguard Worker }
287*5225e6b1SAndroid Build Coastguard Worker .as_ptr() as _
288*5225e6b1SAndroid Build Coastguard Worker }
289*5225e6b1SAndroid Build Coastguard Worker
290*5225e6b1SAndroid Build Coastguard Worker /// C interface wrapper of `abr::mark_slot_active()`
291*5225e6b1SAndroid Build Coastguard Worker ///
292*5225e6b1SAndroid Build Coastguard Worker /// # Safety
293*5225e6b1SAndroid Build Coastguard Worker ///
294*5225e6b1SAndroid Build Coastguard Worker /// * Caller must make sure to pass a valid pointer for `abr_ops`.
295*5225e6b1SAndroid Build Coastguard Worker /// * Caller must make sure that `abr_ops.context` is either not used, or points to a valid and
296*5225e6b1SAndroid Build Coastguard Worker /// correct type of value needed by `abr_ops.read_abr_metadata` and `abr_ops.write_abr_metadata`.
297*5225e6b1SAndroid Build Coastguard Worker #[no_mangle]
298*5225e6b1SAndroid Build Coastguard Worker #[allow(non_snake_case)]
AbrMarkSlotActive( abr_ops: *const AbrOps, slot_index: AbrSlotIndex, ) -> c_uint299*5225e6b1SAndroid Build Coastguard Worker pub unsafe extern "C" fn AbrMarkSlotActive(
300*5225e6b1SAndroid Build Coastguard Worker abr_ops: *const AbrOps,
301*5225e6b1SAndroid Build Coastguard Worker slot_index: AbrSlotIndex,
302*5225e6b1SAndroid Build Coastguard Worker ) -> c_uint {
303*5225e6b1SAndroid Build Coastguard Worker let slot_index = match slot_index.try_into() {
304*5225e6b1SAndroid Build Coastguard Worker Ok(v) => v,
305*5225e6b1SAndroid Build Coastguard Worker Err(_) => return ABR_RESULT_ERR_INVALID_DATA,
306*5225e6b1SAndroid Build Coastguard Worker };
307*5225e6b1SAndroid Build Coastguard Worker
308*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `abr_ops` to be a valid pointer.
309*5225e6b1SAndroid Build Coastguard Worker let abr_ops = unsafe { abr_ops.as_ref() }.unwrap();
310*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `abr_ops.context` to be valid for `AbrOpsSafe::new`.
311*5225e6b1SAndroid Build Coastguard Worker let mut abr_ops = unsafe { AbrOpsSafe::new(abr_ops) };
312*5225e6b1SAndroid Build Coastguard Worker
313*5225e6b1SAndroid Build Coastguard Worker unpack_result(mark_slot_active(&mut abr_ops, slot_index), &mut ())
314*5225e6b1SAndroid Build Coastguard Worker }
315*5225e6b1SAndroid Build Coastguard Worker
316*5225e6b1SAndroid Build Coastguard Worker /// C interface wrapper of `abr::get_slot_last_marked_active()`
317*5225e6b1SAndroid Build Coastguard Worker ///
318*5225e6b1SAndroid Build Coastguard Worker /// # Safety
319*5225e6b1SAndroid Build Coastguard Worker ///
320*5225e6b1SAndroid Build Coastguard Worker /// * Caller must make sure to pass a valid pointer for `abr_ops` and `out_slot`.
321*5225e6b1SAndroid Build Coastguard Worker /// * Caller must make sure that `abr_ops.context` is either not used, or points to a valid and
322*5225e6b1SAndroid Build Coastguard Worker /// correct type of value needed by `abr_ops.read_abr_metadata` and `abr_ops.write_abr_metadata`.
323*5225e6b1SAndroid Build Coastguard Worker #[no_mangle]
324*5225e6b1SAndroid Build Coastguard Worker #[allow(non_snake_case)]
AbrGetSlotLastMarkedActive( abr_ops: *const AbrOps, out_slot: *mut AbrSlotIndex, ) -> c_uint325*5225e6b1SAndroid Build Coastguard Worker pub unsafe extern "C" fn AbrGetSlotLastMarkedActive(
326*5225e6b1SAndroid Build Coastguard Worker abr_ops: *const AbrOps,
327*5225e6b1SAndroid Build Coastguard Worker out_slot: *mut AbrSlotIndex,
328*5225e6b1SAndroid Build Coastguard Worker ) -> c_uint {
329*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `abr_ops` to be a valid pointer.
330*5225e6b1SAndroid Build Coastguard Worker let abr_ops = unsafe { abr_ops.as_ref() }.unwrap();
331*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `abr_ops.context` to be valid for `AbrOpsSafe::new`.
332*5225e6b1SAndroid Build Coastguard Worker let mut abr_ops = unsafe { AbrOpsSafe::new(abr_ops) };
333*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `out_slot` to be a valid pointer.
334*5225e6b1SAndroid Build Coastguard Worker let out_slot = unsafe { out_slot.as_mut() }.unwrap();
335*5225e6b1SAndroid Build Coastguard Worker
336*5225e6b1SAndroid Build Coastguard Worker unpack_result(get_slot_last_marked_active(&mut abr_ops), out_slot)
337*5225e6b1SAndroid Build Coastguard Worker }
338*5225e6b1SAndroid Build Coastguard Worker
339*5225e6b1SAndroid Build Coastguard Worker /// C interface wrapper of `abr::mark_slot_unbootable()`
340*5225e6b1SAndroid Build Coastguard Worker ///
341*5225e6b1SAndroid Build Coastguard Worker /// # Safety
342*5225e6b1SAndroid Build Coastguard Worker ///
343*5225e6b1SAndroid Build Coastguard Worker /// * Caller must make sure to pass a valid pointer for `abr_ops`.
344*5225e6b1SAndroid Build Coastguard Worker /// * Caller must make sure that `abr_ops.context` is either not used, or points to a valid and
345*5225e6b1SAndroid Build Coastguard Worker /// correct type of value needed by `abr_ops.read_abr_metadata` and `abr_ops.write_abr_metadata`.
346*5225e6b1SAndroid Build Coastguard Worker #[no_mangle]
347*5225e6b1SAndroid Build Coastguard Worker #[allow(non_snake_case)]
AbrMarkSlotUnbootable( abr_ops: *const AbrOps, slot_index: AbrSlotIndex, ) -> c_uint348*5225e6b1SAndroid Build Coastguard Worker pub unsafe extern "C" fn AbrMarkSlotUnbootable(
349*5225e6b1SAndroid Build Coastguard Worker abr_ops: *const AbrOps,
350*5225e6b1SAndroid Build Coastguard Worker slot_index: AbrSlotIndex,
351*5225e6b1SAndroid Build Coastguard Worker ) -> c_uint {
352*5225e6b1SAndroid Build Coastguard Worker let slot_index = match slot_index.try_into() {
353*5225e6b1SAndroid Build Coastguard Worker Ok(v) => v,
354*5225e6b1SAndroid Build Coastguard Worker Err(_) => return ABR_RESULT_ERR_INVALID_DATA,
355*5225e6b1SAndroid Build Coastguard Worker };
356*5225e6b1SAndroid Build Coastguard Worker
357*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `abr_ops` to be a valid pointer.
358*5225e6b1SAndroid Build Coastguard Worker let abr_ops = unsafe { abr_ops.as_ref() }.unwrap();
359*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `abr_ops.context` to be valid for `AbrOpsSafe::new`.
360*5225e6b1SAndroid Build Coastguard Worker let mut abr_ops = unsafe { AbrOpsSafe::new(abr_ops) };
361*5225e6b1SAndroid Build Coastguard Worker
362*5225e6b1SAndroid Build Coastguard Worker unpack_result(mark_slot_unbootable(&mut abr_ops, slot_index), &mut ())
363*5225e6b1SAndroid Build Coastguard Worker }
364*5225e6b1SAndroid Build Coastguard Worker
365*5225e6b1SAndroid Build Coastguard Worker /// C interface wrapper of `abr::mark_slot_successful()`
366*5225e6b1SAndroid Build Coastguard Worker ///
367*5225e6b1SAndroid Build Coastguard Worker /// # Safety
368*5225e6b1SAndroid Build Coastguard Worker ///
369*5225e6b1SAndroid Build Coastguard Worker /// * Caller must make sure to pass a valid pointer for `abr_ops`.
370*5225e6b1SAndroid Build Coastguard Worker /// * Caller must make sure that `abr_ops.context` is either not used, or points to a valid and
371*5225e6b1SAndroid Build Coastguard Worker /// correct type of value needed by `abr_ops.read_abr_metadata` and `abr_ops.write_abr_metadata`.
372*5225e6b1SAndroid Build Coastguard Worker #[no_mangle]
373*5225e6b1SAndroid Build Coastguard Worker #[allow(non_snake_case)]
AbrMarkSlotSuccessful( abr_ops: *const AbrOps, slot_index: AbrSlotIndex, ) -> c_uint374*5225e6b1SAndroid Build Coastguard Worker pub unsafe extern "C" fn AbrMarkSlotSuccessful(
375*5225e6b1SAndroid Build Coastguard Worker abr_ops: *const AbrOps,
376*5225e6b1SAndroid Build Coastguard Worker slot_index: AbrSlotIndex,
377*5225e6b1SAndroid Build Coastguard Worker ) -> c_uint {
378*5225e6b1SAndroid Build Coastguard Worker let slot_index = match slot_index.try_into() {
379*5225e6b1SAndroid Build Coastguard Worker Ok(v) => v,
380*5225e6b1SAndroid Build Coastguard Worker Err(_) => return ABR_RESULT_ERR_INVALID_DATA,
381*5225e6b1SAndroid Build Coastguard Worker };
382*5225e6b1SAndroid Build Coastguard Worker
383*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `abr_ops` to be a valid pointer.
384*5225e6b1SAndroid Build Coastguard Worker let abr_ops = unsafe { abr_ops.as_ref() }.unwrap();
385*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `abr_ops.context` to be valid for `AbrOpsSafe::new`.
386*5225e6b1SAndroid Build Coastguard Worker let mut abr_ops = unsafe { AbrOpsSafe::new(abr_ops) };
387*5225e6b1SAndroid Build Coastguard Worker
388*5225e6b1SAndroid Build Coastguard Worker unpack_result(mark_slot_successful(&mut abr_ops, slot_index), &mut ())
389*5225e6b1SAndroid Build Coastguard Worker }
390*5225e6b1SAndroid Build Coastguard Worker
391*5225e6b1SAndroid Build Coastguard Worker /// `SlotInfo` contains the current state of a A/B/R slot.
392*5225e6b1SAndroid Build Coastguard Worker ///
393*5225e6b1SAndroid Build Coastguard Worker /// TODO(b/338243123): Detailed documentation is available in Fuchsia upstream header
394*5225e6b1SAndroid Build Coastguard Worker /// "src/firmware/lib/abr/include/lib/abr/abr.h", which will migrate to the GBL repo.
395*5225e6b1SAndroid Build Coastguard Worker #[repr(C)]
396*5225e6b1SAndroid Build Coastguard Worker #[derive(Debug, Copy, Clone)]
397*5225e6b1SAndroid Build Coastguard Worker pub struct SlotInfo {
398*5225e6b1SAndroid Build Coastguard Worker /// Whether the slot is expected to be bootable.
399*5225e6b1SAndroid Build Coastguard Worker pub is_bootable: bool,
400*5225e6b1SAndroid Build Coastguard Worker /// Whether the slot is the highest priority A/B slot.
401*5225e6b1SAndroid Build Coastguard Worker pub is_active: bool,
402*5225e6b1SAndroid Build Coastguard Worker /// Whether the slot is currently marked successful.
403*5225e6b1SAndroid Build Coastguard Worker pub is_marked_successful: bool,
404*5225e6b1SAndroid Build Coastguard Worker /// If not marked successful, this represents the number of attempts left for booting this slot.
405*5225e6b1SAndroid Build Coastguard Worker pub num_tries_remaining: u8,
406*5225e6b1SAndroid Build Coastguard Worker }
407*5225e6b1SAndroid Build Coastguard Worker
408*5225e6b1SAndroid Build Coastguard Worker impl From<AbrSlotInfo> for SlotInfo {
from(val: abr::SlotInfo) -> Self409*5225e6b1SAndroid Build Coastguard Worker fn from(val: abr::SlotInfo) -> Self {
410*5225e6b1SAndroid Build Coastguard Worker let is_marked_successful = matches!(val.state, SlotState::Successful);
411*5225e6b1SAndroid Build Coastguard Worker let num_tries_remaining = match val.state {
412*5225e6b1SAndroid Build Coastguard Worker SlotState::Bootable(v) => v,
413*5225e6b1SAndroid Build Coastguard Worker _ => 0,
414*5225e6b1SAndroid Build Coastguard Worker };
415*5225e6b1SAndroid Build Coastguard Worker Self {
416*5225e6b1SAndroid Build Coastguard Worker is_bootable: is_marked_successful || num_tries_remaining > 0,
417*5225e6b1SAndroid Build Coastguard Worker is_active: val.is_active,
418*5225e6b1SAndroid Build Coastguard Worker is_marked_successful,
419*5225e6b1SAndroid Build Coastguard Worker num_tries_remaining,
420*5225e6b1SAndroid Build Coastguard Worker }
421*5225e6b1SAndroid Build Coastguard Worker }
422*5225e6b1SAndroid Build Coastguard Worker }
423*5225e6b1SAndroid Build Coastguard Worker
424*5225e6b1SAndroid Build Coastguard Worker /// C interface wrapper of `abr::get_slot_info()`
425*5225e6b1SAndroid Build Coastguard Worker ///
426*5225e6b1SAndroid Build Coastguard Worker /// # Safety
427*5225e6b1SAndroid Build Coastguard Worker ///
428*5225e6b1SAndroid Build Coastguard Worker /// * Caller must make sure to pass a valid pointer for `abr_ops` and 'info'.
429*5225e6b1SAndroid Build Coastguard Worker /// * Caller must make sure that `abr_ops.context` is either not used, or points to a valid and
430*5225e6b1SAndroid Build Coastguard Worker /// correct type of value needed by `abr_ops.read_abr_metadata` and `abr_ops.write_abr_metadata`.
431*5225e6b1SAndroid Build Coastguard Worker #[no_mangle]
432*5225e6b1SAndroid Build Coastguard Worker #[allow(non_snake_case)]
AbrGetSlotInfo( abr_ops: *const AbrOps, slot_index: AbrSlotIndex, info: *mut SlotInfo, ) -> c_uint433*5225e6b1SAndroid Build Coastguard Worker pub unsafe extern "C" fn AbrGetSlotInfo(
434*5225e6b1SAndroid Build Coastguard Worker abr_ops: *const AbrOps,
435*5225e6b1SAndroid Build Coastguard Worker slot_index: AbrSlotIndex,
436*5225e6b1SAndroid Build Coastguard Worker info: *mut SlotInfo,
437*5225e6b1SAndroid Build Coastguard Worker ) -> c_uint {
438*5225e6b1SAndroid Build Coastguard Worker let slot_index = match slot_index.try_into() {
439*5225e6b1SAndroid Build Coastguard Worker Ok(v) => v,
440*5225e6b1SAndroid Build Coastguard Worker Err(_) => return ABR_RESULT_ERR_INVALID_DATA,
441*5225e6b1SAndroid Build Coastguard Worker };
442*5225e6b1SAndroid Build Coastguard Worker
443*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `abr_ops` to be a valid pointer.
444*5225e6b1SAndroid Build Coastguard Worker let abr_ops = unsafe { abr_ops.as_ref() }.unwrap();
445*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `abr_ops.context` to be valid for `AbrOpsSafe::new`.
446*5225e6b1SAndroid Build Coastguard Worker let mut abr_ops = unsafe { AbrOpsSafe::new(abr_ops) };
447*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `info` to be a valid pointer.
448*5225e6b1SAndroid Build Coastguard Worker let info = unsafe { info.as_mut() }.unwrap();
449*5225e6b1SAndroid Build Coastguard Worker
450*5225e6b1SAndroid Build Coastguard Worker unpack_result(get_slot_info(&mut abr_ops, slot_index).map(|v| SlotInfo::from(v)), info)
451*5225e6b1SAndroid Build Coastguard Worker }
452*5225e6b1SAndroid Build Coastguard Worker
453*5225e6b1SAndroid Build Coastguard Worker /// C interface wrapper of `abr::set_one_shot_recovery()`
454*5225e6b1SAndroid Build Coastguard Worker ///
455*5225e6b1SAndroid Build Coastguard Worker /// # Safety
456*5225e6b1SAndroid Build Coastguard Worker ///
457*5225e6b1SAndroid Build Coastguard Worker /// * Caller must make sure to pass a valid pointer for `abr_ops`.
458*5225e6b1SAndroid Build Coastguard Worker /// * Caller must make sure that `abr_ops.context` is either not used, or points to a valid and
459*5225e6b1SAndroid Build Coastguard Worker /// correct type of value needed by `abr_ops.read_abr_metadata` and `abr_ops.write_abr_metadata`.
460*5225e6b1SAndroid Build Coastguard Worker #[no_mangle]
461*5225e6b1SAndroid Build Coastguard Worker #[allow(non_snake_case)]
AbrSetOneShotRecovery(abr_ops: *const AbrOps, enable: bool) -> c_uint462*5225e6b1SAndroid Build Coastguard Worker pub unsafe extern "C" fn AbrSetOneShotRecovery(abr_ops: *const AbrOps, enable: bool) -> c_uint {
463*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `abr_ops` to be a valid pointer.
464*5225e6b1SAndroid Build Coastguard Worker let abr_ops = unsafe { abr_ops.as_ref() }.unwrap();
465*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `abr_ops.context` to be valid for `AbrOpsSafe::new`.
466*5225e6b1SAndroid Build Coastguard Worker let mut abr_ops = unsafe { AbrOpsSafe::new(abr_ops) };
467*5225e6b1SAndroid Build Coastguard Worker
468*5225e6b1SAndroid Build Coastguard Worker unpack_result(set_one_shot_recovery(&mut abr_ops, enable), &mut ())
469*5225e6b1SAndroid Build Coastguard Worker }
470*5225e6b1SAndroid Build Coastguard Worker
471*5225e6b1SAndroid Build Coastguard Worker /// C interface wrapper of `abr::set_one_shot_bootloader()`
472*5225e6b1SAndroid Build Coastguard Worker ///
473*5225e6b1SAndroid Build Coastguard Worker /// # Safety
474*5225e6b1SAndroid Build Coastguard Worker ///
475*5225e6b1SAndroid Build Coastguard Worker /// * Caller must make sure to pass a valid pointer for `abr_ops`.
476*5225e6b1SAndroid Build Coastguard Worker /// * Caller must make sure that `abr_ops.context` is either not used, or points to a valid and
477*5225e6b1SAndroid Build Coastguard Worker /// correct type of value needed by `abr_ops.read_abr_metadata` and `abr_ops.write_abr_metadata`.
478*5225e6b1SAndroid Build Coastguard Worker #[no_mangle]
479*5225e6b1SAndroid Build Coastguard Worker #[allow(non_snake_case)]
AbrSetOneShotBootloader(abr_ops: *const AbrOps, enable: bool) -> c_uint480*5225e6b1SAndroid Build Coastguard Worker pub unsafe extern "C" fn AbrSetOneShotBootloader(abr_ops: *const AbrOps, enable: bool) -> c_uint {
481*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `abr_ops` to be a valid pointer.
482*5225e6b1SAndroid Build Coastguard Worker let abr_ops = unsafe { abr_ops.as_ref() }.unwrap();
483*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `abr_ops.context` to be valid for `AbrOpsSafe::new`.
484*5225e6b1SAndroid Build Coastguard Worker let mut abr_ops = unsafe { AbrOpsSafe::new(abr_ops) };
485*5225e6b1SAndroid Build Coastguard Worker
486*5225e6b1SAndroid Build Coastguard Worker unpack_result(set_one_shot_bootloader(&mut abr_ops, enable), &mut ())
487*5225e6b1SAndroid Build Coastguard Worker }
488*5225e6b1SAndroid Build Coastguard Worker
489*5225e6b1SAndroid Build Coastguard Worker /// Gets and clears the one shot flag.
490*5225e6b1SAndroid Build Coastguard Worker ///
491*5225e6b1SAndroid Build Coastguard Worker /// # Safety
492*5225e6b1SAndroid Build Coastguard Worker ///
493*5225e6b1SAndroid Build Coastguard Worker /// * Caller must make sure to pass a valid pointer for `abr_ops` and `flags`.
494*5225e6b1SAndroid Build Coastguard Worker /// * Caller must make sure that `abr_ops.context` is either not used, or points to a valid and
495*5225e6b1SAndroid Build Coastguard Worker /// correct type of value needed by `abr_ops.read_abr_metadata` and `abr_ops.write_abr_metadata`.
496*5225e6b1SAndroid Build Coastguard Worker #[no_mangle]
497*5225e6b1SAndroid Build Coastguard Worker #[allow(non_snake_case)]
AbrGetAndClearOneShotFlags( abr_ops: *const AbrOps, flags: *mut c_uint, ) -> c_uint498*5225e6b1SAndroid Build Coastguard Worker pub unsafe extern "C" fn AbrGetAndClearOneShotFlags(
499*5225e6b1SAndroid Build Coastguard Worker abr_ops: *const AbrOps,
500*5225e6b1SAndroid Build Coastguard Worker flags: *mut c_uint,
501*5225e6b1SAndroid Build Coastguard Worker ) -> c_uint {
502*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `abr_ops` to be a valid pointer.
503*5225e6b1SAndroid Build Coastguard Worker let abr_ops = unsafe { abr_ops.as_ref() }.unwrap();
504*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `abr_ops.context` to be valid for `AbrOpsSafe::new`.
505*5225e6b1SAndroid Build Coastguard Worker let mut abr_ops = unsafe { AbrOpsSafe::new(abr_ops) };
506*5225e6b1SAndroid Build Coastguard Worker // SAFETY: function safety requires `flags` to be a valid pointer.
507*5225e6b1SAndroid Build Coastguard Worker let flags = unsafe { flags.as_mut() }.unwrap();
508*5225e6b1SAndroid Build Coastguard Worker
509*5225e6b1SAndroid Build Coastguard Worker unpack_result(get_and_clear_one_shot_flag(&mut abr_ops), flags)
510*5225e6b1SAndroid Build Coastguard Worker }
511*5225e6b1SAndroid Build Coastguard Worker
512*5225e6b1SAndroid Build Coastguard Worker // Needed because of no-std environment in static lib build.
513*5225e6b1SAndroid Build Coastguard Worker #[cfg(not(test))]
514*5225e6b1SAndroid Build Coastguard Worker #[no_mangle]
rust_eh_personality()515*5225e6b1SAndroid Build Coastguard Worker pub extern "C" fn rust_eh_personality() {}
516