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