]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
Remove SafeFreePool from MemoryAllocationLib as this API's name is misleading. Its...
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Setup.c
CommitLineData
7936fb6a 1/** @file\r
2Entry and initialization module for the browser.\r
3\r
4Copyright (c) 2007 - 2008, Intel Corporation\r
5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "Setup.h"\r
16#include "Ui.h"\r
17\r
18\r
19SETUP_DRIVER_PRIVATE_DATA mPrivateData = {\r
20 SETUP_DRIVER_SIGNATURE,\r
21 NULL,\r
22 {\r
23 SendForm,\r
24 BrowserCallback\r
25 },\r
26 {\r
ebe43565 27 UnicodeVSPrint,\r
28 UnicodeVSPrintAsciiFormat,\r
29 UnicodeValueToString, \r
30 AsciiVSPrint, \r
31 AsciiVSPrintUnicodeFormat,\r
32 AsciiValueToString\r
7936fb6a 33 }\r
34};\r
35\r
36EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;\r
37EFI_HII_STRING_PROTOCOL *mHiiString;\r
38EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;\r
39\r
40BANNER_DATA *BannerData;\r
41EFI_HII_HANDLE FrontPageHandle;\r
42UINTN gClassOfVfr;\r
43UINTN gFunctionKeySetting;\r
44BOOLEAN gResetRequired;\r
45BOOLEAN gNvUpdateRequired;\r
46EFI_HII_HANDLE gHiiHandle;\r
7936fb6a 47UINT16 gDirection;\r
48EFI_SCREEN_DESCRIPTOR gScreenDimensions;\r
49BOOLEAN gUpArrow;\r
50BOOLEAN gDownArrow;\r
51\r
52//\r
53// Browser Global Strings\r
54//\r
55CHAR16 *gFunctionOneString;\r
56CHAR16 *gFunctionTwoString;\r
57CHAR16 *gFunctionNineString;\r
58CHAR16 *gFunctionTenString;\r
59CHAR16 *gEnterString;\r
60CHAR16 *gEnterCommitString;\r
61CHAR16 *gEscapeString;\r
62CHAR16 *gSaveFailed;\r
63CHAR16 *gMoveHighlight;\r
64CHAR16 *gMakeSelection;\r
65CHAR16 *gDecNumericInput;\r
66CHAR16 *gHexNumericInput;\r
67CHAR16 *gToggleCheckBox;\r
68CHAR16 *gPromptForData;\r
69CHAR16 *gPromptForPassword;\r
70CHAR16 *gPromptForNewPassword;\r
71CHAR16 *gConfirmPassword;\r
72CHAR16 *gConfirmError;\r
73CHAR16 *gPassowordInvalid;\r
74CHAR16 *gPressEnter;\r
75CHAR16 *gEmptyString;\r
76CHAR16 *gAreYouSure;\r
77CHAR16 *gYesResponse;\r
78CHAR16 *gNoResponse;\r
79CHAR16 *gMiniString;\r
80CHAR16 *gPlusString;\r
81CHAR16 *gMinusString;\r
82CHAR16 *gAdjustNumber;\r
ebe43565 83CHAR16 *gSaveChanges;\r
7936fb6a 84\r
85CHAR16 gPromptBlockWidth;\r
86CHAR16 gOptionBlockWidth;\r
87CHAR16 gHelpBlockWidth;\r
88\r
89EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
90EFI_GUID gSetupBrowserGuid = {\r
91 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}\r
92};\r
93\r
94FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {\r
95 //\r
96 // Boot Manager\r
97 //\r
98 {\r
99 {\r
100 0x847bc3fe,\r
101 0xb974,\r
102 0x446d,\r
103 {\r
104 0x94,\r
105 0x49,\r
106 0x5a,\r
107 0xd5,\r
108 0x41,\r
109 0x2e,\r
110 0x99,\r
111 0x3b\r
112 }\r
113 },\r
114 NONE_FUNCTION_KEY_SETTING\r
115 },\r
116 //\r
117 // Device Manager\r
118 //\r
119 {\r
120 {\r
121 0x3ebfa8e6,\r
122 0x511d,\r
123 0x4b5b,\r
124 {\r
125 0xa9,\r
126 0x5f,\r
127 0xfb,\r
128 0x38,\r
129 0x26,\r
130 0xf,\r
131 0x1c,\r
132 0x27\r
133 }\r
134 },\r
135 NONE_FUNCTION_KEY_SETTING\r
136 },\r
137 //\r
138 // BMM FormSet.\r
139 //\r
140 {\r
141 {\r
142 0x642237c7,\r
143 0x35d4,\r
144 0x472d,\r
145 {\r
146 0x83,\r
147 0x65,\r
148 0x12,\r
149 0xe0,\r
150 0xcc,\r
151 0xf2,\r
152 0x7a,\r
153 0x22\r
154 }\r
155 },\r
156 NONE_FUNCTION_KEY_SETTING\r
157 },\r
158 //\r
159 // BMM File Explorer FormSet.\r
160 //\r
161 {\r
162 {\r
163 0x1f2d63e1,\r
164 0xfebd,\r
165 0x4dc7,\r
166 {\r
167 0x9c,\r
168 0xc5,\r
169 0xba,\r
170 0x2b,\r
171 0x1c,\r
172 0xef,\r
173 0x9c,\r
174 0x5b\r
175 }\r
176 },\r
177 NONE_FUNCTION_KEY_SETTING\r
178 },\r
179};\r
180\r
181/**\r
182 This is the routine which an external caller uses to direct the browser\r
183 where to obtain it's information.\r
184\r
185\r
186 @param This The Form Browser protocol instanse.\r
187 @param Handles A pointer to an array of Handles. If HandleCount > 1 we\r
188 display a list of the formsets for the handles specified.\r
189 @param HandleCount The number of Handles specified in Handle.\r
190 @param FormSetGuid This field points to the EFI_GUID which must match the Guid\r
191 field in the EFI_IFR_FORM_SET op-code for the specified\r
192 forms-based package. If FormSetGuid is NULL, then this\r
193 function will display the first found forms package.\r
194 @param FormId This field specifies which EFI_IFR_FORM to render as the first\r
195 displayable page. If this field has a value of 0x0000, then\r
196 the forms browser will render the specified forms in their encoded order.\r
7936fb6a 197 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in \r
198 characters.\r
f02d0c0f 199 @param ActionRequest Points to the action recommended by the form.\r
7936fb6a 200\r
201 @retval EFI_SUCCESS The function completed successfully.\r
202 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
203 @retval EFI_NOT_FOUND No valid forms could be found to display.\r
204\r
205**/\r
206EFI_STATUS\r
207EFIAPI\r
208SendForm (\r
209 IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
210 IN EFI_HII_HANDLE *Handles,\r
211 IN UINTN HandleCount,\r
212 IN EFI_GUID *FormSetGuid, OPTIONAL\r
213 IN UINT16 FormId, OPTIONAL\r
214 IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL\r
215 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL\r
216 )\r
217{\r
218 EFI_STATUS Status;\r
219 UI_MENU_SELECTION *Selection;\r
220 UINTN Index;\r
221 FORM_BROWSER_FORMSET *FormSet;\r
222\r
223 Status = EFI_SUCCESS;\r
224 ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
225\r
226 //\r
227 // Seed the dimensions in the global\r
228 //\r
229 gST->ConOut->QueryMode (\r
230 gST->ConOut,\r
231 gST->ConOut->Mode->Mode,\r
232 &gScreenDimensions.RightColumn,\r
233 &gScreenDimensions.BottomRow\r
234 );\r
235\r
236 if (ScreenDimensions != NULL) {\r
237 //\r
238 // Check local dimension vs. global dimension.\r
239 //\r
240 if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||\r
241 (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)\r
242 ) {\r
243 return EFI_INVALID_PARAMETER;\r
244 } else {\r
245 //\r
246 // Local dimension validation.\r
247 //\r
248 if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) &&\r
249 (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) &&\r
250 ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) &&\r
251 (\r
252 (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +\r
253 SCROLL_ARROW_HEIGHT *\r
254 2 +\r
255 FRONT_PAGE_HEADER_HEIGHT +\r
256 FOOTER_HEIGHT +\r
257 1\r
258 )\r
259 ) {\r
260 CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
261 } else {\r
262 return EFI_INVALID_PARAMETER;\r
263 }\r
264 }\r
265 }\r
266\r
267 gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);\r
268 gHelpBlockWidth = gOptionBlockWidth;\r
269 gPromptBlockWidth = gOptionBlockWidth;\r
270\r
271 //\r
272 // Initialize the strings for the browser, upon exit of the browser, the strings will be freed\r
273 //\r
274 InitializeBrowserStrings ();\r
275\r
276 gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING;\r
277 gClassOfVfr = EFI_SETUP_APPLICATION_SUBCLASS;\r
278\r
279 //\r
280 // Ensure we are in Text mode\r
281 //\r
ebe43565 282 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
283 DisableQuietBoot ();\r
7936fb6a 284\r
285 for (Index = 0; Index < HandleCount; Index++) {\r
286 Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));\r
287 ASSERT (Selection != NULL);\r
288\r
289 Selection->Handle = Handles[Index];\r
290 if (FormSetGuid != NULL) {\r
291 CopyMem (&Selection->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));\r
292 Selection->FormId = FormId;\r
293 }\r
294\r
295 do {\r
296 FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
297 ASSERT (FormSet != NULL);\r
298\r
299 //\r
300 // Initialize internal data structures of FormSet\r
301 //\r
302 Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet);\r
e8e36190 303 if (EFI_ERROR (Status) || IsListEmpty (&FormSet->FormListHead)) {\r
7936fb6a 304 DestroyFormSet (FormSet);\r
305 break;\r
306 }\r
307 Selection->FormSet = FormSet;\r
308\r
309 //\r
310 // Initialize current settings of Questions in this FormSet\r
311 //\r
312 Status = InitializeCurrentSetting (FormSet);\r
313 if (EFI_ERROR (Status)) {\r
314 DestroyFormSet (FormSet);\r
315 break;\r
316 }\r
317\r
318 //\r
319 // Display this formset\r
320 //\r
321 gCurrentSelection = Selection;\r
322\r
323 Status = SetupBrowser (Selection);\r
324\r
325 gCurrentSelection = NULL;\r
326 DestroyFormSet (FormSet);\r
327\r
328 if (EFI_ERROR (Status)) {\r
329 break;\r
330 }\r
331\r
332 } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);\r
333\r
334 gBS->FreePool (Selection);\r
335 }\r
336\r
337 if (ActionRequest != NULL) {\r
338 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
339 if (gResetRequired) {\r
340 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;\r
341 }\r
342 }\r
343\r
344 FreeBrowserStrings ();\r
345\r
346 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
347 gST->ConOut->ClearScreen (gST->ConOut);\r
348\r
349 return Status;\r
350}\r
351\r
352\r
353/**\r
354 This function is called by a callback handler to retrieve uncommitted state\r
355 data from the browser.\r
356\r
357 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL\r
358 instance.\r
359 @param ResultsDataSize A pointer to the size of the buffer associated\r
360 with ResultsData.\r
361 @param ResultsData A string returned from an IFR browser or\r
362 equivalent. The results string will have no\r
363 routing information in them.\r
364 @param RetrieveData A BOOLEAN field which allows an agent to retrieve\r
365 (if RetrieveData = TRUE) data from the uncommitted\r
366 browser state information or set (if RetrieveData\r
367 = FALSE) data in the uncommitted browser state\r
368 information.\r
369 @param VariableGuid An optional field to indicate the target variable\r
370 GUID name to use.\r
371 @param VariableName An optional field to indicate the target\r
372 human-readable variable name.\r
373\r
374 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
375 distribution.\r
376 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to\r
377 contain the results data.\r
378\r
379**/\r
380EFI_STATUS\r
381EFIAPI\r
382BrowserCallback (\r
383 IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
384 IN OUT UINTN *ResultsDataSize,\r
385 IN OUT EFI_STRING ResultsData,\r
386 IN BOOLEAN RetrieveData,\r
387 IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
388 IN CONST CHAR16 *VariableName OPTIONAL\r
389 )\r
390{\r
391 EFI_STATUS Status;\r
392 LIST_ENTRY *Link;\r
393 FORMSET_STORAGE *Storage;\r
394 FORM_BROWSER_FORMSET *FormSet;\r
395 BOOLEAN Found;\r
396 CHAR16 *ConfigResp;\r
397 CHAR16 *StrPtr;\r
398 UINTN BufferSize;\r
399 UINTN TmpSize;\r
400\r
401 if (ResultsDataSize == NULL || ResultsData == NULL) {\r
402 return EFI_INVALID_PARAMETER;\r
403 }\r
404\r
405 if (gCurrentSelection == NULL) {\r
406 return EFI_NOT_READY;\r
407 }\r
408\r
409 Storage = NULL;\r
410 ConfigResp = NULL;\r
411 FormSet = gCurrentSelection->FormSet;\r
412\r
413 //\r
414 // Find target storage\r
415 //\r
416 Link = GetFirstNode (&FormSet->StorageListHead);\r
417 if (IsNull (&FormSet->StorageListHead, Link)) {\r
418 return EFI_UNSUPPORTED;\r
419 }\r
420\r
421 if (VariableGuid != NULL) {\r
422 //\r
423 // Try to find target storage\r
424 //\r
425 Found = FALSE;\r
426 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
427 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
428 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
429\r
430 if (CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {\r
431 if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {\r
432 //\r
433 // Buffer storage require both GUID and Name\r
434 //\r
435 if (VariableName == NULL) {\r
436 return EFI_NOT_FOUND;\r
437 }\r
438\r
439 if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {\r
440 continue;\r
441 }\r
442 }\r
443 Found = TRUE;\r
444 break;\r
445 }\r
446 }\r
447\r
448 if (!Found) {\r
449 return EFI_NOT_FOUND;\r
450 }\r
451 } else {\r
452 //\r
453 // GUID/Name is not specified, take the first storage in FormSet\r
454 //\r
455 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
456 }\r
457\r
458 if (RetrieveData) {\r
459 //\r
460 // Skip if there is no RequestElement\r
461 //\r
462 if (Storage->ElementCount == 0) {\r
463 return EFI_SUCCESS;\r
464 }\r
465\r
466 //\r
467 // Generate <ConfigResp>\r
468 //\r
469 Status = StorageToConfigResp (Storage, &ConfigResp);\r
470 if (EFI_ERROR (Status)) {\r
471 return Status;\r
472 }\r
473\r
474 //\r
475 // Skip <ConfigHdr> and '&' to point to <ConfigBody>\r
476 //\r
477 StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1;\r
478\r
479 BufferSize = StrSize (StrPtr);\r
480 if (*ResultsDataSize < BufferSize) {\r
481 *ResultsDataSize = BufferSize;\r
482\r
483 gBS->FreePool (ConfigResp);\r
484 return EFI_BUFFER_TOO_SMALL;\r
485 }\r
486\r
487 *ResultsDataSize = BufferSize;\r
488 CopyMem (ResultsData, StrPtr, BufferSize);\r
489\r
490 gBS->FreePool (ConfigResp);\r
491 } else {\r
492 //\r
493 // Prepare <ConfigResp>\r
494 //\r
495 TmpSize = StrLen (ResultsData);\r
496 BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16);\r
497 ConfigResp = AllocateZeroPool (BufferSize);\r
498 ASSERT (ConfigResp != NULL);\r
499\r
500 StrCpy (ConfigResp, Storage->ConfigHdr);\r
501 StrCat (ConfigResp, L"&");\r
502 StrCat (ConfigResp, ResultsData);\r
503\r
504 //\r
505 // Update Browser uncommited data\r
506 //\r
507 Status = ConfigRespToStorage (Storage, ConfigResp);\r
508 if (EFI_ERROR (Status)) {\r
509 return Status;\r
510 }\r
511 }\r
512\r
513 return EFI_SUCCESS;\r
514}\r
515\r
516\r
517/**\r
518 Initialize Setup Browser driver.\r
519\r
520 @param ImageHandle The image handle.\r
521 @param SystemTable The system table.\r
522\r
523 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..\r
524 @return Other value if failed to initialize the Setup Browser module.\r
525\r
526**/\r
527EFI_STATUS\r
528EFIAPI\r
529InitializeSetup (\r
530 IN EFI_HANDLE ImageHandle,\r
531 IN EFI_SYSTEM_TABLE *SystemTable\r
532 )\r
533{\r
534 EFI_STATUS Status;\r
535 EFI_HANDLE HiiDriverHandle;\r
536 EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
537\r
538 //\r
539 // Locate required Hii relative protocols\r
540 //\r
541 Status = gBS->LocateProtocol (\r
542 &gEfiHiiDatabaseProtocolGuid,\r
543 NULL,\r
544 (VOID **) &mHiiDatabase\r
545 );\r
546 ASSERT_EFI_ERROR (Status);\r
547\r
548 Status = gBS->LocateProtocol (\r
549 &gEfiHiiStringProtocolGuid,\r
550 NULL,\r
551 (VOID **) &mHiiString\r
552 );\r
553 ASSERT_EFI_ERROR (Status);\r
554\r
555 Status = gBS->LocateProtocol (\r
556 &gEfiHiiConfigRoutingProtocolGuid,\r
557 NULL,\r
558 (VOID **) &mHiiConfigRouting\r
559 );\r
560 ASSERT_EFI_ERROR (Status);\r
561\r
562 //\r
563 // Publish our HII data\r
564 //\r
565 Status = HiiLibCreateHiiDriverHandle (&HiiDriverHandle);\r
566 ASSERT_EFI_ERROR (Status);\r
567\r
568 PackageList = HiiLibPreparePackageList (1, &gSetupBrowserGuid, SetupBrowserStrings);\r
569 ASSERT (PackageList != NULL);\r
570 Status = mHiiDatabase->NewPackageList (\r
571 mHiiDatabase,\r
572 PackageList,\r
573 HiiDriverHandle,\r
574 &gHiiHandle\r
575 );\r
576 ASSERT_EFI_ERROR (Status);\r
577\r
578 //\r
579 // Initialize Driver private data\r
580 //\r
7936fb6a 581 BannerData = AllocateZeroPool (sizeof (BANNER_DATA));\r
582 ASSERT (BannerData != NULL);\r
583\r
584 //\r
585 // Install FormBrowser2 protocol\r
586 //\r
587 mPrivateData.Handle = NULL;\r
588 Status = gBS->InstallProtocolInterface (\r
589 &mPrivateData.Handle,\r
590 &gEfiFormBrowser2ProtocolGuid,\r
591 EFI_NATIVE_INTERFACE,\r
592 &mPrivateData.FormBrowser2\r
593 );\r
594 ASSERT_EFI_ERROR (Status);\r
595\r
596 //\r
597 // Install Print protocol\r
598 //\r
ebe43565 599 Status = gBS->InstallProtocolInterface (\r
600 &mPrivateData.Handle,\r
601 &gEfiPrint2ProtocolGuid,\r
602 EFI_NATIVE_INTERFACE,\r
603 &mPrivateData.Print\r
604 );\r
605\r
606 //\r
607 // Install Ecp Print protocol, which is defined in\r
608 // Edk\Foundation\Protocol\Print\Print.h with protocol\r
609 // GUID of { 0xdf2d868e, 0x32fc, 0x4cf0, {0x8e, 0x6b, 0xff, 0xd9, 0x5d, 0x13, 0x43, 0xd0 }}\r
610 // This is support previous module that written to consume this protocol.\r
611 // \r
7936fb6a 612 Status = gBS->InstallProtocolInterface (\r
613 &mPrivateData.Handle,\r
614 &gEfiPrintProtocolGuid,\r
615 EFI_NATIVE_INTERFACE,\r
616 &mPrivateData.Print\r
617 );\r
618\r
619 return Status;\r
620}\r
621\r
622\r
623/**\r
624 Create a new string in HII Package List.\r
625\r
626 @param String The String to be added\r
627 @param HiiHandle The package list in the HII database to insert the\r
628 specified string.\r
629\r
630 @return The output string.\r
631\r
632**/\r
633EFI_STRING_ID\r
634NewString (\r
635 IN CHAR16 *String,\r
636 IN EFI_HII_HANDLE HiiHandle\r
637 )\r
638{\r
639 EFI_STRING_ID StringId;\r
640 EFI_STATUS Status;\r
641\r
642 StringId = 0;\r
643 Status = HiiLibNewString (HiiHandle, &StringId, String);\r
644 ASSERT_EFI_ERROR (Status);\r
645\r
646 return StringId;\r
647}\r
648\r
649\r
650/**\r
651 Delete a string from HII Package List.\r
652\r
653 @param StringId Id of the string in HII database.\r
654 @param HiiHandle The HII package list handle.\r
655\r
656 @retval EFI_SUCCESS The string was deleted successfully.\r
657\r
658**/\r
659EFI_STATUS\r
660DeleteString (\r
661 IN EFI_STRING_ID StringId,\r
662 IN EFI_HII_HANDLE HiiHandle\r
663 )\r
664{\r
665 CHAR16 NullChar;\r
666\r
667 NullChar = CHAR_NULL;\r
668 return HiiLibSetString (HiiHandle, StringId, &NullChar);\r
669}\r
670\r
671\r
672/**\r
673 Get the string based on the StringId and HII Package List Handle.\r
674\r
675 @param Token The String's ID.\r
676 @param HiiHandle The package list in the HII database to search for\r
677 the specified string.\r
678\r
679 @return The output string.\r
680\r
681**/\r
682CHAR16 *\r
683GetToken (\r
684 IN EFI_STRING_ID Token,\r
685 IN EFI_HII_HANDLE HiiHandle\r
686 )\r
687{\r
688 EFI_STATUS Status;\r
689 CHAR16 *String;\r
690 UINTN BufferLength;\r
691\r
692 //\r
693 // Set default string size assumption at no more than 256 bytes\r
694 //\r
695 BufferLength = 0x100;\r
696 String = AllocateZeroPool (BufferLength);\r
697 ASSERT (String != NULL);\r
698\r
699 Status = HiiLibGetString (HiiHandle, Token, String, &BufferLength);\r
700\r
701 if (Status == EFI_BUFFER_TOO_SMALL) {\r
702 gBS->FreePool (String);\r
703 String = AllocateZeroPool (BufferLength);\r
704 ASSERT (String != NULL);\r
705\r
706 Status = HiiLibGetString (HiiHandle, Token, String, &BufferLength);\r
707 }\r
708 ASSERT_EFI_ERROR (Status);\r
709\r
710 return String;\r
711}\r
712\r
713\r
714/**\r
715 Allocate new memory and then copy the Unicode string Source to Destination.\r
716\r
717 @param Dest Location to copy string\r
718 @param Src String to copy\r
719\r
720**/\r
721VOID\r
722NewStringCpy (\r
723 IN OUT CHAR16 **Dest,\r
724 IN CHAR16 *Src\r
725 )\r
726{\r
727 SafeFreePool (*Dest);\r
728 *Dest = AllocateCopyPool (StrSize (Src), Src);\r
729 ASSERT (*Dest != NULL);\r
730}\r
731\r
732\r
733/**\r
734 Allocate new memory and concatinate Source on the end of Destination.\r
735\r
736 @param Dest String to added to the end of.\r
737 @param Src String to concatinate.\r
738\r
739**/\r
740VOID\r
741NewStringCat (\r
742 IN OUT CHAR16 **Dest,\r
743 IN CHAR16 *Src\r
744 )\r
745{\r
746 CHAR16 *NewString;\r
747 UINTN TmpSize;\r
748\r
749 if (*Dest == NULL) {\r
750 NewStringCpy (Dest, Src);\r
751 return;\r
752 }\r
753\r
754 TmpSize = StrSize (*Dest);\r
755 NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1);\r
756 ASSERT (NewString != NULL);\r
757\r
758 StrCpy (NewString, *Dest);\r
759 StrCat (NewString, Src);\r
760\r
761 gBS->FreePool (*Dest);\r
762 *Dest = NewString;\r
763}\r
764\r
765\r
766/**\r
767 Synchronize Storage's Edit copy to Shadow copy.\r
768\r
769 @param Storage The Storage to be synchronized.\r
770\r
771**/\r
772VOID\r
773SynchronizeStorage (\r
774 IN FORMSET_STORAGE *Storage\r
775 )\r
776{\r
777 LIST_ENTRY *Link;\r
778 NAME_VALUE_NODE *Node;\r
779\r
780 switch (Storage->Type) {\r
781 case EFI_HII_VARSTORE_BUFFER:\r
782 CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);\r
783 break;\r
784\r
785 case EFI_HII_VARSTORE_NAME_VALUE:\r
786 Link = GetFirstNode (&Storage->NameValueListHead);\r
787 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
788 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
789\r
790 NewStringCpy (&Node->Value, Node->EditValue);\r
791\r
792 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
793 }\r
794 break;\r
795\r
796 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
797 default:\r
798 break;\r
799 }\r
800}\r
801\r
802\r
803/**\r
804 Get Value for given Name from a NameValue Storage.\r
805\r
806 @param Storage The NameValue Storage.\r
807 @param Name The Name.\r
808 @param Value The retured Value.\r
809\r
810 @retval EFI_SUCCESS Value found for given Name.\r
811 @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
812\r
813**/\r
814EFI_STATUS\r
815GetValueByName (\r
816 IN FORMSET_STORAGE *Storage,\r
817 IN CHAR16 *Name,\r
818 IN OUT CHAR16 **Value\r
819 )\r
820{\r
821 LIST_ENTRY *Link;\r
822 NAME_VALUE_NODE *Node;\r
823\r
824 *Value = NULL;\r
825\r
826 Link = GetFirstNode (&Storage->NameValueListHead);\r
827 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
828 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
829\r
830 if (StrCmp (Name, Node->Name) == 0) {\r
831 NewStringCpy (Value, Node->EditValue);\r
832 return EFI_SUCCESS;\r
833 }\r
834\r
835 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
836 }\r
837\r
838 return EFI_NOT_FOUND;\r
839}\r
840\r
841\r
842/**\r
843 Set Value of given Name in a NameValue Storage.\r
844\r
845 @param Storage The NameValue Storage.\r
846 @param Name The Name.\r
847 @param Value The Value to set.\r
848\r
849 @retval EFI_SUCCESS Value found for given Name.\r
850 @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
851\r
852**/\r
853EFI_STATUS\r
854SetValueByName (\r
855 IN FORMSET_STORAGE *Storage,\r
856 IN CHAR16 *Name,\r
857 IN CHAR16 *Value\r
858 )\r
859{\r
860 LIST_ENTRY *Link;\r
861 NAME_VALUE_NODE *Node;\r
862\r
863 Link = GetFirstNode (&Storage->NameValueListHead);\r
864 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
865 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
866\r
867 if (StrCmp (Name, Node->Name) == 0) {\r
868 SafeFreePool (Node->EditValue);\r
869 Node->EditValue = AllocateCopyPool (StrSize (Value), Value);\r
870 ASSERT (Node->EditValue != NULL);\r
871 return EFI_SUCCESS;\r
872 }\r
873\r
874 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
875 }\r
876\r
877 return EFI_NOT_FOUND;\r
878}\r
879\r
880\r
881/**\r
882 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
883\r
884 @param Storage The Storage to be conveted.\r
885 @param ConfigResp The returned <ConfigResp>.\r
886\r
887 @retval EFI_SUCCESS Convert success.\r
888 @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
889\r
890**/\r
891EFI_STATUS\r
892StorageToConfigResp (\r
893 IN FORMSET_STORAGE *Storage,\r
894 IN CHAR16 **ConfigResp\r
895 )\r
896{\r
897 EFI_STATUS Status;\r
898 EFI_STRING Progress;\r
899 LIST_ENTRY *Link;\r
900 NAME_VALUE_NODE *Node;\r
901\r
902 Status = EFI_SUCCESS;\r
903\r
904 switch (Storage->Type) {\r
905 case EFI_HII_VARSTORE_BUFFER:\r
906 Status = mHiiConfigRouting->BlockToConfig (\r
907 mHiiConfigRouting,\r
908 Storage->ConfigRequest,\r
909 Storage->EditBuffer,\r
910 Storage->Size,\r
911 ConfigResp,\r
912 &Progress\r
913 );\r
914 break;\r
915\r
916 case EFI_HII_VARSTORE_NAME_VALUE:\r
917 *ConfigResp = NULL;\r
918 NewStringCat (ConfigResp, Storage->ConfigHdr);\r
919\r
920 Link = GetFirstNode (&Storage->NameValueListHead);\r
921 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
922 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
923\r
924 NewStringCat (ConfigResp, L"&");\r
925 NewStringCat (ConfigResp, Node->Name);\r
926 NewStringCat (ConfigResp, L"=");\r
927 NewStringCat (ConfigResp, Node->EditValue);\r
928\r
929 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
930 }\r
931 break;\r
932\r
933 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
934 default:\r
935 Status = EFI_INVALID_PARAMETER;\r
936 break;\r
937 }\r
938\r
939 return Status;\r
940}\r
941\r
942\r
943/**\r
944 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.\r
945\r
946 @param Storage The Storage to receive the settings.\r
947 @param ConfigResp The <ConfigResp> to be converted.\r
948\r
949 @retval EFI_SUCCESS Convert success.\r
950 @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
951\r
952**/\r
953EFI_STATUS\r
954ConfigRespToStorage (\r
955 IN FORMSET_STORAGE *Storage,\r
956 IN CHAR16 *ConfigResp\r
957 )\r
958{\r
959 EFI_STATUS Status;\r
960 EFI_STRING Progress;\r
961 UINTN BufferSize;\r
962 CHAR16 *StrPtr;\r
963 CHAR16 *Name;\r
964 CHAR16 *Value;\r
965\r
966 Status = EFI_SUCCESS;\r
967\r
968 switch (Storage->Type) {\r
969 case EFI_HII_VARSTORE_BUFFER:\r
970 BufferSize = Storage->Size;\r
971 Status = mHiiConfigRouting->ConfigToBlock (\r
972 mHiiConfigRouting,\r
973 ConfigResp,\r
974 Storage->EditBuffer,\r
975 &BufferSize,\r
976 &Progress\r
977 );\r
978 break;\r
979\r
980 case EFI_HII_VARSTORE_NAME_VALUE:\r
981 StrPtr = StrStr (ConfigResp, L"&");\r
982 while (StrPtr != NULL) {\r
983 //\r
984 // Skip '&'\r
985 //\r
986 StrPtr = StrPtr + 1;\r
987 Name = StrPtr;\r
988 StrPtr = StrStr (StrPtr, L"=");\r
989 if (StrPtr == NULL) {\r
990 break;\r
991 }\r
992 *StrPtr = 0;\r
993\r
994 //\r
995 // Skip '='\r
996 //\r
997 StrPtr = StrPtr + 1;\r
998 Value = StrPtr;\r
999 StrPtr = StrStr (StrPtr, L"&");\r
1000 if (StrPtr != NULL) {\r
1001 *StrPtr = 0;\r
1002 }\r
1003 SetValueByName (Storage, Name, Value);\r
1004 }\r
1005 break;\r
1006\r
1007 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
1008 default:\r
1009 Status = EFI_INVALID_PARAMETER;\r
1010 break;\r
1011 }\r
1012\r
1013 return Status;\r
1014}\r
1015\r
1016\r
1017/**\r
1018 Get Question's current Value.\r
1019\r
1020 @param FormSet FormSet data structure.\r
1021 @param Form Form data structure.\r
1022 @param Question Question to be initialized.\r
1023 @param Cached TRUE: get from Edit copy FALSE: get from original\r
1024 Storage\r
1025\r
1026 @retval EFI_SUCCESS The function completed successfully.\r
1027\r
1028**/\r
1029EFI_STATUS\r
1030GetQuestionValue (\r
1031 IN FORM_BROWSER_FORMSET *FormSet,\r
1032 IN FORM_BROWSER_FORM *Form,\r
1033 IN OUT FORM_BROWSER_STATEMENT *Question,\r
1034 IN BOOLEAN Cached\r
1035 )\r
1036{\r
1037 EFI_STATUS Status;\r
1038 BOOLEAN Enabled;\r
1039 BOOLEAN Pending;\r
1040 UINT8 *Dst;\r
1041 UINTN StorageWidth;\r
1042 EFI_TIME EfiTime;\r
1043 FORMSET_STORAGE *Storage;\r
1044 EFI_IFR_TYPE_VALUE *QuestionValue;\r
1045 CHAR16 *ConfigRequest;\r
1046 CHAR16 *Progress;\r
1047 CHAR16 *Result;\r
1048 CHAR16 *Value;\r
1049 UINTN Length;\r
1050 BOOLEAN IsBufferStorage;\r
1051 BOOLEAN IsString;\r
1052\r
1053 Status = EFI_SUCCESS;\r
1054\r
1055 //\r
1056 // Statement don't have storage, skip them\r
1057 //\r
1058 if (Question->QuestionId == 0) {\r
1059 return Status;\r
1060 }\r
1061\r
1062 //\r
1063 // Question value is provided by an Expression, evaluate it\r
1064 //\r
1065 if (Question->ValueExpression != NULL) {\r
1066 Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);\r
1067 if (!EFI_ERROR (Status)) {\r
1068 CopyMem (&Question->HiiValue, &Question->ValueExpression->Result, sizeof (EFI_HII_VALUE));\r
1069 }\r
1070 return Status;\r
1071 }\r
1072\r
1073 //\r
1074 // Question value is provided by RTC\r
1075 //\r
1076 Storage = Question->Storage;\r
1077 QuestionValue = &Question->HiiValue.Value;\r
1078 if (Storage == NULL) {\r
1079 //\r
1080 // It's a Question without storage, or RTC date/time\r
1081 //\r
1082 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1083 //\r
1084 // Date and time define the same Flags bit\r
1085 //\r
1086 switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
1087 case QF_DATE_STORAGE_TIME:\r
1088 Status = gRT->GetTime (&EfiTime, NULL);\r
1089 break;\r
1090\r
1091 case QF_DATE_STORAGE_WAKEUP:\r
1092 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
1093 break;\r
1094\r
1095 case QF_DATE_STORAGE_NORMAL:\r
1096 default:\r
1097 //\r
1098 // For date/time without storage\r
1099 //\r
1100 return EFI_SUCCESS;\r
1101 }\r
1102\r
1103 if (EFI_ERROR (Status)) {\r
1104 return Status;\r
1105 }\r
1106\r
1107 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1108 QuestionValue->date.Year = EfiTime.Year;\r
1109 QuestionValue->date.Month = EfiTime.Month;\r
1110 QuestionValue->date.Day = EfiTime.Day;\r
1111 } else {\r
1112 QuestionValue->time.Hour = EfiTime.Hour;\r
1113 QuestionValue->time.Minute = EfiTime.Minute;\r
1114 QuestionValue->time.Second = EfiTime.Second;\r
1115 }\r
1116 }\r
1117\r
1118 return EFI_SUCCESS;\r
1119 }\r
1120\r
1121 //\r
1122 // Question value is provided by EFI variable\r
1123 //\r
1124 StorageWidth = Question->StorageWidth;\r
1125 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1126 if (Question->BufferValue != NULL) {\r
1127 Dst = Question->BufferValue;\r
1128 } else {\r
1129 Dst = (UINT8 *) QuestionValue;\r
1130 }\r
1131\r
1132 Status = gRT->GetVariable (\r
1133 Question->VariableName,\r
1134 &Storage->Guid,\r
1135 NULL,\r
1136 &StorageWidth,\r
1137 Dst\r
1138 );\r
1139 //\r
1140 // Always return success, even this EFI variable doesn't exist\r
1141 //\r
1142 return EFI_SUCCESS;\r
1143 }\r
1144\r
1145 //\r
1146 // Question Value is provided by Buffer Storage or NameValue Storage\r
1147 //\r
1148 if (Question->BufferValue != NULL) {\r
1149 //\r
1150 // This Question is password or orderedlist\r
1151 //\r
1152 Dst = Question->BufferValue;\r
1153 } else {\r
1154 //\r
1155 // Other type of Questions\r
1156 //\r
1157 Dst = (UINT8 *) &Question->HiiValue.Value;\r
1158 }\r
1159\r
1160 IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
1161 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
1162 if (Cached) {\r
1163 if (IsBufferStorage) {\r
1164 //\r
1165 // Copy from storage Edit buffer\r
1166 //\r
1167 CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
1168 } else {\r
1169 Status = GetValueByName (Storage, Question->VariableName, &Value);\r
1170 if (EFI_ERROR (Status)) {\r
1171 return Status;\r
1172 }\r
1173\r
1174 if (IsString) {\r
1175 //\r
1176 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
1177 //\r
1178 Length = StorageWidth + sizeof (CHAR16);\r
1179 Status = ConfigStringToUnicode ((CHAR16 *) Dst, &Length, Value);\r
1180 } else {\r
1181 Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);\r
1182 }\r
1183\r
1184 gBS->FreePool (Value);\r
1185 }\r
1186 } else {\r
1187 //\r
1188 // Request current settings from Configuration Driver\r
1189 //\r
1190 if (FormSet->ConfigAccess == NULL) {\r
1191 return EFI_NOT_FOUND;\r
1192 }\r
1193\r
1194 //\r
1195 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
1196 // <ConfigHdr> + "&" + <VariableName>\r
1197 //\r
1198 if (IsBufferStorage) {\r
1199 Length = StrLen (Storage->ConfigHdr);\r
1200 Length += StrLen (Question->BlockName);\r
1201 } else {\r
1202 Length = StrLen (Storage->ConfigHdr);\r
1203 Length += StrLen (Question->VariableName) + 1;\r
1204 }\r
1205 ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
1206 ASSERT (ConfigRequest != NULL);\r
1207\r
1208 StrCpy (ConfigRequest, Storage->ConfigHdr);\r
1209 if (IsBufferStorage) {\r
1210 StrCat (ConfigRequest, Question->BlockName);\r
1211 } else {\r
1212 StrCat (ConfigRequest, L"&");\r
1213 StrCat (ConfigRequest, Question->VariableName);\r
1214 }\r
1215\r
1216 Status = FormSet->ConfigAccess->ExtractConfig (\r
1217 FormSet->ConfigAccess,\r
1218 ConfigRequest,\r
1219 &Progress,\r
1220 &Result\r
1221 );\r
1222 if (EFI_ERROR (Status)) {\r
1223 return Status;\r
1224 }\r
1225\r
1226 //\r
1227 // Skip <ConfigRequest>\r
1228 //\r
1229 Value = Result + Length;\r
1230 if (IsBufferStorage) {\r
1231 //\r
1232 // Skip "&VALUE"\r
1233 //\r
1234 Value = Value + 6;\r
1235 }\r
1236 if (*Value != '=') {\r
1237 gBS->FreePool (Result);\r
1238 return EFI_NOT_FOUND;\r
1239 }\r
1240 //\r
1241 // Skip '=', point to value\r
1242 //\r
1243 Value = Value + 1;\r
1244 if (!IsBufferStorage && IsString) {\r
1245 //\r
1246 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
1247 //\r
1248 Length = StorageWidth + sizeof (CHAR16);\r
1249 Status = ConfigStringToUnicode ((CHAR16 *) Dst, &Length, Value);\r
1250 } else {\r
1251 Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);\r
1252 if (EFI_ERROR (Status)) {\r
1253 gBS->FreePool (Result);\r
1254 return Status;\r
1255 }\r
1256 }\r
1257\r
1258 //\r
1259 // Synchronize Edit Buffer\r
1260 //\r
1261 if (IsBufferStorage) {\r
1262 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
1263 } else {\r
1264 SetValueByName (Storage, Question->VariableName, Value);\r
1265 }\r
1266 gBS->FreePool (Result);\r
1267 }\r
1268\r
1269 return Status;\r
1270}\r
1271\r
1272\r
1273/**\r
1274 Save Question Value to edit copy(cached) or Storage(uncached).\r
1275\r
1276 @param FormSet FormSet data structure.\r
1277 @param Form Form data structure.\r
1278 @param Question Pointer to the Question.\r
1279 @param Cached TRUE: set to Edit copy FALSE: set to original\r
1280 Storage\r
1281\r
1282 @retval EFI_SUCCESS The function completed successfully.\r
1283\r
1284**/\r
1285EFI_STATUS\r
1286SetQuestionValue (\r
1287 IN FORM_BROWSER_FORMSET *FormSet,\r
1288 IN FORM_BROWSER_FORM *Form,\r
1289 IN OUT FORM_BROWSER_STATEMENT *Question,\r
1290 IN BOOLEAN Cached\r
1291 )\r
1292{\r
1293 EFI_STATUS Status;\r
1294 BOOLEAN Enabled;\r
1295 BOOLEAN Pending;\r
1296 UINT8 *Src;\r
1297 EFI_TIME EfiTime;\r
1298 UINTN BufferLen;\r
1299 UINTN StorageWidth;\r
1300 FORMSET_STORAGE *Storage;\r
1301 EFI_IFR_TYPE_VALUE *QuestionValue;\r
1302 CHAR16 *ConfigResp;\r
1303 CHAR16 *Progress;\r
1304 CHAR16 *Value;\r
1305 UINTN Length;\r
1306 BOOLEAN IsBufferStorage;\r
1307 BOOLEAN IsString;\r
1308\r
1309 Status = EFI_SUCCESS;\r
1310\r
1311 //\r
1312 // Statement don't have storage, skip them\r
1313 //\r
1314 if (Question->QuestionId == 0) {\r
1315 return Status;\r
1316 }\r
1317\r
1318 //\r
1319 // If Question value is provided by an Expression, then it is read only\r
1320 //\r
1321 if (Question->ValueExpression != NULL) {\r
1322 return Status;\r
1323 }\r
1324\r
1325 //\r
1326 // Question value is provided by RTC\r
1327 //\r
1328 Storage = Question->Storage;\r
1329 QuestionValue = &Question->HiiValue.Value;\r
1330 if (Storage == NULL) {\r
1331 //\r
1332 // It's a Question without storage, or RTC date/time\r
1333 //\r
1334 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1335 //\r
1336 // Date and time define the same Flags bit\r
1337 //\r
1338 switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
1339 case QF_DATE_STORAGE_TIME:\r
1340 Status = gRT->GetTime (&EfiTime, NULL);\r
1341 break;\r
1342\r
1343 case QF_DATE_STORAGE_WAKEUP:\r
1344 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
1345 break;\r
1346\r
1347 case QF_DATE_STORAGE_NORMAL:\r
1348 default:\r
1349 //\r
1350 // For date/time without storage\r
1351 //\r
1352 return EFI_SUCCESS;\r
1353 }\r
1354\r
1355 if (EFI_ERROR (Status)) {\r
1356 return Status;\r
1357 }\r
1358\r
1359 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1360 EfiTime.Year = QuestionValue->date.Year;\r
1361 EfiTime.Month = QuestionValue->date.Month;\r
1362 EfiTime.Day = QuestionValue->date.Day;\r
1363 } else {\r
1364 EfiTime.Hour = QuestionValue->time.Hour;\r
1365 EfiTime.Minute = QuestionValue->time.Minute;\r
1366 EfiTime.Second = QuestionValue->time.Second;\r
1367 }\r
1368\r
1369 if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {\r
1370 Status = gRT->SetTime (&EfiTime);\r
1371 } else {\r
1372 Status = gRT->SetWakeupTime (TRUE, &EfiTime);\r
1373 }\r
1374 }\r
1375\r
1376 return Status;\r
1377 }\r
1378\r
1379 //\r
1380 // Question value is provided by EFI variable\r
1381 //\r
1382 StorageWidth = Question->StorageWidth;\r
1383 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1384 if (Question->BufferValue != NULL) {\r
1385 Src = Question->BufferValue;\r
1386 } else {\r
1387 Src = (UINT8 *) QuestionValue;\r
1388 }\r
1389\r
1390 Status = gRT->SetVariable (\r
1391 Question->VariableName,\r
1392 &Storage->Guid,\r
1393 Storage->Attributes,\r
1394 StorageWidth,\r
1395 Src\r
1396 );\r
1397 return Status;\r
1398 }\r
1399\r
1400 //\r
1401 // Question Value is provided by Buffer Storage or NameValue Storage\r
1402 //\r
1403 if (Question->BufferValue != NULL) {\r
1404 Src = Question->BufferValue;\r
1405 } else {\r
1406 Src = (UINT8 *) &Question->HiiValue.Value;\r
1407 }\r
1408\r
1409 IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
1410 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
1411 if (IsBufferStorage) {\r
1412 //\r
1413 // Copy to storage edit buffer\r
1414 //\r
1415 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
1416 } else {\r
1417 if (IsString) {\r
1418 //\r
1419 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
1420 //\r
1421 Value = NULL;\r
1422 BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
1423 Value = AllocateZeroPool (BufferLen);\r
1424 ASSERT (Value != NULL);\r
1425 Status = UnicodeToConfigString (Value, &BufferLen, (CHAR16 *) Src);\r
1426 ASSERT_EFI_ERROR (Status);\r
1427 } else {\r
1428 BufferLen = StorageWidth * 2 + 1;\r
1429 Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
1430 ASSERT (Value != NULL);\r
1431 BufToHexString (Value, &BufferLen, Src, StorageWidth);\r
1432 ToLower (Value);\r
1433 }\r
1434\r
1435 Status = SetValueByName (Storage, Question->VariableName, Value);\r
1436 gBS->FreePool (Value);\r
1437 }\r
1438\r
1439 if (!Cached) {\r
1440 //\r
1441 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||\r
1442 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"\r
1443 //\r
1444 if (IsBufferStorage) {\r
1445 Length = StrLen (Question->BlockName) + 7;\r
1446 } else {\r
1447 Length = StrLen (Question->VariableName) + 2;\r
1448 }\r
1449 if (!IsBufferStorage && IsString) {\r
1450 Length += (StrLen ((CHAR16 *) Src) * 4);\r
1451 } else {\r
1452 Length += (StorageWidth * 2);\r
1453 }\r
1454 ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16));\r
1455 ASSERT (ConfigResp != NULL);\r
1456\r
1457 StrCpy (ConfigResp, Storage->ConfigHdr);\r
1458 if (IsBufferStorage) {\r
1459 StrCat (ConfigResp, Question->BlockName);\r
1460 StrCat (ConfigResp, L"&VALUE=");\r
1461 } else {\r
1462 StrCat (ConfigResp, L"&");\r
1463 StrCat (ConfigResp, Question->VariableName);\r
1464 StrCat (ConfigResp, L"=");\r
1465 }\r
1466\r
1467 Value = ConfigResp + StrLen (ConfigResp);\r
1468 if (!IsBufferStorage && IsString) {\r
1469 //\r
1470 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
1471 //\r
1472 BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
1473 Status = UnicodeToConfigString (Value, &BufferLen, (CHAR16 *) Src);\r
1474 ASSERT_EFI_ERROR (Status);\r
1475 } else {\r
1476 BufferLen = StorageWidth * 2 + 1;\r
1477 BufToHexString (Value, &BufferLen, Src, StorageWidth);\r
1478 ToLower (Value);\r
1479 }\r
1480\r
1481 //\r
1482 // Submit Question Value to Configuration Driver\r
1483 //\r
1484 if (FormSet->ConfigAccess != NULL) {\r
1485 Status = FormSet->ConfigAccess->RouteConfig (\r
1486 FormSet->ConfigAccess,\r
1487 ConfigResp,\r
1488 &Progress\r
1489 );\r
1490 if (EFI_ERROR (Status)) {\r
1491 gBS->FreePool (ConfigResp);\r
1492 return Status;\r
1493 }\r
1494 }\r
1495 gBS->FreePool (ConfigResp);\r
1496\r
1497 //\r
1498 // Synchronize shadow Buffer\r
1499 //\r
1500 SynchronizeStorage (Storage);\r
1501 }\r
1502\r
1503 return Status;\r
1504}\r
1505\r
1506\r
1507/**\r
1508 Perform inconsistent check for a Form.\r
1509\r
1510 @param FormSet FormSet data structure.\r
1511 @param Form Form data structure.\r
1512 @param Question The Question to be validated.\r
1513 @param Type Validation type: InConsistent or NoSubmit\r
1514\r
1515 @retval EFI_SUCCESS Form validation pass.\r
1516 @retval other Form validation failed.\r
1517\r
1518**/\r
1519EFI_STATUS\r
1520ValidateQuestion (\r
1521 IN FORM_BROWSER_FORMSET *FormSet,\r
1522 IN FORM_BROWSER_FORM *Form,\r
1523 IN FORM_BROWSER_STATEMENT *Question,\r
1524 IN UINTN Type\r
1525 )\r
1526{\r
1527 EFI_STATUS Status;\r
1528 LIST_ENTRY *Link;\r
1529 LIST_ENTRY *ListHead;\r
1530 EFI_STRING PopUp;\r
1531 EFI_INPUT_KEY Key;\r
1532 FORM_EXPRESSION *Expression;\r
1533\r
1534 if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {\r
1535 ListHead = &Question->InconsistentListHead;\r
1536 } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
1537 ListHead = &Question->NoSubmitListHead;\r
1538 } else {\r
1539 return EFI_UNSUPPORTED;\r
1540 }\r
1541\r
1542 Link = GetFirstNode (ListHead);\r
1543 while (!IsNull (ListHead, Link)) {\r
1544 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
1545\r
1546 //\r
1547 // Evaluate the expression\r
1548 //\r
1549 Status = EvaluateExpression (FormSet, Form, Expression);\r
1550 if (EFI_ERROR (Status)) {\r
1551 return Status;\r
1552 }\r
1553\r
1554 if (Expression->Result.Value.b) {\r
1555 //\r
1556 // Condition meet, show up error message\r
1557 //\r
1558 if (Expression->Error != 0) {\r
1559 PopUp = GetToken (Expression->Error, FormSet->HiiHandle);\r
1560 do {\r
1561 CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);\r
1562 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1563 gBS->FreePool (PopUp);\r
1564 }\r
1565\r
1566 return EFI_NOT_READY;\r
1567 }\r
1568\r
1569 Link = GetNextNode (ListHead, Link);\r
1570 }\r
1571\r
1572 return EFI_SUCCESS;\r
1573}\r
1574\r
1575\r
1576/**\r
1577 Perform NoSubmit check for a Form.\r
1578\r
1579 @param FormSet FormSet data structure.\r
1580 @param Form Form data structure.\r
1581\r
1582 @retval EFI_SUCCESS Form validation pass.\r
1583 @retval other Form validation failed.\r
1584\r
1585**/\r
1586EFI_STATUS\r
1587NoSubmitCheck (\r
1588 IN FORM_BROWSER_FORMSET *FormSet,\r
1589 IN FORM_BROWSER_FORM *Form\r
1590 )\r
1591{\r
1592 EFI_STATUS Status;\r
1593 LIST_ENTRY *Link;\r
1594 FORM_BROWSER_STATEMENT *Question;\r
1595\r
1596 Link = GetFirstNode (&Form->StatementListHead);\r
1597 while (!IsNull (&Form->StatementListHead, Link)) {\r
1598 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
1599\r
1600 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);\r
1601 if (EFI_ERROR (Status)) {\r
1602 return Status;\r
1603 }\r
1604\r
1605 Link = GetNextNode (&Form->StatementListHead, Link);\r
1606 }\r
1607\r
1608 return EFI_SUCCESS;\r
1609}\r
1610\r
1611\r
1612/**\r
1613 Submit a Form.\r
1614\r
1615 @param FormSet FormSet data structure.\r
1616 @param Form Form data structure.\r
1617\r
1618 @retval EFI_SUCCESS The function completed successfully.\r
1619\r
1620**/\r
1621EFI_STATUS\r
1622SubmitForm (\r
1623 IN FORM_BROWSER_FORMSET *FormSet,\r
1624 IN FORM_BROWSER_FORM *Form\r
1625 )\r
1626{\r
1627 EFI_STATUS Status;\r
1628 LIST_ENTRY *Link;\r
1629 EFI_STRING ConfigResp;\r
1630 EFI_STRING Progress;\r
1631 FORMSET_STORAGE *Storage;\r
1632\r
1633 //\r
1634 // Validate the Form by NoSubmit check\r
1635 //\r
1636 Status = NoSubmitCheck (FormSet, Form);\r
1637 if (EFI_ERROR (Status)) {\r
1638 return Status;\r
1639 }\r
1640\r
1641 //\r
1642 // Submit Buffer storage or Name/Value storage\r
1643 //\r
1644 Link = GetFirstNode (&FormSet->StorageListHead);\r
1645 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
1646 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
1647 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
1648\r
1649 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1650 continue;\r
1651 }\r
1652\r
1653 //\r
1654 // Skip if there is no RequestElement\r
1655 //\r
1656 if (Storage->ElementCount == 0) {\r
1657 continue;\r
1658 }\r
1659\r
1660 //\r
1661 // Prepare <ConfigResp>\r
1662 //\r
1663 Status = StorageToConfigResp (Storage, &ConfigResp);\r
1664 if (EFI_ERROR (Status)) {\r
1665 return Status;\r
1666 }\r
1667\r
1668 //\r
1669 // Send <ConfigResp> to Configuration Driver\r
1670 //\r
1671 if (FormSet->ConfigAccess != NULL) {\r
1672 Status = FormSet->ConfigAccess->RouteConfig (\r
1673 FormSet->ConfigAccess,\r
1674 ConfigResp,\r
1675 &Progress\r
1676 );\r
1677 if (EFI_ERROR (Status)) {\r
1678 gBS->FreePool (ConfigResp);\r
1679 return Status;\r
1680 }\r
1681 }\r
1682 gBS->FreePool (ConfigResp);\r
1683\r
1684 //\r
1685 // Config success, update storage shadow Buffer\r
1686 //\r
1687 SynchronizeStorage (Storage);\r
1688 }\r
1689\r
1690 gNvUpdateRequired = FALSE;\r
1691\r
1692 return EFI_SUCCESS;\r
1693}\r
1694\r
1695\r
1696/**\r
1697 Reset Question to its default value.\r
1698\r
1699 @param FormSet The form set.\r
1700 @param Form The form.\r
1701 @param Question The question.\r
1702 @param DefaultId The Class of the default.\r
1703\r
1704 @retval EFI_SUCCESS Question is reset to default value.\r
1705\r
1706**/\r
1707EFI_STATUS\r
1708GetQuestionDefault (\r
1709 IN FORM_BROWSER_FORMSET *FormSet,\r
1710 IN FORM_BROWSER_FORM *Form,\r
1711 IN FORM_BROWSER_STATEMENT *Question,\r
1712 IN UINT16 DefaultId\r
1713 )\r
1714{\r
1715 EFI_STATUS Status;\r
1716 LIST_ENTRY *Link;\r
1717 QUESTION_DEFAULT *Default;\r
1718 QUESTION_OPTION *Option;\r
1719 EFI_HII_VALUE *HiiValue;\r
1720 UINT8 Index;\r
1721\r
1722 Status = EFI_SUCCESS;\r
1723\r
1724 //\r
1725 // Statement don't have storage, skip them\r
1726 //\r
1727 if (Question->QuestionId == 0) {\r
1728 return Status;\r
1729 }\r
1730\r
1731 //\r
1732 // There are three ways to specify default value for a Question:\r
1733 // 1, use nested EFI_IFR_DEFAULT (highest priority)\r
1734 // 2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
1735 // 3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
1736 //\r
1737 HiiValue = &Question->HiiValue;\r
1738\r
1739 //\r
1740 // EFI_IFR_DEFAULT has highest priority\r
1741 //\r
1742 if (!IsListEmpty (&Question->DefaultListHead)) {\r
1743 Link = GetFirstNode (&Question->DefaultListHead);\r
1744 while (!IsNull (&Question->DefaultListHead, Link)) {\r
1745 Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
1746\r
1747 if (Default->DefaultId == DefaultId) {\r
1748 if (Default->ValueExpression != NULL) {\r
1749 //\r
1750 // Default is provided by an Expression, evaluate it\r
1751 //\r
1752 Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
1753 if (EFI_ERROR (Status)) {\r
1754 return Status;\r
1755 }\r
1756\r
1757 CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_VALUE));\r
1758 } else {\r
1759 //\r
1760 // Default value is embedded in EFI_IFR_DEFAULT\r
1761 //\r
1762 CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
1763 }\r
1764\r
1765 return EFI_SUCCESS;\r
1766 }\r
1767\r
1768 Link = GetNextNode (&Question->DefaultListHead, Link);\r
1769 }\r
1770 }\r
1771\r
1772 //\r
1773 // EFI_ONE_OF_OPTION\r
1774 //\r
1775 if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
1776 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
1777 //\r
1778 // OneOfOption could only provide Standard and Manufacturing default\r
1779 //\r
1780 Link = GetFirstNode (&Question->OptionListHead);\r
1781 while (!IsNull (&Question->OptionListHead, Link)) {\r
1782 Option = QUESTION_OPTION_FROM_LINK (Link);\r
1783\r
1784 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
1785 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
1786 ) {\r
1787 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
1788\r
1789 return EFI_SUCCESS;\r
1790 }\r
1791\r
1792 Link = GetNextNode (&Question->OptionListHead, Link);\r
1793 }\r
1794 }\r
1795 }\r
1796\r
1797 //\r
1798 // EFI_IFR_CHECKBOX - lowest priority\r
1799 //\r
1800 if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
1801 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
1802 //\r
1803 // Checkbox could only provide Standard and Manufacturing default\r
1804 //\r
1805 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
1806 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
1807 ) {\r
1808 HiiValue->Value.b = TRUE;\r
1809 } else {\r
1810 HiiValue->Value.b = FALSE;\r
1811 }\r
1812\r
1813 return EFI_SUCCESS;\r
1814 }\r
1815 }\r
1816\r
1817 //\r
1818 // For Questions without default\r
1819 //\r
1820 switch (Question->Operand) {\r
1821 case EFI_IFR_NUMERIC_OP:\r
1822 //\r
1823 // Take minimal value as numeric's default value\r
1824 //\r
1825 HiiValue->Value.u64 = Question->Minimum;\r
1826 break;\r
1827\r
1828 case EFI_IFR_ONE_OF_OP:\r
1829 //\r
1830 // Take first oneof option as oneof's default value\r
1831 //\r
1832 Link = GetFirstNode (&Question->OptionListHead);\r
1833 if (!IsNull (&Question->OptionListHead, Link)) {\r
1834 Option = QUESTION_OPTION_FROM_LINK (Link);\r
1835 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
1836 }\r
1837 break;\r
1838\r
1839 case EFI_IFR_ORDERED_LIST_OP:\r
1840 //\r
1841 // Take option sequence in IFR as ordered list's default value\r
1842 //\r
1843 Index = 0;\r
1844 Link = GetFirstNode (&Question->OptionListHead);\r
1845 while (!IsNull (&Question->OptionListHead, Link)) {\r
1846 Option = QUESTION_OPTION_FROM_LINK (Link);\r
1847\r
1848 Question->BufferValue[Index] = Option->Value.Value.u8;\r
1849\r
1850 Index++;\r
1851 if (Index >= Question->MaxContainers) {\r
1852 break;\r
1853 }\r
1854\r
1855 Link = GetNextNode (&Question->OptionListHead, Link);\r
1856 }\r
1857 break;\r
1858\r
1859 default:\r
1860 Status = EFI_NOT_FOUND;\r
1861 break;\r
1862 }\r
1863\r
1864 return Status;\r
1865}\r
1866\r
1867\r
1868/**\r
1869 Reset Questions in a Form to their default value.\r
1870\r
1871 @param FormSet FormSet data structure.\r
1872 @param Form The Form which to be reset.\r
1873 @param DefaultId The Class of the default.\r
1874\r
1875 @retval EFI_SUCCESS The function completed successfully.\r
1876\r
1877**/\r
1878EFI_STATUS\r
1879ExtractFormDefault (\r
1880 IN FORM_BROWSER_FORMSET *FormSet,\r
1881 IN FORM_BROWSER_FORM *Form,\r
1882 IN UINT16 DefaultId\r
1883 )\r
1884{\r
1885 EFI_STATUS Status;\r
1886 LIST_ENTRY *Link;\r
1887 FORM_BROWSER_STATEMENT *Question;\r
1888\r
1889 Link = GetFirstNode (&Form->StatementListHead);\r
1890 while (!IsNull (&Form->StatementListHead, Link)) {\r
1891 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
1892 Link = GetNextNode (&Form->StatementListHead, Link);\r
1893\r
1894 //\r
1895 // Reset Question to its default value\r
1896 //\r
1897 Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
1898 if (EFI_ERROR (Status)) {\r
1899 continue;\r
1900 }\r
1901\r
1902 //\r
1903 // Synchronize Buffer storage's Edit buffer\r
1904 //\r
1905 if ((Question->Storage != NULL) &&\r
1906 (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
1907 SetQuestionValue (FormSet, Form, Question, TRUE);\r
1908 }\r
1909 }\r
1910\r
1911 return EFI_SUCCESS;\r
1912}\r
1913\r
1914\r
1915/**\r
1916 Initialize Question's Edit copy from Storage.\r
1917\r
1918 @param FormSet FormSet data structure.\r
1919 @param Form Form data structure.\r
1920\r
1921 @retval EFI_SUCCESS The function completed successfully.\r
1922\r
1923**/\r
1924EFI_STATUS\r
1925LoadFormConfig (\r
1926 IN FORM_BROWSER_FORMSET *FormSet,\r
1927 IN FORM_BROWSER_FORM *Form\r
1928 )\r
1929{\r
1930 EFI_STATUS Status;\r
1931 LIST_ENTRY *Link;\r
1932 FORM_BROWSER_STATEMENT *Question;\r
1933\r
1934 Link = GetFirstNode (&Form->StatementListHead);\r
1935 while (!IsNull (&Form->StatementListHead, Link)) {\r
1936 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
1937\r
1938 //\r
1939 // Initialize local copy of Value for each Question\r
1940 //\r
1941 Status = GetQuestionValue (FormSet, Form, Question, TRUE);\r
1942 if (EFI_ERROR (Status)) {\r
1943 return Status;\r
1944 }\r
1945\r
1946 Link = GetNextNode (&Form->StatementListHead, Link);\r
1947 }\r
1948\r
1949 return EFI_SUCCESS;\r
1950}\r
1951\r
1952\r
1953/**\r
1954 Fill storage's edit copy with settings requested from Configuration Driver.\r
1955\r
1956 @param FormSet FormSet data structure.\r
1957 @param Storage Buffer Storage.\r
1958\r
1959 @retval EFI_SUCCESS The function completed successfully.\r
1960\r
1961**/\r
1962EFI_STATUS\r
1963LoadStorage (\r
1964 IN FORM_BROWSER_FORMSET *FormSet,\r
1965 IN FORMSET_STORAGE *Storage\r
1966 )\r
1967{\r
1968 EFI_STATUS Status;\r
1969 EFI_STRING Progress;\r
1970 EFI_STRING Result;\r
1971 CHAR16 *StrPtr;\r
1972\r
1973 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1974 return EFI_SUCCESS;\r
1975 }\r
1976\r
1977 if (FormSet->ConfigAccess == NULL) {\r
1978 return EFI_NOT_FOUND;\r
1979 }\r
1980\r
1981 if (Storage->ElementCount == 0) {\r
1982 //\r
1983 // Skip if there is no RequestElement\r
1984 //\r
1985 return EFI_SUCCESS;\r
1986 }\r
1987\r
1988 //\r
1989 // Request current settings from Configuration Driver\r
1990 //\r
1991 Status = FormSet->ConfigAccess->ExtractConfig (\r
1992 FormSet->ConfigAccess,\r
1993 Storage->ConfigRequest,\r
1994 &Progress,\r
1995 &Result\r
1996 );\r
1997 if (EFI_ERROR (Status)) {\r
1998 return Status;\r
1999 }\r
2000\r
2001 //\r
2002 // Convert Result from <ConfigAltResp> to <ConfigResp>\r
2003 //\r
2004 StrPtr = StrStr (Result, L"ALTCFG");\r
2005 if (StrPtr != NULL) {\r
2006 *StrPtr = L'\0';\r
2007 }\r
2008\r
2009 Status = ConfigRespToStorage (Storage, Result);\r
2010 gBS->FreePool (Result);\r
2011 return Status;\r
2012}\r
2013\r
2014\r
2015/**\r
2016 Get current setting of Questions.\r
2017\r
2018 @param FormSet FormSet data structure.\r
2019\r
2020 @retval EFI_SUCCESS The function completed successfully.\r
2021\r
2022**/\r
2023EFI_STATUS\r
2024InitializeCurrentSetting (\r
2025 IN OUT FORM_BROWSER_FORMSET *FormSet\r
2026 )\r
2027{\r
2028 LIST_ENTRY *Link;\r
2029 FORMSET_STORAGE *Storage;\r
2030 FORM_BROWSER_FORM *Form;\r
2031 EFI_STATUS Status;\r
2032\r
2033 //\r
2034 // Extract default from IFR binary\r
2035 //\r
2036 Link = GetFirstNode (&FormSet->FormListHead);\r
2037 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2038 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2039\r
2040 Status = ExtractFormDefault (FormSet, Form, EFI_HII_DEFAULT_CLASS_STANDARD);\r
2041\r
2042 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2043 }\r
2044\r
2045 //\r
2046 // Request current settings from Configuration Driver\r
2047 //\r
2048 Link = GetFirstNode (&FormSet->StorageListHead);\r
2049 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
2050 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
2051\r
2052 Status = LoadStorage (FormSet, Storage);\r
2053\r
2054 //\r
2055 // Now Edit Buffer is filled with default values(lower priority) and current\r
2056 // settings(higher priority), sychronize it to shadow Buffer\r
2057 //\r
2058 if (!EFI_ERROR (Status)) {\r
2059 SynchronizeStorage (Storage);\r
2060 }\r
2061\r
2062 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
2063 }\r
2064\r
2065 return EFI_SUCCESS;\r
2066}\r
2067\r
2068\r
2069/**\r
2070 Fetch the Ifr binary data of a FormSet.\r
2071\r
2072 @param Handle PackageList Handle\r
2073 @param FormSetGuid GUID of a formset. If not specified (NULL or zero\r
2074 GUID), take the first FormSet found in package\r
2075 list.\r
2076 @param BinaryLength The length of the FormSet IFR binary.\r
2077 @param BinaryData The buffer designed to receive the FormSet.\r
2078\r
2079 @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
2080 BufferLength was updated.\r
2081 @retval EFI_INVALID_PARAMETER The handle is unknown.\r
2082 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
2083 be found with the requested FormId.\r
2084\r
2085**/\r
2086EFI_STATUS\r
2087GetIfrBinaryData (\r
2088 IN EFI_HII_HANDLE Handle,\r
2089 IN OUT EFI_GUID *FormSetGuid,\r
2090 OUT UINTN *BinaryLength,\r
2091 OUT UINT8 **BinaryData\r
2092 )\r
2093{\r
2094 EFI_STATUS Status;\r
2095 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
2096 UINTN BufferSize;\r
2097 UINT8 *Package;\r
2098 UINT8 *OpCodeData;\r
2099 UINT32 Offset;\r
2100 UINT32 Offset2;\r
2101 BOOLEAN ReturnDefault;\r
2102 UINT32 PackageListLength;\r
2103 EFI_HII_PACKAGE_HEADER PackageHeader;\r
2104\r
2105 OpCodeData = NULL;\r
2106 Package = NULL;\r
2107 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;\r
2108\r
2109 //\r
2110 // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list\r
2111 //\r
2112 if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {\r
2113 ReturnDefault = TRUE;\r
2114 } else {\r
2115 ReturnDefault = FALSE;\r
2116 }\r
2117\r
2118 //\r
2119 // Get HII PackageList\r
2120 //\r
2121 BufferSize = 0;\r
2122 HiiPackageList = NULL;\r
2123 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
2124 if (Status == EFI_BUFFER_TOO_SMALL) {\r
2125 HiiPackageList = AllocatePool (BufferSize);\r
2126 ASSERT (HiiPackageList != NULL);\r
2127\r
2128 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
2129 }\r
2130 if (EFI_ERROR (Status)) {\r
2131 return Status;\r
2132 }\r
2133\r
2134 //\r
2135 // Get Form package from this HII package List\r
2136 //\r
2137 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
2138 Offset2 = 0;\r
2139 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
2140\r
2141 while (Offset < PackageListLength) {\r
2142 Package = ((UINT8 *) HiiPackageList) + Offset;\r
2143 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
2144\r
2145 if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {\r
2146 //\r
2147 // Search FormSet in this Form Package\r
2148 //\r
2149 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
2150 while (Offset2 < PackageHeader.Length) {\r
2151 OpCodeData = Package + Offset2;\r
2152\r
2153 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
2154 //\r
2155 // Check whether return default FormSet\r
2156 //\r
2157 if (ReturnDefault) {\r
2158 break;\r
2159 }\r
2160\r
2161 //\r
2162 // FormSet GUID is specified, check it\r
2163 //\r
2164 if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
2165 break;\r
2166 }\r
2167 }\r
2168\r
2169 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
2170 }\r
2171\r
2172 if (Offset2 < PackageHeader.Length) {\r
2173 //\r
2174 // Target formset found\r
2175 //\r
2176 break;\r
2177 }\r
2178 }\r
2179\r
2180 Offset += PackageHeader.Length;\r
2181 }\r
2182\r
2183 if (Offset >= PackageListLength) {\r
2184 //\r
2185 // Form package not found in this Package List\r
2186 //\r
2187 gBS->FreePool (HiiPackageList);\r
2188 return EFI_NOT_FOUND;\r
2189 }\r
2190\r
2191 if (ReturnDefault && FormSetGuid != NULL) {\r
2192 //\r
2193 // Return the default FormSet GUID\r
2194 //\r
2195 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
2196 }\r
2197\r
2198 //\r
2199 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
2200 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
2201 // of the Form Package.\r
2202 //\r
2203 *BinaryLength = PackageHeader.Length - Offset2;\r
2204 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
2205\r
2206 gBS->FreePool (HiiPackageList);\r
2207\r
2208 if (*BinaryData == NULL) {\r
2209 return EFI_OUT_OF_RESOURCES;\r
2210 }\r
2211\r
2212 return EFI_SUCCESS;\r
2213}\r
2214\r
2215\r
2216/**\r
2217 Initialize the internal data structure of a FormSet.\r
2218\r
2219 @param Handle PackageList Handle\r
2220 @param FormSetGuid GUID of a formset. If not specified (NULL or zero\r
2221 GUID), take the first FormSet found in package\r
2222 list.\r
2223 @param FormSet FormSet data structure.\r
2224\r
2225 @retval EFI_SUCCESS The function completed successfully.\r
2226 @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
2227\r
2228**/\r
2229EFI_STATUS\r
2230InitializeFormSet (\r
2231 IN EFI_HII_HANDLE Handle,\r
2232 IN OUT EFI_GUID *FormSetGuid,\r
2233 OUT FORM_BROWSER_FORMSET *FormSet\r
2234 )\r
2235{\r
2236 EFI_STATUS Status;\r
2237 EFI_HANDLE DriverHandle;\r
2238 UINT16 Index;\r
2239\r
2240 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
2241 if (EFI_ERROR (Status)) {\r
2242 return Status;\r
2243 }\r
2244\r
2245 FormSet->HiiHandle = Handle;\r
2246 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
2247\r
2248 //\r
2249 // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
2250 //\r
2251 Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
2252 if (EFI_ERROR (Status)) {\r
2253 return Status;\r
2254 }\r
2255 FormSet->DriverHandle = DriverHandle;\r
2256 Status = gBS->HandleProtocol (\r
2257 DriverHandle,\r
2258 &gEfiHiiConfigAccessProtocolGuid,\r
2259 (VOID **) &FormSet->ConfigAccess\r
2260 );\r
2261 if (EFI_ERROR (Status)) {\r
2262 //\r
2263 // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
2264 // list, then there will be no configuration action required\r
2265 //\r
2266 FormSet->ConfigAccess = NULL;\r
2267 }\r
2268\r
2269 //\r
2270 // Parse the IFR binary OpCodes\r
2271 //\r
2272 Status = ParseOpCodes (FormSet);\r
2273 if (EFI_ERROR (Status)) {\r
2274 return Status;\r
2275 }\r
2276\r
2277 gClassOfVfr = FormSet->SubClass;\r
2278 if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {\r
2279 FrontPageHandle = FormSet->HiiHandle;\r
2280 }\r
2281\r
2282 //\r
2283 // Match GUID to find out the function key setting. If match fail, use the default setting.\r
2284 //\r
2285 for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {\r
2286 if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {\r
2287 //\r
2288 // Update the function key setting.\r
2289 //\r
2290 gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;\r
2291 //\r
2292 // Function key prompt can not be displayed if the function key has been disabled.\r
2293 //\r
2294 if ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE) {\r
2295 gFunctionOneString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2296 }\r
2297\r
2298 if ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO) {\r
2299 gFunctionTwoString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2300 }\r
2301\r
2302 if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {\r
2303 gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2304 }\r
2305\r
2306 if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {\r
2307 gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2308 }\r
2309 }\r
2310 }\r
2311\r
2312 return Status;\r
2313}\r