]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
fixed DMA not be stopped issue when gBS->ExitBootServices called.
[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
63d55bb9
LG
1021 UINTN Index;\r
1022 UINTN LengthStr;\r
7936fb6a 1023 BOOLEAN IsBufferStorage;\r
1024 BOOLEAN IsString;\r
63d55bb9
LG
1025 CHAR16 TemStr[5];\r
1026 UINT8 DigitUint8;\r
7936fb6a 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
63d55bb9
LG
1148 \r
1149 LengthStr = StrLen (Value);\r
1150 Status = EFI_SUCCESS;\r
7936fb6a 1151 if (IsString) {\r
1152 //\r
1153 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
63d55bb9 1154 // Add string tail char L'\0' into Length\r
7936fb6a 1155 //\r
63d55bb9
LG
1156 Length = StorageWidth + sizeof (CHAR16);\r
1157 if (Length < ((LengthStr / 4 + 1) * 2)) {\r
1158 Status = EFI_BUFFER_TOO_SMALL;\r
1159 } else {\r
1160 StringPtr = (CHAR16 *) Dst;\r
1161 ZeroMem (TemStr, sizeof (TemStr));\r
1162 for (Index = 0; Index < LengthStr; Index += 4) {\r
1163 StrnCpy (TemStr, Value + Index, 4);\r
1164 StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
1165 }\r
1166 //\r
1167 // Add tailing L'\0' character\r
1168 //\r
1169 StringPtr[Index/4] = L'\0';\r
1170 }\r
7936fb6a 1171 } else {\r
63d55bb9
LG
1172 if (StorageWidth < ((LengthStr + 1) / 2)) {\r
1173 Status = EFI_BUFFER_TOO_SMALL;\r
1174 } else {\r
1175 ZeroMem (TemStr, sizeof (TemStr));\r
1176 for (Index = 0; Index < LengthStr; Index ++) {\r
1177 TemStr[0] = Value[LengthStr - Index - 1];\r
1178 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
1179 if ((Index & 1) == 0) {\r
1180 Dst [Index/2] = DigitUint8;\r
1181 } else {\r
634303c9 1182 Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
63d55bb9
LG
1183 }\r
1184 }\r
1185 }\r
7936fb6a 1186 }\r
1187\r
f4113e1f 1188 FreePool (Value);\r
7936fb6a 1189 }\r
1190 } else {\r
1191 //\r
1192 // Request current settings from Configuration Driver\r
1193 //\r
1194 if (FormSet->ConfigAccess == NULL) {\r
1195 return EFI_NOT_FOUND;\r
1196 }\r
1197\r
1198 //\r
1199 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
1200 // <ConfigHdr> + "&" + <VariableName>\r
1201 //\r
1202 if (IsBufferStorage) {\r
1203 Length = StrLen (Storage->ConfigHdr);\r
1204 Length += StrLen (Question->BlockName);\r
1205 } else {\r
1206 Length = StrLen (Storage->ConfigHdr);\r
1207 Length += StrLen (Question->VariableName) + 1;\r
1208 }\r
1209 ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
1210 ASSERT (ConfigRequest != NULL);\r
1211\r
1212 StrCpy (ConfigRequest, Storage->ConfigHdr);\r
1213 if (IsBufferStorage) {\r
1214 StrCat (ConfigRequest, Question->BlockName);\r
1215 } else {\r
1216 StrCat (ConfigRequest, L"&");\r
1217 StrCat (ConfigRequest, Question->VariableName);\r
1218 }\r
1219\r
1220 Status = FormSet->ConfigAccess->ExtractConfig (\r
1221 FormSet->ConfigAccess,\r
1222 ConfigRequest,\r
1223 &Progress,\r
1224 &Result\r
1225 );\r
1226 if (EFI_ERROR (Status)) {\r
1227 return Status;\r
1228 }\r
1229\r
1230 //\r
1231 // Skip <ConfigRequest>\r
1232 //\r
1233 Value = Result + Length;\r
1234 if (IsBufferStorage) {\r
1235 //\r
1236 // Skip "&VALUE"\r
1237 //\r
1238 Value = Value + 6;\r
1239 }\r
1240 if (*Value != '=') {\r
f4113e1f 1241 FreePool (Result);\r
7936fb6a 1242 return EFI_NOT_FOUND;\r
1243 }\r
1244 //\r
1245 // Skip '=', point to value\r
1246 //\r
1247 Value = Value + 1;\r
8d00a0f1 1248\r
1249 //\r
1250 // Suppress <AltResp> if any\r
1251 //\r
1252 StringPtr = Value;\r
1253 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
1254 StringPtr++;\r
1255 }\r
1256 *StringPtr = L'\0';\r
1257\r
63d55bb9
LG
1258 LengthStr = StrLen (Value);\r
1259 Status = EFI_SUCCESS;\r
7936fb6a 1260 if (!IsBufferStorage && IsString) {\r
1261 //\r
1262 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
63d55bb9 1263 // Add string tail char L'\0' into Length\r
7936fb6a 1264 //\r
63d55bb9
LG
1265 Length = StorageWidth + sizeof (CHAR16);\r
1266 if (Length < ((LengthStr / 4 + 1) * 2)) {\r
1267 Status = EFI_BUFFER_TOO_SMALL;\r
1268 } else {\r
1269 StringPtr = (CHAR16 *) Dst;\r
1270 ZeroMem (TemStr, sizeof (TemStr));\r
1271 for (Index = 0; Index < LengthStr; Index += 4) {\r
1272 StrnCpy (TemStr, Value + Index, 4);\r
1273 StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
1274 }\r
1275 //\r
1276 // Add tailing L'\0' character\r
1277 //\r
1278 StringPtr[Index/4] = L'\0';\r
1279 }\r
7936fb6a 1280 } else {\r
63d55bb9
LG
1281 if (StorageWidth < ((LengthStr + 1) / 2)) {\r
1282 Status = EFI_BUFFER_TOO_SMALL;\r
1283 } else {\r
1284 ZeroMem (TemStr, sizeof (TemStr));\r
1285 for (Index = 0; Index < LengthStr; Index ++) {\r
1286 TemStr[0] = Value[LengthStr - Index - 1];\r
1287 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
1288 if ((Index & 1) == 0) {\r
1289 Dst [Index/2] = DigitUint8;\r
1290 } else {\r
634303c9 1291 Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
63d55bb9
LG
1292 }\r
1293 }\r
7936fb6a 1294 }\r
1295 }\r
1296\r
63d55bb9
LG
1297 if (EFI_ERROR (Status)) {\r
1298 FreePool (Result);\r
1299 return Status;\r
1300 }\r
1301\r
7936fb6a 1302 //\r
1303 // Synchronize Edit Buffer\r
1304 //\r
1305 if (IsBufferStorage) {\r
1306 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
1307 } else {\r
1308 SetValueByName (Storage, Question->VariableName, Value);\r
1309 }\r
63d55bb9 1310\r
f4113e1f 1311 FreePool (Result);\r
7936fb6a 1312 }\r
1313\r
1314 return Status;\r
1315}\r
1316\r
1317\r
1318/**\r
1319 Save Question Value to edit copy(cached) or Storage(uncached).\r
1320\r
1321 @param FormSet FormSet data structure.\r
1322 @param Form Form data structure.\r
1323 @param Question Pointer to the Question.\r
1324 @param Cached TRUE: set to Edit copy FALSE: set to original\r
1325 Storage\r
1326\r
1327 @retval EFI_SUCCESS The function completed successfully.\r
1328\r
1329**/\r
1330EFI_STATUS\r
1331SetQuestionValue (\r
1332 IN FORM_BROWSER_FORMSET *FormSet,\r
1333 IN FORM_BROWSER_FORM *Form,\r
1334 IN OUT FORM_BROWSER_STATEMENT *Question,\r
1335 IN BOOLEAN Cached\r
1336 )\r
1337{\r
1338 EFI_STATUS Status;\r
1339 BOOLEAN Enabled;\r
1340 BOOLEAN Pending;\r
1341 UINT8 *Src;\r
1342 EFI_TIME EfiTime;\r
1343 UINTN BufferLen;\r
1344 UINTN StorageWidth;\r
1345 FORMSET_STORAGE *Storage;\r
1346 EFI_IFR_TYPE_VALUE *QuestionValue;\r
1347 CHAR16 *ConfigResp;\r
1348 CHAR16 *Progress;\r
1349 CHAR16 *Value;\r
1350 UINTN Length;\r
1351 BOOLEAN IsBufferStorage;\r
1352 BOOLEAN IsString;\r
63d55bb9
LG
1353 UINT8 *TemBuffer;\r
1354 CHAR16 *TemName;\r
1355 CHAR16 *TemString;\r
1356 UINTN Index;\r
7936fb6a 1357\r
1358 Status = EFI_SUCCESS;\r
1359\r
1360 //\r
1361 // Statement don't have storage, skip them\r
1362 //\r
1363 if (Question->QuestionId == 0) {\r
1364 return Status;\r
1365 }\r
1366\r
1367 //\r
1368 // If Question value is provided by an Expression, then it is read only\r
1369 //\r
1370 if (Question->ValueExpression != NULL) {\r
1371 return Status;\r
1372 }\r
1373\r
1374 //\r
1375 // Question value is provided by RTC\r
1376 //\r
1377 Storage = Question->Storage;\r
1378 QuestionValue = &Question->HiiValue.Value;\r
1379 if (Storage == NULL) {\r
1380 //\r
1381 // It's a Question without storage, or RTC date/time\r
1382 //\r
1383 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1384 //\r
1385 // Date and time define the same Flags bit\r
1386 //\r
1387 switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
1388 case QF_DATE_STORAGE_TIME:\r
1389 Status = gRT->GetTime (&EfiTime, NULL);\r
1390 break;\r
1391\r
1392 case QF_DATE_STORAGE_WAKEUP:\r
1393 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
1394 break;\r
1395\r
1396 case QF_DATE_STORAGE_NORMAL:\r
1397 default:\r
1398 //\r
1399 // For date/time without storage\r
1400 //\r
1401 return EFI_SUCCESS;\r
1402 }\r
1403\r
1404 if (EFI_ERROR (Status)) {\r
1405 return Status;\r
1406 }\r
1407\r
1408 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1409 EfiTime.Year = QuestionValue->date.Year;\r
1410 EfiTime.Month = QuestionValue->date.Month;\r
1411 EfiTime.Day = QuestionValue->date.Day;\r
1412 } else {\r
1413 EfiTime.Hour = QuestionValue->time.Hour;\r
1414 EfiTime.Minute = QuestionValue->time.Minute;\r
1415 EfiTime.Second = QuestionValue->time.Second;\r
1416 }\r
1417\r
1418 if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {\r
1419 Status = gRT->SetTime (&EfiTime);\r
1420 } else {\r
1421 Status = gRT->SetWakeupTime (TRUE, &EfiTime);\r
1422 }\r
1423 }\r
1424\r
1425 return Status;\r
1426 }\r
1427\r
1428 //\r
1429 // Question value is provided by EFI variable\r
1430 //\r
1431 StorageWidth = Question->StorageWidth;\r
1432 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1433 if (Question->BufferValue != NULL) {\r
1434 Src = Question->BufferValue;\r
1435 } else {\r
1436 Src = (UINT8 *) QuestionValue;\r
1437 }\r
1438\r
1439 Status = gRT->SetVariable (\r
1440 Question->VariableName,\r
1441 &Storage->Guid,\r
1442 Storage->Attributes,\r
1443 StorageWidth,\r
1444 Src\r
1445 );\r
1446 return Status;\r
1447 }\r
1448\r
1449 //\r
1450 // Question Value is provided by Buffer Storage or NameValue Storage\r
1451 //\r
1452 if (Question->BufferValue != NULL) {\r
1453 Src = Question->BufferValue;\r
1454 } else {\r
1455 Src = (UINT8 *) &Question->HiiValue.Value;\r
1456 }\r
1457\r
1458 IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
1459 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
1460 if (IsBufferStorage) {\r
1461 //\r
1462 // Copy to storage edit buffer\r
1463 //\r
1464 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
1465 } else {\r
1466 if (IsString) {\r
1467 //\r
63d55bb9 1468 // Allocate enough string buffer.\r
7936fb6a 1469 //\r
1470 Value = NULL;\r
1471 BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
1472 Value = AllocateZeroPool (BufferLen);\r
1473 ASSERT (Value != NULL);\r
63d55bb9
LG
1474 //\r
1475 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
1476 //\r
1477 TemName = (CHAR16 *) Src;\r
1478 TemString = Value;\r
1479 for (; *TemName != L'\0'; TemName++) {\r
1480 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
1481 }\r
7936fb6a 1482 } else {\r
1483 BufferLen = StorageWidth * 2 + 1;\r
1484 Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
1485 ASSERT (Value != NULL);\r
63d55bb9
LG
1486 //\r
1487 // Convert Buffer to Hex String\r
1488 //\r
1489 TemBuffer = Src + StorageWidth - 1;\r
1490 TemString = Value;\r
1491 for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
1492 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
1493 }\r
7936fb6a 1494 }\r
1495\r
1496 Status = SetValueByName (Storage, Question->VariableName, Value);\r
f4113e1f 1497 FreePool (Value);\r
7936fb6a 1498 }\r
1499\r
1500 if (!Cached) {\r
1501 //\r
1502 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||\r
1503 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"\r
1504 //\r
1505 if (IsBufferStorage) {\r
1506 Length = StrLen (Question->BlockName) + 7;\r
1507 } else {\r
1508 Length = StrLen (Question->VariableName) + 2;\r
1509 }\r
1510 if (!IsBufferStorage && IsString) {\r
1511 Length += (StrLen ((CHAR16 *) Src) * 4);\r
1512 } else {\r
1513 Length += (StorageWidth * 2);\r
1514 }\r
1515 ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16));\r
1516 ASSERT (ConfigResp != NULL);\r
1517\r
1518 StrCpy (ConfigResp, Storage->ConfigHdr);\r
1519 if (IsBufferStorage) {\r
1520 StrCat (ConfigResp, Question->BlockName);\r
1521 StrCat (ConfigResp, L"&VALUE=");\r
1522 } else {\r
1523 StrCat (ConfigResp, L"&");\r
1524 StrCat (ConfigResp, Question->VariableName);\r
1525 StrCat (ConfigResp, L"=");\r
1526 }\r
1527\r
1528 Value = ConfigResp + StrLen (ConfigResp);\r
63d55bb9 1529\r
7936fb6a 1530 if (!IsBufferStorage && IsString) {\r
1531 //\r
1532 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
1533 //\r
63d55bb9
LG
1534 TemName = (CHAR16 *) Src;\r
1535 TemString = Value;\r
1536 for (; *TemName != L'\0'; TemName++) {\r
1537 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
1538 }\r
7936fb6a 1539 } else {\r
63d55bb9
LG
1540 //\r
1541 // Convert Buffer to Hex String\r
1542 //\r
1543 TemBuffer = Src + StorageWidth - 1;\r
1544 TemString = Value;\r
1545 for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
1546 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
1547 }\r
1548 }\r
1549 \r
1550 //\r
1551 // Convert to lower char.\r
1552 //\r
1553 for (TemString = Value; *Value != L'\0'; Value++) {\r
1554 if (*Value >= L'A' && *Value <= L'Z') {\r
1555 *Value = (CHAR16) (*Value - L'A' + L'a');\r
1556 }\r
7936fb6a 1557 }\r
1558\r
1559 //\r
1560 // Submit Question Value to Configuration Driver\r
1561 //\r
1562 if (FormSet->ConfigAccess != NULL) {\r
1563 Status = FormSet->ConfigAccess->RouteConfig (\r
1564 FormSet->ConfigAccess,\r
1565 ConfigResp,\r
1566 &Progress\r
1567 );\r
1568 if (EFI_ERROR (Status)) {\r
f4113e1f 1569 FreePool (ConfigResp);\r
7936fb6a 1570 return Status;\r
1571 }\r
1572 }\r
f4113e1f 1573 FreePool (ConfigResp);\r
7936fb6a 1574\r
1575 //\r
1576 // Synchronize shadow Buffer\r
1577 //\r
1578 SynchronizeStorage (Storage);\r
1579 }\r
1580\r
1581 return Status;\r
1582}\r
1583\r
1584\r
1585/**\r
1586 Perform inconsistent check for a Form.\r
1587\r
1588 @param FormSet FormSet data structure.\r
1589 @param Form Form data structure.\r
1590 @param Question The Question to be validated.\r
1591 @param Type Validation type: InConsistent or NoSubmit\r
1592\r
1593 @retval EFI_SUCCESS Form validation pass.\r
1594 @retval other Form validation failed.\r
1595\r
1596**/\r
1597EFI_STATUS\r
1598ValidateQuestion (\r
1599 IN FORM_BROWSER_FORMSET *FormSet,\r
1600 IN FORM_BROWSER_FORM *Form,\r
1601 IN FORM_BROWSER_STATEMENT *Question,\r
1602 IN UINTN Type\r
1603 )\r
1604{\r
1605 EFI_STATUS Status;\r
1606 LIST_ENTRY *Link;\r
1607 LIST_ENTRY *ListHead;\r
1608 EFI_STRING PopUp;\r
1609 EFI_INPUT_KEY Key;\r
1610 FORM_EXPRESSION *Expression;\r
1611\r
1612 if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {\r
1613 ListHead = &Question->InconsistentListHead;\r
1614 } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
1615 ListHead = &Question->NoSubmitListHead;\r
1616 } else {\r
1617 return EFI_UNSUPPORTED;\r
1618 }\r
1619\r
1620 Link = GetFirstNode (ListHead);\r
1621 while (!IsNull (ListHead, Link)) {\r
1622 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
1623\r
1624 //\r
1625 // Evaluate the expression\r
1626 //\r
1627 Status = EvaluateExpression (FormSet, Form, Expression);\r
1628 if (EFI_ERROR (Status)) {\r
1629 return Status;\r
1630 }\r
1631\r
1632 if (Expression->Result.Value.b) {\r
1633 //\r
1634 // Condition meet, show up error message\r
1635 //\r
1636 if (Expression->Error != 0) {\r
1637 PopUp = GetToken (Expression->Error, FormSet->HiiHandle);\r
1638 do {\r
1639 CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);\r
1640 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
f4113e1f 1641 FreePool (PopUp);\r
7936fb6a 1642 }\r
1643\r
1644 return EFI_NOT_READY;\r
1645 }\r
1646\r
1647 Link = GetNextNode (ListHead, Link);\r
1648 }\r
1649\r
1650 return EFI_SUCCESS;\r
1651}\r
1652\r
1653\r
1654/**\r
1655 Perform NoSubmit check for a Form.\r
1656\r
1657 @param FormSet FormSet data structure.\r
1658 @param Form Form data structure.\r
1659\r
1660 @retval EFI_SUCCESS Form validation pass.\r
1661 @retval other Form validation failed.\r
1662\r
1663**/\r
1664EFI_STATUS\r
1665NoSubmitCheck (\r
1666 IN FORM_BROWSER_FORMSET *FormSet,\r
1667 IN FORM_BROWSER_FORM *Form\r
1668 )\r
1669{\r
1670 EFI_STATUS Status;\r
1671 LIST_ENTRY *Link;\r
1672 FORM_BROWSER_STATEMENT *Question;\r
1673\r
1674 Link = GetFirstNode (&Form->StatementListHead);\r
1675 while (!IsNull (&Form->StatementListHead, Link)) {\r
1676 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
1677\r
1678 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);\r
1679 if (EFI_ERROR (Status)) {\r
1680 return Status;\r
1681 }\r
1682\r
1683 Link = GetNextNode (&Form->StatementListHead, Link);\r
1684 }\r
1685\r
1686 return EFI_SUCCESS;\r
1687}\r
1688\r
1689\r
1690/**\r
1691 Submit a Form.\r
1692\r
1693 @param FormSet FormSet data structure.\r
1694 @param Form Form data structure.\r
1695\r
1696 @retval EFI_SUCCESS The function completed successfully.\r
1697\r
1698**/\r
1699EFI_STATUS\r
1700SubmitForm (\r
1701 IN FORM_BROWSER_FORMSET *FormSet,\r
1702 IN FORM_BROWSER_FORM *Form\r
1703 )\r
1704{\r
1705 EFI_STATUS Status;\r
1706 LIST_ENTRY *Link;\r
1707 EFI_STRING ConfigResp;\r
1708 EFI_STRING Progress;\r
1709 FORMSET_STORAGE *Storage;\r
1710\r
1711 //\r
1712 // Validate the Form by NoSubmit check\r
1713 //\r
1714 Status = NoSubmitCheck (FormSet, Form);\r
1715 if (EFI_ERROR (Status)) {\r
1716 return Status;\r
1717 }\r
1718\r
1719 //\r
1720 // Submit Buffer storage or Name/Value storage\r
1721 //\r
1722 Link = GetFirstNode (&FormSet->StorageListHead);\r
1723 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
1724 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
1725 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
1726\r
1727 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1728 continue;\r
1729 }\r
1730\r
1731 //\r
1732 // Skip if there is no RequestElement\r
1733 //\r
1734 if (Storage->ElementCount == 0) {\r
1735 continue;\r
1736 }\r
1737\r
1738 //\r
1739 // Prepare <ConfigResp>\r
1740 //\r
1741 Status = StorageToConfigResp (Storage, &ConfigResp);\r
1742 if (EFI_ERROR (Status)) {\r
1743 return Status;\r
1744 }\r
1745\r
1746 //\r
1747 // Send <ConfigResp> to Configuration Driver\r
1748 //\r
1749 if (FormSet->ConfigAccess != NULL) {\r
1750 Status = FormSet->ConfigAccess->RouteConfig (\r
1751 FormSet->ConfigAccess,\r
1752 ConfigResp,\r
1753 &Progress\r
1754 );\r
1755 if (EFI_ERROR (Status)) {\r
f4113e1f 1756 FreePool (ConfigResp);\r
7936fb6a 1757 return Status;\r
1758 }\r
1759 }\r
f4113e1f 1760 FreePool (ConfigResp);\r
7936fb6a 1761\r
1762 //\r
1763 // Config success, update storage shadow Buffer\r
1764 //\r
1765 SynchronizeStorage (Storage);\r
1766 }\r
1767\r
1768 gNvUpdateRequired = FALSE;\r
1769\r
1770 return EFI_SUCCESS;\r
1771}\r
1772\r
1773\r
1774/**\r
1775 Reset Question to its default value.\r
1776\r
1777 @param FormSet The form set.\r
1778 @param Form The form.\r
1779 @param Question The question.\r
1780 @param DefaultId The Class of the default.\r
1781\r
1782 @retval EFI_SUCCESS Question is reset to default value.\r
1783\r
1784**/\r
1785EFI_STATUS\r
1786GetQuestionDefault (\r
1787 IN FORM_BROWSER_FORMSET *FormSet,\r
1788 IN FORM_BROWSER_FORM *Form,\r
1789 IN FORM_BROWSER_STATEMENT *Question,\r
1790 IN UINT16 DefaultId\r
1791 )\r
1792{\r
1793 EFI_STATUS Status;\r
1794 LIST_ENTRY *Link;\r
1795 QUESTION_DEFAULT *Default;\r
1796 QUESTION_OPTION *Option;\r
1797 EFI_HII_VALUE *HiiValue;\r
1798 UINT8 Index;\r
1799\r
1800 Status = EFI_SUCCESS;\r
1801\r
1802 //\r
1803 // Statement don't have storage, skip them\r
1804 //\r
1805 if (Question->QuestionId == 0) {\r
1806 return Status;\r
1807 }\r
1808\r
1809 //\r
1810 // There are three ways to specify default value for a Question:\r
1811 // 1, use nested EFI_IFR_DEFAULT (highest priority)\r
1812 // 2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
1813 // 3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
1814 //\r
1815 HiiValue = &Question->HiiValue;\r
1816\r
1817 //\r
1818 // EFI_IFR_DEFAULT has highest priority\r
1819 //\r
1820 if (!IsListEmpty (&Question->DefaultListHead)) {\r
1821 Link = GetFirstNode (&Question->DefaultListHead);\r
1822 while (!IsNull (&Question->DefaultListHead, Link)) {\r
1823 Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
1824\r
1825 if (Default->DefaultId == DefaultId) {\r
1826 if (Default->ValueExpression != NULL) {\r
1827 //\r
1828 // Default is provided by an Expression, evaluate it\r
1829 //\r
1830 Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
1831 if (EFI_ERROR (Status)) {\r
1832 return Status;\r
1833 }\r
1834\r
1835 CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_VALUE));\r
1836 } else {\r
1837 //\r
1838 // Default value is embedded in EFI_IFR_DEFAULT\r
1839 //\r
1840 CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
1841 }\r
1842\r
1843 return EFI_SUCCESS;\r
1844 }\r
1845\r
1846 Link = GetNextNode (&Question->DefaultListHead, Link);\r
1847 }\r
1848 }\r
1849\r
1850 //\r
1851 // EFI_ONE_OF_OPTION\r
1852 //\r
1853 if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
1854 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
1855 //\r
1856 // OneOfOption could only provide Standard and Manufacturing default\r
1857 //\r
1858 Link = GetFirstNode (&Question->OptionListHead);\r
1859 while (!IsNull (&Question->OptionListHead, Link)) {\r
1860 Option = QUESTION_OPTION_FROM_LINK (Link);\r
1861\r
1862 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
1863 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
1864 ) {\r
1865 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
1866\r
1867 return EFI_SUCCESS;\r
1868 }\r
1869\r
1870 Link = GetNextNode (&Question->OptionListHead, Link);\r
1871 }\r
1872 }\r
1873 }\r
1874\r
1875 //\r
1876 // EFI_IFR_CHECKBOX - lowest priority\r
1877 //\r
1878 if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
1879 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
1880 //\r
1881 // Checkbox could only provide Standard and Manufacturing default\r
1882 //\r
1883 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
1884 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
1885 ) {\r
1886 HiiValue->Value.b = TRUE;\r
1887 } else {\r
1888 HiiValue->Value.b = FALSE;\r
1889 }\r
1890\r
1891 return EFI_SUCCESS;\r
1892 }\r
1893 }\r
1894\r
1895 //\r
1896 // For Questions without default\r
1897 //\r
1898 switch (Question->Operand) {\r
1899 case EFI_IFR_NUMERIC_OP:\r
1900 //\r
1901 // Take minimal value as numeric's default value\r
1902 //\r
1903 HiiValue->Value.u64 = Question->Minimum;\r
1904 break;\r
1905\r
1906 case EFI_IFR_ONE_OF_OP:\r
1907 //\r
1908 // Take first oneof option as oneof's default value\r
1909 //\r
1910 Link = GetFirstNode (&Question->OptionListHead);\r
1911 if (!IsNull (&Question->OptionListHead, Link)) {\r
1912 Option = QUESTION_OPTION_FROM_LINK (Link);\r
1913 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
1914 }\r
1915 break;\r
1916\r
1917 case EFI_IFR_ORDERED_LIST_OP:\r
1918 //\r
1919 // Take option sequence in IFR as ordered list's default value\r
1920 //\r
1921 Index = 0;\r
1922 Link = GetFirstNode (&Question->OptionListHead);\r
1923 while (!IsNull (&Question->OptionListHead, Link)) {\r
1924 Option = QUESTION_OPTION_FROM_LINK (Link);\r
1925\r
1926 Question->BufferValue[Index] = Option->Value.Value.u8;\r
1927\r
1928 Index++;\r
1929 if (Index >= Question->MaxContainers) {\r
1930 break;\r
1931 }\r
1932\r
1933 Link = GetNextNode (&Question->OptionListHead, Link);\r
1934 }\r
1935 break;\r
1936\r
1937 default:\r
1938 Status = EFI_NOT_FOUND;\r
1939 break;\r
1940 }\r
1941\r
1942 return Status;\r
1943}\r
1944\r
1945\r
1946/**\r
1947 Reset Questions in a Form to their default value.\r
1948\r
1949 @param FormSet FormSet data structure.\r
1950 @param Form The Form which to be reset.\r
1951 @param DefaultId The Class of the default.\r
1952\r
1953 @retval EFI_SUCCESS The function completed successfully.\r
1954\r
1955**/\r
1956EFI_STATUS\r
1957ExtractFormDefault (\r
1958 IN FORM_BROWSER_FORMSET *FormSet,\r
1959 IN FORM_BROWSER_FORM *Form,\r
1960 IN UINT16 DefaultId\r
1961 )\r
1962{\r
1963 EFI_STATUS Status;\r
1964 LIST_ENTRY *Link;\r
1965 FORM_BROWSER_STATEMENT *Question;\r
1966\r
1967 Link = GetFirstNode (&Form->StatementListHead);\r
1968 while (!IsNull (&Form->StatementListHead, Link)) {\r
1969 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
1970 Link = GetNextNode (&Form->StatementListHead, Link);\r
1971\r
8d00a0f1 1972 //\r
1973 // If Question is suppressed, don't reset it to default\r
1974 //\r
1975 if (Question->SuppressExpression != NULL) {\r
1976 Status = EvaluateExpression (FormSet, Form, Question->SuppressExpression);\r
1977 if (!EFI_ERROR (Status) && Question->SuppressExpression->Result.Value.b) {\r
1978 continue;\r
1979 }\r
1980 }\r
1981\r
7936fb6a 1982 //\r
1983 // Reset Question to its default value\r
1984 //\r
1985 Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
1986 if (EFI_ERROR (Status)) {\r
1987 continue;\r
1988 }\r
1989\r
1990 //\r
1991 // Synchronize Buffer storage's Edit buffer\r
1992 //\r
1993 if ((Question->Storage != NULL) &&\r
1994 (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
1995 SetQuestionValue (FormSet, Form, Question, TRUE);\r
1996 }\r
1997 }\r
1998\r
1999 return EFI_SUCCESS;\r
2000}\r
2001\r
2002\r
2003/**\r
2004 Initialize Question's Edit copy from Storage.\r
2005\r
2006 @param FormSet FormSet data structure.\r
2007 @param Form Form data structure.\r
2008\r
2009 @retval EFI_SUCCESS The function completed successfully.\r
2010\r
2011**/\r
2012EFI_STATUS\r
2013LoadFormConfig (\r
2014 IN FORM_BROWSER_FORMSET *FormSet,\r
2015 IN FORM_BROWSER_FORM *Form\r
2016 )\r
2017{\r
2018 EFI_STATUS Status;\r
2019 LIST_ENTRY *Link;\r
2020 FORM_BROWSER_STATEMENT *Question;\r
2021\r
2022 Link = GetFirstNode (&Form->StatementListHead);\r
2023 while (!IsNull (&Form->StatementListHead, Link)) {\r
2024 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
2025\r
2026 //\r
2027 // Initialize local copy of Value for each Question\r
2028 //\r
2029 Status = GetQuestionValue (FormSet, Form, Question, TRUE);\r
2030 if (EFI_ERROR (Status)) {\r
2031 return Status;\r
2032 }\r
2033\r
2034 Link = GetNextNode (&Form->StatementListHead, Link);\r
2035 }\r
2036\r
2037 return EFI_SUCCESS;\r
2038}\r
2039\r
2040\r
2041/**\r
2042 Fill storage's edit copy with settings requested from Configuration Driver.\r
2043\r
2044 @param FormSet FormSet data structure.\r
2045 @param Storage Buffer Storage.\r
2046\r
2047 @retval EFI_SUCCESS The function completed successfully.\r
2048\r
2049**/\r
2050EFI_STATUS\r
2051LoadStorage (\r
2052 IN FORM_BROWSER_FORMSET *FormSet,\r
2053 IN FORMSET_STORAGE *Storage\r
2054 )\r
2055{\r
2056 EFI_STATUS Status;\r
2057 EFI_STRING Progress;\r
2058 EFI_STRING Result;\r
2059 CHAR16 *StrPtr;\r
2060\r
2061 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2062 return EFI_SUCCESS;\r
2063 }\r
2064\r
2065 if (FormSet->ConfigAccess == NULL) {\r
2066 return EFI_NOT_FOUND;\r
2067 }\r
2068\r
2069 if (Storage->ElementCount == 0) {\r
2070 //\r
2071 // Skip if there is no RequestElement\r
2072 //\r
2073 return EFI_SUCCESS;\r
2074 }\r
2075\r
2076 //\r
2077 // Request current settings from Configuration Driver\r
2078 //\r
2079 Status = FormSet->ConfigAccess->ExtractConfig (\r
2080 FormSet->ConfigAccess,\r
2081 Storage->ConfigRequest,\r
2082 &Progress,\r
2083 &Result\r
2084 );\r
2085 if (EFI_ERROR (Status)) {\r
2086 return Status;\r
2087 }\r
2088\r
2089 //\r
2090 // Convert Result from <ConfigAltResp> to <ConfigResp>\r
2091 //\r
2092 StrPtr = StrStr (Result, L"ALTCFG");\r
2093 if (StrPtr != NULL) {\r
2094 *StrPtr = L'\0';\r
2095 }\r
2096\r
2097 Status = ConfigRespToStorage (Storage, Result);\r
f4113e1f 2098 FreePool (Result);\r
7936fb6a 2099 return Status;\r
2100}\r
2101\r
2102\r
2103/**\r
2104 Get current setting of Questions.\r
2105\r
2106 @param FormSet FormSet data structure.\r
2107\r
2108 @retval EFI_SUCCESS The function completed successfully.\r
2109\r
2110**/\r
2111EFI_STATUS\r
2112InitializeCurrentSetting (\r
2113 IN OUT FORM_BROWSER_FORMSET *FormSet\r
2114 )\r
2115{\r
2116 LIST_ENTRY *Link;\r
2117 FORMSET_STORAGE *Storage;\r
2118 FORM_BROWSER_FORM *Form;\r
2119 EFI_STATUS Status;\r
2120\r
2121 //\r
2122 // Extract default from IFR binary\r
2123 //\r
2124 Link = GetFirstNode (&FormSet->FormListHead);\r
2125 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2126 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2127\r
2128 Status = ExtractFormDefault (FormSet, Form, EFI_HII_DEFAULT_CLASS_STANDARD);\r
2129\r
2130 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2131 }\r
2132\r
2133 //\r
2134 // Request current settings from Configuration Driver\r
2135 //\r
2136 Link = GetFirstNode (&FormSet->StorageListHead);\r
2137 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
2138 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
2139\r
2140 Status = LoadStorage (FormSet, Storage);\r
2141\r
2142 //\r
2143 // Now Edit Buffer is filled with default values(lower priority) and current\r
2144 // settings(higher priority), sychronize it to shadow Buffer\r
2145 //\r
2146 if (!EFI_ERROR (Status)) {\r
2147 SynchronizeStorage (Storage);\r
2148 }\r
2149\r
2150 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
2151 }\r
2152\r
2153 return EFI_SUCCESS;\r
2154}\r
2155\r
2156\r
2157/**\r
2158 Fetch the Ifr binary data of a FormSet.\r
2159\r
2160 @param Handle PackageList Handle\r
2161 @param FormSetGuid GUID of a formset. If not specified (NULL or zero\r
2162 GUID), take the first FormSet found in package\r
2163 list.\r
2164 @param BinaryLength The length of the FormSet IFR binary.\r
2165 @param BinaryData The buffer designed to receive the FormSet.\r
2166\r
2167 @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
2168 BufferLength was updated.\r
2169 @retval EFI_INVALID_PARAMETER The handle is unknown.\r
2170 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
2171 be found with the requested FormId.\r
2172\r
2173**/\r
2174EFI_STATUS\r
2175GetIfrBinaryData (\r
2176 IN EFI_HII_HANDLE Handle,\r
2177 IN OUT EFI_GUID *FormSetGuid,\r
2178 OUT UINTN *BinaryLength,\r
2179 OUT UINT8 **BinaryData\r
2180 )\r
2181{\r
2182 EFI_STATUS Status;\r
2183 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
2184 UINTN BufferSize;\r
2185 UINT8 *Package;\r
2186 UINT8 *OpCodeData;\r
2187 UINT32 Offset;\r
2188 UINT32 Offset2;\r
2189 BOOLEAN ReturnDefault;\r
2190 UINT32 PackageListLength;\r
2191 EFI_HII_PACKAGE_HEADER PackageHeader;\r
2192\r
2193 OpCodeData = NULL;\r
2194 Package = NULL;\r
2195 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;\r
2196\r
2197 //\r
2198 // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list\r
2199 //\r
2200 if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {\r
2201 ReturnDefault = TRUE;\r
2202 } else {\r
2203 ReturnDefault = FALSE;\r
2204 }\r
2205\r
2206 //\r
2207 // Get HII PackageList\r
2208 //\r
2209 BufferSize = 0;\r
2210 HiiPackageList = NULL;\r
2211 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
2212 if (Status == EFI_BUFFER_TOO_SMALL) {\r
2213 HiiPackageList = AllocatePool (BufferSize);\r
2214 ASSERT (HiiPackageList != NULL);\r
2215\r
2216 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
2217 }\r
2218 if (EFI_ERROR (Status)) {\r
2219 return Status;\r
2220 }\r
db0bd81c 2221 ASSERT (HiiPackageList != NULL);\r
2222 \r
7936fb6a 2223 //\r
2224 // Get Form package from this HII package List\r
2225 //\r
2226 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
2227 Offset2 = 0;\r
2228 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
2229\r
2230 while (Offset < PackageListLength) {\r
2231 Package = ((UINT8 *) HiiPackageList) + Offset;\r
2232 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
2233\r
8d00a0f1 2234 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
7936fb6a 2235 //\r
2236 // Search FormSet in this Form Package\r
2237 //\r
2238 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
2239 while (Offset2 < PackageHeader.Length) {\r
2240 OpCodeData = Package + Offset2;\r
2241\r
2242 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
2243 //\r
2244 // Check whether return default FormSet\r
2245 //\r
2246 if (ReturnDefault) {\r
2247 break;\r
2248 }\r
2249\r
2250 //\r
2251 // FormSet GUID is specified, check it\r
2252 //\r
2253 if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
2254 break;\r
2255 }\r
2256 }\r
2257\r
2258 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
2259 }\r
2260\r
2261 if (Offset2 < PackageHeader.Length) {\r
2262 //\r
2263 // Target formset found\r
2264 //\r
2265 break;\r
2266 }\r
2267 }\r
2268\r
2269 Offset += PackageHeader.Length;\r
2270 }\r
2271\r
2272 if (Offset >= PackageListLength) {\r
2273 //\r
2274 // Form package not found in this Package List\r
2275 //\r
f4113e1f 2276 FreePool (HiiPackageList);\r
7936fb6a 2277 return EFI_NOT_FOUND;\r
2278 }\r
2279\r
2280 if (ReturnDefault && FormSetGuid != NULL) {\r
2281 //\r
2282 // Return the default FormSet GUID\r
2283 //\r
2284 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
2285 }\r
2286\r
2287 //\r
2288 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
2289 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
2290 // of the Form Package.\r
2291 //\r
2292 *BinaryLength = PackageHeader.Length - Offset2;\r
2293 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
2294\r
f4113e1f 2295 FreePool (HiiPackageList);\r
7936fb6a 2296\r
2297 if (*BinaryData == NULL) {\r
2298 return EFI_OUT_OF_RESOURCES;\r
2299 }\r
2300\r
2301 return EFI_SUCCESS;\r
2302}\r
2303\r
2304\r
2305/**\r
2306 Initialize the internal data structure of a FormSet.\r
2307\r
2308 @param Handle PackageList Handle\r
2309 @param FormSetGuid GUID of a formset. If not specified (NULL or zero\r
2310 GUID), take the first FormSet found in package\r
2311 list.\r
2312 @param FormSet FormSet data structure.\r
2313\r
2314 @retval EFI_SUCCESS The function completed successfully.\r
2315 @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
2316\r
2317**/\r
2318EFI_STATUS\r
2319InitializeFormSet (\r
2320 IN EFI_HII_HANDLE Handle,\r
2321 IN OUT EFI_GUID *FormSetGuid,\r
2322 OUT FORM_BROWSER_FORMSET *FormSet\r
2323 )\r
2324{\r
2325 EFI_STATUS Status;\r
2326 EFI_HANDLE DriverHandle;\r
2327 UINT16 Index;\r
2328\r
2329 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
2330 if (EFI_ERROR (Status)) {\r
2331 return Status;\r
2332 }\r
2333\r
2334 FormSet->HiiHandle = Handle;\r
2335 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
2336\r
2337 //\r
2338 // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
2339 //\r
2340 Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
2341 if (EFI_ERROR (Status)) {\r
2342 return Status;\r
2343 }\r
2344 FormSet->DriverHandle = DriverHandle;\r
2345 Status = gBS->HandleProtocol (\r
2346 DriverHandle,\r
2347 &gEfiHiiConfigAccessProtocolGuid,\r
2348 (VOID **) &FormSet->ConfigAccess\r
2349 );\r
2350 if (EFI_ERROR (Status)) {\r
2351 //\r
2352 // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
2353 // list, then there will be no configuration action required\r
2354 //\r
2355 FormSet->ConfigAccess = NULL;\r
2356 }\r
2357\r
2358 //\r
2359 // Parse the IFR binary OpCodes\r
2360 //\r
2361 Status = ParseOpCodes (FormSet);\r
2362 if (EFI_ERROR (Status)) {\r
2363 return Status;\r
2364 }\r
2365\r
2366 gClassOfVfr = FormSet->SubClass;\r
2367 if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {\r
2368 FrontPageHandle = FormSet->HiiHandle;\r
2369 }\r
2370\r
2371 //\r
2372 // Match GUID to find out the function key setting. If match fail, use the default setting.\r
2373 //\r
2374 for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {\r
2375 if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {\r
2376 //\r
2377 // Update the function key setting.\r
2378 //\r
2379 gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;\r
2380 //\r
2381 // Function key prompt can not be displayed if the function key has been disabled.\r
2382 //\r
2383 if ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE) {\r
2384 gFunctionOneString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2385 }\r
2386\r
2387 if ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO) {\r
2388 gFunctionTwoString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2389 }\r
2390\r
2391 if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {\r
2392 gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2393 }\r
2394\r
2395 if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {\r
2396 gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2397 }\r
2398 }\r
2399 }\r
2400\r
2401 return Status;\r
2402}\r