3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Implementation for handling the User Interface option processing.
28 ExtractRequestedNvMap (
29 IN EFI_FILE_FORM_TAGS
*FileFormTags
,
31 OUT EFI_VARIABLE_DEFINITION
**VariableDefinition
34 *VariableDefinition
= FileFormTags
->VariableDefinitions
;
37 // Extract the data from the NV variable - consumer will free the buffer.
39 for (; *VariableDefinition
!= NULL
; *VariableDefinition
= (*VariableDefinition
)->Next
) {
41 // If there is a variable with this ID return with EFI_SUCCESS
43 if (!CompareMem (&(*VariableDefinition
)->VariableId
, &VariableId
, sizeof (UINT16
))) {
53 IN EFI_FILE_FORM_TAGS
*FileFormTags
,
55 IN UINT16 VariableSize
,
56 IN UINT16 OffsetValue
,
61 EFI_VARIABLE_DEFINITION
*VariableDefinition
;
63 Status
= ExtractRequestedNvMap (FileFormTags
, VariableId
, &VariableDefinition
);
65 if (!EFI_ERROR (Status
)) {
67 // Allocate sufficient space for the data and copy it into the outgoing buffer
69 if (VariableSize
!= 0) {
70 *Buffer
= AllocateZeroPool (VariableSize
);
71 ASSERT (*Buffer
!= NULL
);
72 CopyMem (*Buffer
, &VariableDefinition
->NvRamMap
[OffsetValue
], VariableSize
);
83 IN EFI_FILE_FORM_TAGS
*FileFormTags
,
84 IN UI_MENU_OPTION
*MenuOption
91 EFI_VARIABLE_DEFINITION
*VariableDefinition
;
95 SizeRequired
= MenuOption
->ThisTag
->StorageStart
+ MenuOption
->ThisTag
->StorageWidth
;
97 ExtractRequestedNvMap (FileFormTags
, MenuOption
->Tags
->VariableNumber
, &VariableDefinition
);
100 // We arrived here because the current NvRamMap is too small for the new op-code to store things and
101 // we need to adjust the buffer to support this.
103 NvRamMap
= AllocateZeroPool (SizeRequired
+ 1);
104 ASSERT (NvRamMap
!= NULL
);
107 // Copy current NvRamMap to the new NvRamMap
109 CopyMem (NvRamMap
, VariableDefinition
->NvRamMap
, VariableDefinition
->VariableFakeSize
);
112 // Remember, the only time we come here is because we are in the NVPlus section of the NvRamMap
114 for (Index
= MenuOption
->TagIndex
;
115 (MenuOption
->Tags
[Index
].Operand
!= EFI_IFR_END_FORM_OP
) && (MenuOption
->Tags
[Index
].Operand
!= EFI_IFR_END_ONE_OF_OP
);
119 switch (MenuOption
->Tags
[Index
].Operand
) {
120 case EFI_IFR_ORDERED_LIST_OP
:
121 case EFI_IFR_ONE_OF_OP
:
122 CachedStart
= MenuOption
->Tags
[Index
].StorageStart
;
125 case EFI_IFR_ONE_OF_OPTION_OP
:
126 if (MenuOption
->Tags
[Index
].Flags
& EFI_IFR_FLAG_DEFAULT
) {
127 CopyMem (&NvRamMap
[CachedStart
], &MenuOption
->Tags
[Index
].Value
, 2);
131 case EFI_IFR_CHECKBOX_OP
:
132 CopyMem (&NvRamMap
[MenuOption
->Tags
[Index
].StorageStart
], &MenuOption
->Tags
[Index
].Flags
, 1);
135 case EFI_IFR_NUMERIC_OP
:
136 case EFI_IFR_DATE_OP
:
137 case EFI_IFR_TIME_OP
:
138 case EFI_IFR_STRING_OP
:
139 case EFI_IFR_PASSWORD_OP
:
141 &NvRamMap
[MenuOption
->Tags
[Index
].StorageStart
],
142 &MenuOption
->Tags
[Index
].Value
,
143 MenuOption
->Tags
[Index
].StorageWidth
150 gBS
->FreePool (VariableDefinition
->NvRamMap
);
151 VariableDefinition
->NvRamMap
= NvRamMap
;
152 VariableDefinition
->VariableFakeSize
= (UINT16
) SizeRequired
;
157 IN UI_MENU_OPTION
*MenuOption
,
159 IN EFI_FILE_FORM_TAGS
*FileFormTagsHead
,
160 IN EFI_IFR_DATA_ARRAY
*PageData
,
161 OUT CHAR16
**OptionString
168 EFI_FILE_FORM_TAGS
*FileFormTags
;
170 CHAR16 FormattedNumber
[6];
181 EFI_FORM_CALLBACK_PROTOCOL
*FormCallback
;
183 CHAR16 NullCharacter
;
185 EFI_VARIABLE_DEFINITION
*VariableDefinition
;
191 FileFormTags
= FileFormTagsHead
;
193 for (Index
= 0; Index
< MenuOption
->IfrNumber
; Index
++) {
194 FileFormTags
= FileFormTags
->NextFile
;
200 VariableDefinition
= NULL
;
203 ZeroMem (&Time
, sizeof (EFI_TIME
));
205 StringPtr
= (CHAR16
*) L
"\0";
206 Tag
= MenuOption
->ThisTag
;
207 ExtractRequestedNvMap (FileFormTags
, Tag
->VariableNumber
, &VariableDefinition
);
209 if (Tag
->StorageStart
> VariableDefinition
->VariableSize
) {
210 NvRamMap
= (UINT16
*) &VariableDefinition
->FakeNvRamMap
[Tag
->StorageStart
];
212 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
219 NullCharacter
= CHAR_NULL
;
222 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_ORDERED_LIST_OP
) {
224 if (((UINT8
*) NvRamMap
)[0] != 0x00) {
229 ZeroMem (FormattedNumber
, 12);
231 Status
= gBS
->HandleProtocol (
232 (VOID
*) (UINTN
) FileFormTags
->FormTags
.Tags
[0].CallbackHandle
,
233 &gEfiFormCallbackProtocolGuid
,
234 (VOID
**) &FormCallback
237 if (*OptionString
!= NULL
) {
238 gBS
->FreePool (*OptionString
);
239 *OptionString
= NULL
;
242 switch (Tag
->Operand
) {
244 case EFI_IFR_ORDERED_LIST_OP
:
245 case EFI_IFR_ONE_OF_OP
:
247 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
248 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
249 // the NvMap so that we can properly display the information
251 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
252 AdjustNvMap (FileFormTags
, MenuOption
);
253 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
256 CachedIndex
= MenuOption
->TagIndex
;
259 // search for EFI_IFR_ONE_OF_OPTION_OP until you hit the EFI_IFR_END_ONE_OF_OP,
260 // each of the .Text in the options are going to be what gets displayed. Break each into 26 char chunks
261 // when hit right/left arrow allows for selection - then repopulate Tag[TagIndex] with the choice
263 for (Index
= MenuOption
->TagIndex
; MenuOption
->Tags
[Index
].Operand
!= EFI_IFR_END_ONE_OF_OP
; Index
++) {
265 // We found an option - which assumedly has a string. We will eventually have to support
266 // wrapping of strings. For now, let's pretend they don't wrap and code that up.
268 // Count how many strings there are
270 if (MenuOption
->Tags
[Index
].Operand
== EFI_IFR_ONE_OF_OPTION_OP
) {
272 // If one of the options for the one-of has an interactive flag, back-define the oneof to have one too
274 if (MenuOption
->Tags
[Index
].Flags
& EFI_IFR_FLAG_INTERACTIVE
) {
275 MenuOption
->Tags
[CachedIndex
].Flags
= (UINT8
) (MenuOption
->Tags
[CachedIndex
].Flags
| EFI_IFR_FLAG_INTERACTIVE
);
282 // We now know how many strings we will have, so we can allocate the
283 // space required for the array or strings.
285 *OptionString
= AllocateZeroPool (StringCount
* (gOptionBlockWidth
+ 1) * 2 * gScreenDimensions
.BottomRow
);
286 ASSERT (*OptionString
);
289 // Add left delimeter to string
291 *OptionString
[0] = LEFT_ONEOF_DELIMITER
;
294 // Retrieve the current OneOf value
298 // Auto selection from list
302 // Copy current setting to the seed Value
304 if (Tag
->Operand
== EFI_IFR_ORDERED_LIST_OP
) {
305 ValueArray
= AllocateZeroPool (MenuOption
->ThisTag
->StorageWidth
);
306 ASSERT (ValueArray
!= NULL
);
307 CopyMem (ValueArray
, NvRamMap
, MenuOption
->ThisTag
->StorageWidth
);
309 CopyMem (&Value
, NvRamMap
, MenuOption
->ThisTag
->StorageWidth
);
310 CopyMem (gPreviousValue
, NvRamMap
, MenuOption
->ThisTag
->StorageWidth
);
314 if (Tag
->Operand
== EFI_IFR_ORDERED_LIST_OP
) {
315 Status
= GetSelectionInputPopUp (MenuOption
, Tag
, MenuOption
->ThisTag
->StorageWidth
, ValueArray
, &KeyValue
);
317 Status
= GetSelectionInputPopUp (MenuOption
, Tag
, 1, &Value
, &KeyValue
);
320 if (!EFI_ERROR (Status
)) {
321 if (Tag
->Operand
== EFI_IFR_ORDERED_LIST_OP
) {
322 CopyMem (NvRamMap
, ValueArray
, MenuOption
->ThisTag
->StorageWidth
);
323 gBS
->FreePool (ValueArray
);
326 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
328 CopyMem (NvRamMap
, &Value
, Tag
->StorageWidth
);
329 MenuOption
->ThisTag
->Key
= KeyValue
;
332 // If a late check is required save off the information. This is used when consistency checks
333 // are required, but certain values might be bound by an impossible consistency check such as
334 // if two questions are bound by consistency checks and each only has two possible choices, there
335 // would be no way for a user to switch the values. Thus we require late checking.
337 if (Tag
->Flags
& EFI_IFR_FLAG_LATE_CHECK
) {
338 CopyMem (&Tag
->OldValue
, &Value
, Tag
->StorageWidth
);
341 // In theory, passing the value and the Id are sufficient to determine what needs
342 // to be done. The Id is the key to look for the entry needed in the Inconsistency
343 // database. That will yields operand and ID data - and since the ID's correspond
344 // to the NV storage, we can determine the values for other IDs there.
346 if (ValueIsNotValid (TRUE
, 0, Tag
, FileFormTags
, &PopUp
)) {
347 if (PopUp
== 0x0000) {
351 if (!Tag
->Suppress
&& !Tag
->GrayOut
) {
352 CopyMem (NvRamMap
, &Number
, MenuOption
->ThisTag
->StorageWidth
);
357 StringPtr
= GetToken (PopUp
, MenuOption
->Handle
);
359 CreatePopUp (GetStringWidth (StringPtr
) / 2, 3, &NullCharacter
, StringPtr
, &NullCharacter
);
362 Status
= WaitForKeyStroke (&Key
);
364 switch (Key
.UnicodeChar
) {
366 case CHAR_CARRIAGE_RETURN
:
368 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
370 CopyMem (NvRamMap
, &Number
, MenuOption
->ThisTag
->StorageWidth
);
371 gBS
->FreePool (StringPtr
);
377 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
381 UpdateStatusBar (NV_UPDATE_REQUIRED
, Tag
->Flags
, TRUE
);
383 if (Tag
->Operand
== EFI_IFR_ORDERED_LIST_OP
) {
384 gBS
->FreePool (ValueArray
);
390 for (Index
= MenuOption
->TagIndex
; MenuOption
->Tags
[Index
].Operand
!= EFI_IFR_END_ONE_OF_OP
; Index
++) {
392 // We found an option - which assumedly has a string. We will eventually have to support
393 // wrapping of strings. For now, let's pretend they don't wrap and code that up.
395 if (MenuOption
->Tags
[Index
].Operand
== EFI_IFR_ONE_OF_OPTION_OP
) {
399 // If the first entry is invalid, then the "default" settings are based on what is reflected
400 // in the order of the op-codes
402 ((UINT8
*) NvRamMap
)[Index
- MenuOption
->TagIndex
- 1] = (UINT8
) MenuOption
->Tags
[Index
].Value
;
405 // Only display 3 lines of stuff at most
407 if ((Index
- MenuOption
->TagIndex
) > ORDERED_LIST_SIZE
) {
411 if (((Index
- MenuOption
->TagIndex
) != 1) && !Skip
) {
412 Character
[0] = LEFT_ONEOF_DELIMITER
;
413 NewStrCat (OptionString
[0], Character
);
416 MenuOption
->ThisTag
->NumberOfLines
= (UINT16
) (Index
- MenuOption
->TagIndex
);
418 StringPtr
= GetToken (MenuOption
->Tags
[Index
].Text
, MenuOption
->Handle
);
420 for (Value
= (UINT16
) (MenuOption
->TagIndex
+ 1);
421 MenuOption
->Tags
[Value
].Operand
!= EFI_IFR_END_ONE_OF_OP
;
424 if (MenuOption
->Tags
[Value
].Value
== ((UINT8
*) NvRamMap
)[Index
- MenuOption
->TagIndex
- 1]) {
425 StringPtr
= GetToken (MenuOption
->Tags
[Value
].Text
, MenuOption
->Handle
);
430 if (MenuOption
->Tags
[Value
].Operand
== EFI_IFR_END_ONE_OF_OP
) {
437 NewStrCat (OptionString
[0], StringPtr
);
438 Character
[0] = RIGHT_ONEOF_DELIMITER
;
439 NewStrCat (OptionString
[0], Character
);
440 Character
[0] = CHAR_CARRIAGE_RETURN
;
441 NewStrCat (OptionString
[0], Character
);
444 // Remove Buffer allocated for StringPtr after it has been used.
446 gBS
->FreePool (StringPtr
);
449 // The option value is the same as what is stored in NV store. Print this.
451 if (!CompareMem (&(MenuOption
->Tags
[Index
].Value
), NvRamMap
, MenuOption
->ThisTag
->StorageWidth
)) {
452 StringPtr
= GetToken (MenuOption
->Tags
[Index
].Text
, MenuOption
->Handle
);
453 NewStrCat (OptionString
[0], StringPtr
);
454 Character
[0] = RIGHT_ONEOF_DELIMITER
;
455 NewStrCat (OptionString
[0], Character
);
457 // Remove Buffer allocated for StringPtr after it has been used.
459 gBS
->FreePool (StringPtr
);
464 if ((MenuOption
->Tags
[Index
].Flags
& EFI_IFR_FLAG_DEFAULT
) == 1) {
465 Default
= MenuOption
->Tags
[Index
].Text
;
466 Value
= MenuOption
->Tags
[Index
].Value
;
472 // We didn't find a value that matched a setting in the NVRAM Map - display default - set default
476 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
478 CopyMem (NvRamMap
, &Value
, MenuOption
->ThisTag
->StorageWidth
);
480 StringPtr
= GetToken ((UINT16
) Default
, MenuOption
->Handle
);
481 NewStrCat (OptionString
[0], StringPtr
);
482 Character
[0] = RIGHT_ONEOF_DELIMITER
;
483 NewStrCat (OptionString
[0], Character
);
485 // Remove Buffer allocated for StringPtr after it has been used.
487 gBS
->FreePool (StringPtr
);
492 case EFI_IFR_CHECKBOX_OP
:
494 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
495 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
496 // the NvMap so that we can properly display the information
498 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
499 AdjustNvMap (FileFormTags
, MenuOption
);
500 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
503 Default
= Tag
->Flags
& 1;
505 // If hit spacebar, set or unset Tag[TagIndex].Flags based on it's previous value - BOOLEAN
507 *OptionString
= AllocateZeroPool ((gOptionBlockWidth
+ 1) * 2 * gScreenDimensions
.BottomRow
);
508 ASSERT (*OptionString
);
511 // Since Checkboxes are BOOLEAN values, bit 0 of the Flags bit defines the default option, therefore, if
512 // the default option (only one option for checkboxes) is on, then the default value is on. Tag.Default is not
513 // an active field for Checkboxes.
515 StrnCpy (OptionString
[0], (CHAR16
*) LEFT_CHECKBOX_DELIMITER
, 1);
518 // Since this is a BOOLEAN operation, flip bit 0 upon selection
521 Tag
->Value
= (UINT16
) (Tag
->Value
^ 1);
522 *(UINT8
*) NvRamMap
= (UINT8
) (Tag
->Value
& 1);
523 UpdateStatusBar (NV_UPDATE_REQUIRED
, Tag
->Flags
, TRUE
);
526 if ((*(UINT8
*) NvRamMap
& 1) == 0x01) {
527 NewStrCat (OptionString
[0], (CHAR16
*) CHECK_ON
);
529 // If someone reset default variables - we may need to reload from our NvMapping....
531 Tag
->Value
= *(UINT8
*) NvRamMap
;
534 // If someone reset default variables - we may need to reload from our NvMapping....
536 NewStrCat (OptionString
[0], (CHAR16
*) CHECK_OFF
);
537 Tag
->Value
= *(UINT8
*) NvRamMap
;
540 NewStrCat (OptionString
[0], (CHAR16
*) RIGHT_CHECKBOX_DELIMITER
);
541 NewStrCat (OptionString
[0], StringPtr
);
544 case EFI_IFR_NUMERIC_OP
:
546 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
547 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
548 // the NvMap so that we can properly display the information
550 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
551 AdjustNvMap (FileFormTags
, MenuOption
);
552 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
555 *OptionString
= AllocateZeroPool ((gOptionBlockWidth
+ 1) * 2 * gScreenDimensions
.BottomRow
);
556 ASSERT (*OptionString
);
559 // Add left delimeter to string
561 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
564 // Retrieve the current numeric value
570 if (Tag
->Step
== 0) {
574 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, TRUE
, Tag
, REGULAR_NUMERIC
, &Number
);
575 if (!EFI_ERROR (Status
)) {
576 CopyMem (gPreviousValue
, NvRamMap
, MenuOption
->ThisTag
->StorageWidth
);
577 UpdateStatusBar (NV_UPDATE_REQUIRED
, Tag
->Flags
, TRUE
);
580 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
582 CopyMem (NvRamMap
, &Number
, MenuOption
->ThisTag
->StorageWidth
);
588 // Auto selection from list
590 if ((((Tag
->StorageWidth
== 1) && (UINT8
) (*NvRamMap
) > Tag
->Maximum
) || ((UINT8
) (*NvRamMap
) < Tag
->Minimum
)) ||
591 (((Tag
->StorageWidth
== 2) && *NvRamMap
> Tag
->Maximum
) || (*NvRamMap
< Tag
->Minimum
))
594 // Seed Number with valid value if currently invalid
596 Number
= Tag
->Default
;
598 if (Tag
->StorageWidth
== 1) {
599 Number
= (UINT8
) (*NvRamMap
);
605 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, FALSE
, Tag
, REGULAR_NUMERIC
, &Number
);
606 if (!EFI_ERROR (Status
)) {
607 CopyMem (gPreviousValue
, NvRamMap
, MenuOption
->ThisTag
->StorageWidth
);
608 UpdateStatusBar (NV_UPDATE_REQUIRED
, Tag
->Flags
, TRUE
);
611 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
613 CopyMem (NvRamMap
, &Number
, MenuOption
->ThisTag
->StorageWidth
);
619 if (((Tag
->StorageWidth
== 1) && (UINT8
) (*NvRamMap
) <= Tag
->Maximum
&& (UINT8
) (*NvRamMap
) >= Tag
->Minimum
) ||
620 ((Tag
->StorageWidth
== 2) && *NvRamMap
<= Tag
->Maximum
&& *NvRamMap
>= Tag
->Minimum
)
622 if (Tag
->StorageWidth
== 1) {
623 Number
= (UINT8
) (*NvRamMap
);
627 UnicodeValueToString (
631 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
633 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
634 StrnCpy (OptionString
[0] + 1, FormattedNumber
, Number
);
637 // If *NvRamMap isn't within parameters, set it to within parameters
640 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
642 CopyMem (NvRamMap
, &Tag
->Default
, MenuOption
->ThisTag
->StorageWidth
);
643 Number
= Tag
->Default
;
645 UnicodeValueToString (
649 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
651 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
652 StrnCpy (OptionString
[0] + 1, FormattedNumber
, Number
);
655 *(OptionString
[0] + Number
/ 2) = RIGHT_NUMERIC_DELIMITER
;
656 NewStrCat (OptionString
[0] + (Number
/ 2) + 1, StringPtr
);
660 case EFI_IFR_DATE_OP
:
662 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
663 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
664 // the NvMap so that we can properly display the information
666 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
667 AdjustNvMap (FileFormTags
, MenuOption
);
668 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
671 Status
= gRT
->GetTime (&Time
, NULL
);
672 if (EFI_ERROR (Status
)) {
676 // This for loop advances Index till it points immediately after a date entry. We can then
677 // subtract MenuOption->TagIndex from Index and find out relative to the start of the Date
678 // structure which field we were in. For instance, if TagIndex was 52, and we advanced Index
679 // to 53 and found it to no longer point to a date operand, we were pointing to the last of 3
683 // This has BUGBUG potential....fix this - if someone wants to ask two DATE questions in a row.....code
684 // against such silliness.
686 // Also, we want to internationalize the order of the date information. We need to code for it as well.
688 for (Index
= MenuOption
->TagIndex
; MenuOption
->Tags
[Index
].Operand
== EFI_IFR_DATE_OP
; Index
++)
692 // Count 0 = We entered on the first Date operand
693 // Count 1 = We entered on the second Date operand
694 // Count 2 = We entered on the third Date operand
696 Count
= 3 - (Index
- MenuOption
->TagIndex
);
701 // This is similar to numerics, except for the following:
702 // We will under normal circumstances get 3 consecutive calls
703 // to process this opcodes data.
705 *OptionString
= AllocateZeroPool ((gOptionBlockWidth
+ 1) * 2 * gScreenDimensions
.BottomRow
);
706 ASSERT (*OptionString
);
711 Number
= (UINT16
) Time
.Month
;
713 if (Tag
->Step
== 0) {
714 MenuOption
->OptCol
++;
715 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, TRUE
, Tag
, DATE_NUMERIC
, &Number
);
718 // Seed value with current setting
720 Tag
->Value
= (UINT16
) Time
.Month
;
721 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, FALSE
, Tag
, DATE_NUMERIC
, &Number
);
724 if (!EFI_ERROR (Status
)) {
725 Time
.Month
= (UINT8
) Number
;
726 gRT
->SetTime (&Time
);
730 VariableDefinition
->FakeNvRamMap
[Tag
->Id
] = Time
.Month
;
731 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
733 UnicodeValueToString (
737 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
739 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
742 FormattedNumber
[2] = FormattedNumber
[1];
743 FormattedNumber
[1] = FormattedNumber
[0];
744 FormattedNumber
[0] = L
'0';
748 StrnCpy (OptionString
[0] + 1, FormattedNumber
, Number
);
749 *(OptionString
[0] + Number
/ 2) = DATE_SEPARATOR
;
750 StrCat (OptionString
[0] + (Number
/ 2) + 1, StringPtr
);
755 Number
= (UINT16
) Time
.Day
;
757 if (Tag
->Step
== 0) {
758 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, TRUE
, Tag
, DATE_NUMERIC
, &Number
);
761 // Seed value with current setting
763 Tag
->Value
= (UINT16
) Time
.Day
;
764 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, FALSE
, Tag
, DATE_NUMERIC
, &Number
);
767 if (!EFI_ERROR (Status
)) {
768 Time
.Day
= (UINT8
) Number
;
769 gRT
->SetTime (&Time
);
773 VariableDefinition
->FakeNvRamMap
[Tag
->Id
] = Time
.Day
;
774 SetUnicodeMem (OptionString
[0], 4, L
' ');
776 UnicodeValueToString (
780 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
782 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
784 FormattedNumber
[2] = FormattedNumber
[1];
785 FormattedNumber
[1] = FormattedNumber
[0];
786 FormattedNumber
[0] = L
'0';
790 StrnCpy (OptionString
[0] + 4, FormattedNumber
, Number
);
791 *(OptionString
[0] + Number
/ 2 + 3) = DATE_SEPARATOR
;
792 StrCat (OptionString
[0] + (Number
/ 2) + 4, StringPtr
);
797 Number
= (UINT16
) Time
.Year
;
799 if (Tag
->Step
== 0) {
800 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, TRUE
, Tag
, DATE_NUMERIC
, &Number
);
803 // Seed value with current setting
805 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, FALSE
, Tag
, DATE_NUMERIC
, &Number
);
808 if (!EFI_ERROR (Status
)) {
809 Time
.Year
= (UINT16
) Number
;
810 gRT
->SetTime (&Time
);
814 Tag
->Value
= (UINT16
) Time
.Year
;
815 VariableDefinition
->FakeNvRamMap
[Tag
->Id
] = (UINT8
) Tag
->Value
;
816 VariableDefinition
->FakeNvRamMap
[Tag
->Id
+ 1] = (UINT8
) (Tag
->Value
>> 8);
817 SetUnicodeMem (OptionString
[0], 7, L
' ');
818 UnicodeValueToString (
822 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
824 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
825 StrnCpy (OptionString
[0] + 7, FormattedNumber
, Number
);
826 *(OptionString
[0] + Number
/ 2 + 6) = RIGHT_NUMERIC_DELIMITER
;
827 StrCat (OptionString
[0] + (Number
/ 2) + 7, StringPtr
);
834 // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG
835 // We need to add code to support the NVRam storage version of Date - this is the 1% case where someone
836 // might want to set an alarm and actually preserve the data in NVRam so a driver can pick up the instruction
837 // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG
839 case EFI_IFR_TIME_OP
:
841 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
842 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
843 // the NvMap so that we can properly display the information
845 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
846 AdjustNvMap (FileFormTags
, MenuOption
);
847 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
850 Status
= gRT
->GetTime (&Time
, NULL
);
851 if (EFI_ERROR (Status
)) {
855 // This is similar to numerics, except for the following:
856 // We will under normal circumstances get 3 consecutive calls
857 // to process this opcodes data.
859 *OptionString
= AllocateZeroPool ((gOptionBlockWidth
+ 1) * 2 * gScreenDimensions
.BottomRow
);
860 ASSERT (*OptionString
);
863 // This for loop advances Index till it points immediately after a date entry. We can then
864 // subtract MenuOption->TagIndex from Index and find out relative to the start of the Date
865 // structure which field we were in. For instance, if TagIndex was 52, and we advanced Index
866 // to 53 and found it to no longer point to a date operand, we were pointing to the last of 3
869 for (Index
= MenuOption
->TagIndex
; MenuOption
->Tags
[Index
].Operand
== EFI_IFR_TIME_OP
; Index
++)
872 // Count 0 = We entered on the first Date operand
873 // Count 1 = We entered on the second Date operand
874 // Count 2 = We entered on the third Date operand
876 Count
= 3 - (Index
- MenuOption
->TagIndex
);
887 Number
= Time
.Minute
;
891 Number
= Time
.Second
;
894 // Retrieve the current numeric value
900 if (Tag
->Step
== 0) {
904 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, TRUE
, Tag
, TIME_NUMERIC
, &Number
);
905 if (!EFI_ERROR (Status
)) {
908 gRT
->SetTime (&Time
);
914 // Auto selection from list
916 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, FALSE
, Tag
, TIME_NUMERIC
, &Number
);
917 if (!EFI_ERROR (Status
)) {
926 Time
.Hour
= (UINT8
) Number
;
930 Time
.Minute
= (UINT8
) Number
;
934 Time
.Second
= (UINT8
) Number
;
938 gRT
->SetTime (&Time
);
942 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
943 UnicodeValueToString (
947 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
949 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
951 FormattedNumber
[2] = FormattedNumber
[1];
952 FormattedNumber
[1] = FormattedNumber
[0];
953 FormattedNumber
[0] = L
'0';
957 StrnCpy (OptionString
[0] + 1, FormattedNumber
, Number
);
958 *(OptionString
[0] + Number
/ 2) = TIME_SEPARATOR
;
959 StrCat (OptionString
[0] + (Number
/ 2) + 1, StringPtr
);
963 SetUnicodeMem (OptionString
[0], 4, L
' ');
964 UnicodeValueToString (
968 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
970 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
972 FormattedNumber
[2] = FormattedNumber
[1];
973 FormattedNumber
[1] = FormattedNumber
[0];
974 FormattedNumber
[0] = L
'0';
978 StrnCpy (OptionString
[0] + 4, FormattedNumber
, Number
);
979 *(OptionString
[0] + Number
/ 2 + 3) = TIME_SEPARATOR
;
980 StrCat (OptionString
[0] + (Number
/ 2) + 4, StringPtr
);
984 SetUnicodeMem (OptionString
[0], 7, L
' ');
985 UnicodeValueToString (
989 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
991 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
993 FormattedNumber
[2] = FormattedNumber
[1];
994 FormattedNumber
[1] = FormattedNumber
[0];
995 FormattedNumber
[0] = L
'0';
999 StrnCpy (OptionString
[0] + 7, FormattedNumber
, Number
);
1000 *(OptionString
[0] + Number
/ 2 + 6) = RIGHT_NUMERIC_DELIMITER
;
1001 StrCat (OptionString
[0] + (Number
/ 2) + 7, StringPtr
);
1005 // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG
1006 // We need to add code to support the NVRam storage version of Date - this is the 1% case where someone
1007 // might want to set an alarm and actually preserve the data in NVRam so a driver can pick up the instruction
1008 // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG
1013 case EFI_IFR_STRING_OP
:
1015 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
1016 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
1017 // the NvMap so that we can properly display the information
1019 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
1020 AdjustNvMap (FileFormTags
, MenuOption
);
1021 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
1024 *OptionString
= AllocateZeroPool ((gOptionBlockWidth
+ 1) * 2 * gScreenDimensions
.BottomRow
);
1025 ASSERT (*OptionString
);
1028 StringPtr
= AllocateZeroPool (Tag
->Maximum
);
1031 Status
= ReadString (MenuOption
, StringPtr
);
1033 if (!EFI_ERROR (Status
)) {
1034 CopyMem (gPreviousValue
, NvRamMap
, MenuOption
->ThisTag
->StorageWidth
);
1035 CopyMem (&VariableDefinition
->NvRamMap
[Tag
->StorageStart
], StringPtr
, Tag
->StorageWidth
);
1037 UpdateStatusBar (NV_UPDATE_REQUIRED
, Tag
->Flags
, TRUE
);
1040 gBS
->FreePool (StringPtr
);
1043 for (Index
= 0; Index
< gOptionBlockWidth
; Index
++) {
1044 if (VariableDefinition
->NvRamMap
[Tag
->StorageStart
+ (Index
* 2)] != 0x0000) {
1045 CopyMem (OptionString
[0] + Index
, &VariableDefinition
->NvRamMap
[Tag
->StorageStart
+ (Index
* 2)], 2);
1048 *(OptionString
[0] + Index
) = '_';
1049 *(OptionString
[0] + 1 + Index
) = 0;
1058 case EFI_IFR_PASSWORD_OP
:
1060 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
1061 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
1062 // the NvMap so that we can properly display the information
1064 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
1065 AdjustNvMap (FileFormTags
, MenuOption
);
1066 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
1070 StringPtr
= AllocateZeroPool (Tag
->Maximum
);
1074 // If interactive, read the password and do the appropriate callbacks in that routine.
1075 // Since interactive passwords assume to handle the password data in a separate variable
1076 // storage, we don't need to do more than what is below for password callbacks
1078 if (Tag
->Flags
& EFI_IFR_FLAG_INTERACTIVE
) {
1079 MenuOption
->Tags
[0].CallbackHandle
= FileFormTags
->FormTags
.Tags
[0].CallbackHandle
;
1080 Status
= ReadPassword (MenuOption
, TRUE
, Tag
, PageData
, FALSE
, FileFormTags
, StringPtr
);
1081 ZeroMem (StringPtr
, Tag
->Maximum
);
1083 if (EFI_ERROR (Status
)) {
1084 if (Status
== EFI_NOT_READY
) {
1085 gBS
->FreePool (StringPtr
);
1090 Status
= ReadPassword (MenuOption
, TRUE
, Tag
, PageData
, TRUE
, FileFormTags
, StringPtr
);
1091 gBS
->FreePool (StringPtr
);
1095 for (Index
= 0; Index
< Tag
->Maximum
; Index
++) {
1096 if (VariableDefinition
->NvRamMap
[Tag
->StorageStart
+ Index
] != 0x00) {
1098 // There is something there! Prompt for password
1100 Status
= ReadPassword (MenuOption
, TRUE
, Tag
, PageData
, FALSE
, FileFormTags
, StringPtr
);
1101 if (EFI_ERROR (Status
)) {
1102 gBS
->FreePool (StringPtr
);
1106 if (Tag
->Encoding
== 1) {
1107 EncodePassword (StringPtr
, (UINT8
) Tag
->Maximum
);
1108 Status
= CompareMem (StringPtr
, &VariableDefinition
->NvRamMap
[Tag
->StorageStart
], Tag
->Maximum
);
1110 Status
= CompareMem (StringPtr
, &VariableDefinition
->NvRamMap
[Tag
->StorageStart
], Tag
->Maximum
);
1114 gBS
->FreePool (StringPtr
);
1124 ZeroMem (StringPtr
, Tag
->Maximum
);
1127 // No password set! Go ahead and prompt the user for a password.
1129 Status
= ReadPassword (MenuOption
, FALSE
, Tag
, PageData
, FALSE
, FileFormTags
, StringPtr
);
1131 if (EFI_ERROR (Status
)) {
1133 // User couldn't figure out how to type two identical passwords
1135 gBS
->FreePool (StringPtr
);
1139 // Very simple example of how one MIGHT do password encoding
1141 if (Tag
->Encoding
== 1) {
1142 EncodePassword (StringPtr
, (UINT8
) Tag
->Maximum
);
1145 TmpNvRamMap
= AllocatePool (VariableDefinition
->VariableSize
);
1146 ASSERT (TmpNvRamMap
!= NULL
);
1148 Count
= VariableDefinition
->VariableSize
;
1150 if ((FormCallback
!= NULL
) && (FormCallback
->NvRead
!= NULL
)) {
1151 Status
= FormCallback
->NvRead (
1153 VariableDefinition
->VariableName
,
1154 &VariableDefinition
->Guid
,
1157 (VOID
*) TmpNvRamMap
1160 Status
= gRT
->GetVariable (
1161 VariableDefinition
->VariableName
,
1162 &VariableDefinition
->Guid
,
1165 (VOID
*) TmpNvRamMap
1169 CopyMem (&VariableDefinition
->NvRamMap
[Tag
->StorageStart
], StringPtr
, Tag
->StorageWidth
);
1170 CopyMem (&TmpNvRamMap
[Tag
->StorageStart
], StringPtr
, Tag
->StorageWidth
);
1172 if ((FormCallback
!= NULL
) && (FormCallback
->NvWrite
!= NULL
)) {
1173 Status
= FormCallback
->NvWrite (
1175 VariableDefinition
->VariableName
,
1176 &VariableDefinition
->Guid
,
1177 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1178 VariableDefinition
->VariableSize
,
1179 (VOID
*) TmpNvRamMap
,
1183 Status
= gRT
->SetVariable (
1184 VariableDefinition
->VariableName
,
1185 &VariableDefinition
->Guid
,
1186 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1187 VariableDefinition
->VariableSize
,
1188 (VOID
*) TmpNvRamMap
1192 gBS
->FreePool (TmpNvRamMap
);
1193 gBS
->FreePool (StringPtr
);
1206 IN CHAR16
*StringPtr
,
1207 OUT CHAR16
**FormattedString
,
1214 UINTN PrevSearchIndex
;
1220 CurrIndex
= gHelpBlockWidth
- 1;
1222 if (*FormattedString
!= NULL
) {
1223 gBS
->FreePool (*FormattedString
);
1224 *FormattedString
= NULL
;
1227 for (; CurrIndex
> PrevIndex
; CurrIndex
--) {
1229 // In the case where the string ended and a new one is immediately after it
1230 // we need to check for the null-terminator and reset the CurrIndex
1232 SearchIndex
= CurrIndex
;
1233 PrevSearchIndex
= PrevIndex
;
1235 for (; SearchIndex
> PrevSearchIndex
; PrevSearchIndex
++) {
1236 if ((StringPtr
[PrevSearchIndex
] == CHAR_NULL
) || (StringPtr
[PrevSearchIndex
] == CHAR_LINEFEED
)) {
1237 CurrIndex
= PrevSearchIndex
;
1241 if (StringPtr
[PrevSearchIndex
] == CHAR_CARRIAGE_RETURN
) {
1242 if (StringPtr
[PrevSearchIndex
+ 1] == CHAR_LINEFEED
) {
1244 // Found a "\n",advance to the next new line.
1246 CurrIndex
= PrevSearchIndex
+ 1;
1250 // Found a "\r",return to the start of the current line.
1252 PrevIndex
= PrevSearchIndex
+ 1;
1253 CurrIndex
= PrevSearchIndex
+ gHelpBlockWidth
;
1260 // End of the string, thus stop counting.
1262 if (StringPtr
[CurrIndex
] == CHAR_NULL
) {
1267 // The premise is that for every HELP_BLOCK_WIDTH we rewind
1268 // until we find the first space. That is the delimiter for
1269 // the string, and we will then advance our CurrIndex another
1270 // HELP_BLOCK_WIDTH and continue the process breaking the larger
1271 // string into chunks that fit within the HELP_BLOCK_WIDTH requirements.
1273 if (StringPtr
[CurrIndex
] == CHAR_SPACE
) {
1275 // How many strings have been found?
1278 PrevIndex
= CurrIndex
+ 1;
1279 CurrIndex
= CurrIndex
+ gHelpBlockWidth
;
1282 // Found a Linefeed, advance to the next line.
1284 if (StringPtr
[CurrIndex
] == CHAR_LINEFEED
) {
1286 PrevIndex
= CurrIndex
+ 1;
1287 CurrIndex
= CurrIndex
+ gHelpBlockWidth
;
1293 // Round the value up one (doesn't hurt)
1298 // Determine the number of pages this help string occupies
1300 PageCount
= StringCount
/ RowCount
;
1301 if (StringCount
% RowCount
> 0) {
1305 // Convert the PageCount into lines so we can allocate the correct buffer size
1307 StringCount
= PageCount
* RowCount
;
1310 // We now know how many strings we will have, so we can allocate the
1311 // space required for the array or strings.
1313 *FormattedString
= AllocateZeroPool ((StringCount
) * (gHelpBlockWidth
+ 1) * 2);
1314 ASSERT (*FormattedString
);
1318 CurrIndex
= gHelpBlockWidth
- 1;
1320 for (; CurrIndex
> PrevIndex
; CurrIndex
--) {
1322 // In the case where the string ended and a new one is immediately after it
1323 // we need to check for the null-terminator and reset the CurrIndex
1325 SearchIndex
= CurrIndex
;
1326 PrevSearchIndex
= PrevIndex
;
1328 for (; SearchIndex
> PrevSearchIndex
; PrevSearchIndex
++) {
1329 if ((StringPtr
[PrevSearchIndex
] == CHAR_NULL
) || (StringPtr
[PrevSearchIndex
] == CHAR_LINEFEED
)) {
1330 CurrIndex
= PrevSearchIndex
;
1334 if (StringPtr
[PrevSearchIndex
] == CHAR_CARRIAGE_RETURN
) {
1335 if (StringPtr
[PrevSearchIndex
+ 1] == CHAR_LINEFEED
) {
1337 // Found a "\n",advance to the next new line.
1339 CurrIndex
= PrevSearchIndex
+ 1;
1343 // Found a "\r",return to the start of the current line.
1345 PrevIndex
= PrevSearchIndex
+ 1;
1346 CurrIndex
= PrevSearchIndex
+ gHelpBlockWidth
;
1353 // End of the string, thus stop counting.
1355 if (StringPtr
[CurrIndex
] == CHAR_NULL
) {
1357 // Copy the fragment to the FormattedString buffer
1359 StrnCpy ((FormattedString
[0] + StringCount
* gHelpBlockWidth
), &StringPtr
[PrevIndex
], CurrIndex
- PrevIndex
);
1364 // The premise is that for every HELP_BLOCK_WIDTH we rewind
1365 // until we find the first space. That is the delimiter for
1366 // the string, and we will then advance our CurrIndex another
1367 // HELP_BLOCK_WIDTH and continue the process breaking the larger
1368 // string into chunks that fit within the HELP_BLOCK_WIDTH requirements.
1370 if (StringPtr
[CurrIndex
] == CHAR_SPACE
) {
1372 // Copy the fragment to the FormattedString buffer
1374 StrnCpy ((FormattedString
[0] + StringCount
* gHelpBlockWidth
), &StringPtr
[PrevIndex
], CurrIndex
- PrevIndex
);
1376 PrevIndex
= CurrIndex
+ 1;
1377 CurrIndex
= CurrIndex
+ gHelpBlockWidth
;
1380 // Found a LineFeed, advance to the next line.
1382 if (StringPtr
[CurrIndex
] == CHAR_LINEFEED
) {
1383 StringPtr
[CurrIndex
] = CHAR_SPACE
;
1385 // "\n" is represented as CHAR_CARRIAGE_RETURN + CHAR_LINEFEED,check this.
1387 if (StringPtr
[CurrIndex
- 1] == CHAR_CARRIAGE_RETURN
) {
1388 StringPtr
[CurrIndex
- 1] = CHAR_SPACE
;
1391 StrnCpy ((FormattedString
[0] + StringCount
* gHelpBlockWidth
), &StringPtr
[PrevIndex
], CurrIndex
- PrevIndex
);
1393 PrevIndex
= CurrIndex
+ 1;
1394 CurrIndex
= CurrIndex
+ gHelpBlockWidth
;
1406 IN EFI_TAG
*TargetTag
,
1408 EFI_VARIABLE_DEFINITION
*VariableDefinitionsHead
1412 CHAR16
*VariableName
;
1414 EFI_VARIABLE_DEFINITION
*VariableDefinitions
;
1415 EFI_VARIABLE_DEFINITION
*PreviousVariableDefinitions
;
1416 STATIC UINT16 VariableSize
;
1418 STATIC UINT16 CurrentVariable
;
1419 STATIC UINT16 CurrentVariable2
;
1423 case EFI_IFR_FORM_OP
:
1424 CopyMem (&TargetTag
->Id
, &((EFI_IFR_FORM
*) FormData
)->FormId
, sizeof (UINT16
));
1425 CopyMem (&TargetTag
->Text
, &((EFI_IFR_FORM
*) FormData
)->FormTitle
, sizeof (UINT16
));
1426 TargetTag
->VariableNumber
= CurrentVariable
;
1427 if (VariableDefinitionsHead
!= NULL
) {
1428 VariableName
= AllocateZeroPool (12);
1429 ASSERT (VariableName
!= NULL
);
1430 CopyMem (VariableName
, L
"Setup", 12);
1431 VariableDefinitionsHead
->VariableName
= VariableName
;
1432 VariableDefinitionsHead
->VariableSize
= VariableSize
;
1433 CopyMem (&VariableDefinitionsHead
->Guid
, &Guid
, sizeof (EFI_GUID
));
1437 case EFI_IFR_SUBTITLE_OP
:
1438 TargetTag
->NumberOfLines
= 1;
1439 CopyMem (&TargetTag
->Text
, &((EFI_IFR_SUBTITLE
*) FormData
)->SubTitle
, sizeof (UINT16
));
1440 TargetTag
->VariableNumber
= CurrentVariable
;
1443 case EFI_IFR_TEXT_OP
:
1444 TargetTag
->NumberOfLines
= 1;
1445 CopyMem (&TargetTag
->Text
, &((EFI_IFR_TEXT
*) FormData
)->Text
, sizeof (UINT16
));
1446 CopyMem (&TargetTag
->Help
, &((EFI_IFR_TEXT
*) FormData
)->Help
, sizeof (UINT16
));
1447 TargetTag
->VariableNumber
= CurrentVariable
;
1450 // To optimize the encoding size, certain opcodes have optional fields such as those
1451 // inside the if() statement. If the encoded length is the complete size, then we
1452 // know we have valid data encoded that we want to integrate
1454 if (((EFI_IFR_TEXT
*) FormData
)->Header
.Length
== sizeof (EFI_IFR_TEXT
)) {
1456 // Text has no help associated with it, but in case there is a second entry due to
1457 // dynamic/interactive flags being active, bring this data over.
1459 CopyMem (&TargetTag
->TextTwo
, &((EFI_IFR_TEXT
*) FormData
)->TextTwo
, sizeof (UINT16
));
1460 TargetTag
->Flags
= ((EFI_IFR_TEXT
*) FormData
)->Flags
;
1461 CopyMem (&TargetTag
->Key
, &((EFI_IFR_TEXT
*) FormData
)->Key
, sizeof (UINT16
));
1465 case EFI_IFR_ONE_OF_OPTION_OP
:
1466 CopyMem (&TargetTag
->Text
, &((EFI_IFR_ONE_OF_OPTION
*) FormData
)->Option
, sizeof (UINT16
));
1467 CopyMem (&TargetTag
->Value
, &((EFI_IFR_ONE_OF_OPTION
*) FormData
)->Value
, sizeof (UINT16
));
1468 TargetTag
->Flags
= ((EFI_IFR_ONE_OF_OPTION
*) FormData
)->Flags
;
1469 CopyMem (&TargetTag
->Key
, &((EFI_IFR_ONE_OF_OPTION
*) FormData
)->Key
, sizeof (UINT16
));
1470 TargetTag
->VariableNumber
= CurrentVariable
;
1473 case EFI_IFR_CHECKBOX_OP
:
1474 TargetTag
->Flags
= ((EFI_IFR_CHECKBOX
*) FormData
)->Flags
;
1475 TargetTag
->ResetRequired
= (BOOLEAN
) (TargetTag
->Flags
& EFI_IFR_FLAG_RESET_REQUIRED
);
1476 CopyMem (&TargetTag
->Key
, &((EFI_IFR_CHECKBOX
*) FormData
)->Key
, sizeof (UINT16
));
1477 TargetTag
->VariableNumber
= CurrentVariable
;
1480 case EFI_IFR_NUMERIC_OP
:
1481 TargetTag
->Flags
= ((EFI_IFR_NUMERIC
*) FormData
)->Flags
;
1482 CopyMem (&TargetTag
->Key
, &((EFI_IFR_NUMERIC
*) FormData
)->Key
, sizeof (UINT16
));
1483 TargetTag
->VariableNumber
= CurrentVariable
;
1486 case EFI_IFR_STRING_OP
:
1488 CopyMem (&TempValue
, &((EFI_IFR_STRING
*) FormData
)->MinSize
, sizeof (UINT8
));
1489 TempValue
= (UINT16
) (TempValue
* 2);
1490 CopyMem (&TargetTag
->Minimum
, &TempValue
, sizeof (UINT16
));
1492 CopyMem (&TempValue
, &((EFI_IFR_STRING
*) FormData
)->MaxSize
, sizeof (UINT8
));
1493 TempValue
= (UINT16
) (TempValue
* 2);
1494 CopyMem (&TargetTag
->Maximum
, &TempValue
, sizeof (UINT16
));
1495 CopyMem (&TargetTag
->StorageWidth
, &TempValue
, sizeof (UINT16
));
1496 TargetTag
->Flags
= (UINT8
) (((EFI_IFR_STRING
*) FormData
)->Flags
);
1497 TargetTag
->ResetRequired
= (BOOLEAN
) (TargetTag
->Flags
& EFI_IFR_FLAG_RESET_REQUIRED
);
1498 CopyMem (&TargetTag
->Key
, &((EFI_IFR_STRING
*) FormData
)->Key
, sizeof (UINT16
));
1499 TargetTag
->VariableNumber
= CurrentVariable
;
1502 case EFI_IFR_PASSWORD_OP
:
1504 CopyMem (&TempValue
, &((EFI_IFR_PASSWORD
*) FormData
)->MinSize
, sizeof (UINT8
));
1505 TempValue
= (UINT16
) (TempValue
* 2);
1506 CopyMem (&TargetTag
->Minimum
, &TempValue
, sizeof (UINT16
));
1508 CopyMem (&TempValue
, &((EFI_IFR_PASSWORD
*) FormData
)->MaxSize
, sizeof (UINT8
));
1509 TempValue
= (UINT16
) (TempValue
* 2);
1510 CopyMem (&TargetTag
->Maximum
, &TempValue
, sizeof (UINT16
));
1511 CopyMem (&TargetTag
->StorageWidth
, &TempValue
, sizeof (UINT16
));
1512 TargetTag
->Flags
= ((EFI_IFR_PASSWORD
*) FormData
)->Flags
;
1513 TargetTag
->ResetRequired
= (BOOLEAN
) (TargetTag
->Flags
& EFI_IFR_FLAG_RESET_REQUIRED
);
1514 CopyMem (&TargetTag
->Key
, &((EFI_IFR_PASSWORD
*) FormData
)->Key
, sizeof (UINT16
));
1515 CopyMem (&TargetTag
->Encoding
, &((EFI_IFR_PASSWORD
*) FormData
)->Encoding
, sizeof (UINT16
));
1516 TargetTag
->VariableNumber
= CurrentVariable
;
1519 case EFI_IFR_VARSTORE_OP
:
1521 // It should NEVER be NULL
1523 if (VariableDefinitionsHead
== NULL
) {
1527 VariableDefinitions
= VariableDefinitionsHead
;
1530 // Advance VariableDefinitions to the last entry
1532 for (; VariableDefinitions
!= NULL
; VariableDefinitions
= VariableDefinitions
->Next
) {
1533 PreviousVariableDefinitions
= VariableDefinitions
;
1535 // If there is a variable with this GUID and ID already, we need to bail out
1537 if (!CompareMem (&VariableDefinitions
->Guid
, &((EFI_IFR_VARSTORE
*) FormData
)->Guid
, sizeof (EFI_GUID
)) &&
1538 !CompareMem (&VariableDefinitions
->VariableId
, &((EFI_IFR_VARSTORE
*) FormData
)->VarId
, sizeof (UINT16
))
1543 if (VariableDefinitions
->Next
== NULL
) {
1548 // If the last entry has a variable in it already, allocate a new entry and use it
1550 if (VariableDefinitions
->VariableName
!= NULL
) {
1551 VariableDefinitions
->Next
= AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION
));
1552 ASSERT (VariableDefinitions
->Next
!= NULL
);
1553 PreviousVariableDefinitions
= VariableDefinitions
;
1554 VariableDefinitions
= VariableDefinitions
->Next
;
1555 VariableDefinitions
->Previous
= PreviousVariableDefinitions
;
1558 // Copy the Variable data to our linked list
1560 CopyMem (&VariableDefinitions
->VariableId
, &((EFI_IFR_VARSTORE
*) FormData
)->VarId
, sizeof (UINT16
));
1561 CopyMem (&VariableDefinitions
->VariableSize
, &((EFI_IFR_VARSTORE
*) FormData
)->Size
, sizeof (UINT16
));
1562 CopyMem (&VariableDefinitions
->Guid
, &((EFI_IFR_VARSTORE
*) FormData
)->Guid
, sizeof (EFI_GUID
));
1565 // The ASCII String which is immediately past the EFI_IFR_VARSTORE is inferred by the structure definition
1566 // due to it being variable sized. There are rules preventing it from being > 40 characters long and should
1567 // be enforced by the compiler.
1569 AsciiString
= (CHAR8
*) (&((EFI_IFR_VARSTORE
*) FormData
)->Size
);
1570 AsciiString
= AsciiString
+ 2;
1571 VariableDefinitions
->VariableName
= AllocateZeroPool ((AsciiStrLen (AsciiString
) + 1) * 2);
1572 ASSERT (VariableDefinitions
->VariableName
!= NULL
);
1573 for (Index
= 0; AsciiString
[Index
] != 0; Index
++) {
1574 VariableDefinitions
->VariableName
[Index
] = (CHAR16
) AsciiString
[Index
];
1577 VariableDefinitions
->VariableName
[Index
] = 0;
1580 // Propogate the tag information for this op-code
1582 CopyMem (&TargetTag
->VariableNumber
, &((EFI_IFR_VARSTORE
*) FormData
)->VarId
, sizeof (UINT16
));
1583 CopyMem (&TargetTag
->GuidValue
, &((EFI_IFR_VARSTORE
*) FormData
)->Guid
, sizeof (EFI_GUID
));
1584 CopyMem (&TargetTag
->StorageWidth
, &((EFI_IFR_VARSTORE
*) FormData
)->Size
, sizeof (UINT16
));
1585 CopyMem (&TargetTag
->Maximum
, &((EFI_IFR_VARSTORE
*) FormData
)->Size
, sizeof (UINT16
));
1588 case EFI_IFR_VARSTORE_SELECT_OP
:
1589 CopyMem (&TargetTag
->VariableNumber
, &((EFI_IFR_VARSTORE_SELECT
*) FormData
)->VarId
, sizeof (UINT16
));
1590 CopyMem (&CurrentVariable
, &((EFI_IFR_VARSTORE_SELECT
*) FormData
)->VarId
, sizeof (UINT16
));
1591 CurrentVariable2
= CurrentVariable
;
1594 case EFI_IFR_VARSTORE_SELECT_PAIR_OP
:
1595 CopyMem (&TargetTag
->VariableNumber
, &((EFI_IFR_VARSTORE_SELECT_PAIR
*) FormData
)->VarId
, sizeof (UINT16
));
1597 &TargetTag
->VariableNumber2
,
1598 &((EFI_IFR_VARSTORE_SELECT_PAIR
*) FormData
)->SecondaryVarId
,
1601 CopyMem (&CurrentVariable
, &((EFI_IFR_VARSTORE_SELECT_PAIR
*) FormData
)->VarId
, sizeof (UINT16
));
1602 CopyMem (&CurrentVariable2
, &((EFI_IFR_VARSTORE_SELECT_PAIR
*) FormData
)->SecondaryVarId
, sizeof (UINT16
));
1605 case EFI_IFR_REF_OP
:
1606 TargetTag
->NumberOfLines
= 1;
1607 CopyMem (&TargetTag
->Id
, &((EFI_IFR_REF
*) FormData
)->FormId
, sizeof (UINT16
));
1608 CopyMem (&TargetTag
->Key
, &((EFI_IFR_REF
*) FormData
)->Key
, sizeof (UINT16
));
1609 CopyMem (&TargetTag
->Text
, &((EFI_IFR_REF
*) FormData
)->Prompt
, sizeof (UINT16
));
1610 CopyMem (&TargetTag
->Help
, &((EFI_IFR_REF
*) FormData
)->Help
, sizeof (UINT16
));
1611 TargetTag
->Flags
= ((EFI_IFR_REF
*) FormData
)->Flags
;
1612 TargetTag
->VariableNumber
= CurrentVariable
;
1615 case EFI_IFR_EQ_ID_VAL_OP
:
1616 CopyMem (&TargetTag
->Value
, &((EFI_IFR_EQ_ID_VAL
*) FormData
)->Value
, sizeof (UINT16
));
1617 CopyMem (&TargetTag
->Id
, &((EFI_IFR_EQ_ID_VAL
*) FormData
)->QuestionId
, sizeof (UINT16
));
1618 TargetTag
->StorageWidth
= ((EFI_IFR_EQ_ID_VAL
*) FormData
)->Width
;
1619 TargetTag
->VariableNumber
= CurrentVariable
;
1622 case EFI_IFR_EQ_VAR_VAL_OP
:
1623 CopyMem (&TargetTag
->Value
, &((EFI_IFR_EQ_VAR_VAL
*) FormData
)->Value
, sizeof (UINT16
));
1624 CopyMem (&TargetTag
->Id
, &((EFI_IFR_EQ_VAR_VAL
*) FormData
)->VariableId
, sizeof (UINT16
));
1625 TargetTag
->VariableNumber
= CurrentVariable
;
1628 case EFI_IFR_EQ_ID_ID_OP
:
1629 CopyMem (&TargetTag
->Id
, &((EFI_IFR_EQ_ID_ID
*) FormData
)->QuestionId1
, sizeof (UINT16
));
1630 CopyMem (&TargetTag
->Id2
, &((EFI_IFR_EQ_ID_ID
*) FormData
)->QuestionId2
, sizeof (UINT16
));
1631 TargetTag
->StorageWidth
= ((EFI_IFR_EQ_ID_ID
*) FormData
)->Width
;
1632 TargetTag
->VariableNumber
= CurrentVariable
;
1633 TargetTag
->VariableNumber
= CurrentVariable2
;
1636 case EFI_IFR_EQ_ID_LIST_OP
:
1637 CopyMem (&TargetTag
->Id
, &((EFI_IFR_EQ_ID_LIST
*) FormData
)->QuestionId
, sizeof (UINT16
));
1638 CopyMem (&TargetTag
->Id2
, &((EFI_IFR_EQ_ID_LIST
*) FormData
)->ListLength
, sizeof (UINT16
));
1639 TargetTag
->StorageWidth
= ((EFI_IFR_EQ_ID_LIST
*) FormData
)->Width
;
1641 TargetTag
->IntList
= AllocateZeroPool (TargetTag
->Id2
* sizeof (UINT16
));
1642 ASSERT (TargetTag
->IntList
);
1644 for (TempValue
= 0; TempValue
< TargetTag
->Id2
; TempValue
++) {
1646 &TargetTag
->IntList
[TempValue
],
1647 &((EFI_IFR_EQ_ID_LIST
*) FormData
)->ValueList
[TempValue
],
1652 TargetTag
->VariableNumber
= CurrentVariable
;
1655 case EFI_IFR_FORM_SET_OP
:
1656 CopyMem (&VariableSize
, &((EFI_IFR_FORM_SET
*) FormData
)->NvDataSize
, sizeof (UINT16
));
1657 CopyMem (&Guid
, &((EFI_IFR_FORM_SET
*) FormData
)->Guid
, sizeof (EFI_GUID
));
1659 // If there is a size specified in the formste, we will establish a "default" variable
1661 if (VariableDefinitionsHead
!= NULL
) {
1662 VariableName
= AllocateZeroPool (12);
1663 ASSERT (VariableName
!= NULL
);
1664 CopyMem (VariableName
, L
"Setup", 12);
1665 VariableDefinitionsHead
->VariableName
= VariableName
;
1666 VariableDefinitionsHead
->VariableSize
= VariableSize
;
1667 CopyMem (&VariableDefinitionsHead
->Guid
, &Guid
, sizeof (EFI_GUID
));
1671 case EFI_IFR_END_FORM_SET_OP
:
1672 CurrentVariable
= 0;
1673 CurrentVariable2
= 0;