]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
Update structure EFI_IFR_VARSTORE_EFI to follow UEFI spec 2.3.1
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Setup.c
CommitLineData
7936fb6a 1/** @file\r
2Entry and initialization module for the browser.\r
3\r
5697f873 4Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
7936fb6a 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
7936fb6a 16\r
17SETUP_DRIVER_PRIVATE_DATA mPrivateData = {\r
18 SETUP_DRIVER_SIGNATURE,\r
19 NULL,\r
20 {\r
21 SendForm,\r
22 BrowserCallback\r
7936fb6a 23 }\r
24};\r
25\r
26EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;\r
27EFI_HII_STRING_PROTOCOL *mHiiString;\r
28EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;\r
29\r
ce6d12cc 30UINTN gBrowserContextCount = 0;\r
31LIST_ENTRY gBrowserContextList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList);\r
32\r
0a1147ed
LG
33BANNER_DATA *gBannerData;\r
34EFI_HII_HANDLE gFrontPageHandle;\r
7936fb6a 35UINTN gClassOfVfr;\r
36UINTN gFunctionKeySetting;\r
37BOOLEAN gResetRequired;\r
7936fb6a 38EFI_HII_HANDLE gHiiHandle;\r
7936fb6a 39UINT16 gDirection;\r
40EFI_SCREEN_DESCRIPTOR gScreenDimensions;\r
7936fb6a 41\r
42//\r
43// Browser Global Strings\r
44//\r
7936fb6a 45CHAR16 *gFunctionNineString;\r
46CHAR16 *gFunctionTenString;\r
47CHAR16 *gEnterString;\r
48CHAR16 *gEnterCommitString;\r
8d00a0f1 49CHAR16 *gEnterEscapeString;\r
7936fb6a 50CHAR16 *gEscapeString;\r
51CHAR16 *gSaveFailed;\r
52CHAR16 *gMoveHighlight;\r
53CHAR16 *gMakeSelection;\r
54CHAR16 *gDecNumericInput;\r
55CHAR16 *gHexNumericInput;\r
56CHAR16 *gToggleCheckBox;\r
57CHAR16 *gPromptForData;\r
58CHAR16 *gPromptForPassword;\r
59CHAR16 *gPromptForNewPassword;\r
60CHAR16 *gConfirmPassword;\r
61CHAR16 *gConfirmError;\r
62CHAR16 *gPassowordInvalid;\r
63CHAR16 *gPressEnter;\r
64CHAR16 *gEmptyString;\r
65CHAR16 *gAreYouSure;\r
66CHAR16 *gYesResponse;\r
67CHAR16 *gNoResponse;\r
68CHAR16 *gMiniString;\r
69CHAR16 *gPlusString;\r
70CHAR16 *gMinusString;\r
71CHAR16 *gAdjustNumber;\r
ebe43565 72CHAR16 *gSaveChanges;\r
8d00a0f1 73CHAR16 *gOptionMismatch;\r
0c66bc76 74CHAR16 *gFormSuppress;\r
7936fb6a 75\r
0e8e994d 76CHAR16 *mUnknownString = L"!";\r
77\r
7936fb6a 78CHAR16 gPromptBlockWidth;\r
79CHAR16 gOptionBlockWidth;\r
80CHAR16 gHelpBlockWidth;\r
81\r
82EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
83EFI_GUID gSetupBrowserGuid = {\r
84 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}\r
85};\r
86\r
ce6d12cc 87FORM_BROWSER_FORMSET *gOldFormSet;\r
d66e6c16 88\r
7936fb6a 89FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {\r
90 //\r
91 // Boot Manager\r
92 //\r
93 {\r
94 {\r
95 0x847bc3fe,\r
96 0xb974,\r
97 0x446d,\r
98 {\r
99 0x94,\r
100 0x49,\r
101 0x5a,\r
102 0xd5,\r
103 0x41,\r
104 0x2e,\r
105 0x99,\r
106 0x3b\r
107 }\r
108 },\r
109 NONE_FUNCTION_KEY_SETTING\r
110 },\r
111 //\r
112 // Device Manager\r
113 //\r
114 {\r
115 {\r
116 0x3ebfa8e6,\r
117 0x511d,\r
118 0x4b5b,\r
119 {\r
120 0xa9,\r
121 0x5f,\r
122 0xfb,\r
123 0x38,\r
124 0x26,\r
125 0xf,\r
126 0x1c,\r
127 0x27\r
128 }\r
129 },\r
130 NONE_FUNCTION_KEY_SETTING\r
131 },\r
132 //\r
133 // BMM FormSet.\r
134 //\r
135 {\r
136 {\r
137 0x642237c7,\r
138 0x35d4,\r
139 0x472d,\r
140 {\r
141 0x83,\r
142 0x65,\r
143 0x12,\r
144 0xe0,\r
145 0xcc,\r
146 0xf2,\r
147 0x7a,\r
148 0x22\r
149 }\r
150 },\r
151 NONE_FUNCTION_KEY_SETTING\r
152 },\r
153 //\r
154 // BMM File Explorer FormSet.\r
155 //\r
156 {\r
157 {\r
158 0x1f2d63e1,\r
159 0xfebd,\r
160 0x4dc7,\r
161 {\r
162 0x9c,\r
163 0xc5,\r
164 0xba,\r
165 0x2b,\r
166 0x1c,\r
167 0xef,\r
168 0x9c,\r
169 0x5b\r
170 }\r
171 },\r
172 NONE_FUNCTION_KEY_SETTING\r
173 },\r
174};\r
175\r
176/**\r
177 This is the routine which an external caller uses to direct the browser\r
178 where to obtain it's information.\r
179\r
180\r
181 @param This The Form Browser protocol instanse.\r
182 @param Handles A pointer to an array of Handles. If HandleCount > 1 we\r
183 display a list of the formsets for the handles specified.\r
184 @param HandleCount The number of Handles specified in Handle.\r
185 @param FormSetGuid This field points to the EFI_GUID which must match the Guid\r
186 field in the EFI_IFR_FORM_SET op-code for the specified\r
187 forms-based package. If FormSetGuid is NULL, then this\r
188 function will display the first found forms package.\r
189 @param FormId This field specifies which EFI_IFR_FORM to render as the first\r
190 displayable page. If this field has a value of 0x0000, then\r
191 the forms browser will render the specified forms in their encoded order.\r
d66e6c16 192 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in\r
7936fb6a 193 characters.\r
f02d0c0f 194 @param ActionRequest Points to the action recommended by the form.\r
7936fb6a 195\r
196 @retval EFI_SUCCESS The function completed successfully.\r
197 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
198 @retval EFI_NOT_FOUND No valid forms could be found to display.\r
199\r
200**/\r
201EFI_STATUS\r
202EFIAPI\r
203SendForm (\r
204 IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
205 IN EFI_HII_HANDLE *Handles,\r
206 IN UINTN HandleCount,\r
207 IN EFI_GUID *FormSetGuid, OPTIONAL\r
208 IN UINT16 FormId, OPTIONAL\r
209 IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL\r
210 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL\r
211 )\r
212{\r
519f076a 213 EFI_STATUS Status;\r
214 UI_MENU_SELECTION *Selection;\r
215 UINTN Index;\r
216 FORM_BROWSER_FORMSET *FormSet;\r
7936fb6a 217\r
ce6d12cc 218 //\r
219 // Save globals used by SendForm()\r
220 //\r
221 SaveBrowserContext ();\r
222\r
7936fb6a 223 Status = EFI_SUCCESS;\r
224 ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
225\r
226 //\r
227 // Seed the dimensions in the global\r
228 //\r
229 gST->ConOut->QueryMode (\r
230 gST->ConOut,\r
231 gST->ConOut->Mode->Mode,\r
232 &gScreenDimensions.RightColumn,\r
233 &gScreenDimensions.BottomRow\r
234 );\r
235\r
236 if (ScreenDimensions != NULL) {\r
237 //\r
238 // Check local dimension vs. global dimension.\r
239 //\r
240 if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||\r
241 (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)\r
242 ) {\r
ce6d12cc 243 Status = EFI_INVALID_PARAMETER;\r
244 goto Done;\r
7936fb6a 245 } else {\r
246 //\r
247 // Local dimension validation.\r
248 //\r
249 if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) &&\r
250 (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) &&\r
251 ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) &&\r
252 (\r
253 (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +\r
254 SCROLL_ARROW_HEIGHT *\r
255 2 +\r
256 FRONT_PAGE_HEADER_HEIGHT +\r
257 FOOTER_HEIGHT +\r
258 1\r
259 )\r
260 ) {\r
261 CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
262 } else {\r
ce6d12cc 263 Status = EFI_INVALID_PARAMETER;\r
264 goto Done;\r
7936fb6a 265 }\r
266 }\r
267 }\r
268\r
269 gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);\r
f7a14a9b 270 gPromptBlockWidth = (CHAR16) (gOptionBlockWidth + LEFT_SKIPPED_COLUMNS);\r
5697f873 271 gHelpBlockWidth = (CHAR16) (gOptionBlockWidth - LEFT_SKIPPED_COLUMNS);\r
7936fb6a 272\r
273 //\r
274 // Initialize the strings for the browser, upon exit of the browser, the strings will be freed\r
275 //\r
276 InitializeBrowserStrings ();\r
277\r
278 gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING;\r
7936fb6a 279\r
280 //\r
281 // Ensure we are in Text mode\r
282 //\r
ebe43565 283 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
519f076a 284\r
7936fb6a 285 for (Index = 0; Index < HandleCount; Index++) {\r
286 Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));\r
287 ASSERT (Selection != NULL);\r
288\r
289 Selection->Handle = Handles[Index];\r
290 if (FormSetGuid != NULL) {\r
291 CopyMem (&Selection->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));\r
292 Selection->FormId = FormId;\r
293 }\r
294\r
ce6d12cc 295 gOldFormSet = NULL;\r
d66e6c16 296\r
7936fb6a 297 do {\r
298 FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
299 ASSERT (FormSet != NULL);\r
300\r
301 //\r
302 // Initialize internal data structures of FormSet\r
303 //\r
304 Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet);\r
e8e36190 305 if (EFI_ERROR (Status) || IsListEmpty (&FormSet->FormListHead)) {\r
7936fb6a 306 DestroyFormSet (FormSet);\r
307 break;\r
308 }\r
309 Selection->FormSet = FormSet;\r
310\r
7936fb6a 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
7936fb6a 319\r
320 if (EFI_ERROR (Status)) {\r
321 break;\r
322 }\r
323\r
324 } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);\r
325\r
d66e6c16 326 if (gOldFormSet != NULL) {\r
327 DestroyFormSet (gOldFormSet);\r
328 gOldFormSet = NULL;\r
329 }\r
330\r
f4113e1f 331 FreePool (Selection);\r
7936fb6a 332 }\r
333\r
334 if (ActionRequest != NULL) {\r
335 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
336 if (gResetRequired) {\r
337 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;\r
338 }\r
339 }\r
340\r
341 FreeBrowserStrings ();\r
342\r
343 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
344 gST->ConOut->ClearScreen (gST->ConOut);\r
345\r
ce6d12cc 346Done:\r
347 //\r
348 // Restore globals used by SendForm()\r
349 //\r
350 RestoreBrowserContext ();\r
351\r
7936fb6a 352 return Status;\r
353}\r
354\r
355\r
356/**\r
357 This function is called by a callback handler to retrieve uncommitted state\r
358 data from the browser.\r
359\r
360 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL\r
361 instance.\r
362 @param ResultsDataSize A pointer to the size of the buffer associated\r
363 with ResultsData.\r
364 @param ResultsData A string returned from an IFR browser or\r
365 equivalent. The results string will have no\r
366 routing information in them.\r
367 @param RetrieveData A BOOLEAN field which allows an agent to retrieve\r
368 (if RetrieveData = TRUE) data from the uncommitted\r
369 browser state information or set (if RetrieveData\r
370 = FALSE) data in the uncommitted browser state\r
371 information.\r
372 @param VariableGuid An optional field to indicate the target variable\r
373 GUID name to use.\r
374 @param VariableName An optional field to indicate the target\r
375 human-readable variable name.\r
376\r
377 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
378 distribution.\r
379 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to\r
380 contain the results data.\r
381\r
382**/\r
383EFI_STATUS\r
384EFIAPI\r
385BrowserCallback (\r
386 IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
387 IN OUT UINTN *ResultsDataSize,\r
388 IN OUT EFI_STRING ResultsData,\r
389 IN BOOLEAN RetrieveData,\r
390 IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
391 IN CONST CHAR16 *VariableName OPTIONAL\r
392 )\r
393{\r
394 EFI_STATUS Status;\r
395 LIST_ENTRY *Link;\r
396 FORMSET_STORAGE *Storage;\r
397 FORM_BROWSER_FORMSET *FormSet;\r
398 BOOLEAN Found;\r
399 CHAR16 *ConfigResp;\r
400 CHAR16 *StrPtr;\r
401 UINTN BufferSize;\r
402 UINTN TmpSize;\r
403\r
404 if (ResultsDataSize == NULL || ResultsData == NULL) {\r
405 return EFI_INVALID_PARAMETER;\r
406 }\r
407\r
408 if (gCurrentSelection == NULL) {\r
409 return EFI_NOT_READY;\r
410 }\r
411\r
412 Storage = NULL;\r
413 ConfigResp = NULL;\r
414 FormSet = gCurrentSelection->FormSet;\r
415\r
416 //\r
417 // Find target storage\r
418 //\r
419 Link = GetFirstNode (&FormSet->StorageListHead);\r
420 if (IsNull (&FormSet->StorageListHead, Link)) {\r
421 return EFI_UNSUPPORTED;\r
422 }\r
423\r
424 if (VariableGuid != NULL) {\r
425 //\r
426 // Try to find target storage\r
427 //\r
428 Found = FALSE;\r
429 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
430 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
431 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
432\r
433 if (CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {\r
434 if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {\r
435 //\r
436 // Buffer storage require both GUID and Name\r
437 //\r
438 if (VariableName == NULL) {\r
439 return EFI_NOT_FOUND;\r
440 }\r
441\r
442 if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {\r
443 continue;\r
444 }\r
445 }\r
446 Found = TRUE;\r
447 break;\r
448 }\r
449 }\r
450\r
451 if (!Found) {\r
452 return EFI_NOT_FOUND;\r
453 }\r
454 } else {\r
455 //\r
456 // GUID/Name is not specified, take the first storage in FormSet\r
457 //\r
458 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
459 }\r
460\r
461 if (RetrieveData) {\r
462 //\r
463 // Skip if there is no RequestElement\r
464 //\r
465 if (Storage->ElementCount == 0) {\r
466 return EFI_SUCCESS;\r
467 }\r
468\r
469 //\r
470 // Generate <ConfigResp>\r
471 //\r
b18e7050 472 Status = StorageToConfigResp (Storage, &ConfigResp, FALSE);\r
7936fb6a 473 if (EFI_ERROR (Status)) {\r
474 return Status;\r
475 }\r
476\r
477 //\r
478 // Skip <ConfigHdr> and '&' to point to <ConfigBody>\r
479 //\r
480 StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1;\r
481\r
482 BufferSize = StrSize (StrPtr);\r
483 if (*ResultsDataSize < BufferSize) {\r
484 *ResultsDataSize = BufferSize;\r
485\r
f4113e1f 486 FreePool (ConfigResp);\r
7936fb6a 487 return EFI_BUFFER_TOO_SMALL;\r
488 }\r
489\r
490 *ResultsDataSize = BufferSize;\r
491 CopyMem (ResultsData, StrPtr, BufferSize);\r
492\r
f4113e1f 493 FreePool (ConfigResp);\r
7936fb6a 494 } else {\r
495 //\r
496 // Prepare <ConfigResp>\r
497 //\r
498 TmpSize = StrLen (ResultsData);\r
499 BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16);\r
500 ConfigResp = AllocateZeroPool (BufferSize);\r
501 ASSERT (ConfigResp != NULL);\r
502\r
503 StrCpy (ConfigResp, Storage->ConfigHdr);\r
504 StrCat (ConfigResp, L"&");\r
505 StrCat (ConfigResp, ResultsData);\r
506\r
507 //\r
508 // Update Browser uncommited data\r
509 //\r
510 Status = ConfigRespToStorage (Storage, ConfigResp);\r
511 if (EFI_ERROR (Status)) {\r
512 return Status;\r
513 }\r
514 }\r
515\r
516 return EFI_SUCCESS;\r
517}\r
518\r
519\r
520/**\r
521 Initialize Setup Browser driver.\r
522\r
523 @param ImageHandle The image handle.\r
524 @param SystemTable The system table.\r
525\r
526 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..\r
527 @return Other value if failed to initialize the Setup Browser module.\r
528\r
529**/\r
530EFI_STATUS\r
531EFIAPI\r
532InitializeSetup (\r
533 IN EFI_HANDLE ImageHandle,\r
534 IN EFI_SYSTEM_TABLE *SystemTable\r
535 )\r
536{\r
537 EFI_STATUS Status;\r
7936fb6a 538\r
539 //\r
540 // Locate required Hii relative protocols\r
541 //\r
542 Status = gBS->LocateProtocol (\r
543 &gEfiHiiDatabaseProtocolGuid,\r
544 NULL,\r
545 (VOID **) &mHiiDatabase\r
546 );\r
547 ASSERT_EFI_ERROR (Status);\r
548\r
549 Status = gBS->LocateProtocol (\r
550 &gEfiHiiStringProtocolGuid,\r
551 NULL,\r
552 (VOID **) &mHiiString\r
553 );\r
554 ASSERT_EFI_ERROR (Status);\r
555\r
556 Status = gBS->LocateProtocol (\r
557 &gEfiHiiConfigRoutingProtocolGuid,\r
558 NULL,\r
559 (VOID **) &mHiiConfigRouting\r
560 );\r
561 ASSERT_EFI_ERROR (Status);\r
562\r
563 //\r
564 // Publish our HII data\r
565 //\r
cb7d01c0 566 gHiiHandle = HiiAddPackages (\r
567 &gSetupBrowserGuid,\r
568 ImageHandle,\r
569 SetupBrowserStrings,\r
570 NULL\r
571 );\r
572 ASSERT (gHiiHandle != NULL);\r
7936fb6a 573\r
574 //\r
575 // Initialize Driver private data\r
576 //\r
0a1147ed
LG
577 gBannerData = AllocateZeroPool (sizeof (BANNER_DATA));\r
578 ASSERT (gBannerData != NULL);\r
7936fb6a 579\r
580 //\r
581 // Install FormBrowser2 protocol\r
582 //\r
583 mPrivateData.Handle = NULL;\r
584 Status = gBS->InstallProtocolInterface (\r
585 &mPrivateData.Handle,\r
586 &gEfiFormBrowser2ProtocolGuid,\r
587 EFI_NATIVE_INTERFACE,\r
588 &mPrivateData.FormBrowser2\r
589 );\r
590 ASSERT_EFI_ERROR (Status);\r
591\r
7936fb6a 592 return Status;\r
593}\r
594\r
595\r
596/**\r
597 Create a new string in HII Package List.\r
598\r
599 @param String The String to be added\r
600 @param HiiHandle The package list in the HII database to insert the\r
601 specified string.\r
602\r
603 @return The output string.\r
604\r
605**/\r
606EFI_STRING_ID\r
607NewString (\r
608 IN CHAR16 *String,\r
609 IN EFI_HII_HANDLE HiiHandle\r
610 )\r
611{\r
612 EFI_STRING_ID StringId;\r
7936fb6a 613\r
cb7d01c0 614 StringId = HiiSetString (HiiHandle, 0, String, NULL);\r
615 ASSERT (StringId != 0);\r
7936fb6a 616\r
617 return StringId;\r
618}\r
619\r
620\r
621/**\r
622 Delete a string from HII Package List.\r
623\r
624 @param StringId Id of the string in HII database.\r
625 @param HiiHandle The HII package list handle.\r
626\r
627 @retval EFI_SUCCESS The string was deleted successfully.\r
628\r
629**/\r
630EFI_STATUS\r
631DeleteString (\r
632 IN EFI_STRING_ID StringId,\r
633 IN EFI_HII_HANDLE HiiHandle\r
634 )\r
635{\r
636 CHAR16 NullChar;\r
637\r
638 NullChar = CHAR_NULL;\r
cb7d01c0 639 HiiSetString (HiiHandle, StringId, &NullChar, NULL);\r
640 return EFI_SUCCESS;\r
7936fb6a 641}\r
642\r
643\r
644/**\r
645 Get the string based on the StringId and HII Package List Handle.\r
646\r
647 @param Token The String's ID.\r
648 @param HiiHandle The package list in the HII database to search for\r
649 the specified string.\r
650\r
651 @return The output string.\r
652\r
653**/\r
654CHAR16 *\r
655GetToken (\r
656 IN EFI_STRING_ID Token,\r
657 IN EFI_HII_HANDLE HiiHandle\r
658 )\r
659{\r
cb7d01c0 660 EFI_STRING String;\r
7936fb6a 661\r
2573712e
LG
662 if (HiiHandle == NULL) {\r
663 return NULL;\r
664 }\r
665\r
cb7d01c0 666 String = HiiGetString (HiiHandle, Token, NULL);\r
0e8e994d 667 if (String == NULL) {\r
668 String = AllocateCopyPool (sizeof (mUnknownString), mUnknownString);\r
669 ASSERT (String != NULL);\r
670 }\r
cb7d01c0 671 return (CHAR16 *) String;\r
7936fb6a 672}\r
673\r
674\r
675/**\r
676 Allocate new memory and then copy the Unicode string Source to Destination.\r
677\r
678 @param Dest Location to copy string\r
679 @param Src String to copy\r
680\r
681**/\r
682VOID\r
683NewStringCpy (\r
684 IN OUT CHAR16 **Dest,\r
685 IN CHAR16 *Src\r
686 )\r
687{\r
676df92c 688 if (*Dest != NULL) {\r
689 FreePool (*Dest);\r
690 }\r
7936fb6a 691 *Dest = AllocateCopyPool (StrSize (Src), Src);\r
692 ASSERT (*Dest != NULL);\r
693}\r
694\r
695\r
696/**\r
697 Allocate new memory and concatinate Source on the end of Destination.\r
698\r
699 @param Dest String to added to the end of.\r
700 @param Src String to concatinate.\r
701\r
702**/\r
703VOID\r
704NewStringCat (\r
705 IN OUT CHAR16 **Dest,\r
706 IN CHAR16 *Src\r
707 )\r
708{\r
709 CHAR16 *NewString;\r
710 UINTN TmpSize;\r
711\r
712 if (*Dest == NULL) {\r
713 NewStringCpy (Dest, Src);\r
714 return;\r
715 }\r
716\r
717 TmpSize = StrSize (*Dest);\r
718 NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1);\r
719 ASSERT (NewString != NULL);\r
720\r
721 StrCpy (NewString, *Dest);\r
722 StrCat (NewString, Src);\r
723\r
f4113e1f 724 FreePool (*Dest);\r
7936fb6a 725 *Dest = NewString;\r
726}\r
727\r
728\r
729/**\r
730 Synchronize Storage's Edit copy to Shadow copy.\r
731\r
732 @param Storage The Storage to be synchronized.\r
733\r
734**/\r
735VOID\r
736SynchronizeStorage (\r
737 IN FORMSET_STORAGE *Storage\r
738 )\r
739{\r
740 LIST_ENTRY *Link;\r
741 NAME_VALUE_NODE *Node;\r
742\r
743 switch (Storage->Type) {\r
744 case EFI_HII_VARSTORE_BUFFER:\r
745 CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);\r
746 break;\r
747\r
748 case EFI_HII_VARSTORE_NAME_VALUE:\r
749 Link = GetFirstNode (&Storage->NameValueListHead);\r
750 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
751 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
752\r
753 NewStringCpy (&Node->Value, Node->EditValue);\r
754\r
755 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
756 }\r
757 break;\r
758\r
759 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
760 default:\r
761 break;\r
762 }\r
763}\r
764\r
765\r
766/**\r
767 Get Value for given Name from a NameValue Storage.\r
768\r
769 @param Storage The NameValue Storage.\r
770 @param Name The Name.\r
771 @param Value The retured Value.\r
772\r
773 @retval EFI_SUCCESS Value found for given Name.\r
774 @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
775\r
776**/\r
777EFI_STATUS\r
778GetValueByName (\r
779 IN FORMSET_STORAGE *Storage,\r
780 IN CHAR16 *Name,\r
781 IN OUT CHAR16 **Value\r
782 )\r
783{\r
784 LIST_ENTRY *Link;\r
785 NAME_VALUE_NODE *Node;\r
786\r
787 *Value = NULL;\r
788\r
789 Link = GetFirstNode (&Storage->NameValueListHead);\r
790 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
791 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
792\r
793 if (StrCmp (Name, Node->Name) == 0) {\r
794 NewStringCpy (Value, Node->EditValue);\r
795 return EFI_SUCCESS;\r
796 }\r
797\r
798 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
799 }\r
800\r
801 return EFI_NOT_FOUND;\r
802}\r
803\r
804\r
805/**\r
806 Set Value of given Name in a NameValue Storage.\r
807\r
808 @param Storage The NameValue Storage.\r
809 @param Name The Name.\r
810 @param Value The Value to set.\r
b18e7050 811 @param Edit Whether update editValue or Value.\r
7936fb6a 812\r
813 @retval EFI_SUCCESS Value found for given Name.\r
814 @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
815\r
816**/\r
817EFI_STATUS\r
818SetValueByName (\r
819 IN FORMSET_STORAGE *Storage,\r
820 IN CHAR16 *Name,\r
b18e7050
ED
821 IN CHAR16 *Value,\r
822 IN BOOLEAN Edit\r
7936fb6a 823 )\r
824{\r
825 LIST_ENTRY *Link;\r
826 NAME_VALUE_NODE *Node;\r
b18e7050 827 CHAR16 *Buffer;\r
7936fb6a 828\r
829 Link = GetFirstNode (&Storage->NameValueListHead);\r
830 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
831 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
832\r
833 if (StrCmp (Name, Node->Name) == 0) {\r
b18e7050
ED
834 if (Edit) {\r
835 Buffer = Node->EditValue;\r
836 } else {\r
837 Buffer = Node->Value;\r
838 }\r
839 if (Buffer != NULL) {\r
840 FreePool (Buffer);\r
841 }\r
842 Buffer = AllocateCopyPool (StrSize (Value), Value);\r
843 ASSERT (Buffer != NULL);\r
844 if (Edit) {\r
845 Node->EditValue = Buffer;\r
846 } else {\r
847 Node->Value = Buffer;\r
676df92c 848 }\r
7936fb6a 849 return EFI_SUCCESS;\r
850 }\r
851\r
852 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
853 }\r
854\r
855 return EFI_NOT_FOUND;\r
856}\r
857\r
858\r
859/**\r
860 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
861\r
b18e7050 862 @param Buffer The Storage to be conveted.\r
7936fb6a 863 @param ConfigResp The returned <ConfigResp>.\r
b18e7050 864 @param SingleForm Whether update data for single form or formset level.\r
7936fb6a 865\r
866 @retval EFI_SUCCESS Convert success.\r
867 @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
868\r
869**/\r
870EFI_STATUS\r
871StorageToConfigResp (\r
b18e7050
ED
872 IN VOID *Buffer,\r
873 IN CHAR16 **ConfigResp,\r
874 IN BOOLEAN SingleForm\r
7936fb6a 875 )\r
876{\r
877 EFI_STATUS Status;\r
878 EFI_STRING Progress;\r
879 LIST_ENTRY *Link;\r
880 NAME_VALUE_NODE *Node;\r
b18e7050
ED
881 CHAR16 *ConfigRequest;\r
882 FORMSET_STORAGE *Storage;\r
883 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
7936fb6a 884\r
885 Status = EFI_SUCCESS;\r
b18e7050
ED
886 if (SingleForm) {\r
887 ConfigInfo = (FORM_BROWSER_CONFIG_REQUEST *) Buffer;\r
888 Storage = ConfigInfo->Storage;\r
889 ConfigRequest = ConfigInfo->ConfigRequest;\r
890 } else {\r
891 Storage = (FORMSET_STORAGE *) Buffer;\r
892 ConfigRequest = Storage->ConfigRequest;\r
893 }\r
7936fb6a 894\r
895 switch (Storage->Type) {\r
896 case EFI_HII_VARSTORE_BUFFER:\r
897 Status = mHiiConfigRouting->BlockToConfig (\r
898 mHiiConfigRouting,\r
b18e7050 899 ConfigRequest,\r
7936fb6a 900 Storage->EditBuffer,\r
901 Storage->Size,\r
902 ConfigResp,\r
903 &Progress\r
904 );\r
905 break;\r
906\r
907 case EFI_HII_VARSTORE_NAME_VALUE:\r
908 *ConfigResp = NULL;\r
909 NewStringCat (ConfigResp, Storage->ConfigHdr);\r
910\r
911 Link = GetFirstNode (&Storage->NameValueListHead);\r
912 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
913 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
914\r
b18e7050
ED
915 if (StrStr (ConfigRequest, Node->Name) != NULL) {\r
916 NewStringCat (ConfigResp, L"&");\r
917 NewStringCat (ConfigResp, Node->Name);\r
918 NewStringCat (ConfigResp, L"=");\r
919 NewStringCat (ConfigResp, Node->EditValue);\r
920 }\r
7936fb6a 921 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
922 }\r
923 break;\r
924\r
925 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
926 default:\r
927 Status = EFI_INVALID_PARAMETER;\r
928 break;\r
929 }\r
930\r
931 return Status;\r
932}\r
933\r
934\r
935/**\r
936 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.\r
937\r
938 @param Storage The Storage to receive the settings.\r
939 @param ConfigResp The <ConfigResp> to be converted.\r
940\r
941 @retval EFI_SUCCESS Convert success.\r
942 @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
943\r
944**/\r
945EFI_STATUS\r
946ConfigRespToStorage (\r
947 IN FORMSET_STORAGE *Storage,\r
948 IN CHAR16 *ConfigResp\r
949 )\r
950{\r
951 EFI_STATUS Status;\r
952 EFI_STRING Progress;\r
953 UINTN BufferSize;\r
954 CHAR16 *StrPtr;\r
955 CHAR16 *Name;\r
956 CHAR16 *Value;\r
957\r
958 Status = EFI_SUCCESS;\r
959\r
960 switch (Storage->Type) {\r
961 case EFI_HII_VARSTORE_BUFFER:\r
962 BufferSize = Storage->Size;\r
963 Status = mHiiConfigRouting->ConfigToBlock (\r
964 mHiiConfigRouting,\r
965 ConfigResp,\r
966 Storage->EditBuffer,\r
967 &BufferSize,\r
968 &Progress\r
969 );\r
970 break;\r
971\r
972 case EFI_HII_VARSTORE_NAME_VALUE:\r
40245175
LG
973 StrPtr = StrStr (ConfigResp, L"PATH");\r
974 if (StrPtr == NULL) {\r
975 break;\r
976 }\r
7936fb6a 977 StrPtr = StrStr (ConfigResp, L"&");\r
978 while (StrPtr != NULL) {\r
979 //\r
980 // Skip '&'\r
981 //\r
982 StrPtr = StrPtr + 1;\r
983 Name = StrPtr;\r
984 StrPtr = StrStr (StrPtr, L"=");\r
985 if (StrPtr == NULL) {\r
986 break;\r
987 }\r
988 *StrPtr = 0;\r
989\r
990 //\r
991 // Skip '='\r
992 //\r
993 StrPtr = StrPtr + 1;\r
994 Value = StrPtr;\r
995 StrPtr = StrStr (StrPtr, L"&");\r
996 if (StrPtr != NULL) {\r
997 *StrPtr = 0;\r
998 }\r
b18e7050 999 SetValueByName (Storage, Name, Value, TRUE);\r
7936fb6a 1000 }\r
1001 break;\r
1002\r
1003 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
1004 default:\r
1005 Status = EFI_INVALID_PARAMETER;\r
1006 break;\r
1007 }\r
1008\r
1009 return Status;\r
1010}\r
1011\r
1012\r
1013/**\r
1014 Get Question's current Value.\r
1015\r
1016 @param FormSet FormSet data structure.\r
1017 @param Form Form data structure.\r
1018 @param Question Question to be initialized.\r
1019 @param Cached TRUE: get from Edit copy FALSE: get from original\r
1020 Storage\r
1021\r
1022 @retval EFI_SUCCESS The function completed successfully.\r
1023\r
1024**/\r
1025EFI_STATUS\r
1026GetQuestionValue (\r
1027 IN FORM_BROWSER_FORMSET *FormSet,\r
1028 IN FORM_BROWSER_FORM *Form,\r
1029 IN OUT FORM_BROWSER_STATEMENT *Question,\r
1030 IN BOOLEAN Cached\r
1031 )\r
1032{\r
1033 EFI_STATUS Status;\r
1034 BOOLEAN Enabled;\r
1035 BOOLEAN Pending;\r
1036 UINT8 *Dst;\r
1037 UINTN StorageWidth;\r
1038 EFI_TIME EfiTime;\r
1039 FORMSET_STORAGE *Storage;\r
1040 EFI_IFR_TYPE_VALUE *QuestionValue;\r
1041 CHAR16 *ConfigRequest;\r
1042 CHAR16 *Progress;\r
1043 CHAR16 *Result;\r
1044 CHAR16 *Value;\r
8d00a0f1 1045 CHAR16 *StringPtr;\r
7936fb6a 1046 UINTN Length;\r
63d55bb9
LG
1047 UINTN Index;\r
1048 UINTN LengthStr;\r
7936fb6a 1049 BOOLEAN IsBufferStorage;\r
1050 BOOLEAN IsString;\r
63d55bb9
LG
1051 CHAR16 TemStr[5];\r
1052 UINT8 DigitUint8;\r
7936fb6a 1053\r
1054 Status = EFI_SUCCESS;\r
1055\r
1056 //\r
1057 // Statement don't have storage, skip them\r
1058 //\r
1059 if (Question->QuestionId == 0) {\r
1060 return Status;\r
1061 }\r
1062\r
1063 //\r
1064 // Question value is provided by an Expression, evaluate it\r
1065 //\r
1066 if (Question->ValueExpression != NULL) {\r
1067 Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);\r
1068 if (!EFI_ERROR (Status)) {\r
1069 CopyMem (&Question->HiiValue, &Question->ValueExpression->Result, sizeof (EFI_HII_VALUE));\r
1070 }\r
1071 return Status;\r
1072 }\r
2573712e
LG
1073 \r
1074 //\r
1075 // Get question value by read expression.\r
1076 //\r
1077 if (Question->ReadExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {\r
1078 Status = EvaluateExpression (FormSet, Form, Question->ReadExpression);\r
1079 if (!EFI_ERROR (Status) && (Question->ReadExpression->Result.Type < EFI_IFR_TYPE_OTHER)) {\r
1080 //\r
1081 // Only update question value to the valid result.\r
1082 //\r
1083 CopyMem (&Question->HiiValue, &Question->ReadExpression->Result, sizeof (EFI_HII_VALUE));\r
1084 return EFI_SUCCESS;\r
1085 }\r
1086 }\r
7936fb6a 1087\r
1088 //\r
1089 // Question value is provided by RTC\r
1090 //\r
1091 Storage = Question->Storage;\r
1092 QuestionValue = &Question->HiiValue.Value;\r
1093 if (Storage == NULL) {\r
1094 //\r
1095 // It's a Question without storage, or RTC date/time\r
1096 //\r
1097 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1098 //\r
1099 // Date and time define the same Flags bit\r
1100 //\r
1101 switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
1102 case QF_DATE_STORAGE_TIME:\r
1103 Status = gRT->GetTime (&EfiTime, NULL);\r
1104 break;\r
1105\r
1106 case QF_DATE_STORAGE_WAKEUP:\r
1107 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
1108 break;\r
1109\r
1110 case QF_DATE_STORAGE_NORMAL:\r
1111 default:\r
1112 //\r
1113 // For date/time without storage\r
1114 //\r
1115 return EFI_SUCCESS;\r
1116 }\r
1117\r
1118 if (EFI_ERROR (Status)) {\r
1119 return Status;\r
1120 }\r
1121\r
1122 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1123 QuestionValue->date.Year = EfiTime.Year;\r
1124 QuestionValue->date.Month = EfiTime.Month;\r
1125 QuestionValue->date.Day = EfiTime.Day;\r
1126 } else {\r
1127 QuestionValue->time.Hour = EfiTime.Hour;\r
1128 QuestionValue->time.Minute = EfiTime.Minute;\r
1129 QuestionValue->time.Second = EfiTime.Second;\r
1130 }\r
1131 }\r
1132\r
1133 return EFI_SUCCESS;\r
1134 }\r
1135\r
1136 //\r
1137 // Question value is provided by EFI variable\r
1138 //\r
1139 StorageWidth = Question->StorageWidth;\r
1140 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1141 if (Question->BufferValue != NULL) {\r
1142 Dst = Question->BufferValue;\r
1143 } else {\r
1144 Dst = (UINT8 *) QuestionValue;\r
1145 }\r
1146\r
1147 Status = gRT->GetVariable (\r
1148 Question->VariableName,\r
1149 &Storage->Guid,\r
1150 NULL,\r
1151 &StorageWidth,\r
1152 Dst\r
1153 );\r
1154 //\r
1155 // Always return success, even this EFI variable doesn't exist\r
1156 //\r
1157 return EFI_SUCCESS;\r
1158 }\r
1159\r
1160 //\r
1161 // Question Value is provided by Buffer Storage or NameValue Storage\r
1162 //\r
1163 if (Question->BufferValue != NULL) {\r
1164 //\r
1165 // This Question is password or orderedlist\r
1166 //\r
1167 Dst = Question->BufferValue;\r
1168 } else {\r
1169 //\r
1170 // Other type of Questions\r
1171 //\r
1172 Dst = (UINT8 *) &Question->HiiValue.Value;\r
1173 }\r
1174\r
1175 IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
1176 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
1177 if (Cached) {\r
1178 if (IsBufferStorage) {\r
1179 //\r
1180 // Copy from storage Edit buffer\r
1181 //\r
1182 CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
1183 } else {\r
1b2bf3ca 1184 Value = NULL;\r
7936fb6a 1185 Status = GetValueByName (Storage, Question->VariableName, &Value);\r
1186 if (EFI_ERROR (Status)) {\r
1187 return Status;\r
1188 }\r
d66e6c16 1189\r
1b2bf3ca 1190 ASSERT (Value != NULL);\r
63d55bb9
LG
1191 LengthStr = StrLen (Value);\r
1192 Status = EFI_SUCCESS;\r
7936fb6a 1193 if (IsString) {\r
1194 //\r
1195 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
63d55bb9 1196 // Add string tail char L'\0' into Length\r
7936fb6a 1197 //\r
63d55bb9
LG
1198 Length = StorageWidth + sizeof (CHAR16);\r
1199 if (Length < ((LengthStr / 4 + 1) * 2)) {\r
1200 Status = EFI_BUFFER_TOO_SMALL;\r
1201 } else {\r
1202 StringPtr = (CHAR16 *) Dst;\r
1203 ZeroMem (TemStr, sizeof (TemStr));\r
1204 for (Index = 0; Index < LengthStr; Index += 4) {\r
1205 StrnCpy (TemStr, Value + Index, 4);\r
1206 StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
1207 }\r
1208 //\r
1209 // Add tailing L'\0' character\r
1210 //\r
1211 StringPtr[Index/4] = L'\0';\r
1212 }\r
7936fb6a 1213 } else {\r
63d55bb9
LG
1214 if (StorageWidth < ((LengthStr + 1) / 2)) {\r
1215 Status = EFI_BUFFER_TOO_SMALL;\r
1216 } else {\r
1217 ZeroMem (TemStr, sizeof (TemStr));\r
1218 for (Index = 0; Index < LengthStr; Index ++) {\r
1219 TemStr[0] = Value[LengthStr - Index - 1];\r
1220 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
1221 if ((Index & 1) == 0) {\r
1222 Dst [Index/2] = DigitUint8;\r
1223 } else {\r
634303c9 1224 Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
63d55bb9
LG
1225 }\r
1226 }\r
1227 }\r
7936fb6a 1228 }\r
1229\r
f4113e1f 1230 FreePool (Value);\r
7936fb6a 1231 }\r
1232 } else {\r
1233 //\r
1234 // Request current settings from Configuration Driver\r
1235 //\r
1236 if (FormSet->ConfigAccess == NULL) {\r
1237 return EFI_NOT_FOUND;\r
1238 }\r
1239\r
1240 //\r
1241 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
1242 // <ConfigHdr> + "&" + <VariableName>\r
1243 //\r
1244 if (IsBufferStorage) {\r
1245 Length = StrLen (Storage->ConfigHdr);\r
1246 Length += StrLen (Question->BlockName);\r
1247 } else {\r
1248 Length = StrLen (Storage->ConfigHdr);\r
1249 Length += StrLen (Question->VariableName) + 1;\r
1250 }\r
1251 ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
1252 ASSERT (ConfigRequest != NULL);\r
1253\r
1254 StrCpy (ConfigRequest, Storage->ConfigHdr);\r
1255 if (IsBufferStorage) {\r
1256 StrCat (ConfigRequest, Question->BlockName);\r
1257 } else {\r
1258 StrCat (ConfigRequest, L"&");\r
1259 StrCat (ConfigRequest, Question->VariableName);\r
1260 }\r
1261\r
1262 Status = FormSet->ConfigAccess->ExtractConfig (\r
1263 FormSet->ConfigAccess,\r
1264 ConfigRequest,\r
1265 &Progress,\r
1266 &Result\r
1267 );\r
1268 if (EFI_ERROR (Status)) {\r
1269 return Status;\r
1270 }\r
1271\r
1272 //\r
1273 // Skip <ConfigRequest>\r
1274 //\r
1275 Value = Result + Length;\r
1276 if (IsBufferStorage) {\r
1277 //\r
1278 // Skip "&VALUE"\r
1279 //\r
1280 Value = Value + 6;\r
1281 }\r
1282 if (*Value != '=') {\r
f4113e1f 1283 FreePool (Result);\r
7936fb6a 1284 return EFI_NOT_FOUND;\r
1285 }\r
1286 //\r
1287 // Skip '=', point to value\r
1288 //\r
1289 Value = Value + 1;\r
8d00a0f1 1290\r
1291 //\r
1292 // Suppress <AltResp> if any\r
1293 //\r
1294 StringPtr = Value;\r
1295 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
1296 StringPtr++;\r
1297 }\r
1298 *StringPtr = L'\0';\r
1299\r
63d55bb9
LG
1300 LengthStr = StrLen (Value);\r
1301 Status = EFI_SUCCESS;\r
7936fb6a 1302 if (!IsBufferStorage && IsString) {\r
1303 //\r
1304 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
63d55bb9 1305 // Add string tail char L'\0' into Length\r
7936fb6a 1306 //\r
63d55bb9
LG
1307 Length = StorageWidth + sizeof (CHAR16);\r
1308 if (Length < ((LengthStr / 4 + 1) * 2)) {\r
1309 Status = EFI_BUFFER_TOO_SMALL;\r
1310 } else {\r
1311 StringPtr = (CHAR16 *) Dst;\r
1312 ZeroMem (TemStr, sizeof (TemStr));\r
1313 for (Index = 0; Index < LengthStr; Index += 4) {\r
1314 StrnCpy (TemStr, Value + Index, 4);\r
1315 StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
1316 }\r
1317 //\r
1318 // Add tailing L'\0' character\r
1319 //\r
1320 StringPtr[Index/4] = L'\0';\r
1321 }\r
7936fb6a 1322 } else {\r
63d55bb9
LG
1323 if (StorageWidth < ((LengthStr + 1) / 2)) {\r
1324 Status = EFI_BUFFER_TOO_SMALL;\r
1325 } else {\r
1326 ZeroMem (TemStr, sizeof (TemStr));\r
1327 for (Index = 0; Index < LengthStr; Index ++) {\r
1328 TemStr[0] = Value[LengthStr - Index - 1];\r
1329 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
1330 if ((Index & 1) == 0) {\r
1331 Dst [Index/2] = DigitUint8;\r
1332 } else {\r
634303c9 1333 Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
63d55bb9
LG
1334 }\r
1335 }\r
7936fb6a 1336 }\r
1337 }\r
1338\r
63d55bb9
LG
1339 if (EFI_ERROR (Status)) {\r
1340 FreePool (Result);\r
1341 return Status;\r
1342 }\r
1343\r
7936fb6a 1344 //\r
1345 // Synchronize Edit Buffer\r
1346 //\r
1347 if (IsBufferStorage) {\r
1348 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
1349 } else {\r
b18e7050 1350 SetValueByName (Storage, Question->VariableName, Value, TRUE);\r
7936fb6a 1351 }\r
63d55bb9 1352\r
f4113e1f 1353 FreePool (Result);\r
7936fb6a 1354 }\r
1355\r
1356 return Status;\r
1357}\r
1358\r
1359\r
1360/**\r
1361 Save Question Value to edit copy(cached) or Storage(uncached).\r
1362\r
1363 @param FormSet FormSet data structure.\r
1364 @param Form Form data structure.\r
1365 @param Question Pointer to the Question.\r
1366 @param Cached TRUE: set to Edit copy FALSE: set to original\r
1367 Storage\r
1368\r
1369 @retval EFI_SUCCESS The function completed successfully.\r
1370\r
1371**/\r
1372EFI_STATUS\r
1373SetQuestionValue (\r
1374 IN FORM_BROWSER_FORMSET *FormSet,\r
1375 IN FORM_BROWSER_FORM *Form,\r
1376 IN OUT FORM_BROWSER_STATEMENT *Question,\r
1377 IN BOOLEAN Cached\r
1378 )\r
1379{\r
1380 EFI_STATUS Status;\r
1381 BOOLEAN Enabled;\r
1382 BOOLEAN Pending;\r
1383 UINT8 *Src;\r
1384 EFI_TIME EfiTime;\r
1385 UINTN BufferLen;\r
1386 UINTN StorageWidth;\r
1387 FORMSET_STORAGE *Storage;\r
1388 EFI_IFR_TYPE_VALUE *QuestionValue;\r
1389 CHAR16 *ConfigResp;\r
1390 CHAR16 *Progress;\r
1391 CHAR16 *Value;\r
1392 UINTN Length;\r
1393 BOOLEAN IsBufferStorage;\r
1394 BOOLEAN IsString;\r
63d55bb9
LG
1395 UINT8 *TemBuffer;\r
1396 CHAR16 *TemName;\r
1397 CHAR16 *TemString;\r
1398 UINTN Index;\r
7936fb6a 1399\r
1400 Status = EFI_SUCCESS;\r
1401\r
1402 //\r
1403 // Statement don't have storage, skip them\r
1404 //\r
1405 if (Question->QuestionId == 0) {\r
1406 return Status;\r
1407 }\r
1408\r
1409 //\r
1410 // If Question value is provided by an Expression, then it is read only\r
1411 //\r
1412 if (Question->ValueExpression != NULL) {\r
1413 return Status;\r
1414 }\r
2573712e
LG
1415 \r
1416 //\r
1417 // Before set question value, evaluate its write expression.\r
1418 //\r
1419 if (Question->WriteExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {\r
1420 Status = EvaluateExpression (FormSet, Form, Question->WriteExpression);\r
1421 if (EFI_ERROR (Status)) {\r
1422 return Status;\r
1423 }\r
1424 }\r
7936fb6a 1425\r
1426 //\r
1427 // Question value is provided by RTC\r
1428 //\r
1429 Storage = Question->Storage;\r
1430 QuestionValue = &Question->HiiValue.Value;\r
1431 if (Storage == NULL) {\r
1432 //\r
1433 // It's a Question without storage, or RTC date/time\r
1434 //\r
1435 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1436 //\r
1437 // Date and time define the same Flags bit\r
1438 //\r
1439 switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
1440 case QF_DATE_STORAGE_TIME:\r
1441 Status = gRT->GetTime (&EfiTime, NULL);\r
1442 break;\r
1443\r
1444 case QF_DATE_STORAGE_WAKEUP:\r
1445 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
1446 break;\r
1447\r
1448 case QF_DATE_STORAGE_NORMAL:\r
1449 default:\r
1450 //\r
1451 // For date/time without storage\r
1452 //\r
1453 return EFI_SUCCESS;\r
1454 }\r
1455\r
1456 if (EFI_ERROR (Status)) {\r
1457 return Status;\r
1458 }\r
1459\r
1460 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1461 EfiTime.Year = QuestionValue->date.Year;\r
1462 EfiTime.Month = QuestionValue->date.Month;\r
1463 EfiTime.Day = QuestionValue->date.Day;\r
1464 } else {\r
1465 EfiTime.Hour = QuestionValue->time.Hour;\r
1466 EfiTime.Minute = QuestionValue->time.Minute;\r
1467 EfiTime.Second = QuestionValue->time.Second;\r
1468 }\r
1469\r
1470 if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {\r
1471 Status = gRT->SetTime (&EfiTime);\r
1472 } else {\r
1473 Status = gRT->SetWakeupTime (TRUE, &EfiTime);\r
1474 }\r
1475 }\r
1476\r
1477 return Status;\r
1478 }\r
1479\r
1480 //\r
1481 // Question value is provided by EFI variable\r
1482 //\r
1483 StorageWidth = Question->StorageWidth;\r
1484 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1485 if (Question->BufferValue != NULL) {\r
1486 Src = Question->BufferValue;\r
1487 } else {\r
1488 Src = (UINT8 *) QuestionValue;\r
1489 }\r
1490\r
1491 Status = gRT->SetVariable (\r
1492 Question->VariableName,\r
1493 &Storage->Guid,\r
1494 Storage->Attributes,\r
1495 StorageWidth,\r
1496 Src\r
1497 );\r
1498 return Status;\r
1499 }\r
1500\r
1501 //\r
1502 // Question Value is provided by Buffer Storage or NameValue Storage\r
1503 //\r
1504 if (Question->BufferValue != NULL) {\r
1505 Src = Question->BufferValue;\r
1506 } else {\r
1507 Src = (UINT8 *) &Question->HiiValue.Value;\r
1508 }\r
1509\r
1510 IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
1511 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
1512 if (IsBufferStorage) {\r
1513 //\r
1514 // Copy to storage edit buffer\r
1515 //\r
1516 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
1517 } else {\r
1518 if (IsString) {\r
1519 //\r
63d55bb9 1520 // Allocate enough string buffer.\r
7936fb6a 1521 //\r
1522 Value = NULL;\r
1523 BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
1524 Value = AllocateZeroPool (BufferLen);\r
1525 ASSERT (Value != NULL);\r
63d55bb9
LG
1526 //\r
1527 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
1528 //\r
1529 TemName = (CHAR16 *) Src;\r
1530 TemString = Value;\r
1531 for (; *TemName != L'\0'; TemName++) {\r
1532 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
1533 }\r
7936fb6a 1534 } else {\r
1535 BufferLen = StorageWidth * 2 + 1;\r
1536 Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
1537 ASSERT (Value != NULL);\r
63d55bb9
LG
1538 //\r
1539 // Convert Buffer to Hex String\r
1540 //\r
1541 TemBuffer = Src + StorageWidth - 1;\r
1542 TemString = Value;\r
1543 for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
1544 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
1545 }\r
7936fb6a 1546 }\r
1547\r
b18e7050 1548 Status = SetValueByName (Storage, Question->VariableName, Value, TRUE);\r
f4113e1f 1549 FreePool (Value);\r
7936fb6a 1550 }\r
1551\r
1552 if (!Cached) {\r
1553 //\r
1554 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||\r
1555 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"\r
1556 //\r
1557 if (IsBufferStorage) {\r
1558 Length = StrLen (Question->BlockName) + 7;\r
1559 } else {\r
1560 Length = StrLen (Question->VariableName) + 2;\r
1561 }\r
1562 if (!IsBufferStorage && IsString) {\r
1563 Length += (StrLen ((CHAR16 *) Src) * 4);\r
1564 } else {\r
1565 Length += (StorageWidth * 2);\r
1566 }\r
1567 ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16));\r
1568 ASSERT (ConfigResp != NULL);\r
1569\r
1570 StrCpy (ConfigResp, Storage->ConfigHdr);\r
1571 if (IsBufferStorage) {\r
1572 StrCat (ConfigResp, Question->BlockName);\r
1573 StrCat (ConfigResp, L"&VALUE=");\r
1574 } else {\r
1575 StrCat (ConfigResp, L"&");\r
1576 StrCat (ConfigResp, Question->VariableName);\r
1577 StrCat (ConfigResp, L"=");\r
1578 }\r
1579\r
1580 Value = ConfigResp + StrLen (ConfigResp);\r
63d55bb9 1581\r
7936fb6a 1582 if (!IsBufferStorage && IsString) {\r
1583 //\r
1584 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
1585 //\r
63d55bb9
LG
1586 TemName = (CHAR16 *) Src;\r
1587 TemString = Value;\r
1588 for (; *TemName != L'\0'; TemName++) {\r
1589 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
1590 }\r
7936fb6a 1591 } else {\r
63d55bb9
LG
1592 //\r
1593 // Convert Buffer to Hex String\r
1594 //\r
1595 TemBuffer = Src + StorageWidth - 1;\r
1596 TemString = Value;\r
1597 for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
1598 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
1599 }\r
1600 }\r
d66e6c16 1601\r
63d55bb9
LG
1602 //\r
1603 // Convert to lower char.\r
1604 //\r
1605 for (TemString = Value; *Value != L'\0'; Value++) {\r
1606 if (*Value >= L'A' && *Value <= L'Z') {\r
1607 *Value = (CHAR16) (*Value - L'A' + L'a');\r
1608 }\r
7936fb6a 1609 }\r
1610\r
1611 //\r
1612 // Submit Question Value to Configuration Driver\r
1613 //\r
1614 if (FormSet->ConfigAccess != NULL) {\r
1615 Status = FormSet->ConfigAccess->RouteConfig (\r
1616 FormSet->ConfigAccess,\r
1617 ConfigResp,\r
1618 &Progress\r
1619 );\r
1620 if (EFI_ERROR (Status)) {\r
f4113e1f 1621 FreePool (ConfigResp);\r
7936fb6a 1622 return Status;\r
1623 }\r
1624 }\r
f4113e1f 1625 FreePool (ConfigResp);\r
7936fb6a 1626\r
1627 //\r
1628 // Synchronize shadow Buffer\r
1629 //\r
1630 SynchronizeStorage (Storage);\r
1631 }\r
1632\r
1633 return Status;\r
1634}\r
1635\r
1636\r
1637/**\r
1638 Perform inconsistent check for a Form.\r
1639\r
1640 @param FormSet FormSet data structure.\r
1641 @param Form Form data structure.\r
1642 @param Question The Question to be validated.\r
1643 @param Type Validation type: InConsistent or NoSubmit\r
1644\r
1645 @retval EFI_SUCCESS Form validation pass.\r
1646 @retval other Form validation failed.\r
1647\r
1648**/\r
1649EFI_STATUS\r
1650ValidateQuestion (\r
1651 IN FORM_BROWSER_FORMSET *FormSet,\r
1652 IN FORM_BROWSER_FORM *Form,\r
1653 IN FORM_BROWSER_STATEMENT *Question,\r
1654 IN UINTN Type\r
1655 )\r
1656{\r
1657 EFI_STATUS Status;\r
1658 LIST_ENTRY *Link;\r
1659 LIST_ENTRY *ListHead;\r
1660 EFI_STRING PopUp;\r
1661 EFI_INPUT_KEY Key;\r
1662 FORM_EXPRESSION *Expression;\r
1663\r
1664 if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {\r
1665 ListHead = &Question->InconsistentListHead;\r
1666 } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
1667 ListHead = &Question->NoSubmitListHead;\r
1668 } else {\r
1669 return EFI_UNSUPPORTED;\r
1670 }\r
1671\r
1672 Link = GetFirstNode (ListHead);\r
1673 while (!IsNull (ListHead, Link)) {\r
1674 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
1675\r
1676 //\r
1677 // Evaluate the expression\r
1678 //\r
1679 Status = EvaluateExpression (FormSet, Form, Expression);\r
1680 if (EFI_ERROR (Status)) {\r
1681 return Status;\r
1682 }\r
1683\r
1684 if (Expression->Result.Value.b) {\r
1685 //\r
1686 // Condition meet, show up error message\r
1687 //\r
1688 if (Expression->Error != 0) {\r
1689 PopUp = GetToken (Expression->Error, FormSet->HiiHandle);\r
1690 do {\r
1691 CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);\r
1692 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
f4113e1f 1693 FreePool (PopUp);\r
7936fb6a 1694 }\r
1695\r
1696 return EFI_NOT_READY;\r
1697 }\r
1698\r
1699 Link = GetNextNode (ListHead, Link);\r
1700 }\r
1701\r
1702 return EFI_SUCCESS;\r
1703}\r
1704\r
1705\r
1706/**\r
5adb8db7 1707 Perform NoSubmit check for each Form in FormSet.\r
7936fb6a 1708\r
1709 @param FormSet FormSet data structure.\r
b18e7050 1710 @param CurrentForm Current input form data structure.\r
7936fb6a 1711\r
1712 @retval EFI_SUCCESS Form validation pass.\r
1713 @retval other Form validation failed.\r
1714\r
1715**/\r
1716EFI_STATUS\r
1717NoSubmitCheck (\r
b18e7050
ED
1718 IN FORM_BROWSER_FORMSET *FormSet,\r
1719 IN FORM_BROWSER_FORM *CurrentForm\r
7936fb6a 1720 )\r
1721{\r
1722 EFI_STATUS Status;\r
1723 LIST_ENTRY *Link;\r
1724 FORM_BROWSER_STATEMENT *Question;\r
5adb8db7
LG
1725 FORM_BROWSER_FORM *Form;\r
1726 LIST_ENTRY *LinkForm;\r
7936fb6a 1727\r
5adb8db7
LG
1728 LinkForm = GetFirstNode (&FormSet->FormListHead);\r
1729 while (!IsNull (&FormSet->FormListHead, LinkForm)) {\r
1730 Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);\r
b18e7050
ED
1731 LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);\r
1732\r
1733 if (CurrentForm != NULL && CurrentForm != Form) {\r
1734 continue;\r
1735 }\r
7936fb6a 1736\r
5adb8db7
LG
1737 Link = GetFirstNode (&Form->StatementListHead);\r
1738 while (!IsNull (&Form->StatementListHead, Link)) {\r
1739 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
1740\r
1741 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);\r
1742 if (EFI_ERROR (Status)) {\r
1743 return Status;\r
1744 }\r
1745\r
1746 Link = GetNextNode (&Form->StatementListHead, Link);\r
7936fb6a 1747 }\r
7936fb6a 1748 }\r
1749\r
1750 return EFI_SUCCESS;\r
1751}\r
1752\r
b18e7050
ED
1753/**\r
1754 Restore Storage's Edit copy to Shadow copy.\r
1755\r
1756 @param Storage The Storage to be synchronized.\r
1757\r
1758**/\r
1759VOID\r
1760RestoreStorage (\r
1761 IN FORMSET_STORAGE *Storage\r
1762 )\r
1763{\r
1764 LIST_ENTRY *Link;\r
1765 NAME_VALUE_NODE *Node;\r
1766\r
1767 switch (Storage->Type) {\r
1768 case EFI_HII_VARSTORE_BUFFER:\r
1769 CopyMem (Storage->EditBuffer, Storage->Buffer, Storage->Size);\r
1770 break;\r
1771\r
1772 case EFI_HII_VARSTORE_NAME_VALUE:\r
1773 Link = GetFirstNode (&Storage->NameValueListHead);\r
1774 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
1775 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
1776\r
1777 if (Node->EditValue != NULL) {\r
1778 FreePool (Node->EditValue);\r
1779 }\r
1780 Node->EditValue = AllocateCopyPool (StrSize (Node->Value), Node->Value);\r
1781 ASSERT (Node->EditValue != NULL);\r
1782 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
1783 }\r
1784 break;\r
1785\r
1786 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
1787 default:\r
1788 break;\r
1789 }\r
1790}\r
7936fb6a 1791\r
1792/**\r
b18e7050
ED
1793 Fill storage's edit copy with settings requested from Configuration Driver.\r
1794\r
1795 @param FormSet FormSet data structure.\r
1796 @param ConfigInfo The config info related to this form.\r
1797\r
1798 @retval EFI_SUCCESS The function completed successfully.\r
1799\r
1800**/\r
1801EFI_STATUS\r
1802FormRestoreStorage (\r
1803 IN FORM_BROWSER_FORMSET *FormSet,\r
1804 IN FORM_BROWSER_CONFIG_REQUEST *ConfigInfo\r
1805 )\r
1806{\r
1807 EFI_STATUS Status;\r
1808 EFI_STRING Progress;\r
1809 EFI_STRING Result;\r
1810 UINTN BufferSize;\r
1811 LIST_ENTRY *Link;\r
1812 NAME_VALUE_NODE *Node;\r
1813\r
1814 Status = EFI_SUCCESS;\r
1815 Result = NULL;\r
1816 if (FormSet->ConfigAccess == NULL) {\r
1817 return EFI_NOT_FOUND;\r
1818 }\r
1819\r
1820 if (ConfigInfo->ElementCount == 0) {\r
1821 //\r
1822 // Skip if there is no RequestElement\r
1823 //\r
1824 return EFI_SUCCESS;\r
1825 }\r
1826\r
1827 if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_BUFFER) {\r
1828 BufferSize = ConfigInfo->Storage->Size;\r
1829 Status = mHiiConfigRouting->BlockToConfig(\r
1830 mHiiConfigRouting,\r
1831 ConfigInfo->ConfigRequest,\r
1832 ConfigInfo->Storage->Buffer,\r
1833 BufferSize,\r
1834 &Result,\r
1835 &Progress\r
1836 );\r
1837 if (EFI_ERROR (Status)) {\r
1838 return Status;\r
1839 }\r
1840\r
1841 Status = mHiiConfigRouting->ConfigToBlock (\r
1842 mHiiConfigRouting,\r
1843 Result,\r
1844 ConfigInfo->Storage->EditBuffer,\r
1845 &BufferSize,\r
1846 &Progress\r
1847 );\r
1848 if (Result != NULL) {\r
1849 FreePool (Result);\r
1850 }\r
1851\r
1852 if (EFI_ERROR (Status)) {\r
1853 return Status;\r
1854 }\r
1855 } else if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
1856 Link = GetFirstNode (&ConfigInfo->Storage->NameValueListHead);\r
1857 while (!IsNull (&ConfigInfo->Storage->NameValueListHead, Link)) {\r
1858 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
1859\r
1860 if (StrStr (ConfigInfo->ConfigRequest, Node->Name) != NULL) {\r
1861 if (Node->EditValue != NULL) {\r
1862 FreePool (Node->EditValue);\r
1863 }\r
1864 Node->EditValue = AllocateCopyPool (StrSize (Node->Value), Node->Value);\r
1865 ASSERT (Node->EditValue != NULL);\r
1866 }\r
1867\r
1868 Link = GetNextNode (&ConfigInfo->Storage->NameValueListHead, Link);\r
1869 }\r
1870 }\r
1871\r
1872 return Status;\r
1873}\r
1874\r
1875\r
1876/**\r
1877 Discard data for form level or formset level.\r
7936fb6a 1878\r
1879 @param FormSet FormSet data structure.\r
1880 @param Form Form data structure.\r
b18e7050
ED
1881 @param SingleForm Only discard single form or formset.\r
1882\r
1883 @retval EFI_SUCCESS The function completed successfully.\r
1884\r
1885**/\r
1886EFI_STATUS\r
1887DiscardForm (\r
1888 IN FORM_BROWSER_FORMSET *FormSet,\r
1889 IN FORM_BROWSER_FORM *Form,\r
1890 IN BOOLEAN SingleForm\r
1891 )\r
1892{\r
1893 LIST_ENTRY *Link;\r
1894 FORMSET_STORAGE *Storage;\r
1895 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
1896\r
1897 if (SingleForm) {\r
1898 if (Form->NvUpdateRequired) {\r
1899 ConfigInfo = NULL;\r
1900 Link = GetFirstNode (&Form->ConfigRequestHead);\r
1901 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
1902 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
1903 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
1904\r
1905 if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1906 continue;\r
1907 }\r
1908\r
1909 //\r
1910 // Skip if there is no RequestElement\r
1911 //\r
1912 if (ConfigInfo->ElementCount == 0) {\r
1913 continue;\r
1914 }\r
1915\r
1916 //\r
1917 // Prepare <ConfigResp>\r
1918 //\r
1919 FormRestoreStorage(FormSet, ConfigInfo);\r
1920 }\r
1921\r
1922 Form->NvUpdateRequired = FALSE;\r
1923 }\r
1924 } else {\r
1925 if (IsNvUpdateRequired(FormSet)) {\r
1926 //\r
1927 // Discard Buffer storage or Name/Value storage\r
1928 //\r
1929 Link = GetFirstNode (&FormSet->StorageListHead);\r
1930 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
1931 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
1932 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
1933\r
1934 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1935 continue;\r
1936 }\r
1937\r
1938 //\r
1939 // Skip if there is no RequestElement\r
1940 //\r
1941 if (Storage->ElementCount == 0) {\r
1942 continue;\r
1943 }\r
1944\r
1945 RestoreStorage(Storage);\r
1946 }\r
1947\r
1948 UpdateNvInfoInForm(FormSet, FALSE); \r
1949 }\r
1950 }\r
1951\r
1952 return EFI_SUCCESS; \r
1953}\r
1954\r
1955/**\r
1956 Submit data for form level or formset level.\r
1957\r
1958 @param FormSet FormSet data structure.\r
1959 @param Form Form data structure.\r
1960 @param SingleForm whether submit for the single form or all form set.\r
7936fb6a 1961\r
1962 @retval EFI_SUCCESS The function completed successfully.\r
1963\r
1964**/\r
1965EFI_STATUS\r
1966SubmitForm (\r
1967 IN FORM_BROWSER_FORMSET *FormSet,\r
b18e7050
ED
1968 IN FORM_BROWSER_FORM *Form,\r
1969 IN BOOLEAN SingleForm\r
7936fb6a 1970 )\r
1971{\r
1972 EFI_STATUS Status;\r
1973 LIST_ENTRY *Link;\r
1974 EFI_STRING ConfigResp;\r
1975 EFI_STRING Progress;\r
1976 FORMSET_STORAGE *Storage;\r
b18e7050 1977 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
7936fb6a 1978\r
1979 //\r
1980 // Validate the Form by NoSubmit check\r
1981 //\r
b18e7050
ED
1982 if (SingleForm) {\r
1983 Status = NoSubmitCheck (FormSet, Form);\r
1984 } else {\r
1985 Status = NoSubmitCheck (FormSet, NULL);\r
1986 }\r
7936fb6a 1987 if (EFI_ERROR (Status)) {\r
1988 return Status;\r
1989 }\r
1990\r
b18e7050
ED
1991 if (SingleForm) {\r
1992 ConfigInfo = NULL;\r
1993 Link = GetFirstNode (&Form->ConfigRequestHead);\r
1994 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
1995 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
1996 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
7936fb6a 1997\r
b18e7050
ED
1998 if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1999 continue;\r
2000 }\r
7936fb6a 2001\r
b18e7050
ED
2002 //\r
2003 // Skip if there is no RequestElement\r
2004 //\r
2005 if (ConfigInfo->ElementCount == 0) {\r
2006 continue;\r
2007 }\r
7936fb6a 2008\r
b18e7050
ED
2009 //\r
2010 // Prepare <ConfigResp>\r
2011 //\r
2012 Status = StorageToConfigResp (ConfigInfo, &ConfigResp, TRUE);\r
2013 if (EFI_ERROR (Status)) {\r
2014 return Status;\r
2015 }\r
2016\r
2017 //\r
2018 // Send <ConfigResp> to Configuration Driver\r
2019 //\r
2020 if (FormSet->ConfigAccess != NULL) {\r
2021 Status = FormSet->ConfigAccess->RouteConfig (\r
2022 FormSet->ConfigAccess,\r
2023 ConfigResp,\r
2024 &Progress\r
2025 );\r
2026 if (EFI_ERROR (Status)) {\r
2027 FreePool (ConfigResp);\r
2028 return Status;\r
2029 }\r
2030 }\r
2031 FreePool (ConfigResp);\r
2032\r
2033 //\r
2034 // Config success, update storage shadow Buffer\r
2035 //\r
2036 SynchronizeStorage (ConfigInfo->Storage);\r
7936fb6a 2037 }\r
2038\r
b18e7050
ED
2039 Form->NvUpdateRequired = FALSE;\r
2040 } else {\r
7936fb6a 2041 //\r
b18e7050 2042 // Submit Buffer storage or Name/Value storage\r
7936fb6a 2043 //\r
b18e7050
ED
2044 Link = GetFirstNode (&FormSet->StorageListHead);\r
2045 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
2046 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
2047 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
2048\r
2049 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2050 continue;\r
2051 }\r
2052\r
2053 //\r
2054 // Skip if there is no RequestElement\r
2055 //\r
2056 if (Storage->ElementCount == 0) {\r
2057 continue;\r
2058 }\r
2059\r
2060 //\r
2061 // Prepare <ConfigResp>\r
2062 //\r
2063 Status = StorageToConfigResp (Storage, &ConfigResp, FALSE);\r
7936fb6a 2064 if (EFI_ERROR (Status)) {\r
7936fb6a 2065 return Status;\r
2066 }\r
b18e7050
ED
2067\r
2068 //\r
2069 // Send <ConfigResp> to Configuration Driver\r
2070 //\r
2071 if (FormSet->ConfigAccess != NULL) {\r
2072 Status = FormSet->ConfigAccess->RouteConfig (\r
2073 FormSet->ConfigAccess,\r
2074 ConfigResp,\r
2075 &Progress\r
2076 );\r
2077 if (EFI_ERROR (Status)) {\r
2078 FreePool (ConfigResp);\r
2079 return Status;\r
2080 }\r
2081 }\r
2082 FreePool (ConfigResp);\r
2083\r
2084 //\r
2085 // Config success, update storage shadow Buffer\r
2086 //\r
2087 SynchronizeStorage (Storage);\r
7936fb6a 2088 }\r
7936fb6a 2089\r
b18e7050 2090 UpdateNvInfoInForm(FormSet, FALSE);\r
7936fb6a 2091 }\r
2092\r
7936fb6a 2093 return EFI_SUCCESS;\r
2094}\r
2095\r
ee31d1be
ED
2096/**\r
2097 Get Question default value from AltCfg string.\r
2098\r
2099 @param FormSet The form set.\r
2100 @param Question The question.\r
2101 @param DefaultId The default Id.\r
2102\r
2103 @retval EFI_SUCCESS Question is reset to default value.\r
2104\r
2105**/\r
2106EFI_STATUS\r
2107GetDefaultValueFromAltCfg (\r
2108 IN FORM_BROWSER_FORMSET *FormSet,\r
2109 IN OUT FORM_BROWSER_STATEMENT *Question,\r
2110 IN UINT16 DefaultId\r
2111 )\r
2112{\r
2113 BOOLEAN IsBufferStorage;\r
2114 BOOLEAN IsString; \r
2115 UINTN Length;\r
2116 FORMSET_STORAGE *Storage;\r
2117 CHAR16 *ConfigRequest;\r
2118 CHAR16 *Progress;\r
2119 CHAR16 *Result;\r
2120 CHAR16 *ConfigResp;\r
2121 CHAR16 *Value;\r
2122 CHAR16 *StringPtr;\r
2123 UINTN LengthStr;\r
2124 UINT8 *Dst;\r
2125 CHAR16 TemStr[5];\r
2126 UINTN Index;\r
2127 UINT8 DigitUint8;\r
2128 EFI_STATUS Status;\r
2129\r
2130 Status = EFI_NOT_FOUND;\r
2131 Length = 0;\r
2132 Dst = NULL;\r
2133 ConfigRequest = NULL;\r
2134 Result = NULL;\r
2135 ConfigResp = NULL;\r
0194d26c 2136 Value = NULL;\r
ee31d1be
ED
2137 Storage = Question->Storage;\r
2138\r
2139 if ((Storage == NULL) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
2140 return Status;\r
2141 }\r
2142\r
2143 //\r
2144 // Question Value is provided by Buffer Storage or NameValue Storage\r
2145 //\r
2146 if (Question->BufferValue != NULL) {\r
2147 //\r
2148 // This Question is password or orderedlist\r
2149 //\r
2150 Dst = Question->BufferValue;\r
2151 } else {\r
2152 //\r
2153 // Other type of Questions\r
2154 //\r
2155 Dst = (UINT8 *) &Question->HiiValue.Value;\r
2156 }\r
2157\r
2158 IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
2159 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
2160\r
2161 //\r
2162 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
2163 // <ConfigHdr> + "&" + <VariableName>\r
2164 //\r
2165 if (IsBufferStorage) {\r
2166 Length = StrLen (Storage->ConfigHdr);\r
2167 Length += StrLen (Question->BlockName);\r
2168 } else {\r
2169 Length = StrLen (Storage->ConfigHdr);\r
2170 Length += StrLen (Question->VariableName) + 1;\r
2171 }\r
2172 ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
2173 ASSERT (ConfigRequest != NULL);\r
2174\r
2175 StrCpy (ConfigRequest, Storage->ConfigHdr);\r
2176 if (IsBufferStorage) {\r
2177 StrCat (ConfigRequest, Question->BlockName);\r
2178 } else {\r
2179 StrCat (ConfigRequest, L"&");\r
2180 StrCat (ConfigRequest, Question->VariableName);\r
2181 }\r
2182\r
2183 Status = FormSet->ConfigAccess->ExtractConfig (\r
2184 FormSet->ConfigAccess,\r
2185 ConfigRequest,\r
2186 &Progress,\r
2187 &Result\r
2188 );\r
2189 if (EFI_ERROR (Status)) {\r
2190 goto Done;\r
2191 }\r
2192\r
2193 //\r
2194 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
2195 // Get the default configuration string according to the default ID.\r
2196 //\r
2197 Status = mHiiConfigRouting->GetAltConfig (\r
2198 mHiiConfigRouting,\r
2199 Result,\r
2200 &Storage->Guid,\r
2201 Storage->Name,\r
2202 NULL,\r
2203 &DefaultId, // it can be NULL to get the current setting.\r
2204 &ConfigResp\r
2205 );\r
2206 \r
2207 //\r
2208 // The required setting can't be found. So, it is not required to be validated and set.\r
2209 //\r
2210 if (EFI_ERROR (Status)) {\r
2211 goto Done;\r
2212 }\r
2213\r
2214 //\r
2215 // Skip <ConfigRequest>\r
2216 //\r
ee31d1be 2217 if (IsBufferStorage) {\r
0194d26c
ED
2218 Value = StrStr (ConfigResp, L"&VALUE");\r
2219 ASSERT (Value != NULL);\r
ee31d1be
ED
2220 //\r
2221 // Skip "&VALUE"\r
2222 //\r
2223 Value = Value + 6;\r
0194d26c
ED
2224 } else {\r
2225 Value = StrStr (ConfigResp, Question->VariableName);\r
2226 ASSERT (Value != NULL);\r
2227\r
2228 Value = Value + StrLen (Question->VariableName);\r
ee31d1be
ED
2229 }\r
2230 if (*Value != '=') {\r
2231 Status = EFI_NOT_FOUND;\r
2232 goto Done;\r
2233 }\r
2234 //\r
2235 // Skip '=', point to value\r
2236 //\r
2237 Value = Value + 1;\r
2238\r
2239 //\r
2240 // Suppress <AltResp> if any\r
2241 //\r
2242 StringPtr = Value;\r
2243 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
2244 StringPtr++;\r
2245 }\r
2246 *StringPtr = L'\0';\r
2247\r
2248 LengthStr = StrLen (Value);\r
2249 if (!IsBufferStorage && IsString) {\r
2250 StringPtr = (CHAR16 *) Dst;\r
2251 ZeroMem (TemStr, sizeof (TemStr));\r
2252 for (Index = 0; Index < LengthStr; Index += 4) {\r
2253 StrnCpy (TemStr, Value + Index, 4);\r
2254 StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
2255 }\r
2256 //\r
2257 // Add tailing L'\0' character\r
2258 //\r
2259 StringPtr[Index/4] = L'\0';\r
2260 } else {\r
2261 ZeroMem (TemStr, sizeof (TemStr));\r
2262 for (Index = 0; Index < LengthStr; Index ++) {\r
2263 TemStr[0] = Value[LengthStr - Index - 1];\r
2264 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
2265 if ((Index & 1) == 0) {\r
2266 Dst [Index/2] = DigitUint8;\r
2267 } else {\r
2268 Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
2269 }\r
2270 }\r
2271 }\r
2272\r
2273Done:\r
2274 if (ConfigRequest != NULL){\r
2275 FreePool (ConfigRequest);\r
2276 }\r
2277\r
2278 if (ConfigResp != NULL) {\r
2279 FreePool (ConfigResp);\r
2280 }\r
2281 \r
2282 if (Result != NULL) {\r
2283 FreePool (Result);\r
2284 }\r
2285\r
2286 return Status;\r
2287}\r
2288\r
2289/**\r
2290 Get default Id value used for browser.\r
2291\r
2292 @param DefaultId The default id value used by hii.\r
2293\r
2294 @retval Browser used default value.\r
2295\r
2296**/\r
2297INTN\r
2298GetDefaultIdForCallBack (\r
2299 UINTN DefaultId\r
2300 )\r
2301{ \r
2302 if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
2303 return EFI_BROWSER_ACTION_DEFAULT_STANDARD;\r
2304 } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
2305 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;\r
2306 } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {\r
2307 return EFI_BROWSER_ACTION_DEFAULT_SAFE;\r
2308 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000) {\r
2309 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;\r
2310 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000) {\r
2311 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;\r
2312 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000) {\r
2313 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;\r
2314 } else {\r
2315 return -1;\r
2316 }\r
2317}\r
7936fb6a 2318\r
2319/**\r
2320 Reset Question to its default value.\r
2321\r
2322 @param FormSet The form set.\r
2323 @param Form The form.\r
2324 @param Question The question.\r
2325 @param DefaultId The Class of the default.\r
2326\r
2327 @retval EFI_SUCCESS Question is reset to default value.\r
2328\r
2329**/\r
2330EFI_STATUS\r
2331GetQuestionDefault (\r
2332 IN FORM_BROWSER_FORMSET *FormSet,\r
2333 IN FORM_BROWSER_FORM *Form,\r
2334 IN FORM_BROWSER_STATEMENT *Question,\r
2335 IN UINT16 DefaultId\r
2336 )\r
2337{\r
2338 EFI_STATUS Status;\r
2339 LIST_ENTRY *Link;\r
2340 QUESTION_DEFAULT *Default;\r
2341 QUESTION_OPTION *Option;\r
2342 EFI_HII_VALUE *HiiValue;\r
2343 UINT8 Index;\r
086cd2c8 2344 EFI_STRING StrValue;\r
ee31d1be
ED
2345 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2346 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
2347 INTN Action;\r
7936fb6a 2348\r
086cd2c8
LG
2349 Status = EFI_SUCCESS;\r
2350 StrValue = NULL;\r
7936fb6a 2351\r
2352 //\r
2353 // Statement don't have storage, skip them\r
2354 //\r
2355 if (Question->QuestionId == 0) {\r
2356 return Status;\r
2357 }\r
2358\r
2359 //\r
ee31d1be
ED
2360 // There are Five ways to specify default value for a Question:\r
2361 // 1, use call back function (highest priority)\r
2362 // 2, use ExtractConfig function\r
2363 // 3, use nested EFI_IFR_DEFAULT \r
2364 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
2365 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
7936fb6a 2366 //\r
2367 HiiValue = &Question->HiiValue;\r
2368\r
ee31d1be
ED
2369 //\r
2370 // Get Question defaut value from call back function.\r
2371 //\r
2372 ConfigAccess = FormSet->ConfigAccess;\r
2373 Action = GetDefaultIdForCallBack (DefaultId);\r
2374 if ((Action > 0) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {\r
2375 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2376 Status = ConfigAccess->Callback (\r
2377 ConfigAccess,\r
2378 Action,\r
2379 Question->QuestionId,\r
2380 HiiValue->Type,\r
2381 &HiiValue->Value,\r
2382 &ActionRequest\r
2383 );\r
2384 if (!EFI_ERROR (Status)) {\r
2385 return Status;\r
2386 }\r
2387 }\r
2388\r
2389 //\r
2390 // Get default value from altcfg string.\r
2391 //\r
2392 if (ConfigAccess != NULL) { \r
2393 Status = GetDefaultValueFromAltCfg(FormSet, Question, DefaultId);\r
2394 if (!EFI_ERROR (Status)) {\r
2395 return Status;\r
2396 }\r
2397 }\r
2398\r
7936fb6a 2399 //\r
2400 // EFI_IFR_DEFAULT has highest priority\r
2401 //\r
2402 if (!IsListEmpty (&Question->DefaultListHead)) {\r
2403 Link = GetFirstNode (&Question->DefaultListHead);\r
2404 while (!IsNull (&Question->DefaultListHead, Link)) {\r
2405 Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
2406\r
2407 if (Default->DefaultId == DefaultId) {\r
2408 if (Default->ValueExpression != NULL) {\r
2409 //\r
2410 // Default is provided by an Expression, evaluate it\r
2411 //\r
2412 Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
2413 if (EFI_ERROR (Status)) {\r
2414 return Status;\r
2415 }\r
2416\r
2417 CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_VALUE));\r
2418 } else {\r
2419 //\r
2420 // Default value is embedded in EFI_IFR_DEFAULT\r
2421 //\r
2422 CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
2423 }\r
2424\r
086cd2c8
LG
2425 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
2426 StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);\r
2427 if (StrValue == NULL) {\r
2428 return EFI_NOT_FOUND;\r
2429 }\r
2430 Question->BufferValue = AllocateCopyPool (StrSize (StrValue), StrValue);\r
2431 }\r
2432\r
7936fb6a 2433 return EFI_SUCCESS;\r
2434 }\r
2435\r
2436 Link = GetNextNode (&Question->DefaultListHead, Link);\r
2437 }\r
2438 }\r
2439\r
2440 //\r
2441 // EFI_ONE_OF_OPTION\r
2442 //\r
2443 if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
2444 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
2445 //\r
2446 // OneOfOption could only provide Standard and Manufacturing default\r
2447 //\r
2448 Link = GetFirstNode (&Question->OptionListHead);\r
2449 while (!IsNull (&Question->OptionListHead, Link)) {\r
2450 Option = QUESTION_OPTION_FROM_LINK (Link);\r
2451\r
2452 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
2453 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
2454 ) {\r
2455 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
2456\r
2457 return EFI_SUCCESS;\r
2458 }\r
2459\r
2460 Link = GetNextNode (&Question->OptionListHead, Link);\r
2461 }\r
2462 }\r
2463 }\r
2464\r
2465 //\r
2466 // EFI_IFR_CHECKBOX - lowest priority\r
2467 //\r
2468 if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
2469 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
2470 //\r
2471 // Checkbox could only provide Standard and Manufacturing default\r
2472 //\r
2473 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
2474 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
2475 ) {\r
2476 HiiValue->Value.b = TRUE;\r
2477 } else {\r
2478 HiiValue->Value.b = FALSE;\r
2479 }\r
2480\r
2481 return EFI_SUCCESS;\r
2482 }\r
2483 }\r
2484\r
2485 //\r
2486 // For Questions without default\r
2487 //\r
2488 switch (Question->Operand) {\r
cf4c5a42
LG
2489 case EFI_IFR_NUMERIC_OP:\r
2490 //\r
2491 // Take minimum value as numeric default value\r
2492 //\r
2493 if ((HiiValue->Value.u64 < Question->Minimum) || (HiiValue->Value.u64 > Question->Maximum)) {\r
2494 HiiValue->Value.u64 = Question->Minimum;\r
2495 }\r
2496 break;\r
2497\r
7936fb6a 2498 case EFI_IFR_ONE_OF_OP:\r
2499 //\r
2500 // Take first oneof option as oneof's default value\r
2501 //\r
d66e6c16 2502 if (ValueToOption (Question, HiiValue) == NULL) {\r
0a1147ed
LG
2503 Link = GetFirstNode (&Question->OptionListHead);\r
2504 if (!IsNull (&Question->OptionListHead, Link)) {\r
2505 Option = QUESTION_OPTION_FROM_LINK (Link);\r
2506 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
2507 }\r
7936fb6a 2508 }\r
2509 break;\r
2510\r
2511 case EFI_IFR_ORDERED_LIST_OP:\r
2512 //\r
2513 // Take option sequence in IFR as ordered list's default value\r
2514 //\r
2515 Index = 0;\r
2516 Link = GetFirstNode (&Question->OptionListHead);\r
2517 while (!IsNull (&Question->OptionListHead, Link)) {\r
2518 Option = QUESTION_OPTION_FROM_LINK (Link);\r
2519\r
d02847d3 2520 SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);\r
7936fb6a 2521\r
2522 Index++;\r
2523 if (Index >= Question->MaxContainers) {\r
2524 break;\r
2525 }\r
2526\r
2527 Link = GetNextNode (&Question->OptionListHead, Link);\r
2528 }\r
2529 break;\r
2530\r
2531 default:\r
2532 Status = EFI_NOT_FOUND;\r
2533 break;\r
2534 }\r
2535\r
2536 return Status;\r
2537}\r
2538\r
2539\r
2540/**\r
4f33c838 2541 Reset Questions in a Formset to their default value.\r
7936fb6a 2542\r
2543 @param FormSet FormSet data structure.\r
7936fb6a 2544 @param DefaultId The Class of the default.\r
2545\r
2546 @retval EFI_SUCCESS The function completed successfully.\r
2547\r
2548**/\r
2549EFI_STATUS\r
4f33c838 2550ExtractFormSetDefault (\r
7936fb6a 2551 IN FORM_BROWSER_FORMSET *FormSet,\r
7936fb6a 2552 IN UINT16 DefaultId\r
2553 )\r
2554{\r
2555 EFI_STATUS Status;\r
4f33c838
ED
2556 LIST_ENTRY *FormLink;\r
2557 LIST_ENTRY *StatementLink;\r
7936fb6a 2558 FORM_BROWSER_STATEMENT *Question;\r
4f33c838 2559 FORM_BROWSER_FORM *Form;\r
7936fb6a 2560\r
4f33c838
ED
2561 FormLink = GetFirstNode (&FormSet->FormListHead);\r
2562 while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
2563 Form = FORM_BROWSER_FORM_FROM_LINK (FormLink); \r
2564 \r
8d00a0f1 2565 //\r
4f33c838 2566 // Extract Form default\r
8d00a0f1 2567 //\r
4f33c838
ED
2568 StatementLink = GetFirstNode (&Form->StatementListHead);\r
2569 while (!IsNull (&Form->StatementListHead, StatementLink)) {\r
2570 Question = FORM_BROWSER_STATEMENT_FROM_LINK (StatementLink);\r
2571 StatementLink = GetNextNode (&Form->StatementListHead, StatementLink);\r
2572\r
2573 //\r
2574 // If Question is disabled, don't reset it to default\r
2575 //\r
2576 if (Question->DisableExpression != NULL) {\r
2577 Status = EvaluateExpression (FormSet, Form, Question->DisableExpression);\r
2578 if (!EFI_ERROR (Status) && Question->DisableExpression->Result.Value.b) {\r
2579 continue;\r
2580 }\r
8d00a0f1 2581 }\r
8d00a0f1 2582\r
4f33c838
ED
2583 //\r
2584 // Reset Question to its default value\r
2585 //\r
2586 Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
2587 if (EFI_ERROR (Status)) {\r
2588 continue;\r
2589 }\r
7936fb6a 2590\r
4f33c838
ED
2591 //\r
2592 // Synchronize Buffer storage's Edit buffer\r
2593 //\r
2594 if ((Question->Storage != NULL) &&\r
2595 (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
2596 SetQuestionValue (FormSet, Form, Question, TRUE);\r
2597 }\r
7936fb6a 2598 }\r
4f33c838 2599 FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
7936fb6a 2600 }\r
2601\r
2602 return EFI_SUCCESS;\r
2603}\r
2604\r
7936fb6a 2605/**\r
2606 Initialize Question's Edit copy from Storage.\r
2607\r
eccfeab1
LG
2608 @param Selection Selection contains the information about \r
2609 the Selection, form and formset to be displayed.\r
2610 Selection action may be updated in retrieve callback.\r
7936fb6a 2611 @param FormSet FormSet data structure.\r
2612 @param Form Form data structure.\r
2613\r
2614 @retval EFI_SUCCESS The function completed successfully.\r
2615\r
2616**/\r
2617EFI_STATUS\r
2618LoadFormConfig (\r
eccfeab1
LG
2619 IN OUT UI_MENU_SELECTION *Selection,\r
2620 IN FORM_BROWSER_FORMSET *FormSet,\r
2621 IN FORM_BROWSER_FORM *Form\r
7936fb6a 2622 )\r
2623{\r
eccfeab1
LG
2624 EFI_STATUS Status;\r
2625 LIST_ENTRY *Link;\r
2626 FORM_BROWSER_STATEMENT *Question;\r
2627 UINT8 *BufferValue;\r
2628 UINTN StorageWidth;\r
eccfeab1 2629 \r
7936fb6a 2630 Link = GetFirstNode (&Form->StatementListHead);\r
2631 while (!IsNull (&Form->StatementListHead, Link)) {\r
2632 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
2633\r
2634 //\r
2635 // Initialize local copy of Value for each Question\r
2636 //\r
2637 Status = GetQuestionValue (FormSet, Form, Question, TRUE);\r
2638 if (EFI_ERROR (Status)) {\r
2639 return Status;\r
2640 }\r
e2100bfa
ED
2641\r
2642 if ((Question->Operand == EFI_IFR_STRING_OP) || (Question->Operand == EFI_IFR_PASSWORD_OP)) {\r
2643 HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);\r
2644 }\r
2645\r
8ca6180f
ED
2646 //\r
2647 // According the spec, ref opcode try to get value from call back with "retrieve" type.\r
2648 //\r
2649 if ((Question->Operand == EFI_IFR_REF_OP) && (FormSet->ConfigAccess != NULL)) {\r
2650 Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE);\r
2651 if (EFI_ERROR (Status)) {\r
2652 return Status;\r
2653 }\r
2654 }\r
2655\r
eccfeab1
LG
2656 //\r
2657 // Check whether EfiVarstore with CallBack can be got.\r
2658 //\r
13ad1def
LG
2659 if ((FormSet->ConfigAccess != NULL) &&\r
2660 (Selection->Action != UI_ACTION_REFRESH_FORMSET) &&\r
2661 (Question->QuestionId != 0) && \r
2662 (Question->Storage != NULL) &&\r
eccfeab1
LG
2663 (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) && \r
2664 ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) {\r
13ad1def 2665\r
eccfeab1
LG
2666 //\r
2667 // Check QuestionValue does exist.\r
2668 //\r
2669 StorageWidth = Question->StorageWidth;\r
2670 if (Question->BufferValue != NULL) {\r
2671 BufferValue = Question->BufferValue;\r
2672 } else {\r
2673 BufferValue = (UINT8 *) &Question->HiiValue.Value;\r
2674 }\r
2675 Status = gRT->GetVariable (\r
2676 Question->VariableName,\r
2677 &Question->Storage->Guid,\r
2678 NULL,\r
2679 &StorageWidth,\r
2680 BufferValue\r
2681 );\r
2682\r
2683 if (!EFI_ERROR (Status)) {\r
b18e7050 2684 Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE);\r
eccfeab1
LG
2685 }\r
2686 }\r
7936fb6a 2687\r
2688 Link = GetNextNode (&Form->StatementListHead, Link);\r
2689 }\r
2690\r
2691 return EFI_SUCCESS;\r
2692}\r
2693\r
d66e6c16 2694/**\r
2695 Initialize Question's Edit copy from Storage for the whole Formset.\r
2696\r
eccfeab1
LG
2697 @param Selection Selection contains the information about \r
2698 the Selection, form and formset to be displayed.\r
2699 Selection action may be updated in retrieve callback.\r
d66e6c16 2700 @param FormSet FormSet data structure.\r
2701\r
2702 @retval EFI_SUCCESS The function completed successfully.\r
2703\r
2704**/\r
2705EFI_STATUS\r
2706LoadFormSetConfig (\r
eccfeab1
LG
2707 IN OUT UI_MENU_SELECTION *Selection,\r
2708 IN FORM_BROWSER_FORMSET *FormSet\r
d66e6c16 2709 )\r
2710{\r
eccfeab1
LG
2711 EFI_STATUS Status;\r
2712 LIST_ENTRY *Link;\r
2713 FORM_BROWSER_FORM *Form;\r
d66e6c16 2714\r
2715 Link = GetFirstNode (&FormSet->FormListHead);\r
2716 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2717 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2718\r
2719 //\r
2720 // Initialize local copy of Value for each Form\r
2721 //\r
eccfeab1 2722 Status = LoadFormConfig (Selection, FormSet, Form);\r
d66e6c16 2723 if (EFI_ERROR (Status)) {\r
2724 return Status;\r
2725 }\r
2726\r
2727 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2728 }\r
2729\r
2730 return EFI_SUCCESS;\r
2731}\r
2732\r
7936fb6a 2733/**\r
2734 Fill storage's edit copy with settings requested from Configuration Driver.\r
2735\r
2736 @param FormSet FormSet data structure.\r
2737 @param Storage Buffer Storage.\r
2738\r
2739 @retval EFI_SUCCESS The function completed successfully.\r
2740\r
2741**/\r
2742EFI_STATUS\r
2743LoadStorage (\r
2744 IN FORM_BROWSER_FORMSET *FormSet,\r
2745 IN FORMSET_STORAGE *Storage\r
2746 )\r
2747{\r
2748 EFI_STATUS Status;\r
2749 EFI_STRING Progress;\r
2750 EFI_STRING Result;\r
2751 CHAR16 *StrPtr;\r
2752\r
2753 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2754 return EFI_SUCCESS;\r
2755 }\r
2756\r
2757 if (FormSet->ConfigAccess == NULL) {\r
2758 return EFI_NOT_FOUND;\r
2759 }\r
2760\r
2761 if (Storage->ElementCount == 0) {\r
2762 //\r
2763 // Skip if there is no RequestElement\r
2764 //\r
2765 return EFI_SUCCESS;\r
2766 }\r
2767\r
2768 //\r
2769 // Request current settings from Configuration Driver\r
2770 //\r
2771 Status = FormSet->ConfigAccess->ExtractConfig (\r
2772 FormSet->ConfigAccess,\r
2773 Storage->ConfigRequest,\r
2774 &Progress,\r
2775 &Result\r
2776 );\r
2777 if (EFI_ERROR (Status)) {\r
2778 return Status;\r
2779 }\r
2780\r
2781 //\r
2782 // Convert Result from <ConfigAltResp> to <ConfigResp>\r
2783 //\r
2784 StrPtr = StrStr (Result, L"ALTCFG");\r
2785 if (StrPtr != NULL) {\r
2786 *StrPtr = L'\0';\r
2787 }\r
2788\r
2789 Status = ConfigRespToStorage (Storage, Result);\r
f4113e1f 2790 FreePool (Result);\r
7936fb6a 2791 return Status;\r
2792}\r
2793\r
2794\r
d66e6c16 2795/**\r
2796 Copy uncommitted data from source Storage to destination Storage.\r
2797\r
2798 @param Dst Target Storage for uncommitted data.\r
2799 @param Src Source Storage for uncommitted data.\r
2800\r
2801 @retval EFI_SUCCESS The function completed successfully.\r
2802 @retval EFI_INVALID_PARAMETER Source and destination Storage is not the same type.\r
2803\r
2804**/\r
2805EFI_STATUS\r
2806CopyStorage (\r
2807 IN OUT FORMSET_STORAGE *Dst,\r
2808 IN FORMSET_STORAGE *Src\r
2809 )\r
2810{\r
2811 LIST_ENTRY *Link;\r
2812 NAME_VALUE_NODE *Node;\r
2813\r
2814 if ((Dst->Type != Src->Type) || (Dst->Size != Src->Size)) {\r
2815 return EFI_INVALID_PARAMETER;\r
2816 }\r
2817\r
2818 switch (Src->Type) {\r
2819 case EFI_HII_VARSTORE_BUFFER:\r
2820 CopyMem (Dst->EditBuffer, Src->EditBuffer, Src->Size);\r
b18e7050 2821 CopyMem (Dst->Buffer, Src->Buffer, Src->Size);\r
d66e6c16 2822 break;\r
2823\r
2824 case EFI_HII_VARSTORE_NAME_VALUE:\r
2825 Link = GetFirstNode (&Src->NameValueListHead);\r
2826 while (!IsNull (&Src->NameValueListHead, Link)) {\r
2827 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
2828\r
b18e7050
ED
2829 SetValueByName (Dst, Node->Name, Node->EditValue, TRUE);\r
2830 SetValueByName (Dst, Node->Name, Node->Value, FALSE);\r
d66e6c16 2831\r
2832 Link = GetNextNode (&Src->NameValueListHead, Link);\r
2833 }\r
2834 break;\r
2835\r
2836 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
2837 default:\r
2838 break;\r
2839 }\r
2840\r
2841 return EFI_SUCCESS;\r
2842}\r
2843\r
2844\r
7936fb6a 2845/**\r
2846 Get current setting of Questions.\r
2847\r
2848 @param FormSet FormSet data structure.\r
2849\r
2850 @retval EFI_SUCCESS The function completed successfully.\r
2851\r
2852**/\r
2853EFI_STATUS\r
2854InitializeCurrentSetting (\r
2855 IN OUT FORM_BROWSER_FORMSET *FormSet\r
2856 )\r
2857{\r
2858 LIST_ENTRY *Link;\r
d66e6c16 2859 LIST_ENTRY *Link2;\r
7936fb6a 2860 FORMSET_STORAGE *Storage;\r
d66e6c16 2861 FORMSET_STORAGE *StorageSrc;\r
2862 FORMSET_STORAGE *OldStorage;\r
7936fb6a 2863 FORM_BROWSER_FORM *Form;\r
b00964a9 2864 FORM_BROWSER_FORM *Form2;\r
7936fb6a 2865 EFI_STATUS Status;\r
2866\r
2867 //\r
2868 // Extract default from IFR binary\r
2869 //\r
4f33c838
ED
2870 Status = ExtractFormSetDefault (FormSet, EFI_HII_DEFAULT_CLASS_STANDARD);\r
2871 if (EFI_ERROR (Status)) {\r
2872 return Status;\r
7936fb6a 2873 }\r
2874\r
2875 //\r
2876 // Request current settings from Configuration Driver\r
2877 //\r
2878 Link = GetFirstNode (&FormSet->StorageListHead);\r
2879 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
2880 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
2881\r
d66e6c16 2882 OldStorage = NULL;\r
2883 if (gOldFormSet != NULL) {\r
2884 //\r
2885 // Try to find the Storage in backup formset gOldFormSet\r
2886 //\r
2887 Link2 = GetFirstNode (&gOldFormSet->StorageListHead);\r
2888 while (!IsNull (&gOldFormSet->StorageListHead, Link2)) {\r
2889 StorageSrc = FORMSET_STORAGE_FROM_LINK (Link2);\r
2890\r
2891 if (StorageSrc->VarStoreId == Storage->VarStoreId) {\r
2892 OldStorage = StorageSrc;\r
2893 break;\r
2894 }\r
2895\r
2896 Link2 = GetNextNode (&gOldFormSet->StorageListHead, Link2);\r
2897 }\r
2898 }\r
2899\r
2900 if (OldStorage == NULL) {\r
2901 //\r
2902 // Storage is not found in backup formset, request it from ConfigDriver\r
2903 //\r
2904 Status = LoadStorage (FormSet, Storage);\r
b18e7050
ED
2905 //\r
2906 // Now Edit Buffer is filled with default values(lower priority) and current\r
2907 // settings(higher priority), sychronize it to shadow Buffer\r
2908 //\r
2909 if (!EFI_ERROR (Status)) {\r
2910 SynchronizeStorage (Storage);\r
2911 }\r
d66e6c16 2912 } else {\r
2913 //\r
2914 // Storage found in backup formset, use it\r
2915 //\r
2916 Status = CopyStorage (Storage, OldStorage);\r
2917 }\r
7936fb6a 2918\r
7936fb6a 2919 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
2920 }\r
2921\r
b00964a9
ED
2922 //\r
2923 // If has old formset, get the old nv update status.\r
2924 //\r
2925 if (gOldFormSet != NULL) {\r
2926 Link = GetFirstNode (&FormSet->FormListHead);\r
2927 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2928 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2929\r
2930 Link2 = GetFirstNode (&gOldFormSet->FormListHead);\r
2931 while (!IsNull (&gOldFormSet->FormListHead, Link2)) {\r
2932 Form2 = FORM_BROWSER_FORM_FROM_LINK (Link2);\r
2933\r
2934 if (Form->FormId == Form2->FormId) {\r
2935 Form->NvUpdateRequired = Form2->NvUpdateRequired;\r
2936 break;\r
2937 }\r
2938\r
2939 Link2 = GetNextNode (&gOldFormSet->FormListHead, Link2);\r
2940 }\r
2941 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2942 }\r
2943 }\r
2944\r
7936fb6a 2945 return EFI_SUCCESS;\r
2946}\r
2947\r
2948\r
2949/**\r
2950 Fetch the Ifr binary data of a FormSet.\r
2951\r
2952 @param Handle PackageList Handle\r
f5006bd9 2953 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
2954 specified (NULL or zero GUID), take the first\r
2955 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
2956 found in package list.\r
2957 On output, GUID of the formset found(if not NULL).\r
7936fb6a 2958 @param BinaryLength The length of the FormSet IFR binary.\r
2959 @param BinaryData The buffer designed to receive the FormSet.\r
2960\r
2961 @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
2962 BufferLength was updated.\r
2963 @retval EFI_INVALID_PARAMETER The handle is unknown.\r
2964 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
2965 be found with the requested FormId.\r
2966\r
2967**/\r
2968EFI_STATUS\r
2969GetIfrBinaryData (\r
2970 IN EFI_HII_HANDLE Handle,\r
2971 IN OUT EFI_GUID *FormSetGuid,\r
2972 OUT UINTN *BinaryLength,\r
2973 OUT UINT8 **BinaryData\r
2974 )\r
2975{\r
2976 EFI_STATUS Status;\r
2977 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
2978 UINTN BufferSize;\r
2979 UINT8 *Package;\r
2980 UINT8 *OpCodeData;\r
2981 UINT32 Offset;\r
2982 UINT32 Offset2;\r
7936fb6a 2983 UINT32 PackageListLength;\r
2984 EFI_HII_PACKAGE_HEADER PackageHeader;\r
0a1147ed
LG
2985 UINT8 Index;\r
2986 UINT8 NumberOfClassGuid;\r
f5006bd9 2987 BOOLEAN ClassGuidMatch;\r
0a1147ed 2988 EFI_GUID *ClassGuid;\r
f5006bd9 2989 EFI_GUID *ComparingGuid;\r
7936fb6a 2990\r
2991 OpCodeData = NULL;\r
2992 Package = NULL;\r
0c66bc76 2993 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
7936fb6a 2994\r
2995 //\r
f5006bd9 2996 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list\r
7936fb6a 2997 //\r
2998 if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {\r
f5006bd9 2999 ComparingGuid = &gEfiHiiPlatformSetupFormsetGuid;\r
7936fb6a 3000 } else {\r
f5006bd9 3001 ComparingGuid = FormSetGuid;\r
7936fb6a 3002 }\r
3003\r
3004 //\r
3005 // Get HII PackageList\r
3006 //\r
3007 BufferSize = 0;\r
3008 HiiPackageList = NULL;\r
3009 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
3010 if (Status == EFI_BUFFER_TOO_SMALL) {\r
3011 HiiPackageList = AllocatePool (BufferSize);\r
3012 ASSERT (HiiPackageList != NULL);\r
3013\r
3014 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
3015 }\r
3016 if (EFI_ERROR (Status)) {\r
3017 return Status;\r
3018 }\r
db0bd81c 3019 ASSERT (HiiPackageList != NULL);\r
d66e6c16 3020\r
7936fb6a 3021 //\r
3022 // Get Form package from this HII package List\r
3023 //\r
3024 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
3025 Offset2 = 0;\r
3026 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
3027\r
f5006bd9 3028 ClassGuidMatch = FALSE;\r
7936fb6a 3029 while (Offset < PackageListLength) {\r
3030 Package = ((UINT8 *) HiiPackageList) + Offset;\r
3031 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
3032\r
8d00a0f1 3033 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
7936fb6a 3034 //\r
3035 // Search FormSet in this Form Package\r
3036 //\r
3037 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
3038 while (Offset2 < PackageHeader.Length) {\r
3039 OpCodeData = Package + Offset2;\r
3040\r
3041 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
3042 //\r
f5006bd9 3043 // Try to compare against formset GUID\r
7936fb6a 3044 //\r
f5006bd9 3045 if (CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
3046 break;\r
7936fb6a 3047 }\r
3048\r
d228526f
LG
3049 if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
3050 //\r
3051 // Try to compare against formset class GUID\r
3052 //\r
3053 NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
3054 ClassGuid = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
3055 for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
3056 if (CompareGuid (ComparingGuid, ClassGuid + Index)) {\r
3057 ClassGuidMatch = TRUE;\r
3058 break;\r
3059 }\r
3060 }\r
3061 if (ClassGuidMatch) {\r
f5006bd9 3062 break;\r
3063 }\r
d228526f
LG
3064 } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {\r
3065 ClassGuidMatch = TRUE;\r
7936fb6a 3066 break;\r
3067 }\r
3068 }\r
3069\r
3070 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
3071 }\r
3072\r
3073 if (Offset2 < PackageHeader.Length) {\r
3074 //\r
3075 // Target formset found\r
3076 //\r
3077 break;\r
3078 }\r
3079 }\r
3080\r
3081 Offset += PackageHeader.Length;\r
3082 }\r
3083\r
3084 if (Offset >= PackageListLength) {\r
3085 //\r
3086 // Form package not found in this Package List\r
3087 //\r
f4113e1f 3088 FreePool (HiiPackageList);\r
7936fb6a 3089 return EFI_NOT_FOUND;\r
3090 }\r
3091\r
f5006bd9 3092 if (ClassGuidMatch && (FormSetGuid != NULL)) {\r
7936fb6a 3093 //\r
f5006bd9 3094 // Return the FormSet GUID\r
7936fb6a 3095 //\r
3096 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
3097 }\r
3098\r
3099 //\r
3100 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
3101 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
3102 // of the Form Package.\r
3103 //\r
3104 *BinaryLength = PackageHeader.Length - Offset2;\r
3105 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
3106\r
f4113e1f 3107 FreePool (HiiPackageList);\r
7936fb6a 3108\r
3109 if (*BinaryData == NULL) {\r
3110 return EFI_OUT_OF_RESOURCES;\r
3111 }\r
3112\r
3113 return EFI_SUCCESS;\r
3114}\r
3115\r
3116\r
3117/**\r
3118 Initialize the internal data structure of a FormSet.\r
3119\r
3120 @param Handle PackageList Handle\r
f5006bd9 3121 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
3122 specified (NULL or zero GUID), take the first\r
3123 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
3124 found in package list.\r
3125 On output, GUID of the formset found(if not NULL).\r
7936fb6a 3126 @param FormSet FormSet data structure.\r
3127\r
3128 @retval EFI_SUCCESS The function completed successfully.\r
3129 @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
3130\r
3131**/\r
3132EFI_STATUS\r
3133InitializeFormSet (\r
3134 IN EFI_HII_HANDLE Handle,\r
3135 IN OUT EFI_GUID *FormSetGuid,\r
3136 OUT FORM_BROWSER_FORMSET *FormSet\r
3137 )\r
3138{\r
3139 EFI_STATUS Status;\r
3140 EFI_HANDLE DriverHandle;\r
3141 UINT16 Index;\r
3142\r
3143 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
3144 if (EFI_ERROR (Status)) {\r
3145 return Status;\r
3146 }\r
3147\r
3148 FormSet->HiiHandle = Handle;\r
3149 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
3150\r
3151 //\r
3152 // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
3153 //\r
3154 Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
3155 if (EFI_ERROR (Status)) {\r
3156 return Status;\r
3157 }\r
3158 FormSet->DriverHandle = DriverHandle;\r
3159 Status = gBS->HandleProtocol (\r
3160 DriverHandle,\r
3161 &gEfiHiiConfigAccessProtocolGuid,\r
3162 (VOID **) &FormSet->ConfigAccess\r
3163 );\r
3164 if (EFI_ERROR (Status)) {\r
3165 //\r
3166 // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
3167 // list, then there will be no configuration action required\r
3168 //\r
3169 FormSet->ConfigAccess = NULL;\r
3170 }\r
3171\r
3172 //\r
3173 // Parse the IFR binary OpCodes\r
3174 //\r
3175 Status = ParseOpCodes (FormSet);\r
3176 if (EFI_ERROR (Status)) {\r
3177 return Status;\r
3178 }\r
3179\r
40245175
LG
3180 //\r
3181 // Set VFR type by FormSet SubClass field\r
3182 //\r
0a1147ed
LG
3183 gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP;\r
3184 if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {\r
3185 gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;\r
40245175
LG
3186 }\r
3187 \r
3188 //\r
3189 // Set VFR type by FormSet class guid\r
3190 //\r
3191 for (Index = 0; Index < 3; Index ++) {\r
3192 if (CompareGuid (&FormSet->ClassGuid[Index], &gEfiHiiPlatformSetupFormsetGuid)) {\r
3193 gClassOfVfr |= FORMSET_CLASS_PLATFORM_SETUP;\r
3194 break;\r
3195 }\r
3196 }\r
3197\r
3198 if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {\r
0a1147ed 3199 gFrontPageHandle = FormSet->HiiHandle;\r
7936fb6a 3200 }\r
3201\r
3202 //\r
3203 // Match GUID to find out the function key setting. If match fail, use the default setting.\r
3204 //\r
3205 for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {\r
3206 if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {\r
3207 //\r
3208 // Update the function key setting.\r
3209 //\r
3210 gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;\r
3211 //\r
3212 // Function key prompt can not be displayed if the function key has been disabled.\r
3213 //\r
7936fb6a 3214 if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {\r
3215 gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
3216 }\r
3217\r
3218 if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {\r
3219 gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
3220 }\r
3221 }\r
3222 }\r
3223\r
3224 return Status;\r
3225}\r
ce6d12cc 3226\r
3227\r
3228/**\r
3229 Save globals used by previous call to SendForm(). SendForm() may be called from \r
3230 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.\r
3231 So, save globals of previous call to SendForm() and restore them upon exit.\r
3232\r
3233**/\r
3234VOID\r
3235SaveBrowserContext (\r
3236 VOID\r
3237 )\r
3238{\r
3239 BROWSER_CONTEXT *Context;\r
3240\r
3241 gBrowserContextCount++;\r
3242 if (gBrowserContextCount == 1) {\r
3243 //\r
3244 // This is not reentry of SendForm(), no context to save\r
3245 //\r
3246 return;\r
3247 }\r
3248\r
3249 Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
3250 ASSERT (Context != NULL);\r
3251\r
3252 Context->Signature = BROWSER_CONTEXT_SIGNATURE;\r
3253\r
3254 //\r
3255 // Save FormBrowser context\r
3256 //\r
3257 Context->BannerData = gBannerData;\r
3258 Context->ClassOfVfr = gClassOfVfr;\r
3259 Context->FunctionKeySetting = gFunctionKeySetting;\r
3260 Context->ResetRequired = gResetRequired;\r
ce6d12cc 3261 Context->Direction = gDirection;\r
3262 Context->FunctionNineString = gFunctionNineString;\r
3263 Context->FunctionTenString = gFunctionTenString;\r
3264 Context->EnterString = gEnterString;\r
3265 Context->EnterCommitString = gEnterCommitString;\r
3266 Context->EnterEscapeString = gEnterEscapeString;\r
3267 Context->EscapeString = gEscapeString;\r
3268 Context->SaveFailed = gSaveFailed;\r
3269 Context->MoveHighlight = gMoveHighlight;\r
3270 Context->MakeSelection = gMakeSelection;\r
3271 Context->DecNumericInput = gDecNumericInput;\r
3272 Context->HexNumericInput = gHexNumericInput;\r
3273 Context->ToggleCheckBox = gToggleCheckBox;\r
3274 Context->PromptForData = gPromptForData;\r
3275 Context->PromptForPassword = gPromptForPassword;\r
3276 Context->PromptForNewPassword = gPromptForNewPassword;\r
3277 Context->ConfirmPassword = gConfirmPassword;\r
3278 Context->ConfirmError = gConfirmError;\r
3279 Context->PassowordInvalid = gPassowordInvalid;\r
3280 Context->PressEnter = gPressEnter;\r
3281 Context->EmptyString = gEmptyString;\r
3282 Context->AreYouSure = gAreYouSure;\r
3283 Context->YesResponse = gYesResponse;\r
3284 Context->NoResponse = gNoResponse;\r
3285 Context->MiniString = gMiniString;\r
3286 Context->PlusString = gPlusString;\r
3287 Context->MinusString = gMinusString;\r
3288 Context->AdjustNumber = gAdjustNumber;\r
3289 Context->SaveChanges = gSaveChanges;\r
3290 Context->OptionMismatch = gOptionMismatch;\r
2bb526f3 3291 Context->FormSuppress = gFormSuppress;\r
ce6d12cc 3292 Context->PromptBlockWidth = gPromptBlockWidth;\r
3293 Context->OptionBlockWidth = gOptionBlockWidth;\r
3294 Context->HelpBlockWidth = gHelpBlockWidth;\r
3295 Context->OldFormSet = gOldFormSet;\r
3296 Context->MenuRefreshHead = gMenuRefreshHead;\r
3297\r
3298 CopyMem (&Context->ScreenDimensions, &gScreenDimensions, sizeof (gScreenDimensions));\r
3299 CopyMem (&Context->MenuOption, &gMenuOption, sizeof (gMenuOption));\r
3300\r
3301 //\r
3302 // Insert to FormBrowser context list\r
3303 //\r
3304 InsertHeadList (&gBrowserContextList, &Context->Link);\r
3305}\r
3306\r
3307\r
3308/**\r
3309 Restore globals used by previous call to SendForm().\r
3310\r
3311**/\r
3312VOID\r
3313RestoreBrowserContext (\r
3314 VOID\r
3315 )\r
3316{\r
3317 LIST_ENTRY *Link;\r
3318 BROWSER_CONTEXT *Context;\r
3319\r
3320 ASSERT (gBrowserContextCount != 0);\r
3321 gBrowserContextCount--;\r
3322 if (gBrowserContextCount == 0) {\r
3323 //\r
3324 // This is not reentry of SendForm(), no context to restore\r
3325 //\r
3326 return;\r
3327 }\r
3328\r
3329 ASSERT (!IsListEmpty (&gBrowserContextList));\r
3330\r
3331 Link = GetFirstNode (&gBrowserContextList);\r
3332 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
3333\r
3334 //\r
3335 // Restore FormBrowser context\r
3336 //\r
3337 gBannerData = Context->BannerData;\r
3338 gClassOfVfr = Context->ClassOfVfr;\r
3339 gFunctionKeySetting = Context->FunctionKeySetting;\r
3340 gResetRequired = Context->ResetRequired;\r
ce6d12cc 3341 gDirection = Context->Direction;\r
3342 gFunctionNineString = Context->FunctionNineString;\r
3343 gFunctionTenString = Context->FunctionTenString;\r
3344 gEnterString = Context->EnterString;\r
3345 gEnterCommitString = Context->EnterCommitString;\r
3346 gEnterEscapeString = Context->EnterEscapeString;\r
3347 gEscapeString = Context->EscapeString;\r
3348 gSaveFailed = Context->SaveFailed;\r
3349 gMoveHighlight = Context->MoveHighlight;\r
3350 gMakeSelection = Context->MakeSelection;\r
3351 gDecNumericInput = Context->DecNumericInput;\r
3352 gHexNumericInput = Context->HexNumericInput;\r
3353 gToggleCheckBox = Context->ToggleCheckBox;\r
3354 gPromptForData = Context->PromptForData;\r
3355 gPromptForPassword = Context->PromptForPassword;\r
3356 gPromptForNewPassword = Context->PromptForNewPassword;\r
3357 gConfirmPassword = Context->ConfirmPassword;\r
3358 gConfirmError = Context->ConfirmError;\r
3359 gPassowordInvalid = Context->PassowordInvalid;\r
3360 gPressEnter = Context->PressEnter;\r
3361 gEmptyString = Context->EmptyString;\r
3362 gAreYouSure = Context->AreYouSure;\r
3363 gYesResponse = Context->YesResponse;\r
3364 gNoResponse = Context->NoResponse;\r
3365 gMiniString = Context->MiniString;\r
3366 gPlusString = Context->PlusString;\r
3367 gMinusString = Context->MinusString;\r
3368 gAdjustNumber = Context->AdjustNumber;\r
3369 gSaveChanges = Context->SaveChanges;\r
3370 gOptionMismatch = Context->OptionMismatch;\r
2bb526f3 3371 gFormSuppress = Context->FormSuppress;\r
ce6d12cc 3372 gPromptBlockWidth = Context->PromptBlockWidth;\r
3373 gOptionBlockWidth = Context->OptionBlockWidth;\r
3374 gHelpBlockWidth = Context->HelpBlockWidth;\r
3375 gOldFormSet = Context->OldFormSet;\r
3376 gMenuRefreshHead = Context->MenuRefreshHead;\r
3377\r
3378 CopyMem (&gScreenDimensions, &Context->ScreenDimensions, sizeof (gScreenDimensions));\r
3379 CopyMem (&gMenuOption, &Context->MenuOption, sizeof (gMenuOption));\r
3380\r
3381 //\r
3382 // Remove from FormBrowser context list\r
3383 //\r
3384 RemoveEntryList (&Context->Link);\r
3385 gBS->FreePool (Context);\r
3386}\r