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
);
82 IN EFI_FILE_FORM_TAGS
*FileFormTags
,
83 IN UI_MENU_OPTION
*MenuOption
90 EFI_VARIABLE_DEFINITION
*VariableDefinition
;
94 SizeRequired
= MenuOption
->ThisTag
->StorageStart
+ MenuOption
->ThisTag
->StorageWidth
;
96 ExtractRequestedNvMap (FileFormTags
, MenuOption
->Tags
->VariableNumber
, &VariableDefinition
);
99 // We arrived here because the current NvRamMap is too small for the new op-code to store things and
100 // we need to adjust the buffer to support this.
102 NvRamMap
= AllocateZeroPool (SizeRequired
+ 1);
103 ASSERT (NvRamMap
!= NULL
);
106 // Copy current NvRamMap to the new NvRamMap
108 CopyMem (NvRamMap
, VariableDefinition
->NvRamMap
, VariableDefinition
->VariableFakeSize
);
111 // Remember, the only time we come here is because we are in the NVPlus section of the NvRamMap
113 for (Index
= MenuOption
->TagIndex
;
114 (MenuOption
->Tags
[Index
].Operand
!= EFI_IFR_END_FORM_OP
) && (MenuOption
->Tags
[Index
].Operand
!= EFI_IFR_END_ONE_OF_OP
);
118 switch (MenuOption
->Tags
[Index
].Operand
) {
119 case EFI_IFR_ORDERED_LIST_OP
:
120 case EFI_IFR_ONE_OF_OP
:
121 CachedStart
= MenuOption
->Tags
[Index
].StorageStart
;
124 case EFI_IFR_ONE_OF_OPTION_OP
:
125 if (MenuOption
->Tags
[Index
].Flags
& EFI_IFR_FLAG_DEFAULT
) {
126 CopyMem (&NvRamMap
[CachedStart
], &MenuOption
->Tags
[Index
].Value
, 2);
130 case EFI_IFR_CHECKBOX_OP
:
131 CopyMem (&NvRamMap
[MenuOption
->Tags
[Index
].StorageStart
], &MenuOption
->Tags
[Index
].Flags
, 1);
134 case EFI_IFR_NUMERIC_OP
:
135 case EFI_IFR_DATE_OP
:
136 case EFI_IFR_TIME_OP
:
137 case EFI_IFR_STRING_OP
:
138 case EFI_IFR_PASSWORD_OP
:
140 &NvRamMap
[MenuOption
->Tags
[Index
].StorageStart
],
141 &MenuOption
->Tags
[Index
].Value
,
142 MenuOption
->Tags
[Index
].StorageWidth
149 gBS
->FreePool (VariableDefinition
->NvRamMap
);
150 VariableDefinition
->NvRamMap
= NvRamMap
;
151 VariableDefinition
->VariableFakeSize
= (UINT16
) SizeRequired
;
156 IN UI_MENU_OPTION
*MenuOption
,
158 IN EFI_FILE_FORM_TAGS
*FileFormTagsHead
,
159 IN EFI_IFR_DATA_ARRAY
*PageData
,
160 OUT CHAR16
**OptionString
167 EFI_FILE_FORM_TAGS
*FileFormTags
;
169 CHAR16 FormattedNumber
[6];
180 EFI_FORM_CALLBACK_PROTOCOL
*FormCallback
;
182 CHAR16 NullCharacter
;
184 EFI_VARIABLE_DEFINITION
*VariableDefinition
;
190 FileFormTags
= FileFormTagsHead
;
192 for (Index
= 0; Index
< MenuOption
->IfrNumber
; Index
++) {
193 FileFormTags
= FileFormTags
->NextFile
;
199 VariableDefinition
= NULL
;
202 ZeroMem (&Time
, sizeof (EFI_TIME
));
204 StringPtr
= (CHAR16
*) L
"\0";
205 Tag
= MenuOption
->ThisTag
;
206 ExtractRequestedNvMap (FileFormTags
, Tag
->VariableNumber
, &VariableDefinition
);
208 if (Tag
->StorageStart
> VariableDefinition
->VariableSize
) {
209 NvRamMap
= (UINT16
*) &VariableDefinition
->FakeNvRamMap
[Tag
->StorageStart
];
211 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
218 NullCharacter
= CHAR_NULL
;
221 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_ORDERED_LIST_OP
) {
223 if (((UINT8
*) NvRamMap
)[0] != 0x00) {
228 ZeroMem (FormattedNumber
, 12);
230 Status
= gBS
->HandleProtocol (
231 (VOID
*) (UINTN
) FileFormTags
->FormTags
.Tags
[0].CallbackHandle
,
232 &gEfiFormCallbackProtocolGuid
,
233 (VOID
**) &FormCallback
236 if (*OptionString
!= NULL
) {
237 gBS
->FreePool (*OptionString
);
238 *OptionString
= NULL
;
241 switch (Tag
->Operand
) {
243 case EFI_IFR_ORDERED_LIST_OP
:
244 case EFI_IFR_ONE_OF_OP
:
246 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
247 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
248 // the NvMap so that we can properly display the information
250 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
251 AdjustNvMap (FileFormTags
, MenuOption
);
252 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
255 CachedIndex
= MenuOption
->TagIndex
;
258 // search for EFI_IFR_ONE_OF_OPTION_OP until you hit the EFI_IFR_END_ONE_OF_OP,
259 // each of the .Text in the options are going to be what gets displayed. Break each into 26 char chunks
260 // when hit right/left arrow allows for selection - then repopulate Tag[TagIndex] with the choice
262 for (Index
= MenuOption
->TagIndex
; MenuOption
->Tags
[Index
].Operand
!= EFI_IFR_END_ONE_OF_OP
; Index
++) {
264 // We found an option - which assumedly has a string. We will eventually have to support
265 // wrapping of strings. For now, let's pretend they don't wrap and code that up.
267 // Count how many strings there are
269 if (MenuOption
->Tags
[Index
].Operand
== EFI_IFR_ONE_OF_OPTION_OP
) {
271 // If one of the options for the one-of has an interactive flag, back-define the oneof to have one too
273 if (MenuOption
->Tags
[Index
].Flags
& EFI_IFR_FLAG_INTERACTIVE
) {
274 MenuOption
->Tags
[CachedIndex
].Flags
= (UINT8
) (MenuOption
->Tags
[CachedIndex
].Flags
| EFI_IFR_FLAG_INTERACTIVE
);
281 // We now know how many strings we will have, so we can allocate the
282 // space required for the array or strings.
284 *OptionString
= AllocateZeroPool (StringCount
* (gOptionBlockWidth
+ 1) * 2 * gScreenDimensions
.BottomRow
);
285 ASSERT (*OptionString
);
288 // Add left delimeter to string
290 *OptionString
[0] = LEFT_ONEOF_DELIMITER
;
293 // Retrieve the current OneOf value
297 // Auto selection from list
301 // Copy current setting to the seed Value
303 if (Tag
->Operand
== EFI_IFR_ORDERED_LIST_OP
) {
304 ValueArray
= AllocateZeroPool (MenuOption
->ThisTag
->StorageWidth
);
305 ASSERT (ValueArray
!= NULL
);
306 CopyMem (ValueArray
, NvRamMap
, MenuOption
->ThisTag
->StorageWidth
);
308 CopyMem (&Value
, NvRamMap
, MenuOption
->ThisTag
->StorageWidth
);
309 CopyMem (gPreviousValue
, NvRamMap
, MenuOption
->ThisTag
->StorageWidth
);
313 if (Tag
->Operand
== EFI_IFR_ORDERED_LIST_OP
) {
314 Status
= GetSelectionInputPopUp (MenuOption
, Tag
, MenuOption
->ThisTag
->StorageWidth
, ValueArray
, &KeyValue
);
316 Status
= GetSelectionInputPopUp (MenuOption
, Tag
, 1, &Value
, &KeyValue
);
319 if (!EFI_ERROR (Status
)) {
320 if (Tag
->Operand
== EFI_IFR_ORDERED_LIST_OP
) {
321 CopyMem (NvRamMap
, ValueArray
, MenuOption
->ThisTag
->StorageWidth
);
322 gBS
->FreePool (ValueArray
);
325 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
327 CopyMem (NvRamMap
, &Value
, Tag
->StorageWidth
);
328 MenuOption
->ThisTag
->Key
= KeyValue
;
331 // If a late check is required save off the information. This is used when consistency checks
332 // are required, but certain values might be bound by an impossible consistency check such as
333 // if two questions are bound by consistency checks and each only has two possible choices, there
334 // would be no way for a user to switch the values. Thus we require late checking.
336 if (Tag
->Flags
& EFI_IFR_FLAG_LATE_CHECK
) {
337 CopyMem (&Tag
->OldValue
, &Value
, Tag
->StorageWidth
);
340 // In theory, passing the value and the Id are sufficient to determine what needs
341 // to be done. The Id is the key to look for the entry needed in the Inconsistency
342 // database. That will yields operand and ID data - and since the ID's correspond
343 // to the NV storage, we can determine the values for other IDs there.
345 if (ValueIsNotValid (TRUE
, 0, Tag
, FileFormTags
, &PopUp
)) {
346 if (PopUp
== 0x0000) {
350 if (!Tag
->Suppress
&& !Tag
->GrayOut
) {
351 CopyMem (NvRamMap
, &Number
, MenuOption
->ThisTag
->StorageWidth
);
356 StringPtr
= GetToken (PopUp
, MenuOption
->Handle
);
358 CreatePopUp (GetStringWidth (StringPtr
) / 2, 3, &NullCharacter
, StringPtr
, &NullCharacter
);
361 Status
= WaitForKeyStroke (&Key
);
363 switch (Key
.UnicodeChar
) {
365 case CHAR_CARRIAGE_RETURN
:
367 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
369 CopyMem (NvRamMap
, &Number
, MenuOption
->ThisTag
->StorageWidth
);
370 gBS
->FreePool (StringPtr
);
376 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
380 UpdateStatusBar (NV_UPDATE_REQUIRED
, Tag
->Flags
, TRUE
);
382 if (Tag
->Operand
== EFI_IFR_ORDERED_LIST_OP
) {
383 gBS
->FreePool (ValueArray
);
389 for (Index
= MenuOption
->TagIndex
; MenuOption
->Tags
[Index
].Operand
!= EFI_IFR_END_ONE_OF_OP
; Index
++) {
391 // We found an option - which assumedly has a string. We will eventually have to support
392 // wrapping of strings. For now, let's pretend they don't wrap and code that up.
394 if (MenuOption
->Tags
[Index
].Operand
== EFI_IFR_ONE_OF_OPTION_OP
) {
398 // If the first entry is invalid, then the "default" settings are based on what is reflected
399 // in the order of the op-codes
401 ((UINT8
*) NvRamMap
)[Index
- MenuOption
->TagIndex
- 1] = (UINT8
) MenuOption
->Tags
[Index
].Value
;
404 // Only display 3 lines of stuff at most
406 if ((Index
- MenuOption
->TagIndex
) > ORDERED_LIST_SIZE
) {
410 if (((Index
- MenuOption
->TagIndex
) != 1) && !Skip
) {
411 Character
[0] = LEFT_ONEOF_DELIMITER
;
412 NewStrCat (OptionString
[0], Character
);
415 MenuOption
->ThisTag
->NumberOfLines
= (UINT16
) (Index
- MenuOption
->TagIndex
);
417 StringPtr
= GetToken (MenuOption
->Tags
[Index
].Text
, MenuOption
->Handle
);
419 for (Value
= (UINT16
) (MenuOption
->TagIndex
+ 1);
420 MenuOption
->Tags
[Value
].Operand
!= EFI_IFR_END_ONE_OF_OP
;
423 if (MenuOption
->Tags
[Value
].Value
== ((UINT8
*) NvRamMap
)[Index
- MenuOption
->TagIndex
- 1]) {
424 StringPtr
= GetToken (MenuOption
->Tags
[Value
].Text
, MenuOption
->Handle
);
429 if (MenuOption
->Tags
[Value
].Operand
== EFI_IFR_END_ONE_OF_OP
) {
436 NewStrCat (OptionString
[0], StringPtr
);
437 Character
[0] = RIGHT_ONEOF_DELIMITER
;
438 NewStrCat (OptionString
[0], Character
);
439 Character
[0] = CHAR_CARRIAGE_RETURN
;
440 NewStrCat (OptionString
[0], Character
);
443 // Remove Buffer allocated for StringPtr after it has been used.
445 gBS
->FreePool (StringPtr
);
448 // The option value is the same as what is stored in NV store. Print this.
450 if (!CompareMem (&(MenuOption
->Tags
[Index
].Value
), NvRamMap
, MenuOption
->ThisTag
->StorageWidth
)) {
451 StringPtr
= GetToken (MenuOption
->Tags
[Index
].Text
, MenuOption
->Handle
);
452 NewStrCat (OptionString
[0], StringPtr
);
453 Character
[0] = RIGHT_ONEOF_DELIMITER
;
454 NewStrCat (OptionString
[0], Character
);
456 // Remove Buffer allocated for StringPtr after it has been used.
458 gBS
->FreePool (StringPtr
);
463 if ((MenuOption
->Tags
[Index
].Flags
& EFI_IFR_FLAG_DEFAULT
) == 1) {
464 Default
= MenuOption
->Tags
[Index
].Text
;
465 Value
= MenuOption
->Tags
[Index
].Value
;
471 // We didn't find a value that matched a setting in the NVRAM Map - display default - set default
475 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
477 CopyMem (NvRamMap
, &Value
, MenuOption
->ThisTag
->StorageWidth
);
479 StringPtr
= GetToken ((UINT16
) Default
, MenuOption
->Handle
);
480 NewStrCat (OptionString
[0], StringPtr
);
481 Character
[0] = RIGHT_ONEOF_DELIMITER
;
482 NewStrCat (OptionString
[0], Character
);
484 // Remove Buffer allocated for StringPtr after it has been used.
486 gBS
->FreePool (StringPtr
);
491 case EFI_IFR_CHECKBOX_OP
:
493 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
494 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
495 // the NvMap so that we can properly display the information
497 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
498 AdjustNvMap (FileFormTags
, MenuOption
);
499 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
502 Default
= Tag
->Flags
& 1;
504 // If hit spacebar, set or unset Tag[TagIndex].Flags based on it's previous value - BOOLEAN
506 *OptionString
= AllocateZeroPool ((gOptionBlockWidth
+ 1) * 2 * gScreenDimensions
.BottomRow
);
507 ASSERT (*OptionString
);
510 // Since Checkboxes are BOOLEAN values, bit 0 of the Flags bit defines the default option, therefore, if
511 // the default option (only one option for checkboxes) is on, then the default value is on. Tag.Default is not
512 // an active field for Checkboxes.
514 StrnCpy (OptionString
[0], (CHAR16
*) LEFT_CHECKBOX_DELIMITER
, 1);
517 // Since this is a BOOLEAN operation, flip bit 0 upon selection
520 Tag
->Value
= (UINT16
) (Tag
->Value
^ 1);
521 *(UINT8
*) NvRamMap
= (UINT8
) (Tag
->Value
& 1);
522 UpdateStatusBar (NV_UPDATE_REQUIRED
, Tag
->Flags
, TRUE
);
525 if ((*(UINT8
*) NvRamMap
& 1) == 0x01) {
526 NewStrCat (OptionString
[0], (CHAR16
*) CHECK_ON
);
528 // If someone reset default variables - we may need to reload from our NvMapping....
530 Tag
->Value
= *(UINT8
*) NvRamMap
;
533 // If someone reset default variables - we may need to reload from our NvMapping....
535 NewStrCat (OptionString
[0], (CHAR16
*) CHECK_OFF
);
536 Tag
->Value
= *(UINT8
*) NvRamMap
;
539 NewStrCat (OptionString
[0], (CHAR16
*) RIGHT_CHECKBOX_DELIMITER
);
540 NewStrCat (OptionString
[0], StringPtr
);
543 case EFI_IFR_NUMERIC_OP
:
545 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
546 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
547 // the NvMap so that we can properly display the information
549 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
550 AdjustNvMap (FileFormTags
, MenuOption
);
551 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
554 *OptionString
= AllocateZeroPool ((gOptionBlockWidth
+ 1) * 2 * gScreenDimensions
.BottomRow
);
555 ASSERT (*OptionString
);
558 // Add left delimeter to string
560 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
563 // Retrieve the current numeric value
569 if (Tag
->Step
== 0) {
573 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, TRUE
, Tag
, REGULAR_NUMERIC
, &Number
);
574 if (!EFI_ERROR (Status
)) {
575 CopyMem (gPreviousValue
, NvRamMap
, MenuOption
->ThisTag
->StorageWidth
);
576 UpdateStatusBar (NV_UPDATE_REQUIRED
, Tag
->Flags
, TRUE
);
579 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
581 CopyMem (NvRamMap
, &Number
, MenuOption
->ThisTag
->StorageWidth
);
587 // Auto selection from list
589 if ((((Tag
->StorageWidth
== 1) && (UINT8
) (*NvRamMap
) > Tag
->Maximum
) || ((UINT8
) (*NvRamMap
) < Tag
->Minimum
)) ||
590 (((Tag
->StorageWidth
== 2) && *NvRamMap
> Tag
->Maximum
) || (*NvRamMap
< Tag
->Minimum
))
593 // Seed Number with valid value if currently invalid
595 Number
= Tag
->Default
;
597 if (Tag
->StorageWidth
== 1) {
598 Number
= (UINT8
) (*NvRamMap
);
604 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, FALSE
, Tag
, REGULAR_NUMERIC
, &Number
);
605 if (!EFI_ERROR (Status
)) {
606 CopyMem (gPreviousValue
, NvRamMap
, MenuOption
->ThisTag
->StorageWidth
);
607 UpdateStatusBar (NV_UPDATE_REQUIRED
, Tag
->Flags
, TRUE
);
610 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
612 CopyMem (NvRamMap
, &Number
, MenuOption
->ThisTag
->StorageWidth
);
618 if (((Tag
->StorageWidth
== 1) && (UINT8
) (*NvRamMap
) <= Tag
->Maximum
&& (UINT8
) (*NvRamMap
) >= Tag
->Minimum
) ||
619 ((Tag
->StorageWidth
== 2) && *NvRamMap
<= Tag
->Maximum
&& *NvRamMap
>= Tag
->Minimum
)
621 if (Tag
->StorageWidth
== 1) {
622 Number
= (UINT8
) (*NvRamMap
);
626 UnicodeValueToString (
630 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
632 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
633 StrnCpy (OptionString
[0] + 1, FormattedNumber
, Number
);
636 // If *NvRamMap isn't within parameters, set it to within parameters
639 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
641 CopyMem (NvRamMap
, &Tag
->Default
, MenuOption
->ThisTag
->StorageWidth
);
642 Number
= Tag
->Default
;
644 UnicodeValueToString (
648 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
650 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
651 StrnCpy (OptionString
[0] + 1, FormattedNumber
, Number
);
654 *(OptionString
[0] + Number
/ 2) = RIGHT_NUMERIC_DELIMITER
;
655 NewStrCat (OptionString
[0] + (Number
/ 2) + 1, StringPtr
);
659 case EFI_IFR_DATE_OP
:
661 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
662 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
663 // the NvMap so that we can properly display the information
665 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
666 AdjustNvMap (FileFormTags
, MenuOption
);
667 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
670 Status
= gRT
->GetTime (&Time
, NULL
);
671 if (EFI_ERROR (Status
)) {
675 // This for loop advances Index till it points immediately after a date entry. We can then
676 // subtract MenuOption->TagIndex from Index and find out relative to the start of the Date
677 // structure which field we were in. For instance, if TagIndex was 52, and we advanced Index
678 // to 53 and found it to no longer point to a date operand, we were pointing to the last of 3
682 // This has BUGBUG potential....fix this - if someone wants to ask two DATE questions in a row.....code
683 // against such silliness.
685 // Also, we want to internationalize the order of the date information. We need to code for it as well.
687 for (Index
= MenuOption
->TagIndex
; MenuOption
->Tags
[Index
].Operand
== EFI_IFR_DATE_OP
; Index
++)
691 // Count 0 = We entered on the first Date operand
692 // Count 1 = We entered on the second Date operand
693 // Count 2 = We entered on the third Date operand
695 Count
= 3 - (Index
- MenuOption
->TagIndex
);
700 // This is similar to numerics, except for the following:
701 // We will under normal circumstances get 3 consecutive calls
702 // to process this opcodes data.
704 *OptionString
= AllocateZeroPool ((gOptionBlockWidth
+ 1) * 2 * gScreenDimensions
.BottomRow
);
705 ASSERT (*OptionString
);
710 Number
= (UINT16
) Time
.Month
;
712 if (Tag
->Step
== 0) {
713 MenuOption
->OptCol
++;
714 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, TRUE
, Tag
, DATE_NUMERIC
, &Number
);
717 // Seed value with current setting
719 Tag
->Value
= (UINT16
) Time
.Month
;
720 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, FALSE
, Tag
, DATE_NUMERIC
, &Number
);
723 if (!EFI_ERROR (Status
)) {
724 Time
.Month
= (UINT8
) Number
;
725 gRT
->SetTime (&Time
);
729 VariableDefinition
->FakeNvRamMap
[Tag
->Id
] = Time
.Month
;
730 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
732 UnicodeValueToString (
736 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
738 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
741 FormattedNumber
[2] = FormattedNumber
[1];
742 FormattedNumber
[1] = FormattedNumber
[0];
743 FormattedNumber
[0] = L
'0';
747 StrnCpy (OptionString
[0] + 1, FormattedNumber
, Number
);
748 *(OptionString
[0] + Number
/ 2) = DATE_SEPARATOR
;
749 StrCat (OptionString
[0] + (Number
/ 2) + 1, StringPtr
);
754 Number
= (UINT16
) Time
.Day
;
756 if (Tag
->Step
== 0) {
757 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, TRUE
, Tag
, DATE_NUMERIC
, &Number
);
760 // Seed value with current setting
762 Tag
->Value
= (UINT16
) Time
.Day
;
763 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, FALSE
, Tag
, DATE_NUMERIC
, &Number
);
766 if (!EFI_ERROR (Status
)) {
767 Time
.Day
= (UINT8
) Number
;
768 gRT
->SetTime (&Time
);
772 VariableDefinition
->FakeNvRamMap
[Tag
->Id
] = Time
.Day
;
773 SetUnicodeMem (OptionString
[0], 4, L
' ');
775 UnicodeValueToString (
779 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
781 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
783 FormattedNumber
[2] = FormattedNumber
[1];
784 FormattedNumber
[1] = FormattedNumber
[0];
785 FormattedNumber
[0] = L
'0';
789 StrnCpy (OptionString
[0] + 4, FormattedNumber
, Number
);
790 *(OptionString
[0] + Number
/ 2 + 3) = DATE_SEPARATOR
;
791 StrCat (OptionString
[0] + (Number
/ 2) + 4, StringPtr
);
796 Number
= (UINT16
) Time
.Year
;
798 if (Tag
->Step
== 0) {
799 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, TRUE
, Tag
, DATE_NUMERIC
, &Number
);
802 // Seed value with current setting
804 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, FALSE
, Tag
, DATE_NUMERIC
, &Number
);
807 if (!EFI_ERROR (Status
)) {
808 Time
.Year
= (UINT16
) Number
;
809 gRT
->SetTime (&Time
);
813 Tag
->Value
= (UINT16
) Time
.Year
;
814 VariableDefinition
->FakeNvRamMap
[Tag
->Id
] = (UINT8
) Tag
->Value
;
815 VariableDefinition
->FakeNvRamMap
[Tag
->Id
+ 1] = (UINT8
) (Tag
->Value
>> 8);
816 SetUnicodeMem (OptionString
[0], 7, L
' ');
817 UnicodeValueToString (
821 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
823 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
824 StrnCpy (OptionString
[0] + 7, FormattedNumber
, Number
);
825 *(OptionString
[0] + Number
/ 2 + 6) = RIGHT_NUMERIC_DELIMITER
;
826 StrCat (OptionString
[0] + (Number
/ 2) + 7, StringPtr
);
833 // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG
834 // We need to add code to support the NVRam storage version of Date - this is the 1% case where someone
835 // might want to set an alarm and actually preserve the data in NVRam so a driver can pick up the instruction
836 // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG
838 case EFI_IFR_TIME_OP
:
840 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
841 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
842 // the NvMap so that we can properly display the information
844 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
845 AdjustNvMap (FileFormTags
, MenuOption
);
846 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
849 Status
= gRT
->GetTime (&Time
, NULL
);
850 if (EFI_ERROR (Status
)) {
854 // This is similar to numerics, except for the following:
855 // We will under normal circumstances get 3 consecutive calls
856 // to process this opcodes data.
858 *OptionString
= AllocateZeroPool ((gOptionBlockWidth
+ 1) * 2 * gScreenDimensions
.BottomRow
);
859 ASSERT (*OptionString
);
862 // This for loop advances Index till it points immediately after a date entry. We can then
863 // subtract MenuOption->TagIndex from Index and find out relative to the start of the Date
864 // structure which field we were in. For instance, if TagIndex was 52, and we advanced Index
865 // to 53 and found it to no longer point to a date operand, we were pointing to the last of 3
868 for (Index
= MenuOption
->TagIndex
; MenuOption
->Tags
[Index
].Operand
== EFI_IFR_TIME_OP
; Index
++)
871 // Count 0 = We entered on the first Date operand
872 // Count 1 = We entered on the second Date operand
873 // Count 2 = We entered on the third Date operand
875 Count
= 3 - (Index
- MenuOption
->TagIndex
);
886 Number
= Time
.Minute
;
890 Number
= Time
.Second
;
893 // Retrieve the current numeric value
899 if (Tag
->Step
== 0) {
903 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, TRUE
, Tag
, TIME_NUMERIC
, &Number
);
904 if (!EFI_ERROR (Status
)) {
907 gRT
->SetTime (&Time
);
913 // Auto selection from list
915 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, FALSE
, Tag
, TIME_NUMERIC
, &Number
);
916 if (!EFI_ERROR (Status
)) {
925 Time
.Hour
= (UINT8
) Number
;
929 Time
.Minute
= (UINT8
) Number
;
933 Time
.Second
= (UINT8
) Number
;
937 gRT
->SetTime (&Time
);
941 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
942 UnicodeValueToString (
946 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
948 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
950 FormattedNumber
[2] = FormattedNumber
[1];
951 FormattedNumber
[1] = FormattedNumber
[0];
952 FormattedNumber
[0] = L
'0';
956 StrnCpy (OptionString
[0] + 1, FormattedNumber
, Number
);
957 *(OptionString
[0] + Number
/ 2) = TIME_SEPARATOR
;
958 StrCat (OptionString
[0] + (Number
/ 2) + 1, StringPtr
);
962 SetUnicodeMem (OptionString
[0], 4, L
' ');
963 UnicodeValueToString (
967 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
969 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
971 FormattedNumber
[2] = FormattedNumber
[1];
972 FormattedNumber
[1] = FormattedNumber
[0];
973 FormattedNumber
[0] = L
'0';
977 StrnCpy (OptionString
[0] + 4, FormattedNumber
, Number
);
978 *(OptionString
[0] + Number
/ 2 + 3) = TIME_SEPARATOR
;
979 StrCat (OptionString
[0] + (Number
/ 2) + 4, StringPtr
);
983 SetUnicodeMem (OptionString
[0], 7, L
' ');
984 UnicodeValueToString (
988 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
990 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
992 FormattedNumber
[2] = FormattedNumber
[1];
993 FormattedNumber
[1] = FormattedNumber
[0];
994 FormattedNumber
[0] = L
'0';
998 StrnCpy (OptionString
[0] + 7, FormattedNumber
, Number
);
999 *(OptionString
[0] + Number
/ 2 + 6) = RIGHT_NUMERIC_DELIMITER
;
1000 StrCat (OptionString
[0] + (Number
/ 2) + 7, StringPtr
);
1004 // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG
1005 // We need to add code to support the NVRam storage version of Date - this is the 1% case where someone
1006 // might want to set an alarm and actually preserve the data in NVRam so a driver can pick up the instruction
1007 // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG
1012 case EFI_IFR_STRING_OP
:
1014 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
1015 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
1016 // the NvMap so that we can properly display the information
1018 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
1019 AdjustNvMap (FileFormTags
, MenuOption
);
1020 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
1023 *OptionString
= AllocateZeroPool ((gOptionBlockWidth
+ 1) * 2 * gScreenDimensions
.BottomRow
);
1024 ASSERT (*OptionString
);
1027 StringPtr
= AllocateZeroPool (Tag
->Maximum
);
1030 Status
= ReadString (MenuOption
, StringPtr
);
1032 if (!EFI_ERROR (Status
)) {
1033 CopyMem (gPreviousValue
, NvRamMap
, MenuOption
->ThisTag
->StorageWidth
);
1034 CopyMem (&VariableDefinition
->NvRamMap
[Tag
->StorageStart
], StringPtr
, Tag
->StorageWidth
);
1036 UpdateStatusBar (NV_UPDATE_REQUIRED
, Tag
->Flags
, TRUE
);
1039 gBS
->FreePool (StringPtr
);
1042 for (Index
= 0; Index
< gOptionBlockWidth
; Index
++) {
1043 if (VariableDefinition
->NvRamMap
[Tag
->StorageStart
+ (Index
* 2)] != 0x0000) {
1044 CopyMem (OptionString
[0] + Index
, &VariableDefinition
->NvRamMap
[Tag
->StorageStart
+ (Index
* 2)], 2);
1047 *(OptionString
[0] + Index
) = '_';
1048 *(OptionString
[0] + 1 + Index
) = 0;
1057 case EFI_IFR_PASSWORD_OP
:
1059 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
1060 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
1061 // the NvMap so that we can properly display the information
1063 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
1064 AdjustNvMap (FileFormTags
, MenuOption
);
1065 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
1069 StringPtr
= AllocateZeroPool (Tag
->Maximum
);
1073 // If interactive, read the password and do the appropriate callbacks in that routine.
1074 // Since interactive passwords assume to handle the password data in a separate variable
1075 // storage, we don't need to do more than what is below for password callbacks
1077 if (Tag
->Flags
& EFI_IFR_FLAG_INTERACTIVE
) {
1078 MenuOption
->Tags
[0].CallbackHandle
= FileFormTags
->FormTags
.Tags
[0].CallbackHandle
;
1079 Status
= ReadPassword (MenuOption
, TRUE
, Tag
, PageData
, FALSE
, FileFormTags
, StringPtr
);
1080 ZeroMem (StringPtr
, Tag
->Maximum
);
1082 if (EFI_ERROR (Status
)) {
1083 if (Status
== EFI_NOT_READY
) {
1084 gBS
->FreePool (StringPtr
);
1089 Status
= ReadPassword (MenuOption
, TRUE
, Tag
, PageData
, TRUE
, FileFormTags
, StringPtr
);
1090 gBS
->FreePool (StringPtr
);
1094 for (Index
= 0; Index
< Tag
->Maximum
; Index
++) {
1095 if (VariableDefinition
->NvRamMap
[Tag
->StorageStart
+ Index
] != 0x00) {
1097 // There is something there! Prompt for password
1099 Status
= ReadPassword (MenuOption
, TRUE
, Tag
, PageData
, FALSE
, FileFormTags
, StringPtr
);
1100 if (EFI_ERROR (Status
)) {
1101 gBS
->FreePool (StringPtr
);
1105 if (Tag
->Encoding
== 1) {
1106 EncodePassword (StringPtr
, (UINT8
) Tag
->Maximum
);
1107 Status
= CompareMem (StringPtr
, &VariableDefinition
->NvRamMap
[Tag
->StorageStart
], Tag
->Maximum
);
1109 Status
= CompareMem (StringPtr
, &VariableDefinition
->NvRamMap
[Tag
->StorageStart
], Tag
->Maximum
);
1113 gBS
->FreePool (StringPtr
);
1123 ZeroMem (StringPtr
, Tag
->Maximum
);
1126 // No password set! Go ahead and prompt the user for a password.
1128 Status
= ReadPassword (MenuOption
, FALSE
, Tag
, PageData
, FALSE
, FileFormTags
, StringPtr
);
1130 if (EFI_ERROR (Status
)) {
1132 // User couldn't figure out how to type two identical passwords
1134 gBS
->FreePool (StringPtr
);
1138 // Very simple example of how one MIGHT do password encoding
1140 if (Tag
->Encoding
== 1) {
1141 EncodePassword (StringPtr
, (UINT8
) Tag
->Maximum
);
1144 TmpNvRamMap
= AllocatePool (VariableDefinition
->VariableSize
);
1145 ASSERT (TmpNvRamMap
!= NULL
);
1147 Count
= VariableDefinition
->VariableSize
;
1149 if ((FormCallback
!= NULL
) && (FormCallback
->NvRead
!= NULL
)) {
1150 Status
= FormCallback
->NvRead (
1152 VariableDefinition
->VariableName
,
1153 &VariableDefinition
->Guid
,
1156 (VOID
*) TmpNvRamMap
1159 Status
= gRT
->GetVariable (
1160 VariableDefinition
->VariableName
,
1161 &VariableDefinition
->Guid
,
1164 (VOID
*) TmpNvRamMap
1168 CopyMem (&VariableDefinition
->NvRamMap
[Tag
->StorageStart
], StringPtr
, Tag
->StorageWidth
);
1169 CopyMem (&TmpNvRamMap
[Tag
->StorageStart
], StringPtr
, Tag
->StorageWidth
);
1171 if ((FormCallback
!= NULL
) && (FormCallback
->NvWrite
!= NULL
)) {
1172 Status
= FormCallback
->NvWrite (
1174 VariableDefinition
->VariableName
,
1175 &VariableDefinition
->Guid
,
1176 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1177 VariableDefinition
->VariableSize
,
1178 (VOID
*) TmpNvRamMap
,
1182 Status
= gRT
->SetVariable (
1183 VariableDefinition
->VariableName
,
1184 &VariableDefinition
->Guid
,
1185 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1186 VariableDefinition
->VariableSize
,
1187 (VOID
*) TmpNvRamMap
1191 gBS
->FreePool (TmpNvRamMap
);
1192 gBS
->FreePool (StringPtr
);
1205 IN CHAR16
*StringPtr
,
1206 OUT CHAR16
**FormattedString
,
1213 UINTN PrevSearchIndex
;
1219 CurrIndex
= gHelpBlockWidth
- 1;
1221 if (*FormattedString
!= NULL
) {
1222 gBS
->FreePool (*FormattedString
);
1223 *FormattedString
= NULL
;
1226 for (; CurrIndex
> PrevIndex
; CurrIndex
--) {
1228 // In the case where the string ended and a new one is immediately after it
1229 // we need to check for the null-terminator and reset the CurrIndex
1231 SearchIndex
= CurrIndex
;
1232 PrevSearchIndex
= PrevIndex
;
1234 for (; SearchIndex
> PrevSearchIndex
; PrevSearchIndex
++) {
1235 if ((StringPtr
[PrevSearchIndex
] == CHAR_NULL
) || (StringPtr
[PrevSearchIndex
] == CHAR_LINEFEED
)) {
1236 CurrIndex
= PrevSearchIndex
;
1240 if (StringPtr
[PrevSearchIndex
] == CHAR_CARRIAGE_RETURN
) {
1241 if (StringPtr
[PrevSearchIndex
+ 1] == CHAR_LINEFEED
) {
1243 // Found a "\n",advance to the next new line.
1245 CurrIndex
= PrevSearchIndex
+ 1;
1249 // Found a "\r",return to the start of the current line.
1251 PrevIndex
= PrevSearchIndex
+ 1;
1252 CurrIndex
= PrevSearchIndex
+ gHelpBlockWidth
;
1259 // End of the string, thus stop counting.
1261 if (StringPtr
[CurrIndex
] == CHAR_NULL
) {
1266 // The premise is that for every HELP_BLOCK_WIDTH we rewind
1267 // until we find the first space. That is the delimiter for
1268 // the string, and we will then advance our CurrIndex another
1269 // HELP_BLOCK_WIDTH and continue the process breaking the larger
1270 // string into chunks that fit within the HELP_BLOCK_WIDTH requirements.
1272 if (StringPtr
[CurrIndex
] == CHAR_SPACE
) {
1274 // How many strings have been found?
1277 PrevIndex
= CurrIndex
+ 1;
1278 CurrIndex
= CurrIndex
+ gHelpBlockWidth
;
1281 // Found a Linefeed, advance to the next line.
1283 if (StringPtr
[CurrIndex
] == CHAR_LINEFEED
) {
1285 PrevIndex
= CurrIndex
+ 1;
1286 CurrIndex
= CurrIndex
+ gHelpBlockWidth
;
1292 // Round the value up one (doesn't hurt)
1297 // Determine the number of pages this help string occupies
1299 PageCount
= StringCount
/ RowCount
;
1300 if (StringCount
% RowCount
> 0) {
1304 // Convert the PageCount into lines so we can allocate the correct buffer size
1306 StringCount
= PageCount
* RowCount
;
1309 // We now know how many strings we will have, so we can allocate the
1310 // space required for the array or strings.
1312 *FormattedString
= AllocateZeroPool ((StringCount
) * (gHelpBlockWidth
+ 1) * 2);
1313 ASSERT (*FormattedString
);
1317 CurrIndex
= gHelpBlockWidth
- 1;
1319 for (; CurrIndex
> PrevIndex
; CurrIndex
--) {
1321 // In the case where the string ended and a new one is immediately after it
1322 // we need to check for the null-terminator and reset the CurrIndex
1324 SearchIndex
= CurrIndex
;
1325 PrevSearchIndex
= PrevIndex
;
1327 for (; SearchIndex
> PrevSearchIndex
; PrevSearchIndex
++) {
1328 if ((StringPtr
[PrevSearchIndex
] == CHAR_NULL
) || (StringPtr
[PrevSearchIndex
] == CHAR_LINEFEED
)) {
1329 CurrIndex
= PrevSearchIndex
;
1333 if (StringPtr
[PrevSearchIndex
] == CHAR_CARRIAGE_RETURN
) {
1334 if (StringPtr
[PrevSearchIndex
+ 1] == CHAR_LINEFEED
) {
1336 // Found a "\n",advance to the next new line.
1338 CurrIndex
= PrevSearchIndex
+ 1;
1342 // Found a "\r",return to the start of the current line.
1344 PrevIndex
= PrevSearchIndex
+ 1;
1345 CurrIndex
= PrevSearchIndex
+ gHelpBlockWidth
;
1352 // End of the string, thus stop counting.
1354 if (StringPtr
[CurrIndex
] == CHAR_NULL
) {
1356 // Copy the fragment to the FormattedString buffer
1358 StrnCpy ((FormattedString
[0] + StringCount
* gHelpBlockWidth
), &StringPtr
[PrevIndex
], CurrIndex
- PrevIndex
);
1363 // The premise is that for every HELP_BLOCK_WIDTH we rewind
1364 // until we find the first space. That is the delimiter for
1365 // the string, and we will then advance our CurrIndex another
1366 // HELP_BLOCK_WIDTH and continue the process breaking the larger
1367 // string into chunks that fit within the HELP_BLOCK_WIDTH requirements.
1369 if (StringPtr
[CurrIndex
] == CHAR_SPACE
) {
1371 // Copy the fragment to the FormattedString buffer
1373 StrnCpy ((FormattedString
[0] + StringCount
* gHelpBlockWidth
), &StringPtr
[PrevIndex
], CurrIndex
- PrevIndex
);
1375 PrevIndex
= CurrIndex
+ 1;
1376 CurrIndex
= CurrIndex
+ gHelpBlockWidth
;
1379 // Found a LineFeed, advance to the next line.
1381 if (StringPtr
[CurrIndex
] == CHAR_LINEFEED
) {
1382 StringPtr
[CurrIndex
] = CHAR_SPACE
;
1384 // "\n" is represented as CHAR_CARRIAGE_RETURN + CHAR_LINEFEED,check this.
1386 if (StringPtr
[CurrIndex
- 1] == CHAR_CARRIAGE_RETURN
) {
1387 StringPtr
[CurrIndex
- 1] = CHAR_SPACE
;
1390 StrnCpy ((FormattedString
[0] + StringCount
* gHelpBlockWidth
), &StringPtr
[PrevIndex
], CurrIndex
- PrevIndex
);
1392 PrevIndex
= CurrIndex
+ 1;
1393 CurrIndex
= CurrIndex
+ gHelpBlockWidth
;
1405 IN EFI_TAG
*TargetTag
,
1407 EFI_VARIABLE_DEFINITION
*VariableDefinitionsHead
1411 CHAR16
*VariableName
;
1413 EFI_VARIABLE_DEFINITION
*VariableDefinitions
;
1414 EFI_VARIABLE_DEFINITION
*PreviousVariableDefinitions
;
1415 STATIC UINT16 VariableSize
;
1417 STATIC UINT16 CurrentVariable
;
1418 STATIC UINT16 CurrentVariable2
;
1422 case EFI_IFR_FORM_OP
:
1423 CopyMem (&TargetTag
->Id
, &((EFI_IFR_FORM
*) FormData
)->FormId
, sizeof (UINT16
));
1424 CopyMem (&TargetTag
->Text
, &((EFI_IFR_FORM
*) FormData
)->FormTitle
, sizeof (UINT16
));
1425 TargetTag
->VariableNumber
= CurrentVariable
;
1426 if (VariableDefinitionsHead
!= NULL
) {
1427 VariableName
= AllocateZeroPool (12);
1428 ASSERT (VariableName
!= NULL
);
1429 CopyMem (VariableName
, L
"Setup", 12);
1430 VariableDefinitionsHead
->VariableName
= VariableName
;
1431 VariableDefinitionsHead
->VariableSize
= VariableSize
;
1432 CopyMem (&VariableDefinitionsHead
->Guid
, &Guid
, sizeof (EFI_GUID
));
1436 case EFI_IFR_SUBTITLE_OP
:
1437 TargetTag
->NumberOfLines
= 1;
1438 CopyMem (&TargetTag
->Text
, &((EFI_IFR_SUBTITLE
*) FormData
)->SubTitle
, sizeof (UINT16
));
1439 TargetTag
->VariableNumber
= CurrentVariable
;
1442 case EFI_IFR_TEXT_OP
:
1443 TargetTag
->NumberOfLines
= 1;
1444 CopyMem (&TargetTag
->Text
, &((EFI_IFR_TEXT
*) FormData
)->Text
, sizeof (UINT16
));
1445 CopyMem (&TargetTag
->Help
, &((EFI_IFR_TEXT
*) FormData
)->Help
, sizeof (UINT16
));
1446 TargetTag
->VariableNumber
= CurrentVariable
;
1449 // To optimize the encoding size, certain opcodes have optional fields such as those
1450 // inside the if() statement. If the encoded length is the complete size, then we
1451 // know we have valid data encoded that we want to integrate
1453 if (((EFI_IFR_TEXT
*) FormData
)->Header
.Length
== sizeof (EFI_IFR_TEXT
)) {
1455 // Text has no help associated with it, but in case there is a second entry due to
1456 // dynamic/interactive flags being active, bring this data over.
1458 CopyMem (&TargetTag
->TextTwo
, &((EFI_IFR_TEXT
*) FormData
)->TextTwo
, sizeof (UINT16
));
1459 TargetTag
->Flags
= ((EFI_IFR_TEXT
*) FormData
)->Flags
;
1460 CopyMem (&TargetTag
->Key
, &((EFI_IFR_TEXT
*) FormData
)->Key
, sizeof (UINT16
));
1464 case EFI_IFR_ONE_OF_OPTION_OP
:
1465 CopyMem (&TargetTag
->Text
, &((EFI_IFR_ONE_OF_OPTION
*) FormData
)->Option
, sizeof (UINT16
));
1466 CopyMem (&TargetTag
->Value
, &((EFI_IFR_ONE_OF_OPTION
*) FormData
)->Value
, sizeof (UINT16
));
1467 TargetTag
->Flags
= ((EFI_IFR_ONE_OF_OPTION
*) FormData
)->Flags
;
1468 CopyMem (&TargetTag
->Key
, &((EFI_IFR_ONE_OF_OPTION
*) FormData
)->Key
, sizeof (UINT16
));
1469 TargetTag
->VariableNumber
= CurrentVariable
;
1472 case EFI_IFR_CHECKBOX_OP
:
1473 TargetTag
->Flags
= ((EFI_IFR_CHECKBOX
*) FormData
)->Flags
;
1474 TargetTag
->ResetRequired
= (BOOLEAN
) (TargetTag
->Flags
& EFI_IFR_FLAG_RESET_REQUIRED
);
1475 CopyMem (&TargetTag
->Key
, &((EFI_IFR_CHECKBOX
*) FormData
)->Key
, sizeof (UINT16
));
1476 TargetTag
->VariableNumber
= CurrentVariable
;
1479 case EFI_IFR_NUMERIC_OP
:
1480 TargetTag
->Flags
= ((EFI_IFR_NUMERIC
*) FormData
)->Flags
;
1481 CopyMem (&TargetTag
->Key
, &((EFI_IFR_NUMERIC
*) FormData
)->Key
, sizeof (UINT16
));
1482 TargetTag
->VariableNumber
= CurrentVariable
;
1485 case EFI_IFR_STRING_OP
:
1487 CopyMem (&TempValue
, &((EFI_IFR_STRING
*) FormData
)->MinSize
, sizeof (UINT8
));
1488 TempValue
= (UINT16
) (TempValue
* 2);
1489 CopyMem (&TargetTag
->Minimum
, &TempValue
, sizeof (UINT16
));
1491 CopyMem (&TempValue
, &((EFI_IFR_STRING
*) FormData
)->MaxSize
, sizeof (UINT8
));
1492 TempValue
= (UINT16
) (TempValue
* 2);
1493 CopyMem (&TargetTag
->Maximum
, &TempValue
, sizeof (UINT16
));
1494 CopyMem (&TargetTag
->StorageWidth
, &TempValue
, sizeof (UINT16
));
1495 TargetTag
->Flags
= (UINT8
) (((EFI_IFR_STRING
*) FormData
)->Flags
);
1496 TargetTag
->ResetRequired
= (BOOLEAN
) (TargetTag
->Flags
& EFI_IFR_FLAG_RESET_REQUIRED
);
1497 CopyMem (&TargetTag
->Key
, &((EFI_IFR_STRING
*) FormData
)->Key
, sizeof (UINT16
));
1498 TargetTag
->VariableNumber
= CurrentVariable
;
1501 case EFI_IFR_PASSWORD_OP
:
1503 CopyMem (&TempValue
, &((EFI_IFR_PASSWORD
*) FormData
)->MinSize
, sizeof (UINT8
));
1504 TempValue
= (UINT16
) (TempValue
* 2);
1505 CopyMem (&TargetTag
->Minimum
, &TempValue
, sizeof (UINT16
));
1507 CopyMem (&TempValue
, &((EFI_IFR_PASSWORD
*) FormData
)->MaxSize
, sizeof (UINT8
));
1508 TempValue
= (UINT16
) (TempValue
* 2);
1509 CopyMem (&TargetTag
->Maximum
, &TempValue
, sizeof (UINT16
));
1510 CopyMem (&TargetTag
->StorageWidth
, &TempValue
, sizeof (UINT16
));
1511 TargetTag
->Flags
= ((EFI_IFR_PASSWORD
*) FormData
)->Flags
;
1512 TargetTag
->ResetRequired
= (BOOLEAN
) (TargetTag
->Flags
& EFI_IFR_FLAG_RESET_REQUIRED
);
1513 CopyMem (&TargetTag
->Key
, &((EFI_IFR_PASSWORD
*) FormData
)->Key
, sizeof (UINT16
));
1514 CopyMem (&TargetTag
->Encoding
, &((EFI_IFR_PASSWORD
*) FormData
)->Encoding
, sizeof (UINT16
));
1515 TargetTag
->VariableNumber
= CurrentVariable
;
1518 case EFI_IFR_VARSTORE_OP
:
1520 // It should NEVER be NULL
1522 if (VariableDefinitionsHead
== NULL
) {
1526 VariableDefinitions
= VariableDefinitionsHead
;
1529 // Advance VariableDefinitions to the last entry
1531 for (; VariableDefinitions
!= NULL
; VariableDefinitions
= VariableDefinitions
->Next
) {
1532 PreviousVariableDefinitions
= VariableDefinitions
;
1534 // If there is a variable with this GUID and ID already, we need to bail out
1536 if (!CompareMem (&VariableDefinitions
->Guid
, &((EFI_IFR_VARSTORE
*) FormData
)->Guid
, sizeof (EFI_GUID
)) &&
1537 !CompareMem (&VariableDefinitions
->VariableId
, &((EFI_IFR_VARSTORE
*) FormData
)->VarId
, sizeof (UINT16
))
1542 if (VariableDefinitions
->Next
== NULL
) {
1547 // If the last entry has a variable in it already, allocate a new entry and use it
1549 if (VariableDefinitions
->VariableName
!= NULL
) {
1550 VariableDefinitions
->Next
= AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION
));
1551 ASSERT (VariableDefinitions
->Next
!= NULL
);
1552 PreviousVariableDefinitions
= VariableDefinitions
;
1553 VariableDefinitions
= VariableDefinitions
->Next
;
1554 VariableDefinitions
->Previous
= PreviousVariableDefinitions
;
1557 // Copy the Variable data to our linked list
1559 CopyMem (&VariableDefinitions
->VariableId
, &((EFI_IFR_VARSTORE
*) FormData
)->VarId
, sizeof (UINT16
));
1560 CopyMem (&VariableDefinitions
->VariableSize
, &((EFI_IFR_VARSTORE
*) FormData
)->Size
, sizeof (UINT16
));
1561 CopyMem (&VariableDefinitions
->Guid
, &((EFI_IFR_VARSTORE
*) FormData
)->Guid
, sizeof (EFI_GUID
));
1564 // The ASCII String which is immediately past the EFI_IFR_VARSTORE is inferred by the structure definition
1565 // due to it being variable sized. There are rules preventing it from being > 40 characters long and should
1566 // be enforced by the compiler.
1568 AsciiString
= (CHAR8
*) (&((EFI_IFR_VARSTORE
*) FormData
)->Size
);
1569 AsciiString
= AsciiString
+ 2;
1570 VariableDefinitions
->VariableName
= AllocateZeroPool ((AsciiStrLen (AsciiString
) + 1) * 2);
1571 ASSERT (VariableDefinitions
->VariableName
!= NULL
);
1572 for (Index
= 0; AsciiString
[Index
] != 0; Index
++) {
1573 VariableDefinitions
->VariableName
[Index
] = (CHAR16
) AsciiString
[Index
];
1576 VariableDefinitions
->VariableName
[Index
] = 0;
1579 // Propogate the tag information for this op-code
1581 CopyMem (&TargetTag
->VariableNumber
, &((EFI_IFR_VARSTORE
*) FormData
)->VarId
, sizeof (UINT16
));
1582 CopyMem (&TargetTag
->GuidValue
, &((EFI_IFR_VARSTORE
*) FormData
)->Guid
, sizeof (EFI_GUID
));
1583 CopyMem (&TargetTag
->StorageWidth
, &((EFI_IFR_VARSTORE
*) FormData
)->Size
, sizeof (UINT16
));
1584 CopyMem (&TargetTag
->Maximum
, &((EFI_IFR_VARSTORE
*) FormData
)->Size
, sizeof (UINT16
));
1587 case EFI_IFR_VARSTORE_SELECT_OP
:
1588 CopyMem (&TargetTag
->VariableNumber
, &((EFI_IFR_VARSTORE_SELECT
*) FormData
)->VarId
, sizeof (UINT16
));
1589 CopyMem (&CurrentVariable
, &((EFI_IFR_VARSTORE_SELECT
*) FormData
)->VarId
, sizeof (UINT16
));
1590 CurrentVariable2
= CurrentVariable
;
1593 case EFI_IFR_VARSTORE_SELECT_PAIR_OP
:
1594 CopyMem (&TargetTag
->VariableNumber
, &((EFI_IFR_VARSTORE_SELECT_PAIR
*) FormData
)->VarId
, sizeof (UINT16
));
1596 &TargetTag
->VariableNumber2
,
1597 &((EFI_IFR_VARSTORE_SELECT_PAIR
*) FormData
)->SecondaryVarId
,
1600 CopyMem (&CurrentVariable
, &((EFI_IFR_VARSTORE_SELECT_PAIR
*) FormData
)->VarId
, sizeof (UINT16
));
1601 CopyMem (&CurrentVariable2
, &((EFI_IFR_VARSTORE_SELECT_PAIR
*) FormData
)->SecondaryVarId
, sizeof (UINT16
));
1604 case EFI_IFR_REF_OP
:
1605 TargetTag
->NumberOfLines
= 1;
1606 CopyMem (&TargetTag
->Id
, &((EFI_IFR_REF
*) FormData
)->FormId
, sizeof (UINT16
));
1607 CopyMem (&TargetTag
->Key
, &((EFI_IFR_REF
*) FormData
)->Key
, sizeof (UINT16
));
1608 CopyMem (&TargetTag
->Text
, &((EFI_IFR_REF
*) FormData
)->Prompt
, sizeof (UINT16
));
1609 CopyMem (&TargetTag
->Help
, &((EFI_IFR_REF
*) FormData
)->Help
, sizeof (UINT16
));
1610 TargetTag
->Flags
= ((EFI_IFR_REF
*) FormData
)->Flags
;
1611 TargetTag
->VariableNumber
= CurrentVariable
;
1614 case EFI_IFR_EQ_ID_VAL_OP
:
1615 CopyMem (&TargetTag
->Value
, &((EFI_IFR_EQ_ID_VAL
*) FormData
)->Value
, sizeof (UINT16
));
1616 CopyMem (&TargetTag
->Id
, &((EFI_IFR_EQ_ID_VAL
*) FormData
)->QuestionId
, sizeof (UINT16
));
1617 TargetTag
->StorageWidth
= ((EFI_IFR_EQ_ID_VAL
*) FormData
)->Width
;
1618 TargetTag
->VariableNumber
= CurrentVariable
;
1621 case EFI_IFR_EQ_VAR_VAL_OP
:
1622 CopyMem (&TargetTag
->Value
, &((EFI_IFR_EQ_VAR_VAL
*) FormData
)->Value
, sizeof (UINT16
));
1623 CopyMem (&TargetTag
->Id
, &((EFI_IFR_EQ_VAR_VAL
*) FormData
)->VariableId
, sizeof (UINT16
));
1624 TargetTag
->VariableNumber
= CurrentVariable
;
1627 case EFI_IFR_EQ_ID_ID_OP
:
1628 CopyMem (&TargetTag
->Id
, &((EFI_IFR_EQ_ID_ID
*) FormData
)->QuestionId1
, sizeof (UINT16
));
1629 CopyMem (&TargetTag
->Id2
, &((EFI_IFR_EQ_ID_ID
*) FormData
)->QuestionId2
, sizeof (UINT16
));
1630 TargetTag
->StorageWidth
= ((EFI_IFR_EQ_ID_ID
*) FormData
)->Width
;
1631 TargetTag
->VariableNumber
= CurrentVariable
;
1632 TargetTag
->VariableNumber
= CurrentVariable2
;
1635 case EFI_IFR_EQ_ID_LIST_OP
:
1636 CopyMem (&TargetTag
->Id
, &((EFI_IFR_EQ_ID_LIST
*) FormData
)->QuestionId
, sizeof (UINT16
));
1637 CopyMem (&TargetTag
->Id2
, &((EFI_IFR_EQ_ID_LIST
*) FormData
)->ListLength
, sizeof (UINT16
));
1638 TargetTag
->StorageWidth
= ((EFI_IFR_EQ_ID_LIST
*) FormData
)->Width
;
1640 TargetTag
->IntList
= AllocateZeroPool (TargetTag
->Id2
* sizeof (UINT16
));
1641 ASSERT (TargetTag
->IntList
);
1643 for (TempValue
= 0; TempValue
< TargetTag
->Id2
; TempValue
++) {
1645 &TargetTag
->IntList
[TempValue
],
1646 &((EFI_IFR_EQ_ID_LIST
*) FormData
)->ValueList
[TempValue
],
1651 TargetTag
->VariableNumber
= CurrentVariable
;
1654 case EFI_IFR_FORM_SET_OP
:
1655 CopyMem (&VariableSize
, &((EFI_IFR_FORM_SET
*) FormData
)->NvDataSize
, sizeof (UINT16
));
1656 CopyMem (&Guid
, &((EFI_IFR_FORM_SET
*) FormData
)->Guid
, sizeof (EFI_GUID
));
1658 // If there is a size specified in the formste, we will establish a "default" variable
1660 if (VariableDefinitionsHead
!= NULL
) {
1661 VariableName
= AllocateZeroPool (12);
1662 ASSERT (VariableName
!= NULL
);
1663 CopyMem (VariableName
, L
"Setup", 12);
1664 VariableDefinitionsHead
->VariableName
= VariableName
;
1665 VariableDefinitionsHead
->VariableSize
= VariableSize
;
1666 CopyMem (&VariableDefinitionsHead
->Guid
, &Guid
, sizeof (EFI_GUID
));
1670 case EFI_IFR_END_FORM_SET_OP
:
1671 CurrentVariable
= 0;
1672 CurrentVariable2
= 0;