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