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