1use core::mem;
2
3use super::{FormId, QuestionId, StringId, VarStoreId};
4use crate::guid::Guid;
5
6#[derive(Clone, Copy, Debug, PartialEq)]
7#[repr(u8)]
8pub enum IfrTypeKind {
9 U8 = 0x00,
10 U16 = 0x01,
11 U32 = 0x02,
12 U64 = 0x03,
13 Bool = 0x04,
14 Time = 0x05,
15 Date = 0x06,
16 String = 0x07,
17 Other = 0x08,
18 Undefined = 0x09,
19 Action = 0x0A,
20 Buffer = 0x0B,
21 Ref = 0x0C,
22}
23
24#[derive(Clone, Copy, Debug, PartialEq)]
25#[repr(C)]
26pub struct HiiTime {
27 pub Hour: u8,
28 pub Minute: u8,
29 pub Second: u8,
30}
31
32#[derive(Clone, Copy, Debug, PartialEq)]
33#[repr(C)]
34pub struct HiiDate {
35 pub Year: u16,
36 pub Month: u8,
37 pub Day: u8,
38}
39
40#[derive(Clone, Copy, Debug, PartialEq)]
41#[repr(C, packed)] pub struct HiiRef {
43 pub QuestionId: QuestionId,
44 pub FormId: FormId,
45 pub FormSetGuid: Guid,
46 pub DevicePath: StringId,
47}
48
49#[derive(Clone, Copy)]
50#[repr(C, packed)] pub union IfrTypeValue {
52 u8: u8,
53 u16: u16,
54 u32: u32,
55 u64: u64,
56 b: bool,
57 time: HiiTime,
58 date: HiiDate,
59 string: StringId,
60 reference: HiiRef,
61 }
63
64impl IfrTypeValue {
65 pub unsafe fn to_enum(self, kind: IfrTypeKind) -> IfrTypeValueEnum {
66 match kind {
67 IfrTypeKind::U8 => IfrTypeValueEnum::U8(self.u8),
68 IfrTypeKind::U16 => IfrTypeValueEnum::U16(self.u16),
69 IfrTypeKind::U32 => IfrTypeValueEnum::U32(self.u32),
70 IfrTypeKind::U64 => IfrTypeValueEnum::U64(self.u64),
71 IfrTypeKind::Bool => IfrTypeValueEnum::Bool(self.b),
72 IfrTypeKind::Time => IfrTypeValueEnum::Time(self.time),
73 IfrTypeKind::Date => IfrTypeValueEnum::Date(self.date),
74 IfrTypeKind::String => IfrTypeValueEnum::String(self.string),
75 IfrTypeKind::Ref => IfrTypeValueEnum::Ref(self.reference),
76 _ => IfrTypeValueEnum::Other(kind, mem::transmute(self)),
77 }
78 }
79}
80
81#[derive(Clone, Copy, Debug, PartialEq)]
82pub enum IfrTypeValueEnum {
83 U8(u8),
84 U16(u16),
85 U32(u32),
86 U64(u64),
87 Bool(bool),
88 Time(HiiTime),
89 Date(HiiDate),
90 String(StringId),
91 Ref(HiiRef),
92 Other(IfrTypeKind, [u8; 22]),
93}
94
95impl IfrTypeValueEnum {
96 pub unsafe fn to_union(self) -> (IfrTypeKind, IfrTypeValue) {
97 match self {
98 IfrTypeValueEnum::U8(u8) => (IfrTypeKind::U8, IfrTypeValue { u8 }),
99 IfrTypeValueEnum::U16(u16) => (IfrTypeKind::U16, IfrTypeValue { u16 }),
100 IfrTypeValueEnum::U32(u32) => (IfrTypeKind::U32, IfrTypeValue { u32 }),
101 IfrTypeValueEnum::U64(u64) => (IfrTypeKind::U64, IfrTypeValue { u64 }),
102 IfrTypeValueEnum::Bool(b) => (IfrTypeKind::Bool, IfrTypeValue { b }),
103 IfrTypeValueEnum::Time(time) => (IfrTypeKind::Time, IfrTypeValue { time }),
104 IfrTypeValueEnum::Date(date) => (IfrTypeKind::Date, IfrTypeValue { date }),
105 IfrTypeValueEnum::String(string) => (IfrTypeKind::String, IfrTypeValue { string }),
106 IfrTypeValueEnum::Ref(reference) => (IfrTypeKind::Ref, IfrTypeValue { reference }),
107 IfrTypeValueEnum::Other(kind, data) => (kind, mem::transmute(data)),
108 }
109 }
110}
111
112#[repr(C)]
113pub struct HiiValue {
114 pub Kind: IfrTypeKind,
115 pub Buffer: *mut u8,
116 pub BufferLen: u16,
117 pub Value: IfrTypeValue,
118}
119
120#[derive(Clone, Copy, Debug)]
121#[repr(C)]
122pub struct IfrStatementHeader {
123 pub Prompt: StringId,
124 pub Help: StringId,
125}
126
127pub const IFR_FLAG_READ_ONLY: u8 = 0x01;
128pub const IFR_FLAG_CALLBACK: u8 = 0x04;
129pub const IFR_FLAG_RESET_REQUIRED: u8 = 0x10;
130pub const IFR_FLAG_RECONNECT_REQUIRED: u8 = 0x40;
131pub const IFR_FLAG_OPTIONS_ONLY: u8 = 0x80;
132
133#[derive(Clone, Copy, Debug)]
134#[repr(C, packed)] pub struct IfrQuestionHeader {
136 pub Header: IfrStatementHeader,
137 pub QuestionId: QuestionId,
138 pub VarStoreId: VarStoreId,
139 pub VarStoreInfo: u16,
141 pub Flags: u8,
142}
143
144#[derive(Clone, Copy, Debug)]
145#[repr(u8)]
146pub enum IfrOpCode {
147 Form = 0x01,
148 Subtitle = 0x02,
149 Text = 0x03,
150 Image = 0x04,
151 OneOf = 0x05,
152 Checkbox = 0x06,
153 Numeric = 0x07,
154 Password = 0x08,
155 OneOfOption = 0x09,
156 SuppressIf = 0x0A,
157 Locked = 0x0B,
158 Action = 0x0C,
159 ResetButton = 0x0D,
160 FormSet = 0x0E,
161 Ref = 0x0F,
162 NoSubmitIf = 0x10,
163 InconsistentIf = 0x11,
164 EqIdVal = 0x12,
165 EqIdId = 0x13,
166 EqIdValList = 0x14,
167 And = 0x15,
168 Or = 0x16,
169 Not = 0x17,
170 Rule = 0x18,
171 GrayOutIf = 0x19,
172 Date = 0x1A,
173 Time = 0x1B,
174 String = 0x1C,
175 Refresh = 0x1D,
176 DisableIf = 0x1E,
177 Animation = 0x1F,
178 ToLower = 0x20,
179 ToUpper = 0x21,
180 Map = 0x22,
181 OrderedList = 0x23,
182 VarStore = 0x24,
183 VarStoreNameValue = 0x25,
184 VarStoreEfi = 0x26,
185 VarStoreDevice = 0x27,
186 Version = 0x28,
187 End = 0x29,
188 Match = 0x2A,
189 Get = 0x2B,
190 Set = 0x2C,
191 Read = 0x2D,
192 Write = 0x2E,
193 Equal = 0x2F,
194 NotEqual = 0x30,
195 GreaterThan = 0x31,
196 GreaterEqual = 0x32,
197 LessThan = 0x33,
198 LessEqual = 0x34,
199 BitwiseAnd = 0x35,
200 BitwiseOr = 0x36,
201 BitwiseNot = 0x37,
202 ShiftLeft = 0x38,
203 ShiftRight = 0x39,
204 Add = 0x3A,
205 Subtract = 0x3B,
206 Multiply = 0x3C,
207 Divide = 0x3D,
208 Modulo = 0x3E,
209 RuleRef = 0x3F,
210 QuestionRef1 = 0x40,
211 QuestionRef2 = 0x41,
212 Uint8 = 0x42,
213 Uint16 = 0x43,
214 Uint32 = 0x44,
215 Uint64 = 0x45,
216 True = 0x46,
217 False = 0x47,
218 ToUint = 0x48,
219 ToString = 0x49,
220 ToBoolean = 0x4A,
221 Mid = 0x4B,
222 Find = 0x4C,
223 Token = 0x4D,
224 StringRef1 = 0x4E,
225 StringRef2 = 0x4F,
226 Conditional = 0x50,
227 QuestionRef3 = 0x51,
228 Zero = 0x52,
229 One = 0x53,
230 Ones = 0x54,
231 Undefined = 0x55,
232 Length = 0x56,
233 Dup = 0x57,
234 This = 0x58,
235 Span = 0x59,
236 Value = 0x5A,
237 Default = 0x5B,
238 DefaultStore = 0x5C,
239 FormMap = 0x5D,
240 Catenate = 0x5E,
241 Guid = 0x5F,
242 Security = 0x60,
243 ModelTag = 0x61,
244 RefreshId = 0x62,
245 WarningIf = 0x63,
246 Match2 = 0x64,
247}
248
249#[derive(Copy, Clone, Debug)]
250#[repr(C)]
251pub struct IfrOpHeader {
252 pub OpCode: IfrOpCode,
253 pub Length_Scope: u8,
254}
255
256impl IfrOpHeader {
257 pub fn Length(&self) -> u8 {
258 self.Length_Scope & 0x7F
259 }
260
261 pub fn Scope(&self) -> bool {
262 self.Length_Scope & 0x80 == 0x80
263 }
264
265 pub unsafe fn cast<T>(&self) -> Option<&T> {
266 if self.Length() as usize >= mem::size_of::<T>() {
267 Some(&*(self as *const Self as *const T))
268 } else {
269 None
270 }
271 }
272}
273
274macro_rules! unsafe_field {
275 ($struct: ident, $field:ident, $type:ty) => {
276 pub fn $field(&self) -> Option<&$type> {
277 unsafe {
278 let self_ptr = self as *const Self;
279 let unsafe_self = &*(self_ptr as *const $struct);
280 let field_ptr = &unsafe_self.$field as *const $type;
281 let length = field_ptr.add(1) as usize - self_ptr as usize;
282 if self.Header.Length() as usize >= length {
283 Some(&*field_ptr)
284 } else {
285 None
286 }
287 }
288 }
289 };
290}
291
292#[derive(Debug)]
293#[repr(C)]
294pub struct IfrAction {
295 pub Header: IfrOpHeader,
296 pub QuestionHeader: IfrQuestionHeader,
297}
298
299#[repr(C)]
300struct UnsafeIfrAction {
301 safe: IfrAction,
302 QuestionConfig: StringId,
303}
304
305impl IfrAction {
306 unsafe_field!(UnsafeIfrAction, QuestionConfig, StringId);
307}
308
309#[derive(Debug)]
310#[repr(C, packed)] pub struct IfrCheckbox {
312 pub Header: IfrOpHeader,
313 pub Question: IfrQuestionHeader,
314 pub Flags: u8,
315}
316
317#[derive(Debug)]
318#[repr(C)]
319pub struct IfrForm {
320 pub Header: IfrOpHeader,
321 pub FormId: FormId,
322 pub FormTitle: StringId,
323}
324
325#[derive(Debug)]
326#[repr(C, packed)] pub struct IfrNumeric {
328 pub Header: IfrOpHeader,
329 pub Question: IfrQuestionHeader,
330 pub Flags: u8,
331 }
333
334#[derive(Debug)]
335#[repr(C)]
336pub struct IfrOneOf {
337 pub Header: IfrOpHeader,
338 pub Question: IfrQuestionHeader,
339 pub Flags: u8,
340 }
342
343#[repr(C)]
344pub struct IfrOneOfOption {
345 pub Header: IfrOpHeader,
346 pub Option: StringId,
347 pub Flags: u8,
348 pub Kind: IfrTypeKind,
349 pub Value: IfrTypeValue,
350}
351
352#[derive(Debug)]
353#[repr(C)]
354pub struct IfrOrderedList {
355 pub Header: IfrOpHeader,
356 pub Question: IfrQuestionHeader,
357 pub MaxContainers: u8,
358 pub Flags: u8,
359}
360
361#[derive(Debug)]
362#[repr(C)]
363pub struct IfrRef {
364 pub Header: IfrOpHeader,
365 pub Question: IfrQuestionHeader,
366}
367
368#[repr(C)]
369struct UnsafeIfrRef {
370 safe: IfrRef,
371 FormId: FormId,
372 QuestionId: QuestionId,
373 FormSetId: Guid,
374 DevicePath: *const u16,
375}
376
377impl IfrRef {
378 unsafe_field!(UnsafeIfrRef, FormId, FormId);
379 unsafe_field!(UnsafeIfrRef, QuestionId, QuestionId);
380 unsafe_field!(UnsafeIfrRef, FormSetId, Guid);
381 unsafe_field!(UnsafeIfrRef, DevicePath, *const u16);
382}
383
384#[repr(C, packed)] pub struct IfrSubtitle {
386 pub Header: IfrOpHeader,
387 pub Statement: IfrStatementHeader,
388 pub Flags: u8,
389}
390
391#[derive(Debug)]
392#[repr(C)]
393pub struct IfrText {
394 pub Header: IfrOpHeader,
395 pub Statement: IfrStatementHeader,
396 pub TextTwo: StringId,
397}