1pub mod r#enum;
6pub mod integer;
7pub mod r#struct;
8
9#[macro_export]
10macro_rules! tpm_bitflags {
11 (@impl $(#[$outer:meta])* $vis:vis struct $name:ident($wrapper:ty, $repr:ty) {
12 $(
13 $(#[$inner:meta])*
14 const $field:ident = $value:expr, $string_name:literal;
15 )*
16 }) => {
17 $(#[$outer])*
18 $vis struct $name($repr);
19
20 impl $name {
21 $(
22 $(#[$inner])*
23 pub const $field: Self = Self($value);
24 )*
25
26 #[must_use]
27 pub const fn bits(&self) -> $repr {
28 self.0
29 }
30
31 #[must_use]
32 pub const fn from_bits_truncate(bits: $repr) -> Self {
33 Self(bits)
34 }
35
36 pub const fn set_bits(&mut self, bits: $repr) {
37 self.0 = bits;
38 }
39
40 #[must_use]
41 pub const fn empty() -> Self {
42 Self(0)
43 }
44
45 #[must_use]
46 pub const fn contains(&self, other: Self) -> bool {
47 (self.0 & other.0) == other.0
48 }
49 }
50
51 impl core::ops::BitOr for $name {
52 type Output = Self;
53 fn bitor(self, rhs: Self) -> Self::Output {
54 Self(self.0 | rhs.0)
55 }
56 }
57
58 impl core::ops::BitOrAssign for $name {
59 fn bitor_assign(&mut self, rhs: Self) {
60 self.0 |= rhs.0;
61 }
62 }
63
64 impl core::ops::BitAnd for $name {
65 type Output = Self;
66 fn bitand(self, rhs: Self) -> Self::Output {
67 Self(self.0 & rhs.0)
68 }
69 }
70
71 impl core::ops::BitAndAssign for $name {
72 fn bitand_assign(&mut self, rhs: Self) {
73 self.0 &= rhs.0;
74 }
75 }
76
77 impl core::ops::BitXor for $name {
78 type Output = Self;
79 fn bitxor(self, rhs: Self) -> Self::Output {
80 Self(self.0 ^ rhs.0)
81 }
82 }
83
84 impl core::ops::BitXorAssign for $name {
85 fn bitxor_assign(&mut self, rhs: Self) {
86 self.0 ^= rhs.0;
87 }
88 }
89
90 impl core::ops::Not for $name {
91 type Output = Self;
92 fn not(self) -> Self::Output {
93 Self(!self.0)
94 }
95 }
96
97 impl $crate::TpmMarshal for $name {
98 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
99 let value = <$wrapper>::from(self.0);
100 $crate::TpmMarshal::marshal(&value, writer)
101 }
102 }
103
104 impl $crate::TpmUnmarshal for $name {
105 fn unmarshal(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
106 let (val, buf) = <$wrapper as $crate::TpmUnmarshal>::unmarshal(buf)?;
107 Ok((Self(val.into()), buf))
108 }
109 }
110
111 impl $crate::TpmSized for $name {
112 const SIZE: usize = core::mem::size_of::<$repr>();
113 fn len(&self) -> usize {
114 Self::SIZE
115 }
116 }
117 };
118
119 ($(#[$meta:meta])* $vis:vis struct $name:ident(TpmUint8) { $($rest:tt)* }) => {
120 tpm_bitflags!(@impl $(#[$meta])* $vis struct $name($crate::basic::TpmUint8, u8) { $($rest)* });
121 };
122 ($(#[$meta:meta])* $vis:vis struct $name:ident(TpmUint16) { $($rest:tt)* }) => {
123 tpm_bitflags!(@impl $(#[$meta])* $vis struct $name($crate::basic::TpmUint16, u16) { $($rest)* });
124 };
125 ($(#[$meta:meta])* $vis:vis struct $name:ident(TpmUint32) { $($rest:tt)* }) => {
126 tpm_bitflags!(@impl $(#[$meta])* $vis struct $name($crate::basic::TpmUint32, u32) { $($rest)* });
127 };
128 ($(#[$meta:meta])* $vis:vis struct $name:ident(TpmUint64) { $($rest:tt)* }) => {
129 tpm_bitflags!(@impl $(#[$meta])* $vis struct $name($crate::basic::TpmUint64, u64) { $($rest)* });
130 };
131}
132
133#[macro_export]
134macro_rules! tpm_bool {
135 (
136 $(#[$outer:meta])*
137 $vis:vis struct $name:ident(bool);
138 ) => {
139 $(#[$outer])*
140 $vis struct $name(pub bool);
141
142 impl From<bool> for $name {
143 fn from(val: bool) -> Self {
144 Self(val)
145 }
146 }
147
148 impl From<$name> for bool {
149 fn from(val: $name) -> Self {
150 val.0
151 }
152 }
153
154 impl $crate::TpmMarshal for $name {
155 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
156 let value = if self.0 { 1 } else { 0 };
157 $crate::basic::TpmUint8::from(value).marshal(writer)
158 }
159 }
160
161 impl $crate::TpmUnmarshal for $name {
162 fn unmarshal(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
163 let (val, buf) = $crate::basic::TpmUint8::unmarshal(buf)?;
164 match u8::from(val) {
165 0 => Ok((Self(false), buf)),
166 1 => Ok((Self(true), buf)),
167 _ => Err($crate::TpmProtocolError::InvalidBoolean),
168 }
169 }
170 }
171
172 impl $crate::TpmSized for $name {
173 const SIZE: usize = core::mem::size_of::<$crate::basic::TpmUint8>();
174 fn len(&self) -> usize {
175 Self::SIZE
176 }
177 }
178 };
179}
180
181#[macro_export]
182macro_rules! tpm_dispatch {
183 (@const_check_sorted) => {};
184 (@const_check_sorted $prev_cmd:ident, $( $rest_cmd:ident, )*) => {
185 $crate::tpm_dispatch!(@const_check_sorted_impl $prev_cmd, $( $rest_cmd, )*);
186 };
187 (@const_check_sorted_impl $prev_cmd:ident,) => {};
188 (@const_check_sorted_impl $prev_cmd:ident, $current_cmd:ident, $( $rest_cmd:ident, )* ) => {
189 const _: () = assert!(
190 <$crate::frame::data::$prev_cmd as $crate::frame::TpmHeader>::CC as u32 <= <$crate::frame::data::$current_cmd as $crate::frame::TpmHeader>::CC as u32,
191 "TPM_DISPATCH_TABLE must be sorted by TpmCc."
192 );
193 $crate::tpm_dispatch!(@const_check_sorted_impl $current_cmd, $( $rest_cmd, )*);
194 };
195
196 ( $( ($cmd:ident, $resp:ident, $variant:ident) ),* $(,)? ) => {
197 #[allow(clippy::large_enum_variant)]
199 #[derive(Debug, PartialEq, Eq, Clone)]
200 pub enum TpmCommandValue {
201 $( $variant($crate::frame::data::$cmd), )*
202 }
203
204 impl $crate::TpmSized for TpmCommandValue {
205 const SIZE: usize = $crate::constant::TPM_MAX_COMMAND_SIZE;
206 fn len(&self) -> usize {
207 match self {
208 $( Self::$variant(c) => $crate::TpmSized::len(c), )*
209 }
210 }
211 }
212
213 impl $crate::frame::TpmMarshalBody for TpmCommandValue {
214 fn marshal_handles(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
215 match self {
216 $( Self::$variant(c) => $crate::frame::TpmMarshalBody::marshal_handles(c, writer), )*
217 }
218 }
219 fn marshal_parameters(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
220 match self {
221 $( Self::$variant(c) => $crate::frame::TpmMarshalBody::marshal_parameters(c, writer), )*
222 }
223 }
224 }
225
226 impl $crate::TpmMarshal for TpmCommandValue {
227 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
228 match self {
229 $( Self::$variant(c) => $crate::TpmMarshal::marshal(c, writer), )*
230 }
231 }
232 }
233
234 impl $crate::frame::TpmFrame for TpmCommandValue {
235 fn cc(&self) -> $crate::data::TpmCc {
236 match self {
237 $( Self::$variant(c) => $crate::frame::TpmFrame::cc(c), )*
238 }
239 }
240 fn handles(&self) -> usize {
241 match self {
242 $( Self::$variant(c) => $crate::frame::TpmFrame::handles(c), )*
243 }
244 }
245 }
246
247 impl TpmCommandValue {
248 pub fn marshal_frame(
254 &self,
255 tag: $crate::data::TpmSt,
256 sessions: &$crate::frame::TpmAuthCommands,
257 writer: &mut $crate::TpmWriter,
258 ) -> $crate::TpmResult<()> {
259 match self {
260 $( Self::$variant(c) => $crate::frame::tpm_marshal_command(c, tag, sessions, writer), )*
261 }
262 }
263 }
264
265 #[allow(clippy::large_enum_variant)]
267 #[derive(Debug, PartialEq, Eq, Clone)]
268 pub enum TpmResponseValue {
269 $( $variant($crate::frame::data::$resp), )*
270 }
271
272 impl $crate::TpmSized for TpmResponseValue {
273 const SIZE: usize = $crate::constant::TPM_MAX_COMMAND_SIZE;
274 fn len(&self) -> usize {
275 match self {
276 $( Self::$variant(r) => $crate::TpmSized::len(r), )*
277 }
278 }
279 }
280
281 impl $crate::frame::TpmMarshalBody for TpmResponseValue {
282 fn marshal_handles(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
283 match self {
284 $( Self::$variant(r) => $crate::frame::TpmMarshalBody::marshal_handles(r, writer), )*
285 }
286 }
287 fn marshal_parameters(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
288 match self {
289 $( Self::$variant(r) => $crate::frame::TpmMarshalBody::marshal_parameters(r, writer), )*
290 }
291 }
292 }
293
294 impl $crate::TpmMarshal for TpmResponseValue {
295 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
296 match self {
297 $( Self::$variant(r) => $crate::TpmMarshal::marshal(r, writer), )*
298 }
299 }
300 }
301
302 impl $crate::frame::TpmFrame for TpmResponseValue {
303 fn cc(&self) -> $crate::data::TpmCc {
304 match self {
305 $( Self::$variant(r) => $crate::frame::TpmFrame::cc(r), )*
306 }
307 }
308 fn handles(&self) -> usize {
309 match self {
310 $( Self::$variant(r) => $crate::frame::TpmFrame::handles(r), )*
311 }
312 }
313 }
314
315 impl TpmResponseValue {
316 $(
317 #[allow(non_snake_case, clippy::result_large_err)]
323 pub fn $variant(self) -> Result<$crate::frame::data::$resp, Self> {
324 if let Self::$variant(r) = self {
325 Ok(r)
326 } else {
327 Err(self)
328 }
329 }
330 )*
331
332 pub fn marshal_frame(
338 &self,
339 rc: $crate::data::TpmRc,
340 sessions: &$crate::frame::TpmAuthResponses,
341 writer: &mut $crate::TpmWriter,
342 ) -> $crate::TpmResult<()> {
343 match self {
344 $( Self::$variant(r) => $crate::frame::tpm_marshal_response(r, sessions, rc, writer), )*
345 }
346 }
347 }
348
349 pub(crate) static TPM_DISPATCH_TABLE: &[$crate::frame::TpmDispatch] = &[
350 $(
351 $crate::frame::TpmDispatch {
352 cc: <$crate::frame::data::$cmd as $crate::frame::TpmHeader>::CC,
353 handles: <$crate::frame::data::$cmd as $crate::frame::TpmHeader>::HANDLES,
354 response_handles: <$crate::frame::data::$resp as $crate::frame::TpmHeader>::HANDLES,
355 command_unmarshaler: |handles, params| {
356 <$crate::frame::data::$cmd as $crate::frame::TpmUnmarshalCommand>::unmarshal_body(handles, params)
357 .map(|(c, r)| (TpmCommandValue::$variant(c), r))
358 },
359 response_unmarshaler: |tag, buf| {
360 <$crate::frame::data::$resp as $crate::frame::TpmUnmarshalResponse>::unmarshal_body(tag, buf)
361 .map(|(r, rest)| (TpmResponseValue::$variant(r), rest))
362 },
363 },
364 )*
365 ];
366
367 $crate::tpm_dispatch!(@const_check_sorted $( $cmd, )*);
368 };
369}