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