2 Entry and initialization module for the browser.
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.
16 // Include common header file for this module.
18 #include "CommonHeader.h"
23 FUNCTIION_KEY_SETTING gFunctionKeySettingTable
[] = {
43 NONE_FUNCTION_KEY_SETTING
64 NONE_FUNCTION_KEY_SETTING
85 NONE_FUNCTION_KEY_SETTING
88 // BMM File Explorer Formset.
106 NONE_FUNCTION_KEY_SETTING
112 InitializeBinaryStructures (
113 IN EFI_HII_HANDLE
*Handle
,
114 IN BOOLEAN UseDatabase
,
115 IN EFI_IFR_PACKET
*Packet
,
116 IN UINT8
*NvMapOverride
,
117 IN UINTN NumberOfIfrImages
,
118 EFI_FILE_FORM_TAGS
**FileFormTagsHead
123 InitializeTagStructures (
124 IN EFI_IFR_BINARY
*BinaryData
,
125 OUT EFI_FILE_FORM_TAGS
*FileFormTags
131 IN UINTN NumberOfIfrImages
,
132 IN EFI_FILE_FORM_TAGS
*FileFormTagsHead
,
133 IN UINT8
*CallbackData
139 IN EFI_HII_PROTOCOL
*Hii
,
140 IN EFI_HII_HANDLE HiiHandle
,
141 IN EFI_IFR_PACKET
*Packet
,
142 IN EFI_IFR_BINARY
*BinaryData
155 IN EFI_FORM_BROWSER_PROTOCOL
* This
,
156 IN BOOLEAN UseDatabase
,
157 IN EFI_HII_HANDLE
* Handle
,
158 IN UINTN HandleCount
,
159 IN EFI_IFR_PACKET
* Packet
,
160 IN EFI_HANDLE CallbackHandle
,
161 IN UINT8
*NvMapOverride
,
162 IN EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
163 OUT BOOLEAN
*ResetRequired OPTIONAL
169 This is the routine which an external caller uses to direct the browser
170 where to obtain it's information.
174 UseDatabase - If set to TRUE, then all information is retrieved from the HII database handle specified
175 If set to FALSE, then the passed in Packet and CallbackHandle is used and Handle is ignored
177 Handle - A pointer to an array of Handles. If HandleCount > 1 we display a list of the formsets for the handles specified
179 HandleCount - The number of Handles specified in Handle.
181 Packet - Valid only if UseDatabase is FALSE. Packet defines the pages being passed into
182 the browser. This is composed of IFR data as well as String information.
184 CallbackHandle - The handle which contains the calling driver's EFI_FORM_CALLBACK_PROTOCOL interface.
186 ScreenDimenions - This allows the browser to be called so that it occupies a portion of the physical screen instead of
187 dynamically determining the screen dimensions.
189 NvMapOverride - This buffer is used only when there is no NV variable to define the current settings and the caller
190 needs to provide to the browser the current settings for the "fake" NV variable. If used, no saving
191 of an NV variable will be possible. This parameter is also ignored if HandleCount > 1.
197 EFI_FORM_CALLBACK_PROTOCOL
*FormCallback
;
198 EFI_FILE_FORM_TAGS
*FileFormTagsHead
;
199 UI_MENU_OPTION
*Selection
;
200 UI_MENU_OPTION
*AltSelection
;
204 EFI_HII_HANDLE BackupHandle
;
206 ZeroMem (&gScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
208 gPreviousValue
= AllocatePool (0x1000);
209 CallbackData
= AllocatePool (0x10000);
210 ASSERT (gPreviousValue
!= NULL
);
211 ASSERT (CallbackData
!= NULL
);
215 // Seed the dimensions in the global
217 gST
->ConOut
->QueryMode (
219 gST
->ConOut
->Mode
->Mode
,
220 &gScreenDimensions
.RightColumn
,
221 &gScreenDimensions
.BottomRow
224 if (ScreenDimensions
!= NULL
) {
226 // Check local dimension vs. global dimension.
228 if ((gScreenDimensions
.RightColumn
< ScreenDimensions
->RightColumn
) ||
229 (gScreenDimensions
.BottomRow
< ScreenDimensions
->BottomRow
)
231 return EFI_INVALID_PARAMETER
;
234 // Local dimension validation.
236 if ((ScreenDimensions
->RightColumn
> ScreenDimensions
->LeftColumn
) &&
237 (ScreenDimensions
->BottomRow
> ScreenDimensions
->TopRow
) &&
238 ((ScreenDimensions
->RightColumn
- ScreenDimensions
->LeftColumn
) > 2) &&
240 (ScreenDimensions
->BottomRow
- ScreenDimensions
->TopRow
) > STATUS_BAR_HEIGHT
+
241 SCROLL_ARROW_HEIGHT
*
243 FRONT_PAGE_HEADER_HEIGHT
+
248 CopyMem (&gScreenDimensions
, ScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
250 return EFI_INVALID_PARAMETER
;
255 gOptionBlockWidth
= (CHAR16
) ((gScreenDimensions
.RightColumn
- gScreenDimensions
.LeftColumn
) / 3);
256 gHelpBlockWidth
= gOptionBlockWidth
;
257 gPromptBlockWidth
= gOptionBlockWidth
;
260 // Initialize the strings for the browser, upon exit of the browser, the strings will be freed
262 InitializeBrowserStrings ();
264 gFunctionKeySetting
= DEFAULT_FUNCTION_KEY_SETTING
;
265 gClassOfVfr
= EFI_SETUP_APPLICATION_SUBCLASS
;
266 gResetRequired
= FALSE
;
267 gExitRequired
= FALSE
;
268 gSaveRequired
= FALSE
;
269 gNvUpdateRequired
= FALSE
;
273 BackupHandle
= *Handle
;
274 gMenuRefreshHead
= NULL
;
275 ASSERT (CallbackData
);
276 ZeroMem (CallbackData
, 0x10000);
279 // We can recurse through this and might need to re-allocate this particular buffer
281 if (gPreviousValue
== NULL
) {
282 gPreviousValue
= AllocatePool (0x1000);
283 ASSERT (gPreviousValue
!= NULL
);
289 if (CallbackHandle
!= NULL
) {
291 // Retrieve the Callback protocol interface
293 Status
= gBS
->HandleProtocol (
295 &gEfiFormCallbackProtocolGuid
,
296 (VOID
**) &FormCallback
299 if (EFI_ERROR (Status
)) {
300 FreePool (CallbackData
);
307 // Initializes all the internal state structures for all IFR images in system
309 Status
= InitializeBinaryStructures (Handle
, UseDatabase
, Packet
, NvMapOverride
, HandleCount
, &FileFormTagsHead
);
311 if (EFI_ERROR (Status
)) {
312 FreePool (CallbackData
);
316 // Beginning of the Presentation of the Data
318 if (UseDatabase
&& (HandleCount
> 1)) {
319 Selection
= DisplayHomePage (HandleCount
, FileFormTagsHead
, CallbackData
);
322 // If passing something specific, we know there is only one Ifr
324 Selection
= AllocateZeroPool (sizeof (UI_MENU_OPTION
));
325 ASSERT (Selection
!= NULL
);
326 Selection
->IfrNumber
= 0;
327 Selection
->Handle
= Handle
[0];
333 if (UseDatabase
&& (HandleCount
> 1)) {
334 if (Selection
== NULL
) {
335 FreePool (CallbackData
);
340 // Launch the setup browser with the user's selection information
342 AltSelection
= SetupBrowser (Selection
, Callback
, FileFormTagsHead
, CallbackData
);
345 // If the caller cares about Reset status, we can return to the caller if something happened that required a reset
347 if (ResetRequired
!= NULL
) {
348 *ResetRequired
= gResetRequired
;
351 if (Callback
&& (AltSelection
!= NULL
)) {
352 if ((FormCallback
!= NULL
) && (FormCallback
->Callback
!= NULL
)) {
353 Status
= FormCallback
->Callback (
355 AltSelection
->ThisTag
->Key
,
357 (EFI_HII_CALLBACK_PACKET
**) &Packet
362 *Handle
= BackupHandle
;
364 if (EFI_ERROR (Status
)) {
365 FreePool (CallbackData
);
369 if (Callback
&& (AltSelection
== NULL
)) {
370 FreePool (CallbackData
);
374 if (UseDatabase
&& (HandleCount
> 1)) {
377 if (gBinaryDataHead
->UnRegisterOnExit
) {
378 Hii
->RemovePack (Hii
, Handle
[0]);
382 ((AltSelection
->ThisTag
->SubClass
== EFI_FRONT_PAGE_SUBCLASS
) ||
383 (AltSelection
->ThisTag
->SubClass
== EFI_SINGLE_USE_SUBCLASS
))) {
385 // If this is the FrontPage, return after every selection
387 FreePool (Selection
);
391 // Clean up the allocated data buffers
393 FreeData (FileFormTagsHead
, NULL
, NULL
);
395 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
396 gST
->ConOut
->ClearScreen (gST
->ConOut
);
398 FreePool (CallbackData
);
402 FreePool (Selection
);
406 // Clean up the allocated data buffers
408 FreeData (FileFormTagsHead
, NULL
, NULL
);
410 gST
->ConOut
->ClearScreen (gST
->ConOut
);
413 FreePool (CallbackData
);
418 } while (!EFI_ERROR (Status
));
420 FreePool (CallbackData
);
427 IN EFI_HANDLE ImageHandle
,
428 IN EFI_SYSTEM_TABLE
*SystemTable
436 (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
439 EFI_SUCCESS - Setup loaded.
445 EFI_FORM_CONFIGURATION_DATA
*FormData
;
446 EFI_FORM_BROWSER_PROTOCOL
*FormBrowser
;
448 EFI_HII_PACKAGES
*PackageList
;
451 // There will be only one FormConfig in the system
452 // If there is another out there, someone is trying to install us
453 // again. Fail that scenario.
455 Status
= gBS
->LocateProtocol (
456 &gEfiFormBrowserProtocolGuid
,
458 (VOID
**) &FormBrowser
464 // If there was no error, assume there is an installation and fail to load
466 if (!EFI_ERROR (Status
)) {
467 return EFI_DEVICE_ERROR
;
470 FormData
= AllocatePool (sizeof (EFI_FORM_CONFIGURATION_DATA
));
472 if (FormData
== NULL
) {
473 return EFI_OUT_OF_RESOURCES
;
478 FormData
->Signature
= EFI_FORM_DATA_SIGNATURE
;
479 FormData
->FormConfig
.SendForm
= SendForm
;
480 FormData
->FormConfig
.CreatePopUp
= CreateDialog
;
483 // There should only be one HII image
485 Status
= gBS
->LocateProtocol (
486 &gEfiHiiProtocolGuid
,
488 (VOID
**) &FormData
->Hii
491 ASSERT_EFI_ERROR (Status
);
495 PackageList
= PreparePackages (1, &gEfiFormBrowserProtocolGuid
, SetupBrowserStrings
);
497 Status
= Hii
->NewPack (Hii
, PackageList
, &gHiiHandle
);
499 FreePool (PackageList
);
502 // Install protocol interface
505 Status
= gBS
->InstallProtocolInterface (
507 &gEfiFormBrowserProtocolGuid
,
508 EFI_NATIVE_INTERFACE
,
509 &FormData
->FormConfig
512 ASSERT_EFI_ERROR (Status
);
514 BannerData
= AllocateZeroPool (sizeof (BANNER_DATA
));
515 ASSERT (BannerData
!= NULL
);
517 Status
= InstallPrint ();
524 IN UINT8
*RawFormSet
,
526 IN EFI_FILE_FORM_TAGS
*FileFormTags
,
527 IN UINT16 CurrentVariable
532 Initialize question tag's members.
535 Tag - Pointer of the current EFI_TAG structure.
536 RawFormSet - Pointer of the formset raw data.
537 Index - Offset of the current opcode in the Ifr raw data.
538 FileFormTags - Pointer of current EFI_FILE_FORM_TAGS structure.
539 CurrentVariable - Current variable number.
545 EFI_VARIABLE_DEFINITION
*VariableDefinition
;
547 Tag
->NumberOfLines
= 1;
548 Tag
->VariableNumber
= CurrentVariable
;
549 CopyMem (&Tag
->Id
, &((EFI_IFR_ONE_OF
*) &RawFormSet
[Index
])->QuestionId
, sizeof (UINT16
));
550 CopyMem (&Tag
->StorageStart
, &((EFI_IFR_ONE_OF
*) &RawFormSet
[Index
])->QuestionId
, sizeof (UINT16
));
551 CopyMem (&Tag
->StorageWidth
, &((EFI_IFR_ONE_OF
*) &RawFormSet
[Index
])->Width
, sizeof (UINT8
));
552 CopyMem (&Tag
->Text
, &((EFI_IFR_ONE_OF
*) &RawFormSet
[Index
])->Prompt
, sizeof (UINT16
));
553 CopyMem (&Tag
->Help
, &((EFI_IFR_ONE_OF
*) &RawFormSet
[Index
])->Help
, sizeof (UINT16
));
555 VariableDefinition
= FileFormTags
->VariableDefinitions
;
557 for (; VariableDefinition
!= NULL
; VariableDefinition
= VariableDefinition
->Next
) {
559 // Have we found the correct variable for the request?
561 if (CurrentVariable
== VariableDefinition
->VariableId
) {
562 if (VariableDefinition
->VariableSize
< (UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
)) {
563 VariableDefinition
->VariableFakeSize
= (UINT16
) (VariableDefinition
->VariableFakeSize
+ Tag
->StorageWidth
);
566 if (VariableDefinition
->NvRamMap
!= NULL
) {
568 // If it is an 8bit or 16bit width, then move it to Tag->Value, otherwise
569 // we will never be looking for the data in Tag->Value (e.g. strings, password, etc)
571 if (Tag
->StorageWidth
== (UINT16
) 1) {
572 CopyMem (&Tag
->Value
, &VariableDefinition
->NvRamMap
[Tag
->StorageStart
], sizeof (UINT16
));
575 if (Tag
->StorageWidth
== (UINT16
) 2) {
578 VariableDefinition
->NvRamMap
[Tag
->StorageStart
] +
579 (VariableDefinition
->NvRamMap
[Tag
->StorageStart
+ 1] * 0x100)
581 CopyMem (&Tag
->Value
, &Index
, sizeof (UINT16
));
585 CopyMem (&Tag
->Value
, &Index
, sizeof (UINT16
));
595 IN UINT8
*RawFormSet
,
597 IN UINT16 NumberOfLines
,
598 IN EFI_FILE_FORM_TAGS
*FileFormTags
,
599 IN UINT16 CurrentVariable
604 Initialize numeric tag's members.
607 Tag - Pointer of the current EFI_TAG structure.
608 RawFormSet - Pointer of the formset raw data.
609 Index - Offset of the current opcode in the Ifr raw data.
610 NumberOfLines - Number of lines this opcode occupied.
611 FileFormTags - Pointer of current EFI_FILE_FORM_TAGS structure.
612 CurrentVariable - Current variable number.
618 EFI_VARIABLE_DEFINITION
*VariableDefinition
;
620 Tag
->NumberOfLines
= NumberOfLines
;
621 Tag
->VariableNumber
= CurrentVariable
;
622 CopyMem (&Tag
->Id
, &((EFI_IFR_ONE_OF
*) &RawFormSet
[Index
])->QuestionId
, sizeof (UINT16
));
623 CopyMem (&Tag
->StorageStart
, &((EFI_IFR_ONE_OF
*) &RawFormSet
[Index
])->QuestionId
, sizeof (UINT16
));
624 CopyMem (&Tag
->StorageWidth
, &((EFI_IFR_ONE_OF
*) &RawFormSet
[Index
])->Width
, sizeof (UINT8
));
625 CopyMem (&Tag
->Text
, &((EFI_IFR_ONE_OF
*) &RawFormSet
[Index
])->Prompt
, sizeof (UINT16
));
626 CopyMem (&Tag
->Help
, &((EFI_IFR_ONE_OF
*) &RawFormSet
[Index
])->Help
, sizeof (UINT16
));
627 CopyMem (&Tag
->Minimum
, &((EFI_IFR_NUMERIC
*) &RawFormSet
[Index
])->Minimum
, sizeof (UINT16
));
628 CopyMem (&Tag
->Maximum
, &((EFI_IFR_NUMERIC
*) &RawFormSet
[Index
])->Maximum
, sizeof (UINT16
));
629 CopyMem (&Tag
->Step
, &((EFI_IFR_NUMERIC
*) &RawFormSet
[Index
])->Step
, sizeof (UINT16
));
630 CopyMem (&Tag
->Default
, &((EFI_IFR_NUMERIC
*) &RawFormSet
[Index
])->Default
, sizeof (UINT16
));
631 Tag
->ResetRequired
= (BOOLEAN
) (((EFI_IFR_NUMERIC
*) &RawFormSet
[Index
])->Flags
& EFI_IFR_FLAG_RESET_REQUIRED
);
633 VariableDefinition
= FileFormTags
->VariableDefinitions
;
635 for (; VariableDefinition
!= NULL
; VariableDefinition
= VariableDefinition
->Next
) {
637 // Have we found the correct variable for the request?
639 if (CurrentVariable
== VariableDefinition
->VariableId
) {
640 if (VariableDefinition
->VariableSize
<= (UINTN
) (Tag
->StorageStart
+ Tag
->StorageWidth
)) {
641 if (Tag
->StorageWidth
== 0) {
642 VariableDefinition
->VariableFakeSize
= (UINT16
) (VariableDefinition
->VariableFakeSize
+ 2);
644 VariableDefinition
->VariableFakeSize
= (UINT16
) (VariableDefinition
->VariableFakeSize
+ Tag
->StorageWidth
);
648 if (VariableDefinition
->NvRamMap
!= NULL
) {
650 // If it is an 8bit or 16bit width, then move it to Tag->Value, otherwise
651 // we will never be looking for the data in Tag->Value (e.g. strings, password, etc)
653 if (Tag
->StorageWidth
== (UINT16
) 1) {
654 CopyMem (&Tag
->Value
, &VariableDefinition
->NvRamMap
[Tag
->StorageStart
], sizeof (UINT16
));
657 if (Tag
->StorageWidth
== (UINT16
) 2) {
660 VariableDefinition
->NvRamMap
[Tag
->StorageStart
] +
661 (VariableDefinition
->NvRamMap
[Tag
->StorageStart
+ 1] * 0x100)
663 CopyMem (&Tag
->Value
, &Index
, sizeof (UINT16
));
666 CopyMem (&Tag
->Value
, &Tag
->Default
, sizeof (UINT16
));
675 IN UINT8
*RawFormSet
,
676 IN OUT UINT16
*NumberOfTags
682 // Assume on entry we are pointing to an OpCode - reasonably this should
683 // be a FormOp since the purpose is to count the tags in a particular Form.
685 for (Index
= 0; RawFormSet
[Index
] != EFI_IFR_END_FORM_OP
;) {
687 // If we encounter the end of a form set, bail out
689 if (RawFormSet
[Index
] == EFI_IFR_END_FORM_SET_OP
) {
693 // We treat date/time internally as three op-codes
695 if (RawFormSet
[Index
] == EFI_IFR_DATE_OP
|| RawFormSet
[Index
] == EFI_IFR_TIME_OP
) {
696 *NumberOfTags
= (UINT16
) (*NumberOfTags
+ 3);
699 // Assume that we could have no more tags than op-codes
704 Index
= (UINT16
) (Index
+ RawFormSet
[Index
+ 1]);
707 // Increase the tag count by one so it is inclusive of the end_form_op
714 AddNextInconsistentTag (
715 IN OUT EFI_INCONSISTENCY_DATA
**InconsistentTagsPtr
720 Initialize the next inconsistent tag data and add it to the inconsistent tag list.
723 InconsistentTagsPtr - Pointer of the inconsistent tag's pointer.
730 EFI_INCONSISTENCY_DATA
*PreviousInconsistentTags
;
731 EFI_INCONSISTENCY_DATA
*InconsistentTags
;
733 InconsistentTags
= *InconsistentTagsPtr
;
735 // We just hit the end of an inconsistent expression. Let's allocate the ->Next structure
737 InconsistentTags
->Next
= AllocatePool (sizeof (EFI_INCONSISTENCY_DATA
));
738 ASSERT (InconsistentTags
->Next
!= NULL
);
741 // Preserve current Tag entry
743 PreviousInconsistentTags
= InconsistentTags
;
745 InconsistentTags
= InconsistentTags
->Next
;
748 // This will zero on the entry including the ->Next so I don't have to do it
750 ZeroMem (InconsistentTags
, sizeof (EFI_INCONSISTENCY_DATA
));
753 // Point our Previous field to the previous entry
755 InconsistentTags
->Previous
= PreviousInconsistentTags
;
757 *InconsistentTagsPtr
= InconsistentTags
;
764 InitializeTagStructures (
765 IN EFI_IFR_BINARY
*BinaryData
,
766 OUT EFI_FILE_FORM_TAGS
*FileFormTags
772 UINT16 QuestionIndex
;
776 EFI_FORM_TAGS
*FormTags
;
777 EFI_FORM_TAGS
*SavedFormTags
;
778 EFI_INCONSISTENCY_DATA
*InconsistentTags
;
779 EFI_VARIABLE_DEFINITION
*VariableDefinitions
;
784 UINT16 CurrentVariable
;
785 UINT16 CurrentVariable2
;
788 // Initialize some Index variable and Status
794 CurrentVariable2
= 0;
797 Status
= EFI_SUCCESS
;
798 FormTags
= &FileFormTags
->FormTags
;
799 FormTags
->Next
= NULL
;
800 if (FileFormTags
->InconsistentTags
== NULL
) {
801 InconsistentTags
= NULL
;
803 InconsistentTags
= FileFormTags
->InconsistentTags
;
806 if (FileFormTags
->VariableDefinitions
== NULL
) {
807 VariableDefinitions
= NULL
;
809 VariableDefinitions
= FileFormTags
->VariableDefinitions
;
812 // RawFormSet now points to the beginning of the forms portion of
813 // the specific IFR Binary.
815 RawFormSet
= (UINT8
*) BinaryData
->FormBinary
;
818 // Determine the number of tags for the first form
820 GetTagCount (&RawFormSet
[0], &NumberOfTags
);
822 SavedFormTags
= FormTags
;
824 if (FormTags
->Tags
!= NULL
) {
827 // Advance FormTags to the last entry
829 for (; FormTags
->Next
!= NULL
; FormTags
= FormTags
->Next
)
833 // Walk through each of the tags and free the IntList allocation
835 for (Index
= 0; Index
< NumberOfTags
; Index
++) {
836 if (FormTags
->Tags
[Index
].IntList
!= NULL
) {
837 FreePool (FormTags
->Tags
[Index
].IntList
);
841 FreePool (FormTags
->Tags
);
843 ASSERT (FormTags
->Next
== NULL
);
845 FormTags
->Tags
= NULL
;
847 FormTags
= SavedFormTags
;
849 } while (FormTags
->Next
!= NULL
);
855 // Test for an allocated buffer. If already allocated this is due to having called this routine
856 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
857 // the tag structure with current values from the NV
859 if (FormTags
->Tags
== NULL
) {
861 // Allocate memory for our tags on the first form
863 FormTags
->Tags
= AllocateZeroPool (NumberOfTags
* sizeof (EFI_TAG
));
864 ASSERT (FormTags
->Tags
);
867 // Test for an allocated buffer. If already allocated this is due to having called this routine
868 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
869 // the tag structure with current values from the NV
871 if (InconsistentTags
== NULL
) {
873 // We just hit the end of an inconsistent expression. Let's allocate the ->Next structure
875 InconsistentTags
= AllocateZeroPool (sizeof (EFI_INCONSISTENCY_DATA
));
876 ASSERT (InconsistentTags
!= NULL
);
878 FileFormTags
->InconsistentTags
= InconsistentTags
;
881 ZeroMem (FormTags
->Tags
, NumberOfTags
* sizeof (EFI_TAG
));
883 for (CurrTag
= 0; RawFormSet
[Index
] != EFI_IFR_END_FORM_SET_OP
; CurrTag
++) {
885 // Operand = IFR OpCode
887 FormTags
->Tags
[CurrTag
].Operand
= RawFormSet
[Index
];
890 // Assume for now 0 lines occupied by this OpCode
892 FormTags
->Tags
[CurrTag
].NumberOfLines
= 0;
894 FormTags
->Tags
[CurrTag
].Class
= Class
;
895 FormTags
->Tags
[CurrTag
].SubClass
= SubClass
;
898 // Determine the length of the Tag so we can later skip to the next tag in the form
900 TagLength
= RawFormSet
[Index
+ 1];
904 // Operate on the Found OpCode
906 switch (RawFormSet
[Index
]) {
908 case EFI_IFR_FORM_OP
:
910 // If there was no variable op-code defined, create a dummy entry for one
912 if (FileFormTags
->VariableDefinitions
== NULL
) {
913 FileFormTags
->VariableDefinitions
= AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION
));
914 ASSERT (FileFormTags
->VariableDefinitions
!= NULL
);
917 &FormTags
->Tags
[CurrTag
],
918 (VOID
*) &RawFormSet
[Index
],
919 FileFormTags
->VariableDefinitions
922 IfrToFormTag (RawFormSet
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &RawFormSet
[Index
], NULL
);
926 case EFI_IFR_SUBTITLE_OP
:
927 case EFI_IFR_TEXT_OP
:
929 IfrToFormTag (RawFormSet
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &RawFormSet
[Index
], NULL
);
932 case EFI_IFR_VARSTORE_OP
:
933 if (FileFormTags
->VariableDefinitions
== NULL
) {
934 VariableDefinitions
= AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION
));
935 ASSERT (VariableDefinitions
!= NULL
);
936 FileFormTags
->VariableDefinitions
= VariableDefinitions
;
941 &FormTags
->Tags
[CurrTag
],
942 (VOID
*) &RawFormSet
[Index
],
943 FileFormTags
->VariableDefinitions
947 case EFI_IFR_VARSTORE_SELECT_OP
:
948 IfrToFormTag (RawFormSet
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &RawFormSet
[Index
], NULL
);
949 CopyMem (&CurrentVariable
, &((EFI_IFR_VARSTORE_SELECT
*) &RawFormSet
[Index
])->VarId
, sizeof (UINT16
));
950 CurrentVariable2
= CurrentVariable
;
953 case EFI_IFR_VARSTORE_SELECT_PAIR_OP
:
954 IfrToFormTag (RawFormSet
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &RawFormSet
[Index
], NULL
);
955 CopyMem(&CurrentVariable
, &((EFI_IFR_VARSTORE_SELECT_PAIR
*)&RawFormSet
[Index
])->VarId
, sizeof (UINT16
));
958 &((EFI_IFR_VARSTORE_SELECT_PAIR
*) &RawFormSet
[Index
])->SecondaryVarId
,
963 case EFI_IFR_END_FORM_OP
:
965 // Test for an allocated buffer. If already allocated this is due to having called this routine
966 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
967 // the tag structure with current values from the NV
969 if (FormTags
->Next
== NULL
) {
971 // We just hit the end of a form. Let's allocate the ->Next structure
973 FormTags
->Next
= AllocatePool (sizeof (EFI_FORM_TAGS
));
974 ASSERT (FormTags
->Next
);
977 FormTags
= FormTags
->Next
;
978 ZeroMem (FormTags
, sizeof (EFI_FORM_TAGS
));
981 // Reset the tag count to one
986 // Reset the CurrTag value (it will be incremented, after this case statement
987 // so set to a negative one so that we get the desired effect.) Fish can beat me later.
992 // Determine the number of tags after this form. If this is the last
993 // form, then we will count the endformset and preserve that information
994 // in the tag structure.
996 GetTagCount (&RawFormSet
[Index
+ TagLength
], &NumberOfTags
);
999 // Allocate memory for our tags
1001 FormTags
->Tags
= AllocateZeroPool (NumberOfTags
* sizeof (EFI_TAG
));
1002 ASSERT (FormTags
->Tags
);
1006 // Two types of tags constitute the One Of question: a one-of header and
1007 // several one-of options.
1009 case EFI_IFR_ONE_OF_OP
:
1010 case EFI_IFR_ORDERED_LIST_OP
:
1011 GetQuestionHeader (&FormTags
->Tags
[CurrTag
], RawFormSet
, Index
, FileFormTags
, CurrentVariable
);
1014 // Store away the CurrTag since what follows will be the answer that we
1015 // need to place into the appropriate location in the tag array
1018 // record for setting default later
1020 QuestionIndex
= (UINT16
) CurrTag
;
1023 case EFI_IFR_ONE_OF_OPTION_OP
:
1024 IfrToFormTag (RawFormSet
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &RawFormSet
[Index
], NULL
);
1025 FormTags
->Tags
[QuestionIndex
].Flags
= ((EFI_IFR_ONE_OF_OPTION
*) &RawFormSet
[Index
])->Flags
;
1027 &FormTags
->Tags
[QuestionIndex
].Key
,
1028 &((EFI_IFR_ONE_OF_OPTION
*) &RawFormSet
[Index
])->Key
,
1031 FormTags
->Tags
[QuestionIndex
].ResetRequired
= (BOOLEAN
) (FormTags
->Tags
[QuestionIndex
].Flags
& EFI_IFR_FLAG_RESET_REQUIRED
);
1034 case EFI_IFR_CHECKBOX_OP
:
1035 GetQuestionHeader (&FormTags
->Tags
[CurrTag
], RawFormSet
, Index
, FileFormTags
, CurrentVariable
);
1036 IfrToFormTag (RawFormSet
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &RawFormSet
[Index
], NULL
);
1039 case EFI_IFR_NUMERIC_OP
:
1040 GetNumericHeader (&FormTags
->Tags
[CurrTag
], RawFormSet
, Index
, (UINT16
) 1, FileFormTags
, CurrentVariable
);
1041 IfrToFormTag (RawFormSet
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &RawFormSet
[Index
], NULL
);
1044 case EFI_IFR_DATE_OP
:
1046 // Date elements come in as a Year, Month, Day. We need to process them as a country-based
1047 // Order. It is much easier to do it here than anywhere else.
1049 // For US standards - we want Month/Day/Year, thus we advance "Index" +1, +2, +0 while CurrTag is +0, +1, +2
1052 &FormTags
->Tags
[CurrTag
],
1054 (UINT16
) (Index
+ TagLength
),
1061 // The current language selected + the Date operand
1063 FormTags
->Tags
[CurrTag
+ 1].Operand
= RawFormSet
[Index
];
1065 &FormTags
->Tags
[CurrTag
+ 1],
1067 (UINT16
) (Index
+ TagLength
+ RawFormSet
[Index
+ TagLength
+ 1]),
1074 // The current language selected + the Date operand
1076 FormTags
->Tags
[CurrTag
+ 2].Operand
= RawFormSet
[Index
];
1077 GetNumericHeader (&FormTags
->Tags
[CurrTag
+ 2], RawFormSet
, Index
, (UINT16
) 1, FileFormTags
, CurrentVariable
);
1079 CurrTag
= (INT16
) (CurrTag
+ 2);
1081 Index
= (UINT16
) (Index
+ TagLength
);
1085 TagLength
= RawFormSet
[Index
+ 1];
1086 Index
= (UINT16
) (Index
+ TagLength
);
1090 TagLength
= RawFormSet
[Index
+ 1];
1093 case EFI_IFR_TIME_OP
:
1094 GetNumericHeader (&FormTags
->Tags
[CurrTag
], RawFormSet
, Index
, (UINT16
) 0, FileFormTags
, CurrentVariable
);
1098 // Override the GetQuestionHeader information - date/time are treated very differently
1100 FormTags
->Tags
[CurrTag
].NumberOfLines
= 1;
1104 // The premise is that every date/time op-code have 3 elements, the first 2 have 0 lines
1105 // associated with them, and the third has 1 line to allow to space beyond the choice.
1111 case EFI_IFR_PASSWORD_OP
:
1112 case EFI_IFR_STRING_OP
:
1113 GetQuestionHeader (&FormTags
->Tags
[CurrTag
], RawFormSet
, Index
, FileFormTags
, CurrentVariable
);
1114 IfrToFormTag (RawFormSet
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &RawFormSet
[Index
], NULL
);
1117 case EFI_IFR_SUPPRESS_IF_OP
:
1118 case EFI_IFR_GRAYOUT_IF_OP
:
1119 InconsistentTags
->Operand
= ((EFI_IFR_INCONSISTENT
*) &RawFormSet
[Index
])->Header
.OpCode
;
1123 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1124 // Unfortunately 0 is a valid offset value for a QuestionId
1126 InconsistentTags
->QuestionId1
= INVALID_OFFSET_VALUE
;
1127 InconsistentTags
->QuestionId2
= INVALID_OFFSET_VALUE
;
1130 // Test for an allocated buffer. If already allocated this is due to having called this routine
1131 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1132 // the tag structure with current values from the NV
1134 if (InconsistentTags
->Next
== NULL
) {
1135 AddNextInconsistentTag (&InconsistentTags
);
1139 InconsistentTags
= InconsistentTags
->Next
;
1142 case EFI_IFR_FORM_SET_OP
:
1144 &FormTags
->Tags
[CurrTag
].GuidValue
,
1145 &((EFI_IFR_FORM_SET
*) &RawFormSet
[Index
])->Guid
,
1149 &FormTags
->Tags
[CurrTag
].CallbackHandle
,
1150 &((EFI_IFR_FORM_SET
*) &RawFormSet
[Index
])->CallbackHandle
,
1151 sizeof (EFI_PHYSICAL_ADDRESS
)
1153 CopyMem (&FormTags
->Tags
[CurrTag
].Class
, &((EFI_IFR_FORM_SET
*) &RawFormSet
[Index
])->Class
, sizeof (UINT8
));
1155 &FormTags
->Tags
[CurrTag
].SubClass
,
1156 &((EFI_IFR_FORM_SET
*) &RawFormSet
[Index
])->SubClass
,
1160 &FormTags
->Tags
[CurrTag
].NvDataSize
,
1161 &((EFI_IFR_FORM_SET
*) &RawFormSet
[Index
])->NvDataSize
,
1164 Class
= ((EFI_IFR_FORM_SET
*) &RawFormSet
[Index
])->Class
;
1165 SubClass
= ((EFI_IFR_FORM_SET
*) &RawFormSet
[Index
])->SubClass
;
1167 // If the formset has a size value, that means someone must be using this, so create a variable
1168 // We also shall reserve the formid of 0 for this specific purpose.
1170 if ((FileFormTags
->VariableDefinitions
== NULL
) && (FormTags
->Tags
[CurrTag
].NvDataSize
> 0)) {
1171 FileFormTags
->VariableDefinitions
= AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION
));
1172 ASSERT (FileFormTags
->VariableDefinitions
!= NULL
);
1175 &FormTags
->Tags
[CurrTag
],
1176 (VOID
*) &RawFormSet
[Index
],
1177 FileFormTags
->VariableDefinitions
1180 IfrToFormTag (RawFormSet
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &RawFormSet
[Index
], NULL
);
1184 case EFI_IFR_BANNER_OP
:
1185 if (gClassOfVfr
== EFI_FRONT_PAGE_SUBCLASS
) {
1187 CopyMem (&TempValue
, &((EFI_IFR_BANNER
*) &RawFormSet
[Index
])->Alignment
, sizeof (UINT8
));
1189 // If this is the special timeout value, we will dynamically figure out where to put it
1190 // Also the least significant byte refers to the TimeOut desired.
1192 if (TempValue
== EFI_IFR_BANNER_TIMEOUT
) {
1193 CopyMem (&FrontPageTimeOutTitle
, &((EFI_IFR_BANNER
*) &RawFormSet
[Index
])->Title
, sizeof (UINT16
));
1194 if (FrontPageTimeOutValue
!= (INT16
) -1) {
1195 CopyMem (&FrontPageTimeOutValue
, &((EFI_IFR_BANNER
*) &RawFormSet
[Index
])->LineNumber
, sizeof (UINT16
));
1201 &BannerData
->Banner
[((EFI_IFR_BANNER
*) &RawFormSet
[Index
])->LineNumber
][
1202 ((EFI_IFR_BANNER
*) &RawFormSet
[Index
])->Alignment
],
1203 &((EFI_IFR_BANNER
*) &RawFormSet
[Index
])->Title
,
1209 case EFI_IFR_INCONSISTENT_IF_OP
:
1211 &FormTags
->Tags
[CurrTag
].Text
,
1212 &((EFI_IFR_INCONSISTENT
*) &RawFormSet
[Index
])->Popup
,
1217 InconsistentTags
->Operand
= ((EFI_IFR_INCONSISTENT
*) &RawFormSet
[Index
])->Header
.OpCode
;
1218 CopyMem (&InconsistentTags
->Popup
, &((EFI_IFR_INCONSISTENT
*) &RawFormSet
[Index
])->Popup
, sizeof (UINT16
));
1221 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1222 // Unfortunately 0 is a valid offset value for a QuestionId
1224 InconsistentTags
->QuestionId1
= INVALID_OFFSET_VALUE
;
1225 InconsistentTags
->QuestionId2
= INVALID_OFFSET_VALUE
;
1227 InconsistentTags
->VariableNumber
= CurrentVariable
;
1230 // Test for an allocated buffer. If already allocated this is due to having called this routine
1231 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1232 // the tag structure with current values from the NV
1234 if (InconsistentTags
->Next
== NULL
) {
1235 AddNextInconsistentTag (&InconsistentTags
);
1239 InconsistentTags
= InconsistentTags
->Next
;
1242 case EFI_IFR_EQ_ID_VAL_OP
:
1243 IfrToFormTag (RawFormSet
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &RawFormSet
[Index
], NULL
);
1245 InconsistentTags
->Operand
= ((EFI_IFR_EQ_ID_VAL
*) &RawFormSet
[Index
])->Header
.OpCode
;
1246 CopyMem (&InconsistentTags
->Value
, &((EFI_IFR_EQ_ID_VAL
*) &RawFormSet
[Index
])->Value
, sizeof (UINT16
));
1248 &InconsistentTags
->QuestionId1
,
1249 &((EFI_IFR_EQ_ID_VAL
*) &RawFormSet
[Index
])->QuestionId
,
1254 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1255 // Unfortunately 0 is a valid offset value for a QuestionId
1257 InconsistentTags
->Width
= FormTags
->Tags
[CurrTag
].StorageWidth
;
1258 InconsistentTags
->QuestionId2
= INVALID_OFFSET_VALUE
;
1259 InconsistentTags
->ConsistencyId
= gConsistencyId
;
1260 FormTags
->Tags
[CurrTag
].ConsistencyId
= gConsistencyId
;
1262 InconsistentTags
->VariableNumber
= CurrentVariable
;
1265 // Test for an allocated buffer. If already allocated this is due to having called this routine
1266 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1267 // the tag structure with current values from the NV
1269 if (InconsistentTags
->Next
== NULL
) {
1270 AddNextInconsistentTag (&InconsistentTags
);
1274 InconsistentTags
= InconsistentTags
->Next
;
1277 case EFI_IFR_EQ_VAR_VAL_OP
:
1278 IfrToFormTag (RawFormSet
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &RawFormSet
[Index
], NULL
);
1280 InconsistentTags
->Operand
= ((EFI_IFR_EQ_VAR_VAL
*) &RawFormSet
[Index
])->Header
.OpCode
;
1281 CopyMem (&InconsistentTags
->Value
, &((EFI_IFR_EQ_VAR_VAL
*) &RawFormSet
[Index
])->Value
, sizeof (UINT16
));
1283 &InconsistentTags
->QuestionId1
,
1284 &((EFI_IFR_EQ_VAR_VAL
*) &RawFormSet
[Index
])->VariableId
,
1289 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1290 // Unfortunately 0 is a valid offset value for a QuestionId
1292 InconsistentTags
->QuestionId2
= INVALID_OFFSET_VALUE
;
1293 InconsistentTags
->ConsistencyId
= gConsistencyId
;
1294 FormTags
->Tags
[CurrTag
].ConsistencyId
= gConsistencyId
;
1296 InconsistentTags
->VariableNumber
= CurrentVariable
;
1299 // Test for an allocated buffer. If already allocated this is due to having called this routine
1300 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1301 // the tag structure with current values from the NV
1303 if (InconsistentTags
->Next
== NULL
) {
1304 AddNextInconsistentTag (&InconsistentTags
);
1308 InconsistentTags
= InconsistentTags
->Next
;
1311 case EFI_IFR_EQ_ID_ID_OP
:
1312 IfrToFormTag (RawFormSet
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &RawFormSet
[Index
], NULL
);
1314 InconsistentTags
->Operand
= ((EFI_IFR_EQ_ID_ID
*) &RawFormSet
[Index
])->Header
.OpCode
;
1316 &InconsistentTags
->QuestionId1
,
1317 &((EFI_IFR_EQ_ID_ID
*) &RawFormSet
[Index
])->QuestionId1
,
1321 &InconsistentTags
->QuestionId2
,
1322 &((EFI_IFR_EQ_ID_ID
*) &RawFormSet
[Index
])->QuestionId2
,
1326 InconsistentTags
->Width
= FormTags
->Tags
[CurrTag
].StorageWidth
;
1327 InconsistentTags
->ConsistencyId
= gConsistencyId
;
1328 FormTags
->Tags
[CurrTag
].ConsistencyId
= gConsistencyId
;
1330 InconsistentTags
->VariableNumber
= CurrentVariable
;
1331 InconsistentTags
->VariableNumber2
= CurrentVariable2
;
1334 // Test for an allocated buffer. If already allocated this is due to having called this routine
1335 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1336 // the tag structure with current values from the NV
1338 if (InconsistentTags
->Next
== NULL
) {
1339 AddNextInconsistentTag (&InconsistentTags
);
1343 InconsistentTags
= InconsistentTags
->Next
;
1346 case EFI_IFR_AND_OP
:
1348 case EFI_IFR_NOT_OP
:
1351 case EFI_IFR_TRUE_OP
:
1352 case EFI_IFR_FALSE_OP
:
1353 InconsistentTags
->Operand
= ((EFI_IFR_NOT
*) &RawFormSet
[Index
])->Header
.OpCode
;
1356 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1357 // Unfortunately 0 is a valid offset value for a QuestionId
1361 // Reserve INVALID_OFFSET_VALUE - 1 for TRUE or FALSE because they are inconsistency tags also, but
1362 // have no coresponding id. The examination of id is needed by evaluating boolean expression.
1364 if (RawFormSet
[Index
] == EFI_IFR_TRUE_OP
||
1365 RawFormSet
[Index
] == EFI_IFR_FALSE_OP
) {
1366 InconsistentTags
->QuestionId1
= INVALID_OFFSET_VALUE
- 1;
1368 InconsistentTags
->QuestionId1
= INVALID_OFFSET_VALUE
;
1370 InconsistentTags
->QuestionId2
= INVALID_OFFSET_VALUE
;
1371 InconsistentTags
->ConsistencyId
= gConsistencyId
;
1372 FormTags
->Tags
[CurrTag
].ConsistencyId
= gConsistencyId
;
1375 // Test for an allocated buffer. If already allocated this is due to having called this routine
1376 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1377 // the tag structure with current values from the NV
1379 if (InconsistentTags
->Next
== NULL
) {
1380 AddNextInconsistentTag (&InconsistentTags
);
1384 InconsistentTags
= InconsistentTags
->Next
;
1387 case EFI_IFR_EQ_ID_LIST_OP
:
1388 IfrToFormTag (RawFormSet
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &RawFormSet
[Index
], NULL
);
1390 InconsistentTags
->Operand
= ((EFI_IFR_EQ_ID_LIST
*) &RawFormSet
[Index
])->Header
.OpCode
;
1392 &InconsistentTags
->QuestionId1
,
1393 &((EFI_IFR_EQ_ID_LIST
*) &RawFormSet
[Index
])->QuestionId
,
1397 &InconsistentTags
->ListLength
,
1398 &((EFI_IFR_EQ_ID_LIST
*) &RawFormSet
[Index
])->ListLength
,
1401 InconsistentTags
->ValueList
= FormTags
->Tags
[CurrTag
].IntList
;
1404 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1405 // Unfortunately 0 is a valid offset value for a QuestionId
1407 InconsistentTags
->Width
= FormTags
->Tags
[CurrTag
].StorageWidth
;
1408 InconsistentTags
->QuestionId2
= INVALID_OFFSET_VALUE
;
1409 InconsistentTags
->ConsistencyId
= gConsistencyId
;
1410 FormTags
->Tags
[CurrTag
].ConsistencyId
= gConsistencyId
;
1413 // Test for an allocated buffer. If already allocated this is due to having called this routine
1414 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1415 // the tag structure with current values from the NV
1417 if (InconsistentTags
->Next
== NULL
) {
1418 AddNextInconsistentTag (&InconsistentTags
);
1422 InconsistentTags
= InconsistentTags
->Next
;
1425 case EFI_IFR_END_IF_OP
:
1426 InconsistentTags
->Operand
= ((EFI_IFR_END_EXPR
*) &RawFormSet
[Index
])->Header
.OpCode
;
1429 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1430 // Unfortunately 0 is a valid offset value for a QuestionId
1432 InconsistentTags
->QuestionId1
= INVALID_OFFSET_VALUE
;
1433 InconsistentTags
->QuestionId2
= INVALID_OFFSET_VALUE
;
1436 // Test for an allocated buffer. If already allocated this is due to having called this routine
1437 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1438 // the tag structure with current values from the NV
1440 if (InconsistentTags
->Next
== NULL
) {
1441 AddNextInconsistentTag (&InconsistentTags
);
1445 InconsistentTags
= InconsistentTags
->Next
;
1448 case EFI_IFR_END_ONE_OF_OP
:
1457 // Per spec., we ignore ops that we don't know how to deal with. Skip to next tag
1459 Index
= (UINT16
) (Index
+ TagLength
);
1464 // When we eventually exit, make sure we mark the last tag with an op-code
1466 FormTags
->Tags
[CurrTag
].Operand
= RawFormSet
[Index
];
1468 IfrToFormTag (RawFormSet
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &RawFormSet
[Index
], NULL
);
1471 // Place this as an end of the database marker
1473 InconsistentTags
->Operand
= 0xFF;
1476 // This is the Head of the linked list of pages. Each page is an array of tags
1478 FormTags
= &FileFormTags
->FormTags
;
1479 InconsistentTags
= FileFormTags
->InconsistentTags
;
1481 for (; InconsistentTags
->Operand
!= 0xFF;) {
1482 if (InconsistentTags
->QuestionId1
!= INVALID_OFFSET_VALUE
) {
1484 // Search the tags for the tag which corresponds to this ID
1486 for (CurrTag
= 0; FormTags
->Tags
[0].Operand
!= EFI_IFR_END_FORM_SET_OP
; CurrTag
++) {
1488 // If we hit the end of a form, go to the next set of Tags.
1489 // Remember - EndFormSet op-codes sit on their own page after an end form.
1491 if (FormTags
->Tags
[CurrTag
].Operand
== EFI_IFR_END_FORM_OP
) {
1493 // Reset the CurrTag value (it will be incremented, after this case statement
1494 // so set to a negative one so that we get the desired effect.) Fish can beat me later.
1497 FormTags
= FormTags
->Next
;
1501 if (FormTags
->Tags
[CurrTag
].Id
== InconsistentTags
->QuestionId1
) {
1502 FormTags
->Tags
[CurrTag
].Consistency
++;
1507 FormTags
= &FileFormTags
->FormTags
;
1509 if (InconsistentTags
->QuestionId2
!= INVALID_OFFSET_VALUE
) {
1511 // Search the tags for the tag which corresponds to this ID
1513 for (CurrTag
= 0; FormTags
->Tags
[CurrTag
].Operand
!= EFI_IFR_END_FORM_SET_OP
; CurrTag
++) {
1515 // If we hit the end of a form, go to the next set of Tags.
1516 // Remember - EndFormSet op-codes sit on their own page after an end form.
1518 if (FormTags
->Tags
[CurrTag
].Operand
== EFI_IFR_END_FORM_OP
) {
1520 // Reset the CurrTag value (it will be incremented, after this case statement
1521 // so set to a negative one so that we get the desired effect.) Fish can beat me later.
1524 FormTags
= FormTags
->Next
;
1528 if (FormTags
->Tags
[CurrTag
].Id
== InconsistentTags
->QuestionId2
) {
1529 FormTags
->Tags
[CurrTag
].Consistency
++;
1534 InconsistentTags
= InconsistentTags
->Next
;
1545 CHAR16
*HomePageString
;
1546 CHAR16
*HomeEscapeString
;
1549 // Displays the Header and Footer borders
1551 DisplayPageFrame ();
1553 HomePageString
= GetToken (STRING_TOKEN (HOME_PAGE_TITLE
), gHiiHandle
);
1554 HomeEscapeString
= GetToken (STRING_TOKEN (HOME_ESCAPE_STRING
), gHiiHandle
);
1556 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_YELLOW
| EFI_BRIGHT
);
1558 // PrintStringAt ((gScreenDimensions.RightColumn - GetStringWidth(HomePageString)/2)/2, 1, HomePageString);
1561 (gScreenDimensions
.RightColumn
+ gScreenDimensions
.LeftColumn
- GetStringWidth (HomePageString
) / 2) / 2,
1566 gScreenDimensions
.LeftColumn
+ 2,
1567 gScreenDimensions
.BottomRow
- 3,
1568 (CHAR16
*) L
"%c%c%s",
1574 gScreenDimensions
.RightColumn
- (GetStringWidth (HomeEscapeString
) / 2) - 2,
1575 gScreenDimensions
.BottomRow
- 3,
1579 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
1580 FreePool (HomeEscapeString
);
1581 FreePool (HomePageString
);
1588 IN STRING_REF Token
,
1589 IN EFI_HII_HANDLE HiiHandle
1593 Routine Description:
1595 Get the string based on the TokenID and HII Handle.
1599 Token - The Token ID.
1600 HiiHandle - Handle of Ifr to be fetched.
1613 // Set default string size assumption at no more than 256 bytes
1615 BufferLength
= 0x100;
1617 Buffer
= AllocateZeroPool (BufferLength
);
1618 ASSERT (Buffer
!= NULL
);
1620 Status
= Hii
->GetString (Hii
, HiiHandle
, Token
, TRUE
, NULL
, &BufferLength
, Buffer
);
1622 if (EFI_ERROR (Status
)) {
1623 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1625 // Free the old pool
1630 // Allocate new pool with correct value
1632 Buffer
= AllocatePool (BufferLength
);
1633 ASSERT (Buffer
!= NULL
);
1635 Status
= Hii
->GetString (Hii
, HiiHandle
, Token
, TRUE
, NULL
, &BufferLength
, Buffer
);
1637 if (!EFI_ERROR (Status
)) {
1642 ASSERT_EFI_ERROR (Status
);
1651 IN UINTN NumberOfIfrImages
,
1652 IN EFI_FILE_FORM_TAGS
*FileFormTagsHead
1657 EFI_IFR_BINARY
*IfrBinary
;
1659 EFI_FILE_FORM_TAGS
*FileFormTags
;
1660 EFI_FORM_TAGS LocalTags
;
1662 FileFormTags
= FileFormTagsHead
;
1666 Status
= EFI_SUCCESS
;
1669 // If there are no images
1671 if (NumberOfIfrImages
== 0) {
1672 Status
= EFI_NO_MEDIA
;
1676 // IfrBinary points to the beginning of the Binary data linked-list
1678 IfrBinary
= gBinaryDataHead
;
1681 // Print the entries which were in the default language.
1683 for (Index
= 0; Index
< NumberOfIfrImages
; Index
++) {
1684 LocalTags
= FileFormTags
->FormTags
;
1687 // Populate the Menu
1689 StringPtr
= GetToken (IfrBinary
->TitleToken
, IfrBinary
->Handle
);
1692 // If the default language doesn't exist, don't add a menu option yet
1694 if (StringPtr
[0] != CHAR_NULL
) {
1696 // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do
1697 // it in UiFreeMenu.
1699 UiAddMenuOption (StringPtr
, IfrBinary
->Handle
, LocalTags
.Tags
, IfrBinary
->FormBinary
, Index
);
1702 // Advance to the next HII handle
1704 IfrBinary
= IfrBinary
->Next
;
1705 FileFormTags
= FileFormTags
->NextFile
;
1714 IN UINTN NumberOfIfrImages
,
1715 IN EFI_FILE_FORM_TAGS
*FileFormTagsHead
,
1716 IN UINT8
*CallbackData
1720 UI_MENU_OPTION
*Selection
;
1723 // This prints the basic home page template which the user sees
1727 Status
= PopulateHomePage (NumberOfIfrImages
, FileFormTagsHead
);
1729 if (EFI_ERROR (Status
)) {
1734 Selection
= UiDisplayMenu (FALSE
, FileFormTagsHead
, (EFI_IFR_DATA_ARRAY
*) CallbackData
);
1741 InitializeBinaryStructures (
1742 IN EFI_HII_HANDLE
*Handle
,
1743 IN BOOLEAN UseDatabase
,
1744 IN EFI_IFR_PACKET
*Packet
,
1745 IN UINT8
*NvMapOverride
,
1746 IN UINTN NumberOfIfrImages
,
1747 OUT EFI_FILE_FORM_TAGS
**FileFormTagsHead
1752 EFI_IFR_BINARY
*BinaryData
;
1753 EFI_FILE_FORM_TAGS
*FileFormTags
;
1754 UINTN SizeOfNvStore
;
1755 EFI_FORM_CALLBACK_PROTOCOL
*FormCallback
;
1756 EFI_VARIABLE_DEFINITION
*VariableDefinition
;
1757 EFI_VARIABLE_DEFINITION
*OverrideDefinition
;
1760 EFI_HII_VARIABLE_PACK_LIST
*NvMapListHead
;
1761 EFI_HII_VARIABLE_PACK_LIST
*NvMapListNode
;
1764 // Initialize some variables to avoid warnings
1767 *FileFormTagsHead
= NULL
;
1768 FileFormTags
= NULL
;
1769 gBinaryDataHead
= NULL
;
1770 Status
= EFI_SUCCESS
;
1771 FormCallback
= NULL
;
1775 if (NumberOfIfrImages
> 1) {
1776 NvMapOverride
= NULL
;
1779 for (HandleIndex
= 0; HandleIndex
< NumberOfIfrImages
; HandleIndex
+= 1) {
1781 // If the buffers are uninitialized, allocate them, otherwise work on the ->Next members
1783 if ((BinaryData
== NULL
) || (FileFormTags
== NULL
)) {
1785 // Allocate memory for our Binary Data
1787 BinaryData
= AllocateZeroPool (sizeof (EFI_IFR_BINARY
));
1788 ASSERT (BinaryData
);
1791 // Preserve the Head of what will be a linked-list.
1793 gBinaryDataHead
= BinaryData
;
1794 gBinaryDataHead
->Next
= NULL
;
1797 Status
= GetIfrBinaryData (Hii
, Handle
[HandleIndex
], NULL
, BinaryData
);
1799 Status
= GetIfrBinaryData (Hii
, Handle
[HandleIndex
], Packet
, BinaryData
);
1802 // Allocate memory for our File Form Tags
1804 FileFormTags
= AllocateZeroPool (sizeof (EFI_FILE_FORM_TAGS
));
1805 ASSERT (FileFormTags
);
1808 // Preserve the Head of what will be a linked-list.
1810 *FileFormTagsHead
= FileFormTags
;
1811 (*FileFormTagsHead
)->NextFile
= NULL
;
1815 // Allocate memory for our Binary Data linked-list
1816 // Each handle represents a Binary and we will store that data away.
1818 BinaryData
->Next
= AllocateZeroPool (sizeof (EFI_IFR_BINARY
));
1819 ASSERT (BinaryData
->Next
);
1821 BinaryData
= BinaryData
->Next
;
1822 BinaryData
->Next
= NULL
;
1825 Status
= GetIfrBinaryData (Hii
, Handle
[HandleIndex
], NULL
, BinaryData
);
1827 Status
= GetIfrBinaryData (Hii
, Handle
[HandleIndex
], Packet
, BinaryData
);
1830 if (EFI_ERROR (Status
)) {
1831 return EFI_DEVICE_ERROR
;
1834 // Allocate memory for our FileFormTags linked-list
1835 // Each allocation reserves handle represents a Binary and we will store that data away.
1837 FileFormTags
->NextFile
= AllocateZeroPool (sizeof (EFI_FILE_FORM_TAGS
));
1838 ASSERT (FileFormTags
->NextFile
);
1840 FileFormTags
= FileFormTags
->NextFile
;
1845 // Tag Structure Initialization
1847 Status
= InitializeTagStructures (BinaryData
, FileFormTags
);
1849 VariableDefinition
= FileFormTags
->VariableDefinitions
;
1852 // Allocate memory for our NVRAM Maps for all of our variables
1854 for (; VariableDefinition
!= NULL
; VariableDefinition
= VariableDefinition
->Next
) {
1856 // Pad the fake variable size accordingly - this value should reflect the size of information that is not accounted by
1857 // the mainstream NVRAM variable such as DATE/TIME information that the browser needs to track but is saved to an RTC
1859 VariableDefinition
->VariableFakeSize
= (UINT16
) (VariableDefinition
->VariableSize
+ VariableDefinition
->VariableFakeSize
);
1862 // In the case where a file has no "real" NV data, we should pad the buffer accordingly
1864 if (VariableDefinition
->VariableSize
== 0) {
1865 if (VariableDefinition
->VariableFakeSize
!= 0) {
1866 VariableDefinition
->NvRamMap
= AllocateZeroPool (VariableDefinition
->VariableFakeSize
);
1867 ASSERT (VariableDefinition
->NvRamMap
!= NULL
);
1870 VariableDefinition
->NvRamMap
= AllocateZeroPool (VariableDefinition
->VariableSize
);
1871 ASSERT (VariableDefinition
->NvRamMap
!= NULL
);
1874 if (VariableDefinition
->VariableFakeSize
!= 0) {
1875 VariableDefinition
->FakeNvRamMap
= AllocateZeroPool (VariableDefinition
->VariableFakeSize
);
1876 ASSERT (VariableDefinition
->FakeNvRamMap
!= NULL
);
1880 Status
= gBS
->HandleProtocol (
1881 (VOID
*) (UINTN
) FileFormTags
->FormTags
.Tags
[0].CallbackHandle
,
1882 &gEfiFormCallbackProtocolGuid
,
1883 (VOID
**) &FormCallback
1887 // Since we might have multiple variables, if there is an NvMapOverride we need to use the EFI_VARIABLE_DEFINITION
1888 // information as the information that we pass back and forth. NOTE that callbacks that are initiated will only have the
1889 // NVRAM data refreshed based on the op-code that initiated the callback. In other words, we will pass to the caller a single
1890 // NVRAM map for a single variable based on the op-code that the user selected.
1892 if (NvMapOverride
!= NULL
) {
1893 VariableDefinition
= FileFormTags
->VariableDefinitions
;
1894 OverrideDefinition
= ((EFI_VARIABLE_DEFINITION
*) NvMapOverride
);
1897 // Search through the variable definitions. There should be sufficient passed in settings for the variable op-codes specified
1899 for (; VariableDefinition
!= NULL
; VariableDefinition
= VariableDefinition
->Next
) {
1900 if ((!CompareMem (VariableDefinition
->VariableName
, L
"Setup", 10)) && (VariableDefinition
->Next
== NULL
)) {
1901 if (VariableDefinition
->VariableSize
!= 0) {
1902 CopyMem (VariableDefinition
->NvRamMap
, NvMapOverride
, VariableDefinition
->VariableSize
);
1904 CopyMem (VariableDefinition
->NvRamMap
, NvMapOverride
, VariableDefinition
->VariableFakeSize
);
1908 VariableDefinition
->NvRamMap
= OverrideDefinition
->NvRamMap
;
1911 // There should NEVER be a ->Next for VariableDefinition and a NULL ->Next for the OverrideDefinition
1913 ASSERT (OverrideDefinition
->Next
);
1914 OverrideDefinition
= OverrideDefinition
->Next
;
1917 VariableDefinition
= FileFormTags
->VariableDefinitions
;
1920 // Search through the variable definitions. There should be sufficient passed in settings for the variable op-codes specified
1922 for (; VariableDefinition
!= NULL
; VariableDefinition
= VariableDefinition
->Next
) {
1923 SizeOfNvStore
= VariableDefinition
->VariableSize
;
1926 // Getting the NvStore and placing it into our Global Data
1928 if ((FormCallback
!= NULL
) && (FormCallback
->NvRead
!= NULL
)) {
1929 Status
= FormCallback
->NvRead (
1931 VariableDefinition
->VariableName
,
1932 &VariableDefinition
->Guid
,
1935 (VOID
*) VariableDefinition
->NvRamMap
1938 Status
= gRT
->GetVariable (
1939 VariableDefinition
->VariableName
,
1940 &VariableDefinition
->Guid
,
1943 (VOID
*) VariableDefinition
->NvRamMap
1947 if (EFI_ERROR (Status
)) {
1949 // If there is a variable that exists already and it is larger than what we calculated the
1950 // storage needs to be, we must assume the variable size from GetVariable is correct and not
1951 // allow the truncation of the variable. It is very possible that the user who created the IFR
1952 // we are cracking is not referring to a variable that was in a previous map, however we cannot
1953 // allow it's truncation.
1955 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1957 // If the buffer was too small, we should have the expanded size requirement in SizeOfNvStore now.
1959 VariableDefinition
->VariableSize
= (UINT16
) SizeOfNvStore
;
1962 // Free the buffer that was allocated that was too small
1964 FreePool (VariableDefinition
->NvRamMap
);
1965 FreePool (VariableDefinition
->FakeNvRamMap
);
1967 VariableDefinition
->NvRamMap
= AllocateZeroPool (SizeOfNvStore
);
1968 VariableDefinition
->FakeNvRamMap
= AllocateZeroPool (SizeOfNvStore
+ VariableDefinition
->VariableFakeSize
);
1969 ASSERT (VariableDefinition
->NvRamMap
);
1970 ASSERT (VariableDefinition
->FakeNvRamMap
);
1972 if ((FormCallback
!= NULL
) && (FormCallback
->NvRead
!= NULL
)) {
1973 Status
= FormCallback
->NvRead (
1975 VariableDefinition
->VariableName
,
1976 &VariableDefinition
->Guid
,
1979 (VOID
*) VariableDefinition
->NvRamMap
1982 Status
= gRT
->GetVariable (
1983 VariableDefinition
->VariableName
,
1984 &VariableDefinition
->Guid
,
1987 (VOID
*) VariableDefinition
->NvRamMap
1992 // if the variable was not found, we will retrieve default values
1994 if (Status
== EFI_NOT_FOUND
) {
1996 if (0 == CompareMem (VariableDefinition
->VariableName
, L
"Setup", 10)) {
1998 NvMapListHead
= NULL
;
2000 Status
= Hii
->GetDefaultImage (Hii
, Handle
[HandleIndex
], EFI_IFR_FLAG_DEFAULT
, &NvMapListHead
);
2002 if (!EFI_ERROR (Status
)) {
2003 ASSERT_EFI_ERROR (NULL
!= NvMapListHead
);
2005 NvMapListNode
= NvMapListHead
;
2007 while (NULL
!= NvMapListNode
) {
2008 if (VariableDefinition
->VariableId
== NvMapListNode
->VariablePack
->VariableId
) {
2009 NvMap
= (VOID
*) ((CHAR8
*) NvMapListNode
->VariablePack
+ sizeof (EFI_HII_VARIABLE_PACK
) + NvMapListNode
->VariablePack
->VariableNameLength
);
2010 NvMapSize
= NvMapListNode
->VariablePack
->Header
.Length
- sizeof (EFI_HII_VARIABLE_PACK
) - NvMapListNode
->VariablePack
->VariableNameLength
;
2013 NvMapListNode
= NvMapListNode
->NextVariablePack
;
2017 // Free the buffer that was allocated.
2019 FreePool (VariableDefinition
->NvRamMap
);
2020 FreePool (VariableDefinition
->FakeNvRamMap
);
2023 // Allocate, copy the NvRamMap.
2025 VariableDefinition
->VariableFakeSize
= (UINT16
) (VariableDefinition
->VariableFakeSize
- VariableDefinition
->VariableSize
);
2026 VariableDefinition
->VariableSize
= (UINT16
) NvMapSize
;
2027 VariableDefinition
->VariableFakeSize
= (UINT16
) (VariableDefinition
->VariableFakeSize
+ VariableDefinition
->VariableSize
);
2029 VariableDefinition
->NvRamMap
= AllocateZeroPool (VariableDefinition
->VariableSize
);
2030 VariableDefinition
->FakeNvRamMap
= AllocateZeroPool (NvMapSize
+ VariableDefinition
->VariableFakeSize
);
2032 CopyMem (VariableDefinition
->NvRamMap
, NvMap
, NvMapSize
);
2033 FreePool (NvMapListHead
);
2037 Status
= EFI_SUCCESS
;
2043 InitializeTagStructures (BinaryData
, FileFormTags
);
2054 IN EFI_HII_PROTOCOL
*Hii
,
2055 IN EFI_HII_HANDLE HiiHandle
,
2056 IN EFI_IFR_PACKET
*Packet
,
2057 IN OUT EFI_IFR_BINARY
*BinaryData
2061 Routine Description:
2062 Fetch the Ifr binary data.
2065 Hii - Point to HII protocol.
2066 HiiHandle - Handle of Ifr to be fetched.
2067 Packet - Pointer to IFR packet.
2068 BinaryData - Buffer to copy the string into
2071 Returns the number of CHAR16 characters that were copied into the OutputString buffer.
2077 EFI_HII_PACKAGES
*PackageList
;
2080 UINT8
*RawFormBinary
;
2081 EFI_IFR_FORM_SET
*FormOp
;
2087 // Initialize the TitleToken to 0 just in case not found
2092 // Try for a 32K Buffer
2094 BufferSize
= 0x8000;
2097 // Allocate memory for our Form binary
2099 Buffer
= AllocateZeroPool (BufferSize
);
2102 if (Packet
== NULL
) {
2103 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &BufferSize
, Buffer
);
2105 if (Status
== EFI_BUFFER_TOO_SMALL
) {
2110 // Allocate memory for our Form binary
2112 Buffer
= AllocatePool (BufferSize
);
2115 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &BufferSize
, Buffer
);
2119 // Copies the data to local usable buffer
2121 CopyMem (Buffer
, Packet
->IfrData
, Packet
->IfrData
->Header
.Length
);
2124 // Register the string data with HII
2126 PackageList
= PreparePackages (2, NULL
, Packet
->IfrData
, Packet
->StringData
);
2128 Status
= Hii
->NewPack (Hii
, PackageList
, &HiiHandle
);
2130 FreePool (PackageList
);
2133 if (EFI_ERROR (Status
)) {
2137 // We now have the IFR binary in our Buffer
2139 BinaryData
->IfrPackage
= Buffer
;
2140 RawFormBinary
= (UINT8
*) ((CHAR8
*) (Buffer
) + sizeof (EFI_HII_PACK_HEADER
));
2141 BinaryData
->FormBinary
= (UINT8
*) ((CHAR8
*) (Buffer
) + sizeof (EFI_HII_PACK_HEADER
));
2142 BinaryData
->Handle
= HiiHandle
;
2145 // If a packet was passed in, remove the string data when exiting.
2147 if (Packet
!= NULL
) {
2148 BinaryData
->UnRegisterOnExit
= TRUE
;
2150 BinaryData
->UnRegisterOnExit
= FALSE
;
2153 // Walk through the FormSet Opcodes looking for the FormSet opcode
2154 // If we hit EFI_IFR_END_SET_OP we know we hit the end of the FormSet.
2156 for (Index
= 0; RawFormBinary
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
2157 FormOp
= (EFI_IFR_FORM_SET
*) &RawFormBinary
[Index
];
2158 Index
= (UINT16
) (Index
+ FormOp
->Header
.Length
);
2160 if (FormOp
->Header
.OpCode
== EFI_IFR_FORM_SET_OP
) {
2161 TitleToken
= FormOp
->FormSetTitle
;
2163 // If displaying FrontPage - set the flag signifying it
2165 switch (FormOp
->SubClass
) {
2166 case EFI_FRONT_PAGE_SUBCLASS
:
2167 FrontPageHandle
= HiiHandle
;
2170 gClassOfVfr
= FormOp
->SubClass
;
2173 // Match GUID to find out the function key setting. If match fail, use the default setting.
2175 for (Index2
= 0; Index2
< sizeof (gFunctionKeySettingTable
) / sizeof (FUNCTIION_KEY_SETTING
); Index2
++) {
2176 if (CompareGuid ((EFI_GUID
*)(UINTN
)&FormOp
->Guid
, &(gFunctionKeySettingTable
[Index2
].FormSetGuid
))) {
2178 // Update the function key setting.
2180 gFunctionKeySetting
= gFunctionKeySettingTable
[Index2
].KeySetting
;
2182 // Function key prompt can not be displayed if the function key has been disabled.
2184 if ((gFunctionKeySetting
& FUNCTION_ONE
) != FUNCTION_ONE
) {
2185 gFunctionOneString
= GetToken (STRING_TOKEN (EMPTY_STRING
), gHiiHandle
);
2188 if ((gFunctionKeySetting
& FUNCTION_TWO
) != FUNCTION_TWO
) {
2189 gFunctionTwoString
= GetToken (STRING_TOKEN (EMPTY_STRING
), gHiiHandle
);
2192 if ((gFunctionKeySetting
& FUNCTION_NINE
) != FUNCTION_NINE
) {
2193 gFunctionNineString
= GetToken (STRING_TOKEN (EMPTY_STRING
), gHiiHandle
);
2196 if ((gFunctionKeySetting
& FUNCTION_TEN
) != FUNCTION_TEN
) {
2197 gFunctionTenString
= GetToken (STRING_TOKEN (EMPTY_STRING
), gHiiHandle
);
2204 BinaryData
->TitleToken
= TitleToken
;
2209 EFI_HANDLE PrintHandle
= NULL
;
2210 EFI_PRINT_PROTOCOL mPrintProtocol
= { UnicodeVSPrint
};
2218 return gBS
->InstallProtocolInterface (
2220 &gEfiPrintProtocolGuid
,
2221 EFI_NATIVE_INTERFACE
,