]> 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
676df92c 727 if (*Dest != NULL) {\r
728 FreePool (*Dest);\r
729 }\r
7936fb6a 730 *Dest = AllocateCopyPool (StrSize (Src), Src);\r
731 ASSERT (*Dest != NULL);\r
732}\r
733\r
734\r
735/**\r
736 Allocate new memory and concatinate Source on the end of Destination.\r
737\r
738 @param Dest String to added to the end of.\r
739 @param Src String to concatinate.\r
740\r
741**/\r
742VOID\r
743NewStringCat (\r
744 IN OUT CHAR16 **Dest,\r
745 IN CHAR16 *Src\r
746 )\r
747{\r
748 CHAR16 *NewString;\r
749 UINTN TmpSize;\r
750\r
751 if (*Dest == NULL) {\r
752 NewStringCpy (Dest, Src);\r
753 return;\r
754 }\r
755\r
756 TmpSize = StrSize (*Dest);\r
757 NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1);\r
758 ASSERT (NewString != NULL);\r
759\r
760 StrCpy (NewString, *Dest);\r
761 StrCat (NewString, Src);\r
762\r
763 gBS->FreePool (*Dest);\r
764 *Dest = NewString;\r
765}\r
766\r
767\r
768/**\r
769 Synchronize Storage's Edit copy to Shadow copy.\r
770\r
771 @param Storage The Storage to be synchronized.\r
772\r
773**/\r
774VOID\r
775SynchronizeStorage (\r
776 IN FORMSET_STORAGE *Storage\r
777 )\r
778{\r
779 LIST_ENTRY *Link;\r
780 NAME_VALUE_NODE *Node;\r
781\r
782 switch (Storage->Type) {\r
783 case EFI_HII_VARSTORE_BUFFER:\r
784 CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);\r
785 break;\r
786\r
787 case EFI_HII_VARSTORE_NAME_VALUE:\r
788 Link = GetFirstNode (&Storage->NameValueListHead);\r
789 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
790 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
791\r
792 NewStringCpy (&Node->Value, Node->EditValue);\r
793\r
794 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
795 }\r
796 break;\r
797\r
798 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
799 default:\r
800 break;\r
801 }\r
802}\r
803\r
804\r
805/**\r
806 Get Value for given Name from a NameValue Storage.\r
807\r
808 @param Storage The NameValue Storage.\r
809 @param Name The Name.\r
810 @param Value The retured Value.\r
811\r
812 @retval EFI_SUCCESS Value found for given Name.\r
813 @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
814\r
815**/\r
816EFI_STATUS\r
817GetValueByName (\r
818 IN FORMSET_STORAGE *Storage,\r
819 IN CHAR16 *Name,\r
820 IN OUT CHAR16 **Value\r
821 )\r
822{\r
823 LIST_ENTRY *Link;\r
824 NAME_VALUE_NODE *Node;\r
825\r
826 *Value = NULL;\r
827\r
828 Link = GetFirstNode (&Storage->NameValueListHead);\r
829 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
830 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
831\r
832 if (StrCmp (Name, Node->Name) == 0) {\r
833 NewStringCpy (Value, Node->EditValue);\r
834 return EFI_SUCCESS;\r
835 }\r
836\r
837 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
838 }\r
839\r
840 return EFI_NOT_FOUND;\r
841}\r
842\r
843\r
844/**\r
845 Set Value of given Name in a NameValue Storage.\r
846\r
847 @param Storage The NameValue Storage.\r
848 @param Name The Name.\r
849 @param Value The Value to set.\r
850\r
851 @retval EFI_SUCCESS Value found for given Name.\r
852 @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
853\r
854**/\r
855EFI_STATUS\r
856SetValueByName (\r
857 IN FORMSET_STORAGE *Storage,\r
858 IN CHAR16 *Name,\r
859 IN CHAR16 *Value\r
860 )\r
861{\r
862 LIST_ENTRY *Link;\r
863 NAME_VALUE_NODE *Node;\r
864\r
865 Link = GetFirstNode (&Storage->NameValueListHead);\r
866 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
867 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
868\r
869 if (StrCmp (Name, Node->Name) == 0) {\r
676df92c 870 if (Node->EditValue != NULL) {\r
871 FreePool (Node->EditValue);\r
872 }\r
7936fb6a 873 Node->EditValue = AllocateCopyPool (StrSize (Value), Value);\r
874 ASSERT (Node->EditValue != NULL);\r
875 return EFI_SUCCESS;\r
876 }\r
877\r
878 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
879 }\r
880\r
881 return EFI_NOT_FOUND;\r
882}\r
883\r
884\r
885/**\r
886 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
887\r
888 @param Storage The Storage to be conveted.\r
889 @param ConfigResp The returned <ConfigResp>.\r
890\r
891 @retval EFI_SUCCESS Convert success.\r
892 @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
893\r
894**/\r
895EFI_STATUS\r
896StorageToConfigResp (\r
897 IN FORMSET_STORAGE *Storage,\r
898 IN CHAR16 **ConfigResp\r
899 )\r
900{\r
901 EFI_STATUS Status;\r
902 EFI_STRING Progress;\r
903 LIST_ENTRY *Link;\r
904 NAME_VALUE_NODE *Node;\r
905\r
906 Status = EFI_SUCCESS;\r
907\r
908 switch (Storage->Type) {\r
909 case EFI_HII_VARSTORE_BUFFER:\r
910 Status = mHiiConfigRouting->BlockToConfig (\r
911 mHiiConfigRouting,\r
912 Storage->ConfigRequest,\r
913 Storage->EditBuffer,\r
914 Storage->Size,\r
915 ConfigResp,\r
916 &Progress\r
917 );\r
918 break;\r
919\r
920 case EFI_HII_VARSTORE_NAME_VALUE:\r
921 *ConfigResp = NULL;\r
922 NewStringCat (ConfigResp, Storage->ConfigHdr);\r
923\r
924 Link = GetFirstNode (&Storage->NameValueListHead);\r
925 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
926 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
927\r
928 NewStringCat (ConfigResp, L"&");\r
929 NewStringCat (ConfigResp, Node->Name);\r
930 NewStringCat (ConfigResp, L"=");\r
931 NewStringCat (ConfigResp, Node->EditValue);\r
932\r
933 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
934 }\r
935 break;\r
936\r
937 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
938 default:\r
939 Status = EFI_INVALID_PARAMETER;\r
940 break;\r
941 }\r
942\r
943 return Status;\r
944}\r
945\r
946\r
947/**\r
948 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.\r
949\r
950 @param Storage The Storage to receive the settings.\r
951 @param ConfigResp The <ConfigResp> to be converted.\r
952\r
953 @retval EFI_SUCCESS Convert success.\r
954 @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
955\r
956**/\r
957EFI_STATUS\r
958ConfigRespToStorage (\r
959 IN FORMSET_STORAGE *Storage,\r
960 IN CHAR16 *ConfigResp\r
961 )\r
962{\r
963 EFI_STATUS Status;\r
964 EFI_STRING Progress;\r
965 UINTN BufferSize;\r
966 CHAR16 *StrPtr;\r
967 CHAR16 *Name;\r
968 CHAR16 *Value;\r
969\r
970 Status = EFI_SUCCESS;\r
971\r
972 switch (Storage->Type) {\r
973 case EFI_HII_VARSTORE_BUFFER:\r
974 BufferSize = Storage->Size;\r
975 Status = mHiiConfigRouting->ConfigToBlock (\r
976 mHiiConfigRouting,\r
977 ConfigResp,\r
978 Storage->EditBuffer,\r
979 &BufferSize,\r
980 &Progress\r
981 );\r
982 break;\r
983\r
984 case EFI_HII_VARSTORE_NAME_VALUE:\r
985 StrPtr = StrStr (ConfigResp, L"&");\r
986 while (StrPtr != NULL) {\r
987 //\r
988 // Skip '&'\r
989 //\r
990 StrPtr = StrPtr + 1;\r
991 Name = StrPtr;\r
992 StrPtr = StrStr (StrPtr, L"=");\r
993 if (StrPtr == NULL) {\r
994 break;\r
995 }\r
996 *StrPtr = 0;\r
997\r
998 //\r
999 // Skip '='\r
1000 //\r
1001 StrPtr = StrPtr + 1;\r
1002 Value = StrPtr;\r
1003 StrPtr = StrStr (StrPtr, L"&");\r
1004 if (StrPtr != NULL) {\r
1005 *StrPtr = 0;\r
1006 }\r
1007 SetValueByName (Storage, Name, Value);\r
1008 }\r
1009 break;\r
1010\r
1011 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
1012 default:\r
1013 Status = EFI_INVALID_PARAMETER;\r
1014 break;\r
1015 }\r
1016\r
1017 return Status;\r
1018}\r
1019\r
1020\r
1021/**\r
1022 Get Question's current Value.\r
1023\r
1024 @param FormSet FormSet data structure.\r
1025 @param Form Form data structure.\r
1026 @param Question Question to be initialized.\r
1027 @param Cached TRUE: get from Edit copy FALSE: get from original\r
1028 Storage\r
1029\r
1030 @retval EFI_SUCCESS The function completed successfully.\r
1031\r
1032**/\r
1033EFI_STATUS\r
1034GetQuestionValue (\r
1035 IN FORM_BROWSER_FORMSET *FormSet,\r
1036 IN FORM_BROWSER_FORM *Form,\r
1037 IN OUT FORM_BROWSER_STATEMENT *Question,\r
1038 IN BOOLEAN Cached\r
1039 )\r
1040{\r
1041 EFI_STATUS Status;\r
1042 BOOLEAN Enabled;\r
1043 BOOLEAN Pending;\r
1044 UINT8 *Dst;\r
1045 UINTN StorageWidth;\r
1046 EFI_TIME EfiTime;\r
1047 FORMSET_STORAGE *Storage;\r
1048 EFI_IFR_TYPE_VALUE *QuestionValue;\r
1049 CHAR16 *ConfigRequest;\r
1050 CHAR16 *Progress;\r
1051 CHAR16 *Result;\r
1052 CHAR16 *Value;\r
1053 UINTN Length;\r
1054 BOOLEAN IsBufferStorage;\r
1055 BOOLEAN IsString;\r
1056\r
1057 Status = EFI_SUCCESS;\r
1058\r
1059 //\r
1060 // Statement don't have storage, skip them\r
1061 //\r
1062 if (Question->QuestionId == 0) {\r
1063 return Status;\r
1064 }\r
1065\r
1066 //\r
1067 // Question value is provided by an Expression, evaluate it\r
1068 //\r
1069 if (Question->ValueExpression != NULL) {\r
1070 Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);\r
1071 if (!EFI_ERROR (Status)) {\r
1072 CopyMem (&Question->HiiValue, &Question->ValueExpression->Result, sizeof (EFI_HII_VALUE));\r
1073 }\r
1074 return Status;\r
1075 }\r
1076\r
1077 //\r
1078 // Question value is provided by RTC\r
1079 //\r
1080 Storage = Question->Storage;\r
1081 QuestionValue = &Question->HiiValue.Value;\r
1082 if (Storage == NULL) {\r
1083 //\r
1084 // It's a Question without storage, or RTC date/time\r
1085 //\r
1086 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1087 //\r
1088 // Date and time define the same Flags bit\r
1089 //\r
1090 switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
1091 case QF_DATE_STORAGE_TIME:\r
1092 Status = gRT->GetTime (&EfiTime, NULL);\r
1093 break;\r
1094\r
1095 case QF_DATE_STORAGE_WAKEUP:\r
1096 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
1097 break;\r
1098\r
1099 case QF_DATE_STORAGE_NORMAL:\r
1100 default:\r
1101 //\r
1102 // For date/time without storage\r
1103 //\r
1104 return EFI_SUCCESS;\r
1105 }\r
1106\r
1107 if (EFI_ERROR (Status)) {\r
1108 return Status;\r
1109 }\r
1110\r
1111 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1112 QuestionValue->date.Year = EfiTime.Year;\r
1113 QuestionValue->date.Month = EfiTime.Month;\r
1114 QuestionValue->date.Day = EfiTime.Day;\r
1115 } else {\r
1116 QuestionValue->time.Hour = EfiTime.Hour;\r
1117 QuestionValue->time.Minute = EfiTime.Minute;\r
1118 QuestionValue->time.Second = EfiTime.Second;\r
1119 }\r
1120 }\r
1121\r
1122 return EFI_SUCCESS;\r
1123 }\r
1124\r
1125 //\r
1126 // Question value is provided by EFI variable\r
1127 //\r
1128 StorageWidth = Question->StorageWidth;\r
1129 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1130 if (Question->BufferValue != NULL) {\r
1131 Dst = Question->BufferValue;\r
1132 } else {\r
1133 Dst = (UINT8 *) QuestionValue;\r
1134 }\r
1135\r
1136 Status = gRT->GetVariable (\r
1137 Question->VariableName,\r
1138 &Storage->Guid,\r
1139 NULL,\r
1140 &StorageWidth,\r
1141 Dst\r
1142 );\r
1143 //\r
1144 // Always return success, even this EFI variable doesn't exist\r
1145 //\r
1146 return EFI_SUCCESS;\r
1147 }\r
1148\r
1149 //\r
1150 // Question Value is provided by Buffer Storage or NameValue Storage\r
1151 //\r
1152 if (Question->BufferValue != NULL) {\r
1153 //\r
1154 // This Question is password or orderedlist\r
1155 //\r
1156 Dst = Question->BufferValue;\r
1157 } else {\r
1158 //\r
1159 // Other type of Questions\r
1160 //\r
1161 Dst = (UINT8 *) &Question->HiiValue.Value;\r
1162 }\r
1163\r
1164 IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
1165 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
1166 if (Cached) {\r
1167 if (IsBufferStorage) {\r
1168 //\r
1169 // Copy from storage Edit buffer\r
1170 //\r
1171 CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
1172 } else {\r
1173 Status = GetValueByName (Storage, Question->VariableName, &Value);\r
1174 if (EFI_ERROR (Status)) {\r
1175 return Status;\r
1176 }\r
1177\r
1178 if (IsString) {\r
1179 //\r
1180 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
1181 //\r
1182 Length = StorageWidth + sizeof (CHAR16);\r
1183 Status = ConfigStringToUnicode ((CHAR16 *) Dst, &Length, Value);\r
1184 } else {\r
1185 Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);\r
1186 }\r
1187\r
1188 gBS->FreePool (Value);\r
1189 }\r
1190 } else {\r
1191 //\r
1192 // Request current settings from Configuration Driver\r
1193 //\r
1194 if (FormSet->ConfigAccess == NULL) {\r
1195 return EFI_NOT_FOUND;\r
1196 }\r
1197\r
1198 //\r
1199 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
1200 // <ConfigHdr> + "&" + <VariableName>\r
1201 //\r
1202 if (IsBufferStorage) {\r
1203 Length = StrLen (Storage->ConfigHdr);\r
1204 Length += StrLen (Question->BlockName);\r
1205 } else {\r
1206 Length = StrLen (Storage->ConfigHdr);\r
1207 Length += StrLen (Question->VariableName) + 1;\r
1208 }\r
1209 ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
1210 ASSERT (ConfigRequest != NULL);\r
1211\r
1212 StrCpy (ConfigRequest, Storage->ConfigHdr);\r
1213 if (IsBufferStorage) {\r
1214 StrCat (ConfigRequest, Question->BlockName);\r
1215 } else {\r
1216 StrCat (ConfigRequest, L"&");\r
1217 StrCat (ConfigRequest, Question->VariableName);\r
1218 }\r
1219\r
1220 Status = FormSet->ConfigAccess->ExtractConfig (\r
1221 FormSet->ConfigAccess,\r
1222 ConfigRequest,\r
1223 &Progress,\r
1224 &Result\r
1225 );\r
1226 if (EFI_ERROR (Status)) {\r
1227 return Status;\r
1228 }\r
1229\r
1230 //\r
1231 // Skip <ConfigRequest>\r
1232 //\r
1233 Value = Result + Length;\r
1234 if (IsBufferStorage) {\r
1235 //\r
1236 // Skip "&VALUE"\r
1237 //\r
1238 Value = Value + 6;\r
1239 }\r
1240 if (*Value != '=') {\r
1241 gBS->FreePool (Result);\r
1242 return EFI_NOT_FOUND;\r
1243 }\r
1244 //\r
1245 // Skip '=', point to value\r
1246 //\r
1247 Value = Value + 1;\r
1248 if (!IsBufferStorage && IsString) {\r
1249 //\r
1250 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
1251 //\r
1252 Length = StorageWidth + sizeof (CHAR16);\r
1253 Status = ConfigStringToUnicode ((CHAR16 *) Dst, &Length, Value);\r
1254 } else {\r
1255 Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);\r
1256 if (EFI_ERROR (Status)) {\r
1257 gBS->FreePool (Result);\r
1258 return Status;\r
1259 }\r
1260 }\r
1261\r
1262 //\r
1263 // Synchronize Edit Buffer\r
1264 //\r
1265 if (IsBufferStorage) {\r
1266 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
1267 } else {\r
1268 SetValueByName (Storage, Question->VariableName, Value);\r
1269 }\r
1270 gBS->FreePool (Result);\r
1271 }\r
1272\r
1273 return Status;\r
1274}\r
1275\r
1276\r
1277/**\r
1278 Save Question Value to edit copy(cached) or Storage(uncached).\r
1279\r
1280 @param FormSet FormSet data structure.\r
1281 @param Form Form data structure.\r
1282 @param Question Pointer to the Question.\r
1283 @param Cached TRUE: set to Edit copy FALSE: set to original\r
1284 Storage\r
1285\r
1286 @retval EFI_SUCCESS The function completed successfully.\r
1287\r
1288**/\r
1289EFI_STATUS\r
1290SetQuestionValue (\r
1291 IN FORM_BROWSER_FORMSET *FormSet,\r
1292 IN FORM_BROWSER_FORM *Form,\r
1293 IN OUT FORM_BROWSER_STATEMENT *Question,\r
1294 IN BOOLEAN Cached\r
1295 )\r
1296{\r
1297 EFI_STATUS Status;\r
1298 BOOLEAN Enabled;\r
1299 BOOLEAN Pending;\r
1300 UINT8 *Src;\r
1301 EFI_TIME EfiTime;\r
1302 UINTN BufferLen;\r
1303 UINTN StorageWidth;\r
1304 FORMSET_STORAGE *Storage;\r
1305 EFI_IFR_TYPE_VALUE *QuestionValue;\r
1306 CHAR16 *ConfigResp;\r
1307 CHAR16 *Progress;\r
1308 CHAR16 *Value;\r
1309 UINTN Length;\r
1310 BOOLEAN IsBufferStorage;\r
1311 BOOLEAN IsString;\r
1312\r
1313 Status = EFI_SUCCESS;\r
1314\r
1315 //\r
1316 // Statement don't have storage, skip them\r
1317 //\r
1318 if (Question->QuestionId == 0) {\r
1319 return Status;\r
1320 }\r
1321\r
1322 //\r
1323 // If Question value is provided by an Expression, then it is read only\r
1324 //\r
1325 if (Question->ValueExpression != NULL) {\r
1326 return Status;\r
1327 }\r
1328\r
1329 //\r
1330 // Question value is provided by RTC\r
1331 //\r
1332 Storage = Question->Storage;\r
1333 QuestionValue = &Question->HiiValue.Value;\r
1334 if (Storage == NULL) {\r
1335 //\r
1336 // It's a Question without storage, or RTC date/time\r
1337 //\r
1338 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1339 //\r
1340 // Date and time define the same Flags bit\r
1341 //\r
1342 switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
1343 case QF_DATE_STORAGE_TIME:\r
1344 Status = gRT->GetTime (&EfiTime, NULL);\r
1345 break;\r
1346\r
1347 case QF_DATE_STORAGE_WAKEUP:\r
1348 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
1349 break;\r
1350\r
1351 case QF_DATE_STORAGE_NORMAL:\r
1352 default:\r
1353 //\r
1354 // For date/time without storage\r
1355 //\r
1356 return EFI_SUCCESS;\r
1357 }\r
1358\r
1359 if (EFI_ERROR (Status)) {\r
1360 return Status;\r
1361 }\r
1362\r
1363 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1364 EfiTime.Year = QuestionValue->date.Year;\r
1365 EfiTime.Month = QuestionValue->date.Month;\r
1366 EfiTime.Day = QuestionValue->date.Day;\r
1367 } else {\r
1368 EfiTime.Hour = QuestionValue->time.Hour;\r
1369 EfiTime.Minute = QuestionValue->time.Minute;\r
1370 EfiTime.Second = QuestionValue->time.Second;\r
1371 }\r
1372\r
1373 if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {\r
1374 Status = gRT->SetTime (&EfiTime);\r
1375 } else {\r
1376 Status = gRT->SetWakeupTime (TRUE, &EfiTime);\r
1377 }\r
1378 }\r
1379\r
1380 return Status;\r
1381 }\r
1382\r
1383 //\r
1384 // Question value is provided by EFI variable\r
1385 //\r
1386 StorageWidth = Question->StorageWidth;\r
1387 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1388 if (Question->BufferValue != NULL) {\r
1389 Src = Question->BufferValue;\r
1390 } else {\r
1391 Src = (UINT8 *) QuestionValue;\r
1392 }\r
1393\r
1394 Status = gRT->SetVariable (\r
1395 Question->VariableName,\r
1396 &Storage->Guid,\r
1397 Storage->Attributes,\r
1398 StorageWidth,\r
1399 Src\r
1400 );\r
1401 return Status;\r
1402 }\r
1403\r
1404 //\r
1405 // Question Value is provided by Buffer Storage or NameValue Storage\r
1406 //\r
1407 if (Question->BufferValue != NULL) {\r
1408 Src = Question->BufferValue;\r
1409 } else {\r
1410 Src = (UINT8 *) &Question->HiiValue.Value;\r
1411 }\r
1412\r
1413 IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
1414 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
1415 if (IsBufferStorage) {\r
1416 //\r
1417 // Copy to storage edit buffer\r
1418 //\r
1419 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
1420 } else {\r
1421 if (IsString) {\r
1422 //\r
1423 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
1424 //\r
1425 Value = NULL;\r
1426 BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
1427 Value = AllocateZeroPool (BufferLen);\r
1428 ASSERT (Value != NULL);\r
1429 Status = UnicodeToConfigString (Value, &BufferLen, (CHAR16 *) Src);\r
1430 ASSERT_EFI_ERROR (Status);\r
1431 } else {\r
1432 BufferLen = StorageWidth * 2 + 1;\r
1433 Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
1434 ASSERT (Value != NULL);\r
1435 BufToHexString (Value, &BufferLen, Src, StorageWidth);\r
1436 ToLower (Value);\r
1437 }\r
1438\r
1439 Status = SetValueByName (Storage, Question->VariableName, Value);\r
1440 gBS->FreePool (Value);\r
1441 }\r
1442\r
1443 if (!Cached) {\r
1444 //\r
1445 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||\r
1446 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"\r
1447 //\r
1448 if (IsBufferStorage) {\r
1449 Length = StrLen (Question->BlockName) + 7;\r
1450 } else {\r
1451 Length = StrLen (Question->VariableName) + 2;\r
1452 }\r
1453 if (!IsBufferStorage && IsString) {\r
1454 Length += (StrLen ((CHAR16 *) Src) * 4);\r
1455 } else {\r
1456 Length += (StorageWidth * 2);\r
1457 }\r
1458 ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16));\r
1459 ASSERT (ConfigResp != NULL);\r
1460\r
1461 StrCpy (ConfigResp, Storage->ConfigHdr);\r
1462 if (IsBufferStorage) {\r
1463 StrCat (ConfigResp, Question->BlockName);\r
1464 StrCat (ConfigResp, L"&VALUE=");\r
1465 } else {\r
1466 StrCat (ConfigResp, L"&");\r
1467 StrCat (ConfigResp, Question->VariableName);\r
1468 StrCat (ConfigResp, L"=");\r
1469 }\r
1470\r
1471 Value = ConfigResp + StrLen (ConfigResp);\r
1472 if (!IsBufferStorage && IsString) {\r
1473 //\r
1474 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
1475 //\r
1476 BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
1477 Status = UnicodeToConfigString (Value, &BufferLen, (CHAR16 *) Src);\r
1478 ASSERT_EFI_ERROR (Status);\r
1479 } else {\r
1480 BufferLen = StorageWidth * 2 + 1;\r
1481 BufToHexString (Value, &BufferLen, Src, StorageWidth);\r
1482 ToLower (Value);\r
1483 }\r
1484\r
1485 //\r
1486 // Submit Question Value to Configuration Driver\r
1487 //\r
1488 if (FormSet->ConfigAccess != NULL) {\r
1489 Status = FormSet->ConfigAccess->RouteConfig (\r
1490 FormSet->ConfigAccess,\r
1491 ConfigResp,\r
1492 &Progress\r
1493 );\r
1494 if (EFI_ERROR (Status)) {\r
1495 gBS->FreePool (ConfigResp);\r
1496 return Status;\r
1497 }\r
1498 }\r
1499 gBS->FreePool (ConfigResp);\r
1500\r
1501 //\r
1502 // Synchronize shadow Buffer\r
1503 //\r
1504 SynchronizeStorage (Storage);\r
1505 }\r
1506\r
1507 return Status;\r
1508}\r
1509\r
1510\r
1511/**\r
1512 Perform inconsistent check for a Form.\r
1513\r
1514 @param FormSet FormSet data structure.\r
1515 @param Form Form data structure.\r
1516 @param Question The Question to be validated.\r
1517 @param Type Validation type: InConsistent or NoSubmit\r
1518\r
1519 @retval EFI_SUCCESS Form validation pass.\r
1520 @retval other Form validation failed.\r
1521\r
1522**/\r
1523EFI_STATUS\r
1524ValidateQuestion (\r
1525 IN FORM_BROWSER_FORMSET *FormSet,\r
1526 IN FORM_BROWSER_FORM *Form,\r
1527 IN FORM_BROWSER_STATEMENT *Question,\r
1528 IN UINTN Type\r
1529 )\r
1530{\r
1531 EFI_STATUS Status;\r
1532 LIST_ENTRY *Link;\r
1533 LIST_ENTRY *ListHead;\r
1534 EFI_STRING PopUp;\r
1535 EFI_INPUT_KEY Key;\r
1536 FORM_EXPRESSION *Expression;\r
1537\r
1538 if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {\r
1539 ListHead = &Question->InconsistentListHead;\r
1540 } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
1541 ListHead = &Question->NoSubmitListHead;\r
1542 } else {\r
1543 return EFI_UNSUPPORTED;\r
1544 }\r
1545\r
1546 Link = GetFirstNode (ListHead);\r
1547 while (!IsNull (ListHead, Link)) {\r
1548 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
1549\r
1550 //\r
1551 // Evaluate the expression\r
1552 //\r
1553 Status = EvaluateExpression (FormSet, Form, Expression);\r
1554 if (EFI_ERROR (Status)) {\r
1555 return Status;\r
1556 }\r
1557\r
1558 if (Expression->Result.Value.b) {\r
1559 //\r
1560 // Condition meet, show up error message\r
1561 //\r
1562 if (Expression->Error != 0) {\r
1563 PopUp = GetToken (Expression->Error, FormSet->HiiHandle);\r
1564 do {\r
1565 CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);\r
1566 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1567 gBS->FreePool (PopUp);\r
1568 }\r
1569\r
1570 return EFI_NOT_READY;\r
1571 }\r
1572\r
1573 Link = GetNextNode (ListHead, Link);\r
1574 }\r
1575\r
1576 return EFI_SUCCESS;\r
1577}\r
1578\r
1579\r
1580/**\r
1581 Perform NoSubmit check for a Form.\r
1582\r
1583 @param FormSet FormSet data structure.\r
1584 @param Form Form data structure.\r
1585\r
1586 @retval EFI_SUCCESS Form validation pass.\r
1587 @retval other Form validation failed.\r
1588\r
1589**/\r
1590EFI_STATUS\r
1591NoSubmitCheck (\r
1592 IN FORM_BROWSER_FORMSET *FormSet,\r
1593 IN FORM_BROWSER_FORM *Form\r
1594 )\r
1595{\r
1596 EFI_STATUS Status;\r
1597 LIST_ENTRY *Link;\r
1598 FORM_BROWSER_STATEMENT *Question;\r
1599\r
1600 Link = GetFirstNode (&Form->StatementListHead);\r
1601 while (!IsNull (&Form->StatementListHead, Link)) {\r
1602 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
1603\r
1604 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);\r
1605 if (EFI_ERROR (Status)) {\r
1606 return Status;\r
1607 }\r
1608\r
1609 Link = GetNextNode (&Form->StatementListHead, Link);\r
1610 }\r
1611\r
1612 return EFI_SUCCESS;\r
1613}\r
1614\r
1615\r
1616/**\r
1617 Submit a Form.\r
1618\r
1619 @param FormSet FormSet data structure.\r
1620 @param Form Form data structure.\r
1621\r
1622 @retval EFI_SUCCESS The function completed successfully.\r
1623\r
1624**/\r
1625EFI_STATUS\r
1626SubmitForm (\r
1627 IN FORM_BROWSER_FORMSET *FormSet,\r
1628 IN FORM_BROWSER_FORM *Form\r
1629 )\r
1630{\r
1631 EFI_STATUS Status;\r
1632 LIST_ENTRY *Link;\r
1633 EFI_STRING ConfigResp;\r
1634 EFI_STRING Progress;\r
1635 FORMSET_STORAGE *Storage;\r
1636\r
1637 //\r
1638 // Validate the Form by NoSubmit check\r
1639 //\r
1640 Status = NoSubmitCheck (FormSet, Form);\r
1641 if (EFI_ERROR (Status)) {\r
1642 return Status;\r
1643 }\r
1644\r
1645 //\r
1646 // Submit Buffer storage or Name/Value storage\r
1647 //\r
1648 Link = GetFirstNode (&FormSet->StorageListHead);\r
1649 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
1650 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
1651 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
1652\r
1653 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1654 continue;\r
1655 }\r
1656\r
1657 //\r
1658 // Skip if there is no RequestElement\r
1659 //\r
1660 if (Storage->ElementCount == 0) {\r
1661 continue;\r
1662 }\r
1663\r
1664 //\r
1665 // Prepare <ConfigResp>\r
1666 //\r
1667 Status = StorageToConfigResp (Storage, &ConfigResp);\r
1668 if (EFI_ERROR (Status)) {\r
1669 return Status;\r
1670 }\r
1671\r
1672 //\r
1673 // Send <ConfigResp> to Configuration Driver\r
1674 //\r
1675 if (FormSet->ConfigAccess != NULL) {\r
1676 Status = FormSet->ConfigAccess->RouteConfig (\r
1677 FormSet->ConfigAccess,\r
1678 ConfigResp,\r
1679 &Progress\r
1680 );\r
1681 if (EFI_ERROR (Status)) {\r
1682 gBS->FreePool (ConfigResp);\r
1683 return Status;\r
1684 }\r
1685 }\r
1686 gBS->FreePool (ConfigResp);\r
1687\r
1688 //\r
1689 // Config success, update storage shadow Buffer\r
1690 //\r
1691 SynchronizeStorage (Storage);\r
1692 }\r
1693\r
1694 gNvUpdateRequired = FALSE;\r
1695\r
1696 return EFI_SUCCESS;\r
1697}\r
1698\r
1699\r
1700/**\r
1701 Reset Question to its default value.\r
1702\r
1703 @param FormSet The form set.\r
1704 @param Form The form.\r
1705 @param Question The question.\r
1706 @param DefaultId The Class of the default.\r
1707\r
1708 @retval EFI_SUCCESS Question is reset to default value.\r
1709\r
1710**/\r
1711EFI_STATUS\r
1712GetQuestionDefault (\r
1713 IN FORM_BROWSER_FORMSET *FormSet,\r
1714 IN FORM_BROWSER_FORM *Form,\r
1715 IN FORM_BROWSER_STATEMENT *Question,\r
1716 IN UINT16 DefaultId\r
1717 )\r
1718{\r
1719 EFI_STATUS Status;\r
1720 LIST_ENTRY *Link;\r
1721 QUESTION_DEFAULT *Default;\r
1722 QUESTION_OPTION *Option;\r
1723 EFI_HII_VALUE *HiiValue;\r
1724 UINT8 Index;\r
1725\r
1726 Status = EFI_SUCCESS;\r
1727\r
1728 //\r
1729 // Statement don't have storage, skip them\r
1730 //\r
1731 if (Question->QuestionId == 0) {\r
1732 return Status;\r
1733 }\r
1734\r
1735 //\r
1736 // There are three ways to specify default value for a Question:\r
1737 // 1, use nested EFI_IFR_DEFAULT (highest priority)\r
1738 // 2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
1739 // 3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
1740 //\r
1741 HiiValue = &Question->HiiValue;\r
1742\r
1743 //\r
1744 // EFI_IFR_DEFAULT has highest priority\r
1745 //\r
1746 if (!IsListEmpty (&Question->DefaultListHead)) {\r
1747 Link = GetFirstNode (&Question->DefaultListHead);\r
1748 while (!IsNull (&Question->DefaultListHead, Link)) {\r
1749 Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
1750\r
1751 if (Default->DefaultId == DefaultId) {\r
1752 if (Default->ValueExpression != NULL) {\r
1753 //\r
1754 // Default is provided by an Expression, evaluate it\r
1755 //\r
1756 Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
1757 if (EFI_ERROR (Status)) {\r
1758 return Status;\r
1759 }\r
1760\r
1761 CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_VALUE));\r
1762 } else {\r
1763 //\r
1764 // Default value is embedded in EFI_IFR_DEFAULT\r
1765 //\r
1766 CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
1767 }\r
1768\r
1769 return EFI_SUCCESS;\r
1770 }\r
1771\r
1772 Link = GetNextNode (&Question->DefaultListHead, Link);\r
1773 }\r
1774 }\r
1775\r
1776 //\r
1777 // EFI_ONE_OF_OPTION\r
1778 //\r
1779 if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
1780 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
1781 //\r
1782 // OneOfOption could only provide Standard and Manufacturing default\r
1783 //\r
1784 Link = GetFirstNode (&Question->OptionListHead);\r
1785 while (!IsNull (&Question->OptionListHead, Link)) {\r
1786 Option = QUESTION_OPTION_FROM_LINK (Link);\r
1787\r
1788 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
1789 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
1790 ) {\r
1791 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
1792\r
1793 return EFI_SUCCESS;\r
1794 }\r
1795\r
1796 Link = GetNextNode (&Question->OptionListHead, Link);\r
1797 }\r
1798 }\r
1799 }\r
1800\r
1801 //\r
1802 // EFI_IFR_CHECKBOX - lowest priority\r
1803 //\r
1804 if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
1805 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
1806 //\r
1807 // Checkbox could only provide Standard and Manufacturing default\r
1808 //\r
1809 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
1810 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
1811 ) {\r
1812 HiiValue->Value.b = TRUE;\r
1813 } else {\r
1814 HiiValue->Value.b = FALSE;\r
1815 }\r
1816\r
1817 return EFI_SUCCESS;\r
1818 }\r
1819 }\r
1820\r
1821 //\r
1822 // For Questions without default\r
1823 //\r
1824 switch (Question->Operand) {\r
1825 case EFI_IFR_NUMERIC_OP:\r
1826 //\r
1827 // Take minimal value as numeric's default value\r
1828 //\r
1829 HiiValue->Value.u64 = Question->Minimum;\r
1830 break;\r
1831\r
1832 case EFI_IFR_ONE_OF_OP:\r
1833 //\r
1834 // Take first oneof option as oneof's default value\r
1835 //\r
1836 Link = GetFirstNode (&Question->OptionListHead);\r
1837 if (!IsNull (&Question->OptionListHead, Link)) {\r
1838 Option = QUESTION_OPTION_FROM_LINK (Link);\r
1839 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
1840 }\r
1841 break;\r
1842\r
1843 case EFI_IFR_ORDERED_LIST_OP:\r
1844 //\r
1845 // Take option sequence in IFR as ordered list's default value\r
1846 //\r
1847 Index = 0;\r
1848 Link = GetFirstNode (&Question->OptionListHead);\r
1849 while (!IsNull (&Question->OptionListHead, Link)) {\r
1850 Option = QUESTION_OPTION_FROM_LINK (Link);\r
1851\r
1852 Question->BufferValue[Index] = Option->Value.Value.u8;\r
1853\r
1854 Index++;\r
1855 if (Index >= Question->MaxContainers) {\r
1856 break;\r
1857 }\r
1858\r
1859 Link = GetNextNode (&Question->OptionListHead, Link);\r
1860 }\r
1861 break;\r
1862\r
1863 default:\r
1864 Status = EFI_NOT_FOUND;\r
1865 break;\r
1866 }\r
1867\r
1868 return Status;\r
1869}\r
1870\r
1871\r
1872/**\r
1873 Reset Questions in a Form to their default value.\r
1874\r
1875 @param FormSet FormSet data structure.\r
1876 @param Form The Form which to be reset.\r
1877 @param DefaultId The Class of the default.\r
1878\r
1879 @retval EFI_SUCCESS The function completed successfully.\r
1880\r
1881**/\r
1882EFI_STATUS\r
1883ExtractFormDefault (\r
1884 IN FORM_BROWSER_FORMSET *FormSet,\r
1885 IN FORM_BROWSER_FORM *Form,\r
1886 IN UINT16 DefaultId\r
1887 )\r
1888{\r
1889 EFI_STATUS Status;\r
1890 LIST_ENTRY *Link;\r
1891 FORM_BROWSER_STATEMENT *Question;\r
1892\r
1893 Link = GetFirstNode (&Form->StatementListHead);\r
1894 while (!IsNull (&Form->StatementListHead, Link)) {\r
1895 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
1896 Link = GetNextNode (&Form->StatementListHead, Link);\r
1897\r
1898 //\r
1899 // Reset Question to its default value\r
1900 //\r
1901 Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
1902 if (EFI_ERROR (Status)) {\r
1903 continue;\r
1904 }\r
1905\r
1906 //\r
1907 // Synchronize Buffer storage's Edit buffer\r
1908 //\r
1909 if ((Question->Storage != NULL) &&\r
1910 (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
1911 SetQuestionValue (FormSet, Form, Question, TRUE);\r
1912 }\r
1913 }\r
1914\r
1915 return EFI_SUCCESS;\r
1916}\r
1917\r
1918\r
1919/**\r
1920 Initialize Question's Edit copy from Storage.\r
1921\r
1922 @param FormSet FormSet data structure.\r
1923 @param Form Form data structure.\r
1924\r
1925 @retval EFI_SUCCESS The function completed successfully.\r
1926\r
1927**/\r
1928EFI_STATUS\r
1929LoadFormConfig (\r
1930 IN FORM_BROWSER_FORMSET *FormSet,\r
1931 IN FORM_BROWSER_FORM *Form\r
1932 )\r
1933{\r
1934 EFI_STATUS Status;\r
1935 LIST_ENTRY *Link;\r
1936 FORM_BROWSER_STATEMENT *Question;\r
1937\r
1938 Link = GetFirstNode (&Form->StatementListHead);\r
1939 while (!IsNull (&Form->StatementListHead, Link)) {\r
1940 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
1941\r
1942 //\r
1943 // Initialize local copy of Value for each Question\r
1944 //\r
1945 Status = GetQuestionValue (FormSet, Form, Question, TRUE);\r
1946 if (EFI_ERROR (Status)) {\r
1947 return Status;\r
1948 }\r
1949\r
1950 Link = GetNextNode (&Form->StatementListHead, Link);\r
1951 }\r
1952\r
1953 return EFI_SUCCESS;\r
1954}\r
1955\r
1956\r
1957/**\r
1958 Fill storage's edit copy with settings requested from Configuration Driver.\r
1959\r
1960 @param FormSet FormSet data structure.\r
1961 @param Storage Buffer Storage.\r
1962\r
1963 @retval EFI_SUCCESS The function completed successfully.\r
1964\r
1965**/\r
1966EFI_STATUS\r
1967LoadStorage (\r
1968 IN FORM_BROWSER_FORMSET *FormSet,\r
1969 IN FORMSET_STORAGE *Storage\r
1970 )\r
1971{\r
1972 EFI_STATUS Status;\r
1973 EFI_STRING Progress;\r
1974 EFI_STRING Result;\r
1975 CHAR16 *StrPtr;\r
1976\r
1977 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1978 return EFI_SUCCESS;\r
1979 }\r
1980\r
1981 if (FormSet->ConfigAccess == NULL) {\r
1982 return EFI_NOT_FOUND;\r
1983 }\r
1984\r
1985 if (Storage->ElementCount == 0) {\r
1986 //\r
1987 // Skip if there is no RequestElement\r
1988 //\r
1989 return EFI_SUCCESS;\r
1990 }\r
1991\r
1992 //\r
1993 // Request current settings from Configuration Driver\r
1994 //\r
1995 Status = FormSet->ConfigAccess->ExtractConfig (\r
1996 FormSet->ConfigAccess,\r
1997 Storage->ConfigRequest,\r
1998 &Progress,\r
1999 &Result\r
2000 );\r
2001 if (EFI_ERROR (Status)) {\r
2002 return Status;\r
2003 }\r
2004\r
2005 //\r
2006 // Convert Result from <ConfigAltResp> to <ConfigResp>\r
2007 //\r
2008 StrPtr = StrStr (Result, L"ALTCFG");\r
2009 if (StrPtr != NULL) {\r
2010 *StrPtr = L'\0';\r
2011 }\r
2012\r
2013 Status = ConfigRespToStorage (Storage, Result);\r
2014 gBS->FreePool (Result);\r
2015 return Status;\r
2016}\r
2017\r
2018\r
2019/**\r
2020 Get current setting of Questions.\r
2021\r
2022 @param FormSet FormSet data structure.\r
2023\r
2024 @retval EFI_SUCCESS The function completed successfully.\r
2025\r
2026**/\r
2027EFI_STATUS\r
2028InitializeCurrentSetting (\r
2029 IN OUT FORM_BROWSER_FORMSET *FormSet\r
2030 )\r
2031{\r
2032 LIST_ENTRY *Link;\r
2033 FORMSET_STORAGE *Storage;\r
2034 FORM_BROWSER_FORM *Form;\r
2035 EFI_STATUS Status;\r
2036\r
2037 //\r
2038 // Extract default from IFR binary\r
2039 //\r
2040 Link = GetFirstNode (&FormSet->FormListHead);\r
2041 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2042 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2043\r
2044 Status = ExtractFormDefault (FormSet, Form, EFI_HII_DEFAULT_CLASS_STANDARD);\r
2045\r
2046 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2047 }\r
2048\r
2049 //\r
2050 // Request current settings from Configuration Driver\r
2051 //\r
2052 Link = GetFirstNode (&FormSet->StorageListHead);\r
2053 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
2054 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
2055\r
2056 Status = LoadStorage (FormSet, Storage);\r
2057\r
2058 //\r
2059 // Now Edit Buffer is filled with default values(lower priority) and current\r
2060 // settings(higher priority), sychronize it to shadow Buffer\r
2061 //\r
2062 if (!EFI_ERROR (Status)) {\r
2063 SynchronizeStorage (Storage);\r
2064 }\r
2065\r
2066 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
2067 }\r
2068\r
2069 return EFI_SUCCESS;\r
2070}\r
2071\r
2072\r
2073/**\r
2074 Fetch the Ifr binary data of a FormSet.\r
2075\r
2076 @param Handle PackageList Handle\r
2077 @param FormSetGuid GUID of a formset. If not specified (NULL or zero\r
2078 GUID), take the first FormSet found in package\r
2079 list.\r
2080 @param BinaryLength The length of the FormSet IFR binary.\r
2081 @param BinaryData The buffer designed to receive the FormSet.\r
2082\r
2083 @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
2084 BufferLength was updated.\r
2085 @retval EFI_INVALID_PARAMETER The handle is unknown.\r
2086 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
2087 be found with the requested FormId.\r
2088\r
2089**/\r
2090EFI_STATUS\r
2091GetIfrBinaryData (\r
2092 IN EFI_HII_HANDLE Handle,\r
2093 IN OUT EFI_GUID *FormSetGuid,\r
2094 OUT UINTN *BinaryLength,\r
2095 OUT UINT8 **BinaryData\r
2096 )\r
2097{\r
2098 EFI_STATUS Status;\r
2099 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
2100 UINTN BufferSize;\r
2101 UINT8 *Package;\r
2102 UINT8 *OpCodeData;\r
2103 UINT32 Offset;\r
2104 UINT32 Offset2;\r
2105 BOOLEAN ReturnDefault;\r
2106 UINT32 PackageListLength;\r
2107 EFI_HII_PACKAGE_HEADER PackageHeader;\r
2108\r
2109 OpCodeData = NULL;\r
2110 Package = NULL;\r
2111 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;\r
2112\r
2113 //\r
2114 // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list\r
2115 //\r
2116 if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {\r
2117 ReturnDefault = TRUE;\r
2118 } else {\r
2119 ReturnDefault = FALSE;\r
2120 }\r
2121\r
2122 //\r
2123 // Get HII PackageList\r
2124 //\r
2125 BufferSize = 0;\r
2126 HiiPackageList = NULL;\r
2127 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
2128 if (Status == EFI_BUFFER_TOO_SMALL) {\r
2129 HiiPackageList = AllocatePool (BufferSize);\r
2130 ASSERT (HiiPackageList != NULL);\r
2131\r
2132 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
2133 }\r
2134 if (EFI_ERROR (Status)) {\r
2135 return Status;\r
2136 }\r
2137\r
2138 //\r
2139 // Get Form package from this HII package List\r
2140 //\r
2141 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
2142 Offset2 = 0;\r
2143 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
2144\r
2145 while (Offset < PackageListLength) {\r
2146 Package = ((UINT8 *) HiiPackageList) + Offset;\r
2147 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
2148\r
2149 if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {\r
2150 //\r
2151 // Search FormSet in this Form Package\r
2152 //\r
2153 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
2154 while (Offset2 < PackageHeader.Length) {\r
2155 OpCodeData = Package + Offset2;\r
2156\r
2157 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
2158 //\r
2159 // Check whether return default FormSet\r
2160 //\r
2161 if (ReturnDefault) {\r
2162 break;\r
2163 }\r
2164\r
2165 //\r
2166 // FormSet GUID is specified, check it\r
2167 //\r
2168 if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
2169 break;\r
2170 }\r
2171 }\r
2172\r
2173 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
2174 }\r
2175\r
2176 if (Offset2 < PackageHeader.Length) {\r
2177 //\r
2178 // Target formset found\r
2179 //\r
2180 break;\r
2181 }\r
2182 }\r
2183\r
2184 Offset += PackageHeader.Length;\r
2185 }\r
2186\r
2187 if (Offset >= PackageListLength) {\r
2188 //\r
2189 // Form package not found in this Package List\r
2190 //\r
2191 gBS->FreePool (HiiPackageList);\r
2192 return EFI_NOT_FOUND;\r
2193 }\r
2194\r
2195 if (ReturnDefault && FormSetGuid != NULL) {\r
2196 //\r
2197 // Return the default FormSet GUID\r
2198 //\r
2199 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
2200 }\r
2201\r
2202 //\r
2203 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
2204 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
2205 // of the Form Package.\r
2206 //\r
2207 *BinaryLength = PackageHeader.Length - Offset2;\r
2208 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
2209\r
2210 gBS->FreePool (HiiPackageList);\r
2211\r
2212 if (*BinaryData == NULL) {\r
2213 return EFI_OUT_OF_RESOURCES;\r
2214 }\r
2215\r
2216 return EFI_SUCCESS;\r
2217}\r
2218\r
2219\r
2220/**\r
2221 Initialize the internal data structure of a FormSet.\r
2222\r
2223 @param Handle PackageList Handle\r
2224 @param FormSetGuid GUID of a formset. If not specified (NULL or zero\r
2225 GUID), take the first FormSet found in package\r
2226 list.\r
2227 @param FormSet FormSet data structure.\r
2228\r
2229 @retval EFI_SUCCESS The function completed successfully.\r
2230 @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
2231\r
2232**/\r
2233EFI_STATUS\r
2234InitializeFormSet (\r
2235 IN EFI_HII_HANDLE Handle,\r
2236 IN OUT EFI_GUID *FormSetGuid,\r
2237 OUT FORM_BROWSER_FORMSET *FormSet\r
2238 )\r
2239{\r
2240 EFI_STATUS Status;\r
2241 EFI_HANDLE DriverHandle;\r
2242 UINT16 Index;\r
2243\r
2244 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
2245 if (EFI_ERROR (Status)) {\r
2246 return Status;\r
2247 }\r
2248\r
2249 FormSet->HiiHandle = Handle;\r
2250 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
2251\r
2252 //\r
2253 // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
2254 //\r
2255 Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
2256 if (EFI_ERROR (Status)) {\r
2257 return Status;\r
2258 }\r
2259 FormSet->DriverHandle = DriverHandle;\r
2260 Status = gBS->HandleProtocol (\r
2261 DriverHandle,\r
2262 &gEfiHiiConfigAccessProtocolGuid,\r
2263 (VOID **) &FormSet->ConfigAccess\r
2264 );\r
2265 if (EFI_ERROR (Status)) {\r
2266 //\r
2267 // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
2268 // list, then there will be no configuration action required\r
2269 //\r
2270 FormSet->ConfigAccess = NULL;\r
2271 }\r
2272\r
2273 //\r
2274 // Parse the IFR binary OpCodes\r
2275 //\r
2276 Status = ParseOpCodes (FormSet);\r
2277 if (EFI_ERROR (Status)) {\r
2278 return Status;\r
2279 }\r
2280\r
2281 gClassOfVfr = FormSet->SubClass;\r
2282 if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {\r
2283 FrontPageHandle = FormSet->HiiHandle;\r
2284 }\r
2285\r
2286 //\r
2287 // Match GUID to find out the function key setting. If match fail, use the default setting.\r
2288 //\r
2289 for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {\r
2290 if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {\r
2291 //\r
2292 // Update the function key setting.\r
2293 //\r
2294 gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;\r
2295 //\r
2296 // Function key prompt can not be displayed if the function key has been disabled.\r
2297 //\r
2298 if ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE) {\r
2299 gFunctionOneString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2300 }\r
2301\r
2302 if ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO) {\r
2303 gFunctionTwoString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2304 }\r
2305\r
2306 if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {\r
2307 gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2308 }\r
2309\r
2310 if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {\r
2311 gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2312 }\r
2313 }\r
2314 }\r
2315\r
2316 return Status;\r
2317}\r