]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Setup.c
Partially make EdkModulePkg pass intel IPF compiler with /W4 /WX switched on.
[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
111EFI_STATUS\r
112InitializeBinaryStructures (\r
113 IN EFI_HII_HANDLE *Handle,\r
114 IN BOOLEAN UseDatabase,\r
115 IN EFI_IFR_PACKET *Packet,\r
116 IN UINT8 *NvMapOverride,\r
117 IN UINTN NumberOfIfrImages,\r
118 EFI_FILE_FORM_TAGS **FileFormTagsHead\r
119 );\r
120\r
121EFI_STATUS\r
122InitializeTagStructures (\r
123 IN EFI_IFR_BINARY *BinaryData,\r
124 OUT EFI_FILE_FORM_TAGS *FileFormTags\r
125 );\r
126\r
127UI_MENU_OPTION *\r
128DisplayHomePage (\r
129 IN UINTN NumberOfIfrImages,\r
130 IN EFI_FILE_FORM_TAGS *FileFormTagsHead,\r
131 IN UINT8 *CallbackData\r
132 );\r
133\r
134EFI_STATUS\r
135GetIfrBinaryData (\r
136 IN EFI_HII_PROTOCOL *Hii,\r
137 IN EFI_HII_HANDLE HiiHandle,\r
138 IN EFI_IFR_PACKET *Packet,\r
139 IN EFI_IFR_BINARY *BinaryData\r
140 );\r
141\r
142EFI_STATUS\r
143InstallPrint (\r
144 VOID\r
145 );\r
146\r
1cc8ee78 147STATIC\r
878ddf1f 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
878ddf1f 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
878ddf1f 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 gBS->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 gBS->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 gBS->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 gBS->FreePool (CallbackData);\r
362 return Status;\r
363 }\r
364\r
365 if (Callback && (AltSelection == NULL)) {\r
366 gBS->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 gBS->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 gBS->FreePool (CallbackData);\r
395 return EFI_SUCCESS;\r
396 }\r
397\r
398 gBS->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 gBS->FreePool (CallbackData);\r
410 return EFI_SUCCESS;\r
411 }\r
412 }\r
413\r
414 } while (!EFI_ERROR (Status));\r
415\r
416 gBS->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 gBS->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 } else {\r
585 continue;\r
586 }\r
587 }\r
588}\r
589\r
590VOID\r
591GetNumericHeader (\r
592 IN EFI_TAG *Tag,\r
593 IN UINT8 *RawFormSet,\r
594 IN UINT16 Index,\r
595 IN UINT16 NumberOfLines,\r
596 IN EFI_FILE_FORM_TAGS *FileFormTags,\r
597 IN UINT16 CurrentVariable\r
598 )\r
599/*++\r
600\r
601Routine Description:\r
602 Initialize numeric tag's members.\r
603\r
604Arguments:\r
605 Tag - Pointer of the current EFI_TAG structure.\r
606 RawFormSet - Pointer of the formset raw data.\r
607 Index - Offset of the current opcode in the Ifr raw data.\r
608 NumberOfLines - Number of lines this opcode occupied.\r
609 FileFormTags - Pointer of current EFI_FILE_FORM_TAGS structure.\r
610 CurrentVariable - Current variable number.\r
611 \r
612Returns:\r
613 None.\r
614--*/\r
615{\r
616 EFI_VARIABLE_DEFINITION *VariableDefinition;\r
617\r
618 Tag->NumberOfLines = NumberOfLines;\r
619 Tag->VariableNumber = CurrentVariable;\r
620 CopyMem (&Tag->Id, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->QuestionId, sizeof (UINT16));\r
621 CopyMem (&Tag->StorageStart, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->QuestionId, sizeof (UINT16));\r
622 CopyMem (&Tag->StorageWidth, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Width, sizeof (UINT8));\r
623 CopyMem (&Tag->Text, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Prompt, sizeof (UINT16));\r
624 CopyMem (&Tag->Help, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Help, sizeof (UINT16));\r
625 CopyMem (&Tag->Minimum, &((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Minimum, sizeof (UINT16));\r
626 CopyMem (&Tag->Maximum, &((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Maximum, sizeof (UINT16));\r
627 CopyMem (&Tag->Step, &((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Step, sizeof (UINT16));\r
628 CopyMem (&Tag->Default, &((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Default, sizeof (UINT16));\r
629 Tag->ResetRequired = (BOOLEAN) (((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Flags & EFI_IFR_FLAG_RESET_REQUIRED);\r
630\r
631 VariableDefinition = FileFormTags->VariableDefinitions;\r
632\r
633 for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {\r
634 //\r
635 // Have we found the correct variable for the request?\r
636 //\r
637 if (CurrentVariable == VariableDefinition->VariableId) {\r
638 if (VariableDefinition->VariableSize <= (UINTN) (Tag->StorageStart + Tag->StorageWidth)) {\r
639 if (Tag->StorageWidth == 0) {\r
640 VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize + 2);\r
641 } else {\r
642 VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize + Tag->StorageWidth);\r
643 }\r
644 }\r
645\r
646 if (VariableDefinition->NvRamMap != NULL) {\r
647 //\r
648 // If it is an 8bit or 16bit width, then move it to Tag->Value, otherwise\r
649 // we will never be looking for the data in Tag->Value (e.g. strings, password, etc)\r
650 //\r
651 if (Tag->StorageWidth == (UINT16) 1) {\r
652 CopyMem (&Tag->Value, &VariableDefinition->NvRamMap[Tag->StorageStart], sizeof (UINT16));\r
653 }\r
654\r
655 if (Tag->StorageWidth == (UINT16) 2) {\r
656 Index = (UINT16)\r
657 (\r
658 VariableDefinition->NvRamMap[Tag->StorageStart] +\r
659 (VariableDefinition->NvRamMap[Tag->StorageStart + 1] * 0x100)\r
660 );\r
661 CopyMem (&Tag->Value, &Index, sizeof (UINT16));\r
662 }\r
663 } else {\r
664 CopyMem (&Tag->Value, &Tag->Default, sizeof (UINT16));\r
665 }\r
666 break;\r
667 } else {\r
668 continue;\r
669 }\r
670 }\r
671}\r
672\r
673VOID\r
674GetTagCount (\r
675 IN UINT8 *RawFormSet,\r
676 IN OUT UINT16 *NumberOfTags\r
677 )\r
678{\r
679 UINT16 Index;\r
680\r
681 //\r
682 // Assume on entry we are pointing to an OpCode - reasonably this should\r
683 // be a FormOp since the purpose is to count the tags in a particular Form.\r
684 //\r
685 for (Index = 0; RawFormSet[Index] != EFI_IFR_END_FORM_OP;) {\r
686 //\r
687 // If we encounter the end of a form set, bail out\r
688 //\r
689 if (RawFormSet[Index] == EFI_IFR_END_FORM_SET_OP) {\r
690 break;\r
691 }\r
692 //\r
693 // We treat date/time internally as three op-codes\r
694 //\r
695 if (RawFormSet[Index] == EFI_IFR_DATE_OP || RawFormSet[Index] == EFI_IFR_TIME_OP) {\r
696 *NumberOfTags = (UINT16) (*NumberOfTags + 3);\r
697 } else {\r
698 //\r
699 // Assume that we could have no more tags than op-codes\r
700 //\r
701 (*NumberOfTags)++;\r
702 }\r
703\r
704 Index = (UINT16) (Index + RawFormSet[Index + 1]);\r
705 }\r
706 //\r
707 // Increase the tag count by one so it is inclusive of the end_form_op\r
708 //\r
709 (*NumberOfTags)++;\r
710}\r
711\r
1cc8ee78 712STATIC\r
878ddf1f 713VOID\r
714AddNextInconsistentTag (\r
715 IN OUT EFI_INCONSISTENCY_DATA **InconsistentTagsPtr\r
716 )\r
717/*++\r
718\r
719Routine Description:\r
720 Initialize the next inconsistent tag data and add it to the inconsistent tag list.\r
721 \r
722Arguments:\r
723 InconsistentTagsPtr - Pointer of the inconsistent tag's pointer.\r
724\r
725Returns: \r
726 None.\r
727\r
728--*/\r
729{\r
730 EFI_INCONSISTENCY_DATA *PreviousInconsistentTags;\r
731 EFI_INCONSISTENCY_DATA *InconsistentTags;\r
732\r
733 InconsistentTags = *InconsistentTagsPtr;\r
734 //\r
735 // We just hit the end of an inconsistent expression. Let's allocate the ->Next structure\r
736 //\r
737 InconsistentTags->Next = AllocatePool (sizeof (EFI_INCONSISTENCY_DATA));\r
738 ASSERT (InconsistentTags->Next != NULL);\r
739\r
740 //\r
741 // Preserve current Tag entry\r
742 //\r
743 PreviousInconsistentTags = InconsistentTags;\r
744\r
745 InconsistentTags = InconsistentTags->Next;\r
746\r
747 //\r
748 // This will zero on the entry including the ->Next so I don't have to do it\r
749 //\r
750 ZeroMem (InconsistentTags, sizeof (EFI_INCONSISTENCY_DATA));\r
751\r
752 //\r
753 // Point our Previous field to the previous entry\r
754 //\r
755 InconsistentTags->Previous = PreviousInconsistentTags;\r
756\r
757 *InconsistentTagsPtr = InconsistentTags;\r
758\r
759 return ;\r
760}\r
761\r
762EFI_STATUS\r
763InitializeTagStructures (\r
764 IN EFI_IFR_BINARY *BinaryData,\r
765 OUT EFI_FILE_FORM_TAGS *FileFormTags\r
766 )\r
767{\r
768 EFI_STATUS Status;\r
769 UINT8 *RawFormSet;\r
770 UINT16 Index;\r
771 UINT16 QuestionIndex;\r
772 UINT16 NumberOfTags;\r
773 INT16 CurrTag;\r
774 UINT8 TagLength;\r
775 EFI_FORM_TAGS *FormTags;\r
776 EFI_FORM_TAGS *SavedFormTags;\r
777 EFI_INCONSISTENCY_DATA *InconsistentTags;\r
778 EFI_VARIABLE_DEFINITION *VariableDefinitions;\r
779 UINTN Count;\r
780 UINT16 Class;\r
781 UINT16 SubClass;\r
782 UINT16 TempValue;\r
783 UINT16 CurrentVariable;\r
784 UINT16 CurrentVariable2;\r
785\r
786 //\r
787 // Initialize some Index variable and Status\r
788 //\r
789 Count = 0;\r
790 Class = 0;\r
791 SubClass = 0;\r
792 CurrentVariable = 0;\r
793 CurrentVariable2 = 0;\r
794 QuestionIndex = 0;\r
795 NumberOfTags = 1;\r
796 Status = EFI_SUCCESS;\r
797 FormTags = &FileFormTags->FormTags;\r
798 FormTags->Next = NULL;\r
799 if (FileFormTags->InconsistentTags == NULL) {\r
800 InconsistentTags = NULL;\r
801 } else {\r
802 InconsistentTags = FileFormTags->InconsistentTags;\r
803 }\r
804\r
805 if (FileFormTags->VariableDefinitions == NULL) {\r
806 VariableDefinitions = NULL;\r
807 } else {\r
808 VariableDefinitions = FileFormTags->VariableDefinitions;\r
809 }\r
810 //\r
811 // RawFormSet now points to the beginning of the forms portion of\r
812 // the specific IFR Binary.\r
813 //\r
814 RawFormSet = (UINT8 *) BinaryData->FormBinary;\r
815\r
816 //\r
817 // Determine the number of tags for the first form\r
818 //\r
819 GetTagCount (&RawFormSet[0], &NumberOfTags);\r
820\r
821 SavedFormTags = FormTags;\r
822\r
823 if (FormTags->Tags != NULL) {\r
824 do {\r
825 //\r
826 // Advance FormTags to the last entry\r
827 //\r
828 for (; FormTags->Next != NULL; FormTags = FormTags->Next)\r
829 ;\r
830\r
831 //\r
832 // Walk through each of the tags and free the IntList allocation\r
833 //\r
834 for (Index = 0; Index < NumberOfTags; Index++) {\r
835 if (FormTags->Tags[Index].IntList != NULL) {\r
836 gBS->FreePool (FormTags->Tags[Index].IntList);\r
837 }\r
838 }\r
839\r
840 gBS->FreePool (FormTags->Tags);\r
841 gBS->FreePool (FormTags->Next);\r
842 FormTags->Next = NULL;\r
843 FormTags->Tags = NULL;\r
844\r
845 FormTags = SavedFormTags;\r
846\r
847 } while (FormTags->Next != NULL);\r
848 }\r
849\r
850 Index = 0;\r
851\r
852 //\r
853 // Test for an allocated buffer. If already allocated this is due to having called this routine\r
854 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize\r
855 // the tag structure with current values from the NV\r
856 //\r
857 if (FormTags->Tags == NULL) {\r
858 //\r
859 // Allocate memory for our tags on the first form\r
860 //\r
861 FormTags->Tags = AllocateZeroPool (NumberOfTags * sizeof (EFI_TAG));\r
862 ASSERT (FormTags->Tags);\r
863 }\r
864 //\r
865 // Test for an allocated buffer. If already allocated this is due to having called this routine\r
866 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize\r
867 // the tag structure with current values from the NV\r
868 //\r
869 if (InconsistentTags == NULL) {\r
870 //\r
871 // We just hit the end of an inconsistent expression. Let's allocate the ->Next structure\r
872 //\r
873 InconsistentTags = AllocateZeroPool (sizeof (EFI_INCONSISTENCY_DATA));\r
874 ASSERT (InconsistentTags != NULL);\r
875\r
876 FileFormTags->InconsistentTags = InconsistentTags;\r
877 }\r
878\r
879 ZeroMem (FormTags->Tags, NumberOfTags * sizeof (EFI_TAG));\r
880\r
881 for (CurrTag = 0; RawFormSet[Index] != EFI_IFR_END_FORM_SET_OP; CurrTag++) {\r
882 //\r
883 // Operand = IFR OpCode\r
884 //\r
885 FormTags->Tags[CurrTag].Operand = RawFormSet[Index];\r
886\r
887 //\r
888 // Assume for now 0 lines occupied by this OpCode\r
889 //\r
890 FormTags->Tags[CurrTag].NumberOfLines = 0;\r
891\r
892 FormTags->Tags[CurrTag].Class = Class;\r
893 FormTags->Tags[CurrTag].SubClass = SubClass;\r
894\r
895 //\r
896 // Determine the length of the Tag so we can later skip to the next tag in the form\r
897 //\r
898 TagLength = RawFormSet[Index + 1];\r
899 //\r
900 // get the length\r
901 //\r
902 // Operate on the Found OpCode\r
903 //\r
904 switch (RawFormSet[Index]) {\r
905\r
906 case EFI_IFR_FORM_OP:\r
907 //\r
908 // If there was no variable op-code defined, create a dummy entry for one\r
909 //\r
910 if (FileFormTags->VariableDefinitions == NULL) {\r
911 FileFormTags->VariableDefinitions = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION));\r
912 ASSERT (FileFormTags->VariableDefinitions != NULL);\r
913 IfrToFormTag (\r
914 RawFormSet[Index],\r
915 &FormTags->Tags[CurrTag],\r
916 (VOID *) &RawFormSet[Index],\r
917 FileFormTags->VariableDefinitions\r
918 );\r
919 } else {\r
920 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);\r
921 }\r
922 break;\r
923\r
924 case EFI_IFR_SUBTITLE_OP:\r
925 case EFI_IFR_TEXT_OP:\r
926 case EFI_IFR_REF_OP:\r
927 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);\r
928 break;\r
929\r
930 case EFI_IFR_VARSTORE_OP:\r
931 if (FileFormTags->VariableDefinitions == NULL) {\r
932 VariableDefinitions = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION));\r
933 ASSERT (VariableDefinitions != NULL);\r
934 FileFormTags->VariableDefinitions = VariableDefinitions;\r
935 }\r
936\r
937 IfrToFormTag (\r
938 RawFormSet[Index],\r
939 &FormTags->Tags[CurrTag],\r
940 (VOID *) &RawFormSet[Index],\r
941 FileFormTags->VariableDefinitions\r
942 );\r
943 break;\r
944\r
945 case EFI_IFR_VARSTORE_SELECT_OP:\r
946 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);\r
947 CopyMem (&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT *) &RawFormSet[Index])->VarId, sizeof (UINT16));\r
948 CurrentVariable2 = CurrentVariable;\r
949 break;\r
950\r
951 case EFI_IFR_VARSTORE_SELECT_PAIR_OP:\r
952 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);\r
953 CopyMem(&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT_PAIR *)&RawFormSet[Index])->VarId, sizeof (UINT16));\r
954 CopyMem (\r
955 &CurrentVariable2,\r
956 &((EFI_IFR_VARSTORE_SELECT_PAIR *) &RawFormSet[Index])->SecondaryVarId,\r
957 sizeof (UINT16)\r
958 );\r
959 break;\r
960\r
961 case EFI_IFR_END_FORM_OP:\r
962 //\r
963 // Test for an allocated buffer. If already allocated this is due to having called this routine\r
964 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize\r
965 // the tag structure with current values from the NV\r
966 //\r
967 if (FormTags->Next == NULL) {\r
968 //\r
969 // We just hit the end of a form. Let's allocate the ->Next structure\r
970 //\r
971 FormTags->Next = AllocatePool (sizeof (EFI_FORM_TAGS));\r
972 ASSERT (FormTags->Next);\r
973 }\r
974\r
975 FormTags = FormTags->Next;\r
976 ZeroMem (FormTags, sizeof (EFI_FORM_TAGS));\r
977\r
978 //\r
979 // Reset the tag count to one\r
980 //\r
981 NumberOfTags = 1;\r
982\r
983 //\r
984 // Reset the CurrTag value (it will be incremented, after this case statement\r
985 // so set to a negative one so that we get the desired effect.) Fish can beat me later.\r
986 //\r
987 CurrTag = -1;\r
988\r
989 //\r
990 // Determine the number of tags after this form. If this is the last\r
991 // form, then we will count the endformset and preserve that information\r
992 // in the tag structure.\r
993 //\r
994 GetTagCount (&RawFormSet[Index + TagLength], &NumberOfTags);\r
995\r
996 //\r
997 // Allocate memory for our tags\r
998 //\r
999 FormTags->Tags = AllocateZeroPool (NumberOfTags * sizeof (EFI_TAG));\r
1000 ASSERT (FormTags->Tags);\r
1001 break;\r
1002\r
1003 //\r
1004 // Two types of tags constitute the One Of question: a one-of header and\r
1005 // several one-of options.\r
1006 //\r
1007 case EFI_IFR_ONE_OF_OP:\r
1008 case EFI_IFR_ORDERED_LIST_OP:\r
1009 GetQuestionHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, FileFormTags, CurrentVariable);\r
1010\r
1011 //\r
1012 // Store away the CurrTag since what follows will be the answer that we\r
1013 // need to place into the appropriate location in the tag array\r
1014 //\r
1015 //\r
1016 // record for setting default later\r
1017 //\r
1018 QuestionIndex = (UINT16) CurrTag;\r
1019 break;\r
1020\r
1021 case EFI_IFR_ONE_OF_OPTION_OP:\r
1022 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);\r
1023 FormTags->Tags[QuestionIndex].Flags = ((EFI_IFR_ONE_OF_OPTION *) &RawFormSet[Index])->Flags;\r
1024 CopyMem (\r
1025 &FormTags->Tags[QuestionIndex].Key,\r
1026 &((EFI_IFR_ONE_OF_OPTION *) &RawFormSet[Index])->Key,\r
1027 sizeof (UINT16)\r
1028 );\r
1029 FormTags->Tags[QuestionIndex].ResetRequired = (BOOLEAN) (FormTags->Tags[QuestionIndex].Flags & EFI_IFR_FLAG_RESET_REQUIRED);\r
1030 break;\r
1031\r
1032 case EFI_IFR_CHECKBOX_OP:\r
1033 GetQuestionHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, FileFormTags, CurrentVariable);\r
1034 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);\r
1035 break;\r
1036\r
1037 case EFI_IFR_NUMERIC_OP:\r
1038 GetNumericHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, (UINT16) 1, FileFormTags, CurrentVariable);\r
1039 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);\r
1040 break;\r
1041\r
1042 case EFI_IFR_DATE_OP:\r
1043 //\r
1044 // Date elements come in as a Year, Month, Day. We need to process them as a country-based\r
1045 // Order. It is much easier to do it here than anywhere else.\r
1046 //\r
1047 // For US standards - we want Month/Day/Year, thus we advance "Index" +1, +2, +0 while CurrTag is +0, +1, +2\r
1048 //\r
1049 GetNumericHeader (\r
1050 &FormTags->Tags[CurrTag],\r
1051 RawFormSet,\r
1052 (UINT16) (Index + TagLength),\r
1053 (UINT16) 0,\r
1054 FileFormTags,\r
1055 CurrentVariable\r
1056 );\r
1057\r
1058 //\r
1059 // The current language selected + the Date operand\r
1060 //\r
1061 FormTags->Tags[CurrTag + 1].Operand = RawFormSet[Index];\r
1062 GetNumericHeader (\r
1063 &FormTags->Tags[CurrTag + 1],\r
1064 RawFormSet,\r
1065 (UINT16) (Index + TagLength + RawFormSet[Index + TagLength + 1]),\r
1066 (UINT16) 0,\r
1067 FileFormTags,\r
1068 CurrentVariable\r
1069 );\r
1070\r
1071 //\r
1072 // The current language selected + the Date operand\r
1073 //\r
1074 FormTags->Tags[CurrTag + 2].Operand = RawFormSet[Index];\r
1075 GetNumericHeader (&FormTags->Tags[CurrTag + 2], RawFormSet, Index, (UINT16) 1, FileFormTags, CurrentVariable);\r
1076\r
1077 CurrTag = (INT16) (CurrTag + 2);\r
1078\r
1079 Index = (UINT16) (Index + TagLength);\r
1080 //\r
1081 // get the length\r
1082 //\r
1083 TagLength = RawFormSet[Index + 1];\r
1084 Index = (UINT16) (Index + TagLength);\r
1085 //\r
1086 // get the length\r
1087 //\r
1088 TagLength = RawFormSet[Index + 1];\r
1089 break;\r
1090\r
1091 case EFI_IFR_TIME_OP:\r
1092 GetNumericHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, (UINT16) 0, FileFormTags, CurrentVariable);\r
1093\r
1094 if (Count == 2) {\r
1095 //\r
1096 // Override the GetQuestionHeader information - date/time are treated very differently\r
1097 //\r
1098 FormTags->Tags[CurrTag].NumberOfLines = 1;\r
1099 Count = 0;\r
1100 } else {\r
1101 //\r
1102 // The premise is that every date/time op-code have 3 elements, the first 2 have 0 lines\r
1103 // associated with them, and the third has 1 line to allow to space beyond the choice.\r
1104 //\r
1105 Count++;\r
1106 }\r
1107 break;\r
1108\r
1109 case EFI_IFR_PASSWORD_OP:\r
1110 case EFI_IFR_STRING_OP:\r
1111 GetQuestionHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, FileFormTags, CurrentVariable);\r
1112 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);\r
1113 break;\r
1114\r
1115 case EFI_IFR_SUPPRESS_IF_OP:\r
1116 case EFI_IFR_GRAYOUT_IF_OP:\r
1117 InconsistentTags->Operand = ((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Header.OpCode;\r
1118 gConsistencyId++;\r
1119\r
1120 //\r
1121 // Since this op-code doesn't use the next field(s), initialize them with something invalid.\r
1122 // Unfortunately 0 is a valid offset value for a QuestionId\r
1123 //\r
1124 InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE;\r
1125 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;\r
1126\r
1127 //\r
1128 // Test for an allocated buffer. If already allocated this is due to having called this routine\r
1129 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize\r
1130 // the tag structure with current values from the NV\r
1131 //\r
1132 if (InconsistentTags->Next == NULL) {\r
1133 AddNextInconsistentTag (&InconsistentTags);\r
1134 break;\r
1135 }\r
1136\r
1137 InconsistentTags = InconsistentTags->Next;\r
1138 break;\r
1139\r
1140 case EFI_IFR_FORM_SET_OP:\r
1141 CopyMem (\r
1142 &FormTags->Tags[CurrTag].GuidValue,\r
1143 &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->Guid,\r
1144 sizeof (EFI_GUID)\r
1145 );\r
1146 CopyMem (\r
1147 &FormTags->Tags[CurrTag].CallbackHandle,\r
1148 &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->CallbackHandle,\r
1149 sizeof (EFI_PHYSICAL_ADDRESS)\r
1150 );\r
1151 CopyMem (&FormTags->Tags[CurrTag].Class, &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->Class, sizeof (UINT8));\r
1152 CopyMem (\r
1153 &FormTags->Tags[CurrTag].SubClass,\r
1154 &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->SubClass,\r
1155 sizeof (UINT8)\r
1156 );\r
1157 CopyMem (\r
1158 &FormTags->Tags[CurrTag].NvDataSize,\r
1159 &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->NvDataSize,\r
1160 sizeof (UINT16)\r
1161 );\r
1162 Class = ((EFI_IFR_FORM_SET *) &RawFormSet[Index])->Class;\r
1163 SubClass = ((EFI_IFR_FORM_SET *) &RawFormSet[Index])->SubClass;\r
1164 //\r
1165 // If the formset has a size value, that means someone must be using this, so create a variable\r
1166 // We also shall reserve the formid of 0 for this specific purpose.\r
1167 //\r
1168 if ((FileFormTags->VariableDefinitions == NULL) && (FormTags->Tags[CurrTag].NvDataSize > 0)) {\r
1169 FileFormTags->VariableDefinitions = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION));\r
1170 ASSERT (FileFormTags->VariableDefinitions != NULL);\r
1171 IfrToFormTag (\r
1172 RawFormSet[Index],\r
1173 &FormTags->Tags[CurrTag],\r
1174 (VOID *) &RawFormSet[Index],\r
1175 FileFormTags->VariableDefinitions\r
1176 );\r
1177 } else {\r
1178 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);\r
1179 }\r
1180 break;\r
1181\r
1182 case EFI_IFR_BANNER_OP:\r
1183 if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {\r
1184 TempValue = 0;\r
1185 CopyMem (&TempValue, &((EFI_IFR_BANNER *) &RawFormSet[Index])->Alignment, sizeof (UINT8));\r
1186 //\r
1187 // If this is the special timeout value, we will dynamically figure out where to put it\r
1188 // Also the least significant byte refers to the TimeOut desired.\r
1189 //\r
1190 if (TempValue == EFI_IFR_BANNER_TIMEOUT) {\r
1191 CopyMem (&FrontPageTimeOutTitle, &((EFI_IFR_BANNER *) &RawFormSet[Index])->Title, sizeof (UINT16));\r
1192 if (FrontPageTimeOutValue != (INT16) -1) {\r
1193 CopyMem (&FrontPageTimeOutValue, &((EFI_IFR_BANNER *) &RawFormSet[Index])->LineNumber, sizeof (UINT16));\r
1194 }\r
1195 break;\r
1196 }\r
1197\r
1198 CopyMem (\r
1199 &BannerData->Banner[((EFI_IFR_BANNER *) &RawFormSet[Index])->LineNumber][\r
1200 ((EFI_IFR_BANNER *) &RawFormSet[Index])->Alignment],\r
1201 &((EFI_IFR_BANNER *) &RawFormSet[Index])->Title,\r
1202 sizeof (STRING_REF)\r
1203 );\r
1204 }\r
1205 break;\r
1206\r
1207 case EFI_IFR_INCONSISTENT_IF_OP:\r
1208 CopyMem (\r
1209 &FormTags->Tags[CurrTag].Text,\r
1210 &((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Popup,\r
1211 sizeof (UINT16)\r
1212 );\r
1213 gConsistencyId++;\r
1214\r
1215 InconsistentTags->Operand = ((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Header.OpCode;\r
1216 CopyMem (&InconsistentTags->Popup, &((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Popup, sizeof (UINT16));\r
1217\r
1218 //\r
1219 // Since this op-code doesn't use the next field(s), initialize them with something invalid.\r
1220 // Unfortunately 0 is a valid offset value for a QuestionId\r
1221 //\r
1222 InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE;\r
1223 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;\r
1224\r
1225 InconsistentTags->VariableNumber = CurrentVariable;\r
1226\r
1227 //\r
1228 // Test for an allocated buffer. If already allocated this is due to having called this routine\r
1229 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize\r
1230 // the tag structure with current values from the NV\r
1231 //\r
1232 if (InconsistentTags->Next == NULL) {\r
1233 AddNextInconsistentTag (&InconsistentTags);\r
1234 break;\r
1235 }\r
1236\r
1237 InconsistentTags = InconsistentTags->Next;\r
1238 break;\r
1239\r
1240 case EFI_IFR_EQ_ID_VAL_OP:\r
1241 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);\r
1242\r
1243 InconsistentTags->Operand = ((EFI_IFR_EQ_ID_VAL *) &RawFormSet[Index])->Header.OpCode;\r
1244 CopyMem (&InconsistentTags->Value, &((EFI_IFR_EQ_ID_VAL *) &RawFormSet[Index])->Value, sizeof (UINT16));\r
1245 CopyMem (\r
1246 &InconsistentTags->QuestionId1,\r
1247 &((EFI_IFR_EQ_ID_VAL *) &RawFormSet[Index])->QuestionId,\r
1248 sizeof (UINT16)\r
1249 );\r
1250\r
1251 //\r
1252 // Since this op-code doesn't use the next field(s), initialize them with something invalid.\r
1253 // Unfortunately 0 is a valid offset value for a QuestionId\r
1254 //\r
1255 InconsistentTags->Width = FormTags->Tags[CurrTag].StorageWidth;\r
1256 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;\r
1257 InconsistentTags->ConsistencyId = gConsistencyId;\r
1258 FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;\r
1259\r
1260 InconsistentTags->VariableNumber = CurrentVariable;\r
1261\r
1262 //\r
1263 // Test for an allocated buffer. If already allocated this is due to having called this routine\r
1264 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize\r
1265 // the tag structure with current values from the NV\r
1266 //\r
1267 if (InconsistentTags->Next == NULL) {\r
1268 AddNextInconsistentTag (&InconsistentTags);\r
1269 break;\r
1270 }\r
1271\r
1272 InconsistentTags = InconsistentTags->Next;\r
1273 break;\r
1274\r
1275 case EFI_IFR_EQ_VAR_VAL_OP:\r
1276 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);\r
1277\r
1278 InconsistentTags->Operand = ((EFI_IFR_EQ_VAR_VAL *) &RawFormSet[Index])->Header.OpCode;\r
1279 CopyMem (&InconsistentTags->Value, &((EFI_IFR_EQ_VAR_VAL *) &RawFormSet[Index])->Value, sizeof (UINT16));\r
1280 CopyMem (\r
1281 &InconsistentTags->QuestionId1,\r
1282 &((EFI_IFR_EQ_VAR_VAL *) &RawFormSet[Index])->VariableId,\r
1283 sizeof (UINT16)\r
1284 );\r
1285\r
1286 //\r
1287 // Since this op-code doesn't use the next field(s), initialize them with something invalid.\r
1288 // Unfortunately 0 is a valid offset value for a QuestionId\r
1289 //\r
1290 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;\r
1291 InconsistentTags->ConsistencyId = gConsistencyId;\r
1292 FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;\r
1293\r
1294 InconsistentTags->VariableNumber = CurrentVariable;\r
1295\r
1296 //\r
1297 // Test for an allocated buffer. If already allocated this is due to having called this routine\r
1298 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize\r
1299 // the tag structure with current values from the NV\r
1300 //\r
1301 if (InconsistentTags->Next == NULL) {\r
1302 AddNextInconsistentTag (&InconsistentTags);\r
1303 break;\r
1304 }\r
1305\r
1306 InconsistentTags = InconsistentTags->Next;\r
1307 break;\r
1308\r
1309 case EFI_IFR_EQ_ID_ID_OP:\r
1310 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);\r
1311\r
1312 InconsistentTags->Operand = ((EFI_IFR_EQ_ID_ID *) &RawFormSet[Index])->Header.OpCode;\r
1313 CopyMem (\r
1314 &InconsistentTags->QuestionId1,\r
1315 &((EFI_IFR_EQ_ID_ID *) &RawFormSet[Index])->QuestionId1,\r
1316 sizeof (UINT16)\r
1317 );\r
1318 CopyMem (\r
1319 &InconsistentTags->QuestionId2,\r
1320 &((EFI_IFR_EQ_ID_ID *) &RawFormSet[Index])->QuestionId2,\r
1321 sizeof (UINT16)\r
1322 );\r
1323\r
1324 InconsistentTags->Width = FormTags->Tags[CurrTag].StorageWidth;\r
1325 InconsistentTags->ConsistencyId = gConsistencyId;\r
1326 FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;\r
1327\r
1328 InconsistentTags->VariableNumber = CurrentVariable;\r
1329 InconsistentTags->VariableNumber2 = CurrentVariable2;\r
1330\r
1331 //\r
1332 // Test for an allocated buffer. If already allocated this is due to having called this routine\r
1333 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize\r
1334 // the tag structure with current values from the NV\r
1335 //\r
1336 if (InconsistentTags->Next == NULL) {\r
1337 AddNextInconsistentTag (&InconsistentTags);\r
1338 break;\r
1339 }\r
1340\r
1341 InconsistentTags = InconsistentTags->Next;\r
1342 break;\r
1343\r
1344 case EFI_IFR_AND_OP:\r
1345 case EFI_IFR_OR_OP:\r
1346 case EFI_IFR_NOT_OP:\r
1347 case EFI_IFR_GT_OP:\r
1348 case EFI_IFR_GE_OP:\r
1349 case EFI_IFR_TRUE_OP:\r
1350 case EFI_IFR_FALSE_OP:\r
1351 InconsistentTags->Operand = ((EFI_IFR_NOT *) &RawFormSet[Index])->Header.OpCode;\r
1352\r
1353 //\r
1354 // Since this op-code doesn't use the next field(s), initialize them with something invalid.\r
1355 // Unfortunately 0 is a valid offset value for a QuestionId\r
1356 //\r
1357 \r
1358 //\r
1359 // Reserve INVALID_OFFSET_VALUE - 1 for TRUE or FALSE because they are inconsistency tags also, but\r
1360 // have no coresponding id. The examination of id is needed by evaluating boolean expression.\r
1361 //\r
1362 if (RawFormSet[Index] == EFI_IFR_TRUE_OP ||\r
1363 RawFormSet[Index] == EFI_IFR_FALSE_OP) {\r
1364 InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE - 1;\r
1365 } else {\r
1366 InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE;\r
1367 }\r
1368 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;\r
1369 InconsistentTags->ConsistencyId = gConsistencyId;\r
1370 FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;\r
1371\r
1372 //\r
1373 // Test for an allocated buffer. If already allocated this is due to having called this routine\r
1374 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize\r
1375 // the tag structure with current values from the NV\r
1376 //\r
1377 if (InconsistentTags->Next == NULL) {\r
1378 AddNextInconsistentTag (&InconsistentTags);\r
1379 break;\r
1380 }\r
1381\r
1382 InconsistentTags = InconsistentTags->Next;\r
1383 break;\r
1384\r
1385 case EFI_IFR_EQ_ID_LIST_OP:\r
1386 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);\r
1387\r
1388 InconsistentTags->Operand = ((EFI_IFR_EQ_ID_LIST *) &RawFormSet[Index])->Header.OpCode;\r
1389 CopyMem (\r
1390 &InconsistentTags->QuestionId1,\r
1391 &((EFI_IFR_EQ_ID_LIST *) &RawFormSet[Index])->QuestionId,\r
1392 sizeof (UINT16)\r
1393 );\r
1394 CopyMem (\r
1395 &InconsistentTags->ListLength,\r
1396 &((EFI_IFR_EQ_ID_LIST *) &RawFormSet[Index])->ListLength,\r
1397 sizeof (UINT16)\r
1398 );\r
1399 InconsistentTags->ValueList = FormTags->Tags[CurrTag].IntList;\r
1400\r
1401 //\r
1402 // Since this op-code doesn't use the next field(s), initialize them with something invalid.\r
1403 // Unfortunately 0 is a valid offset value for a QuestionId\r
1404 //\r
1405 InconsistentTags->Width = FormTags->Tags[CurrTag].StorageWidth;\r
1406 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;\r
1407 InconsistentTags->ConsistencyId = gConsistencyId;\r
1408 FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;\r
1409\r
1410 //\r
1411 // Test for an allocated buffer. If already allocated this is due to having called this routine\r
1412 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize\r
1413 // the tag structure with current values from the NV\r
1414 //\r
1415 if (InconsistentTags->Next == NULL) {\r
1416 AddNextInconsistentTag (&InconsistentTags);\r
1417 break;\r
1418 }\r
1419\r
1420 InconsistentTags = InconsistentTags->Next;\r
1421 break;\r
1422\r
1423 case EFI_IFR_END_IF_OP:\r
1424 InconsistentTags->Operand = ((EFI_IFR_END_EXPR *) &RawFormSet[Index])->Header.OpCode;\r
1425\r
1426 //\r
1427 // Since this op-code doesn't use the next field(s), initialize them with something invalid.\r
1428 // Unfortunately 0 is a valid offset value for a QuestionId\r
1429 //\r
1430 InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE;\r
1431 InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;\r
1432\r
1433 //\r
1434 // Test for an allocated buffer. If already allocated this is due to having called this routine\r
1435 // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize\r
1436 // the tag structure with current values from the NV\r
1437 //\r
1438 if (InconsistentTags->Next == NULL) {\r
1439 AddNextInconsistentTag (&InconsistentTags);\r
1440 break;\r
1441 }\r
1442\r
1443 InconsistentTags = InconsistentTags->Next;\r
1444 break;\r
1445\r
1446 case EFI_IFR_END_ONE_OF_OP:\r
1447 break;\r
1448\r
1449 default:\r
1450 break;\r
1451 }\r
1452 //\r
1453 // End of switch\r
1454 //\r
1455 // Per spec., we ignore ops that we don't know how to deal with. Skip to next tag\r
1456 //\r
1457 Index = (UINT16) (Index + TagLength);\r
1458 }\r
1459 //\r
1460 // End of Index\r
1461 //\r
1462 // When we eventually exit, make sure we mark the last tag with an op-code\r
1463 //\r
1464 FormTags->Tags[CurrTag].Operand = RawFormSet[Index];\r
1465\r
1466 IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);\r
1467\r
1468 //\r
1469 // Place this as an end of the database marker\r
1470 //\r
1471 InconsistentTags->Operand = 0xFF;\r
1472\r
1473 //\r
1474 // This is the Head of the linked list of pages. Each page is an array of tags\r
1475 //\r
1476 FormTags = &FileFormTags->FormTags;\r
1477 InconsistentTags = FileFormTags->InconsistentTags;\r
1478\r
1479 for (; InconsistentTags->Operand != 0xFF;) {\r
1480 if (InconsistentTags->QuestionId1 != INVALID_OFFSET_VALUE) {\r
1481 //\r
1482 // Search the tags for the tag which corresponds to this ID\r
1483 //\r
1484 for (CurrTag = 0; FormTags->Tags[0].Operand != EFI_IFR_END_FORM_SET_OP; CurrTag++) {\r
1485 //\r
1486 // If we hit the end of a form, go to the next set of Tags.\r
1487 // Remember - EndFormSet op-codes sit on their own page after an end form.\r
1488 //\r
1489 if (FormTags->Tags[CurrTag].Operand == EFI_IFR_END_FORM_OP) {\r
1490 //\r
1491 // Reset the CurrTag value (it will be incremented, after this case statement\r
1492 // so set to a negative one so that we get the desired effect.) Fish can beat me later.\r
1493 //\r
1494 CurrTag = -1;\r
1495 FormTags = FormTags->Next;\r
1496 continue;\r
1497 }\r
1498\r
1499 if (FormTags->Tags[CurrTag].Id == InconsistentTags->QuestionId1) {\r
1500 FormTags->Tags[CurrTag].Consistency++;\r
1501 }\r
1502 }\r
1503 }\r
1504\r
1505 FormTags = &FileFormTags->FormTags;\r
1506\r
1507 if (InconsistentTags->QuestionId2 != INVALID_OFFSET_VALUE) {\r
1508 //\r
1509 // Search the tags for the tag which corresponds to this ID\r
1510 //\r
1511 for (CurrTag = 0; FormTags->Tags[CurrTag].Operand != EFI_IFR_END_FORM_SET_OP; CurrTag++) {\r
1512 //\r
1513 // If we hit the end of a form, go to the next set of Tags.\r
1514 // Remember - EndFormSet op-codes sit on their own page after an end form.\r
1515 //\r
1516 if (FormTags->Tags[CurrTag].Operand == EFI_IFR_END_FORM_OP) {\r
1517 //\r
1518 // Reset the CurrTag value (it will be incremented, after this case statement\r
1519 // so set to a negative one so that we get the desired effect.) Fish can beat me later.\r
1520 //\r
1521 CurrTag = -1;\r
1522 FormTags = FormTags->Next;\r
1523 continue;\r
1524 }\r
1525\r
1526 if (FormTags->Tags[CurrTag].Id == InconsistentTags->QuestionId2) {\r
1527 FormTags->Tags[CurrTag].Consistency++;\r
1528 }\r
1529 }\r
1530 }\r
1531\r
1532 InconsistentTags = InconsistentTags->Next;\r
1533 }\r
1534\r
1535 return Status;\r
1536}\r
1537\r
1538VOID\r
1539InitPage (\r
1540 VOID\r
1541 )\r
1542{\r
1543 CHAR16 *HomePageString;\r
1544 CHAR16 *HomeEscapeString;\r
1545\r
1546 //\r
1547 // Displays the Header and Footer borders\r
1548 //\r
1549 DisplayPageFrame ();\r
1550\r
1551 HomePageString = GetToken (STRING_TOKEN (HOME_PAGE_TITLE), gHiiHandle);\r
1552 HomeEscapeString = GetToken (STRING_TOKEN (HOME_ESCAPE_STRING), gHiiHandle);\r
1553\r
1554 gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
1555 //\r
1556 // PrintStringAt ((gScreenDimensions.RightColumn - GetStringWidth(HomePageString)/2)/2, 1, HomePageString);\r
1557 //\r
1558 PrintStringAt (\r
1559 (gScreenDimensions.RightColumn + gScreenDimensions.LeftColumn - GetStringWidth (HomePageString) / 2) / 2,\r
1560 1,\r
1561 HomePageString\r
1562 );\r
1563 PrintAt (\r
1564 gScreenDimensions.LeftColumn + 2,\r
1565 gScreenDimensions.BottomRow - 3,\r
1566 (CHAR16 *) L"%c%c%s",\r
1567 ARROW_UP,\r
1568 ARROW_DOWN,\r
1569 gMoveHighlight\r
1570 );\r
1571 PrintAt (\r
1572 gScreenDimensions.RightColumn - (GetStringWidth (HomeEscapeString) / 2) - 2,\r
1573 gScreenDimensions.BottomRow - 3,\r
1574 (CHAR16 *) L" %s",\r
1575 HomeEscapeString\r
1576 );\r
1577 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
1578 gBS->FreePool (HomeEscapeString);\r
1579 gBS->FreePool (HomePageString);\r
1580\r
1581 return ;\r
1582}\r
1583\r
1584CHAR16 *\r
1585GetToken (\r
1586 IN STRING_REF Token,\r
1587 IN EFI_HII_HANDLE HiiHandle\r
1588 )\r
1589/*++\r
1590\r
1591Routine Description:\r
1592 \r
1593 Get the string based on the TokenID and HII Handle.\r
1594\r
1595Arguments:\r
1596\r
1597 Token - The Token ID.\r
1598 HiiHandle - Handle of Ifr to be fetched.\r
1599 \r
1600Returns:\r
1601\r
1602 The output string.\r
1603\r
1604--*/\r
1605{\r
1606 CHAR16 *Buffer;\r
1607 UINTN BufferLength;\r
1608 EFI_STATUS Status;\r
1609\r
1610 //\r
1611 // Set default string size assumption at no more than 256 bytes\r
1612 //\r
1613 BufferLength = 0x100;\r
1614\r
1615 Buffer = AllocateZeroPool (BufferLength);\r
1616 ASSERT (Buffer != NULL);\r
1617\r
1618 Status = Hii->GetString (Hii, HiiHandle, Token, TRUE, NULL, &BufferLength, Buffer);\r
1619\r
1620 if (EFI_ERROR (Status)) {\r
1621 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1622 //\r
1623 // Free the old pool\r
1624 //\r
1625 gBS->FreePool (Buffer);\r
1626\r
1627 //\r
1628 // Allocate new pool with correct value\r
1629 //\r
1630 Buffer = AllocatePool (BufferLength);\r
1631 ASSERT (Buffer != NULL);\r
1632\r
1633 Status = Hii->GetString (Hii, HiiHandle, Token, TRUE, NULL, &BufferLength, Buffer);\r
1634\r
1635 if (!EFI_ERROR (Status)) {\r
1636 return Buffer;\r
1637 }\r
1638 }\r
1639\r
1640 ASSERT_EFI_ERROR (Status);\r
1641 }\r
1642\r
1643 return Buffer;\r
1644}\r
1645\r
1cc8ee78 1646STATIC\r
878ddf1f 1647EFI_STATUS\r
1648PopulateHomePage (\r
1649 IN UINTN NumberOfIfrImages,\r
1650 IN EFI_FILE_FORM_TAGS *FileFormTagsHead\r
1651 )\r
1652{\r
1653 EFI_STATUS Status;\r
1654 UINTN Index;\r
1655 EFI_IFR_BINARY *IfrBinary;\r
1656 CHAR16 *StringPtr;\r
1657 EFI_FILE_FORM_TAGS *FileFormTags;\r
1658 EFI_FORM_TAGS LocalTags;\r
1659\r
1660 FileFormTags = FileFormTagsHead;\r
1661\r
1662 UiInitMenu ();\r
1663\r
1664 Status = EFI_SUCCESS;\r
1665\r
1666 //\r
1667 // If there are no images\r
1668 //\r
1669 if (NumberOfIfrImages == 0) {\r
1670 Status = EFI_NO_MEDIA;\r
1671 return Status;\r
1672 }\r
1673 //\r
1674 // IfrBinary points to the beginning of the Binary data linked-list\r
1675 //\r
1676 IfrBinary = gBinaryDataHead;\r
1677\r
1678 //\r
1679 // Print the entries which were in the default language.\r
1680 //\r
1681 for (Index = 0; Index < NumberOfIfrImages; Index++) {\r
1682 LocalTags = FileFormTags->FormTags;\r
1683\r
1684 //\r
1685 // Populate the Menu\r
1686 //\r
1687 StringPtr = GetToken (IfrBinary->TitleToken, IfrBinary->Handle);\r
1688\r
1689 //\r
1690 // If the default language doesn't exist, don't add a menu option yet\r
1691 //\r
1692 if (StringPtr[0] != CHAR_NULL) {\r
1693 //\r
1694 // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do\r
1695 // it in UiFreeMenu.\r
1696 //\r
1697 UiAddMenuOption (StringPtr, IfrBinary->Handle, LocalTags.Tags, IfrBinary->FormBinary, Index);\r
1698 }\r
1699 //\r
1700 // Advance to the next HII handle\r
1701 //\r
1702 IfrBinary = IfrBinary->Next;\r
1703 FileFormTags = FileFormTags->NextFile;\r
1704 }\r
1705\r
1706 return Status;\r
1707}\r
1708\r
1709UI_MENU_OPTION *\r
1710DisplayHomePage (\r
1711 IN UINTN NumberOfIfrImages,\r
1712 IN EFI_FILE_FORM_TAGS *FileFormTagsHead,\r
1713 IN UINT8 *CallbackData\r
1714 )\r
1715{\r
1716 EFI_STATUS Status;\r
1717 UI_MENU_OPTION *Selection;\r
1718\r
1719 //\r
1720 // This prints the basic home page template which the user sees\r
1721 //\r
1722 InitPage ();\r
1723\r
1724 Status = PopulateHomePage (NumberOfIfrImages, FileFormTagsHead);\r
1725\r
1726 if (EFI_ERROR (Status)) {\r
1727 Selection = NULL;\r
1728 return Selection;\r
1729 }\r
1730\r
1731 Selection = UiDisplayMenu (FALSE, FileFormTagsHead, (EFI_IFR_DATA_ARRAY *) CallbackData);\r
1732\r
1733 return Selection;\r
1734}\r
1735\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 gBS->FreePool (VariableDefinition->NvRamMap);\r
1961 gBS->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 gBS->FreePool (VariableDefinition->NvRamMap);\r
2016 gBS->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 gBS->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
2047EFI_STATUS\r
2048GetIfrBinaryData (\r
2049 IN EFI_HII_PROTOCOL *Hii,\r
2050 IN EFI_HII_HANDLE HiiHandle,\r
2051 IN EFI_IFR_PACKET *Packet,\r
2052 IN OUT EFI_IFR_BINARY *BinaryData\r
2053 )\r
2054/*++\r
2055\r
2056Routine Description:\r
2057 Fetch the Ifr binary data.\r
2058\r
2059Arguments:\r
2060 Hii - Point to HII protocol.\r
2061 HiiHandle - Handle of Ifr to be fetched.\r
2062 Packet - Pointer to IFR packet.\r
2063 BinaryData - Buffer to copy the string into\r
2064 \r
2065Returns:\r
2066 Returns the number of CHAR16 characters that were copied into the OutputString buffer.\r
2067\r
2068\r
2069--*/\r
2070{\r
2071 EFI_STATUS Status;\r
2072 EFI_HII_PACKAGES *PackageList;\r
2073 UINTN BufferSize;\r
2074 VOID *Buffer;\r
2075 UINT8 *RawFormBinary;\r
2076 EFI_IFR_FORM_SET *FormOp;\r
2077 UINT16 Index;\r
2078 UINT16 Index2;\r
2079 UINT16 TitleToken;\r
2080\r
2081 //\r
2082 // Initialize the TitleToken to 0 just in case not found\r
2083 //\r
2084 TitleToken = 0;\r
2085\r
2086 //\r
2087 // Try for a 32K Buffer\r
2088 //\r
2089 BufferSize = 0x8000;\r
2090\r
2091 //\r
2092 // Allocate memory for our Form binary\r
2093 //\r
2094 Buffer = AllocateZeroPool (BufferSize);\r
2095 ASSERT (Buffer);\r
2096\r
2097 if (Packet == NULL) {\r
2098 Status = Hii->GetForms (Hii, HiiHandle, 0, &BufferSize, Buffer);\r
2099\r
2100 if (Status == EFI_BUFFER_TOO_SMALL) {\r
2101\r
2102 gBS->FreePool (Buffer);\r
2103\r
2104 //\r
2105 // Allocate memory for our Form binary\r
2106 //\r
2107 Buffer = AllocatePool (BufferSize);\r
2108 ASSERT (Buffer);\r
2109\r
2110 Status = Hii->GetForms (Hii, HiiHandle, 0, &BufferSize, Buffer);\r
2111 }\r
2112 } else {\r
2113 //\r
2114 // Copies the data to local usable buffer\r
2115 //\r
2116 CopyMem (Buffer, Packet->IfrData, Packet->IfrData->Header.Length);\r
2117\r
2118 //\r
2119 // Register the string data with HII\r
2120 //\r
2121 PackageList = PreparePackages (2, NULL, Packet->IfrData, Packet->StringData);\r
2122\r
2123 Status = Hii->NewPack (Hii, PackageList, &HiiHandle);\r
2124\r
2125 gBS->FreePool (PackageList);\r
2126 }\r
2127\r
2128 if (EFI_ERROR (Status)) {\r
2129 return Status;\r
2130 }\r
2131 //\r
2132 // We now have the IFR binary in our Buffer\r
2133 //\r
2134 BinaryData->IfrPackage = Buffer;\r
2135 RawFormBinary = (UINT8 *) ((CHAR8 *) (Buffer) + sizeof (EFI_HII_PACK_HEADER));\r
2136 BinaryData->FormBinary = (UINT8 *) ((CHAR8 *) (Buffer) + sizeof (EFI_HII_PACK_HEADER));\r
2137 BinaryData->Handle = HiiHandle;\r
2138\r
2139 //\r
2140 // If a packet was passed in, remove the string data when exiting.\r
2141 //\r
2142 if (Packet != NULL) {\r
2143 BinaryData->UnRegisterOnExit = TRUE;\r
2144 } else {\r
2145 BinaryData->UnRegisterOnExit = FALSE;\r
2146 }\r
2147 //\r
2148 // Walk through the FormSet Opcodes looking for the FormSet opcode\r
2149 // If we hit EFI_IFR_END_SET_OP we know we hit the end of the FormSet.\r
2150 //\r
2151 for (Index = 0; RawFormBinary[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
2152 FormOp = (EFI_IFR_FORM_SET *) &RawFormBinary[Index];\r
2153 Index = (UINT16) (Index + FormOp->Header.Length);\r
2154\r
2155 if (FormOp->Header.OpCode == EFI_IFR_FORM_SET_OP) {\r
2156 TitleToken = FormOp->FormSetTitle;\r
2157 //\r
2158 // If displaying FrontPage - set the flag signifying it\r
2159 //\r
2160 switch (FormOp->SubClass) {\r
2161 case EFI_FRONT_PAGE_SUBCLASS:\r
2162 FrontPageHandle = HiiHandle;\r
2163\r
2164 default:\r
2165 gClassOfVfr = FormOp->SubClass;\r
2166 }\r
2167 //\r
2168 // Match GUID to find out the function key setting. If match fail, use the default setting.\r
2169 //\r
2170 for (Index2 = 0; Index2 < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index2++) {\r
2171 if (CompareGuid ((EFI_GUID *)(UINTN)&FormOp->Guid, &(gFunctionKeySettingTable[Index2].FormSetGuid))) {\r
2172 //\r
2173 // Update the function key setting.\r
2174 //\r
2175 gFunctionKeySetting = gFunctionKeySettingTable[Index2].KeySetting;\r
2176 //\r
2177 // Function key prompt can not be displayed if the function key has been disabled.\r
2178 //\r
2179 if ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE) {\r
2180 gFunctionOneString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2181 }\r
2182\r
2183 if ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO) {\r
2184 gFunctionTwoString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2185 }\r
2186\r
2187 if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {\r
2188 gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2189 }\r
2190\r
2191 if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {\r
2192 gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2193 }\r
2194 }\r
2195 }\r
2196 }\r
2197 }\r
2198\r
2199 BinaryData->TitleToken = TitleToken;\r
2200\r
2201 return Status;\r
2202}\r
2203\r
2204EFI_HANDLE PrintHandle = NULL;\r
2205EFI_PRINT_PROTOCOL mPrintProtocol = { UnicodeVSPrint };\r
2206\r
2207EFI_STATUS\r
2208InstallPrint (\r
2209 VOID\r
2210 )\r
2211{\r
2212 return gBS->InstallProtocolInterface (\r
2213 &PrintHandle,\r
2214 &gEfiPrintProtocolGuid,\r
2215 EFI_NATIVE_INTERFACE,\r
2216 &mPrintProtocol\r
2217 );\r
2218}\r