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