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