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