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