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