1 // Copyright 2024 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://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, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 15 //! Types related to command arguments. 16 17 use crate::error::{DpeResult, ErrCode}; 18 use crate::memory::SizedMessage; 19 use heapless::FnvIndexMap; 20 use log::error; 21 22 /// Represents the numeric identifier of a command or response argument. 23 pub type ArgId = u32; 24 25 /// Represents the type of a command or response argument. 26 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash)] 27 pub enum ArgTypeSelector { 28 /// Indicates an argument was not recognized, so its type is unknown. 29 #[default] 30 Unknown, 31 /// Indicates an argument is encoded as a CBOR byte string. 32 Bytes, 33 /// Indicates an argument is encoded as a CBOR unsigned integer. 34 Int, 35 /// Indicates an argument is encoded as a CBOR true or false simple value. 36 Bool, 37 /// Indicates an argument needs additional custom decoding. 38 Other, 39 } 40 41 /// Represents a command or response argument value. 42 #[derive(Clone, Debug, Eq, PartialEq, Hash)] 43 pub enum ArgValue<'a> { 44 /// This instantiation borrows a slice of a message buffer that was decoded 45 /// as a CBOR byte string. The slice needs to live at least as long as 46 /// this. 47 BytesArg(&'a [u8]), 48 /// This instantiation contains a decoded CBOR unsigned integer. 49 IntArg(u64), 50 /// This instantiation contains a decoded CBOR boolean value. 51 BoolArg(bool), 52 } 53 54 impl<'a> ArgValue<'a> { 55 /// Creates a new `BytesArg` from a slice, borrowing the slice. from_slice(value: &'a [u8]) -> Self56 pub fn from_slice(value: &'a [u8]) -> Self { 57 ArgValue::BytesArg(value) 58 } 59 60 /// Returns the borrowed slice if this is a BytesArg. 61 /// 62 /// # Errors 63 /// 64 /// Returns an InternalError error if this is not a BytesArg. try_into_slice(&self) -> DpeResult<&'a [u8]>65 pub fn try_into_slice(&self) -> DpeResult<&'a [u8]> { 66 match self { 67 ArgValue::IntArg(_) | ArgValue::BoolArg(_) => { 68 error!("ArgValue::try_info_slice called on {:?}", self); 69 Err(ErrCode::InternalError) 70 } 71 ArgValue::BytesArg(value) => Ok(value), 72 } 73 } 74 75 /// Returns the value held by an IntArg as a u32. 76 /// 77 /// # Errors 78 /// 79 /// Returns an InternalError error if this is not an IntArg. try_into_u32(&self) -> DpeResult<u32>80 pub fn try_into_u32(&self) -> DpeResult<u32> { 81 match self { 82 ArgValue::IntArg(i) => Ok((*i).try_into()?), 83 _ => { 84 error!("ArgValue::try_into_u32 called on {:?}", self); 85 Err(ErrCode::InternalError) 86 } 87 } 88 } 89 90 /// Creates a new `IntArg` holding the given u32 `value`. from_u32(value: u32) -> Self91 pub fn from_u32(value: u32) -> Self { 92 ArgValue::IntArg(value as u64) 93 } 94 95 /// Returns the value held by an IntArg as a u64. 96 /// 97 /// # Errors 98 /// 99 /// Returns an InternalError error if this is not an IntArg. try_into_u64(&self) -> DpeResult<u64>100 pub fn try_into_u64(&self) -> DpeResult<u64> { 101 match self { 102 ArgValue::IntArg(i) => Ok(*i), 103 _ => { 104 error!("ArgValue::try_into_u64 called on {:?}", self); 105 Err(ErrCode::InternalError) 106 } 107 } 108 } 109 110 /// Creates a new `IntArg` holding the given u64 `value`. from_u64(value: u64) -> Self111 pub fn from_u64(value: u64) -> Self { 112 ArgValue::IntArg(value) 113 } 114 115 /// Returns the value held by a BoolArg. 116 /// 117 /// # Errors 118 /// 119 /// Returns an InternalError error if this is not a BoolArg. try_into_bool(&self) -> DpeResult<bool>120 pub fn try_into_bool(&self) -> DpeResult<bool> { 121 match self { 122 ArgValue::BoolArg(b) => Ok(*b), 123 _ => { 124 error!("ArgValue::try_into_bool called on {:?}", self); 125 Err(ErrCode::InternalError) 126 } 127 } 128 } 129 130 /// Creates a new `BoolArg` holding the given `value`. from_bool(value: bool) -> Self131 pub fn from_bool(value: bool) -> Self { 132 ArgValue::BoolArg(value) 133 } 134 } 135 136 impl<'a, const S: usize> From<&'a SizedMessage<S>> for ArgValue<'a> { from(message: &'a SizedMessage<S>) -> Self137 fn from(message: &'a SizedMessage<S>) -> Self { 138 Self::BytesArg(message.as_slice()) 139 } 140 } 141 142 /// Contains a set of command or response arguments in the form of a map from 143 /// [`ArgId`] to [`ArgValue`]. 144 pub type ArgMap<'a> = FnvIndexMap<ArgId, ArgValue<'a>, 16>; 145 146 /// Contains a set of argument types in the form of a map from ArgId to 147 /// [`ArgTypeSelector`]. 148 pub type ArgTypeMap = FnvIndexMap<ArgId, ArgTypeSelector, 16>; 149