]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Setup.c
759eb5efb993398e5c51870e4163939ade7dd616
[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 gBS->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 gBS->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 gBS->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 gBS->FreePool (CallbackData);
361 return Status;
362 }
363
364 if (Callback && (AltSelection == NULL)) {
365 gBS->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 gBS->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 gBS->FreePool (CallbackData);
394 return EFI_SUCCESS;
395 }
396
397 gBS->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 gBS->FreePool (CallbackData);
409 return EFI_SUCCESS;
410 }
411 }
412
413 } while (!EFI_ERROR (Status));
414
415 gBS->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 gBS->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 gBS->FreePool (FormTags->Tags[Index].IntList);
833 }
834 }
835
836 gBS->FreePool (FormTags->Tags);
837 gBS->FreePool (FormTags->Next);
838 FormTags->Next = NULL;
839 FormTags->Tags = NULL;
840
841 FormTags = SavedFormTags;
842
843 } while (FormTags->Next != NULL);
844 }
845
846 Index = 0;
847
848 //
849 // Test for an allocated buffer. If already allocated this is due to having called this routine
850 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
851 // the tag structure with current values from the NV
852 //
853 if (FormTags->Tags == NULL) {
854 //
855 // Allocate memory for our tags on the first form
856 //
857 FormTags->Tags = AllocateZeroPool (NumberOfTags * sizeof (EFI_TAG));
858 ASSERT (FormTags->Tags);
859 }
860 //
861 // Test for an allocated buffer. If already allocated this is due to having called this routine
862 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
863 // the tag structure with current values from the NV
864 //
865 if (InconsistentTags == NULL) {
866 //
867 // We just hit the end of an inconsistent expression. Let's allocate the ->Next structure
868 //
869 InconsistentTags = AllocateZeroPool (sizeof (EFI_INCONSISTENCY_DATA));
870 ASSERT (InconsistentTags != NULL);
871
872 FileFormTags->InconsistentTags = InconsistentTags;
873 }
874
875 ZeroMem (FormTags->Tags, NumberOfTags * sizeof (EFI_TAG));
876
877 for (CurrTag = 0; RawFormSet[Index] != EFI_IFR_END_FORM_SET_OP; CurrTag++) {
878 //
879 // Operand = IFR OpCode
880 //
881 FormTags->Tags[CurrTag].Operand = RawFormSet[Index];
882
883 //
884 // Assume for now 0 lines occupied by this OpCode
885 //
886 FormTags->Tags[CurrTag].NumberOfLines = 0;
887
888 FormTags->Tags[CurrTag].Class = Class;
889 FormTags->Tags[CurrTag].SubClass = SubClass;
890
891 //
892 // Determine the length of the Tag so we can later skip to the next tag in the form
893 //
894 TagLength = RawFormSet[Index + 1];
895 //
896 // get the length
897 //
898 // Operate on the Found OpCode
899 //
900 switch (RawFormSet[Index]) {
901
902 case EFI_IFR_FORM_OP:
903 //
904 // If there was no variable op-code defined, create a dummy entry for one
905 //
906 if (FileFormTags->VariableDefinitions == NULL) {
907 FileFormTags->VariableDefinitions = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION));
908 ASSERT (FileFormTags->VariableDefinitions != NULL);
909 IfrToFormTag (
910 RawFormSet[Index],
911 &FormTags->Tags[CurrTag],
912 (VOID *) &RawFormSet[Index],
913 FileFormTags->VariableDefinitions
914 );
915 } else {
916 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
917 }
918 break;
919
920 case EFI_IFR_SUBTITLE_OP:
921 case EFI_IFR_TEXT_OP:
922 case EFI_IFR_REF_OP:
923 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
924 break;
925
926 case EFI_IFR_VARSTORE_OP:
927 if (FileFormTags->VariableDefinitions == NULL) {
928 VariableDefinitions = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION));
929 ASSERT (VariableDefinitions != NULL);
930 FileFormTags->VariableDefinitions = VariableDefinitions;
931 }
932
933 IfrToFormTag (
934 RawFormSet[Index],
935 &FormTags->Tags[CurrTag],
936 (VOID *) &RawFormSet[Index],
937 FileFormTags->VariableDefinitions
938 );
939 break;
940
941 case EFI_IFR_VARSTORE_SELECT_OP:
942 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
943 CopyMem (&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT *) &RawFormSet[Index])->VarId, sizeof (UINT16));
944 CurrentVariable2 = CurrentVariable;
945 break;
946
947 case EFI_IFR_VARSTORE_SELECT_PAIR_OP:
948 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
949 CopyMem(&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT_PAIR *)&RawFormSet[Index])->VarId, sizeof (UINT16));
950 CopyMem (
951 &CurrentVariable2,
952 &((EFI_IFR_VARSTORE_SELECT_PAIR *) &RawFormSet[Index])->SecondaryVarId,
953 sizeof (UINT16)
954 );
955 break;
956
957 case EFI_IFR_END_FORM_OP:
958 //
959 // Test for an allocated buffer. If already allocated this is due to having called this routine
960 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
961 // the tag structure with current values from the NV
962 //
963 if (FormTags->Next == NULL) {
964 //
965 // We just hit the end of a form. Let's allocate the ->Next structure
966 //
967 FormTags->Next = AllocatePool (sizeof (EFI_FORM_TAGS));
968 ASSERT (FormTags->Next);
969 }
970
971 FormTags = FormTags->Next;
972 ZeroMem (FormTags, sizeof (EFI_FORM_TAGS));
973
974 //
975 // Reset the tag count to one
976 //
977 NumberOfTags = 1;
978
979 //
980 // Reset the CurrTag value (it will be incremented, after this case statement
981 // so set to a negative one so that we get the desired effect.) Fish can beat me later.
982 //
983 CurrTag = -1;
984
985 //
986 // Determine the number of tags after this form. If this is the last
987 // form, then we will count the endformset and preserve that information
988 // in the tag structure.
989 //
990 GetTagCount (&RawFormSet[Index + TagLength], &NumberOfTags);
991
992 //
993 // Allocate memory for our tags
994 //
995 FormTags->Tags = AllocateZeroPool (NumberOfTags * sizeof (EFI_TAG));
996 ASSERT (FormTags->Tags);
997 break;
998
999 //
1000 // Two types of tags constitute the One Of question: a one-of header and
1001 // several one-of options.
1002 //
1003 case EFI_IFR_ONE_OF_OP:
1004 case EFI_IFR_ORDERED_LIST_OP:
1005 GetQuestionHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, FileFormTags, CurrentVariable);
1006
1007 //
1008 // Store away the CurrTag since what follows will be the answer that we
1009 // need to place into the appropriate location in the tag array
1010 //
1011 //
1012 // record for setting default later
1013 //
1014 QuestionIndex = (UINT16) CurrTag;
1015 break;
1016
1017 case EFI_IFR_ONE_OF_OPTION_OP:
1018 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
1019 FormTags->Tags[QuestionIndex].Flags = ((EFI_IFR_ONE_OF_OPTION *) &RawFormSet[Index])->Flags;
1020 CopyMem (
1021 &FormTags->Tags[QuestionIndex].Key,
1022 &((EFI_IFR_ONE_OF_OPTION *) &RawFormSet[Index])->Key,
1023 sizeof (UINT16)
1024 );
1025 FormTags->Tags[QuestionIndex].ResetRequired = (BOOLEAN) (FormTags->Tags[QuestionIndex].Flags & EFI_IFR_FLAG_RESET_REQUIRED);
1026 break;
1027
1028 case EFI_IFR_CHECKBOX_OP:
1029 GetQuestionHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, FileFormTags, CurrentVariable);
1030 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
1031 break;
1032
1033 case EFI_IFR_NUMERIC_OP:
1034 GetNumericHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, (UINT16) 1, FileFormTags, CurrentVariable);
1035 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
1036 break;
1037
1038 case EFI_IFR_DATE_OP:
1039 //
1040 // Date elements come in as a Year, Month, Day. We need to process them as a country-based
1041 // Order. It is much easier to do it here than anywhere else.
1042 //
1043 // For US standards - we want Month/Day/Year, thus we advance "Index" +1, +2, +0 while CurrTag is +0, +1, +2
1044 //
1045 GetNumericHeader (
1046 &FormTags->Tags[CurrTag],
1047 RawFormSet,
1048 (UINT16) (Index + TagLength),
1049 (UINT16) 0,
1050 FileFormTags,
1051 CurrentVariable
1052 );
1053
1054 //
1055 // The current language selected + the Date operand
1056 //
1057 FormTags->Tags[CurrTag + 1].Operand = RawFormSet[Index];
1058 GetNumericHeader (
1059 &FormTags->Tags[CurrTag + 1],
1060 RawFormSet,
1061 (UINT16) (Index + TagLength + RawFormSet[Index + TagLength + 1]),
1062 (UINT16) 0,
1063 FileFormTags,
1064 CurrentVariable
1065 );
1066
1067 //
1068 // The current language selected + the Date operand
1069 //
1070 FormTags->Tags[CurrTag + 2].Operand = RawFormSet[Index];
1071 GetNumericHeader (&FormTags->Tags[CurrTag + 2], RawFormSet, Index, (UINT16) 1, FileFormTags, CurrentVariable);
1072
1073 CurrTag = (INT16) (CurrTag + 2);
1074
1075 Index = (UINT16) (Index + TagLength);
1076 //
1077 // get the length
1078 //
1079 TagLength = RawFormSet[Index + 1];
1080 Index = (UINT16) (Index + TagLength);
1081 //
1082 // get the length
1083 //
1084 TagLength = RawFormSet[Index + 1];
1085 break;
1086
1087 case EFI_IFR_TIME_OP:
1088 GetNumericHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, (UINT16) 0, FileFormTags, CurrentVariable);
1089
1090 if (Count == 2) {
1091 //
1092 // Override the GetQuestionHeader information - date/time are treated very differently
1093 //
1094 FormTags->Tags[CurrTag].NumberOfLines = 1;
1095 Count = 0;
1096 } else {
1097 //
1098 // The premise is that every date/time op-code have 3 elements, the first 2 have 0 lines
1099 // associated with them, and the third has 1 line to allow to space beyond the choice.
1100 //
1101 Count++;
1102 }
1103 break;
1104
1105 case EFI_IFR_PASSWORD_OP:
1106 case EFI_IFR_STRING_OP:
1107 GetQuestionHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, FileFormTags, CurrentVariable);
1108 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
1109 break;
1110
1111 case EFI_IFR_SUPPRESS_IF_OP:
1112 case EFI_IFR_GRAYOUT_IF_OP:
1113 InconsistentTags->Operand = ((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Header.OpCode;
1114 gConsistencyId++;
1115
1116 //
1117 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1118 // Unfortunately 0 is a valid offset value for a QuestionId
1119 //
1120 InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE;
1121 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
1122
1123 //
1124 // Test for an allocated buffer. If already allocated this is due to having called this routine
1125 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1126 // the tag structure with current values from the NV
1127 //
1128 if (InconsistentTags->Next == NULL) {
1129 AddNextInconsistentTag (&InconsistentTags);
1130 break;
1131 }
1132
1133 InconsistentTags = InconsistentTags->Next;
1134 break;
1135
1136 case EFI_IFR_FORM_SET_OP:
1137 CopyMem (
1138 &FormTags->Tags[CurrTag].GuidValue,
1139 &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->Guid,
1140 sizeof (EFI_GUID)
1141 );
1142 CopyMem (
1143 &FormTags->Tags[CurrTag].CallbackHandle,
1144 &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->CallbackHandle,
1145 sizeof (EFI_PHYSICAL_ADDRESS)
1146 );
1147 CopyMem (&FormTags->Tags[CurrTag].Class, &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->Class, sizeof (UINT8));
1148 CopyMem (
1149 &FormTags->Tags[CurrTag].SubClass,
1150 &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->SubClass,
1151 sizeof (UINT8)
1152 );
1153 CopyMem (
1154 &FormTags->Tags[CurrTag].NvDataSize,
1155 &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->NvDataSize,
1156 sizeof (UINT16)
1157 );
1158 Class = ((EFI_IFR_FORM_SET *) &RawFormSet[Index])->Class;
1159 SubClass = ((EFI_IFR_FORM_SET *) &RawFormSet[Index])->SubClass;
1160 //
1161 // If the formset has a size value, that means someone must be using this, so create a variable
1162 // We also shall reserve the formid of 0 for this specific purpose.
1163 //
1164 if ((FileFormTags->VariableDefinitions == NULL) && (FormTags->Tags[CurrTag].NvDataSize > 0)) {
1165 FileFormTags->VariableDefinitions = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION));
1166 ASSERT (FileFormTags->VariableDefinitions != NULL);
1167 IfrToFormTag (
1168 RawFormSet[Index],
1169 &FormTags->Tags[CurrTag],
1170 (VOID *) &RawFormSet[Index],
1171 FileFormTags->VariableDefinitions
1172 );
1173 } else {
1174 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
1175 }
1176 break;
1177
1178 case EFI_IFR_BANNER_OP:
1179 if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
1180 TempValue = 0;
1181 CopyMem (&TempValue, &((EFI_IFR_BANNER *) &RawFormSet[Index])->Alignment, sizeof (UINT8));
1182 //
1183 // If this is the special timeout value, we will dynamically figure out where to put it
1184 // Also the least significant byte refers to the TimeOut desired.
1185 //
1186 if (TempValue == EFI_IFR_BANNER_TIMEOUT) {
1187 CopyMem (&FrontPageTimeOutTitle, &((EFI_IFR_BANNER *) &RawFormSet[Index])->Title, sizeof (UINT16));
1188 if (FrontPageTimeOutValue != (INT16) -1) {
1189 CopyMem (&FrontPageTimeOutValue, &((EFI_IFR_BANNER *) &RawFormSet[Index])->LineNumber, sizeof (UINT16));
1190 }
1191 break;
1192 }
1193
1194 CopyMem (
1195 &BannerData->Banner[((EFI_IFR_BANNER *) &RawFormSet[Index])->LineNumber][
1196 ((EFI_IFR_BANNER *) &RawFormSet[Index])->Alignment],
1197 &((EFI_IFR_BANNER *) &RawFormSet[Index])->Title,
1198 sizeof (STRING_REF)
1199 );
1200 }
1201 break;
1202
1203 case EFI_IFR_INCONSISTENT_IF_OP:
1204 CopyMem (
1205 &FormTags->Tags[CurrTag].Text,
1206 &((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Popup,
1207 sizeof (UINT16)
1208 );
1209 gConsistencyId++;
1210
1211 InconsistentTags->Operand = ((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Header.OpCode;
1212 CopyMem (&InconsistentTags->Popup, &((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Popup, sizeof (UINT16));
1213
1214 //
1215 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1216 // Unfortunately 0 is a valid offset value for a QuestionId
1217 //
1218 InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE;
1219 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
1220
1221 InconsistentTags->VariableNumber = CurrentVariable;
1222
1223 //
1224 // Test for an allocated buffer. If already allocated this is due to having called this routine
1225 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1226 // the tag structure with current values from the NV
1227 //
1228 if (InconsistentTags->Next == NULL) {
1229 AddNextInconsistentTag (&InconsistentTags);
1230 break;
1231 }
1232
1233 InconsistentTags = InconsistentTags->Next;
1234 break;
1235
1236 case EFI_IFR_EQ_ID_VAL_OP:
1237 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
1238
1239 InconsistentTags->Operand = ((EFI_IFR_EQ_ID_VAL *) &RawFormSet[Index])->Header.OpCode;
1240 CopyMem (&InconsistentTags->Value, &((EFI_IFR_EQ_ID_VAL *) &RawFormSet[Index])->Value, sizeof (UINT16));
1241 CopyMem (
1242 &InconsistentTags->QuestionId1,
1243 &((EFI_IFR_EQ_ID_VAL *) &RawFormSet[Index])->QuestionId,
1244 sizeof (UINT16)
1245 );
1246
1247 //
1248 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1249 // Unfortunately 0 is a valid offset value for a QuestionId
1250 //
1251 InconsistentTags->Width = FormTags->Tags[CurrTag].StorageWidth;
1252 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
1253 InconsistentTags->ConsistencyId = gConsistencyId;
1254 FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;
1255
1256 InconsistentTags->VariableNumber = CurrentVariable;
1257
1258 //
1259 // Test for an allocated buffer. If already allocated this is due to having called this routine
1260 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1261 // the tag structure with current values from the NV
1262 //
1263 if (InconsistentTags->Next == NULL) {
1264 AddNextInconsistentTag (&InconsistentTags);
1265 break;
1266 }
1267
1268 InconsistentTags = InconsistentTags->Next;
1269 break;
1270
1271 case EFI_IFR_EQ_VAR_VAL_OP:
1272 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
1273
1274 InconsistentTags->Operand = ((EFI_IFR_EQ_VAR_VAL *) &RawFormSet[Index])->Header.OpCode;
1275 CopyMem (&InconsistentTags->Value, &((EFI_IFR_EQ_VAR_VAL *) &RawFormSet[Index])->Value, sizeof (UINT16));
1276 CopyMem (
1277 &InconsistentTags->QuestionId1,
1278 &((EFI_IFR_EQ_VAR_VAL *) &RawFormSet[Index])->VariableId,
1279 sizeof (UINT16)
1280 );
1281
1282 //
1283 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1284 // Unfortunately 0 is a valid offset value for a QuestionId
1285 //
1286 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
1287 InconsistentTags->ConsistencyId = gConsistencyId;
1288 FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;
1289
1290 InconsistentTags->VariableNumber = CurrentVariable;
1291
1292 //
1293 // Test for an allocated buffer. If already allocated this is due to having called this routine
1294 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1295 // the tag structure with current values from the NV
1296 //
1297 if (InconsistentTags->Next == NULL) {
1298 AddNextInconsistentTag (&InconsistentTags);
1299 break;
1300 }
1301
1302 InconsistentTags = InconsistentTags->Next;
1303 break;
1304
1305 case EFI_IFR_EQ_ID_ID_OP:
1306 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
1307
1308 InconsistentTags->Operand = ((EFI_IFR_EQ_ID_ID *) &RawFormSet[Index])->Header.OpCode;
1309 CopyMem (
1310 &InconsistentTags->QuestionId1,
1311 &((EFI_IFR_EQ_ID_ID *) &RawFormSet[Index])->QuestionId1,
1312 sizeof (UINT16)
1313 );
1314 CopyMem (
1315 &InconsistentTags->QuestionId2,
1316 &((EFI_IFR_EQ_ID_ID *) &RawFormSet[Index])->QuestionId2,
1317 sizeof (UINT16)
1318 );
1319
1320 InconsistentTags->Width = FormTags->Tags[CurrTag].StorageWidth;
1321 InconsistentTags->ConsistencyId = gConsistencyId;
1322 FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;
1323
1324 InconsistentTags->VariableNumber = CurrentVariable;
1325 InconsistentTags->VariableNumber2 = CurrentVariable2;
1326
1327 //
1328 // Test for an allocated buffer. If already allocated this is due to having called this routine
1329 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1330 // the tag structure with current values from the NV
1331 //
1332 if (InconsistentTags->Next == NULL) {
1333 AddNextInconsistentTag (&InconsistentTags);
1334 break;
1335 }
1336
1337 InconsistentTags = InconsistentTags->Next;
1338 break;
1339
1340 case EFI_IFR_AND_OP:
1341 case EFI_IFR_OR_OP:
1342 case EFI_IFR_NOT_OP:
1343 case EFI_IFR_GT_OP:
1344 case EFI_IFR_GE_OP:
1345 case EFI_IFR_TRUE_OP:
1346 case EFI_IFR_FALSE_OP:
1347 InconsistentTags->Operand = ((EFI_IFR_NOT *) &RawFormSet[Index])->Header.OpCode;
1348
1349 //
1350 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1351 // Unfortunately 0 is a valid offset value for a QuestionId
1352 //
1353
1354 //
1355 // Reserve INVALID_OFFSET_VALUE - 1 for TRUE or FALSE because they are inconsistency tags also, but
1356 // have no coresponding id. The examination of id is needed by evaluating boolean expression.
1357 //
1358 if (RawFormSet[Index] == EFI_IFR_TRUE_OP ||
1359 RawFormSet[Index] == EFI_IFR_FALSE_OP) {
1360 InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE - 1;
1361 } else {
1362 InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE;
1363 }
1364 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
1365 InconsistentTags->ConsistencyId = gConsistencyId;
1366 FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;
1367
1368 //
1369 // Test for an allocated buffer. If already allocated this is due to having called this routine
1370 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1371 // the tag structure with current values from the NV
1372 //
1373 if (InconsistentTags->Next == NULL) {
1374 AddNextInconsistentTag (&InconsistentTags);
1375 break;
1376 }
1377
1378 InconsistentTags = InconsistentTags->Next;
1379 break;
1380
1381 case EFI_IFR_EQ_ID_LIST_OP:
1382 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
1383
1384 InconsistentTags->Operand = ((EFI_IFR_EQ_ID_LIST *) &RawFormSet[Index])->Header.OpCode;
1385 CopyMem (
1386 &InconsistentTags->QuestionId1,
1387 &((EFI_IFR_EQ_ID_LIST *) &RawFormSet[Index])->QuestionId,
1388 sizeof (UINT16)
1389 );
1390 CopyMem (
1391 &InconsistentTags->ListLength,
1392 &((EFI_IFR_EQ_ID_LIST *) &RawFormSet[Index])->ListLength,
1393 sizeof (UINT16)
1394 );
1395 InconsistentTags->ValueList = FormTags->Tags[CurrTag].IntList;
1396
1397 //
1398 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1399 // Unfortunately 0 is a valid offset value for a QuestionId
1400 //
1401 InconsistentTags->Width = FormTags->Tags[CurrTag].StorageWidth;
1402 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
1403 InconsistentTags->ConsistencyId = gConsistencyId;
1404 FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;
1405
1406 //
1407 // Test for an allocated buffer. If already allocated this is due to having called this routine
1408 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1409 // the tag structure with current values from the NV
1410 //
1411 if (InconsistentTags->Next == NULL) {
1412 AddNextInconsistentTag (&InconsistentTags);
1413 break;
1414 }
1415
1416 InconsistentTags = InconsistentTags->Next;
1417 break;
1418
1419 case EFI_IFR_END_IF_OP:
1420 InconsistentTags->Operand = ((EFI_IFR_END_EXPR *) &RawFormSet[Index])->Header.OpCode;
1421
1422 //
1423 // Since this op-code doesn't use the next field(s), initialize them with something invalid.
1424 // Unfortunately 0 is a valid offset value for a QuestionId
1425 //
1426 InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE;
1427 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
1428
1429 //
1430 // Test for an allocated buffer. If already allocated this is due to having called this routine
1431 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
1432 // the tag structure with current values from the NV
1433 //
1434 if (InconsistentTags->Next == NULL) {
1435 AddNextInconsistentTag (&InconsistentTags);
1436 break;
1437 }
1438
1439 InconsistentTags = InconsistentTags->Next;
1440 break;
1441
1442 case EFI_IFR_END_ONE_OF_OP:
1443 break;
1444
1445 default:
1446 break;
1447 }
1448 //
1449 // End of switch
1450 //
1451 // Per spec., we ignore ops that we don't know how to deal with. Skip to next tag
1452 //
1453 Index = (UINT16) (Index + TagLength);
1454 }
1455 //
1456 // End of Index
1457 //
1458 // When we eventually exit, make sure we mark the last tag with an op-code
1459 //
1460 FormTags->Tags[CurrTag].Operand = RawFormSet[Index];
1461
1462 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
1463
1464 //
1465 // Place this as an end of the database marker
1466 //
1467 InconsistentTags->Operand = 0xFF;
1468
1469 //
1470 // This is the Head of the linked list of pages. Each page is an array of tags
1471 //
1472 FormTags = &FileFormTags->FormTags;
1473 InconsistentTags = FileFormTags->InconsistentTags;
1474
1475 for (; InconsistentTags->Operand != 0xFF;) {
1476 if (InconsistentTags->QuestionId1 != INVALID_OFFSET_VALUE) {
1477 //
1478 // Search the tags for the tag which corresponds to this ID
1479 //
1480 for (CurrTag = 0; FormTags->Tags[0].Operand != EFI_IFR_END_FORM_SET_OP; CurrTag++) {
1481 //
1482 // If we hit the end of a form, go to the next set of Tags.
1483 // Remember - EndFormSet op-codes sit on their own page after an end form.
1484 //
1485 if (FormTags->Tags[CurrTag].Operand == EFI_IFR_END_FORM_OP) {
1486 //
1487 // Reset the CurrTag value (it will be incremented, after this case statement
1488 // so set to a negative one so that we get the desired effect.) Fish can beat me later.
1489 //
1490 CurrTag = -1;
1491 FormTags = FormTags->Next;
1492 continue;
1493 }
1494
1495 if (FormTags->Tags[CurrTag].Id == InconsistentTags->QuestionId1) {
1496 FormTags->Tags[CurrTag].Consistency++;
1497 }
1498 }
1499 }
1500
1501 FormTags = &FileFormTags->FormTags;
1502
1503 if (InconsistentTags->QuestionId2 != INVALID_OFFSET_VALUE) {
1504 //
1505 // Search the tags for the tag which corresponds to this ID
1506 //
1507 for (CurrTag = 0; FormTags->Tags[CurrTag].Operand != EFI_IFR_END_FORM_SET_OP; CurrTag++) {
1508 //
1509 // If we hit the end of a form, go to the next set of Tags.
1510 // Remember - EndFormSet op-codes sit on their own page after an end form.
1511 //
1512 if (FormTags->Tags[CurrTag].Operand == EFI_IFR_END_FORM_OP) {
1513 //
1514 // Reset the CurrTag value (it will be incremented, after this case statement
1515 // so set to a negative one so that we get the desired effect.) Fish can beat me later.
1516 //
1517 CurrTag = -1;
1518 FormTags = FormTags->Next;
1519 continue;
1520 }
1521
1522 if (FormTags->Tags[CurrTag].Id == InconsistentTags->QuestionId2) {
1523 FormTags->Tags[CurrTag].Consistency++;
1524 }
1525 }
1526 }
1527
1528 InconsistentTags = InconsistentTags->Next;
1529 }
1530
1531 return Status;
1532 }
1533
1534 VOID
1535 InitPage (
1536 VOID
1537 )
1538 {
1539 CHAR16 *HomePageString;
1540 CHAR16 *HomeEscapeString;
1541
1542 //
1543 // Displays the Header and Footer borders
1544 //
1545 DisplayPageFrame ();
1546
1547 HomePageString = GetToken (STRING_TOKEN (HOME_PAGE_TITLE), gHiiHandle);
1548 HomeEscapeString = GetToken (STRING_TOKEN (HOME_ESCAPE_STRING), gHiiHandle);
1549
1550 gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);
1551 //
1552 // PrintStringAt ((gScreenDimensions.RightColumn - GetStringWidth(HomePageString)/2)/2, 1, HomePageString);
1553 //
1554 PrintStringAt (
1555 (gScreenDimensions.RightColumn + gScreenDimensions.LeftColumn - GetStringWidth (HomePageString) / 2) / 2,
1556 1,
1557 HomePageString
1558 );
1559 PrintAt (
1560 gScreenDimensions.LeftColumn + 2,
1561 gScreenDimensions.BottomRow - 3,
1562 (CHAR16 *) L"%c%c%s",
1563 ARROW_UP,
1564 ARROW_DOWN,
1565 gMoveHighlight
1566 );
1567 PrintAt (
1568 gScreenDimensions.RightColumn - (GetStringWidth (HomeEscapeString) / 2) - 2,
1569 gScreenDimensions.BottomRow - 3,
1570 (CHAR16 *) L" %s",
1571 HomeEscapeString
1572 );
1573 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
1574 gBS->FreePool (HomeEscapeString);
1575 gBS->FreePool (HomePageString);
1576
1577 return ;
1578 }
1579
1580 CHAR16 *
1581 GetToken (
1582 IN STRING_REF Token,
1583 IN EFI_HII_HANDLE HiiHandle
1584 )
1585 /*++
1586
1587 Routine Description:
1588
1589 Get the string based on the TokenID and HII Handle.
1590
1591 Arguments:
1592
1593 Token - The Token ID.
1594 HiiHandle - Handle of Ifr to be fetched.
1595
1596 Returns:
1597
1598 The output string.
1599
1600 --*/
1601 {
1602 CHAR16 *Buffer;
1603 UINTN BufferLength;
1604 EFI_STATUS Status;
1605
1606 //
1607 // Set default string size assumption at no more than 256 bytes
1608 //
1609 BufferLength = 0x100;
1610
1611 Buffer = AllocateZeroPool (BufferLength);
1612 ASSERT (Buffer != NULL);
1613
1614 Status = Hii->GetString (Hii, HiiHandle, Token, TRUE, NULL, &BufferLength, Buffer);
1615
1616 if (EFI_ERROR (Status)) {
1617 if (Status == EFI_BUFFER_TOO_SMALL) {
1618 //
1619 // Free the old pool
1620 //
1621 gBS->FreePool (Buffer);
1622
1623 //
1624 // Allocate new pool with correct value
1625 //
1626 Buffer = AllocatePool (BufferLength);
1627 ASSERT (Buffer != NULL);
1628
1629 Status = Hii->GetString (Hii, HiiHandle, Token, TRUE, NULL, &BufferLength, Buffer);
1630
1631 if (!EFI_ERROR (Status)) {
1632 return Buffer;
1633 }
1634 }
1635
1636 ASSERT_EFI_ERROR (Status);
1637 }
1638
1639 return Buffer;
1640 }
1641
1642 STATIC
1643 EFI_STATUS
1644 PopulateHomePage (
1645 IN UINTN NumberOfIfrImages,
1646 IN EFI_FILE_FORM_TAGS *FileFormTagsHead
1647 )
1648 {
1649 EFI_STATUS Status;
1650 UINTN Index;
1651 EFI_IFR_BINARY *IfrBinary;
1652 CHAR16 *StringPtr;
1653 EFI_FILE_FORM_TAGS *FileFormTags;
1654 EFI_FORM_TAGS LocalTags;
1655
1656 FileFormTags = FileFormTagsHead;
1657
1658 UiInitMenu ();
1659
1660 Status = EFI_SUCCESS;
1661
1662 //
1663 // If there are no images
1664 //
1665 if (NumberOfIfrImages == 0) {
1666 Status = EFI_NO_MEDIA;
1667 return Status;
1668 }
1669 //
1670 // IfrBinary points to the beginning of the Binary data linked-list
1671 //
1672 IfrBinary = gBinaryDataHead;
1673
1674 //
1675 // Print the entries which were in the default language.
1676 //
1677 for (Index = 0; Index < NumberOfIfrImages; Index++) {
1678 LocalTags = FileFormTags->FormTags;
1679
1680 //
1681 // Populate the Menu
1682 //
1683 StringPtr = GetToken (IfrBinary->TitleToken, IfrBinary->Handle);
1684
1685 //
1686 // If the default language doesn't exist, don't add a menu option yet
1687 //
1688 if (StringPtr[0] != CHAR_NULL) {
1689 //
1690 // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do
1691 // it in UiFreeMenu.
1692 //
1693 UiAddMenuOption (StringPtr, IfrBinary->Handle, LocalTags.Tags, IfrBinary->FormBinary, Index);
1694 }
1695 //
1696 // Advance to the next HII handle
1697 //
1698 IfrBinary = IfrBinary->Next;
1699 FileFormTags = FileFormTags->NextFile;
1700 }
1701
1702 return Status;
1703 }
1704
1705 STATIC
1706 UI_MENU_OPTION *
1707 DisplayHomePage (
1708 IN UINTN NumberOfIfrImages,
1709 IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
1710 IN UINT8 *CallbackData
1711 )
1712 {
1713 EFI_STATUS Status;
1714 UI_MENU_OPTION *Selection;
1715
1716 //
1717 // This prints the basic home page template which the user sees
1718 //
1719 InitPage ();
1720
1721 Status = PopulateHomePage (NumberOfIfrImages, FileFormTagsHead);
1722
1723 if (EFI_ERROR (Status)) {
1724 Selection = NULL;
1725 return Selection;
1726 }
1727
1728 Selection = UiDisplayMenu (FALSE, FileFormTagsHead, (EFI_IFR_DATA_ARRAY *) CallbackData);
1729
1730 return Selection;
1731 }
1732
1733 STATIC
1734 EFI_STATUS
1735 InitializeBinaryStructures (
1736 IN EFI_HII_HANDLE *Handle,
1737 IN BOOLEAN UseDatabase,
1738 IN EFI_IFR_PACKET *Packet,
1739 IN UINT8 *NvMapOverride,
1740 IN UINTN NumberOfIfrImages,
1741 OUT EFI_FILE_FORM_TAGS **FileFormTagsHead
1742 )
1743 {
1744 UINTN HandleIndex;
1745 EFI_STATUS Status;
1746 EFI_IFR_BINARY *BinaryData;
1747 EFI_FILE_FORM_TAGS *FileFormTags;
1748 UINTN SizeOfNvStore;
1749 EFI_FORM_CALLBACK_PROTOCOL *FormCallback;
1750 EFI_VARIABLE_DEFINITION *VariableDefinition;
1751 EFI_VARIABLE_DEFINITION *OverrideDefinition;
1752 VOID *NvMap;
1753 UINTN NvMapSize;
1754 EFI_HII_VARIABLE_PACK_LIST *NvMapListHead;
1755 EFI_HII_VARIABLE_PACK_LIST *NvMapListNode;
1756
1757 //
1758 // Initialize some variables to avoid warnings
1759 //
1760 BinaryData = NULL;
1761 *FileFormTagsHead = NULL;
1762 FileFormTags = NULL;
1763 gBinaryDataHead = NULL;
1764 Status = EFI_SUCCESS;
1765 FormCallback = NULL;
1766 NvMap = NULL;
1767 NvMapSize = 0;
1768
1769 if (NumberOfIfrImages > 1) {
1770 NvMapOverride = NULL;
1771 }
1772
1773 for (HandleIndex = 0; HandleIndex < NumberOfIfrImages; HandleIndex += 1) {
1774 //
1775 // If the buffers are uninitialized, allocate them, otherwise work on the ->Next members
1776 //
1777 if ((BinaryData == NULL) || (FileFormTags == NULL)) {
1778 //
1779 // Allocate memory for our Binary Data
1780 //
1781 BinaryData = AllocateZeroPool (sizeof (EFI_IFR_BINARY));
1782 ASSERT (BinaryData);
1783
1784 //
1785 // Preserve the Head of what will be a linked-list.
1786 //
1787 gBinaryDataHead = BinaryData;
1788 gBinaryDataHead->Next = NULL;
1789
1790 if (UseDatabase) {
1791 Status = GetIfrBinaryData (Hii, Handle[HandleIndex], NULL, BinaryData);
1792 } else {
1793 Status = GetIfrBinaryData (Hii, Handle[HandleIndex], Packet, BinaryData);
1794 }
1795 //
1796 // Allocate memory for our File Form Tags
1797 //
1798 FileFormTags = AllocateZeroPool (sizeof (EFI_FILE_FORM_TAGS));
1799 ASSERT (FileFormTags);
1800
1801 //
1802 // Preserve the Head of what will be a linked-list.
1803 //
1804 *FileFormTagsHead = FileFormTags;
1805 (*FileFormTagsHead)->NextFile = NULL;
1806
1807 } else {
1808 //
1809 // Allocate memory for our Binary Data linked-list
1810 // Each handle represents a Binary and we will store that data away.
1811 //
1812 BinaryData->Next = AllocateZeroPool (sizeof (EFI_IFR_BINARY));
1813 ASSERT (BinaryData->Next);
1814
1815 BinaryData = BinaryData->Next;
1816 BinaryData->Next = NULL;
1817
1818 if (UseDatabase) {
1819 Status = GetIfrBinaryData (Hii, Handle[HandleIndex], NULL, BinaryData);
1820 } else {
1821 Status = GetIfrBinaryData (Hii, Handle[HandleIndex], Packet, BinaryData);
1822 }
1823
1824 if (EFI_ERROR (Status)) {
1825 return EFI_DEVICE_ERROR;
1826 }
1827 //
1828 // Allocate memory for our FileFormTags linked-list
1829 // Each allocation reserves handle represents a Binary and we will store that data away.
1830 //
1831 FileFormTags->NextFile = AllocateZeroPool (sizeof (EFI_FILE_FORM_TAGS));
1832 ASSERT (FileFormTags->NextFile);
1833
1834 FileFormTags = FileFormTags->NextFile;
1835 }
1836 //
1837 // endif
1838 //
1839 // Tag Structure Initialization
1840 //
1841 Status = InitializeTagStructures (BinaryData, FileFormTags);
1842
1843 VariableDefinition = FileFormTags->VariableDefinitions;
1844
1845 //
1846 // Allocate memory for our NVRAM Maps for all of our variables
1847 //
1848 for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
1849 //
1850 // Pad the fake variable size accordingly - this value should reflect the size of information that is not accounted by
1851 // the mainstream NVRAM variable such as DATE/TIME information that the browser needs to track but is saved to an RTC
1852 //
1853 VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableSize + VariableDefinition->VariableFakeSize);
1854
1855 //
1856 // In the case where a file has no "real" NV data, we should pad the buffer accordingly
1857 //
1858 if (VariableDefinition->VariableSize == 0) {
1859 if (VariableDefinition->VariableFakeSize != 0) {
1860 VariableDefinition->NvRamMap = AllocateZeroPool (VariableDefinition->VariableFakeSize);
1861 ASSERT (VariableDefinition->NvRamMap != NULL);
1862 }
1863 } else {
1864 VariableDefinition->NvRamMap = AllocateZeroPool (VariableDefinition->VariableSize);
1865 ASSERT (VariableDefinition->NvRamMap != NULL);
1866 }
1867
1868 if (VariableDefinition->VariableFakeSize != 0) {
1869 VariableDefinition->FakeNvRamMap = AllocateZeroPool (VariableDefinition->VariableFakeSize);
1870 ASSERT (VariableDefinition->FakeNvRamMap != NULL);
1871 }
1872 }
1873
1874 Status = gBS->HandleProtocol (
1875 (VOID *) (UINTN) FileFormTags->FormTags.Tags[0].CallbackHandle,
1876 &gEfiFormCallbackProtocolGuid,
1877 (VOID **) &FormCallback
1878 );
1879
1880 //
1881 // Since we might have multiple variables, if there is an NvMapOverride we need to use the EFI_VARIABLE_DEFINITION
1882 // information as the information that we pass back and forth. NOTE that callbacks that are initiated will only have the
1883 // NVRAM data refreshed based on the op-code that initiated the callback. In other words, we will pass to the caller a single
1884 // NVRAM map for a single variable based on the op-code that the user selected.
1885 //
1886 if (NvMapOverride != NULL) {
1887 VariableDefinition = FileFormTags->VariableDefinitions;
1888 OverrideDefinition = ((EFI_VARIABLE_DEFINITION *) NvMapOverride);
1889
1890 //
1891 // Search through the variable definitions. There should be sufficient passed in settings for the variable op-codes specified
1892 //
1893 for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
1894 if ((!CompareMem (VariableDefinition->VariableName, L"Setup", 10)) && (VariableDefinition->Next == NULL)) {
1895 if (VariableDefinition->VariableSize != 0) {
1896 CopyMem (VariableDefinition->NvRamMap, NvMapOverride, VariableDefinition->VariableSize);
1897 } else {
1898 CopyMem (VariableDefinition->NvRamMap, NvMapOverride, VariableDefinition->VariableFakeSize);
1899 }
1900 break;
1901 } else {
1902 VariableDefinition->NvRamMap = OverrideDefinition->NvRamMap;
1903 }
1904 //
1905 // There should NEVER be a ->Next for VariableDefinition and a NULL ->Next for the OverrideDefinition
1906 //
1907 ASSERT (OverrideDefinition->Next);
1908 OverrideDefinition = OverrideDefinition->Next;
1909 }
1910 } else {
1911 VariableDefinition = FileFormTags->VariableDefinitions;
1912
1913 //
1914 // Search through the variable definitions. There should be sufficient passed in settings for the variable op-codes specified
1915 //
1916 for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
1917 SizeOfNvStore = VariableDefinition->VariableSize;
1918
1919 //
1920 // Getting the NvStore and placing it into our Global Data
1921 //
1922 if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {
1923 Status = FormCallback->NvRead (
1924 FormCallback,
1925 VariableDefinition->VariableName,
1926 &VariableDefinition->Guid,
1927 NULL,
1928 &SizeOfNvStore,
1929 (VOID *) VariableDefinition->NvRamMap
1930 );
1931 } else {
1932 Status = gRT->GetVariable (
1933 VariableDefinition->VariableName,
1934 &VariableDefinition->Guid,
1935 NULL,
1936 &SizeOfNvStore,
1937 (VOID *) VariableDefinition->NvRamMap
1938 );
1939 }
1940
1941 if (EFI_ERROR (Status)) {
1942 //
1943 // If there is a variable that exists already and it is larger than what we calculated the
1944 // storage needs to be, we must assume the variable size from GetVariable is correct and not
1945 // allow the truncation of the variable. It is very possible that the user who created the IFR
1946 // we are cracking is not referring to a variable that was in a previous map, however we cannot
1947 // allow it's truncation.
1948 //
1949 if (Status == EFI_BUFFER_TOO_SMALL) {
1950 //
1951 // If the buffer was too small, we should have the expanded size requirement in SizeOfNvStore now.
1952 //
1953 VariableDefinition->VariableSize = (UINT16) SizeOfNvStore;
1954
1955 //
1956 // Free the buffer that was allocated that was too small
1957 //
1958 gBS->FreePool (VariableDefinition->NvRamMap);
1959 gBS->FreePool (VariableDefinition->FakeNvRamMap);
1960
1961 VariableDefinition->NvRamMap = AllocateZeroPool (SizeOfNvStore);
1962 VariableDefinition->FakeNvRamMap = AllocateZeroPool (SizeOfNvStore + VariableDefinition->VariableFakeSize);
1963 ASSERT (VariableDefinition->NvRamMap);
1964 ASSERT (VariableDefinition->FakeNvRamMap);
1965
1966 if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {
1967 Status = FormCallback->NvRead (
1968 FormCallback,
1969 VariableDefinition->VariableName,
1970 &VariableDefinition->Guid,
1971 NULL,
1972 &SizeOfNvStore,
1973 (VOID *) VariableDefinition->NvRamMap
1974 );
1975 } else {
1976 Status = gRT->GetVariable (
1977 VariableDefinition->VariableName,
1978 &VariableDefinition->Guid,
1979 NULL,
1980 &SizeOfNvStore,
1981 (VOID *) VariableDefinition->NvRamMap
1982 );
1983 }
1984 }
1985 //
1986 // if the variable was not found, we will retrieve default values
1987 //
1988 if (Status == EFI_NOT_FOUND) {
1989
1990 if (0 == CompareMem (VariableDefinition->VariableName, L"Setup", 10)) {
1991
1992 NvMapListHead = NULL;
1993
1994 Status = Hii->GetDefaultImage (Hii, Handle[HandleIndex], EFI_IFR_FLAG_DEFAULT, &NvMapListHead);
1995
1996 if (!EFI_ERROR (Status)) {
1997 ASSERT_EFI_ERROR (NULL != NvMapListHead);
1998
1999 NvMapListNode = NvMapListHead;
2000
2001 while (NULL != NvMapListNode) {
2002 if (VariableDefinition->VariableId == NvMapListNode->VariablePack->VariableId) {
2003 NvMap = (VOID *) ((CHAR8 *) NvMapListNode->VariablePack + sizeof (EFI_HII_VARIABLE_PACK) + NvMapListNode->VariablePack->VariableNameLength);
2004 NvMapSize = NvMapListNode->VariablePack->Header.Length - sizeof (EFI_HII_VARIABLE_PACK) - NvMapListNode->VariablePack->VariableNameLength;
2005 break;
2006 }
2007 NvMapListNode = NvMapListNode->NextVariablePack;
2008 }
2009
2010 //
2011 // Free the buffer that was allocated.
2012 //
2013 gBS->FreePool (VariableDefinition->NvRamMap);
2014 gBS->FreePool (VariableDefinition->FakeNvRamMap);
2015
2016 //
2017 // Allocate, copy the NvRamMap.
2018 //
2019 VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize - VariableDefinition->VariableSize);
2020 VariableDefinition->VariableSize = (UINT16) NvMapSize;
2021 VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize + VariableDefinition->VariableSize);
2022
2023 VariableDefinition->NvRamMap = AllocateZeroPool (VariableDefinition->VariableSize);
2024 VariableDefinition->FakeNvRamMap = AllocateZeroPool (NvMapSize + VariableDefinition->VariableFakeSize);
2025
2026 CopyMem (VariableDefinition->NvRamMap, NvMap, NvMapSize);
2027 gBS->FreePool (NvMapListHead);
2028 }
2029
2030 }
2031 Status = EFI_SUCCESS;
2032 }
2033 }
2034 }
2035 }
2036
2037 InitializeTagStructures (BinaryData, FileFormTags);
2038 }
2039 //
2040 // endfor
2041 //
2042 return Status;
2043 }
2044
2045 STATIC
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 STATIC
2207 EFI_STATUS
2208 InstallPrint (
2209 VOID
2210 )
2211 {
2212 return gBS->InstallProtocolInterface (
2213 &PrintHandle,
2214 &gEfiPrintProtocolGuid,
2215 EFI_NATIVE_INTERFACE,
2216 &mPrintProtocol
2217 );
2218 }