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