2 Implementation for handling the User Interface option processing.
4 Copyright (c) 2006 - 2007 Intel Corporation. <BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 ExtractRequestedNvMap (
20 IN EFI_FILE_FORM_TAGS
*FileFormTags
,
22 OUT EFI_VARIABLE_DEFINITION
**VariableDefinition
25 *VariableDefinition
= FileFormTags
->VariableDefinitions
;
28 // Extract the data from the NV variable - consumer will free the buffer.
30 for (; *VariableDefinition
!= NULL
; *VariableDefinition
= (*VariableDefinition
)->Next
) {
32 // If there is a variable with this ID return with EFI_SUCCESS
34 if (!CompareMem (&(*VariableDefinition
)->VariableId
, &VariableId
, sizeof (UINT16
))) {
44 IN EFI_FILE_FORM_TAGS
*FileFormTags
,
46 IN UINT16 VariableSize
,
47 IN UINT16 OffsetValue
,
52 EFI_VARIABLE_DEFINITION
*VariableDefinition
;
54 Status
= ExtractRequestedNvMap (FileFormTags
, VariableId
, &VariableDefinition
);
56 if (!EFI_ERROR (Status
)) {
58 // Allocate sufficient space for the data and copy it into the outgoing buffer
60 if (VariableSize
!= 0) {
61 *Buffer
= AllocateZeroPool (VariableSize
);
62 ASSERT (*Buffer
!= NULL
);
63 CopyMem (*Buffer
, &VariableDefinition
->NvRamMap
[OffsetValue
], VariableSize
);
74 IN EFI_FILE_FORM_TAGS
*FileFormTags
,
75 IN UI_MENU_OPTION
*MenuOption
82 EFI_VARIABLE_DEFINITION
*VariableDefinition
;
86 SizeRequired
= MenuOption
->ThisTag
->StorageStart
+ MenuOption
->ThisTag
->StorageWidth
;
88 ExtractRequestedNvMap (FileFormTags
, MenuOption
->Tags
->VariableNumber
, &VariableDefinition
);
91 // We arrived here because the current NvRamMap is too small for the new op-code to store things and
92 // we need to adjust the buffer to support this.
94 NvRamMap
= AllocateZeroPool (SizeRequired
+ 1);
95 ASSERT (NvRamMap
!= NULL
);
98 // Copy current NvRamMap to the new NvRamMap
100 CopyMem (NvRamMap
, VariableDefinition
->NvRamMap
, VariableDefinition
->VariableFakeSize
);
103 // Remember, the only time we come here is because we are in the NVPlus section of the NvRamMap
105 for (Index
= MenuOption
->TagIndex
;
106 (MenuOption
->Tags
[Index
].Operand
!= EFI_IFR_END_FORM_OP
) && (MenuOption
->Tags
[Index
].Operand
!= EFI_IFR_END_ONE_OF_OP
);
110 switch (MenuOption
->Tags
[Index
].Operand
) {
111 case EFI_IFR_ORDERED_LIST_OP
:
112 case EFI_IFR_ONE_OF_OP
:
113 CachedStart
= MenuOption
->Tags
[Index
].StorageStart
;
116 case EFI_IFR_ONE_OF_OPTION_OP
:
117 if (MenuOption
->Tags
[Index
].Flags
& EFI_IFR_FLAG_DEFAULT
) {
118 CopyMem (&NvRamMap
[CachedStart
], &MenuOption
->Tags
[Index
].Value
, 2);
122 case EFI_IFR_CHECKBOX_OP
:
123 CopyMem (&NvRamMap
[MenuOption
->Tags
[Index
].StorageStart
], &MenuOption
->Tags
[Index
].Flags
, 1);
126 case EFI_IFR_NUMERIC_OP
:
127 case EFI_IFR_DATE_OP
:
128 case EFI_IFR_TIME_OP
:
129 case EFI_IFR_STRING_OP
:
130 case EFI_IFR_PASSWORD_OP
:
132 &NvRamMap
[MenuOption
->Tags
[Index
].StorageStart
],
133 &MenuOption
->Tags
[Index
].Value
,
134 MenuOption
->Tags
[Index
].StorageWidth
141 FreePool (VariableDefinition
->NvRamMap
);
142 VariableDefinition
->NvRamMap
= NvRamMap
;
143 VariableDefinition
->VariableFakeSize
= (UINT16
) SizeRequired
;
148 IN UI_MENU_OPTION
*MenuOption
,
150 IN EFI_FILE_FORM_TAGS
*FileFormTagsHead
,
151 IN EFI_IFR_DATA_ARRAY
*PageData
,
152 OUT CHAR16
**OptionString
159 EFI_FILE_FORM_TAGS
*FileFormTags
;
161 CHAR16 FormattedNumber
[6];
172 EFI_FORM_CALLBACK_PROTOCOL
*FormCallback
;
174 CHAR16 NullCharacter
;
176 EFI_VARIABLE_DEFINITION
*VariableDefinition
;
182 FileFormTags
= FileFormTagsHead
;
184 for (Index
= 0; Index
< MenuOption
->IfrNumber
; Index
++) {
185 FileFormTags
= FileFormTags
->NextFile
;
191 VariableDefinition
= NULL
;
194 ZeroMem (&Time
, sizeof (EFI_TIME
));
196 StringPtr
= (CHAR16
*) L
"\0";
197 Tag
= MenuOption
->ThisTag
;
198 ExtractRequestedNvMap (FileFormTags
, Tag
->VariableNumber
, &VariableDefinition
);
200 if (Tag
->StorageStart
> VariableDefinition
->VariableSize
) {
201 NvRamMap
= (UINT16
*) &VariableDefinition
->FakeNvRamMap
[Tag
->StorageStart
];
203 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
210 NullCharacter
= CHAR_NULL
;
213 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_ORDERED_LIST_OP
) {
215 if (((UINT8
*) NvRamMap
)[0] != 0x00) {
220 ZeroMem (FormattedNumber
, 12);
222 Status
= gBS
->HandleProtocol (
223 (VOID
*) (UINTN
) FileFormTags
->FormTags
.Tags
[0].CallbackHandle
,
224 &gEfiFormCallbackProtocolGuid
,
225 (VOID
**) &FormCallback
228 if (*OptionString
!= NULL
) {
229 FreePool (*OptionString
);
230 *OptionString
= NULL
;
233 switch (Tag
->Operand
) {
235 case EFI_IFR_ORDERED_LIST_OP
:
236 case EFI_IFR_ONE_OF_OP
:
238 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
239 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
240 // the NvMap so that we can properly display the information
242 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
243 AdjustNvMap (FileFormTags
, MenuOption
);
244 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
247 CachedIndex
= MenuOption
->TagIndex
;
250 // search for EFI_IFR_ONE_OF_OPTION_OP until you hit the EFI_IFR_END_ONE_OF_OP,
251 // each of the .Text in the options are going to be what gets displayed. Break each into 26 char chunks
252 // when hit right/left arrow allows for selection - then repopulate Tag[TagIndex] with the choice
254 for (Index
= MenuOption
->TagIndex
; MenuOption
->Tags
[Index
].Operand
!= EFI_IFR_END_ONE_OF_OP
; Index
++) {
256 // We found an option - which assumedly has a string. We will eventually have to support
257 // wrapping of strings. For now, let's pretend they don't wrap and code that up.
259 // Count how many strings there are
261 if (MenuOption
->Tags
[Index
].Operand
== EFI_IFR_ONE_OF_OPTION_OP
) {
263 // If one of the options for the one-of has an interactive flag, back-define the oneof to have one too
265 if (MenuOption
->Tags
[Index
].Flags
& EFI_IFR_FLAG_INTERACTIVE
) {
266 MenuOption
->Tags
[CachedIndex
].Flags
= (UINT8
) (MenuOption
->Tags
[CachedIndex
].Flags
| EFI_IFR_FLAG_INTERACTIVE
);
273 // We now know how many strings we will have, so we can allocate the
274 // space required for the array or strings.
276 *OptionString
= AllocateZeroPool (StringCount
* (gOptionBlockWidth
+ 1) * 2 * gScreenDimensions
.BottomRow
);
277 ASSERT (*OptionString
);
280 // Add left delimeter to string
282 *OptionString
[0] = LEFT_ONEOF_DELIMITER
;
285 // Retrieve the current OneOf value
289 // Auto selection from list
293 // Copy current setting to the seed Value
295 if (Tag
->Operand
== EFI_IFR_ORDERED_LIST_OP
) {
296 ValueArray
= AllocateZeroPool (MenuOption
->ThisTag
->StorageWidth
);
297 ASSERT (ValueArray
!= NULL
);
298 CopyMem (ValueArray
, NvRamMap
, MenuOption
->ThisTag
->StorageWidth
);
300 CopyMem (&Value
, NvRamMap
, MenuOption
->ThisTag
->StorageWidth
);
301 CopyMem (gPreviousValue
, NvRamMap
, MenuOption
->ThisTag
->StorageWidth
);
305 if (Tag
->Operand
== EFI_IFR_ORDERED_LIST_OP
) {
306 Status
= GetSelectionInputPopUp (MenuOption
, Tag
, MenuOption
->ThisTag
->StorageWidth
, ValueArray
, &KeyValue
);
308 Status
= GetSelectionInputPopUp (MenuOption
, Tag
, 1, &Value
, &KeyValue
);
311 if (!EFI_ERROR (Status
)) {
312 if (Tag
->Operand
== EFI_IFR_ORDERED_LIST_OP
) {
313 CopyMem (NvRamMap
, ValueArray
, MenuOption
->ThisTag
->StorageWidth
);
314 FreePool (ValueArray
);
317 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
319 CopyMem (NvRamMap
, &Value
, Tag
->StorageWidth
);
320 MenuOption
->ThisTag
->Key
= KeyValue
;
323 // If a late check is required save off the information. This is used when consistency checks
324 // are required, but certain values might be bound by an impossible consistency check such as
325 // if two questions are bound by consistency checks and each only has two possible choices, there
326 // would be no way for a user to switch the values. Thus we require late checking.
328 if (Tag
->Flags
& EFI_IFR_FLAG_LATE_CHECK
) {
329 CopyMem (&Tag
->OldValue
, &Value
, Tag
->StorageWidth
);
332 // In theory, passing the value and the Id are sufficient to determine what needs
333 // to be done. The Id is the key to look for the entry needed in the Inconsistency
334 // database. That will yields operand and ID data - and since the ID's correspond
335 // to the NV storage, we can determine the values for other IDs there.
337 if (ValueIsNotValid (TRUE
, 0, Tag
, FileFormTags
, &PopUp
)) {
338 if (PopUp
== 0x0000) {
342 if (!Tag
->Suppress
&& !Tag
->GrayOut
) {
343 CopyMem (NvRamMap
, &Number
, MenuOption
->ThisTag
->StorageWidth
);
348 StringPtr
= GetToken (PopUp
, MenuOption
->Handle
);
350 CreatePopUp (GetStringWidth (StringPtr
) / 2, 3, &NullCharacter
, StringPtr
, &NullCharacter
);
353 Status
= WaitForKeyStroke (&Key
);
355 switch (Key
.UnicodeChar
) {
357 case CHAR_CARRIAGE_RETURN
:
359 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
361 CopyMem (NvRamMap
, &Number
, MenuOption
->ThisTag
->StorageWidth
);
362 FreePool (StringPtr
);
368 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
373 UpdateStatusBar (NV_UPDATE_REQUIRED
, Tag
->Flags
, TRUE
);
375 if (Tag
->Operand
== EFI_IFR_ORDERED_LIST_OP
) {
376 FreePool (ValueArray
);
382 for (Index
= MenuOption
->TagIndex
; MenuOption
->Tags
[Index
].Operand
!= EFI_IFR_END_ONE_OF_OP
; Index
++) {
384 // We found an option - which assumedly has a string. We will eventually have to support
385 // wrapping of strings. For now, let's pretend they don't wrap and code that up.
387 if (MenuOption
->Tags
[Index
].Operand
== EFI_IFR_ONE_OF_OPTION_OP
) {
391 // If the first entry is invalid, then the "default" settings are based on what is reflected
392 // in the order of the op-codes
394 ((UINT8
*) NvRamMap
)[Index
- MenuOption
->TagIndex
- 1] = (UINT8
) MenuOption
->Tags
[Index
].Value
;
397 // Only display 3 lines of stuff at most
399 if ((Index
- MenuOption
->TagIndex
) > ORDERED_LIST_SIZE
) {
403 if (((Index
- MenuOption
->TagIndex
) != 1) && !Skip
) {
404 Character
[0] = LEFT_ONEOF_DELIMITER
;
405 NewStrCat (OptionString
[0], Character
);
408 MenuOption
->ThisTag
->NumberOfLines
= (UINT16
) (Index
- MenuOption
->TagIndex
);
410 StringPtr
= GetToken (MenuOption
->Tags
[Index
].Text
, MenuOption
->Handle
);
412 for (Value
= (UINT16
) (MenuOption
->TagIndex
+ 1);
413 MenuOption
->Tags
[Value
].Operand
!= EFI_IFR_END_ONE_OF_OP
;
416 if (MenuOption
->Tags
[Value
].Value
== ((UINT8
*) NvRamMap
)[Index
- MenuOption
->TagIndex
- 1]) {
417 StringPtr
= GetToken (MenuOption
->Tags
[Value
].Text
, MenuOption
->Handle
);
422 if (MenuOption
->Tags
[Value
].Operand
== EFI_IFR_END_ONE_OF_OP
) {
429 NewStrCat (OptionString
[0], StringPtr
);
430 Character
[0] = RIGHT_ONEOF_DELIMITER
;
431 NewStrCat (OptionString
[0], Character
);
432 Character
[0] = CHAR_CARRIAGE_RETURN
;
433 NewStrCat (OptionString
[0], Character
);
436 // Remove Buffer allocated for StringPtr after it has been used.
438 FreePool (StringPtr
);
441 // The option value is the same as what is stored in NV store. Print this.
443 if (!CompareMem (&(MenuOption
->Tags
[Index
].Value
), NvRamMap
, MenuOption
->ThisTag
->StorageWidth
)) {
444 StringPtr
= GetToken (MenuOption
->Tags
[Index
].Text
, MenuOption
->Handle
);
445 NewStrCat (OptionString
[0], StringPtr
);
446 Character
[0] = RIGHT_ONEOF_DELIMITER
;
447 NewStrCat (OptionString
[0], Character
);
449 // Remove Buffer allocated for StringPtr after it has been used.
451 FreePool (StringPtr
);
456 if ((MenuOption
->Tags
[Index
].Flags
& EFI_IFR_FLAG_DEFAULT
) == 1) {
457 Default
= MenuOption
->Tags
[Index
].Text
;
458 Value
= MenuOption
->Tags
[Index
].Value
;
464 // We didn't find a value that matched a setting in the NVRAM Map - display default - set default
468 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
470 CopyMem (NvRamMap
, &Value
, MenuOption
->ThisTag
->StorageWidth
);
472 StringPtr
= GetToken ((UINT16
) Default
, MenuOption
->Handle
);
473 NewStrCat (OptionString
[0], StringPtr
);
474 Character
[0] = RIGHT_ONEOF_DELIMITER
;
475 NewStrCat (OptionString
[0], Character
);
477 // Remove Buffer allocated for StringPtr after it has been used.
479 FreePool (StringPtr
);
484 case EFI_IFR_CHECKBOX_OP
:
486 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
487 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
488 // the NvMap so that we can properly display the information
490 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
491 AdjustNvMap (FileFormTags
, MenuOption
);
492 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
495 Default
= Tag
->Flags
& 1;
497 // If hit spacebar, set or unset Tag[TagIndex].Flags based on it's previous value - BOOLEAN
499 *OptionString
= AllocateZeroPool ((gOptionBlockWidth
+ 1) * 2 * gScreenDimensions
.BottomRow
);
500 ASSERT (*OptionString
);
503 // Since Checkboxes are BOOLEAN values, bit 0 of the Flags bit defines the default option, therefore, if
504 // the default option (only one option for checkboxes) is on, then the default value is on. Tag.Default is not
505 // an active field for Checkboxes.
507 StrnCpy (OptionString
[0], (CHAR16
*) LEFT_CHECKBOX_DELIMITER
, 1);
510 // Since this is a BOOLEAN operation, flip bit 0 upon selection
513 Tag
->Value
= (UINT16
) (Tag
->Value
^ 1);
514 *(UINT8
*) NvRamMap
= (UINT8
) (Tag
->Value
& 1);
515 UpdateStatusBar (NV_UPDATE_REQUIRED
, Tag
->Flags
, TRUE
);
518 if ((*(UINT8
*) NvRamMap
& 1) == 0x01) {
519 NewStrCat (OptionString
[0], (CHAR16
*) CHECK_ON
);
521 // If someone reset default variables - we may need to reload from our NvMapping....
523 Tag
->Value
= *(UINT8
*) NvRamMap
;
526 // If someone reset default variables - we may need to reload from our NvMapping....
528 NewStrCat (OptionString
[0], (CHAR16
*) CHECK_OFF
);
529 Tag
->Value
= *(UINT8
*) NvRamMap
;
532 NewStrCat (OptionString
[0], (CHAR16
*) RIGHT_CHECKBOX_DELIMITER
);
533 NewStrCat (OptionString
[0], StringPtr
);
536 case EFI_IFR_NUMERIC_OP
:
538 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
539 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
540 // the NvMap so that we can properly display the information
542 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
543 AdjustNvMap (FileFormTags
, MenuOption
);
544 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
547 *OptionString
= AllocateZeroPool ((gOptionBlockWidth
+ 1) * 2 * gScreenDimensions
.BottomRow
);
548 ASSERT (*OptionString
);
551 // Add left delimeter to string
553 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
556 // Retrieve the current numeric value
562 if (Tag
->Step
== 0) {
566 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, TRUE
, Tag
, REGULAR_NUMERIC
, &Number
);
567 if (!EFI_ERROR (Status
)) {
568 CopyMem (gPreviousValue
, NvRamMap
, MenuOption
->ThisTag
->StorageWidth
);
569 UpdateStatusBar (NV_UPDATE_REQUIRED
, Tag
->Flags
, TRUE
);
572 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
574 CopyMem (NvRamMap
, &Number
, MenuOption
->ThisTag
->StorageWidth
);
580 // Auto selection from list
582 if ((((Tag
->StorageWidth
== 1) && (UINT8
) (*NvRamMap
) > Tag
->Maximum
) || ((UINT8
) (*NvRamMap
) < Tag
->Minimum
)) ||
583 (((Tag
->StorageWidth
== 2) && *NvRamMap
> Tag
->Maximum
) || (*NvRamMap
< Tag
->Minimum
))
586 // Seed Number with valid value if currently invalid
588 Number
= Tag
->Default
;
590 if (Tag
->StorageWidth
== 1) {
591 Number
= (UINT8
) (*NvRamMap
);
597 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, FALSE
, Tag
, REGULAR_NUMERIC
, &Number
);
598 if (!EFI_ERROR (Status
)) {
599 CopyMem (gPreviousValue
, NvRamMap
, MenuOption
->ThisTag
->StorageWidth
);
600 UpdateStatusBar (NV_UPDATE_REQUIRED
, Tag
->Flags
, TRUE
);
603 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
605 CopyMem (NvRamMap
, &Number
, MenuOption
->ThisTag
->StorageWidth
);
611 if (((Tag
->StorageWidth
== 1) && (UINT8
) (*NvRamMap
) <= Tag
->Maximum
&& (UINT8
) (*NvRamMap
) >= Tag
->Minimum
) ||
612 ((Tag
->StorageWidth
== 2) && *NvRamMap
<= Tag
->Maximum
&& *NvRamMap
>= Tag
->Minimum
)
614 if (Tag
->StorageWidth
== 1) {
615 Number
= (UINT8
) (*NvRamMap
);
619 UnicodeValueToString (
623 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
625 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
626 StrnCpy (OptionString
[0] + 1, FormattedNumber
, Number
);
629 // If *NvRamMap isn't within parameters, set it to within parameters
632 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
634 CopyMem (NvRamMap
, &Tag
->Default
, MenuOption
->ThisTag
->StorageWidth
);
635 Number
= Tag
->Default
;
637 UnicodeValueToString (
641 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
643 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
644 StrnCpy (OptionString
[0] + 1, FormattedNumber
, Number
);
647 *(OptionString
[0] + Number
/ 2) = RIGHT_NUMERIC_DELIMITER
;
648 NewStrCat (OptionString
[0] + (Number
/ 2) + 1, StringPtr
);
652 case EFI_IFR_DATE_OP
:
654 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
655 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
656 // the NvMap so that we can properly display the information
658 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
659 AdjustNvMap (FileFormTags
, MenuOption
);
660 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
663 Status
= gRT
->GetTime (&Time
, NULL
);
664 if (EFI_ERROR (Status
)) {
668 // This for loop advances Index till it points immediately after a date entry. We can then
669 // subtract MenuOption->TagIndex from Index and find out relative to the start of the Date
670 // structure which field we were in. For instance, if TagIndex was 52, and we advanced Index
671 // to 53 and found it to no longer point to a date operand, we were pointing to the last of 3
675 // This has BUGBUG potential....fix this - if someone wants to ask two DATE questions in a row.....code
676 // against such silliness.
678 // Also, we want to internationalize the order of the date information. We need to code for it as well.
680 for (Index
= MenuOption
->TagIndex
; MenuOption
->Tags
[Index
].Operand
== EFI_IFR_DATE_OP
; Index
++)
684 // Count 0 = We entered on the first Date operand
685 // Count 1 = We entered on the second Date operand
686 // Count 2 = We entered on the third Date operand
688 Count
= 3 - (Index
- MenuOption
->TagIndex
);
693 // This is similar to numerics, except for the following:
694 // We will under normal circumstances get 3 consecutive calls
695 // to process this opcodes data.
697 *OptionString
= AllocateZeroPool ((gOptionBlockWidth
+ 1) * 2 * gScreenDimensions
.BottomRow
);
698 ASSERT (*OptionString
);
703 Number
= (UINT16
) Time
.Month
;
705 if (Tag
->Step
== 0) {
706 MenuOption
->OptCol
++;
707 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, TRUE
, Tag
, DATE_NUMERIC
, &Number
);
710 // Seed value with current setting
712 Tag
->Value
= (UINT16
) Time
.Month
;
713 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, FALSE
, Tag
, DATE_NUMERIC
, &Number
);
716 if (!EFI_ERROR (Status
)) {
717 Time
.Month
= (UINT8
) Number
;
718 gRT
->SetTime (&Time
);
722 VariableDefinition
->FakeNvRamMap
[Tag
->Id
] = Time
.Month
;
723 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
725 UnicodeValueToString (
729 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
731 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
734 FormattedNumber
[2] = FormattedNumber
[1];
735 FormattedNumber
[1] = FormattedNumber
[0];
736 FormattedNumber
[0] = L
'0';
740 StrnCpy (OptionString
[0] + 1, FormattedNumber
, Number
);
741 *(OptionString
[0] + Number
/ 2) = DATE_SEPARATOR
;
742 StrCat (OptionString
[0] + (Number
/ 2) + 1, StringPtr
);
747 Number
= (UINT16
) Time
.Day
;
749 if (Tag
->Step
== 0) {
750 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, TRUE
, Tag
, DATE_NUMERIC
, &Number
);
753 // Seed value with current setting
755 Tag
->Value
= (UINT16
) Time
.Day
;
756 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, FALSE
, Tag
, DATE_NUMERIC
, &Number
);
759 if (!EFI_ERROR (Status
)) {
760 Time
.Day
= (UINT8
) Number
;
761 gRT
->SetTime (&Time
);
765 VariableDefinition
->FakeNvRamMap
[Tag
->Id
] = Time
.Day
;
766 SetUnicodeMem (OptionString
[0], 4, L
' ');
768 UnicodeValueToString (
772 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
774 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
776 FormattedNumber
[2] = FormattedNumber
[1];
777 FormattedNumber
[1] = FormattedNumber
[0];
778 FormattedNumber
[0] = L
'0';
782 StrnCpy (OptionString
[0] + 4, FormattedNumber
, Number
);
783 *(OptionString
[0] + Number
/ 2 + 3) = DATE_SEPARATOR
;
784 StrCat (OptionString
[0] + (Number
/ 2) + 4, StringPtr
);
789 Number
= (UINT16
) Time
.Year
;
791 if (Tag
->Step
== 0) {
792 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, TRUE
, Tag
, DATE_NUMERIC
, &Number
);
795 // Seed value with current setting
797 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, FALSE
, Tag
, DATE_NUMERIC
, &Number
);
800 if (!EFI_ERROR (Status
)) {
801 Time
.Year
= (UINT16
) Number
;
802 gRT
->SetTime (&Time
);
806 Tag
->Value
= (UINT16
) Time
.Year
;
807 VariableDefinition
->FakeNvRamMap
[Tag
->Id
] = (UINT8
) Tag
->Value
;
808 VariableDefinition
->FakeNvRamMap
[Tag
->Id
+ 1] = (UINT8
) (Tag
->Value
>> 8);
809 SetUnicodeMem (OptionString
[0], 7, L
' ');
810 UnicodeValueToString (
814 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
816 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
817 StrnCpy (OptionString
[0] + 7, FormattedNumber
, Number
);
818 *(OptionString
[0] + Number
/ 2 + 6) = RIGHT_NUMERIC_DELIMITER
;
819 StrCat (OptionString
[0] + (Number
/ 2) + 7, StringPtr
);
826 // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG
827 // We need to add code to support the NVRam storage version of Date - this is the 1% case where someone
828 // might want to set an alarm and actually preserve the data in NVRam so a driver can pick up the instruction
829 // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG
831 case EFI_IFR_TIME_OP
:
833 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
834 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
835 // the NvMap so that we can properly display the information
837 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
838 AdjustNvMap (FileFormTags
, MenuOption
);
839 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
842 Status
= gRT
->GetTime (&Time
, NULL
);
843 if (EFI_ERROR (Status
)) {
847 // This is similar to numerics, except for the following:
848 // We will under normal circumstances get 3 consecutive calls
849 // to process this opcodes data.
851 *OptionString
= AllocateZeroPool ((gOptionBlockWidth
+ 1) * 2 * gScreenDimensions
.BottomRow
);
852 ASSERT (*OptionString
);
855 // This for loop advances Index till it points immediately after a date entry. We can then
856 // subtract MenuOption->TagIndex from Index and find out relative to the start of the Date
857 // structure which field we were in. For instance, if TagIndex was 52, and we advanced Index
858 // to 53 and found it to no longer point to a date operand, we were pointing to the last of 3
861 for (Index
= MenuOption
->TagIndex
; MenuOption
->Tags
[Index
].Operand
== EFI_IFR_TIME_OP
; Index
++)
864 // Count 0 = We entered on the first Date operand
865 // Count 1 = We entered on the second Date operand
866 // Count 2 = We entered on the third Date operand
868 Count
= 3 - (Index
- MenuOption
->TagIndex
);
879 Number
= Time
.Minute
;
883 Number
= Time
.Second
;
886 // Retrieve the current numeric value
892 if (Tag
->Step
== 0) {
896 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, TRUE
, Tag
, TIME_NUMERIC
, &Number
);
897 if (!EFI_ERROR (Status
)) {
900 gRT
->SetTime (&Time
);
906 // Auto selection from list
908 Status
= GetNumericInput (MenuOption
, FileFormTagsHead
, FALSE
, Tag
, TIME_NUMERIC
, &Number
);
909 if (!EFI_ERROR (Status
)) {
918 Time
.Hour
= (UINT8
) Number
;
922 Time
.Minute
= (UINT8
) Number
;
926 Time
.Second
= (UINT8
) Number
;
930 gRT
->SetTime (&Time
);
934 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
935 UnicodeValueToString (
939 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
941 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
943 FormattedNumber
[2] = FormattedNumber
[1];
944 FormattedNumber
[1] = FormattedNumber
[0];
945 FormattedNumber
[0] = L
'0';
949 StrnCpy (OptionString
[0] + 1, FormattedNumber
, Number
);
950 *(OptionString
[0] + Number
/ 2) = TIME_SEPARATOR
;
951 StrCat (OptionString
[0] + (Number
/ 2) + 1, StringPtr
);
955 SetUnicodeMem (OptionString
[0], 4, L
' ');
956 UnicodeValueToString (
960 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
962 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
964 FormattedNumber
[2] = FormattedNumber
[1];
965 FormattedNumber
[1] = FormattedNumber
[0];
966 FormattedNumber
[0] = L
'0';
970 StrnCpy (OptionString
[0] + 4, FormattedNumber
, Number
);
971 *(OptionString
[0] + Number
/ 2 + 3) = TIME_SEPARATOR
;
972 StrCat (OptionString
[0] + (Number
/ 2) + 4, StringPtr
);
976 SetUnicodeMem (OptionString
[0], 7, L
' ');
977 UnicodeValueToString (
981 (sizeof (FormattedNumber
) / sizeof (FormattedNumber
[0]))
983 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
985 FormattedNumber
[2] = FormattedNumber
[1];
986 FormattedNumber
[1] = FormattedNumber
[0];
987 FormattedNumber
[0] = L
'0';
991 StrnCpy (OptionString
[0] + 7, FormattedNumber
, Number
);
992 *(OptionString
[0] + Number
/ 2 + 6) = RIGHT_NUMERIC_DELIMITER
;
993 StrCat (OptionString
[0] + (Number
/ 2) + 7, StringPtr
);
997 // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG
998 // We need to add code to support the NVRam storage version of Date - this is the 1% case where someone
999 // might want to set an alarm and actually preserve the data in NVRam so a driver can pick up the instruction
1000 // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG
1005 case EFI_IFR_STRING_OP
:
1007 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
1008 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
1009 // the NvMap so that we can properly display the information
1011 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
1012 AdjustNvMap (FileFormTags
, MenuOption
);
1013 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
1016 *OptionString
= AllocateZeroPool ((gOptionBlockWidth
+ 1) * 2 * gScreenDimensions
.BottomRow
);
1017 ASSERT (*OptionString
);
1020 StringPtr
= AllocateZeroPool (Tag
->Maximum
);
1023 Status
= ReadString (MenuOption
, StringPtr
);
1025 if (!EFI_ERROR (Status
)) {
1026 CopyMem (gPreviousValue
, NvRamMap
, MenuOption
->ThisTag
->StorageWidth
);
1027 CopyMem (&VariableDefinition
->NvRamMap
[Tag
->StorageStart
], StringPtr
, Tag
->StorageWidth
);
1029 UpdateStatusBar (NV_UPDATE_REQUIRED
, Tag
->Flags
, TRUE
);
1032 FreePool (StringPtr
);
1035 for (Index
= 0; Index
< gOptionBlockWidth
; Index
++) {
1036 if (VariableDefinition
->NvRamMap
[Tag
->StorageStart
+ (Index
* 2)] != 0x0000) {
1037 CopyMem (OptionString
[0] + Index
, &VariableDefinition
->NvRamMap
[Tag
->StorageStart
+ (Index
* 2)], 2);
1040 *(OptionString
[0] + Index
) = '_';
1041 *(OptionString
[0] + 1 + Index
) = 0;
1050 case EFI_IFR_PASSWORD_OP
:
1052 // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
1053 // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
1054 // the NvMap so that we can properly display the information
1056 if ((UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
) > VariableDefinition
->VariableFakeSize
) {
1057 AdjustNvMap (FileFormTags
, MenuOption
);
1058 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
1062 StringPtr
= AllocateZeroPool (Tag
->Maximum
);
1066 // If interactive, read the password and do the appropriate callbacks in that routine.
1067 // Since interactive passwords assume to handle the password data in a separate variable
1068 // storage, we don't need to do more than what is below for password callbacks
1070 if (Tag
->Flags
& EFI_IFR_FLAG_INTERACTIVE
) {
1071 MenuOption
->Tags
[0].CallbackHandle
= FileFormTags
->FormTags
.Tags
[0].CallbackHandle
;
1072 Status
= ReadPassword (MenuOption
, TRUE
, Tag
, PageData
, FALSE
, FileFormTags
, StringPtr
);
1073 ZeroMem (StringPtr
, Tag
->Maximum
);
1075 if (EFI_ERROR (Status
)) {
1076 if (Status
== EFI_NOT_READY
) {
1077 FreePool (StringPtr
);
1082 Status
= ReadPassword (MenuOption
, TRUE
, Tag
, PageData
, TRUE
, FileFormTags
, StringPtr
);
1083 FreePool (StringPtr
);
1087 for (Index
= 0; Index
< Tag
->Maximum
; Index
++) {
1088 if (VariableDefinition
->NvRamMap
[Tag
->StorageStart
+ Index
] != 0x00) {
1090 // There is something there! Prompt for password
1092 Status
= ReadPassword (MenuOption
, TRUE
, Tag
, PageData
, FALSE
, FileFormTags
, StringPtr
);
1093 if (EFI_ERROR (Status
)) {
1094 FreePool (StringPtr
);
1098 if (Tag
->Encoding
== 1) {
1099 EncodePassword (StringPtr
, (UINT8
) Tag
->Maximum
);
1100 Status
= CompareMem (StringPtr
, &VariableDefinition
->NvRamMap
[Tag
->StorageStart
], Tag
->Maximum
);
1102 Status
= CompareMem (StringPtr
, &VariableDefinition
->NvRamMap
[Tag
->StorageStart
], Tag
->Maximum
);
1106 FreePool (StringPtr
);
1116 ZeroMem (StringPtr
, Tag
->Maximum
);
1119 // No password set! Go ahead and prompt the user for a password.
1121 Status
= ReadPassword (MenuOption
, FALSE
, Tag
, PageData
, FALSE
, FileFormTags
, StringPtr
);
1123 if (EFI_ERROR (Status
)) {
1125 // User couldn't figure out how to type two identical passwords
1127 FreePool (StringPtr
);
1131 // Very simple example of how one MIGHT do password encoding
1133 if (Tag
->Encoding
== 1) {
1134 EncodePassword (StringPtr
, (UINT8
) Tag
->Maximum
);
1137 TmpNvRamMap
= AllocatePool (VariableDefinition
->VariableSize
);
1138 ASSERT (TmpNvRamMap
!= NULL
);
1140 Count
= VariableDefinition
->VariableSize
;
1142 if ((FormCallback
!= NULL
) && (FormCallback
->NvRead
!= NULL
)) {
1143 Status
= FormCallback
->NvRead (
1145 VariableDefinition
->VariableName
,
1146 &VariableDefinition
->Guid
,
1149 (VOID
*) TmpNvRamMap
1152 Status
= gRT
->GetVariable (
1153 VariableDefinition
->VariableName
,
1154 &VariableDefinition
->Guid
,
1157 (VOID
*) TmpNvRamMap
1161 CopyMem (&VariableDefinition
->NvRamMap
[Tag
->StorageStart
], StringPtr
, Tag
->StorageWidth
);
1162 CopyMem (&TmpNvRamMap
[Tag
->StorageStart
], StringPtr
, Tag
->StorageWidth
);
1164 if ((FormCallback
!= NULL
) && (FormCallback
->NvWrite
!= NULL
)) {
1165 Status
= FormCallback
->NvWrite (
1167 VariableDefinition
->VariableName
,
1168 &VariableDefinition
->Guid
,
1169 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1170 VariableDefinition
->VariableSize
,
1171 (VOID
*) TmpNvRamMap
,
1175 Status
= gRT
->SetVariable (
1176 VariableDefinition
->VariableName
,
1177 &VariableDefinition
->Guid
,
1178 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1179 VariableDefinition
->VariableSize
,
1180 (VOID
*) TmpNvRamMap
1184 FreePool (TmpNvRamMap
);
1185 FreePool (StringPtr
);
1197 Split StringPtr to several lines of strings stored in FormattedString and the glyph width of
1198 each line cannot exceed gHelpBlockWidth.
1200 @param StringPtr The pointer of string
1201 @param FormattedString The pointer of format string
1202 @param RowCount The count of row
1207 IN CHAR16
*StringPtr
,
1208 OUT CHAR16
**FormattedString
,
1212 CONST UINTN BlockWidth
= (UINTN
) gHelpBlockWidth
- 1;
1215 // [PrevCurrIndex, CurrIndex) forms a range of a screen-line
1218 UINTN PrevCurrIndex
;
1220 UINTN VirtualLineCount
;
1222 // GlyphOffset stores glyph width of current screen-line
1226 // GlyphWidth equals to 2 if we meet width directive
1230 // during scanning, we remember the position of last space character
1231 // in case that if next word cannot put in current line, we could restore back to the position
1232 // of last space character
1233 // while we should also remmeber the glyph width of the last space character for restoring
1235 UINTN LastSpaceIndex
;
1236 UINTN LastSpaceGlyphWidth
;
1238 // every time we begin to form a new screen-line, we should remember glyph width of single character
1241 UINTN LineStartGlyphWidth
;
1243 UINTN
*OldIndexArray
;
1246 // every three elements of IndexArray form a screen-line of string:[ IndexArray[i*3], IndexArray[i*3+1] )
1247 // IndexArray[i*3+2] stores the initial glyph width of single character. to save this is because we want
1248 // to bring the width directive of the last line to current screen-line.
1249 // e.g.: "\wideabcde ... fghi", if "fghi" also has width directive but is splitted to the next screen-line
1250 // different from that of "\wideabcde", we should remember the width directive.
1252 AllocateSize
= 0x20;
1253 IndexArray
= AllocatePool (AllocateSize
* sizeof (UINTN
) * 3);
1255 if (*FormattedString
!= NULL
) {
1256 FreePool (*FormattedString
);
1257 *FormattedString
= NULL
;
1260 for (PrevCurrIndex
= 0, CurrIndex
= 0, LineCount
= 0, LastSpaceIndex
= 0,
1261 IndexArray
[0] = 0, GlyphWidth
= 1, GlyphOffset
= 0, LastSpaceGlyphWidth
= 1, LineStartGlyphWidth
= 1;
1262 (StringPtr
[CurrIndex
] != CHAR_NULL
);
1265 if (LineCount
== AllocateSize
) {
1266 AllocateSize
+= 0x10;
1267 OldIndexArray
= IndexArray
;
1268 IndexArray
= AllocatePool (AllocateSize
* sizeof (UINTN
) * 3);
1269 CopyMem (IndexArray
, OldIndexArray
, LineCount
* sizeof (UINTN
) * 3);
1270 if (OldIndexArray
!= NULL
) {
1271 FreePool (OldIndexArray
);
1275 switch (StringPtr
[CurrIndex
]) {
1279 GlyphWidth
= ((StringPtr
[CurrIndex
] == WIDE_CHAR
) ? 2 : 1);
1280 if (CurrIndex
== 0) {
1281 LineStartGlyphWidth
= GlyphWidth
;
1287 // "\r\n" isn't handled here, handled by case CHAR_CARRIAGE_RETURN
1291 // Store a range of string as a line
1293 IndexArray
[LineCount
*3] = PrevCurrIndex
;
1294 IndexArray
[LineCount
*3+1] = CurrIndex
;
1295 IndexArray
[LineCount
*3+2] = LineStartGlyphWidth
;
1298 // Reset offset and save begin position of line
1301 LineStartGlyphWidth
= GlyphWidth
;
1302 PrevCurrIndex
= CurrIndex
+ 1;
1307 // "\r\n" and "\r" both are handled here
1309 case CHAR_CARRIAGE_RETURN
:
1310 if (StringPtr
[CurrIndex
+ 1] == CHAR_LINEFEED
) {
1312 // next char is '\n'
1314 IndexArray
[LineCount
*3] = PrevCurrIndex
;
1315 IndexArray
[LineCount
*3+1] = CurrIndex
;
1316 IndexArray
[LineCount
*3+2] = LineStartGlyphWidth
;
1321 LineStartGlyphWidth
= GlyphWidth
;
1322 PrevCurrIndex
= CurrIndex
+ 1;
1326 // char is space or other char
1329 GlyphOffset
+= GlyphWidth
;
1330 if (GlyphOffset
>= BlockWidth
) {
1331 if (LastSpaceIndex
> PrevCurrIndex
) {
1333 // LastSpaceIndex points to space inside current screen-line,
1334 // restore to LastSpaceIndex
1335 // (Otherwise the word is too long to fit one screen-line, just cut it)
1337 CurrIndex
= LastSpaceIndex
;
1338 GlyphWidth
= LastSpaceGlyphWidth
;
1339 } else if (GlyphOffset
> BlockWidth
) {
1341 // the word is too long to fit one screen-line and we don't get the chance
1342 // of GlyphOffset == BlockWidth because GlyphWidth = 2
1347 IndexArray
[LineCount
*3] = PrevCurrIndex
;
1348 IndexArray
[LineCount
*3+1] = CurrIndex
+ 1;
1349 IndexArray
[LineCount
*3+2] = LineStartGlyphWidth
;
1350 LineStartGlyphWidth
= GlyphWidth
;
1353 // Reset offset and save begin position of line
1356 PrevCurrIndex
= CurrIndex
+ 1;
1360 // LastSpaceIndex: remember position of last space
1362 if (StringPtr
[CurrIndex
] == CHAR_SPACE
) {
1363 LastSpaceIndex
= CurrIndex
;
1364 LastSpaceGlyphWidth
= GlyphWidth
;
1370 if (GlyphOffset
> 0) {
1371 IndexArray
[LineCount
*3] = PrevCurrIndex
;
1372 IndexArray
[LineCount
*3+1] = CurrIndex
;
1373 IndexArray
[LineCount
*3+2] = GlyphWidth
;
1377 if (LineCount
== 0) {
1379 // in case we meet null string
1384 // we assume null string's glyph width is 1
1390 VirtualLineCount
= RowCount
* (LineCount
/ RowCount
+ (LineCount
% RowCount
> 0));
1391 *FormattedString
= AllocateZeroPool (VirtualLineCount
* (BlockWidth
+ 1) * sizeof (CHAR16
) * 2);
1393 for (CurrIndex
= 0; CurrIndex
< LineCount
; CurrIndex
++) {
1394 *(*FormattedString
+ CurrIndex
* 2 * (BlockWidth
+ 1)) = (CHAR16
)((IndexArray
[CurrIndex
*3+2] == 2) ? WIDE_CHAR
: NARROW_CHAR
);
1396 *FormattedString
+ CurrIndex
* 2 * (BlockWidth
+ 1) + 1,
1397 StringPtr
+ IndexArray
[CurrIndex
*3],
1398 IndexArray
[CurrIndex
*3+1]-IndexArray
[CurrIndex
*3]
1402 if (IndexArray
!= NULL
) {
1403 FreePool (IndexArray
);
1410 IN EFI_TAG
*TargetTag
,
1412 EFI_VARIABLE_DEFINITION
*VariableDefinitionsHead
1416 CHAR16
*VariableName
;
1418 EFI_VARIABLE_DEFINITION
*VariableDefinitions
;
1419 EFI_VARIABLE_DEFINITION
*PreviousVariableDefinitions
;
1420 STATIC UINT16 VariableSize
;
1422 STATIC UINT16 CurrentVariable
;
1423 STATIC UINT16 CurrentVariable2
;
1427 case EFI_IFR_FORM_OP
:
1428 CopyMem (&TargetTag
->Id
, &((EFI_IFR_FORM
*) FormData
)->FormId
, sizeof (UINT16
));
1429 CopyMem (&TargetTag
->Text
, &((EFI_IFR_FORM
*) FormData
)->FormTitle
, sizeof (UINT16
));
1430 TargetTag
->VariableNumber
= CurrentVariable
;
1431 if (VariableDefinitionsHead
!= NULL
) {
1432 VariableName
= AllocateZeroPool (12);
1433 ASSERT (VariableName
!= NULL
);
1434 CopyMem (VariableName
, L
"Setup", 12);
1435 VariableDefinitionsHead
->VariableName
= VariableName
;
1436 VariableDefinitionsHead
->VariableSize
= VariableSize
;
1437 CopyMem (&VariableDefinitionsHead
->Guid
, &Guid
, sizeof (EFI_GUID
));
1441 case EFI_IFR_SUBTITLE_OP
:
1442 TargetTag
->NumberOfLines
= 1;
1443 CopyMem (&TargetTag
->Text
, &((EFI_IFR_SUBTITLE
*) FormData
)->SubTitle
, sizeof (UINT16
));
1444 TargetTag
->VariableNumber
= CurrentVariable
;
1447 case EFI_IFR_TEXT_OP
:
1448 TargetTag
->NumberOfLines
= 1;
1449 CopyMem (&TargetTag
->Text
, &((EFI_IFR_TEXT
*) FormData
)->Text
, sizeof (UINT16
));
1450 CopyMem (&TargetTag
->Help
, &((EFI_IFR_TEXT
*) FormData
)->Help
, sizeof (UINT16
));
1451 TargetTag
->VariableNumber
= CurrentVariable
;
1454 // To optimize the encoding size, certain opcodes have optional fields such as those
1455 // inside the if() statement. If the encoded length is the complete size, then we
1456 // know we have valid data encoded that we want to integrate
1458 if (((EFI_IFR_TEXT
*) FormData
)->Header
.Length
== sizeof (EFI_IFR_TEXT
)) {
1460 // Text has no help associated with it, but in case there is a second entry due to
1461 // dynamic/interactive flags being active, bring this data over.
1463 CopyMem (&TargetTag
->TextTwo
, &((EFI_IFR_TEXT
*) FormData
)->TextTwo
, sizeof (UINT16
));
1464 TargetTag
->Flags
= ((EFI_IFR_TEXT
*) FormData
)->Flags
;
1465 CopyMem (&TargetTag
->Key
, &((EFI_IFR_TEXT
*) FormData
)->Key
, sizeof (UINT16
));
1469 case EFI_IFR_ONE_OF_OPTION_OP
:
1470 CopyMem (&TargetTag
->Text
, &((EFI_IFR_ONE_OF_OPTION
*) FormData
)->Option
, sizeof (UINT16
));
1471 CopyMem (&TargetTag
->Value
, &((EFI_IFR_ONE_OF_OPTION
*) FormData
)->Value
, sizeof (UINT16
));
1472 TargetTag
->Flags
= ((EFI_IFR_ONE_OF_OPTION
*) FormData
)->Flags
;
1473 CopyMem (&TargetTag
->Key
, &((EFI_IFR_ONE_OF_OPTION
*) FormData
)->Key
, sizeof (UINT16
));
1474 TargetTag
->VariableNumber
= CurrentVariable
;
1477 case EFI_IFR_CHECKBOX_OP
:
1478 TargetTag
->Flags
= ((EFI_IFR_CHECKBOX
*) FormData
)->Flags
;
1479 TargetTag
->ResetRequired
= (BOOLEAN
) (TargetTag
->Flags
& EFI_IFR_FLAG_RESET_REQUIRED
);
1480 CopyMem (&TargetTag
->Key
, &((EFI_IFR_CHECKBOX
*) FormData
)->Key
, sizeof (UINT16
));
1481 TargetTag
->VariableNumber
= CurrentVariable
;
1484 case EFI_IFR_NUMERIC_OP
:
1485 TargetTag
->Flags
= ((EFI_IFR_NUMERIC
*) FormData
)->Flags
;
1486 CopyMem (&TargetTag
->Key
, &((EFI_IFR_NUMERIC
*) FormData
)->Key
, sizeof (UINT16
));
1487 TargetTag
->VariableNumber
= CurrentVariable
;
1490 case EFI_IFR_STRING_OP
:
1492 // Convert EFI_IFR_STRING.MinSize and EFI_IFR_STRING.MaxSize to actual minimum and maximum bytes
1493 // and store to EFI_TAG.Minimum and EFI_TAG.Maximum
1496 CopyMem (&TempValue
, &((EFI_IFR_STRING
*) FormData
)->MinSize
, sizeof (UINT8
));
1497 TempValue
= (UINT16
) (TempValue
* 2);
1498 CopyMem (&TargetTag
->Minimum
, &TempValue
, sizeof (UINT16
));
1501 CopyMem (&TempValue
, &((EFI_IFR_STRING
*) FormData
)->MaxSize
, sizeof (UINT8
));
1502 TempValue
= (UINT16
) (TempValue
* 2);
1503 CopyMem (&TargetTag
->Maximum
, &TempValue
, sizeof (UINT16
));
1504 CopyMem (&TargetTag
->StorageWidth
, &TempValue
, sizeof (UINT16
));
1505 TargetTag
->Flags
= (UINT8
) (((EFI_IFR_STRING
*) FormData
)->Flags
);
1506 TargetTag
->ResetRequired
= (BOOLEAN
) (TargetTag
->Flags
& EFI_IFR_FLAG_RESET_REQUIRED
);
1507 CopyMem (&TargetTag
->Key
, &((EFI_IFR_STRING
*) FormData
)->Key
, sizeof (UINT16
));
1508 TargetTag
->VariableNumber
= CurrentVariable
;
1511 case EFI_IFR_PASSWORD_OP
:
1513 CopyMem (&TempValue
, &((EFI_IFR_PASSWORD
*) FormData
)->MinSize
, sizeof (UINT8
));
1514 TempValue
= (UINT16
) (TempValue
* 2);
1515 CopyMem (&TargetTag
->Minimum
, &TempValue
, sizeof (UINT16
));
1518 CopyMem (&TempValue
, &((EFI_IFR_PASSWORD
*) FormData
)->MaxSize
, sizeof (UINT8
));
1519 TempValue
= (UINT16
) (TempValue
* 2);
1520 CopyMem (&TargetTag
->Maximum
, &TempValue
, sizeof (UINT16
));
1521 CopyMem (&TargetTag
->StorageWidth
, &TempValue
, sizeof (UINT16
));
1522 TargetTag
->Flags
= ((EFI_IFR_PASSWORD
*) FormData
)->Flags
;
1523 TargetTag
->ResetRequired
= (BOOLEAN
) (TargetTag
->Flags
& EFI_IFR_FLAG_RESET_REQUIRED
);
1524 CopyMem (&TargetTag
->Key
, &((EFI_IFR_PASSWORD
*) FormData
)->Key
, sizeof (UINT16
));
1525 CopyMem (&TargetTag
->Encoding
, &((EFI_IFR_PASSWORD
*) FormData
)->Encoding
, sizeof (UINT16
));
1526 TargetTag
->VariableNumber
= CurrentVariable
;
1529 case EFI_IFR_VARSTORE_OP
:
1531 // It should NEVER be NULL
1533 if (VariableDefinitionsHead
== NULL
) {
1537 VariableDefinitions
= VariableDefinitionsHead
;
1540 // Advance VariableDefinitions to the last entry
1542 for (; VariableDefinitions
!= NULL
; VariableDefinitions
= VariableDefinitions
->Next
) {
1543 PreviousVariableDefinitions
= VariableDefinitions
;
1545 // If there is a variable with this GUID and ID already, we need to bail out
1547 if (!CompareMem (&VariableDefinitions
->Guid
, &((EFI_IFR_VARSTORE
*) FormData
)->Guid
, sizeof (EFI_GUID
)) &&
1548 !CompareMem (&VariableDefinitions
->VariableId
, &((EFI_IFR_VARSTORE
*) FormData
)->VarId
, sizeof (UINT16
))
1553 if (VariableDefinitions
->Next
== NULL
) {
1558 // If the last entry has a variable in it already, allocate a new entry and use it
1560 if (VariableDefinitions
->VariableName
!= NULL
) {
1561 VariableDefinitions
->Next
= AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION
));
1562 ASSERT (VariableDefinitions
->Next
!= NULL
);
1563 PreviousVariableDefinitions
= VariableDefinitions
;
1564 VariableDefinitions
= VariableDefinitions
->Next
;
1565 VariableDefinitions
->Previous
= PreviousVariableDefinitions
;
1568 // Copy the Variable data to our linked list
1570 CopyMem (&VariableDefinitions
->VariableId
, &((EFI_IFR_VARSTORE
*) FormData
)->VarId
, sizeof (UINT16
));
1571 CopyMem (&VariableDefinitions
->VariableSize
, &((EFI_IFR_VARSTORE
*) FormData
)->Size
, sizeof (UINT16
));
1572 CopyMem (&VariableDefinitions
->Guid
, &((EFI_IFR_VARSTORE
*) FormData
)->Guid
, sizeof (EFI_GUID
));
1575 // The ASCII String which is immediately past the EFI_IFR_VARSTORE is inferred by the structure definition
1576 // due to it being variable sized. There are rules preventing it from being > 40 characters long and should
1577 // be enforced by the compiler.
1579 AsciiString
= (CHAR8
*) (&((EFI_IFR_VARSTORE
*) FormData
)->Size
);
1580 AsciiString
= AsciiString
+ 2;
1581 VariableDefinitions
->VariableName
= AllocateZeroPool ((AsciiStrLen (AsciiString
) + 1) * 2);
1582 ASSERT (VariableDefinitions
->VariableName
!= NULL
);
1583 for (Index
= 0; AsciiString
[Index
] != 0; Index
++) {
1584 VariableDefinitions
->VariableName
[Index
] = (CHAR16
) AsciiString
[Index
];
1587 VariableDefinitions
->VariableName
[Index
] = 0;
1590 // Propogate the tag information for this op-code
1592 CopyMem (&TargetTag
->VariableNumber
, &((EFI_IFR_VARSTORE
*) FormData
)->VarId
, sizeof (UINT16
));
1593 CopyMem (&TargetTag
->GuidValue
, &((EFI_IFR_VARSTORE
*) FormData
)->Guid
, sizeof (EFI_GUID
));
1594 CopyMem (&TargetTag
->StorageWidth
, &((EFI_IFR_VARSTORE
*) FormData
)->Size
, sizeof (UINT16
));
1595 CopyMem (&TargetTag
->Maximum
, &((EFI_IFR_VARSTORE
*) FormData
)->Size
, sizeof (UINT16
));
1598 case EFI_IFR_VARSTORE_SELECT_OP
:
1599 CopyMem (&TargetTag
->VariableNumber
, &((EFI_IFR_VARSTORE_SELECT
*) FormData
)->VarId
, sizeof (UINT16
));
1600 CopyMem (&CurrentVariable
, &((EFI_IFR_VARSTORE_SELECT
*) FormData
)->VarId
, sizeof (UINT16
));
1601 CurrentVariable2
= CurrentVariable
;
1604 case EFI_IFR_VARSTORE_SELECT_PAIR_OP
:
1605 CopyMem (&TargetTag
->VariableNumber
, &((EFI_IFR_VARSTORE_SELECT_PAIR
*) FormData
)->VarId
, sizeof (UINT16
));
1607 &TargetTag
->VariableNumber2
,
1608 &((EFI_IFR_VARSTORE_SELECT_PAIR
*) FormData
)->SecondaryVarId
,
1611 CopyMem (&CurrentVariable
, &((EFI_IFR_VARSTORE_SELECT_PAIR
*) FormData
)->VarId
, sizeof (UINT16
));
1612 CopyMem (&CurrentVariable2
, &((EFI_IFR_VARSTORE_SELECT_PAIR
*) FormData
)->SecondaryVarId
, sizeof (UINT16
));
1615 case EFI_IFR_REF_OP
:
1616 TargetTag
->NumberOfLines
= 1;
1617 CopyMem (&TargetTag
->Id
, &((EFI_IFR_REF
*) FormData
)->FormId
, sizeof (UINT16
));
1618 CopyMem (&TargetTag
->Key
, &((EFI_IFR_REF
*) FormData
)->Key
, sizeof (UINT16
));
1619 CopyMem (&TargetTag
->Text
, &((EFI_IFR_REF
*) FormData
)->Prompt
, sizeof (UINT16
));
1620 CopyMem (&TargetTag
->Help
, &((EFI_IFR_REF
*) FormData
)->Help
, sizeof (UINT16
));
1621 TargetTag
->Flags
= ((EFI_IFR_REF
*) FormData
)->Flags
;
1622 TargetTag
->VariableNumber
= CurrentVariable
;
1625 case EFI_IFR_EQ_ID_VAL_OP
:
1626 CopyMem (&TargetTag
->Value
, &((EFI_IFR_EQ_ID_VAL
*) FormData
)->Value
, sizeof (UINT16
));
1627 CopyMem (&TargetTag
->Id
, &((EFI_IFR_EQ_ID_VAL
*) FormData
)->QuestionId
, sizeof (UINT16
));
1628 TargetTag
->StorageWidth
= ((EFI_IFR_EQ_ID_VAL
*) FormData
)->Width
;
1629 TargetTag
->VariableNumber
= CurrentVariable
;
1632 case EFI_IFR_EQ_VAR_VAL_OP
:
1633 CopyMem (&TargetTag
->Value
, &((EFI_IFR_EQ_VAR_VAL
*) FormData
)->Value
, sizeof (UINT16
));
1634 CopyMem (&TargetTag
->Id
, &((EFI_IFR_EQ_VAR_VAL
*) FormData
)->VariableId
, sizeof (UINT16
));
1635 TargetTag
->VariableNumber
= CurrentVariable
;
1638 case EFI_IFR_EQ_ID_ID_OP
:
1639 CopyMem (&TargetTag
->Id
, &((EFI_IFR_EQ_ID_ID
*) FormData
)->QuestionId1
, sizeof (UINT16
));
1640 CopyMem (&TargetTag
->Id2
, &((EFI_IFR_EQ_ID_ID
*) FormData
)->QuestionId2
, sizeof (UINT16
));
1641 TargetTag
->StorageWidth
= ((EFI_IFR_EQ_ID_ID
*) FormData
)->Width
;
1642 TargetTag
->VariableNumber
= CurrentVariable
;
1643 TargetTag
->VariableNumber
= CurrentVariable2
;
1646 case EFI_IFR_EQ_ID_LIST_OP
:
1647 CopyMem (&TargetTag
->Id
, &((EFI_IFR_EQ_ID_LIST
*) FormData
)->QuestionId
, sizeof (UINT16
));
1648 CopyMem (&TargetTag
->Id2
, &((EFI_IFR_EQ_ID_LIST
*) FormData
)->ListLength
, sizeof (UINT16
));
1649 TargetTag
->StorageWidth
= ((EFI_IFR_EQ_ID_LIST
*) FormData
)->Width
;
1651 TargetTag
->IntList
= AllocateZeroPool (TargetTag
->Id2
* sizeof (UINT16
));
1652 ASSERT (TargetTag
->IntList
);
1654 for (TempValue
= 0; TempValue
< TargetTag
->Id2
; TempValue
++) {
1656 &TargetTag
->IntList
[TempValue
],
1657 &((EFI_IFR_EQ_ID_LIST
*) FormData
)->ValueList
[TempValue
],
1662 TargetTag
->VariableNumber
= CurrentVariable
;
1665 case EFI_IFR_FORM_SET_OP
:
1666 CopyMem (&VariableSize
, &((EFI_IFR_FORM_SET
*) FormData
)->NvDataSize
, sizeof (UINT16
));
1667 CopyMem (&Guid
, &((EFI_IFR_FORM_SET
*) FormData
)->Guid
, sizeof (EFI_GUID
));
1669 // If there is a size specified in the formste, we will establish a "default" variable
1671 if (VariableDefinitionsHead
!= NULL
) {
1672 VariableName
= AllocateZeroPool (12);
1673 ASSERT (VariableName
!= NULL
);
1674 CopyMem (VariableName
, L
"Setup", 12);
1675 VariableDefinitionsHead
->VariableName
= VariableName
;
1676 VariableDefinitionsHead
->VariableSize
= VariableSize
;
1677 CopyMem (&VariableDefinitionsHead
->Guid
, &Guid
, sizeof (EFI_GUID
));
1681 case EFI_IFR_END_FORM_SET_OP
:
1682 CurrentVariable
= 0;
1683 CurrentVariable2
= 0;