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