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