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