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