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