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