1*d289c2baSAndroid Build Coastguard Worker // Copyright 2022, The Android Open Source Project
2*d289c2baSAndroid Build Coastguard Worker //
3*d289c2baSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*d289c2baSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*d289c2baSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*d289c2baSAndroid Build Coastguard Worker //
7*d289c2baSAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*d289c2baSAndroid Build Coastguard Worker //
9*d289c2baSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*d289c2baSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*d289c2baSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*d289c2baSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*d289c2baSAndroid Build Coastguard Worker // limitations under the License.
14*d289c2baSAndroid Build Coastguard Worker
15*d289c2baSAndroid Build Coastguard Worker //! Error types used in libavb.
16*d289c2baSAndroid Build Coastguard Worker //!
17*d289c2baSAndroid Build Coastguard Worker //! There are a few advantages of providing these custom types rather than exposing the raw bindgen
18*d289c2baSAndroid Build Coastguard Worker //! enums directly:
19*d289c2baSAndroid Build Coastguard Worker //! * More idiomatic error handling
20*d289c2baSAndroid Build Coastguard Worker //! * C code defines a "status" enum that can contain either OK or an error, whereas Rust prefers
21*d289c2baSAndroid Build Coastguard Worker //! error-only enums to use with `Result<>` e.g. `Result<(), IoError>`. An "OK" status doesn't
22*d289c2baSAndroid Build Coastguard Worker //! make sense when used with `Result<>`.
23*d289c2baSAndroid Build Coastguard Worker //! * Better naming e.g. `IoError::Oom` vs the redundant `AvbIoResult::AVB_IO_RESULT_ERROR_OOM`
24*d289c2baSAndroid Build Coastguard Worker //! * We can implement traits such as `Display` for added convenience.
25*d289c2baSAndroid Build Coastguard Worker
26*d289c2baSAndroid Build Coastguard Worker // The naming scheme can be a bit confusing due to the re-use of "result" in a few places:
27*d289c2baSAndroid Build Coastguard Worker // * `Avb*Result`: raw libavb enums generated by bindgen, containing errors and "OK". Internal-only;
28*d289c2baSAndroid Build Coastguard Worker // library users should never have to use these types.
29*d289c2baSAndroid Build Coastguard Worker // * `*Error`: `Avb*Result` wrappers which only contain error conditions, not "OK". Should be
30*d289c2baSAndroid Build Coastguard Worker // wrapped in a Rust `Result<>` in public API.
31*d289c2baSAndroid Build Coastguard Worker // * `Result<T, *Error>`: top-level `Result<>` type used in this library's public API.
32*d289c2baSAndroid Build Coastguard Worker
33*d289c2baSAndroid Build Coastguard Worker use crate::SlotVerifyData;
34*d289c2baSAndroid Build Coastguard Worker use avb_bindgen::{AvbIOResult, AvbSlotVerifyResult, AvbVBMetaVerifyResult};
35*d289c2baSAndroid Build Coastguard Worker use core::{fmt, str::Utf8Error};
36*d289c2baSAndroid Build Coastguard Worker
37*d289c2baSAndroid Build Coastguard Worker /// `AvbSlotVerifyResult` error wrapper.
38*d289c2baSAndroid Build Coastguard Worker #[derive(Debug, PartialEq, Eq)]
39*d289c2baSAndroid Build Coastguard Worker pub enum SlotVerifyError<'a> {
40*d289c2baSAndroid Build Coastguard Worker /// `AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT`
41*d289c2baSAndroid Build Coastguard Worker InvalidArgument,
42*d289c2baSAndroid Build Coastguard Worker /// `AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA`
43*d289c2baSAndroid Build Coastguard Worker InvalidMetadata,
44*d289c2baSAndroid Build Coastguard Worker /// `AVB_SLOT_VERIFY_RESULT_ERROR_IO`
45*d289c2baSAndroid Build Coastguard Worker Io,
46*d289c2baSAndroid Build Coastguard Worker /// `AVB_SLOT_VERIFY_RESULT_ERROR_OOM`
47*d289c2baSAndroid Build Coastguard Worker Oom,
48*d289c2baSAndroid Build Coastguard Worker /// `AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED`
49*d289c2baSAndroid Build Coastguard Worker PublicKeyRejected,
50*d289c2baSAndroid Build Coastguard Worker /// `AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX`
51*d289c2baSAndroid Build Coastguard Worker RollbackIndex,
52*d289c2baSAndroid Build Coastguard Worker /// `AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION`
53*d289c2baSAndroid Build Coastguard Worker UnsupportedVersion,
54*d289c2baSAndroid Build Coastguard Worker /// `AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION`
55*d289c2baSAndroid Build Coastguard Worker ///
56*d289c2baSAndroid Build Coastguard Worker /// This verification error can contain the resulting `SlotVerifyData` if the
57*d289c2baSAndroid Build Coastguard Worker /// `AllowVerificationError` flag was passed into `slot_verify()`.
58*d289c2baSAndroid Build Coastguard Worker Verification(Option<SlotVerifyData<'a>>),
59*d289c2baSAndroid Build Coastguard Worker /// Unexpected internal error. This does not have a corresponding libavb error code.
60*d289c2baSAndroid Build Coastguard Worker Internal,
61*d289c2baSAndroid Build Coastguard Worker }
62*d289c2baSAndroid Build Coastguard Worker
63*d289c2baSAndroid Build Coastguard Worker /// `Result` type for `SlotVerifyError` errors.
64*d289c2baSAndroid Build Coastguard Worker pub type SlotVerifyResult<'a, T> = Result<T, SlotVerifyError<'a>>;
65*d289c2baSAndroid Build Coastguard Worker
66*d289c2baSAndroid Build Coastguard Worker /// `Result` type for `SlotVerifyError` errors without any `SlotVerifyData`.
67*d289c2baSAndroid Build Coastguard Worker ///
68*d289c2baSAndroid Build Coastguard Worker /// If the contained error will never hold a `SlotVerifyData`, this is easier to work with compared
69*d289c2baSAndroid Build Coastguard Worker /// to `SlotVerifyResult` due to the static lifetime bound.
70*d289c2baSAndroid Build Coastguard Worker pub type SlotVerifyNoDataResult<T> = SlotVerifyResult<'static, T>;
71*d289c2baSAndroid Build Coastguard Worker
72*d289c2baSAndroid Build Coastguard Worker impl<'a> SlotVerifyError<'a> {
73*d289c2baSAndroid Build Coastguard Worker /// Returns a copy of this error without any contained `SlotVerifyData`.
74*d289c2baSAndroid Build Coastguard Worker ///
75*d289c2baSAndroid Build Coastguard Worker /// This can simplify usage if the user doesn't care about the `SlotVerifyData` by turning the
76*d289c2baSAndroid Build Coastguard Worker /// current lifetime bound into `'static`.
without_verify_data(&self) -> SlotVerifyError<'static>77*d289c2baSAndroid Build Coastguard Worker pub fn without_verify_data(&self) -> SlotVerifyError<'static> {
78*d289c2baSAndroid Build Coastguard Worker match self {
79*d289c2baSAndroid Build Coastguard Worker Self::InvalidArgument => SlotVerifyError::InvalidArgument,
80*d289c2baSAndroid Build Coastguard Worker Self::InvalidMetadata => SlotVerifyError::InvalidMetadata,
81*d289c2baSAndroid Build Coastguard Worker Self::Io => SlotVerifyError::Io,
82*d289c2baSAndroid Build Coastguard Worker Self::Oom => SlotVerifyError::Oom,
83*d289c2baSAndroid Build Coastguard Worker Self::PublicKeyRejected => SlotVerifyError::PublicKeyRejected,
84*d289c2baSAndroid Build Coastguard Worker Self::RollbackIndex => SlotVerifyError::RollbackIndex,
85*d289c2baSAndroid Build Coastguard Worker Self::UnsupportedVersion => SlotVerifyError::UnsupportedVersion,
86*d289c2baSAndroid Build Coastguard Worker Self::Verification(_) => SlotVerifyError::Verification(None),
87*d289c2baSAndroid Build Coastguard Worker Self::Internal => SlotVerifyError::Internal,
88*d289c2baSAndroid Build Coastguard Worker }
89*d289c2baSAndroid Build Coastguard Worker }
90*d289c2baSAndroid Build Coastguard Worker }
91*d289c2baSAndroid Build Coastguard Worker
92*d289c2baSAndroid Build Coastguard Worker impl<'a> fmt::Display for SlotVerifyError<'a> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result93*d289c2baSAndroid Build Coastguard Worker fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
94*d289c2baSAndroid Build Coastguard Worker match self {
95*d289c2baSAndroid Build Coastguard Worker Self::InvalidArgument => write!(f, "Invalid parameters"),
96*d289c2baSAndroid Build Coastguard Worker Self::InvalidMetadata => write!(f, "Invalid metadata"),
97*d289c2baSAndroid Build Coastguard Worker Self::Io => write!(f, "I/O error"),
98*d289c2baSAndroid Build Coastguard Worker Self::Oom => write!(f, "Unable to allocate memory"),
99*d289c2baSAndroid Build Coastguard Worker Self::PublicKeyRejected => write!(f, "Public key rejected or data not signed"),
100*d289c2baSAndroid Build Coastguard Worker Self::RollbackIndex => write!(f, "Rollback index violation"),
101*d289c2baSAndroid Build Coastguard Worker Self::UnsupportedVersion => write!(f, "Unsupported vbmeta version"),
102*d289c2baSAndroid Build Coastguard Worker Self::Verification(_) => write!(f, "Verification failure"),
103*d289c2baSAndroid Build Coastguard Worker Self::Internal => write!(f, "Internal error"),
104*d289c2baSAndroid Build Coastguard Worker }
105*d289c2baSAndroid Build Coastguard Worker }
106*d289c2baSAndroid Build Coastguard Worker }
107*d289c2baSAndroid Build Coastguard Worker
108*d289c2baSAndroid Build Coastguard Worker /// Converts a bindgen `AvbSlotVerifyResult` enum to a `SlotVerifyNoDataResult<>`, mapping
109*d289c2baSAndroid Build Coastguard Worker /// `AVB_SLOT_VERIFY_RESULT_OK` to the Rust equivalent `Ok(())` and errors to the corresponding
110*d289c2baSAndroid Build Coastguard Worker /// `Err(SlotVerifyError)`.
111*d289c2baSAndroid Build Coastguard Worker ///
112*d289c2baSAndroid Build Coastguard Worker /// A `Verification` error returned here will always have a `None` `SlotVerifyData`; the data should
113*d289c2baSAndroid Build Coastguard Worker /// be added in later if it exists.
114*d289c2baSAndroid Build Coastguard Worker ///
115*d289c2baSAndroid Build Coastguard Worker /// This function is also important to serve as a compile-time check that we're handling all the
116*d289c2baSAndroid Build Coastguard Worker /// libavb enums; if a new one is added to (or removed from) the C code, this will fail to compile
117*d289c2baSAndroid Build Coastguard Worker /// until it is updated to match.
slot_verify_enum_to_result( result: AvbSlotVerifyResult, ) -> SlotVerifyNoDataResult<()>118*d289c2baSAndroid Build Coastguard Worker pub(crate) fn slot_verify_enum_to_result(
119*d289c2baSAndroid Build Coastguard Worker result: AvbSlotVerifyResult,
120*d289c2baSAndroid Build Coastguard Worker ) -> SlotVerifyNoDataResult<()> {
121*d289c2baSAndroid Build Coastguard Worker match result {
122*d289c2baSAndroid Build Coastguard Worker AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_OK => Ok(()),
123*d289c2baSAndroid Build Coastguard Worker AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT => {
124*d289c2baSAndroid Build Coastguard Worker Err(SlotVerifyError::InvalidArgument)
125*d289c2baSAndroid Build Coastguard Worker }
126*d289c2baSAndroid Build Coastguard Worker AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA => {
127*d289c2baSAndroid Build Coastguard Worker Err(SlotVerifyError::InvalidMetadata)
128*d289c2baSAndroid Build Coastguard Worker }
129*d289c2baSAndroid Build Coastguard Worker AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_ERROR_IO => Err(SlotVerifyError::Io),
130*d289c2baSAndroid Build Coastguard Worker AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_ERROR_OOM => Err(SlotVerifyError::Oom),
131*d289c2baSAndroid Build Coastguard Worker AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED => {
132*d289c2baSAndroid Build Coastguard Worker Err(SlotVerifyError::PublicKeyRejected)
133*d289c2baSAndroid Build Coastguard Worker }
134*d289c2baSAndroid Build Coastguard Worker AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX => {
135*d289c2baSAndroid Build Coastguard Worker Err(SlotVerifyError::RollbackIndex)
136*d289c2baSAndroid Build Coastguard Worker }
137*d289c2baSAndroid Build Coastguard Worker AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION => {
138*d289c2baSAndroid Build Coastguard Worker Err(SlotVerifyError::UnsupportedVersion)
139*d289c2baSAndroid Build Coastguard Worker }
140*d289c2baSAndroid Build Coastguard Worker AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION => {
141*d289c2baSAndroid Build Coastguard Worker Err(SlotVerifyError::Verification(None))
142*d289c2baSAndroid Build Coastguard Worker }
143*d289c2baSAndroid Build Coastguard Worker }
144*d289c2baSAndroid Build Coastguard Worker }
145*d289c2baSAndroid Build Coastguard Worker
146*d289c2baSAndroid Build Coastguard Worker /// `AvbIOResult` error wrapper.
147*d289c2baSAndroid Build Coastguard Worker #[derive(Clone, Debug, PartialEq, Eq)]
148*d289c2baSAndroid Build Coastguard Worker pub enum IoError {
149*d289c2baSAndroid Build Coastguard Worker /// `AVB_IO_RESULT_ERROR_OOM`
150*d289c2baSAndroid Build Coastguard Worker Oom,
151*d289c2baSAndroid Build Coastguard Worker /// `AVB_IO_RESULT_ERROR_IO`
152*d289c2baSAndroid Build Coastguard Worker Io,
153*d289c2baSAndroid Build Coastguard Worker /// `AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION`
154*d289c2baSAndroid Build Coastguard Worker NoSuchPartition,
155*d289c2baSAndroid Build Coastguard Worker /// `AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION`
156*d289c2baSAndroid Build Coastguard Worker RangeOutsidePartition,
157*d289c2baSAndroid Build Coastguard Worker /// `AVB_IO_RESULT_ERROR_NO_SUCH_VALUE`
158*d289c2baSAndroid Build Coastguard Worker NoSuchValue,
159*d289c2baSAndroid Build Coastguard Worker /// `AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE`
160*d289c2baSAndroid Build Coastguard Worker InvalidValueSize,
161*d289c2baSAndroid Build Coastguard Worker /// `AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE`. Also contains the space that would be required.
162*d289c2baSAndroid Build Coastguard Worker InsufficientSpace(usize),
163*d289c2baSAndroid Build Coastguard Worker /// Custom error code to indicate that an optional callback method has not been implemented.
164*d289c2baSAndroid Build Coastguard Worker /// If this is returned from a required callback method, it will bubble up as an `Io` error.
165*d289c2baSAndroid Build Coastguard Worker NotImplemented,
166*d289c2baSAndroid Build Coastguard Worker }
167*d289c2baSAndroid Build Coastguard Worker
168*d289c2baSAndroid Build Coastguard Worker /// `Result` type for `IoError` errors.
169*d289c2baSAndroid Build Coastguard Worker pub type IoResult<T> = Result<T, IoError>;
170*d289c2baSAndroid Build Coastguard Worker
171*d289c2baSAndroid Build Coastguard Worker impl fmt::Display for IoError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result172*d289c2baSAndroid Build Coastguard Worker fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
173*d289c2baSAndroid Build Coastguard Worker match self {
174*d289c2baSAndroid Build Coastguard Worker Self::Oom => write!(f, "Unable to allocate memory"),
175*d289c2baSAndroid Build Coastguard Worker Self::Io => write!(f, "I/O error"),
176*d289c2baSAndroid Build Coastguard Worker Self::NoSuchPartition => write!(f, "No such partition exists"),
177*d289c2baSAndroid Build Coastguard Worker Self::RangeOutsidePartition => write!(f, "Range is outside the partition"),
178*d289c2baSAndroid Build Coastguard Worker Self::NoSuchValue => write!(f, "No such named persistent value"),
179*d289c2baSAndroid Build Coastguard Worker Self::InvalidValueSize => write!(f, "Invalid named persistent value size"),
180*d289c2baSAndroid Build Coastguard Worker Self::InsufficientSpace(size) => write!(f, "Buffer is too small (requires {})", size),
181*d289c2baSAndroid Build Coastguard Worker Self::NotImplemented => write!(f, "Function not implemented"),
182*d289c2baSAndroid Build Coastguard Worker }
183*d289c2baSAndroid Build Coastguard Worker }
184*d289c2baSAndroid Build Coastguard Worker }
185*d289c2baSAndroid Build Coastguard Worker
186*d289c2baSAndroid Build Coastguard Worker impl From<Utf8Error> for IoError {
from(_: Utf8Error) -> Self187*d289c2baSAndroid Build Coastguard Worker fn from(_: Utf8Error) -> Self {
188*d289c2baSAndroid Build Coastguard Worker Self::Io
189*d289c2baSAndroid Build Coastguard Worker }
190*d289c2baSAndroid Build Coastguard Worker }
191*d289c2baSAndroid Build Coastguard Worker
192*d289c2baSAndroid Build Coastguard Worker // Converts our `IoError` to the bindgen `AvbIOResult` enum.
193*d289c2baSAndroid Build Coastguard Worker //
194*d289c2baSAndroid Build Coastguard Worker // Unlike `SlotVerifyError` which gets generated by libavb and passed to the caller, `IoError` is
195*d289c2baSAndroid Build Coastguard Worker // created by the user callbacks and passed back into libavb so we need to be able to convert in
196*d289c2baSAndroid Build Coastguard Worker // this direction as well.
197*d289c2baSAndroid Build Coastguard Worker impl From<IoError> for AvbIOResult {
from(error: IoError) -> Self198*d289c2baSAndroid Build Coastguard Worker fn from(error: IoError) -> Self {
199*d289c2baSAndroid Build Coastguard Worker match error {
200*d289c2baSAndroid Build Coastguard Worker IoError::Oom => AvbIOResult::AVB_IO_RESULT_ERROR_OOM,
201*d289c2baSAndroid Build Coastguard Worker IoError::Io => AvbIOResult::AVB_IO_RESULT_ERROR_IO,
202*d289c2baSAndroid Build Coastguard Worker IoError::NoSuchPartition => AvbIOResult::AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION,
203*d289c2baSAndroid Build Coastguard Worker IoError::RangeOutsidePartition => {
204*d289c2baSAndroid Build Coastguard Worker AvbIOResult::AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION
205*d289c2baSAndroid Build Coastguard Worker }
206*d289c2baSAndroid Build Coastguard Worker IoError::NoSuchValue => AvbIOResult::AVB_IO_RESULT_ERROR_NO_SUCH_VALUE,
207*d289c2baSAndroid Build Coastguard Worker IoError::InvalidValueSize => AvbIOResult::AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE,
208*d289c2baSAndroid Build Coastguard Worker IoError::InsufficientSpace(_) => AvbIOResult::AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE,
209*d289c2baSAndroid Build Coastguard Worker // `NotImplemented` is internal to this library and doesn't have a libavb equivalent,
210*d289c2baSAndroid Build Coastguard Worker // convert it to the default I/O error.
211*d289c2baSAndroid Build Coastguard Worker IoError::NotImplemented => AvbIOResult::AVB_IO_RESULT_ERROR_IO,
212*d289c2baSAndroid Build Coastguard Worker }
213*d289c2baSAndroid Build Coastguard Worker }
214*d289c2baSAndroid Build Coastguard Worker }
215*d289c2baSAndroid Build Coastguard Worker
216*d289c2baSAndroid Build Coastguard Worker /// Converts an `IoResult<>` to the bindgen `AvbIOResult` enum.
result_to_io_enum(result: IoResult<()>) -> AvbIOResult217*d289c2baSAndroid Build Coastguard Worker pub(crate) fn result_to_io_enum(result: IoResult<()>) -> AvbIOResult {
218*d289c2baSAndroid Build Coastguard Worker result.map_or_else(|e| e.into(), |_| AvbIOResult::AVB_IO_RESULT_OK)
219*d289c2baSAndroid Build Coastguard Worker }
220*d289c2baSAndroid Build Coastguard Worker
221*d289c2baSAndroid Build Coastguard Worker /// Converts a bindgen `AvbIOResult` enum to an `IoResult<>`, mapping `AVB_IO_RESULT_OK` to the Rust
222*d289c2baSAndroid Build Coastguard Worker /// equivalent `Ok(())` and errors to the corresponding `Err(IoError)`.
223*d289c2baSAndroid Build Coastguard Worker ///
224*d289c2baSAndroid Build Coastguard Worker /// This function is also important to serve as a compile-time check that we're handling all the
225*d289c2baSAndroid Build Coastguard Worker /// libavb enums; if a new one is added to (or removed from) the C code, this will fail to compile
226*d289c2baSAndroid Build Coastguard Worker /// until it is updated to match.
io_enum_to_result(result: AvbIOResult) -> IoResult<()>227*d289c2baSAndroid Build Coastguard Worker pub(crate) fn io_enum_to_result(result: AvbIOResult) -> IoResult<()> {
228*d289c2baSAndroid Build Coastguard Worker match result {
229*d289c2baSAndroid Build Coastguard Worker AvbIOResult::AVB_IO_RESULT_OK => Ok(()),
230*d289c2baSAndroid Build Coastguard Worker AvbIOResult::AVB_IO_RESULT_ERROR_OOM => Err(IoError::Oom),
231*d289c2baSAndroid Build Coastguard Worker AvbIOResult::AVB_IO_RESULT_ERROR_IO => Err(IoError::Io),
232*d289c2baSAndroid Build Coastguard Worker AvbIOResult::AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION => Err(IoError::NoSuchPartition),
233*d289c2baSAndroid Build Coastguard Worker AvbIOResult::AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION => {
234*d289c2baSAndroid Build Coastguard Worker Err(IoError::RangeOutsidePartition)
235*d289c2baSAndroid Build Coastguard Worker }
236*d289c2baSAndroid Build Coastguard Worker AvbIOResult::AVB_IO_RESULT_ERROR_NO_SUCH_VALUE => Err(IoError::NoSuchValue),
237*d289c2baSAndroid Build Coastguard Worker AvbIOResult::AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE => Err(IoError::InvalidValueSize),
238*d289c2baSAndroid Build Coastguard Worker AvbIOResult::AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE => Err(IoError::InsufficientSpace(0)),
239*d289c2baSAndroid Build Coastguard Worker }
240*d289c2baSAndroid Build Coastguard Worker }
241*d289c2baSAndroid Build Coastguard Worker
242*d289c2baSAndroid Build Coastguard Worker /// `AvbVBMetaVerifyResult` error wrapper.
243*d289c2baSAndroid Build Coastguard Worker #[derive(Clone, Debug, PartialEq, Eq)]
244*d289c2baSAndroid Build Coastguard Worker pub enum VbmetaVerifyError {
245*d289c2baSAndroid Build Coastguard Worker /// `AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED`
246*d289c2baSAndroid Build Coastguard Worker NotSigned,
247*d289c2baSAndroid Build Coastguard Worker /// `AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER`
248*d289c2baSAndroid Build Coastguard Worker InvalidVbmetaHeader,
249*d289c2baSAndroid Build Coastguard Worker /// `AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION`
250*d289c2baSAndroid Build Coastguard Worker UnsupportedVersion,
251*d289c2baSAndroid Build Coastguard Worker /// `AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH`
252*d289c2baSAndroid Build Coastguard Worker HashMismatch,
253*d289c2baSAndroid Build Coastguard Worker /// `AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH`
254*d289c2baSAndroid Build Coastguard Worker SignatureMismatch,
255*d289c2baSAndroid Build Coastguard Worker }
256*d289c2baSAndroid Build Coastguard Worker
257*d289c2baSAndroid Build Coastguard Worker /// `Result` type for `VbmetaVerifyError` errors.
258*d289c2baSAndroid Build Coastguard Worker pub type VbmetaVerifyResult<T> = Result<T, VbmetaVerifyError>;
259*d289c2baSAndroid Build Coastguard Worker
260*d289c2baSAndroid Build Coastguard Worker impl fmt::Display for VbmetaVerifyError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result261*d289c2baSAndroid Build Coastguard Worker fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
262*d289c2baSAndroid Build Coastguard Worker match self {
263*d289c2baSAndroid Build Coastguard Worker Self::NotSigned => write!(f, "vbmeta is unsigned"),
264*d289c2baSAndroid Build Coastguard Worker Self::InvalidVbmetaHeader => write!(f, "invalid vbmeta header"),
265*d289c2baSAndroid Build Coastguard Worker Self::UnsupportedVersion => write!(f, "unsupported vbmeta version"),
266*d289c2baSAndroid Build Coastguard Worker Self::HashMismatch => write!(f, "vbmeta hash mismatch"),
267*d289c2baSAndroid Build Coastguard Worker Self::SignatureMismatch => write!(f, "vbmeta signature mismatch"),
268*d289c2baSAndroid Build Coastguard Worker }
269*d289c2baSAndroid Build Coastguard Worker }
270*d289c2baSAndroid Build Coastguard Worker }
271*d289c2baSAndroid Build Coastguard Worker
272*d289c2baSAndroid Build Coastguard Worker // Converts a bindgen `AvbVBMetaVerifyResult` enum to a `VbmetaVerifyResult<>`, mapping
273*d289c2baSAndroid Build Coastguard Worker // `AVB_VBMETA_VERIFY_RESULT_OK` to the Rust equivalent `Ok(())` and errors to the corresponding
274*d289c2baSAndroid Build Coastguard Worker // `Err(SlotVerifyError)`.
275*d289c2baSAndroid Build Coastguard Worker //
276*d289c2baSAndroid Build Coastguard Worker // This function is also important to serve as a compile-time check that we're handling all the
277*d289c2baSAndroid Build Coastguard Worker // libavb enums; if a new one is added to (or removed from) the C code, this will fail to compile
278*d289c2baSAndroid Build Coastguard Worker // until it is updated to match.
vbmeta_verify_enum_to_result(result: AvbVBMetaVerifyResult) -> VbmetaVerifyResult<()>279*d289c2baSAndroid Build Coastguard Worker pub fn vbmeta_verify_enum_to_result(result: AvbVBMetaVerifyResult) -> VbmetaVerifyResult<()> {
280*d289c2baSAndroid Build Coastguard Worker match result {
281*d289c2baSAndroid Build Coastguard Worker AvbVBMetaVerifyResult::AVB_VBMETA_VERIFY_RESULT_OK => Ok(()),
282*d289c2baSAndroid Build Coastguard Worker AvbVBMetaVerifyResult::AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED => {
283*d289c2baSAndroid Build Coastguard Worker Err(VbmetaVerifyError::NotSigned)
284*d289c2baSAndroid Build Coastguard Worker }
285*d289c2baSAndroid Build Coastguard Worker AvbVBMetaVerifyResult::AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER => {
286*d289c2baSAndroid Build Coastguard Worker Err(VbmetaVerifyError::InvalidVbmetaHeader)
287*d289c2baSAndroid Build Coastguard Worker }
288*d289c2baSAndroid Build Coastguard Worker AvbVBMetaVerifyResult::AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION => {
289*d289c2baSAndroid Build Coastguard Worker Err(VbmetaVerifyError::UnsupportedVersion)
290*d289c2baSAndroid Build Coastguard Worker }
291*d289c2baSAndroid Build Coastguard Worker AvbVBMetaVerifyResult::AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH => {
292*d289c2baSAndroid Build Coastguard Worker Err(VbmetaVerifyError::HashMismatch)
293*d289c2baSAndroid Build Coastguard Worker }
294*d289c2baSAndroid Build Coastguard Worker AvbVBMetaVerifyResult::AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH => {
295*d289c2baSAndroid Build Coastguard Worker Err(VbmetaVerifyError::SignatureMismatch)
296*d289c2baSAndroid Build Coastguard Worker }
297*d289c2baSAndroid Build Coastguard Worker }
298*d289c2baSAndroid Build Coastguard Worker }
299*d289c2baSAndroid Build Coastguard Worker
300*d289c2baSAndroid Build Coastguard Worker #[cfg(test)]
301*d289c2baSAndroid Build Coastguard Worker mod tests {
302*d289c2baSAndroid Build Coastguard Worker use super::*;
303*d289c2baSAndroid Build Coastguard Worker
304*d289c2baSAndroid Build Coastguard Worker #[test]
display_slot_verify_error()305*d289c2baSAndroid Build Coastguard Worker fn display_slot_verify_error() {
306*d289c2baSAndroid Build Coastguard Worker // The actual error message can change as needed, the point of the test is just to make sure
307*d289c2baSAndroid Build Coastguard Worker // the fmt::Display trait is properly implemented.
308*d289c2baSAndroid Build Coastguard Worker assert_eq!(
309*d289c2baSAndroid Build Coastguard Worker format!("{}", SlotVerifyError::Verification(None)),
310*d289c2baSAndroid Build Coastguard Worker "Verification failure"
311*d289c2baSAndroid Build Coastguard Worker );
312*d289c2baSAndroid Build Coastguard Worker }
313*d289c2baSAndroid Build Coastguard Worker
314*d289c2baSAndroid Build Coastguard Worker #[test]
convert_slot_verify_enum_to_result()315*d289c2baSAndroid Build Coastguard Worker fn convert_slot_verify_enum_to_result() {
316*d289c2baSAndroid Build Coastguard Worker assert!(matches!(
317*d289c2baSAndroid Build Coastguard Worker slot_verify_enum_to_result(AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_OK),
318*d289c2baSAndroid Build Coastguard Worker Ok(())
319*d289c2baSAndroid Build Coastguard Worker ));
320*d289c2baSAndroid Build Coastguard Worker assert!(matches!(
321*d289c2baSAndroid Build Coastguard Worker slot_verify_enum_to_result(AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_ERROR_IO),
322*d289c2baSAndroid Build Coastguard Worker Err(SlotVerifyError::Io)
323*d289c2baSAndroid Build Coastguard Worker ));
324*d289c2baSAndroid Build Coastguard Worker }
325*d289c2baSAndroid Build Coastguard Worker
326*d289c2baSAndroid Build Coastguard Worker #[test]
display_io_error()327*d289c2baSAndroid Build Coastguard Worker fn display_io_error() {
328*d289c2baSAndroid Build Coastguard Worker // The actual error message can change as needed, the point of the test is just to make sure
329*d289c2baSAndroid Build Coastguard Worker // the fmt::Display trait is properly implemented.
330*d289c2baSAndroid Build Coastguard Worker assert_eq!(
331*d289c2baSAndroid Build Coastguard Worker format!("{}", IoError::NoSuchPartition),
332*d289c2baSAndroid Build Coastguard Worker "No such partition exists"
333*d289c2baSAndroid Build Coastguard Worker );
334*d289c2baSAndroid Build Coastguard Worker }
335*d289c2baSAndroid Build Coastguard Worker
336*d289c2baSAndroid Build Coastguard Worker #[test]
convert_io_enum_to_result()337*d289c2baSAndroid Build Coastguard Worker fn convert_io_enum_to_result() {
338*d289c2baSAndroid Build Coastguard Worker // This is a compile-time check that we handle all the `AvbIOResult` enum values. If any
339*d289c2baSAndroid Build Coastguard Worker // enums are added or removed this will break, indicating we need to update `IoError` to
340*d289c2baSAndroid Build Coastguard Worker // match.
341*d289c2baSAndroid Build Coastguard Worker assert_eq!(io_enum_to_result(AvbIOResult::AVB_IO_RESULT_OK), Ok(()));
342*d289c2baSAndroid Build Coastguard Worker assert_eq!(
343*d289c2baSAndroid Build Coastguard Worker io_enum_to_result(AvbIOResult::AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION),
344*d289c2baSAndroid Build Coastguard Worker Err(IoError::NoSuchPartition)
345*d289c2baSAndroid Build Coastguard Worker );
346*d289c2baSAndroid Build Coastguard Worker }
347*d289c2baSAndroid Build Coastguard Worker
348*d289c2baSAndroid Build Coastguard Worker #[test]
convert_io_result_to_enum()349*d289c2baSAndroid Build Coastguard Worker fn convert_io_result_to_enum() {
350*d289c2baSAndroid Build Coastguard Worker assert_eq!(result_to_io_enum(Ok(())), AvbIOResult::AVB_IO_RESULT_OK);
351*d289c2baSAndroid Build Coastguard Worker assert_eq!(
352*d289c2baSAndroid Build Coastguard Worker result_to_io_enum(Err(IoError::Io)),
353*d289c2baSAndroid Build Coastguard Worker AvbIOResult::AVB_IO_RESULT_ERROR_IO
354*d289c2baSAndroid Build Coastguard Worker );
355*d289c2baSAndroid Build Coastguard Worker }
356*d289c2baSAndroid Build Coastguard Worker
357*d289c2baSAndroid Build Coastguard Worker #[test]
display_vmbeta_verify_error()358*d289c2baSAndroid Build Coastguard Worker fn display_vmbeta_verify_error() {
359*d289c2baSAndroid Build Coastguard Worker // The actual error message can change as needed, the point of the test is just to make sure
360*d289c2baSAndroid Build Coastguard Worker // the fmt::Display trait is properly implemented.
361*d289c2baSAndroid Build Coastguard Worker assert_eq!(
362*d289c2baSAndroid Build Coastguard Worker format!("{}", VbmetaVerifyError::NotSigned),
363*d289c2baSAndroid Build Coastguard Worker "vbmeta is unsigned"
364*d289c2baSAndroid Build Coastguard Worker );
365*d289c2baSAndroid Build Coastguard Worker }
366*d289c2baSAndroid Build Coastguard Worker
367*d289c2baSAndroid Build Coastguard Worker #[test]
convert_vbmeta_verify_enum_to_result()368*d289c2baSAndroid Build Coastguard Worker fn convert_vbmeta_verify_enum_to_result() {
369*d289c2baSAndroid Build Coastguard Worker assert_eq!(
370*d289c2baSAndroid Build Coastguard Worker vbmeta_verify_enum_to_result(AvbVBMetaVerifyResult::AVB_VBMETA_VERIFY_RESULT_OK),
371*d289c2baSAndroid Build Coastguard Worker Ok(())
372*d289c2baSAndroid Build Coastguard Worker );
373*d289c2baSAndroid Build Coastguard Worker assert_eq!(
374*d289c2baSAndroid Build Coastguard Worker vbmeta_verify_enum_to_result(
375*d289c2baSAndroid Build Coastguard Worker AvbVBMetaVerifyResult::AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH
376*d289c2baSAndroid Build Coastguard Worker ),
377*d289c2baSAndroid Build Coastguard Worker Err(VbmetaVerifyError::HashMismatch)
378*d289c2baSAndroid Build Coastguard Worker );
379*d289c2baSAndroid Build Coastguard Worker }
380*d289c2baSAndroid Build Coastguard Worker }
381