]>
Commit | Line | Data |
---|---|---|
e52c5a9f | 1 | /** @file |
ad1b3619 | 2 | Library Routines to create IFR independent of string data - assume tokens already exist |
3 | Primarily to be used for exporting op-codes at a label in pre-defined forms. | |
4 | ||
e52c5a9f | 5 | |
6 | Copyright (c) 2007, Intel Corporation | |
7 | All rights reserved. This program and the accompanying materials | |
8 | are licensed and made available under the terms and conditions of the BSD License | |
9 | which accompanies this distribution. The full text of the license may be found at | |
10 | http://opensource.org/licenses/bsd-license.php | |
11 | ||
12 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
13 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
14 | ||
e52c5a9f | 15 | |
ad1b3619 | 16 | **/ |
e52c5a9f | 17 | |
ad1b3619 | 18 | #include "UefiIfrLibraryInternal.h" |
e52c5a9f | 19 | |
ad1b3619 | 20 | /** |
21 | Check if the input question flags is a valid value. | |
22 | The valid combination of question flags includes | |
23 | EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY. | |
e52c5a9f | 24 | |
ad1b3619 | 25 | @param Flags The question flags to check. |
e52c5a9f | 26 | |
ad1b3619 | 27 | @retval TRUE If the question flag is a valid combination. |
28 | @retval FALSE If the question flag is an invalid combination. | |
29 | ||
e52c5a9f | 30 | **/ |
e52c5a9f | 31 | BOOLEAN |
32 | IsValidQuestionFlags ( | |
33 | IN UINT8 Flags | |
34 | ) | |
35 | { | |
ad1b3619 | 36 | return (BOOLEAN) (((Flags & (~QUESTION_FLAGS)) != 0) ? FALSE : TRUE); |
e52c5a9f | 37 | } |
38 | ||
ad1b3619 | 39 | /** |
40 | Check if the input value type is a valid type. | |
41 | The valid value type is smaller or equal than EFI_IFR_TYPE_OTHER. | |
42 | ||
43 | @param Type The value type to check. | |
44 | ||
45 | @retval TRUE If the value type is valid. | |
46 | @retval FALSE If the value type is invalid. | |
47 | ||
48 | **/ | |
e52c5a9f | 49 | BOOLEAN |
50 | IsValidValueType ( | |
51 | IN UINT8 Type | |
52 | ) | |
53 | { | |
54 | return (BOOLEAN) ((Type <= EFI_IFR_TYPE_OTHER) ? TRUE : FALSE); | |
55 | } | |
56 | ||
ad1b3619 | 57 | /** |
58 | Check if the input numeric flags is a valid value. | |
59 | ||
60 | @param Flags The numeric flags to check. | |
61 | ||
62 | @retval TRUE If the numeric flags is valid. | |
63 | @retval FALSE If the numeric flags is invalid. | |
64 | ||
65 | **/ | |
e52c5a9f | 66 | BOOLEAN |
67 | IsValidNumricFlags ( | |
68 | IN UINT8 Flags | |
69 | ) | |
70 | { | |
ad1b3619 | 71 | if ((Flags & ~(EFI_IFR_NUMERIC_SIZE | EFI_IFR_DISPLAY)) != 0) { |
e52c5a9f | 72 | return FALSE; |
73 | } | |
74 | ||
75 | if ((Flags & EFI_IFR_DISPLAY) > EFI_IFR_DISPLAY_UINT_HEX) { | |
76 | return FALSE; | |
77 | } | |
78 | ||
79 | return TRUE; | |
80 | } | |
81 | ||
ad1b3619 | 82 | /** |
83 | Check if the checkbox flags is a valid value. | |
84 | ||
85 | @param Flags The checkbox flags to check. | |
86 | ||
87 | @retval TRUE If the checkbox flags is valid. | |
88 | @retval FALSE If the checkbox flags is invalid. | |
89 | ||
90 | **/ | |
e52c5a9f | 91 | BOOLEAN |
92 | IsValidCheckboxFlags ( | |
93 | IN UINT8 Flags | |
94 | ) | |
95 | { | |
96 | return (BOOLEAN) ((Flags <= EFI_IFR_CHECKBOX_DEFAULT_MFG) ? TRUE : FALSE); | |
97 | } | |
98 | ||
ad1b3619 | 99 | /** |
100 | Create EFI_IFR_END_OP opcode. | |
101 | ||
102 | If Data is NULL or Data->Data is NULL, then ASSERT. | |
103 | ||
104 | @param Data Destination for the created opcode binary | |
105 | ||
106 | @retval EFI_SUCCESS Opcode create success | |
107 | @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. | |
108 | ||
109 | **/ | |
e52c5a9f | 110 | EFI_STATUS |
111 | EFIAPI | |
112 | CreateEndOpCode ( | |
113 | IN OUT EFI_HII_UPDATE_DATA *Data | |
114 | ) | |
115 | { | |
116 | EFI_IFR_END End; | |
117 | UINT8 *LocalBuffer; | |
118 | ||
119 | ASSERT (Data != NULL && Data->Data != NULL); | |
120 | ||
121 | if (Data->Offset + sizeof (EFI_IFR_END) > Data->BufferSize) { | |
122 | return EFI_BUFFER_TOO_SMALL; | |
123 | } | |
124 | ||
125 | End.Header.Length = sizeof (EFI_IFR_END); | |
126 | End.Header.OpCode = EFI_IFR_END_OP; | |
127 | End.Header.Scope = 0; | |
128 | ||
129 | LocalBuffer = (UINT8 *) Data->Data + Data->Offset; | |
a8ff9715 LG |
130 | // |
131 | // CopyMem is used for EFI_IFR_END to cover the unaligned address access. | |
132 | // | |
e52c5a9f | 133 | CopyMem (LocalBuffer, &End, sizeof (EFI_IFR_END)); |
134 | Data->Offset += sizeof (EFI_IFR_END); | |
135 | ||
136 | return EFI_SUCCESS; | |
137 | } | |
138 | ||
ad1b3619 | 139 | /** |
140 | Create EFI_IFR_DEFAULT_OP opcode. | |
141 | ||
142 | @param Value Value for the default | |
143 | @param Type Type for the default | |
144 | @param Data Destination for the created opcode binary | |
145 | ||
146 | @retval EFI_SUCCESS Opcode create success | |
147 | @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. | |
148 | @retval EFI_INVALID_PARAMETER The type is not valid. | |
149 | ||
150 | **/ | |
e52c5a9f | 151 | EFI_STATUS |
152 | EFIAPI | |
153 | CreateDefaultOpCode ( | |
154 | IN EFI_IFR_TYPE_VALUE *Value, | |
155 | IN UINT8 Type, | |
156 | IN OUT EFI_HII_UPDATE_DATA *Data | |
157 | ) | |
158 | { | |
159 | EFI_IFR_DEFAULT Default; | |
160 | UINT8 *LocalBuffer; | |
161 | ||
162 | ASSERT (Data != NULL && Data->Data != NULL); | |
163 | ||
164 | if ((Value == NULL) || !IsValidValueType (Type)) { | |
165 | return EFI_INVALID_PARAMETER; | |
166 | } | |
167 | ||
168 | if (Data->Offset + sizeof (EFI_IFR_DEFAULT) > Data->BufferSize) { | |
169 | return EFI_BUFFER_TOO_SMALL; | |
170 | } | |
171 | ||
172 | Default.Header.OpCode = EFI_IFR_DEFAULT_OP; | |
173 | Default.Header.Length = sizeof (EFI_IFR_DEFAULT); | |
174 | Default.Header.Scope = 0; | |
175 | Default.Type = Type; | |
176 | Default.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD; | |
177 | CopyMem (&Default.Value, Value, sizeof(EFI_IFR_TYPE_VALUE)); | |
178 | ||
179 | LocalBuffer = (UINT8 *) Data->Data + Data->Offset; | |
a8ff9715 LG |
180 | // |
181 | // CopyMem is used for EFI_IFR_DEFAULT to cover the unaligned address access. | |
182 | // | |
e52c5a9f | 183 | CopyMem (LocalBuffer, &Default, sizeof (EFI_IFR_DEFAULT)); |
184 | Data->Offset += sizeof (EFI_IFR_DEFAULT); | |
185 | ||
186 | return EFI_SUCCESS; | |
187 | } | |
188 | ||
ad1b3619 | 189 | /** |
190 | Create EFI_IFR_ACTION_OP opcode. | |
191 | ||
192 | @param QuestionId Question ID | |
193 | @param Prompt String ID for Prompt | |
194 | @param Help String ID for Help | |
195 | @param QuestionFlags Flags in Question Header | |
196 | @param QuestionConfig String ID for configuration | |
197 | @param Data Destination for the created opcode binary | |
198 | ||
199 | @retval EFI_SUCCESS Opcode create success | |
200 | @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. | |
201 | @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid. | |
202 | ||
203 | **/ | |
e52c5a9f | 204 | EFI_STATUS |
205 | EFIAPI | |
206 | CreateActionOpCode ( | |
207 | IN EFI_QUESTION_ID QuestionId, | |
208 | IN EFI_STRING_ID Prompt, | |
209 | IN EFI_STRING_ID Help, | |
210 | IN UINT8 QuestionFlags, | |
211 | IN EFI_STRING_ID QuestionConfig, | |
212 | IN OUT EFI_HII_UPDATE_DATA *Data | |
213 | ) | |
214 | { | |
215 | EFI_IFR_ACTION Action; | |
216 | UINT8 *LocalBuffer; | |
217 | ||
218 | ASSERT (Data != NULL && Data->Data != NULL); | |
219 | ||
220 | if (!IsValidQuestionFlags (QuestionFlags)) { | |
221 | return EFI_INVALID_PARAMETER; | |
222 | } | |
223 | ||
224 | if (Data->Offset + sizeof (EFI_IFR_ACTION) > Data->BufferSize) { | |
225 | return EFI_BUFFER_TOO_SMALL; | |
226 | } | |
227 | ||
228 | Action.Header.OpCode = EFI_IFR_ACTION_OP; | |
229 | Action.Header.Length = sizeof (EFI_IFR_ACTION); | |
230 | Action.Header.Scope = 0; | |
231 | Action.Question.QuestionId = QuestionId; | |
232 | Action.Question.Header.Prompt = Prompt; | |
233 | Action.Question.Header.Help = Help; | |
234 | Action.Question.VarStoreId = INVALID_VARSTORE_ID; | |
235 | Action.Question.Flags = QuestionFlags; | |
236 | Action.QuestionConfig = QuestionConfig; | |
237 | ||
238 | LocalBuffer = (UINT8 *) Data->Data + Data->Offset; | |
a8ff9715 LG |
239 | // |
240 | // CopyMem is used for EFI_IFR_ACTION to cover the unaligned address access. | |
241 | // | |
e52c5a9f | 242 | CopyMem (LocalBuffer, &Action, sizeof (EFI_IFR_ACTION)); |
243 | Data->Offset += sizeof (EFI_IFR_ACTION); | |
244 | ||
245 | return EFI_SUCCESS; | |
246 | } | |
247 | ||
ad1b3619 | 248 | /** |
249 | Create EFI_IFR_SUBTITLE_OP opcode. | |
250 | ||
251 | @param Prompt String ID for Prompt | |
252 | @param Help String ID for Help | |
253 | @param Flags Subtitle opcode flags | |
254 | @param Scope Subtitle Scope bit | |
255 | @param Data Destination for the created opcode binary | |
256 | ||
257 | @retval EFI_SUCCESS Opcode create success | |
258 | @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. | |
259 | ||
260 | **/ | |
e52c5a9f | 261 | EFI_STATUS |
262 | EFIAPI | |
263 | CreateSubTitleOpCode ( | |
264 | IN EFI_STRING_ID Prompt, | |
265 | IN EFI_STRING_ID Help, | |
266 | IN UINT8 Flags, | |
267 | IN UINT8 Scope, | |
268 | IN OUT EFI_HII_UPDATE_DATA *Data | |
269 | ) | |
270 | { | |
271 | EFI_IFR_SUBTITLE Subtitle; | |
272 | UINT8 *LocalBuffer; | |
273 | ||
274 | ASSERT (Data != NULL && Data->Data != NULL); | |
275 | ||
276 | if (Data->Offset + sizeof (EFI_IFR_SUBTITLE) > Data->BufferSize) { | |
277 | return EFI_BUFFER_TOO_SMALL; | |
278 | } | |
279 | ||
280 | Subtitle.Header.OpCode = EFI_IFR_SUBTITLE_OP; | |
281 | Subtitle.Header.Length = sizeof (EFI_IFR_SUBTITLE); | |
282 | Subtitle.Header.Scope = Scope; | |
283 | Subtitle.Statement.Prompt = Prompt; | |
284 | Subtitle.Statement.Help = Help; | |
285 | Subtitle.Flags = Flags; | |
286 | ||
287 | LocalBuffer = (UINT8 *) Data->Data + Data->Offset; | |
a8ff9715 LG |
288 | // |
289 | // CopyMem is used for EFI_IFR_SUBTITLE to cover the unaligned address access. | |
290 | // | |
e52c5a9f | 291 | CopyMem (LocalBuffer, &Subtitle, sizeof (EFI_IFR_SUBTITLE)); |
292 | Data->Offset += sizeof (EFI_IFR_SUBTITLE); | |
293 | ||
294 | return EFI_SUCCESS; | |
295 | } | |
296 | ||
297 | ||
ad1b3619 | 298 | /** |
299 | Create EFI_IFR_TEXT_OP opcode. | |
300 | ||
301 | @param Prompt String ID for Prompt | |
302 | @param Help String ID for Help | |
303 | @param TextTwo String ID for text two | |
304 | @param Data Destination for the created opcode binary | |
305 | ||
306 | @retval EFI_SUCCESS Opcode create success | |
307 | @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. | |
308 | ||
309 | **/ | |
e52c5a9f | 310 | EFI_STATUS |
311 | EFIAPI | |
312 | CreateTextOpCode ( | |
313 | IN EFI_STRING_ID Prompt, | |
314 | IN EFI_STRING_ID Help, | |
315 | IN EFI_STRING_ID TextTwo, | |
316 | IN OUT EFI_HII_UPDATE_DATA *Data | |
317 | ) | |
318 | { | |
319 | EFI_IFR_TEXT Text; | |
320 | UINT8 *LocalBuffer; | |
321 | ||
322 | ASSERT (Data != NULL && Data->Data != NULL); | |
323 | ||
324 | if (Data->Offset + sizeof (EFI_IFR_TEXT) > Data->BufferSize) { | |
325 | return EFI_BUFFER_TOO_SMALL; | |
326 | } | |
327 | ||
328 | Text.Header.OpCode = EFI_IFR_TEXT_OP; | |
329 | Text.Header.Length = sizeof (EFI_IFR_TEXT); | |
330 | Text.Header.Scope = 0; | |
331 | Text.Statement.Prompt = Prompt; | |
332 | Text.Statement.Help = Help; | |
333 | Text.TextTwo = TextTwo; | |
334 | ||
335 | LocalBuffer = (UINT8 *) Data->Data + Data->Offset; | |
a8ff9715 LG |
336 | // |
337 | // CopyMem is used for EFI_IFR_TEXT to cover the unaligned address access. | |
338 | // | |
e52c5a9f | 339 | CopyMem (LocalBuffer, &Text, sizeof (EFI_IFR_TEXT)); |
340 | Data->Offset += sizeof (EFI_IFR_TEXT); | |
341 | ||
342 | return EFI_SUCCESS; | |
343 | } | |
344 | ||
ad1b3619 | 345 | /** |
346 | Create EFI_IFR_REF_OP opcode. | |
347 | ||
348 | @param FormId Destination Form ID | |
349 | @param Prompt String ID for Prompt | |
350 | @param Help String ID for Help | |
351 | @param QuestionFlags Flags in Question Header | |
352 | @param QuestionId Question ID | |
353 | @param Data Destination for the created opcode binary | |
354 | ||
355 | @retval EFI_SUCCESS Opcode create success | |
356 | @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. | |
357 | @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid. | |
358 | ||
359 | **/ | |
e52c5a9f | 360 | EFI_STATUS |
361 | EFIAPI | |
362 | CreateGotoOpCode ( | |
363 | IN EFI_FORM_ID FormId, | |
364 | IN EFI_STRING_ID Prompt, | |
365 | IN EFI_STRING_ID Help, | |
366 | IN UINT8 QuestionFlags, | |
367 | IN EFI_QUESTION_ID QuestionId, | |
368 | IN OUT EFI_HII_UPDATE_DATA *Data | |
369 | ) | |
370 | { | |
371 | EFI_IFR_REF Goto; | |
372 | UINT8 *LocalBuffer; | |
373 | ||
374 | ASSERT (Data != NULL && Data->Data != NULL); | |
375 | ||
376 | if (!IsValidQuestionFlags (QuestionFlags)) { | |
377 | return EFI_INVALID_PARAMETER; | |
378 | } | |
379 | ||
380 | if (Data->Offset + sizeof (EFI_IFR_REF) > Data->BufferSize) { | |
381 | return EFI_BUFFER_TOO_SMALL; | |
382 | } | |
383 | ||
384 | Goto.Header.OpCode = EFI_IFR_REF_OP; | |
385 | Goto.Header.Length = sizeof (EFI_IFR_REF); | |
386 | Goto.Header.Scope = 0; | |
387 | Goto.Question.Header.Prompt = Prompt; | |
388 | Goto.Question.Header.Help = Help; | |
389 | Goto.Question.VarStoreId = INVALID_VARSTORE_ID; | |
390 | Goto.Question.QuestionId = QuestionId; | |
391 | Goto.Question.Flags = QuestionFlags; | |
392 | Goto.FormId = FormId; | |
393 | ||
394 | LocalBuffer = (UINT8 *) Data->Data + Data->Offset; | |
a8ff9715 LG |
395 | // |
396 | // CopyMem is used for EFI_IFR_REF to cover the unaligned address access. | |
397 | // | |
e52c5a9f | 398 | CopyMem (LocalBuffer, &Goto, sizeof (EFI_IFR_REF)); |
399 | Data->Offset += sizeof (EFI_IFR_REF); | |
400 | ||
401 | return EFI_SUCCESS; | |
402 | } | |
403 | ||
ad1b3619 | 404 | /** |
405 | Create EFI_IFR_ONE_OF_OPTION_OP opcode. | |
406 | ||
407 | @param OptionCount The number of options. | |
408 | @param OptionsList The list of Options. | |
409 | @param Type The data type. | |
410 | @param Data Destination for the created opcode binary | |
411 | ||
412 | @retval EFI_SUCCESS Opcode create success | |
413 | @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. | |
414 | ||
415 | **/ | |
e52c5a9f | 416 | EFI_STATUS |
417 | EFIAPI | |
418 | CreateOneOfOptionOpCode ( | |
419 | IN UINTN OptionCount, | |
420 | IN IFR_OPTION *OptionsList, | |
421 | IN UINT8 Type, | |
422 | IN OUT EFI_HII_UPDATE_DATA *Data | |
423 | ) | |
424 | { | |
425 | UINTN Index; | |
426 | UINT8 *LocalBuffer; | |
427 | EFI_IFR_ONE_OF_OPTION OneOfOption; | |
428 | ||
429 | ASSERT (Data != NULL && Data->Data != NULL); | |
430 | ||
431 | if ((OptionCount != 0) && (OptionsList == NULL)) { | |
432 | return EFI_INVALID_PARAMETER; | |
433 | } | |
434 | ||
435 | if (Data->Offset + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) > Data->BufferSize) { | |
436 | return EFI_BUFFER_TOO_SMALL; | |
437 | } | |
438 | ||
439 | for (Index = 0; Index < OptionCount; Index++) { | |
440 | OneOfOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP; | |
441 | OneOfOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION); | |
442 | OneOfOption.Header.Scope = 0; | |
443 | ||
444 | OneOfOption.Option = OptionsList[Index].StringToken; | |
445 | OneOfOption.Value = OptionsList[Index].Value; | |
446 | OneOfOption.Flags = (UINT8) (OptionsList[Index].Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG)); | |
447 | OneOfOption.Type = Type; | |
448 | ||
449 | LocalBuffer = (UINT8 *) Data->Data + Data->Offset; | |
a8ff9715 LG |
450 | // |
451 | // CopyMem is used for EFI_IFR_ONF_OF_OPTION to cover the unaligned address access. | |
452 | // | |
e52c5a9f | 453 | CopyMem (LocalBuffer, &OneOfOption, sizeof (EFI_IFR_ONE_OF_OPTION)); |
454 | Data->Offset += sizeof (EFI_IFR_ONE_OF_OPTION); | |
455 | } | |
456 | ||
457 | return EFI_SUCCESS; | |
458 | } | |
459 | ||
ad1b3619 | 460 | /** |
461 | Create EFI_IFR_ONE_OF_OP opcode. | |
462 | ||
463 | @param QuestionId Question ID | |
464 | @param VarStoreId Storage ID | |
465 | @param VarOffset Offset in Storage | |
466 | @param Prompt String ID for Prompt | |
467 | @param Help String ID for Help | |
468 | @param QuestionFlags Flags in Question Header | |
469 | @param OneOfFlags Flags for oneof opcode | |
470 | @param OptionsList List of options | |
471 | @param OptionCount Number of options in option list | |
472 | @param Data Destination for the created opcode binary | |
473 | ||
474 | @retval EFI_SUCCESS Opcode create success | |
475 | @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. | |
476 | @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid. | |
477 | ||
478 | **/ | |
e52c5a9f | 479 | EFI_STATUS |
480 | EFIAPI | |
481 | CreateOneOfOpCode ( | |
482 | IN EFI_QUESTION_ID QuestionId, | |
483 | IN EFI_VARSTORE_ID VarStoreId, | |
484 | IN UINT16 VarOffset, | |
485 | IN EFI_STRING_ID Prompt, | |
486 | IN EFI_STRING_ID Help, | |
487 | IN UINT8 QuestionFlags, | |
488 | IN UINT8 OneOfFlags, | |
489 | IN IFR_OPTION *OptionsList, | |
490 | IN UINTN OptionCount, | |
491 | IN OUT EFI_HII_UPDATE_DATA *Data | |
492 | ) | |
493 | { | |
494 | UINTN Length; | |
495 | EFI_IFR_ONE_OF OneOf; | |
496 | UINT8 *LocalBuffer; | |
497 | ||
498 | ASSERT (Data != NULL && Data->Data != NULL); | |
499 | ||
500 | if (!IsValidNumricFlags (OneOfFlags) || | |
501 | !IsValidQuestionFlags (QuestionFlags) || | |
502 | ((OptionCount != 0) && (OptionsList == NULL))) { | |
503 | return EFI_INVALID_PARAMETER; | |
504 | } | |
505 | ||
506 | Length = sizeof (EFI_IFR_ONE_OF) + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) + sizeof (EFI_IFR_END); | |
507 | if (Data->Offset + Length > Data->BufferSize) { | |
508 | return EFI_BUFFER_TOO_SMALL; | |
509 | } | |
510 | ||
511 | OneOf.Header.OpCode = EFI_IFR_ONE_OF_OP; | |
512 | OneOf.Header.Length = sizeof (EFI_IFR_ONE_OF); | |
513 | OneOf.Header.Scope = 1; | |
514 | OneOf.Question.Header.Prompt = Prompt; | |
515 | OneOf.Question.Header.Help = Help; | |
516 | OneOf.Question.QuestionId = QuestionId; | |
517 | OneOf.Question.VarStoreId = VarStoreId; | |
518 | OneOf.Question.VarStoreInfo.VarOffset = VarOffset; | |
519 | OneOf.Question.Flags = QuestionFlags; | |
520 | OneOf.Flags = OneOfFlags; | |
521 | ZeroMem ((VOID *) &OneOf.data, sizeof (MINMAXSTEP_DATA)); | |
522 | ||
523 | LocalBuffer = (UINT8 *) Data->Data + Data->Offset; | |
a8ff9715 LG |
524 | // |
525 | // CopyMem is used for EFI_IFR_ONF_OF to cover the unaligned address access. | |
526 | // | |
e52c5a9f | 527 | CopyMem (LocalBuffer, &OneOf, sizeof (EFI_IFR_ONE_OF)); |
528 | Data->Offset += sizeof (EFI_IFR_ONE_OF); | |
529 | ||
530 | CreateOneOfOptionOpCode (OptionCount, OptionsList, (UINT8) (OneOfFlags & EFI_IFR_NUMERIC_SIZE), Data); | |
531 | ||
532 | CreateEndOpCode (Data); | |
533 | ||
534 | return EFI_SUCCESS; | |
535 | } | |
536 | ||
ad1b3619 | 537 | /** |
538 | Create EFI_IFR_ORDERED_LIST_OP opcode. | |
539 | ||
540 | @param QuestionId Question ID | |
541 | @param VarStoreId Storage ID | |
542 | @param VarOffset Offset in Storage | |
543 | @param Prompt String ID for Prompt | |
544 | @param Help String ID for Help | |
545 | @param QuestionFlags Flags in Question Header | |
546 | @param OrderedListFlags Flags for ordered list opcode | |
547 | @param DataType Type for option value | |
548 | @param MaxContainers Maximum count for options in this ordered list | |
549 | @param OptionsList List of options | |
550 | @param OptionCount Number of options in option list | |
551 | @param Data Destination for the created opcode binary | |
552 | ||
553 | @retval EFI_SUCCESS Opcode create success | |
554 | @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. | |
555 | @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid. | |
556 | ||
557 | **/ | |
e52c5a9f | 558 | EFI_STATUS |
559 | EFIAPI | |
560 | CreateOrderedListOpCode ( | |
561 | IN EFI_QUESTION_ID QuestionId, | |
562 | IN EFI_VARSTORE_ID VarStoreId, | |
563 | IN UINT16 VarOffset, | |
564 | IN EFI_STRING_ID Prompt, | |
565 | IN EFI_STRING_ID Help, | |
566 | IN UINT8 QuestionFlags, | |
567 | IN UINT8 OrderedListFlags, | |
568 | IN UINT8 DataType, | |
569 | IN UINT8 MaxContainers, | |
570 | IN IFR_OPTION *OptionsList, | |
571 | IN UINTN OptionCount, | |
572 | IN OUT EFI_HII_UPDATE_DATA *Data | |
573 | ) | |
574 | { | |
575 | UINTN Length; | |
576 | EFI_IFR_ORDERED_LIST OrderedList; | |
577 | UINT8 *LocalBuffer; | |
578 | ||
579 | ASSERT (Data != NULL && Data->Data != NULL); | |
580 | ||
581 | if (!IsValidQuestionFlags (QuestionFlags) || | |
582 | ((OptionCount != 0) && (OptionsList == NULL))) { | |
583 | return EFI_INVALID_PARAMETER; | |
584 | } | |
585 | ||
586 | if ((OrderedListFlags != 0) && | |
587 | (OrderedListFlags != EFI_IFR_UNIQUE_SET) && | |
588 | (OrderedListFlags != EFI_IFR_NO_EMPTY_SET)) { | |
589 | return EFI_INVALID_PARAMETER; | |
590 | } | |
591 | ||
592 | Length = sizeof (EFI_IFR_ORDERED_LIST) + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) + sizeof (EFI_IFR_END); | |
593 | if (Data->Offset + Length > Data->BufferSize) { | |
594 | return EFI_BUFFER_TOO_SMALL; | |
595 | } | |
596 | ||
597 | OrderedList.Header.OpCode = EFI_IFR_ORDERED_LIST_OP; | |
598 | OrderedList.Header.Length = sizeof (EFI_IFR_ORDERED_LIST); | |
599 | OrderedList.Header.Scope = 1; | |
600 | OrderedList.Question.Header.Prompt = Prompt; | |
601 | OrderedList.Question.Header.Help = Help; | |
602 | OrderedList.Question.QuestionId = QuestionId; | |
603 | OrderedList.Question.VarStoreId = VarStoreId; | |
604 | OrderedList.Question.VarStoreInfo.VarOffset = VarOffset; | |
605 | OrderedList.Question.Flags = QuestionFlags; | |
606 | OrderedList.MaxContainers = MaxContainers; | |
607 | OrderedList.Flags = OrderedListFlags; | |
608 | ||
609 | LocalBuffer = (UINT8 *) Data->Data + Data->Offset; | |
a8ff9715 LG |
610 | // |
611 | // CopyMem is used for EFI_IFR_ORDERED_LIST to cover the unaligned address access. | |
612 | // | |
e52c5a9f | 613 | CopyMem (LocalBuffer, &OrderedList, sizeof (EFI_IFR_ORDERED_LIST)); |
614 | Data->Offset += sizeof (EFI_IFR_ORDERED_LIST); | |
615 | ||
616 | CreateOneOfOptionOpCode (OptionCount, OptionsList, DataType, Data); | |
617 | ||
618 | CreateEndOpCode (Data); | |
619 | ||
620 | return EFI_SUCCESS; | |
621 | } | |
622 | ||
ad1b3619 | 623 | /** |
624 | Create EFI_IFR_CHECKBOX_OP opcode. | |
625 | ||
626 | @param QuestionId Question ID | |
627 | @param VarStoreId Storage ID | |
628 | @param VarOffset Offset in Storage | |
629 | @param Prompt String ID for Prompt | |
630 | @param Help String ID for Help | |
631 | @param QuestionFlags Flags in Question Header | |
632 | @param CheckBoxFlags Flags for checkbox opcode | |
633 | @param Data Destination for the created opcode binary | |
634 | ||
635 | @retval EFI_SUCCESS Opcode create success | |
636 | @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. | |
637 | @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid. | |
638 | ||
639 | **/ | |
e52c5a9f | 640 | EFI_STATUS |
641 | EFIAPI | |
642 | CreateCheckBoxOpCode ( | |
643 | IN EFI_QUESTION_ID QuestionId, | |
644 | IN EFI_VARSTORE_ID VarStoreId, | |
645 | IN UINT16 VarOffset, | |
646 | IN EFI_STRING_ID Prompt, | |
647 | IN EFI_STRING_ID Help, | |
648 | IN UINT8 QuestionFlags, | |
649 | IN UINT8 CheckBoxFlags, | |
650 | IN OUT EFI_HII_UPDATE_DATA *Data | |
651 | ) | |
652 | { | |
653 | EFI_IFR_CHECKBOX CheckBox; | |
654 | UINT8 *LocalBuffer; | |
655 | ||
656 | ASSERT (Data != NULL && Data->Data != NULL); | |
657 | ||
658 | if (!IsValidQuestionFlags (QuestionFlags) || !IsValidCheckboxFlags (CheckBoxFlags)) { | |
659 | return EFI_INVALID_PARAMETER; | |
660 | } | |
661 | ||
662 | if (Data->Offset + sizeof (EFI_IFR_CHECKBOX) > Data->BufferSize) { | |
663 | return EFI_BUFFER_TOO_SMALL; | |
664 | } | |
665 | ||
666 | CheckBox.Header.OpCode = EFI_IFR_CHECKBOX_OP; | |
667 | CheckBox.Header.Length = sizeof (EFI_IFR_CHECKBOX); | |
668 | CheckBox.Header.Scope = 0; | |
669 | CheckBox.Question.QuestionId = QuestionId; | |
670 | CheckBox.Question.VarStoreId = VarStoreId; | |
671 | CheckBox.Question.VarStoreInfo.VarOffset = VarOffset; | |
672 | CheckBox.Question.Header.Prompt = Prompt; | |
673 | CheckBox.Question.Header.Help = Help; | |
674 | CheckBox.Question.Flags = QuestionFlags; | |
675 | CheckBox.Flags = CheckBoxFlags; | |
676 | ||
677 | LocalBuffer = (UINT8 *) Data->Data + Data->Offset; | |
a8ff9715 LG |
678 | // |
679 | // CopyMem is used for EFI_IFR_CHECKBOX to cover the unaligned address access. | |
680 | // | |
e52c5a9f | 681 | CopyMem (LocalBuffer, &CheckBox, sizeof (EFI_IFR_CHECKBOX)); |
682 | Data->Offset += sizeof (EFI_IFR_CHECKBOX); | |
683 | ||
684 | return EFI_SUCCESS; | |
685 | } | |
686 | ||
ad1b3619 | 687 | /** |
688 | Create EFI_IFR_NUMERIC_OP opcode. | |
689 | ||
690 | @param QuestionId Question ID | |
691 | @param VarStoreId Storage ID | |
692 | @param VarOffset Offset in Storage | |
693 | @param Prompt String ID for Prompt | |
694 | @param Help String ID for Help | |
695 | @param QuestionFlags Flags in Question Header | |
696 | @param NumericFlags Flags for numeric opcode | |
697 | @param Minimum Numeric minimum value | |
698 | @param Maximum Numeric maximum value | |
699 | @param Step Numeric step for edit | |
700 | @param Default Numeric default value | |
701 | @param Data Destination for the created opcode binary | |
702 | ||
703 | @retval EFI_SUCCESS Opcode create success | |
704 | @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. | |
705 | @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid. | |
706 | ||
707 | **/ | |
e52c5a9f | 708 | EFI_STATUS |
709 | EFIAPI | |
710 | CreateNumericOpCode ( | |
711 | IN EFI_QUESTION_ID QuestionId, | |
712 | IN EFI_VARSTORE_ID VarStoreId, | |
713 | IN UINT16 VarOffset, | |
714 | IN EFI_STRING_ID Prompt, | |
715 | IN EFI_STRING_ID Help, | |
716 | IN UINT8 QuestionFlags, | |
717 | IN UINT8 NumericFlags, | |
718 | IN UINT64 Minimum, | |
719 | IN UINT64 Maximum, | |
720 | IN UINT64 Step, | |
721 | IN UINT64 Default, | |
722 | IN OUT EFI_HII_UPDATE_DATA *Data | |
723 | ) | |
724 | { | |
725 | EFI_STATUS Status; | |
726 | EFI_IFR_NUMERIC Numeric; | |
727 | MINMAXSTEP_DATA MinMaxStep; | |
728 | EFI_IFR_TYPE_VALUE DefaultValue; | |
729 | UINT8 *LocalBuffer; | |
730 | ||
731 | ASSERT (Data != NULL && Data->Data != NULL); | |
732 | ||
733 | if (!IsValidQuestionFlags (QuestionFlags) || !IsValidNumricFlags (NumericFlags)) { | |
734 | return EFI_INVALID_PARAMETER; | |
735 | } | |
736 | ||
737 | if (Data->Offset + sizeof (EFI_IFR_CHECKBOX) > Data->BufferSize) { | |
738 | return EFI_BUFFER_TOO_SMALL; | |
739 | } | |
740 | ||
741 | Numeric.Header.OpCode = EFI_IFR_NUMERIC_OP; | |
742 | Numeric.Header.Length = sizeof (EFI_IFR_NUMERIC); | |
743 | Numeric.Header.Scope = 1; | |
744 | Numeric.Question.QuestionId = QuestionId; | |
745 | Numeric.Question.VarStoreId = VarStoreId; | |
746 | Numeric.Question.VarStoreInfo.VarOffset = VarOffset; | |
747 | Numeric.Question.Header.Prompt = Prompt; | |
748 | Numeric.Question.Header.Help = Help; | |
749 | Numeric.Question.Flags = QuestionFlags; | |
750 | Numeric.Flags = NumericFlags; | |
751 | ||
752 | switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) { | |
753 | case EFI_IFR_NUMERIC_SIZE_1: | |
754 | MinMaxStep.u8.MinValue = (UINT8) Minimum; | |
755 | MinMaxStep.u8.MaxValue = (UINT8) Maximum; | |
756 | MinMaxStep.u8.Step = (UINT8) Step; | |
757 | break; | |
758 | ||
759 | case EFI_IFR_NUMERIC_SIZE_2: | |
760 | MinMaxStep.u16.MinValue = (UINT16) Minimum; | |
761 | MinMaxStep.u16.MaxValue = (UINT16) Maximum; | |
762 | MinMaxStep.u16.Step = (UINT16) Step; | |
763 | break; | |
764 | ||
765 | case EFI_IFR_NUMERIC_SIZE_4: | |
766 | MinMaxStep.u32.MinValue = (UINT32) Minimum; | |
767 | MinMaxStep.u32.MaxValue = (UINT32) Maximum; | |
768 | MinMaxStep.u32.Step = (UINT32) Step; | |
769 | break; | |
770 | ||
771 | case EFI_IFR_NUMERIC_SIZE_8: | |
772 | MinMaxStep.u64.MinValue = Minimum; | |
773 | MinMaxStep.u64.MaxValue = Maximum; | |
774 | MinMaxStep.u64.Step = Step; | |
775 | break; | |
776 | } | |
777 | ||
778 | CopyMem (&Numeric.data, &MinMaxStep, sizeof (MINMAXSTEP_DATA)); | |
779 | ||
780 | LocalBuffer = (UINT8 *) Data->Data + Data->Offset; | |
a8ff9715 LG |
781 | // |
782 | // CopyMem is used for EFI_IFR_NUMERIC to cover the unaligned address access. | |
783 | // | |
e52c5a9f | 784 | CopyMem (LocalBuffer, &Numeric, sizeof (EFI_IFR_NUMERIC)); |
785 | Data->Offset += sizeof (EFI_IFR_NUMERIC); | |
786 | ||
787 | DefaultValue.u64 = Default; | |
788 | Status = CreateDefaultOpCode (&DefaultValue, (UINT8) (NumericFlags & EFI_IFR_NUMERIC_SIZE), Data); | |
789 | if (EFI_ERROR(Status)) { | |
790 | return Status; | |
791 | } | |
792 | ||
793 | CreateEndOpCode (Data); | |
794 | ||
795 | return EFI_SUCCESS; | |
796 | } | |
797 | ||
ad1b3619 | 798 | /** |
799 | Create EFI_IFR_STRING_OP opcode. | |
800 | ||
801 | @param QuestionId Question ID | |
802 | @param VarStoreId Storage ID | |
803 | @param VarOffset Offset in Storage | |
804 | @param Prompt String ID for Prompt | |
805 | @param Help String ID for Help | |
806 | @param QuestionFlags Flags in Question Header | |
807 | @param StringFlags Flags for string opcode | |
808 | @param MinSize String minimum length | |
809 | @param MaxSize String maximum length | |
810 | @param Data Destination for the created opcode binary | |
811 | ||
812 | @retval EFI_SUCCESS Opcode create success | |
813 | @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. | |
814 | @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid. | |
815 | ||
816 | **/ | |
e52c5a9f | 817 | EFI_STATUS |
818 | EFIAPI | |
819 | CreateStringOpCode ( | |
820 | IN EFI_QUESTION_ID QuestionId, | |
821 | IN EFI_VARSTORE_ID VarStoreId, | |
822 | IN UINT16 VarOffset, | |
823 | IN EFI_STRING_ID Prompt, | |
824 | IN EFI_STRING_ID Help, | |
825 | IN UINT8 QuestionFlags, | |
826 | IN UINT8 StringFlags, | |
827 | IN UINT8 MinSize, | |
828 | IN UINT8 MaxSize, | |
829 | IN OUT EFI_HII_UPDATE_DATA *Data | |
830 | ) | |
831 | { | |
832 | EFI_IFR_STRING String; | |
833 | UINT8 *LocalBuffer; | |
834 | ||
835 | ASSERT (Data != NULL && Data->Data != NULL); | |
836 | ||
ad1b3619 | 837 | if (!IsValidQuestionFlags (QuestionFlags) || (StringFlags & ~EFI_IFR_STRING_MULTI_LINE) != 0) { |
e52c5a9f | 838 | return EFI_INVALID_PARAMETER; |
839 | } | |
840 | ||
841 | if (Data->Offset + sizeof (EFI_IFR_STRING) > Data->BufferSize) { | |
842 | return EFI_BUFFER_TOO_SMALL; | |
843 | } | |
844 | ||
845 | String.Header.OpCode = EFI_IFR_STRING_OP; | |
846 | String.Header.Length = sizeof (EFI_IFR_STRING); | |
847 | String.Header.Scope = 0; | |
848 | String.Question.Header.Prompt = Prompt; | |
849 | String.Question.Header.Help = Help; | |
850 | String.Question.QuestionId = QuestionId; | |
851 | String.Question.VarStoreId = VarStoreId; | |
852 | String.Question.VarStoreInfo.VarOffset = VarOffset; | |
853 | String.Question.Flags = QuestionFlags; | |
854 | String.MinSize = MinSize; | |
855 | String.MaxSize = MaxSize; | |
856 | String.Flags = StringFlags; | |
857 | ||
858 | LocalBuffer = (UINT8 *) Data->Data + Data->Offset; | |
a8ff9715 LG |
859 | // |
860 | // CopyMem is used for EFI_IFR_STRING to cover the unaligned address access. | |
861 | // | |
e52c5a9f | 862 | CopyMem (LocalBuffer, &String, sizeof (EFI_IFR_STRING)); |
863 | Data->Offset += sizeof (EFI_IFR_STRING); | |
864 | ||
865 | return EFI_SUCCESS; | |
866 | } | |
867 | ||
868 |