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