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