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