]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Setup.c
Modules clean up.
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / SetupBrowserDxe / Setup.c
1 /**@file
2 Entry and initialization module for the browser.
3
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
9
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.
12
13 **/
14
15
16 #include "Setup.h"
17 #include "Ui.h"
18
19 FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {
20 //
21 // Boot Manager
22 //
23 {
24 {
25 0x847bc3fe,
26 0xb974,
27 0x446d,
28 {
29 0x94,
30 0x49,
31 0x5a,
32 0xd5,
33 0x41,
34 0x2e,
35 0x99,
36 0x3b
37 }
38 },
39 NONE_FUNCTION_KEY_SETTING
40 },
41 //
42 // Device Manager
43 //
44 {
45 {
46 0x3ebfa8e6,
47 0x511d,
48 0x4b5b,
49 {
50 0xa9,
51 0x5f,
52 0xfb,
53 0x38,
54 0x26,
55 0xf,
56 0x1c,
57 0x27
58 }
59 },
60 NONE_FUNCTION_KEY_SETTING
61 },
62 //
63 // BMM Formset.
64 //
65 {
66 {
67 0x642237c7,
68 0x35d4,
69 0x472d,
70 {
71 0x83,
72 0x65,
73 0x12,
74 0xe0,
75 0xcc,
76 0xf2,
77 0x7a,
78 0x22
79 }
80 },
81 NONE_FUNCTION_KEY_SETTING
82 },
83 //
84 // BMM File Explorer Formset.
85 //
86 {
87 {
88 0x1f2d63e1,
89 0xfebd,
90 0x4dc7,
91 {
92 0x9c,
93 0xc5,
94 0xba,
95 0x2b,
96 0x1c,
97 0xef,
98 0x9c,
99 0x5b
100 }
101 },
102 NONE_FUNCTION_KEY_SETTING
103 },
104 };
105
106 STATIC
107 EFI_STATUS
108 InitializeBinaryStructures (
109 IN EFI_HII_HANDLE *Handle,
110 IN BOOLEAN UseDatabase,
111 IN EFI_IFR_PACKET *Packet,
112 IN UINT8 *NvMapOverride,
113 IN UINTN NumberOfIfrImages,
114 EFI_FILE_FORM_TAGS **FileFormTagsHead
115 );
116
117 STATIC
118 EFI_STATUS
119 InitializeTagStructures (
120 IN EFI_IFR_BINARY *BinaryData,
121 OUT EFI_FILE_FORM_TAGS *FileFormTags
122 );
123
124 STATIC
125 UI_MENU_OPTION *
126 DisplayHomePage (
127 IN UINTN NumberOfIfrImages,
128 IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
129 IN UINT8 *CallbackData
130 );
131
132 STATIC
133 EFI_STATUS
134 GetIfrBinaryData (
135 IN EFI_HII_PROTOCOL *Hii,
136 IN EFI_HII_HANDLE HiiHandle,
137 IN EFI_IFR_PACKET *Packet,
138 IN EFI_IFR_BINARY *BinaryData
139 );
140
141 STATIC
142 EFI_STATUS
143 InstallPrint (
144 VOID
145 );
146
147 STATIC
148 EFI_STATUS
149 EFIAPI
150 SendForm (
151 IN EFI_FORM_BROWSER_PROTOCOL * This,
152 IN BOOLEAN UseDatabase,
153 IN EFI_HII_HANDLE * Handle,
154 IN UINTN HandleCount,
155 IN EFI_IFR_PACKET * Packet,
156 IN EFI_HANDLE CallbackHandle,
157 IN UINT8 *NvMapOverride,
158 IN EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL
159 OUT BOOLEAN *ResetRequired OPTIONAL
160 )
161 /*++
162
163 Routine Description:
164
165 This is the routine which an external caller uses to direct the browser
166 where to obtain it's information.
167
168 Arguments:
169
170 UseDatabase - If set to TRUE, then all information is retrieved from the HII database handle specified
171 If set to FALSE, then the passed in Packet and CallbackHandle is used and Handle is ignored
172
173 Handle - A pointer to an array of Handles. If HandleCount > 1 we display a list of the formsets for the handles specified
174
175 HandleCount - The number of Handles specified in Handle.
176
177 Packet - Valid only if UseDatabase is FALSE. Packet defines the pages being passed into
178 the browser. This is composed of IFR data as well as String information.
179
180 CallbackHandle - The handle which contains the calling driver's EFI_FORM_CALLBACK_PROTOCOL interface.
181
182 ScreenDimenions - This allows the browser to be called so that it occupies a portion of the physical screen instead of
183 dynamically determining the screen dimensions.
184
185 NvMapOverride - This buffer is used only when there is no NV variable to define the current settings and the caller
186 needs to provide to the browser the current settings for the "fake" NV variable. If used, no saving
187 of an NV variable will be possible. This parameter is also ignored if HandleCount > 1.
188
189 Returns:
190
191 --*/
192 {
193 EFI_FORM_CALLBACK_PROTOCOL *FormCallback;
194 EFI_FILE_FORM_TAGS *FileFormTagsHead;
195 UI_MENU_OPTION *Selection;
196 UI_MENU_OPTION *AltSelection;
197 EFI_STATUS Status;
198 BOOLEAN Callback;
199 VOID *CallbackData;
200 EFI_HII_HANDLE BackupHandle;
201
202 ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
203
204 gPreviousValue = AllocatePool (0x1000);
205 CallbackData = AllocatePool (0x10000);
206 ASSERT (gPreviousValue != NULL);
207 ASSERT (CallbackData != NULL);
208
209 do {
210 //
211 // Seed the dimensions in the global
212 //
213 gST->ConOut->QueryMode (
214 gST->ConOut,
215 gST->ConOut->Mode->Mode,
216 &gScreenDimensions.RightColumn,
217 &gScreenDimensions.BottomRow
218 );
219
220 if (ScreenDimensions != NULL) {
221 //
222 // Check local dimension vs. global dimension.
223 //
224 if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||
225 (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)
226 ) {
227 return EFI_INVALID_PARAMETER;
228 } else {
229 //
230 // Local dimension validation.
231 //
232 if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) &&
233 (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) &&
234 ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) &&
235 (
236 (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +
237 SCROLL_ARROW_HEIGHT *
238 2 +
239 FRONT_PAGE_HEADER_HEIGHT +
240 FOOTER_HEIGHT +
241 1
242 )
243 ) {
244 CopyMem (&gScreenDimensions, ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
245 } else {
246 return EFI_INVALID_PARAMETER;
247 }
248 }
249 }
250
251 gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);
252 gHelpBlockWidth = gOptionBlockWidth;
253 gPromptBlockWidth = gOptionBlockWidth;
254
255 //
256 // Initialize the strings for the browser, upon exit of the browser, the strings will be freed
257 //
258 InitializeBrowserStrings ();
259
260 gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING;
261 gClassOfVfr = EFI_SETUP_APPLICATION_SUBCLASS;
262 gResetRequired = FALSE;
263 gExitRequired = FALSE;
264 gSaveRequired = FALSE;
265 gNvUpdateRequired = FALSE;
266 gActiveIfr = 0;
267 gConsistencyId = 0;
268 gPriorMenuEntry = 0;
269 BackupHandle = *Handle;
270 gMenuRefreshHead = NULL;
271 ASSERT (CallbackData);
272 ZeroMem (CallbackData, 0x10000);
273
274 //
275 // We can recurse through this and might need to re-allocate this particular buffer
276 //
277 if (gPreviousValue == NULL) {
278 gPreviousValue = AllocatePool (0x1000);
279 ASSERT (gPreviousValue != NULL);
280 }
281
282 Callback = FALSE;
283 FormCallback = NULL;
284
285 if (CallbackHandle != NULL) {
286 //
287 // Retrieve the Callback protocol interface
288 //
289 Status = gBS->HandleProtocol (
290 CallbackHandle,
291 &gEfiFormCallbackProtocolGuid,
292 (VOID **) &FormCallback
293 );
294
295 if (EFI_ERROR (Status)) {
296 FreePool (CallbackData);
297 return Status;;
298 }
299
300 Callback = TRUE;
301 }
302 //
303 // Initializes all the internal state structures for all IFR images in system
304 //
305 Status = InitializeBinaryStructures (Handle, UseDatabase, Packet, NvMapOverride, HandleCount, &FileFormTagsHead);
306
307 if (EFI_ERROR (Status)) {
308 FreePool (CallbackData);
309 return Status;
310 }
311 //
312 // Beginning of the Presentation of the Data
313 //
314 if (UseDatabase && (HandleCount > 1)) {
315 Selection = DisplayHomePage (HandleCount, FileFormTagsHead, CallbackData);
316 } else {
317 //
318 // If passing something specific, we know there is only one Ifr
319 //
320 Selection = AllocateZeroPool (sizeof (UI_MENU_OPTION));
321 ASSERT (Selection != NULL);
322 Selection->IfrNumber = 0;
323 Selection->Handle = Handle[0];
324 UiInitMenu ();
325 }
326
327 UiInitMenuList ();
328
329 if (UseDatabase && (HandleCount > 1)) {
330 if (Selection == NULL) {
331 FreePool (CallbackData);
332 return EFI_SUCCESS;
333 }
334 }
335 //
336 // Launch the setup browser with the user's selection information
337 //
338 AltSelection = SetupBrowser (Selection, Callback, FileFormTagsHead, CallbackData);
339
340 //
341 // If the caller cares about Reset status, we can return to the caller if something happened that required a reset
342 //
343 if (ResetRequired != NULL) {
344 *ResetRequired = gResetRequired;
345 }
346
347 if (Callback && (AltSelection != NULL)) {
348 if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
349 Status = FormCallback->Callback (
350 FormCallback,
351 AltSelection->ThisTag->Key,
352 CallbackData,
353 (EFI_HII_CALLBACK_PACKET **) &Packet
354 );
355 }
356 }
357
358 *Handle = BackupHandle;
359
360 if (EFI_ERROR (Status)) {
361 FreePool (CallbackData);
362 return Status;
363 }
364
365 if (Callback && (AltSelection == NULL)) {
366 FreePool (CallbackData);
367 return Status;
368 }
369
370 if (UseDatabase && (HandleCount > 1)) {
371 } else {
372
373 if (gBinaryDataHead->UnRegisterOnExit) {
374 Hii->RemovePack (Hii, Handle[0]);
375 }
376
377 if (Callback &&
378 ((AltSelection->ThisTag->SubClass == EFI_FRONT_PAGE_SUBCLASS) ||
379 (AltSelection->ThisTag->SubClass == EFI_SINGLE_USE_SUBCLASS))) {
380 //
381 // If this is the FrontPage, return after every selection
382 //
383 FreePool (Selection);
384 UiFreeMenu ();
385
386 //
387 // Clean up the allocated data buffers
388 //
389 FreeData (FileFormTagsHead, NULL, NULL);
390
391 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
392 gST->ConOut->ClearScreen (gST->ConOut);
393
394 FreePool (CallbackData);
395 return EFI_SUCCESS;
396 }
397
398 FreePool (Selection);
399 UiFreeMenu ();
400
401 //
402 // Clean up the allocated data buffers
403 //
404 FreeData (FileFormTagsHead, NULL, NULL);
405
406 gST->ConOut->ClearScreen (gST->ConOut);
407
408 if (!Callback) {
409 FreePool (CallbackData);
410 return EFI_SUCCESS;
411 }
412 }
413
414 } while (!EFI_ERROR (Status));
415
416 FreePool (CallbackData);
417 return Status;
418 }
419
420 EFI_STATUS
421 EFIAPI
422 InitializeSetup (
423 IN EFI_HANDLE ImageHandle,
424 IN EFI_SYSTEM_TABLE *SystemTable
425 )
426 /*++
427
428 Routine Description:
429 Initialize Setup
430
431 Arguments:
432 (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
433
434 Returns:
435 EFI_SUCCESS - Setup loaded.
436 other - Setup Error
437
438 --*/
439 {
440 EFI_STATUS Status;
441 EFI_FORM_CONFIGURATION_DATA *FormData;
442 EFI_FORM_BROWSER_PROTOCOL *FormBrowser;
443 EFI_HANDLE Handle;
444 EFI_HII_PACKAGES *PackageList;
445
446 //
447 // There will be only one FormConfig in the system
448 // If there is another out there, someone is trying to install us
449 // again. Fail that scenario.
450 //
451 Status = gBS->LocateProtocol (
452 &gEfiFormBrowserProtocolGuid,
453 NULL,
454 (VOID **) &FormBrowser
455 );
456
457 gFirstIn = TRUE;
458
459 //
460 // If there was no error, assume there is an installation and fail to load
461 //
462 if (!EFI_ERROR (Status)) {
463 return EFI_DEVICE_ERROR;
464 }
465
466 FormData = AllocatePool (sizeof (EFI_FORM_CONFIGURATION_DATA));
467
468 if (FormData == NULL) {
469 return EFI_OUT_OF_RESOURCES;
470 }
471 //
472 // Fill in HII data
473 //
474 FormData->Signature = EFI_FORM_DATA_SIGNATURE;
475 FormData->FormConfig.SendForm = SendForm;
476 FormData->FormConfig.CreatePopUp = CreateDialog;
477
478 //
479 // There should only be one HII image
480 //
481 Status = gBS->LocateProtocol (
482 &gEfiHiiProtocolGuid,
483 NULL,
484 (VOID **) &FormData->Hii
485 );
486
487 ASSERT_EFI_ERROR (Status);
488
489 Hii = FormData->Hii;
490
491 PackageList = PreparePackages (1, &gEfiFormBrowserProtocolGuid, SetupBrowserStrings);
492
493 Status = Hii->NewPack (Hii, PackageList, &gHiiHandle);
494
495 FreePool (PackageList);
496
497 //
498 // Install protocol interface
499 //
500 Handle = NULL;
501 Status = gBS->InstallProtocolInterface (
502 &Handle,
503 &gEfiFormBrowserProtocolGuid,
504 EFI_NATIVE_INTERFACE,
505 &FormData->FormConfig
506 );
507
508 ASSERT_EFI_ERROR (Status);
509
510 BannerData = AllocateZeroPool (sizeof (BANNER_DATA));
511 ASSERT (BannerData != NULL);
512
513 Status = InstallPrint ();
514 return Status;
515 }
516
517 VOID
518 GetQuestionHeader (
519 IN EFI_TAG *Tag,
520 IN UINT8 *RawFormSet,
521 IN UINT16 Index,
522 IN EFI_FILE_FORM_TAGS *FileFormTags,
523 IN UINT16 CurrentVariable
524 )
525 /*++
526
527 Routine Description:
528 Initialize question tag's members.
529
530 Arguments:
531 Tag - Pointer of the current EFI_TAG structure.
532 RawFormSet - Pointer of the formset raw data.
533 Index - Offset of the current opcode in the Ifr raw data.
534 FileFormTags - Pointer of current EFI_FILE_FORM_TAGS structure.
535 CurrentVariable - Current variable number.
536
537 Returns:
538 None.
539 --*/
540 {
541 EFI_VARIABLE_DEFINITION *VariableDefinition;
542
543 Tag->NumberOfLines = 1;
544 Tag->VariableNumber = CurrentVariable;
545 CopyMem (&Tag->Id, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->QuestionId, sizeof (UINT16));
546 CopyMem (&Tag->StorageStart, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->QuestionId, sizeof (UINT16));
547 CopyMem (&Tag->StorageWidth, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Width, sizeof (UINT8));
548 CopyMem (&Tag->Text, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Prompt, sizeof (UINT16));
549 CopyMem (&Tag->Help, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Help, sizeof (UINT16));
550
551 VariableDefinition = FileFormTags->VariableDefinitions;
552
553 for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
554 //
555 // Have we found the correct variable for the request?
556 //
557 if (CurrentVariable == VariableDefinition->VariableId) {
558 if (VariableDefinition->VariableSize < (UINTN) (Tag->StorageStart + Tag->StorageWidth)) {
559 VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize + Tag->StorageWidth);
560 }
561
562 if (VariableDefinition->NvRamMap != NULL) {
563 //
564 // If it is an 8bit or 16bit width, then move it to Tag->Value, otherwise
565 // we will never be looking for the data in Tag->Value (e.g. strings, password, etc)
566 //
567 if (Tag->StorageWidth == (UINT16) 1) {
568 CopyMem (&Tag->Value, &VariableDefinition->NvRamMap[Tag->StorageStart], sizeof (UINT16));
569 }
570
571 if (Tag->StorageWidth == (UINT16) 2) {
572 Index = (UINT16)
573 (
574 VariableDefinition->NvRamMap[Tag->StorageStart] +
575 (VariableDefinition->NvRamMap[Tag->StorageStart + 1] * 0x100)
576 );
577 CopyMem (&Tag->Value, &Index, sizeof (UINT16));
578 }
579 } else {
580 Index = 0;
581 CopyMem (&Tag->Value, &Index, sizeof (UINT16));
582 }
583 break;
584 }
585 }
586 }
587
588 VOID
589 GetNumericHeader (
590 IN EFI_TAG *Tag,
591 IN UINT8 *RawFormSet,
592 IN UINT16 Index,
593 IN UINT16 NumberOfLines,
594 IN EFI_FILE_FORM_TAGS *FileFormTags,
595 IN UINT16 CurrentVariable
596 )
597 /*++
598
599 Routine Description:
600 Initialize numeric tag's members.
601
602 Arguments:
603 Tag - Pointer of the current EFI_TAG structure.
604 RawFormSet - Pointer of the formset raw data.
605 Index - Offset of the current opcode in the Ifr raw data.
606 NumberOfLines - Number of lines this opcode occupied.
607 FileFormTags - Pointer of current EFI_FILE_FORM_TAGS structure.
608 CurrentVariable - Current variable number.
609
610 Returns:
611 None.
612 --*/
613 {
614 EFI_VARIABLE_DEFINITION *VariableDefinition;
615
616 Tag->NumberOfLines = NumberOfLines;
617 Tag->VariableNumber = CurrentVariable;
618 CopyMem (&Tag->Id, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->QuestionId, sizeof (UINT16));
619 CopyMem (&Tag->StorageStart, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->QuestionId, sizeof (UINT16));
620 CopyMem (&Tag->StorageWidth, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Width, sizeof (UINT8));
621 CopyMem (&Tag->Text, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Prompt, sizeof (UINT16));
622 CopyMem (&Tag->Help, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Help, sizeof (UINT16));
623 CopyMem (&Tag->Minimum, &((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Minimum, sizeof (UINT16));
624 CopyMem (&Tag->Maximum, &((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Maximum, sizeof (UINT16));
625 CopyMem (&Tag->Step, &((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Step, sizeof (UINT16));
626 CopyMem (&Tag->Default, &((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Default, sizeof (UINT16));
627 Tag->ResetRequired = (BOOLEAN) (((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Flags & EFI_IFR_FLAG_RESET_REQUIRED);
628
629 VariableDefinition = FileFormTags->VariableDefinitions;
630
631 for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
632 //
633 // Have we found the correct variable for the request?
634 //
635 if (CurrentVariable == VariableDefinition->VariableId) {
636 if (VariableDefinition->VariableSize <= (UINTN) (Tag->StorageStart + Tag->StorageWidth)) {
637 if (Tag->StorageWidth == 0) {
638 VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize + 2);
639 } else {
640 VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize + Tag->StorageWidth);
641 }
642 }
643
644 if (VariableDefinition->NvRamMap != NULL) {
645 //
646 // If it is an 8bit or 16bit width, then move it to Tag->Value, otherwise
647 // we will never be looking for the data in Tag->Value (e.g. strings, password, etc)
648 //
649 if (Tag->StorageWidth == (UINT16) 1) {
650 CopyMem (&Tag->Value, &VariableDefinition->NvRamMap[Tag->StorageStart], sizeof (UINT16));
651 }
652
653 if (Tag->StorageWidth == (UINT16) 2) {
654 Index = (UINT16)
655 (
656 VariableDefinition->NvRamMap[Tag->StorageStart] +
657 (VariableDefinition->NvRamMap[Tag->StorageStart + 1] * 0x100)
658 );
659 CopyMem (&Tag->Value, &Index, sizeof (UINT16));
660 }
661 } else {
662 CopyMem (&Tag->Value, &Tag->Default, sizeof (UINT16));
663 }
664 break;
665 }
666 }
667 }
668
669 VOID
670 GetTagCount (
671 IN UINT8 *RawFormSet,
672 IN OUT UINT16 *NumberOfTags
673 )
674 {
675 UINT16 Index;
676
677 //
678 // Assume on entry we are pointing to an OpCode - reasonably this should
679 // be a FormOp since the purpose is to count the tags in a particular Form.
680 //
681 for (Index = 0; RawFormSet[Index] != EFI_IFR_END_FORM_OP;) {
682 //
683 // If we encounter the end of a form set, bail out
684 //
685 if (RawFormSet[Index] == EFI_IFR_END_FORM_SET_OP) {
686 break;
687 }
688 //
689 // We treat date/time internally as three op-codes
690 //
691 if (RawFormSet[Index] == EFI_IFR_DATE_OP || RawFormSet[Index] == EFI_IFR_TIME_OP) {
692 *NumberOfTags = (UINT16) (*NumberOfTags + 3);
693 } else {
694 //
695 // Assume that we could have no more tags than op-codes
696 //
697 (*NumberOfTags)++;
698 }
699
700 Index = (UINT16) (Index + RawFormSet[Index + 1]);
701 }
702 //
703 // Increase the tag count by one so it is inclusive of the end_form_op
704 //
705 (*NumberOfTags)++;
706 }
707
708 STATIC
709 VOID
710 AddNextInconsistentTag (
711 IN OUT EFI_INCONSISTENCY_DATA **InconsistentTagsPtr
712 )
713 /*++
714
715 Routine Description:
716 Initialize the next inconsistent tag data and add it to the inconsistent tag list.
717
718 Arguments:
719 InconsistentTagsPtr - Pointer of the inconsistent tag's pointer.
720
721 Returns:
722 None.
723
724 --*/
725 {
726 EFI_INCONSISTENCY_DATA *PreviousInconsistentTags;
727 EFI_INCONSISTENCY_DATA *InconsistentTags;
728
729 InconsistentTags = *InconsistentTagsPtr;
730 //
731 // We just hit the end of an inconsistent expression. Let's allocate the ->Next structure
732 //
733 InconsistentTags->Next = AllocatePool (sizeof (EFI_INCONSISTENCY_DATA));
734 ASSERT (InconsistentTags->Next != NULL);
735
736 //
737 // Preserve current Tag entry
738 //
739 PreviousInconsistentTags = InconsistentTags;
740
741 InconsistentTags = InconsistentTags->Next;
742
743 //
744 // This will zero on the entry including the ->Next so I don't have to do it
745 //
746 ZeroMem (InconsistentTags, sizeof (EFI_INCONSISTENCY_DATA));
747
748 //
749 // Point our Previous field to the previous entry
750 //
751 InconsistentTags->Previous = PreviousInconsistentTags;
752
753 *InconsistentTagsPtr = InconsistentTags;
754
755 return ;
756 }
757
758 STATIC
759 EFI_STATUS
760 InitializeTagStructures (
761 IN EFI_IFR_BINARY *BinaryData,
762 OUT EFI_FILE_FORM_TAGS *FileFormTags
763 )
764 {
765 EFI_STATUS Status;
766 UINT8 *RawFormSet;
767 UINT16 Index;
768 UINT16 QuestionIndex;
769 UINT16 NumberOfTags;
770 INT16 CurrTag;
771 UINT8 TagLength;
772 EFI_FORM_TAGS *FormTags;
773 EFI_FORM_TAGS *SavedFormTags;
774 EFI_INCONSISTENCY_DATA *InconsistentTags;
775 EFI_VARIABLE_DEFINITION *VariableDefinitions;
776 UINTN Count;
777 UINT16 Class;
778 UINT16 SubClass;
779 UINT16 TempValue;
780 UINT16 CurrentVariable;
781 UINT16 CurrentVariable2;
782
783 //
784 // Initialize some Index variable and Status
785 //
786 Count = 0;
787 Class = 0;
788 SubClass = 0;
789 CurrentVariable = 0;
790 CurrentVariable2 = 0;
791 QuestionIndex = 0;
792 NumberOfTags = 1;
793 Status = EFI_SUCCESS;
794 FormTags = &FileFormTags->FormTags;
795 FormTags->Next = NULL;
796 if (FileFormTags->InconsistentTags == NULL) {
797 InconsistentTags = NULL;
798 } else {
799 InconsistentTags = FileFormTags->InconsistentTags;
800 }
801
802 if (FileFormTags->VariableDefinitions == NULL) {
803 VariableDefinitions = NULL;
804 } else {
805 VariableDefinitions = FileFormTags->VariableDefinitions;
806 }
807 //
808 // RawFormSet now points to the beginning of the forms portion of
809 // the specific IFR Binary.
810 //
811 RawFormSet = (UINT8 *) BinaryData->FormBinary;
812
813 //
814 // Determine the number of tags for the first form
815 //
816 GetTagCount (&RawFormSet[0], &NumberOfTags);
817
818 SavedFormTags = FormTags;
819
820 if (FormTags->Tags != NULL) {
821 do {
822 //
823 // Advance FormTags to the last entry
824 //
825 for (; FormTags->Next != NULL; FormTags = FormTags->Next)
826 ;
827
828 //
829 // Walk through each of the tags and free the IntList allocation
830 //
831 for (Index = 0; Index < NumberOfTags; Index++) {
832 if (FormTags->Tags[Index].IntList != NULL) {
833 FreePool (FormTags->Tags[Index].IntList);
834 }
835 }
836
837 FreePool (FormTags->Tags);
838
839 ASSERT (FormTags->Next == NULL);
840
841 FormTags->Tags = NULL;
842
843 FormTags = SavedFormTags;
844
845 } while (FormTags->Next != NULL);
846 }
847
848 Index = 0;
849
850 //
851 // Test for an allocated buffer. If already allocated this is due to having called this routine
852 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
853 // the tag structure with current values from the NV
854 //
855 if (FormTags->Tags == NULL) {
856 //
857 // Allocate memory for our tags on the first form
858 //
859 FormTags->Tags = AllocateZeroPool (NumberOfTags * sizeof (EFI_TAG));
860 ASSERT (FormTags->Tags);
861 }
862 //
863 // Test for an allocated buffer. If already allocated this is due to having called this routine
864 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
865 // the tag structure with current values from the NV
866 //
867 if (InconsistentTags == NULL) {
868 //
869 // We just hit the end of an inconsistent expression. Let's allocate the ->Next structure
870 //
871 InconsistentTags = AllocateZeroPool (sizeof (EFI_INCONSISTENCY_DATA));
872 ASSERT (InconsistentTags != NULL);
873
874 FileFormTags->InconsistentTags = InconsistentTags;
875 }
876
877 ZeroMem (FormTags->Tags, NumberOfTags * sizeof (EFI_TAG));
878
879 for (CurrTag = 0; RawFormSet[Index] != EFI_IFR_END_FORM_SET_OP; CurrTag++) {
880 //
881 // Operand = IFR OpCode
882 //
883 FormTags->Tags[CurrTag].Operand = RawFormSet[Index];
884
885 //
886 // Assume for now 0 lines occupied by this OpCode
887 //
888 FormTags->Tags[CurrTag].NumberOfLines = 0;
889
890 FormTags->Tags[CurrTag].Class = Class;
891 FormTags->Tags[CurrTag].SubClass = SubClass;
892
893 //
894 // Determine the length of the Tag so we can later skip to the next tag in the form
895 //
896 TagLength = RawFormSet[Index + 1];
897 //
898 // get the length
899 //
900 // Operate on the Found OpCode
901 //
902 switch (RawFormSet[Index]) {
903
904 case EFI_IFR_FORM_OP:
905 //
906 // If there was no variable op-code defined, create a dummy entry for one
907 //
908 if (FileFormTags->VariableDefinitions == NULL) {
909 FileFormTags->VariableDefinitions = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION));
910 ASSERT (FileFormTags->VariableDefinitions != NULL);
911 IfrToFormTag (
912 RawFormSet[Index],
913 &FormTags->Tags[CurrTag],
914 (VOID *) &RawFormSet[Index],
915 FileFormTags->VariableDefinitions
916 );
917 } else {
918 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
919 }
920 break;
921
922 case EFI_IFR_SUBTITLE_OP:
923 case EFI_IFR_TEXT_OP:
924 case EFI_IFR_REF_OP:
925 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
926 break;
927
928 case EFI_IFR_VARSTORE_OP:
929 if (FileFormTags->VariableDefinitions == NULL) {
930 VariableDefinitions = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION));
931 ASSERT (VariableDefinitions != NULL);
932 FileFormTags->VariableDefinitions = VariableDefinitions;
933 }
934
935 IfrToFormTag (
936 RawFormSet[Index],
937 &FormTags->Tags[CurrTag],
938 (VOID *) &RawFormSet[Index],
939 FileFormTags->VariableDefinitions
940 );
941 break;
942
943 case EFI_IFR_VARSTORE_SELECT_OP:
944 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
945 CopyMem (&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT *) &RawFormSet[Index])->VarId, sizeof (UINT16));
946 CurrentVariable2 = CurrentVariable;
947 break;
948
949 case EFI_IFR_VARSTORE_SELECT_PAIR_OP:
950 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
951 CopyMem(&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT_PAIR *)&RawFormSet[Index])->VarId, sizeof (UINT16));
952 CopyMem (
953 &CurrentVariable2,
954 &((EFI_IFR_VARSTORE_SELECT_PAIR *) &RawFormSet[Index])->SecondaryVarId,
955 sizeof (UINT16)
956 );
957 break;
958
959 case EFI_IFR_END_FORM_OP:
960 //
961 // Test for an allocated buffer. If already allocated this is due to having called this routine
962 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
963 // the tag structure with current values from the NV
964 //
965 if (FormTags->Next == NULL) {
966 //
967 // We just hit the end of a form. Let's allocate the ->Next structure
968 //
969 FormTags->Next = AllocatePool (sizeof (EFI_FORM_TAGS));
970 ASSERT (FormTags->Next);
971 }
972
973 FormTags = FormTags->Next;
974 ZeroMem (FormTags, sizeof (EFI_FORM_TAGS));
975
976 //
977 // Reset the tag count to one
978 //
979 NumberOfTags = 1;
980
981 //
982 // Reset the CurrTag value (it will be incremented, after this case statement
983 // so set to a negative one so that we get the desired effect.) Fish can beat me later.
984 //
985 CurrTag = -1;
986
987 //
988 // Determine the number of tags after this form. If this is the last
989 // form, then we will count the endformset and preserve that information
990 // in the tag structure.
991 //
992 GetTagCount (&RawFormSet[Index + TagLength], &NumberOfTags);
993
994 //
995 // Allocate memory for our tags
996 //
997 FormTags->Tags = AllocateZeroPool (NumberOfTags * sizeof (EFI_TAG));
998 ASSERT (FormTags->Tags);
999 break;
1000
1001 //
1002 // Two types of tags constitute the One Of question: a one-of header and
1003 // several one-of options.
1004 //
1005 case EFI_IFR_ONE_OF_OP:
1006 case EFI_IFR_ORDERED_LIST_OP:
1007 GetQuestionHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, FileFormTags, CurrentVariable);
1008
1009 //
1010 // Store away the CurrTag since what follows will be the answer that we
1011 // need to place into the appropriate location in the tag array
1012 //
1013 //
1014 // record for setting default later
1015 //
1016 QuestionIndex = (UINT16) CurrTag;
1017 break;
1018
1019 case EFI_IFR_ONE_OF_OPTION_OP:
1020 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
1021 FormTags->Tags[QuestionIndex].Flags = ((EFI_IFR_ONE_OF_OPTION *) &RawFormSet[Index])->Flags;
1022 CopyMem (
1023 &FormTags->Tags[QuestionIndex].Key,
1024 &((EFI_IFR_ONE_OF_OPTION *) &RawFormSet[Index])->Key,
1025 sizeof (UINT16)
1026 );
1027 FormTags->Tags[QuestionIndex].ResetRequired = (BOOLEAN) (FormTags->Tags[QuestionIndex].Flags & EFI_IFR_FLAG_RESET_REQUIRED);
1028 break;
1029
1030 case EFI_IFR_CHECKBOX_OP:
1031 GetQuestionHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, FileFormTags, CurrentVariable);
1032 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
1033 break;
1034
1035 case EFI_IFR_NUMERIC_OP:
1036 GetNumericHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, (UINT16) 1, FileFormTags, CurrentVariable);
1037 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
1038 break;
1039
1040 case EFI_IFR_DATE_OP:
1041 //
1042 // Date elements come in as a Year, Month, Day. We need to process them as a country-based
1043 // Order. It is much easier to do it here than anywhere else.
1044 //
1045 // For US standards - we want Month/Day/Year, thus we advance "Index" +1, +2, +0 while CurrTag is +0, +1, +2
1046 //
1047 GetNumericHeader (
1048 &FormTags->Tags[CurrTag],
1049 RawFormSet,
1050 (UINT16) (Index + TagLength),
1051 (UINT16) 0,
1052 FileFormTags,
1053 CurrentVariable
1054 );
1055
1056 //
1057 // The current language selected + the Date operand
1058 //
1059 FormTags->Tags[CurrTag + 1].Operand = RawFormSet[Index];
1060 GetNumericHeader (
1061 &FormTags->Tags[CurrTag + 1],
1062 RawFormSet,
1063 (UINT16) (Index + TagLength + RawFormSet[Index + TagLength + 1]),
1064 (UINT16) 0,
1065 FileFormTags,
1066 CurrentVariable
1067 );
1068
1069 //
1070 // The current language selected + the Date operand
1071 //
1072 FormTags->Tags[CurrTag + 2].Operand = RawFormSet[Index];
1073 GetNumericHeader (&FormTags->Tags[CurrTag + 2], RawFormSet, Index, (UINT16) 1, FileFormTags, CurrentVariable);
1074
1075 CurrTag = (INT16) (CurrTag + 2);
1076
1077 Index = (UINT16) (Index + TagLength);
1078 //
1079 // get the length
1080 //
1081 TagLength = RawFormSet[Index + 1];
1082 Index = (UINT16) (Index + TagLength);
1083 //
1084 // get the length
1085 //
1086 TagLength = RawFormSet[Index + 1];
1087 break;
1088
1089 case EFI_IFR_TIME_OP:
1090 GetNumericHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, (UINT16) 0, FileFormTags, CurrentVariable);
1091
1092 if (Count == 2) {
1093 //
1094 // Override the GetQuestionHeader information - date/time are treated very differently
1095 //
1096 FormTags->Tags[CurrTag].NumberOfLines = 1;
1097 Count = 0;
1098 } else {
1099 //
1100 // The premise is that every date/time op-code have 3 elements, the first 2 have 0 lines
1101 // associated with them, and the third has 1 line to allow to space beyond the choice.
1102 //
1103 Count++;
1104 }
1105 break;
1106
1107 case EFI_IFR_PASSWORD_OP:
1108 case EFI_IFR_STRING_OP:
1109 GetQuestionHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, FileFormTags, CurrentVariable);
1110 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
1111 break;
1112
1113 case EFI_IFR_SUPPRESS_IF_OP:
1114 case EFI_IFR_GRAYOUT_IF_OP:
1115 InconsistentTags->Operand = ((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Header.OpCode;
1116 gConsistencyId++;
1117
1118 //
1119 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1120 // Unfortunately 0 is a valid offset value for a QuestionId
1121 //
1122 InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE;
1123 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
1124
1125 //
1126 // Test for an allocated buffer. If already allocated this is due to having called this routine
1127 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1128 // the tag structure with current values from the NV
1129 //
1130 if (InconsistentTags->Next == NULL) {
1131 AddNextInconsistentTag (&InconsistentTags);
1132 break;
1133 }
1134
1135 InconsistentTags = InconsistentTags->Next;
1136 break;
1137
1138 case EFI_IFR_FORM_SET_OP:
1139 CopyMem (
1140 &FormTags->Tags[CurrTag].GuidValue,
1141 &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->Guid,
1142 sizeof (EFI_GUID)
1143 );
1144 CopyMem (
1145 &FormTags->Tags[CurrTag].CallbackHandle,
1146 &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->CallbackHandle,
1147 sizeof (EFI_PHYSICAL_ADDRESS)
1148 );
1149 CopyMem (&FormTags->Tags[CurrTag].Class, &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->Class, sizeof (UINT8));
1150 CopyMem (
1151 &FormTags->Tags[CurrTag].SubClass,
1152 &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->SubClass,
1153 sizeof (UINT8)
1154 );
1155 CopyMem (
1156 &FormTags->Tags[CurrTag].NvDataSize,
1157 &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->NvDataSize,
1158 sizeof (UINT16)
1159 );
1160 Class = ((EFI_IFR_FORM_SET *) &RawFormSet[Index])->Class;
1161 SubClass = ((EFI_IFR_FORM_SET *) &RawFormSet[Index])->SubClass;
1162 //
1163 // If the formset has a size value, that means someone must be using this, so create a variable
1164 // We also shall reserve the formid of 0 for this specific purpose.
1165 //
1166 if ((FileFormTags->VariableDefinitions == NULL) && (FormTags->Tags[CurrTag].NvDataSize > 0)) {
1167 FileFormTags->VariableDefinitions = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION));
1168 ASSERT (FileFormTags->VariableDefinitions != NULL);
1169 IfrToFormTag (
1170 RawFormSet[Index],
1171 &FormTags->Tags[CurrTag],
1172 (VOID *) &RawFormSet[Index],
1173 FileFormTags->VariableDefinitions
1174 );
1175 } else {
1176 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
1177 }
1178 break;
1179
1180 case EFI_IFR_BANNER_OP:
1181 if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
1182 TempValue = 0;
1183 CopyMem (&TempValue, &((EFI_IFR_BANNER *) &RawFormSet[Index])->Alignment, sizeof (UINT8));
1184 //
1185 // If this is the special timeout value, we will dynamically figure out where to put it
1186 // Also the least significant byte refers to the TimeOut desired.
1187 //
1188 if (TempValue == EFI_IFR_BANNER_TIMEOUT) {
1189 CopyMem (&FrontPageTimeOutTitle, &((EFI_IFR_BANNER *) &RawFormSet[Index])->Title, sizeof (UINT16));
1190 if (FrontPageTimeOutValue != (INT16) -1) {
1191 CopyMem (&FrontPageTimeOutValue, &((EFI_IFR_BANNER *) &RawFormSet[Index])->LineNumber, sizeof (UINT16));
1192 }
1193 break;
1194 }
1195
1196 CopyMem (
1197 &BannerData->Banner[((EFI_IFR_BANNER *) &RawFormSet[Index])->LineNumber][
1198 ((EFI_IFR_BANNER *) &RawFormSet[Index])->Alignment],
1199 &((EFI_IFR_BANNER *) &RawFormSet[Index])->Title,
1200 sizeof (STRING_REF)
1201 );
1202 }
1203 break;
1204
1205 case EFI_IFR_INCONSISTENT_IF_OP:
1206 CopyMem (
1207 &FormTags->Tags[CurrTag].Text,
1208 &((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Popup,
1209 sizeof (UINT16)
1210 );
1211 gConsistencyId++;
1212
1213 InconsistentTags->Operand = ((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Header.OpCode;
1214 CopyMem (&InconsistentTags->Popup, &((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Popup, sizeof (UINT16));
1215
1216 //
1217 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1218 // Unfortunately 0 is a valid offset value for a QuestionId
1219 //
1220 InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE;
1221 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
1222
1223 InconsistentTags->VariableNumber = CurrentVariable;
1224
1225 //
1226 // Test for an allocated buffer. If already allocated this is due to having called this routine
1227 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1228 // the tag structure with current values from the NV
1229 //
1230 if (InconsistentTags->Next == NULL) {
1231 AddNextInconsistentTag (&InconsistentTags);
1232 break;
1233 }
1234
1235 InconsistentTags = InconsistentTags->Next;
1236 break;
1237
1238 case EFI_IFR_EQ_ID_VAL_OP:
1239 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
1240
1241 InconsistentTags->Operand = ((EFI_IFR_EQ_ID_VAL *) &RawFormSet[Index])->Header.OpCode;
1242 CopyMem (&InconsistentTags->Value, &((EFI_IFR_EQ_ID_VAL *) &RawFormSet[Index])->Value, sizeof (UINT16));
1243 CopyMem (
1244 &InconsistentTags->QuestionId1,
1245 &((EFI_IFR_EQ_ID_VAL *) &RawFormSet[Index])->QuestionId,
1246 sizeof (UINT16)
1247 );
1248
1249 //
1250 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1251 // Unfortunately 0 is a valid offset value for a QuestionId
1252 //
1253 InconsistentTags->Width = FormTags->Tags[CurrTag].StorageWidth;
1254 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
1255 InconsistentTags->ConsistencyId = gConsistencyId;
1256 FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;
1257
1258 InconsistentTags->VariableNumber = CurrentVariable;
1259
1260 //
1261 // Test for an allocated buffer. If already allocated this is due to having called this routine
1262 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1263 // the tag structure with current values from the NV
1264 //
1265 if (InconsistentTags->Next == NULL) {
1266 AddNextInconsistentTag (&InconsistentTags);
1267 break;
1268 }
1269
1270 InconsistentTags = InconsistentTags->Next;
1271 break;
1272
1273 case EFI_IFR_EQ_VAR_VAL_OP:
1274 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
1275
1276 InconsistentTags->Operand = ((EFI_IFR_EQ_VAR_VAL *) &RawFormSet[Index])->Header.OpCode;
1277 CopyMem (&InconsistentTags->Value, &((EFI_IFR_EQ_VAR_VAL *) &RawFormSet[Index])->Value, sizeof (UINT16));
1278 CopyMem (
1279 &InconsistentTags->QuestionId1,
1280 &((EFI_IFR_EQ_VAR_VAL *) &RawFormSet[Index])->VariableId,
1281 sizeof (UINT16)
1282 );
1283
1284 //
1285 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1286 // Unfortunately 0 is a valid offset value for a QuestionId
1287 //
1288 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
1289 InconsistentTags->ConsistencyId = gConsistencyId;
1290 FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;
1291
1292 InconsistentTags->VariableNumber = CurrentVariable;
1293
1294 //
1295 // Test for an allocated buffer. If already allocated this is due to having called this routine
1296 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1297 // the tag structure with current values from the NV
1298 //
1299 if (InconsistentTags->Next == NULL) {
1300 AddNextInconsistentTag (&InconsistentTags);
1301 break;
1302 }
1303
1304 InconsistentTags = InconsistentTags->Next;
1305 break;
1306
1307 case EFI_IFR_EQ_ID_ID_OP:
1308 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
1309
1310 InconsistentTags->Operand = ((EFI_IFR_EQ_ID_ID *) &RawFormSet[Index])->Header.OpCode;
1311 CopyMem (
1312 &InconsistentTags->QuestionId1,
1313 &((EFI_IFR_EQ_ID_ID *) &RawFormSet[Index])->QuestionId1,
1314 sizeof (UINT16)
1315 );
1316 CopyMem (
1317 &InconsistentTags->QuestionId2,
1318 &((EFI_IFR_EQ_ID_ID *) &RawFormSet[Index])->QuestionId2,
1319 sizeof (UINT16)
1320 );
1321
1322 InconsistentTags->Width = FormTags->Tags[CurrTag].StorageWidth;
1323 InconsistentTags->ConsistencyId = gConsistencyId;
1324 FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;
1325
1326 InconsistentTags->VariableNumber = CurrentVariable;
1327 InconsistentTags->VariableNumber2 = CurrentVariable2;
1328
1329 //
1330 // Test for an allocated buffer. If already allocated this is due to having called this routine
1331 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1332 // the tag structure with current values from the NV
1333 //
1334 if (InconsistentTags->Next == NULL) {
1335 AddNextInconsistentTag (&InconsistentTags);
1336 break;
1337 }
1338
1339 InconsistentTags = InconsistentTags->Next;
1340 break;
1341
1342 case EFI_IFR_AND_OP:
1343 case EFI_IFR_OR_OP:
1344 case EFI_IFR_NOT_OP:
1345 case EFI_IFR_GT_OP:
1346 case EFI_IFR_GE_OP:
1347 case EFI_IFR_TRUE_OP:
1348 case EFI_IFR_FALSE_OP:
1349 InconsistentTags->Operand = ((EFI_IFR_NOT *) &RawFormSet[Index])->Header.OpCode;
1350
1351 //
1352 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1353 // Unfortunately 0 is a valid offset value for a QuestionId
1354 //
1355
1356 //
1357 // Reserve INVALID_OFFSET_VALUE - 1 for TRUE or FALSE because they are inconsistency tags also, but
1358 // have no coresponding id. The examination of id is needed by evaluating boolean expression.
1359 //
1360 if (RawFormSet[Index] == EFI_IFR_TRUE_OP ||
1361 RawFormSet[Index] == EFI_IFR_FALSE_OP) {
1362 InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE - 1;
1363 } else {
1364 InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE;
1365 }
1366 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
1367 InconsistentTags->ConsistencyId = gConsistencyId;
1368 FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;
1369
1370 //
1371 // Test for an allocated buffer. If already allocated this is due to having called this routine
1372 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1373 // the tag structure with current values from the NV
1374 //
1375 if (InconsistentTags->Next == NULL) {
1376 AddNextInconsistentTag (&InconsistentTags);
1377 break;
1378 }
1379
1380 InconsistentTags = InconsistentTags->Next;
1381 break;
1382
1383 case EFI_IFR_EQ_ID_LIST_OP:
1384 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
1385
1386 InconsistentTags->Operand = ((EFI_IFR_EQ_ID_LIST *) &RawFormSet[Index])->Header.OpCode;
1387 CopyMem (
1388 &InconsistentTags->QuestionId1,
1389 &((EFI_IFR_EQ_ID_LIST *) &RawFormSet[Index])->QuestionId,
1390 sizeof (UINT16)
1391 );
1392 CopyMem (
1393 &InconsistentTags->ListLength,
1394 &((EFI_IFR_EQ_ID_LIST *) &RawFormSet[Index])->ListLength,
1395 sizeof (UINT16)
1396 );
1397 InconsistentTags->ValueList = FormTags->Tags[CurrTag].IntList;
1398
1399 //
1400 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1401 // Unfortunately 0 is a valid offset value for a QuestionId
1402 //
1403 InconsistentTags->Width = FormTags->Tags[CurrTag].StorageWidth;
1404 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
1405 InconsistentTags->ConsistencyId = gConsistencyId;
1406 FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;
1407
1408 //
1409 // Test for an allocated buffer. If already allocated this is due to having called this routine
1410 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1411 // the tag structure with current values from the NV
1412 //
1413 if (InconsistentTags->Next == NULL) {
1414 AddNextInconsistentTag (&InconsistentTags);
1415 break;
1416 }
1417
1418 InconsistentTags = InconsistentTags->Next;
1419 break;
1420
1421 case EFI_IFR_END_IF_OP:
1422 InconsistentTags->Operand = ((EFI_IFR_END_EXPR *) &RawFormSet[Index])->Header.OpCode;
1423
1424 //
1425 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1426 // Unfortunately 0 is a valid offset value for a QuestionId
1427 //
1428 InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE;
1429 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
1430
1431 //
1432 // Test for an allocated buffer. If already allocated this is due to having called this routine
1433 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1434 // the tag structure with current values from the NV
1435 //
1436 if (InconsistentTags->Next == NULL) {
1437 AddNextInconsistentTag (&InconsistentTags);
1438 break;
1439 }
1440
1441 InconsistentTags = InconsistentTags->Next;
1442 break;
1443
1444 case EFI_IFR_END_ONE_OF_OP:
1445 break;
1446
1447 default:
1448 break;
1449 }
1450 //
1451 // End of switch
1452 //
1453 // Per spec., we ignore ops that we don't know how to deal with. Skip to next tag
1454 //
1455 Index = (UINT16) (Index + TagLength);
1456 }
1457 //
1458 // End of Index
1459 //
1460 // When we eventually exit, make sure we mark the last tag with an op-code
1461 //
1462 FormTags->Tags[CurrTag].Operand = RawFormSet[Index];
1463
1464 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
1465
1466 //
1467 // Place this as an end of the database marker
1468 //
1469 InconsistentTags->Operand = 0xFF;
1470
1471 //
1472 // This is the Head of the linked list of pages. Each page is an array of tags
1473 //
1474 FormTags = &FileFormTags->FormTags;
1475 InconsistentTags = FileFormTags->InconsistentTags;
1476
1477 for (; InconsistentTags->Operand != 0xFF;) {
1478 if (InconsistentTags->QuestionId1 != INVALID_OFFSET_VALUE) {
1479 //
1480 // Search the tags for the tag which corresponds to this ID
1481 //
1482 for (CurrTag = 0; FormTags->Tags[0].Operand != EFI_IFR_END_FORM_SET_OP; CurrTag++) {
1483 //
1484 // If we hit the end of a form, go to the next set of Tags.
1485 // Remember - EndFormSet op-codes sit on their own page after an end form.
1486 //
1487 if (FormTags->Tags[CurrTag].Operand == EFI_IFR_END_FORM_OP) {
1488 //
1489 // Reset the CurrTag value (it will be incremented, after this case statement
1490 // so set to a negative one so that we get the desired effect.) Fish can beat me later.
1491 //
1492 CurrTag = -1;
1493 FormTags = FormTags->Next;
1494 continue;
1495 }
1496
1497 if (FormTags->Tags[CurrTag].Id == InconsistentTags->QuestionId1) {
1498 FormTags->Tags[CurrTag].Consistency++;
1499 }
1500 }
1501 }
1502
1503 FormTags = &FileFormTags->FormTags;
1504
1505 if (InconsistentTags->QuestionId2 != INVALID_OFFSET_VALUE) {
1506 //
1507 // Search the tags for the tag which corresponds to this ID
1508 //
1509 for (CurrTag = 0; FormTags->Tags[CurrTag].Operand != EFI_IFR_END_FORM_SET_OP; CurrTag++) {
1510 //
1511 // If we hit the end of a form, go to the next set of Tags.
1512 // Remember - EndFormSet op-codes sit on their own page after an end form.
1513 //
1514 if (FormTags->Tags[CurrTag].Operand == EFI_IFR_END_FORM_OP) {
1515 //
1516 // Reset the CurrTag value (it will be incremented, after this case statement
1517 // so set to a negative one so that we get the desired effect.) Fish can beat me later.
1518 //
1519 CurrTag = -1;
1520 FormTags = FormTags->Next;
1521 continue;
1522 }
1523
1524 if (FormTags->Tags[CurrTag].Id == InconsistentTags->QuestionId2) {
1525 FormTags->Tags[CurrTag].Consistency++;
1526 }
1527 }
1528 }
1529
1530 InconsistentTags = InconsistentTags->Next;
1531 }
1532
1533 return Status;
1534 }
1535
1536 VOID
1537 InitPage (
1538 VOID
1539 )
1540 {
1541 CHAR16 *HomePageString;
1542 CHAR16 *HomeEscapeString;
1543
1544 //
1545 // Displays the Header and Footer borders
1546 //
1547 DisplayPageFrame ();
1548
1549 HomePageString = GetToken (STRING_TOKEN (HOME_PAGE_TITLE), gHiiHandle);
1550 HomeEscapeString = GetToken (STRING_TOKEN (HOME_ESCAPE_STRING), gHiiHandle);
1551
1552 gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);
1553 //
1554 // PrintStringAt ((gScreenDimensions.RightColumn - GetStringWidth(HomePageString)/2)/2, 1, HomePageString);
1555 //
1556 PrintStringAt (
1557 (gScreenDimensions.RightColumn + gScreenDimensions.LeftColumn - GetStringWidth (HomePageString) / 2) / 2,
1558 1,
1559 HomePageString
1560 );
1561 PrintAt (
1562 gScreenDimensions.LeftColumn + 2,
1563 gScreenDimensions.BottomRow - 3,
1564 (CHAR16 *) L"%c%c%s",
1565 ARROW_UP,
1566 ARROW_DOWN,
1567 gMoveHighlight
1568 );
1569 PrintAt (
1570 gScreenDimensions.RightColumn - (GetStringWidth (HomeEscapeString) / 2) - 2,
1571 gScreenDimensions.BottomRow - 3,
1572 (CHAR16 *) L" %s",
1573 HomeEscapeString
1574 );
1575 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
1576 FreePool (HomeEscapeString);
1577 FreePool (HomePageString);
1578
1579 return ;
1580 }
1581
1582 CHAR16 *
1583 GetToken (
1584 IN STRING_REF Token,
1585 IN EFI_HII_HANDLE HiiHandle
1586 )
1587 /*++
1588
1589 Routine Description:
1590
1591 Get the string based on the TokenID and HII Handle.
1592
1593 Arguments:
1594
1595 Token - The Token ID.
1596 HiiHandle - Handle of Ifr to be fetched.
1597
1598 Returns:
1599
1600 The output string.
1601
1602 --*/
1603 {
1604 CHAR16 *Buffer;
1605 UINTN BufferLength;
1606 EFI_STATUS Status;
1607
1608 //
1609 // Set default string size assumption at no more than 256 bytes
1610 //
1611 BufferLength = 0x100;
1612
1613 Buffer = AllocateZeroPool (BufferLength);
1614 ASSERT (Buffer != NULL);
1615
1616 Status = Hii->GetString (Hii, HiiHandle, Token, TRUE, NULL, &BufferLength, Buffer);
1617
1618 if (EFI_ERROR (Status)) {
1619 if (Status == EFI_BUFFER_TOO_SMALL) {
1620 //
1621 // Free the old pool
1622 //
1623 FreePool (Buffer);
1624
1625 //
1626 // Allocate new pool with correct value
1627 //
1628 Buffer = AllocatePool (BufferLength);
1629 ASSERT (Buffer != NULL);
1630
1631 Status = Hii->GetString (Hii, HiiHandle, Token, TRUE, NULL, &BufferLength, Buffer);
1632
1633 if (!EFI_ERROR (Status)) {
1634 return Buffer;
1635 }
1636 }
1637
1638 ASSERT_EFI_ERROR (Status);
1639 }
1640
1641 return Buffer;
1642 }
1643
1644 STATIC
1645 EFI_STATUS
1646 PopulateHomePage (
1647 IN UINTN NumberOfIfrImages,
1648 IN EFI_FILE_FORM_TAGS *FileFormTagsHead
1649 )
1650 {
1651 EFI_STATUS Status;
1652 UINTN Index;
1653 EFI_IFR_BINARY *IfrBinary;
1654 CHAR16 *StringPtr;
1655 EFI_FILE_FORM_TAGS *FileFormTags;
1656 EFI_FORM_TAGS LocalTags;
1657
1658 FileFormTags = FileFormTagsHead;
1659
1660 UiInitMenu ();
1661
1662 Status = EFI_SUCCESS;
1663
1664 //
1665 // If there are no images
1666 //
1667 if (NumberOfIfrImages == 0) {
1668 Status = EFI_NO_MEDIA;
1669 return Status;
1670 }
1671 //
1672 // IfrBinary points to the beginning of the Binary data linked-list
1673 //
1674 IfrBinary = gBinaryDataHead;
1675
1676 //
1677 // Print the entries which were in the default language.
1678 //
1679 for (Index = 0; Index < NumberOfIfrImages; Index++) {
1680 LocalTags = FileFormTags->FormTags;
1681
1682 //
1683 // Populate the Menu
1684 //
1685 StringPtr = GetToken (IfrBinary->TitleToken, IfrBinary->Handle);
1686
1687 //
1688 // If the default language doesn't exist, don't add a menu option yet
1689 //
1690 if (StringPtr[0] != CHAR_NULL) {
1691 //
1692 // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do
1693 // it in UiFreeMenu.
1694 //
1695 UiAddMenuOption (StringPtr, IfrBinary->Handle, LocalTags.Tags, IfrBinary->FormBinary, Index);
1696 }
1697 //
1698 // Advance to the next HII handle
1699 //
1700 IfrBinary = IfrBinary->Next;
1701 FileFormTags = FileFormTags->NextFile;
1702 }
1703
1704 return Status;
1705 }
1706
1707 STATIC
1708 UI_MENU_OPTION *
1709 DisplayHomePage (
1710 IN UINTN NumberOfIfrImages,
1711 IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
1712 IN UINT8 *CallbackData
1713 )
1714 {
1715 EFI_STATUS Status;
1716 UI_MENU_OPTION *Selection;
1717
1718 //
1719 // This prints the basic home page template which the user sees
1720 //
1721 InitPage ();
1722
1723 Status = PopulateHomePage (NumberOfIfrImages, FileFormTagsHead);
1724
1725 if (EFI_ERROR (Status)) {
1726 Selection = NULL;
1727 return Selection;
1728 }
1729
1730 Selection = UiDisplayMenu (FALSE, FileFormTagsHead, (EFI_IFR_DATA_ARRAY *) CallbackData);
1731
1732 return Selection;
1733 }
1734
1735 STATIC
1736 EFI_STATUS
1737 InitializeBinaryStructures (
1738 IN EFI_HII_HANDLE *Handle,
1739 IN BOOLEAN UseDatabase,
1740 IN EFI_IFR_PACKET *Packet,
1741 IN UINT8 *NvMapOverride,
1742 IN UINTN NumberOfIfrImages,
1743 OUT EFI_FILE_FORM_TAGS **FileFormTagsHead
1744 )
1745 {
1746 UINTN HandleIndex;
1747 EFI_STATUS Status;
1748 EFI_IFR_BINARY *BinaryData;
1749 EFI_FILE_FORM_TAGS *FileFormTags;
1750 UINTN SizeOfNvStore;
1751 EFI_FORM_CALLBACK_PROTOCOL *FormCallback;
1752 EFI_VARIABLE_DEFINITION *VariableDefinition;
1753 EFI_VARIABLE_DEFINITION *OverrideDefinition;
1754 VOID *NvMap;
1755 UINTN NvMapSize;
1756 EFI_HII_VARIABLE_PACK_LIST *NvMapListHead;
1757 EFI_HII_VARIABLE_PACK_LIST *NvMapListNode;
1758
1759 //
1760 // Initialize some variables to avoid warnings
1761 //
1762 BinaryData = NULL;
1763 *FileFormTagsHead = NULL;
1764 FileFormTags = NULL;
1765 gBinaryDataHead = NULL;
1766 Status = EFI_SUCCESS;
1767 FormCallback = NULL;
1768 NvMap = NULL;
1769 NvMapSize = 0;
1770
1771 if (NumberOfIfrImages > 1) {
1772 NvMapOverride = NULL;
1773 }
1774
1775 for (HandleIndex = 0; HandleIndex < NumberOfIfrImages; HandleIndex += 1) {
1776 //
1777 // If the buffers are uninitialized, allocate them, otherwise work on the ->Next members
1778 //
1779 if ((BinaryData == NULL) || (FileFormTags == NULL)) {
1780 //
1781 // Allocate memory for our Binary Data
1782 //
1783 BinaryData = AllocateZeroPool (sizeof (EFI_IFR_BINARY));
1784 ASSERT (BinaryData);
1785
1786 //
1787 // Preserve the Head of what will be a linked-list.
1788 //
1789 gBinaryDataHead = BinaryData;
1790 gBinaryDataHead->Next = NULL;
1791
1792 if (UseDatabase) {
1793 Status = GetIfrBinaryData (Hii, Handle[HandleIndex], NULL, BinaryData);
1794 } else {
1795 Status = GetIfrBinaryData (Hii, Handle[HandleIndex], Packet, BinaryData);
1796 }
1797 //
1798 // Allocate memory for our File Form Tags
1799 //
1800 FileFormTags = AllocateZeroPool (sizeof (EFI_FILE_FORM_TAGS));
1801 ASSERT (FileFormTags);
1802
1803 //
1804 // Preserve the Head of what will be a linked-list.
1805 //
1806 *FileFormTagsHead = FileFormTags;
1807 (*FileFormTagsHead)->NextFile = NULL;
1808
1809 } else {
1810 //
1811 // Allocate memory for our Binary Data linked-list
1812 // Each handle represents a Binary and we will store that data away.
1813 //
1814 BinaryData->Next = AllocateZeroPool (sizeof (EFI_IFR_BINARY));
1815 ASSERT (BinaryData->Next);
1816
1817 BinaryData = BinaryData->Next;
1818 BinaryData->Next = NULL;
1819
1820 if (UseDatabase) {
1821 Status = GetIfrBinaryData (Hii, Handle[HandleIndex], NULL, BinaryData);
1822 } else {
1823 Status = GetIfrBinaryData (Hii, Handle[HandleIndex], Packet, BinaryData);
1824 }
1825
1826 if (EFI_ERROR (Status)) {
1827 return EFI_DEVICE_ERROR;
1828 }
1829 //
1830 // Allocate memory for our FileFormTags linked-list
1831 // Each allocation reserves handle represents a Binary and we will store that data away.
1832 //
1833 FileFormTags->NextFile = AllocateZeroPool (sizeof (EFI_FILE_FORM_TAGS));
1834 ASSERT (FileFormTags->NextFile);
1835
1836 FileFormTags = FileFormTags->NextFile;
1837 }
1838 //
1839 // endif
1840 //
1841 // Tag Structure Initialization
1842 //
1843 Status = InitializeTagStructures (BinaryData, FileFormTags);
1844
1845 VariableDefinition = FileFormTags->VariableDefinitions;
1846
1847 //
1848 // Allocate memory for our NVRAM Maps for all of our variables
1849 //
1850 for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
1851 //
1852 // Pad the fake variable size accordingly - this value should reflect the size of information that is not accounted by
1853 // the mainstream NVRAM variable such as DATE/TIME information that the browser needs to track but is saved to an RTC
1854 //
1855 VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableSize + VariableDefinition->VariableFakeSize);
1856
1857 //
1858 // In the case where a file has no "real" NV data, we should pad the buffer accordingly
1859 //
1860 if (VariableDefinition->VariableSize == 0) {
1861 if (VariableDefinition->VariableFakeSize != 0) {
1862 VariableDefinition->NvRamMap = AllocateZeroPool (VariableDefinition->VariableFakeSize);
1863 ASSERT (VariableDefinition->NvRamMap != NULL);
1864 }
1865 } else {
1866 VariableDefinition->NvRamMap = AllocateZeroPool (VariableDefinition->VariableSize);
1867 ASSERT (VariableDefinition->NvRamMap != NULL);
1868 }
1869
1870 if (VariableDefinition->VariableFakeSize != 0) {
1871 VariableDefinition->FakeNvRamMap = AllocateZeroPool (VariableDefinition->VariableFakeSize);
1872 ASSERT (VariableDefinition->FakeNvRamMap != NULL);
1873 }
1874 }
1875
1876 Status = gBS->HandleProtocol (
1877 (VOID *) (UINTN) FileFormTags->FormTags.Tags[0].CallbackHandle,
1878 &gEfiFormCallbackProtocolGuid,
1879 (VOID **) &FormCallback
1880 );
1881
1882 //
1883 // Since we might have multiple variables, if there is an NvMapOverride we need to use the EFI_VARIABLE_DEFINITION
1884 // information as the information that we pass back and forth. NOTE that callbacks that are initiated will only have the
1885 // NVRAM data refreshed based on the op-code that initiated the callback. In other words, we will pass to the caller a single
1886 // NVRAM map for a single variable based on the op-code that the user selected.
1887 //
1888 if (NvMapOverride != NULL) {
1889 VariableDefinition = FileFormTags->VariableDefinitions;
1890 OverrideDefinition = ((EFI_VARIABLE_DEFINITION *) NvMapOverride);
1891
1892 //
1893 // Search through the variable definitions. There should be sufficient passed in settings for the variable op-codes specified
1894 //
1895 for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
1896 if ((!CompareMem (VariableDefinition->VariableName, L"Setup", 10)) && (VariableDefinition->Next == NULL)) {
1897 if (VariableDefinition->VariableSize != 0) {
1898 CopyMem (VariableDefinition->NvRamMap, NvMapOverride, VariableDefinition->VariableSize);
1899 } else {
1900 CopyMem (VariableDefinition->NvRamMap, NvMapOverride, VariableDefinition->VariableFakeSize);
1901 }
1902 break;
1903 } else {
1904 VariableDefinition->NvRamMap = OverrideDefinition->NvRamMap;
1905 }
1906 //
1907 // There should NEVER be a ->Next for VariableDefinition and a NULL ->Next for the OverrideDefinition
1908 //
1909 ASSERT (OverrideDefinition->Next);
1910 OverrideDefinition = OverrideDefinition->Next;
1911 }
1912 } else {
1913 VariableDefinition = FileFormTags->VariableDefinitions;
1914
1915 //
1916 // Search through the variable definitions. There should be sufficient passed in settings for the variable op-codes specified
1917 //
1918 for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
1919 SizeOfNvStore = VariableDefinition->VariableSize;
1920
1921 //
1922 // Getting the NvStore and placing it into our Global Data
1923 //
1924 if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {
1925 Status = FormCallback->NvRead (
1926 FormCallback,
1927 VariableDefinition->VariableName,
1928 &VariableDefinition->Guid,
1929 NULL,
1930 &SizeOfNvStore,
1931 (VOID *) VariableDefinition->NvRamMap
1932 );
1933 } else {
1934 Status = gRT->GetVariable (
1935 VariableDefinition->VariableName,
1936 &VariableDefinition->Guid,
1937 NULL,
1938 &SizeOfNvStore,
1939 (VOID *) VariableDefinition->NvRamMap
1940 );
1941 }
1942
1943 if (EFI_ERROR (Status)) {
1944 //
1945 // If there is a variable that exists already and it is larger than what we calculated the
1946 // storage needs to be, we must assume the variable size from GetVariable is correct and not
1947 // allow the truncation of the variable. It is very possible that the user who created the IFR
1948 // we are cracking is not referring to a variable that was in a previous map, however we cannot
1949 // allow it's truncation.
1950 //
1951 if (Status == EFI_BUFFER_TOO_SMALL) {
1952 //
1953 // If the buffer was too small, we should have the expanded size requirement in SizeOfNvStore now.
1954 //
1955 VariableDefinition->VariableSize = (UINT16) SizeOfNvStore;
1956
1957 //
1958 // Free the buffer that was allocated that was too small
1959 //
1960 FreePool (VariableDefinition->NvRamMap);
1961 FreePool (VariableDefinition->FakeNvRamMap);
1962
1963 VariableDefinition->NvRamMap = AllocateZeroPool (SizeOfNvStore);
1964 VariableDefinition->FakeNvRamMap = AllocateZeroPool (SizeOfNvStore + VariableDefinition->VariableFakeSize);
1965 ASSERT (VariableDefinition->NvRamMap);
1966 ASSERT (VariableDefinition->FakeNvRamMap);
1967
1968 if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {
1969 Status = FormCallback->NvRead (
1970 FormCallback,
1971 VariableDefinition->VariableName,
1972 &VariableDefinition->Guid,
1973 NULL,
1974 &SizeOfNvStore,
1975 (VOID *) VariableDefinition->NvRamMap
1976 );
1977 } else {
1978 Status = gRT->GetVariable (
1979 VariableDefinition->VariableName,
1980 &VariableDefinition->Guid,
1981 NULL,
1982 &SizeOfNvStore,
1983 (VOID *) VariableDefinition->NvRamMap
1984 );
1985 }
1986 }
1987 //
1988 // if the variable was not found, we will retrieve default values
1989 //
1990 if (Status == EFI_NOT_FOUND) {
1991
1992 if (0 == CompareMem (VariableDefinition->VariableName, L"Setup", 10)) {
1993
1994 NvMapListHead = NULL;
1995
1996 Status = Hii->GetDefaultImage (Hii, Handle[HandleIndex], EFI_IFR_FLAG_DEFAULT, &NvMapListHead);
1997
1998 if (!EFI_ERROR (Status)) {
1999 ASSERT_EFI_ERROR (NULL != NvMapListHead);
2000
2001 NvMapListNode = NvMapListHead;
2002
2003 while (NULL != NvMapListNode) {
2004 if (VariableDefinition->VariableId == NvMapListNode->VariablePack->VariableId) {
2005 NvMap = (VOID *) ((CHAR8 *) NvMapListNode->VariablePack + sizeof (EFI_HII_VARIABLE_PACK) + NvMapListNode->VariablePack->VariableNameLength);
2006 NvMapSize = NvMapListNode->VariablePack->Header.Length - sizeof (EFI_HII_VARIABLE_PACK) - NvMapListNode->VariablePack->VariableNameLength;
2007 break;
2008 }
2009 NvMapListNode = NvMapListNode->NextVariablePack;
2010 }
2011
2012 //
2013 // Free the buffer that was allocated.
2014 //
2015 FreePool (VariableDefinition->NvRamMap);
2016 FreePool (VariableDefinition->FakeNvRamMap);
2017
2018 //
2019 // Allocate, copy the NvRamMap.
2020 //
2021 VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize - VariableDefinition->VariableSize);
2022 VariableDefinition->VariableSize = (UINT16) NvMapSize;
2023 VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize + VariableDefinition->VariableSize);
2024
2025 VariableDefinition->NvRamMap = AllocateZeroPool (VariableDefinition->VariableSize);
2026 VariableDefinition->FakeNvRamMap = AllocateZeroPool (NvMapSize + VariableDefinition->VariableFakeSize);
2027
2028 CopyMem (VariableDefinition->NvRamMap, NvMap, NvMapSize);
2029 FreePool (NvMapListHead);
2030 }
2031
2032 }
2033 Status = EFI_SUCCESS;
2034 }
2035 }
2036 }
2037 }
2038
2039 InitializeTagStructures (BinaryData, FileFormTags);
2040 }
2041 //
2042 // endfor
2043 //
2044 return Status;
2045 }
2046
2047 STATIC
2048 EFI_STATUS
2049 GetIfrBinaryData (
2050 IN EFI_HII_PROTOCOL *Hii,
2051 IN EFI_HII_HANDLE HiiHandle,
2052 IN EFI_IFR_PACKET *Packet,
2053 IN OUT EFI_IFR_BINARY *BinaryData
2054 )
2055 /*++
2056
2057 Routine Description:
2058 Fetch the Ifr binary data.
2059
2060 Arguments:
2061 Hii - Point to HII protocol.
2062 HiiHandle - Handle of Ifr to be fetched.
2063 Packet - Pointer to IFR packet.
2064 BinaryData - Buffer to copy the string into
2065
2066 Returns:
2067 Returns the number of CHAR16 characters that were copied into the OutputString buffer.
2068
2069
2070 --*/
2071 {
2072 EFI_STATUS Status;
2073 EFI_HII_PACKAGES *PackageList;
2074 UINTN BufferSize;
2075 VOID *Buffer;
2076 UINT8 *RawFormBinary;
2077 EFI_IFR_FORM_SET *FormOp;
2078 UINT16 Index;
2079 UINT16 Index2;
2080 UINT16 TitleToken;
2081
2082 //
2083 // Initialize the TitleToken to 0 just in case not found
2084 //
2085 TitleToken = 0;
2086
2087 //
2088 // Try for a 32K Buffer
2089 //
2090 BufferSize = 0x8000;
2091
2092 //
2093 // Allocate memory for our Form binary
2094 //
2095 Buffer = AllocateZeroPool (BufferSize);
2096 ASSERT (Buffer);
2097
2098 if (Packet == NULL) {
2099 Status = Hii->GetForms (Hii, HiiHandle, 0, &BufferSize, Buffer);
2100
2101 if (Status == EFI_BUFFER_TOO_SMALL) {
2102
2103 FreePool (Buffer);
2104
2105 //
2106 // Allocate memory for our Form binary
2107 //
2108 Buffer = AllocatePool (BufferSize);
2109 ASSERT (Buffer);
2110
2111 Status = Hii->GetForms (Hii, HiiHandle, 0, &BufferSize, Buffer);
2112 }
2113 } else {
2114 //
2115 // Copies the data to local usable buffer
2116 //
2117 CopyMem (Buffer, Packet->IfrData, Packet->IfrData->Header.Length);
2118
2119 //
2120 // Register the string data with HII
2121 //
2122 PackageList = PreparePackages (2, NULL, Packet->IfrData, Packet->StringData);
2123
2124 Status = Hii->NewPack (Hii, PackageList, &HiiHandle);
2125
2126 FreePool (PackageList);
2127 }
2128
2129 if (EFI_ERROR (Status)) {
2130 return Status;
2131 }
2132 //
2133 // We now have the IFR binary in our Buffer
2134 //
2135 BinaryData->IfrPackage = Buffer;
2136 RawFormBinary = (UINT8 *) ((CHAR8 *) (Buffer) + sizeof (EFI_HII_PACK_HEADER));
2137 BinaryData->FormBinary = (UINT8 *) ((CHAR8 *) (Buffer) + sizeof (EFI_HII_PACK_HEADER));
2138 BinaryData->Handle = HiiHandle;
2139
2140 //
2141 // If a packet was passed in, remove the string data when exiting.
2142 //
2143 if (Packet != NULL) {
2144 BinaryData->UnRegisterOnExit = TRUE;
2145 } else {
2146 BinaryData->UnRegisterOnExit = FALSE;
2147 }
2148 //
2149 // Walk through the FormSet Opcodes looking for the FormSet opcode
2150 // If we hit EFI_IFR_END_SET_OP we know we hit the end of the FormSet.
2151 //
2152 for (Index = 0; RawFormBinary[Index] != EFI_IFR_END_FORM_SET_OP;) {
2153 FormOp = (EFI_IFR_FORM_SET *) &RawFormBinary[Index];
2154 Index = (UINT16) (Index + FormOp->Header.Length);
2155
2156 if (FormOp->Header.OpCode == EFI_IFR_FORM_SET_OP) {
2157 TitleToken = FormOp->FormSetTitle;
2158 //
2159 // If displaying FrontPage - set the flag signifying it
2160 //
2161 switch (FormOp->SubClass) {
2162 case EFI_FRONT_PAGE_SUBCLASS:
2163 FrontPageHandle = HiiHandle;
2164
2165 default:
2166 gClassOfVfr = FormOp->SubClass;
2167 }
2168 //
2169 // Match GUID to find out the function key setting. If match fail, use the default setting.
2170 //
2171 for (Index2 = 0; Index2 < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index2++) {
2172 if (CompareGuid ((EFI_GUID *)(UINTN)&FormOp->Guid, &(gFunctionKeySettingTable[Index2].FormSetGuid))) {
2173 //
2174 // Update the function key setting.
2175 //
2176 gFunctionKeySetting = gFunctionKeySettingTable[Index2].KeySetting;
2177 //
2178 // Function key prompt can not be displayed if the function key has been disabled.
2179 //
2180 if ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE) {
2181 gFunctionOneString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
2182 }
2183
2184 if ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO) {
2185 gFunctionTwoString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
2186 }
2187
2188 if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {
2189 gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
2190 }
2191
2192 if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {
2193 gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
2194 }
2195 }
2196 }
2197 }
2198 }
2199
2200 BinaryData->TitleToken = TitleToken;
2201
2202 return Status;
2203 }
2204
2205 EFI_HANDLE PrintHandle = NULL;
2206 EFI_PRINT_PROTOCOL mPrintProtocol = { UnicodeVSPrint };
2207
2208 STATIC
2209 EFI_STATUS
2210 InstallPrint (
2211 VOID
2212 )
2213 {
2214 return gBS->InstallProtocolInterface (
2215 &PrintHandle,
2216 &gEfiPrintProtocolGuid,
2217 EFI_NATIVE_INTERFACE,
2218 &mPrintProtocol
2219 );
2220 }