]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
1. Support inconsistent if opcode used in string/password opcode.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Setup.c
CommitLineData
7936fb6a 1/** @file\r
2Entry and initialization module for the browser.\r
3\r
e5eed7d3
HT
4Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>\r
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
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
f7a14a9b
LG
272 gPromptBlockWidth = (CHAR16) (gOptionBlockWidth + LEFT_SKIPPED_COLUMNS);\r
273 gOptionBlockWidth = (CHAR16) (gOptionBlockWidth - LEFT_SKIPPED_COLUMNS);\r
7936fb6a 274\r
275 //\r
276 // Initialize the strings for the browser, upon exit of the browser, the strings will be freed\r
277 //\r
278 InitializeBrowserStrings ();\r
279\r
280 gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING;\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
2573712e
LG
665 if (HiiHandle == NULL) {\r
666 return NULL;\r
667 }\r
668\r
cb7d01c0 669 String = HiiGetString (HiiHandle, Token, NULL);\r
0e8e994d 670 if (String == NULL) {\r
671 String = AllocateCopyPool (sizeof (mUnknownString), mUnknownString);\r
672 ASSERT (String != NULL);\r
673 }\r
cb7d01c0 674 return (CHAR16 *) String;\r
7936fb6a 675}\r
676\r
677\r
678/**\r
679 Allocate new memory and then copy the Unicode string Source to Destination.\r
680\r
681 @param Dest Location to copy string\r
682 @param Src String to copy\r
683\r
684**/\r
685VOID\r
686NewStringCpy (\r
687 IN OUT CHAR16 **Dest,\r
688 IN CHAR16 *Src\r
689 )\r
690{\r
676df92c 691 if (*Dest != NULL) {\r
692 FreePool (*Dest);\r
693 }\r
7936fb6a 694 *Dest = AllocateCopyPool (StrSize (Src), Src);\r
695 ASSERT (*Dest != NULL);\r
696}\r
697\r
698\r
699/**\r
700 Allocate new memory and concatinate Source on the end of Destination.\r
701\r
702 @param Dest String to added to the end of.\r
703 @param Src String to concatinate.\r
704\r
705**/\r
706VOID\r
707NewStringCat (\r
708 IN OUT CHAR16 **Dest,\r
709 IN CHAR16 *Src\r
710 )\r
711{\r
712 CHAR16 *NewString;\r
713 UINTN TmpSize;\r
714\r
715 if (*Dest == NULL) {\r
716 NewStringCpy (Dest, Src);\r
717 return;\r
718 }\r
719\r
720 TmpSize = StrSize (*Dest);\r
721 NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1);\r
722 ASSERT (NewString != NULL);\r
723\r
724 StrCpy (NewString, *Dest);\r
725 StrCat (NewString, Src);\r
726\r
f4113e1f 727 FreePool (*Dest);\r
7936fb6a 728 *Dest = NewString;\r
729}\r
730\r
731\r
732/**\r
733 Synchronize Storage's Edit copy to Shadow copy.\r
734\r
735 @param Storage The Storage to be synchronized.\r
736\r
737**/\r
738VOID\r
739SynchronizeStorage (\r
740 IN FORMSET_STORAGE *Storage\r
741 )\r
742{\r
743 LIST_ENTRY *Link;\r
744 NAME_VALUE_NODE *Node;\r
745\r
746 switch (Storage->Type) {\r
747 case EFI_HII_VARSTORE_BUFFER:\r
748 CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);\r
749 break;\r
750\r
751 case EFI_HII_VARSTORE_NAME_VALUE:\r
752 Link = GetFirstNode (&Storage->NameValueListHead);\r
753 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
754 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
755\r
756 NewStringCpy (&Node->Value, Node->EditValue);\r
757\r
758 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
759 }\r
760 break;\r
761\r
762 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
763 default:\r
764 break;\r
765 }\r
766}\r
767\r
768\r
769/**\r
770 Get Value for given Name from a NameValue Storage.\r
771\r
772 @param Storage The NameValue Storage.\r
773 @param Name The Name.\r
774 @param Value The retured Value.\r
775\r
776 @retval EFI_SUCCESS Value found for given Name.\r
777 @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
778\r
779**/\r
780EFI_STATUS\r
781GetValueByName (\r
782 IN FORMSET_STORAGE *Storage,\r
783 IN CHAR16 *Name,\r
784 IN OUT CHAR16 **Value\r
785 )\r
786{\r
787 LIST_ENTRY *Link;\r
788 NAME_VALUE_NODE *Node;\r
789\r
790 *Value = NULL;\r
791\r
792 Link = GetFirstNode (&Storage->NameValueListHead);\r
793 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
794 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
795\r
796 if (StrCmp (Name, Node->Name) == 0) {\r
797 NewStringCpy (Value, Node->EditValue);\r
798 return EFI_SUCCESS;\r
799 }\r
800\r
801 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
802 }\r
803\r
804 return EFI_NOT_FOUND;\r
805}\r
806\r
807\r
808/**\r
809 Set Value of given Name in a NameValue Storage.\r
810\r
811 @param Storage The NameValue Storage.\r
812 @param Name The Name.\r
813 @param Value The Value to set.\r
814\r
815 @retval EFI_SUCCESS Value found for given Name.\r
816 @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
817\r
818**/\r
819EFI_STATUS\r
820SetValueByName (\r
821 IN FORMSET_STORAGE *Storage,\r
822 IN CHAR16 *Name,\r
823 IN CHAR16 *Value\r
824 )\r
825{\r
826 LIST_ENTRY *Link;\r
827 NAME_VALUE_NODE *Node;\r
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
676df92c 834 if (Node->EditValue != NULL) {\r
835 FreePool (Node->EditValue);\r
836 }\r
7936fb6a 837 Node->EditValue = AllocateCopyPool (StrSize (Value), Value);\r
838 ASSERT (Node->EditValue != NULL);\r
839 return EFI_SUCCESS;\r
840 }\r
841\r
842 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
843 }\r
844\r
845 return EFI_NOT_FOUND;\r
846}\r
847\r
848\r
849/**\r
850 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
851\r
852 @param Storage The Storage to be conveted.\r
853 @param ConfigResp The returned <ConfigResp>.\r
854\r
855 @retval EFI_SUCCESS Convert success.\r
856 @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
857\r
858**/\r
859EFI_STATUS\r
860StorageToConfigResp (\r
861 IN FORMSET_STORAGE *Storage,\r
862 IN CHAR16 **ConfigResp\r
863 )\r
864{\r
865 EFI_STATUS Status;\r
866 EFI_STRING Progress;\r
867 LIST_ENTRY *Link;\r
868 NAME_VALUE_NODE *Node;\r
869\r
870 Status = EFI_SUCCESS;\r
871\r
872 switch (Storage->Type) {\r
873 case EFI_HII_VARSTORE_BUFFER:\r
874 Status = mHiiConfigRouting->BlockToConfig (\r
875 mHiiConfigRouting,\r
876 Storage->ConfigRequest,\r
877 Storage->EditBuffer,\r
878 Storage->Size,\r
879 ConfigResp,\r
880 &Progress\r
881 );\r
882 break;\r
883\r
884 case EFI_HII_VARSTORE_NAME_VALUE:\r
885 *ConfigResp = NULL;\r
886 NewStringCat (ConfigResp, Storage->ConfigHdr);\r
887\r
888 Link = GetFirstNode (&Storage->NameValueListHead);\r
889 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
890 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
891\r
892 NewStringCat (ConfigResp, L"&");\r
893 NewStringCat (ConfigResp, Node->Name);\r
894 NewStringCat (ConfigResp, L"=");\r
895 NewStringCat (ConfigResp, Node->EditValue);\r
896\r
897 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
898 }\r
899 break;\r
900\r
901 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
902 default:\r
903 Status = EFI_INVALID_PARAMETER;\r
904 break;\r
905 }\r
906\r
907 return Status;\r
908}\r
909\r
910\r
911/**\r
912 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.\r
913\r
914 @param Storage The Storage to receive the settings.\r
915 @param ConfigResp The <ConfigResp> to be converted.\r
916\r
917 @retval EFI_SUCCESS Convert success.\r
918 @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
919\r
920**/\r
921EFI_STATUS\r
922ConfigRespToStorage (\r
923 IN FORMSET_STORAGE *Storage,\r
924 IN CHAR16 *ConfigResp\r
925 )\r
926{\r
927 EFI_STATUS Status;\r
928 EFI_STRING Progress;\r
929 UINTN BufferSize;\r
930 CHAR16 *StrPtr;\r
931 CHAR16 *Name;\r
932 CHAR16 *Value;\r
933\r
934 Status = EFI_SUCCESS;\r
935\r
936 switch (Storage->Type) {\r
937 case EFI_HII_VARSTORE_BUFFER:\r
938 BufferSize = Storage->Size;\r
939 Status = mHiiConfigRouting->ConfigToBlock (\r
940 mHiiConfigRouting,\r
941 ConfigResp,\r
942 Storage->EditBuffer,\r
943 &BufferSize,\r
944 &Progress\r
945 );\r
946 break;\r
947\r
948 case EFI_HII_VARSTORE_NAME_VALUE:\r
40245175
LG
949 StrPtr = StrStr (ConfigResp, L"PATH");\r
950 if (StrPtr == NULL) {\r
951 break;\r
952 }\r
7936fb6a 953 StrPtr = StrStr (ConfigResp, L"&");\r
954 while (StrPtr != NULL) {\r
955 //\r
956 // Skip '&'\r
957 //\r
958 StrPtr = StrPtr + 1;\r
959 Name = StrPtr;\r
960 StrPtr = StrStr (StrPtr, L"=");\r
961 if (StrPtr == NULL) {\r
962 break;\r
963 }\r
964 *StrPtr = 0;\r
965\r
966 //\r
967 // Skip '='\r
968 //\r
969 StrPtr = StrPtr + 1;\r
970 Value = StrPtr;\r
971 StrPtr = StrStr (StrPtr, L"&");\r
972 if (StrPtr != NULL) {\r
973 *StrPtr = 0;\r
974 }\r
975 SetValueByName (Storage, Name, Value);\r
976 }\r
977 break;\r
978\r
979 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
980 default:\r
981 Status = EFI_INVALID_PARAMETER;\r
982 break;\r
983 }\r
984\r
985 return Status;\r
986}\r
987\r
988\r
989/**\r
990 Get Question's current Value.\r
991\r
992 @param FormSet FormSet data structure.\r
993 @param Form Form data structure.\r
994 @param Question Question to be initialized.\r
995 @param Cached TRUE: get from Edit copy FALSE: get from original\r
996 Storage\r
997\r
998 @retval EFI_SUCCESS The function completed successfully.\r
999\r
1000**/\r
1001EFI_STATUS\r
1002GetQuestionValue (\r
1003 IN FORM_BROWSER_FORMSET *FormSet,\r
1004 IN FORM_BROWSER_FORM *Form,\r
1005 IN OUT FORM_BROWSER_STATEMENT *Question,\r
1006 IN BOOLEAN Cached\r
1007 )\r
1008{\r
1009 EFI_STATUS Status;\r
1010 BOOLEAN Enabled;\r
1011 BOOLEAN Pending;\r
1012 UINT8 *Dst;\r
1013 UINTN StorageWidth;\r
1014 EFI_TIME EfiTime;\r
1015 FORMSET_STORAGE *Storage;\r
1016 EFI_IFR_TYPE_VALUE *QuestionValue;\r
1017 CHAR16 *ConfigRequest;\r
1018 CHAR16 *Progress;\r
1019 CHAR16 *Result;\r
1020 CHAR16 *Value;\r
8d00a0f1 1021 CHAR16 *StringPtr;\r
7936fb6a 1022 UINTN Length;\r
63d55bb9
LG
1023 UINTN Index;\r
1024 UINTN LengthStr;\r
7936fb6a 1025 BOOLEAN IsBufferStorage;\r
1026 BOOLEAN IsString;\r
63d55bb9
LG
1027 CHAR16 TemStr[5];\r
1028 UINT8 DigitUint8;\r
7936fb6a 1029\r
1030 Status = EFI_SUCCESS;\r
1031\r
1032 //\r
1033 // Statement don't have storage, skip them\r
1034 //\r
1035 if (Question->QuestionId == 0) {\r
1036 return Status;\r
1037 }\r
1038\r
1039 //\r
1040 // Question value is provided by an Expression, evaluate it\r
1041 //\r
1042 if (Question->ValueExpression != NULL) {\r
1043 Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);\r
1044 if (!EFI_ERROR (Status)) {\r
1045 CopyMem (&Question->HiiValue, &Question->ValueExpression->Result, sizeof (EFI_HII_VALUE));\r
1046 }\r
1047 return Status;\r
1048 }\r
2573712e
LG
1049 \r
1050 //\r
1051 // Get question value by read expression.\r
1052 //\r
1053 if (Question->ReadExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {\r
1054 Status = EvaluateExpression (FormSet, Form, Question->ReadExpression);\r
1055 if (!EFI_ERROR (Status) && (Question->ReadExpression->Result.Type < EFI_IFR_TYPE_OTHER)) {\r
1056 //\r
1057 // Only update question value to the valid result.\r
1058 //\r
1059 CopyMem (&Question->HiiValue, &Question->ReadExpression->Result, sizeof (EFI_HII_VALUE));\r
1060 return EFI_SUCCESS;\r
1061 }\r
1062 }\r
7936fb6a 1063\r
1064 //\r
1065 // Question value is provided by RTC\r
1066 //\r
1067 Storage = Question->Storage;\r
1068 QuestionValue = &Question->HiiValue.Value;\r
1069 if (Storage == NULL) {\r
1070 //\r
1071 // It's a Question without storage, or RTC date/time\r
1072 //\r
1073 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1074 //\r
1075 // Date and time define the same Flags bit\r
1076 //\r
1077 switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
1078 case QF_DATE_STORAGE_TIME:\r
1079 Status = gRT->GetTime (&EfiTime, NULL);\r
1080 break;\r
1081\r
1082 case QF_DATE_STORAGE_WAKEUP:\r
1083 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
1084 break;\r
1085\r
1086 case QF_DATE_STORAGE_NORMAL:\r
1087 default:\r
1088 //\r
1089 // For date/time without storage\r
1090 //\r
1091 return EFI_SUCCESS;\r
1092 }\r
1093\r
1094 if (EFI_ERROR (Status)) {\r
1095 return Status;\r
1096 }\r
1097\r
1098 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1099 QuestionValue->date.Year = EfiTime.Year;\r
1100 QuestionValue->date.Month = EfiTime.Month;\r
1101 QuestionValue->date.Day = EfiTime.Day;\r
1102 } else {\r
1103 QuestionValue->time.Hour = EfiTime.Hour;\r
1104 QuestionValue->time.Minute = EfiTime.Minute;\r
1105 QuestionValue->time.Second = EfiTime.Second;\r
1106 }\r
1107 }\r
1108\r
1109 return EFI_SUCCESS;\r
1110 }\r
1111\r
1112 //\r
1113 // Question value is provided by EFI variable\r
1114 //\r
1115 StorageWidth = Question->StorageWidth;\r
1116 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1117 if (Question->BufferValue != NULL) {\r
1118 Dst = Question->BufferValue;\r
1119 } else {\r
1120 Dst = (UINT8 *) QuestionValue;\r
1121 }\r
1122\r
1123 Status = gRT->GetVariable (\r
1124 Question->VariableName,\r
1125 &Storage->Guid,\r
1126 NULL,\r
1127 &StorageWidth,\r
1128 Dst\r
1129 );\r
1130 //\r
1131 // Always return success, even this EFI variable doesn't exist\r
1132 //\r
1133 return EFI_SUCCESS;\r
1134 }\r
1135\r
1136 //\r
1137 // Question Value is provided by Buffer Storage or NameValue Storage\r
1138 //\r
1139 if (Question->BufferValue != NULL) {\r
1140 //\r
1141 // This Question is password or orderedlist\r
1142 //\r
1143 Dst = Question->BufferValue;\r
1144 } else {\r
1145 //\r
1146 // Other type of Questions\r
1147 //\r
1148 Dst = (UINT8 *) &Question->HiiValue.Value;\r
1149 }\r
1150\r
1151 IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
1152 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
1153 if (Cached) {\r
1154 if (IsBufferStorage) {\r
1155 //\r
1156 // Copy from storage Edit buffer\r
1157 //\r
1158 CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
1159 } else {\r
1b2bf3ca 1160 Value = NULL;\r
7936fb6a 1161 Status = GetValueByName (Storage, Question->VariableName, &Value);\r
1162 if (EFI_ERROR (Status)) {\r
1163 return Status;\r
1164 }\r
d66e6c16 1165\r
1b2bf3ca 1166 ASSERT (Value != NULL);\r
63d55bb9
LG
1167 LengthStr = StrLen (Value);\r
1168 Status = EFI_SUCCESS;\r
7936fb6a 1169 if (IsString) {\r
1170 //\r
1171 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
63d55bb9 1172 // Add string tail char L'\0' into Length\r
7936fb6a 1173 //\r
63d55bb9
LG
1174 Length = StorageWidth + sizeof (CHAR16);\r
1175 if (Length < ((LengthStr / 4 + 1) * 2)) {\r
1176 Status = EFI_BUFFER_TOO_SMALL;\r
1177 } else {\r
1178 StringPtr = (CHAR16 *) Dst;\r
1179 ZeroMem (TemStr, sizeof (TemStr));\r
1180 for (Index = 0; Index < LengthStr; Index += 4) {\r
1181 StrnCpy (TemStr, Value + Index, 4);\r
1182 StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
1183 }\r
1184 //\r
1185 // Add tailing L'\0' character\r
1186 //\r
1187 StringPtr[Index/4] = L'\0';\r
1188 }\r
7936fb6a 1189 } else {\r
63d55bb9
LG
1190 if (StorageWidth < ((LengthStr + 1) / 2)) {\r
1191 Status = EFI_BUFFER_TOO_SMALL;\r
1192 } else {\r
1193 ZeroMem (TemStr, sizeof (TemStr));\r
1194 for (Index = 0; Index < LengthStr; Index ++) {\r
1195 TemStr[0] = Value[LengthStr - Index - 1];\r
1196 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
1197 if ((Index & 1) == 0) {\r
1198 Dst [Index/2] = DigitUint8;\r
1199 } else {\r
634303c9 1200 Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
63d55bb9
LG
1201 }\r
1202 }\r
1203 }\r
7936fb6a 1204 }\r
1205\r
f4113e1f 1206 FreePool (Value);\r
7936fb6a 1207 }\r
1208 } else {\r
1209 //\r
1210 // Request current settings from Configuration Driver\r
1211 //\r
1212 if (FormSet->ConfigAccess == NULL) {\r
1213 return EFI_NOT_FOUND;\r
1214 }\r
1215\r
1216 //\r
1217 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
1218 // <ConfigHdr> + "&" + <VariableName>\r
1219 //\r
1220 if (IsBufferStorage) {\r
1221 Length = StrLen (Storage->ConfigHdr);\r
1222 Length += StrLen (Question->BlockName);\r
1223 } else {\r
1224 Length = StrLen (Storage->ConfigHdr);\r
1225 Length += StrLen (Question->VariableName) + 1;\r
1226 }\r
1227 ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
1228 ASSERT (ConfigRequest != NULL);\r
1229\r
1230 StrCpy (ConfigRequest, Storage->ConfigHdr);\r
1231 if (IsBufferStorage) {\r
1232 StrCat (ConfigRequest, Question->BlockName);\r
1233 } else {\r
1234 StrCat (ConfigRequest, L"&");\r
1235 StrCat (ConfigRequest, Question->VariableName);\r
1236 }\r
1237\r
1238 Status = FormSet->ConfigAccess->ExtractConfig (\r
1239 FormSet->ConfigAccess,\r
1240 ConfigRequest,\r
1241 &Progress,\r
1242 &Result\r
1243 );\r
1244 if (EFI_ERROR (Status)) {\r
1245 return Status;\r
1246 }\r
1247\r
1248 //\r
1249 // Skip <ConfigRequest>\r
1250 //\r
1251 Value = Result + Length;\r
1252 if (IsBufferStorage) {\r
1253 //\r
1254 // Skip "&VALUE"\r
1255 //\r
1256 Value = Value + 6;\r
1257 }\r
1258 if (*Value != '=') {\r
f4113e1f 1259 FreePool (Result);\r
7936fb6a 1260 return EFI_NOT_FOUND;\r
1261 }\r
1262 //\r
1263 // Skip '=', point to value\r
1264 //\r
1265 Value = Value + 1;\r
8d00a0f1 1266\r
1267 //\r
1268 // Suppress <AltResp> if any\r
1269 //\r
1270 StringPtr = Value;\r
1271 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
1272 StringPtr++;\r
1273 }\r
1274 *StringPtr = L'\0';\r
1275\r
63d55bb9
LG
1276 LengthStr = StrLen (Value);\r
1277 Status = EFI_SUCCESS;\r
7936fb6a 1278 if (!IsBufferStorage && IsString) {\r
1279 //\r
1280 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
63d55bb9 1281 // Add string tail char L'\0' into Length\r
7936fb6a 1282 //\r
63d55bb9
LG
1283 Length = StorageWidth + sizeof (CHAR16);\r
1284 if (Length < ((LengthStr / 4 + 1) * 2)) {\r
1285 Status = EFI_BUFFER_TOO_SMALL;\r
1286 } else {\r
1287 StringPtr = (CHAR16 *) Dst;\r
1288 ZeroMem (TemStr, sizeof (TemStr));\r
1289 for (Index = 0; Index < LengthStr; Index += 4) {\r
1290 StrnCpy (TemStr, Value + Index, 4);\r
1291 StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
1292 }\r
1293 //\r
1294 // Add tailing L'\0' character\r
1295 //\r
1296 StringPtr[Index/4] = L'\0';\r
1297 }\r
7936fb6a 1298 } else {\r
63d55bb9
LG
1299 if (StorageWidth < ((LengthStr + 1) / 2)) {\r
1300 Status = EFI_BUFFER_TOO_SMALL;\r
1301 } else {\r
1302 ZeroMem (TemStr, sizeof (TemStr));\r
1303 for (Index = 0; Index < LengthStr; Index ++) {\r
1304 TemStr[0] = Value[LengthStr - Index - 1];\r
1305 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
1306 if ((Index & 1) == 0) {\r
1307 Dst [Index/2] = DigitUint8;\r
1308 } else {\r
634303c9 1309 Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
63d55bb9
LG
1310 }\r
1311 }\r
7936fb6a 1312 }\r
1313 }\r
1314\r
63d55bb9
LG
1315 if (EFI_ERROR (Status)) {\r
1316 FreePool (Result);\r
1317 return Status;\r
1318 }\r
1319\r
7936fb6a 1320 //\r
1321 // Synchronize Edit Buffer\r
1322 //\r
1323 if (IsBufferStorage) {\r
1324 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
1325 } else {\r
1326 SetValueByName (Storage, Question->VariableName, Value);\r
1327 }\r
63d55bb9 1328\r
f4113e1f 1329 FreePool (Result);\r
7936fb6a 1330 }\r
1331\r
1332 return Status;\r
1333}\r
1334\r
1335\r
1336/**\r
1337 Save Question Value to edit copy(cached) or Storage(uncached).\r
1338\r
1339 @param FormSet FormSet data structure.\r
1340 @param Form Form data structure.\r
1341 @param Question Pointer to the Question.\r
1342 @param Cached TRUE: set to Edit copy FALSE: set to original\r
1343 Storage\r
1344\r
1345 @retval EFI_SUCCESS The function completed successfully.\r
1346\r
1347**/\r
1348EFI_STATUS\r
1349SetQuestionValue (\r
1350 IN FORM_BROWSER_FORMSET *FormSet,\r
1351 IN FORM_BROWSER_FORM *Form,\r
1352 IN OUT FORM_BROWSER_STATEMENT *Question,\r
1353 IN BOOLEAN Cached\r
1354 )\r
1355{\r
1356 EFI_STATUS Status;\r
1357 BOOLEAN Enabled;\r
1358 BOOLEAN Pending;\r
1359 UINT8 *Src;\r
1360 EFI_TIME EfiTime;\r
1361 UINTN BufferLen;\r
1362 UINTN StorageWidth;\r
1363 FORMSET_STORAGE *Storage;\r
1364 EFI_IFR_TYPE_VALUE *QuestionValue;\r
1365 CHAR16 *ConfigResp;\r
1366 CHAR16 *Progress;\r
1367 CHAR16 *Value;\r
1368 UINTN Length;\r
1369 BOOLEAN IsBufferStorage;\r
1370 BOOLEAN IsString;\r
63d55bb9
LG
1371 UINT8 *TemBuffer;\r
1372 CHAR16 *TemName;\r
1373 CHAR16 *TemString;\r
1374 UINTN Index;\r
7936fb6a 1375\r
1376 Status = EFI_SUCCESS;\r
1377\r
1378 //\r
1379 // Statement don't have storage, skip them\r
1380 //\r
1381 if (Question->QuestionId == 0) {\r
1382 return Status;\r
1383 }\r
1384\r
1385 //\r
1386 // If Question value is provided by an Expression, then it is read only\r
1387 //\r
1388 if (Question->ValueExpression != NULL) {\r
1389 return Status;\r
1390 }\r
2573712e
LG
1391 \r
1392 //\r
1393 // Before set question value, evaluate its write expression.\r
1394 //\r
1395 if (Question->WriteExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {\r
1396 Status = EvaluateExpression (FormSet, Form, Question->WriteExpression);\r
1397 if (EFI_ERROR (Status)) {\r
1398 return Status;\r
1399 }\r
1400 }\r
7936fb6a 1401\r
1402 //\r
1403 // Question value is provided by RTC\r
1404 //\r
1405 Storage = Question->Storage;\r
1406 QuestionValue = &Question->HiiValue.Value;\r
1407 if (Storage == NULL) {\r
1408 //\r
1409 // It's a Question without storage, or RTC date/time\r
1410 //\r
1411 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1412 //\r
1413 // Date and time define the same Flags bit\r
1414 //\r
1415 switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
1416 case QF_DATE_STORAGE_TIME:\r
1417 Status = gRT->GetTime (&EfiTime, NULL);\r
1418 break;\r
1419\r
1420 case QF_DATE_STORAGE_WAKEUP:\r
1421 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
1422 break;\r
1423\r
1424 case QF_DATE_STORAGE_NORMAL:\r
1425 default:\r
1426 //\r
1427 // For date/time without storage\r
1428 //\r
1429 return EFI_SUCCESS;\r
1430 }\r
1431\r
1432 if (EFI_ERROR (Status)) {\r
1433 return Status;\r
1434 }\r
1435\r
1436 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1437 EfiTime.Year = QuestionValue->date.Year;\r
1438 EfiTime.Month = QuestionValue->date.Month;\r
1439 EfiTime.Day = QuestionValue->date.Day;\r
1440 } else {\r
1441 EfiTime.Hour = QuestionValue->time.Hour;\r
1442 EfiTime.Minute = QuestionValue->time.Minute;\r
1443 EfiTime.Second = QuestionValue->time.Second;\r
1444 }\r
1445\r
1446 if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {\r
1447 Status = gRT->SetTime (&EfiTime);\r
1448 } else {\r
1449 Status = gRT->SetWakeupTime (TRUE, &EfiTime);\r
1450 }\r
1451 }\r
1452\r
1453 return Status;\r
1454 }\r
1455\r
1456 //\r
1457 // Question value is provided by EFI variable\r
1458 //\r
1459 StorageWidth = Question->StorageWidth;\r
1460 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1461 if (Question->BufferValue != NULL) {\r
1462 Src = Question->BufferValue;\r
1463 } else {\r
1464 Src = (UINT8 *) QuestionValue;\r
1465 }\r
1466\r
1467 Status = gRT->SetVariable (\r
1468 Question->VariableName,\r
1469 &Storage->Guid,\r
1470 Storage->Attributes,\r
1471 StorageWidth,\r
1472 Src\r
1473 );\r
1474 return Status;\r
1475 }\r
1476\r
1477 //\r
1478 // Question Value is provided by Buffer Storage or NameValue Storage\r
1479 //\r
1480 if (Question->BufferValue != NULL) {\r
1481 Src = Question->BufferValue;\r
1482 } else {\r
1483 Src = (UINT8 *) &Question->HiiValue.Value;\r
1484 }\r
1485\r
1486 IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
1487 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
1488 if (IsBufferStorage) {\r
1489 //\r
1490 // Copy to storage edit buffer\r
1491 //\r
1492 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
1493 } else {\r
1494 if (IsString) {\r
1495 //\r
63d55bb9 1496 // Allocate enough string buffer.\r
7936fb6a 1497 //\r
1498 Value = NULL;\r
1499 BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
1500 Value = AllocateZeroPool (BufferLen);\r
1501 ASSERT (Value != NULL);\r
63d55bb9
LG
1502 //\r
1503 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
1504 //\r
1505 TemName = (CHAR16 *) Src;\r
1506 TemString = Value;\r
1507 for (; *TemName != L'\0'; TemName++) {\r
1508 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
1509 }\r
7936fb6a 1510 } else {\r
1511 BufferLen = StorageWidth * 2 + 1;\r
1512 Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
1513 ASSERT (Value != NULL);\r
63d55bb9
LG
1514 //\r
1515 // Convert Buffer to Hex String\r
1516 //\r
1517 TemBuffer = Src + StorageWidth - 1;\r
1518 TemString = Value;\r
1519 for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
1520 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
1521 }\r
7936fb6a 1522 }\r
1523\r
1524 Status = SetValueByName (Storage, Question->VariableName, Value);\r
f4113e1f 1525 FreePool (Value);\r
7936fb6a 1526 }\r
1527\r
1528 if (!Cached) {\r
1529 //\r
1530 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||\r
1531 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"\r
1532 //\r
1533 if (IsBufferStorage) {\r
1534 Length = StrLen (Question->BlockName) + 7;\r
1535 } else {\r
1536 Length = StrLen (Question->VariableName) + 2;\r
1537 }\r
1538 if (!IsBufferStorage && IsString) {\r
1539 Length += (StrLen ((CHAR16 *) Src) * 4);\r
1540 } else {\r
1541 Length += (StorageWidth * 2);\r
1542 }\r
1543 ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16));\r
1544 ASSERT (ConfigResp != NULL);\r
1545\r
1546 StrCpy (ConfigResp, Storage->ConfigHdr);\r
1547 if (IsBufferStorage) {\r
1548 StrCat (ConfigResp, Question->BlockName);\r
1549 StrCat (ConfigResp, L"&VALUE=");\r
1550 } else {\r
1551 StrCat (ConfigResp, L"&");\r
1552 StrCat (ConfigResp, Question->VariableName);\r
1553 StrCat (ConfigResp, L"=");\r
1554 }\r
1555\r
1556 Value = ConfigResp + StrLen (ConfigResp);\r
63d55bb9 1557\r
7936fb6a 1558 if (!IsBufferStorage && IsString) {\r
1559 //\r
1560 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
1561 //\r
63d55bb9
LG
1562 TemName = (CHAR16 *) Src;\r
1563 TemString = Value;\r
1564 for (; *TemName != L'\0'; TemName++) {\r
1565 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
1566 }\r
7936fb6a 1567 } else {\r
63d55bb9
LG
1568 //\r
1569 // Convert Buffer to Hex String\r
1570 //\r
1571 TemBuffer = Src + StorageWidth - 1;\r
1572 TemString = Value;\r
1573 for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
1574 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
1575 }\r
1576 }\r
d66e6c16 1577\r
63d55bb9
LG
1578 //\r
1579 // Convert to lower char.\r
1580 //\r
1581 for (TemString = Value; *Value != L'\0'; Value++) {\r
1582 if (*Value >= L'A' && *Value <= L'Z') {\r
1583 *Value = (CHAR16) (*Value - L'A' + L'a');\r
1584 }\r
7936fb6a 1585 }\r
1586\r
1587 //\r
1588 // Submit Question Value to Configuration Driver\r
1589 //\r
1590 if (FormSet->ConfigAccess != NULL) {\r
1591 Status = FormSet->ConfigAccess->RouteConfig (\r
1592 FormSet->ConfigAccess,\r
1593 ConfigResp,\r
1594 &Progress\r
1595 );\r
1596 if (EFI_ERROR (Status)) {\r
f4113e1f 1597 FreePool (ConfigResp);\r
7936fb6a 1598 return Status;\r
1599 }\r
1600 }\r
f4113e1f 1601 FreePool (ConfigResp);\r
7936fb6a 1602\r
1603 //\r
1604 // Synchronize shadow Buffer\r
1605 //\r
1606 SynchronizeStorage (Storage);\r
1607 }\r
1608\r
1609 return Status;\r
1610}\r
1611\r
1612\r
1613/**\r
1614 Perform inconsistent check for a Form.\r
1615\r
1616 @param FormSet FormSet data structure.\r
1617 @param Form Form data structure.\r
1618 @param Question The Question to be validated.\r
1619 @param Type Validation type: InConsistent or NoSubmit\r
1620\r
1621 @retval EFI_SUCCESS Form validation pass.\r
1622 @retval other Form validation failed.\r
1623\r
1624**/\r
1625EFI_STATUS\r
1626ValidateQuestion (\r
1627 IN FORM_BROWSER_FORMSET *FormSet,\r
1628 IN FORM_BROWSER_FORM *Form,\r
1629 IN FORM_BROWSER_STATEMENT *Question,\r
1630 IN UINTN Type\r
1631 )\r
1632{\r
1633 EFI_STATUS Status;\r
1634 LIST_ENTRY *Link;\r
1635 LIST_ENTRY *ListHead;\r
1636 EFI_STRING PopUp;\r
1637 EFI_INPUT_KEY Key;\r
1638 FORM_EXPRESSION *Expression;\r
1639\r
1640 if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {\r
1641 ListHead = &Question->InconsistentListHead;\r
1642 } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
1643 ListHead = &Question->NoSubmitListHead;\r
1644 } else {\r
1645 return EFI_UNSUPPORTED;\r
1646 }\r
1647\r
1648 Link = GetFirstNode (ListHead);\r
1649 while (!IsNull (ListHead, Link)) {\r
1650 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
1651\r
1652 //\r
1653 // Evaluate the expression\r
1654 //\r
1655 Status = EvaluateExpression (FormSet, Form, Expression);\r
1656 if (EFI_ERROR (Status)) {\r
1657 return Status;\r
1658 }\r
1659\r
1660 if (Expression->Result.Value.b) {\r
1661 //\r
1662 // Condition meet, show up error message\r
1663 //\r
1664 if (Expression->Error != 0) {\r
1665 PopUp = GetToken (Expression->Error, FormSet->HiiHandle);\r
1666 do {\r
1667 CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);\r
1668 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
f4113e1f 1669 FreePool (PopUp);\r
7936fb6a 1670 }\r
1671\r
1672 return EFI_NOT_READY;\r
1673 }\r
1674\r
1675 Link = GetNextNode (ListHead, Link);\r
1676 }\r
1677\r
1678 return EFI_SUCCESS;\r
1679}\r
1680\r
1681\r
1682/**\r
5adb8db7 1683 Perform NoSubmit check for each Form in FormSet.\r
7936fb6a 1684\r
1685 @param FormSet FormSet data structure.\r
7936fb6a 1686\r
1687 @retval EFI_SUCCESS Form validation pass.\r
1688 @retval other Form validation failed.\r
1689\r
1690**/\r
1691EFI_STATUS\r
1692NoSubmitCheck (\r
5adb8db7 1693 IN FORM_BROWSER_FORMSET *FormSet\r
7936fb6a 1694 )\r
1695{\r
1696 EFI_STATUS Status;\r
1697 LIST_ENTRY *Link;\r
1698 FORM_BROWSER_STATEMENT *Question;\r
5adb8db7
LG
1699 FORM_BROWSER_FORM *Form;\r
1700 LIST_ENTRY *LinkForm;\r
7936fb6a 1701\r
5adb8db7
LG
1702 LinkForm = GetFirstNode (&FormSet->FormListHead);\r
1703 while (!IsNull (&FormSet->FormListHead, LinkForm)) {\r
1704 Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);\r
7936fb6a 1705\r
5adb8db7
LG
1706 Link = GetFirstNode (&Form->StatementListHead);\r
1707 while (!IsNull (&Form->StatementListHead, Link)) {\r
1708 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
1709\r
1710 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);\r
1711 if (EFI_ERROR (Status)) {\r
1712 return Status;\r
1713 }\r
1714\r
1715 Link = GetNextNode (&Form->StatementListHead, Link);\r
7936fb6a 1716 }\r
1717\r
5adb8db7 1718 LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);\r
7936fb6a 1719 }\r
1720\r
1721 return EFI_SUCCESS;\r
1722}\r
1723\r
1724\r
1725/**\r
1726 Submit a Form.\r
1727\r
1728 @param FormSet FormSet data structure.\r
1729 @param Form Form data structure.\r
1730\r
1731 @retval EFI_SUCCESS The function completed successfully.\r
1732\r
1733**/\r
1734EFI_STATUS\r
1735SubmitForm (\r
1736 IN FORM_BROWSER_FORMSET *FormSet,\r
1737 IN FORM_BROWSER_FORM *Form\r
1738 )\r
1739{\r
1740 EFI_STATUS Status;\r
1741 LIST_ENTRY *Link;\r
1742 EFI_STRING ConfigResp;\r
1743 EFI_STRING Progress;\r
1744 FORMSET_STORAGE *Storage;\r
1745\r
1746 //\r
1747 // Validate the Form by NoSubmit check\r
1748 //\r
5adb8db7 1749 Status = NoSubmitCheck (FormSet);\r
7936fb6a 1750 if (EFI_ERROR (Status)) {\r
1751 return Status;\r
1752 }\r
1753\r
1754 //\r
1755 // Submit Buffer storage or Name/Value storage\r
1756 //\r
1757 Link = GetFirstNode (&FormSet->StorageListHead);\r
1758 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
1759 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
1760 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
1761\r
1762 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1763 continue;\r
1764 }\r
1765\r
1766 //\r
1767 // Skip if there is no RequestElement\r
1768 //\r
1769 if (Storage->ElementCount == 0) {\r
1770 continue;\r
1771 }\r
1772\r
1773 //\r
1774 // Prepare <ConfigResp>\r
1775 //\r
1776 Status = StorageToConfigResp (Storage, &ConfigResp);\r
1777 if (EFI_ERROR (Status)) {\r
1778 return Status;\r
1779 }\r
1780\r
1781 //\r
1782 // Send <ConfigResp> to Configuration Driver\r
1783 //\r
1784 if (FormSet->ConfigAccess != NULL) {\r
1785 Status = FormSet->ConfigAccess->RouteConfig (\r
1786 FormSet->ConfigAccess,\r
1787 ConfigResp,\r
1788 &Progress\r
1789 );\r
1790 if (EFI_ERROR (Status)) {\r
f4113e1f 1791 FreePool (ConfigResp);\r
7936fb6a 1792 return Status;\r
1793 }\r
1794 }\r
f4113e1f 1795 FreePool (ConfigResp);\r
7936fb6a 1796\r
1797 //\r
1798 // Config success, update storage shadow Buffer\r
1799 //\r
1800 SynchronizeStorage (Storage);\r
1801 }\r
1802\r
1803 gNvUpdateRequired = FALSE;\r
1804\r
1805 return EFI_SUCCESS;\r
1806}\r
1807\r
1808\r
1809/**\r
1810 Reset Question to its default value.\r
1811\r
1812 @param FormSet The form set.\r
1813 @param Form The form.\r
1814 @param Question The question.\r
1815 @param DefaultId The Class of the default.\r
1816\r
1817 @retval EFI_SUCCESS Question is reset to default value.\r
1818\r
1819**/\r
1820EFI_STATUS\r
1821GetQuestionDefault (\r
1822 IN FORM_BROWSER_FORMSET *FormSet,\r
1823 IN FORM_BROWSER_FORM *Form,\r
1824 IN FORM_BROWSER_STATEMENT *Question,\r
1825 IN UINT16 DefaultId\r
1826 )\r
1827{\r
1828 EFI_STATUS Status;\r
1829 LIST_ENTRY *Link;\r
1830 QUESTION_DEFAULT *Default;\r
1831 QUESTION_OPTION *Option;\r
1832 EFI_HII_VALUE *HiiValue;\r
1833 UINT8 Index;\r
086cd2c8 1834 EFI_STRING StrValue;\r
7936fb6a 1835\r
086cd2c8
LG
1836 Status = EFI_SUCCESS;\r
1837 StrValue = NULL;\r
7936fb6a 1838\r
1839 //\r
1840 // Statement don't have storage, skip them\r
1841 //\r
1842 if (Question->QuestionId == 0) {\r
1843 return Status;\r
1844 }\r
1845\r
1846 //\r
1847 // There are three ways to specify default value for a Question:\r
1848 // 1, use nested EFI_IFR_DEFAULT (highest priority)\r
1849 // 2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
1850 // 3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
1851 //\r
1852 HiiValue = &Question->HiiValue;\r
1853\r
1854 //\r
1855 // EFI_IFR_DEFAULT has highest priority\r
1856 //\r
1857 if (!IsListEmpty (&Question->DefaultListHead)) {\r
1858 Link = GetFirstNode (&Question->DefaultListHead);\r
1859 while (!IsNull (&Question->DefaultListHead, Link)) {\r
1860 Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
1861\r
1862 if (Default->DefaultId == DefaultId) {\r
1863 if (Default->ValueExpression != NULL) {\r
1864 //\r
1865 // Default is provided by an Expression, evaluate it\r
1866 //\r
1867 Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
1868 if (EFI_ERROR (Status)) {\r
1869 return Status;\r
1870 }\r
1871\r
1872 CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_VALUE));\r
1873 } else {\r
1874 //\r
1875 // Default value is embedded in EFI_IFR_DEFAULT\r
1876 //\r
1877 CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
1878 }\r
1879\r
086cd2c8
LG
1880 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
1881 StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);\r
1882 if (StrValue == NULL) {\r
1883 return EFI_NOT_FOUND;\r
1884 }\r
1885 Question->BufferValue = AllocateCopyPool (StrSize (StrValue), StrValue);\r
1886 }\r
1887\r
7936fb6a 1888 return EFI_SUCCESS;\r
1889 }\r
1890\r
1891 Link = GetNextNode (&Question->DefaultListHead, Link);\r
1892 }\r
1893 }\r
1894\r
1895 //\r
1896 // EFI_ONE_OF_OPTION\r
1897 //\r
1898 if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
1899 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
1900 //\r
1901 // OneOfOption could only provide Standard and Manufacturing default\r
1902 //\r
1903 Link = GetFirstNode (&Question->OptionListHead);\r
1904 while (!IsNull (&Question->OptionListHead, Link)) {\r
1905 Option = QUESTION_OPTION_FROM_LINK (Link);\r
1906\r
1907 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
1908 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
1909 ) {\r
1910 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
1911\r
1912 return EFI_SUCCESS;\r
1913 }\r
1914\r
1915 Link = GetNextNode (&Question->OptionListHead, Link);\r
1916 }\r
1917 }\r
1918 }\r
1919\r
1920 //\r
1921 // EFI_IFR_CHECKBOX - lowest priority\r
1922 //\r
1923 if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
1924 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
1925 //\r
1926 // Checkbox could only provide Standard and Manufacturing default\r
1927 //\r
1928 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
1929 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
1930 ) {\r
1931 HiiValue->Value.b = TRUE;\r
1932 } else {\r
1933 HiiValue->Value.b = FALSE;\r
1934 }\r
1935\r
1936 return EFI_SUCCESS;\r
1937 }\r
1938 }\r
1939\r
1940 //\r
1941 // For Questions without default\r
1942 //\r
1943 switch (Question->Operand) {\r
7936fb6a 1944 case EFI_IFR_ONE_OF_OP:\r
1945 //\r
1946 // Take first oneof option as oneof's default value\r
1947 //\r
d66e6c16 1948 if (ValueToOption (Question, HiiValue) == NULL) {\r
0a1147ed
LG
1949 Link = GetFirstNode (&Question->OptionListHead);\r
1950 if (!IsNull (&Question->OptionListHead, Link)) {\r
1951 Option = QUESTION_OPTION_FROM_LINK (Link);\r
1952 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
1953 }\r
7936fb6a 1954 }\r
1955 break;\r
1956\r
1957 case EFI_IFR_ORDERED_LIST_OP:\r
1958 //\r
1959 // Take option sequence in IFR as ordered list's default value\r
1960 //\r
1961 Index = 0;\r
1962 Link = GetFirstNode (&Question->OptionListHead);\r
1963 while (!IsNull (&Question->OptionListHead, Link)) {\r
1964 Option = QUESTION_OPTION_FROM_LINK (Link);\r
1965\r
d02847d3 1966 SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);\r
7936fb6a 1967\r
1968 Index++;\r
1969 if (Index >= Question->MaxContainers) {\r
1970 break;\r
1971 }\r
1972\r
1973 Link = GetNextNode (&Question->OptionListHead, Link);\r
1974 }\r
1975 break;\r
1976\r
1977 default:\r
1978 Status = EFI_NOT_FOUND;\r
1979 break;\r
1980 }\r
1981\r
1982 return Status;\r
1983}\r
1984\r
1985\r
1986/**\r
1987 Reset Questions in a Form to their default value.\r
1988\r
1989 @param FormSet FormSet data structure.\r
1990 @param Form The Form which to be reset.\r
1991 @param DefaultId The Class of the default.\r
1992\r
1993 @retval EFI_SUCCESS The function completed successfully.\r
1994\r
1995**/\r
1996EFI_STATUS\r
1997ExtractFormDefault (\r
1998 IN FORM_BROWSER_FORMSET *FormSet,\r
1999 IN FORM_BROWSER_FORM *Form,\r
2000 IN UINT16 DefaultId\r
2001 )\r
2002{\r
2003 EFI_STATUS Status;\r
2004 LIST_ENTRY *Link;\r
2005 FORM_BROWSER_STATEMENT *Question;\r
2006\r
2007 Link = GetFirstNode (&Form->StatementListHead);\r
2008 while (!IsNull (&Form->StatementListHead, Link)) {\r
2009 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
2010 Link = GetNextNode (&Form->StatementListHead, Link);\r
2011\r
8d00a0f1 2012 //\r
0a1147ed 2013 // If Question is disabled, don't reset it to default\r
8d00a0f1 2014 //\r
0a1147ed
LG
2015 if (Question->DisableExpression != NULL) {\r
2016 Status = EvaluateExpression (FormSet, Form, Question->DisableExpression);\r
2017 if (!EFI_ERROR (Status) && Question->DisableExpression->Result.Value.b) {\r
8d00a0f1 2018 continue;\r
2019 }\r
2020 }\r
2021\r
7936fb6a 2022 //\r
2023 // Reset Question to its default value\r
2024 //\r
2025 Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
2026 if (EFI_ERROR (Status)) {\r
2027 continue;\r
2028 }\r
2029\r
2030 //\r
2031 // Synchronize Buffer storage's Edit buffer\r
2032 //\r
2033 if ((Question->Storage != NULL) &&\r
2034 (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
2035 SetQuestionValue (FormSet, Form, Question, TRUE);\r
2036 }\r
2037 }\r
2038\r
2039 return EFI_SUCCESS;\r
2040}\r
2041\r
7936fb6a 2042/**\r
2043 Initialize Question's Edit copy from Storage.\r
2044\r
eccfeab1
LG
2045 @param Selection Selection contains the information about \r
2046 the Selection, form and formset to be displayed.\r
2047 Selection action may be updated in retrieve callback.\r
7936fb6a 2048 @param FormSet FormSet data structure.\r
2049 @param Form Form data structure.\r
2050\r
2051 @retval EFI_SUCCESS The function completed successfully.\r
2052\r
2053**/\r
2054EFI_STATUS\r
2055LoadFormConfig (\r
eccfeab1
LG
2056 IN OUT UI_MENU_SELECTION *Selection,\r
2057 IN FORM_BROWSER_FORMSET *FormSet,\r
2058 IN FORM_BROWSER_FORM *Form\r
7936fb6a 2059 )\r
2060{\r
eccfeab1
LG
2061 EFI_STATUS Status;\r
2062 LIST_ENTRY *Link;\r
2063 FORM_BROWSER_STATEMENT *Question;\r
2064 UINT8 *BufferValue;\r
2065 UINTN StorageWidth;\r
2066 EFI_HII_VALUE *HiiValue;\r
2067 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
2068 \r
7936fb6a 2069 Link = GetFirstNode (&Form->StatementListHead);\r
2070 while (!IsNull (&Form->StatementListHead, Link)) {\r
2071 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
2072\r
2073 //\r
2074 // Initialize local copy of Value for each Question\r
2075 //\r
2076 Status = GetQuestionValue (FormSet, Form, Question, TRUE);\r
2077 if (EFI_ERROR (Status)) {\r
2078 return Status;\r
2079 }\r
e2100bfa
ED
2080\r
2081 if ((Question->Operand == EFI_IFR_STRING_OP) || (Question->Operand == EFI_IFR_PASSWORD_OP)) {\r
2082 HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);\r
2083 }\r
2084\r
eccfeab1
LG
2085 //\r
2086 // Check whether EfiVarstore with CallBack can be got.\r
2087 //\r
13ad1def
LG
2088 if ((FormSet->ConfigAccess != NULL) &&\r
2089 (Selection->Action != UI_ACTION_REFRESH_FORMSET) &&\r
2090 (Question->QuestionId != 0) && \r
2091 (Question->Storage != NULL) &&\r
eccfeab1
LG
2092 (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) && \r
2093 ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) {\r
13ad1def 2094\r
eccfeab1
LG
2095 //\r
2096 // Check QuestionValue does exist.\r
2097 //\r
2098 StorageWidth = Question->StorageWidth;\r
2099 if (Question->BufferValue != NULL) {\r
2100 BufferValue = Question->BufferValue;\r
2101 } else {\r
2102 BufferValue = (UINT8 *) &Question->HiiValue.Value;\r
2103 }\r
2104 Status = gRT->GetVariable (\r
2105 Question->VariableName,\r
2106 &Question->Storage->Guid,\r
2107 NULL,\r
2108 &StorageWidth,\r
2109 BufferValue\r
2110 );\r
2111\r
2112 if (!EFI_ERROR (Status)) {\r
2113 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2114 HiiValue = &Question->HiiValue;\r
2115 BufferValue = (UINT8 *) &Question->HiiValue.Value;\r
e2100bfa 2116 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
eccfeab1
LG
2117 BufferValue = Question->BufferValue;\r
2118 }\r
2119\r
2120 Status = FormSet->ConfigAccess->Callback (\r
2121 FormSet->ConfigAccess,\r
2122 EFI_BROWSER_ACTION_RETRIEVE,\r
2123 Question->QuestionId,\r
2124 HiiValue->Type,\r
2125 (EFI_IFR_TYPE_VALUE *) BufferValue,\r
2126 &ActionRequest\r
2127 );\r
eccfeab1
LG
2128 if (!EFI_ERROR (Status)) {\r
2129 switch (ActionRequest) {\r
2130 case EFI_BROWSER_ACTION_REQUEST_RESET:\r
2131 gResetRequired = TRUE;\r
2132 break;\r
2133\r
2134 case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
2135 //\r
2136 // Till now there is no uncommitted data, so ignore this request\r
2137 //\r
2138 break;\r
2139\r
2140 case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
2141 Selection->Action = UI_ACTION_EXIT;\r
2142 break;\r
2143\r
2144 default:\r
2145 break;\r
2146 }\r
2147 }\r
2148 }\r
2149 }\r
7936fb6a 2150\r
2151 Link = GetNextNode (&Form->StatementListHead, Link);\r
2152 }\r
2153\r
2154 return EFI_SUCCESS;\r
2155}\r
2156\r
d66e6c16 2157/**\r
2158 Initialize Question's Edit copy from Storage for the whole Formset.\r
2159\r
eccfeab1
LG
2160 @param Selection Selection contains the information about \r
2161 the Selection, form and formset to be displayed.\r
2162 Selection action may be updated in retrieve callback.\r
d66e6c16 2163 @param FormSet FormSet data structure.\r
2164\r
2165 @retval EFI_SUCCESS The function completed successfully.\r
2166\r
2167**/\r
2168EFI_STATUS\r
2169LoadFormSetConfig (\r
eccfeab1
LG
2170 IN OUT UI_MENU_SELECTION *Selection,\r
2171 IN FORM_BROWSER_FORMSET *FormSet\r
d66e6c16 2172 )\r
2173{\r
eccfeab1
LG
2174 EFI_STATUS Status;\r
2175 LIST_ENTRY *Link;\r
2176 FORM_BROWSER_FORM *Form;\r
d66e6c16 2177\r
2178 Link = GetFirstNode (&FormSet->FormListHead);\r
2179 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2180 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2181\r
2182 //\r
2183 // Initialize local copy of Value for each Form\r
2184 //\r
eccfeab1 2185 Status = LoadFormConfig (Selection, FormSet, Form);\r
d66e6c16 2186 if (EFI_ERROR (Status)) {\r
2187 return Status;\r
2188 }\r
2189\r
2190 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2191 }\r
2192\r
2193 return EFI_SUCCESS;\r
2194}\r
2195\r
7936fb6a 2196/**\r
2197 Fill storage's edit copy with settings requested from Configuration Driver.\r
2198\r
2199 @param FormSet FormSet data structure.\r
2200 @param Storage Buffer Storage.\r
2201\r
2202 @retval EFI_SUCCESS The function completed successfully.\r
2203\r
2204**/\r
2205EFI_STATUS\r
2206LoadStorage (\r
2207 IN FORM_BROWSER_FORMSET *FormSet,\r
2208 IN FORMSET_STORAGE *Storage\r
2209 )\r
2210{\r
2211 EFI_STATUS Status;\r
2212 EFI_STRING Progress;\r
2213 EFI_STRING Result;\r
2214 CHAR16 *StrPtr;\r
2215\r
2216 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2217 return EFI_SUCCESS;\r
2218 }\r
2219\r
2220 if (FormSet->ConfigAccess == NULL) {\r
2221 return EFI_NOT_FOUND;\r
2222 }\r
2223\r
2224 if (Storage->ElementCount == 0) {\r
2225 //\r
2226 // Skip if there is no RequestElement\r
2227 //\r
2228 return EFI_SUCCESS;\r
2229 }\r
2230\r
2231 //\r
2232 // Request current settings from Configuration Driver\r
2233 //\r
2234 Status = FormSet->ConfigAccess->ExtractConfig (\r
2235 FormSet->ConfigAccess,\r
2236 Storage->ConfigRequest,\r
2237 &Progress,\r
2238 &Result\r
2239 );\r
2240 if (EFI_ERROR (Status)) {\r
2241 return Status;\r
2242 }\r
2243\r
2244 //\r
2245 // Convert Result from <ConfigAltResp> to <ConfigResp>\r
2246 //\r
2247 StrPtr = StrStr (Result, L"ALTCFG");\r
2248 if (StrPtr != NULL) {\r
2249 *StrPtr = L'\0';\r
2250 }\r
2251\r
2252 Status = ConfigRespToStorage (Storage, Result);\r
f4113e1f 2253 FreePool (Result);\r
7936fb6a 2254 return Status;\r
2255}\r
2256\r
2257\r
d66e6c16 2258/**\r
2259 Copy uncommitted data from source Storage to destination Storage.\r
2260\r
2261 @param Dst Target Storage for uncommitted data.\r
2262 @param Src Source Storage for uncommitted data.\r
2263\r
2264 @retval EFI_SUCCESS The function completed successfully.\r
2265 @retval EFI_INVALID_PARAMETER Source and destination Storage is not the same type.\r
2266\r
2267**/\r
2268EFI_STATUS\r
2269CopyStorage (\r
2270 IN OUT FORMSET_STORAGE *Dst,\r
2271 IN FORMSET_STORAGE *Src\r
2272 )\r
2273{\r
2274 LIST_ENTRY *Link;\r
2275 NAME_VALUE_NODE *Node;\r
2276\r
2277 if ((Dst->Type != Src->Type) || (Dst->Size != Src->Size)) {\r
2278 return EFI_INVALID_PARAMETER;\r
2279 }\r
2280\r
2281 switch (Src->Type) {\r
2282 case EFI_HII_VARSTORE_BUFFER:\r
2283 CopyMem (Dst->EditBuffer, Src->EditBuffer, Src->Size);\r
2284 break;\r
2285\r
2286 case EFI_HII_VARSTORE_NAME_VALUE:\r
2287 Link = GetFirstNode (&Src->NameValueListHead);\r
2288 while (!IsNull (&Src->NameValueListHead, Link)) {\r
2289 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
2290\r
2291 SetValueByName (Dst, Node->Name, Node->EditValue);\r
2292\r
2293 Link = GetNextNode (&Src->NameValueListHead, Link);\r
2294 }\r
2295 break;\r
2296\r
2297 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
2298 default:\r
2299 break;\r
2300 }\r
2301\r
2302 return EFI_SUCCESS;\r
2303}\r
2304\r
2305\r
7936fb6a 2306/**\r
2307 Get current setting of Questions.\r
2308\r
2309 @param FormSet FormSet data structure.\r
2310\r
2311 @retval EFI_SUCCESS The function completed successfully.\r
2312\r
2313**/\r
2314EFI_STATUS\r
2315InitializeCurrentSetting (\r
2316 IN OUT FORM_BROWSER_FORMSET *FormSet\r
2317 )\r
2318{\r
2319 LIST_ENTRY *Link;\r
d66e6c16 2320 LIST_ENTRY *Link2;\r
7936fb6a 2321 FORMSET_STORAGE *Storage;\r
d66e6c16 2322 FORMSET_STORAGE *StorageSrc;\r
2323 FORMSET_STORAGE *OldStorage;\r
7936fb6a 2324 FORM_BROWSER_FORM *Form;\r
2325 EFI_STATUS Status;\r
2326\r
2327 //\r
2328 // Extract default from IFR binary\r
2329 //\r
2330 Link = GetFirstNode (&FormSet->FormListHead);\r
2331 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2332 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2333\r
2334 Status = ExtractFormDefault (FormSet, Form, EFI_HII_DEFAULT_CLASS_STANDARD);\r
2335\r
2336 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2337 }\r
2338\r
2339 //\r
2340 // Request current settings from Configuration Driver\r
2341 //\r
2342 Link = GetFirstNode (&FormSet->StorageListHead);\r
2343 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
2344 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
2345\r
d66e6c16 2346 OldStorage = NULL;\r
2347 if (gOldFormSet != NULL) {\r
2348 //\r
2349 // Try to find the Storage in backup formset gOldFormSet\r
2350 //\r
2351 Link2 = GetFirstNode (&gOldFormSet->StorageListHead);\r
2352 while (!IsNull (&gOldFormSet->StorageListHead, Link2)) {\r
2353 StorageSrc = FORMSET_STORAGE_FROM_LINK (Link2);\r
2354\r
2355 if (StorageSrc->VarStoreId == Storage->VarStoreId) {\r
2356 OldStorage = StorageSrc;\r
2357 break;\r
2358 }\r
2359\r
2360 Link2 = GetNextNode (&gOldFormSet->StorageListHead, Link2);\r
2361 }\r
2362 }\r
2363\r
2364 if (OldStorage == NULL) {\r
2365 //\r
2366 // Storage is not found in backup formset, request it from ConfigDriver\r
2367 //\r
2368 Status = LoadStorage (FormSet, Storage);\r
2369 } else {\r
2370 //\r
2371 // Storage found in backup formset, use it\r
2372 //\r
2373 Status = CopyStorage (Storage, OldStorage);\r
2374 }\r
7936fb6a 2375\r
2376 //\r
2377 // Now Edit Buffer is filled with default values(lower priority) and current\r
2378 // settings(higher priority), sychronize it to shadow Buffer\r
2379 //\r
2380 if (!EFI_ERROR (Status)) {\r
2381 SynchronizeStorage (Storage);\r
2382 }\r
2383\r
2384 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
2385 }\r
2386\r
2387 return EFI_SUCCESS;\r
2388}\r
2389\r
2390\r
2391/**\r
2392 Fetch the Ifr binary data of a FormSet.\r
2393\r
2394 @param Handle PackageList Handle\r
f5006bd9 2395 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
2396 specified (NULL or zero GUID), take the first\r
2397 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
2398 found in package list.\r
2399 On output, GUID of the formset found(if not NULL).\r
7936fb6a 2400 @param BinaryLength The length of the FormSet IFR binary.\r
2401 @param BinaryData The buffer designed to receive the FormSet.\r
2402\r
2403 @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
2404 BufferLength was updated.\r
2405 @retval EFI_INVALID_PARAMETER The handle is unknown.\r
2406 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
2407 be found with the requested FormId.\r
2408\r
2409**/\r
2410EFI_STATUS\r
2411GetIfrBinaryData (\r
2412 IN EFI_HII_HANDLE Handle,\r
2413 IN OUT EFI_GUID *FormSetGuid,\r
2414 OUT UINTN *BinaryLength,\r
2415 OUT UINT8 **BinaryData\r
2416 )\r
2417{\r
2418 EFI_STATUS Status;\r
2419 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
2420 UINTN BufferSize;\r
2421 UINT8 *Package;\r
2422 UINT8 *OpCodeData;\r
2423 UINT32 Offset;\r
2424 UINT32 Offset2;\r
7936fb6a 2425 UINT32 PackageListLength;\r
2426 EFI_HII_PACKAGE_HEADER PackageHeader;\r
0a1147ed
LG
2427 UINT8 Index;\r
2428 UINT8 NumberOfClassGuid;\r
f5006bd9 2429 BOOLEAN ClassGuidMatch;\r
0a1147ed 2430 EFI_GUID *ClassGuid;\r
f5006bd9 2431 EFI_GUID *ComparingGuid;\r
7936fb6a 2432\r
2433 OpCodeData = NULL;\r
2434 Package = NULL;\r
0c66bc76 2435 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
7936fb6a 2436\r
2437 //\r
f5006bd9 2438 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list\r
7936fb6a 2439 //\r
2440 if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {\r
f5006bd9 2441 ComparingGuid = &gEfiHiiPlatformSetupFormsetGuid;\r
7936fb6a 2442 } else {\r
f5006bd9 2443 ComparingGuid = FormSetGuid;\r
7936fb6a 2444 }\r
2445\r
2446 //\r
2447 // Get HII PackageList\r
2448 //\r
2449 BufferSize = 0;\r
2450 HiiPackageList = NULL;\r
2451 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
2452 if (Status == EFI_BUFFER_TOO_SMALL) {\r
2453 HiiPackageList = AllocatePool (BufferSize);\r
2454 ASSERT (HiiPackageList != NULL);\r
2455\r
2456 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
2457 }\r
2458 if (EFI_ERROR (Status)) {\r
2459 return Status;\r
2460 }\r
db0bd81c 2461 ASSERT (HiiPackageList != NULL);\r
d66e6c16 2462\r
7936fb6a 2463 //\r
2464 // Get Form package from this HII package List\r
2465 //\r
2466 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
2467 Offset2 = 0;\r
2468 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
2469\r
f5006bd9 2470 ClassGuidMatch = FALSE;\r
7936fb6a 2471 while (Offset < PackageListLength) {\r
2472 Package = ((UINT8 *) HiiPackageList) + Offset;\r
2473 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
2474\r
8d00a0f1 2475 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
7936fb6a 2476 //\r
2477 // Search FormSet in this Form Package\r
2478 //\r
2479 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
2480 while (Offset2 < PackageHeader.Length) {\r
2481 OpCodeData = Package + Offset2;\r
2482\r
2483 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
2484 //\r
f5006bd9 2485 // Try to compare against formset GUID\r
7936fb6a 2486 //\r
f5006bd9 2487 if (CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
2488 break;\r
7936fb6a 2489 }\r
2490\r
d228526f
LG
2491 if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
2492 //\r
2493 // Try to compare against formset class GUID\r
2494 //\r
2495 NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
2496 ClassGuid = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
2497 for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
2498 if (CompareGuid (ComparingGuid, ClassGuid + Index)) {\r
2499 ClassGuidMatch = TRUE;\r
2500 break;\r
2501 }\r
2502 }\r
2503 if (ClassGuidMatch) {\r
f5006bd9 2504 break;\r
2505 }\r
d228526f
LG
2506 } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {\r
2507 ClassGuidMatch = TRUE;\r
7936fb6a 2508 break;\r
2509 }\r
2510 }\r
2511\r
2512 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
2513 }\r
2514\r
2515 if (Offset2 < PackageHeader.Length) {\r
2516 //\r
2517 // Target formset found\r
2518 //\r
2519 break;\r
2520 }\r
2521 }\r
2522\r
2523 Offset += PackageHeader.Length;\r
2524 }\r
2525\r
2526 if (Offset >= PackageListLength) {\r
2527 //\r
2528 // Form package not found in this Package List\r
2529 //\r
f4113e1f 2530 FreePool (HiiPackageList);\r
7936fb6a 2531 return EFI_NOT_FOUND;\r
2532 }\r
2533\r
f5006bd9 2534 if (ClassGuidMatch && (FormSetGuid != NULL)) {\r
7936fb6a 2535 //\r
f5006bd9 2536 // Return the FormSet GUID\r
7936fb6a 2537 //\r
2538 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
2539 }\r
2540\r
2541 //\r
2542 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
2543 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
2544 // of the Form Package.\r
2545 //\r
2546 *BinaryLength = PackageHeader.Length - Offset2;\r
2547 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
2548\r
f4113e1f 2549 FreePool (HiiPackageList);\r
7936fb6a 2550\r
2551 if (*BinaryData == NULL) {\r
2552 return EFI_OUT_OF_RESOURCES;\r
2553 }\r
2554\r
2555 return EFI_SUCCESS;\r
2556}\r
2557\r
2558\r
2559/**\r
2560 Initialize the internal data structure of a FormSet.\r
2561\r
2562 @param Handle PackageList Handle\r
f5006bd9 2563 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
2564 specified (NULL or zero GUID), take the first\r
2565 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
2566 found in package list.\r
2567 On output, GUID of the formset found(if not NULL).\r
7936fb6a 2568 @param FormSet FormSet data structure.\r
2569\r
2570 @retval EFI_SUCCESS The function completed successfully.\r
2571 @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
2572\r
2573**/\r
2574EFI_STATUS\r
2575InitializeFormSet (\r
2576 IN EFI_HII_HANDLE Handle,\r
2577 IN OUT EFI_GUID *FormSetGuid,\r
2578 OUT FORM_BROWSER_FORMSET *FormSet\r
2579 )\r
2580{\r
2581 EFI_STATUS Status;\r
2582 EFI_HANDLE DriverHandle;\r
2583 UINT16 Index;\r
2584\r
2585 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
2586 if (EFI_ERROR (Status)) {\r
2587 return Status;\r
2588 }\r
2589\r
2590 FormSet->HiiHandle = Handle;\r
2591 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
2592\r
2593 //\r
2594 // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
2595 //\r
2596 Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
2597 if (EFI_ERROR (Status)) {\r
2598 return Status;\r
2599 }\r
2600 FormSet->DriverHandle = DriverHandle;\r
2601 Status = gBS->HandleProtocol (\r
2602 DriverHandle,\r
2603 &gEfiHiiConfigAccessProtocolGuid,\r
2604 (VOID **) &FormSet->ConfigAccess\r
2605 );\r
2606 if (EFI_ERROR (Status)) {\r
2607 //\r
2608 // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
2609 // list, then there will be no configuration action required\r
2610 //\r
2611 FormSet->ConfigAccess = NULL;\r
2612 }\r
2613\r
2614 //\r
2615 // Parse the IFR binary OpCodes\r
2616 //\r
2617 Status = ParseOpCodes (FormSet);\r
2618 if (EFI_ERROR (Status)) {\r
2619 return Status;\r
2620 }\r
2621\r
40245175
LG
2622 //\r
2623 // Set VFR type by FormSet SubClass field\r
2624 //\r
0a1147ed
LG
2625 gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP;\r
2626 if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {\r
2627 gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;\r
40245175
LG
2628 }\r
2629 \r
2630 //\r
2631 // Set VFR type by FormSet class guid\r
2632 //\r
2633 for (Index = 0; Index < 3; Index ++) {\r
2634 if (CompareGuid (&FormSet->ClassGuid[Index], &gEfiHiiPlatformSetupFormsetGuid)) {\r
2635 gClassOfVfr |= FORMSET_CLASS_PLATFORM_SETUP;\r
2636 break;\r
2637 }\r
2638 }\r
2639\r
2640 if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {\r
0a1147ed 2641 gFrontPageHandle = FormSet->HiiHandle;\r
7936fb6a 2642 }\r
2643\r
2644 //\r
2645 // Match GUID to find out the function key setting. If match fail, use the default setting.\r
2646 //\r
2647 for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {\r
2648 if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {\r
2649 //\r
2650 // Update the function key setting.\r
2651 //\r
2652 gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;\r
2653 //\r
2654 // Function key prompt can not be displayed if the function key has been disabled.\r
2655 //\r
7936fb6a 2656 if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {\r
2657 gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2658 }\r
2659\r
2660 if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {\r
2661 gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2662 }\r
2663 }\r
2664 }\r
2665\r
2666 return Status;\r
2667}\r
ce6d12cc 2668\r
2669\r
2670/**\r
2671 Save globals used by previous call to SendForm(). SendForm() may be called from \r
2672 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.\r
2673 So, save globals of previous call to SendForm() and restore them upon exit.\r
2674\r
2675**/\r
2676VOID\r
2677SaveBrowserContext (\r
2678 VOID\r
2679 )\r
2680{\r
2681 BROWSER_CONTEXT *Context;\r
2682\r
2683 gBrowserContextCount++;\r
2684 if (gBrowserContextCount == 1) {\r
2685 //\r
2686 // This is not reentry of SendForm(), no context to save\r
2687 //\r
2688 return;\r
2689 }\r
2690\r
2691 Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
2692 ASSERT (Context != NULL);\r
2693\r
2694 Context->Signature = BROWSER_CONTEXT_SIGNATURE;\r
2695\r
2696 //\r
2697 // Save FormBrowser context\r
2698 //\r
2699 Context->BannerData = gBannerData;\r
2700 Context->ClassOfVfr = gClassOfVfr;\r
2701 Context->FunctionKeySetting = gFunctionKeySetting;\r
2702 Context->ResetRequired = gResetRequired;\r
2703 Context->NvUpdateRequired = gNvUpdateRequired;\r
2704 Context->Direction = gDirection;\r
2705 Context->FunctionNineString = gFunctionNineString;\r
2706 Context->FunctionTenString = gFunctionTenString;\r
2707 Context->EnterString = gEnterString;\r
2708 Context->EnterCommitString = gEnterCommitString;\r
2709 Context->EnterEscapeString = gEnterEscapeString;\r
2710 Context->EscapeString = gEscapeString;\r
2711 Context->SaveFailed = gSaveFailed;\r
2712 Context->MoveHighlight = gMoveHighlight;\r
2713 Context->MakeSelection = gMakeSelection;\r
2714 Context->DecNumericInput = gDecNumericInput;\r
2715 Context->HexNumericInput = gHexNumericInput;\r
2716 Context->ToggleCheckBox = gToggleCheckBox;\r
2717 Context->PromptForData = gPromptForData;\r
2718 Context->PromptForPassword = gPromptForPassword;\r
2719 Context->PromptForNewPassword = gPromptForNewPassword;\r
2720 Context->ConfirmPassword = gConfirmPassword;\r
2721 Context->ConfirmError = gConfirmError;\r
2722 Context->PassowordInvalid = gPassowordInvalid;\r
2723 Context->PressEnter = gPressEnter;\r
2724 Context->EmptyString = gEmptyString;\r
2725 Context->AreYouSure = gAreYouSure;\r
2726 Context->YesResponse = gYesResponse;\r
2727 Context->NoResponse = gNoResponse;\r
2728 Context->MiniString = gMiniString;\r
2729 Context->PlusString = gPlusString;\r
2730 Context->MinusString = gMinusString;\r
2731 Context->AdjustNumber = gAdjustNumber;\r
2732 Context->SaveChanges = gSaveChanges;\r
2733 Context->OptionMismatch = gOptionMismatch;\r
2bb526f3 2734 Context->FormSuppress = gFormSuppress;\r
ce6d12cc 2735 Context->PromptBlockWidth = gPromptBlockWidth;\r
2736 Context->OptionBlockWidth = gOptionBlockWidth;\r
2737 Context->HelpBlockWidth = gHelpBlockWidth;\r
2738 Context->OldFormSet = gOldFormSet;\r
2739 Context->MenuRefreshHead = gMenuRefreshHead;\r
2740\r
2741 CopyMem (&Context->ScreenDimensions, &gScreenDimensions, sizeof (gScreenDimensions));\r
2742 CopyMem (&Context->MenuOption, &gMenuOption, sizeof (gMenuOption));\r
2743\r
2744 //\r
2745 // Insert to FormBrowser context list\r
2746 //\r
2747 InsertHeadList (&gBrowserContextList, &Context->Link);\r
2748}\r
2749\r
2750\r
2751/**\r
2752 Restore globals used by previous call to SendForm().\r
2753\r
2754**/\r
2755VOID\r
2756RestoreBrowserContext (\r
2757 VOID\r
2758 )\r
2759{\r
2760 LIST_ENTRY *Link;\r
2761 BROWSER_CONTEXT *Context;\r
2762\r
2763 ASSERT (gBrowserContextCount != 0);\r
2764 gBrowserContextCount--;\r
2765 if (gBrowserContextCount == 0) {\r
2766 //\r
2767 // This is not reentry of SendForm(), no context to restore\r
2768 //\r
2769 return;\r
2770 }\r
2771\r
2772 ASSERT (!IsListEmpty (&gBrowserContextList));\r
2773\r
2774 Link = GetFirstNode (&gBrowserContextList);\r
2775 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
2776\r
2777 //\r
2778 // Restore FormBrowser context\r
2779 //\r
2780 gBannerData = Context->BannerData;\r
2781 gClassOfVfr = Context->ClassOfVfr;\r
2782 gFunctionKeySetting = Context->FunctionKeySetting;\r
2783 gResetRequired = Context->ResetRequired;\r
2784 gNvUpdateRequired = Context->NvUpdateRequired;\r
2785 gDirection = Context->Direction;\r
2786 gFunctionNineString = Context->FunctionNineString;\r
2787 gFunctionTenString = Context->FunctionTenString;\r
2788 gEnterString = Context->EnterString;\r
2789 gEnterCommitString = Context->EnterCommitString;\r
2790 gEnterEscapeString = Context->EnterEscapeString;\r
2791 gEscapeString = Context->EscapeString;\r
2792 gSaveFailed = Context->SaveFailed;\r
2793 gMoveHighlight = Context->MoveHighlight;\r
2794 gMakeSelection = Context->MakeSelection;\r
2795 gDecNumericInput = Context->DecNumericInput;\r
2796 gHexNumericInput = Context->HexNumericInput;\r
2797 gToggleCheckBox = Context->ToggleCheckBox;\r
2798 gPromptForData = Context->PromptForData;\r
2799 gPromptForPassword = Context->PromptForPassword;\r
2800 gPromptForNewPassword = Context->PromptForNewPassword;\r
2801 gConfirmPassword = Context->ConfirmPassword;\r
2802 gConfirmError = Context->ConfirmError;\r
2803 gPassowordInvalid = Context->PassowordInvalid;\r
2804 gPressEnter = Context->PressEnter;\r
2805 gEmptyString = Context->EmptyString;\r
2806 gAreYouSure = Context->AreYouSure;\r
2807 gYesResponse = Context->YesResponse;\r
2808 gNoResponse = Context->NoResponse;\r
2809 gMiniString = Context->MiniString;\r
2810 gPlusString = Context->PlusString;\r
2811 gMinusString = Context->MinusString;\r
2812 gAdjustNumber = Context->AdjustNumber;\r
2813 gSaveChanges = Context->SaveChanges;\r
2814 gOptionMismatch = Context->OptionMismatch;\r
2bb526f3 2815 gFormSuppress = Context->FormSuppress;\r
ce6d12cc 2816 gPromptBlockWidth = Context->PromptBlockWidth;\r
2817 gOptionBlockWidth = Context->OptionBlockWidth;\r
2818 gHelpBlockWidth = Context->HelpBlockWidth;\r
2819 gOldFormSet = Context->OldFormSet;\r
2820 gMenuRefreshHead = Context->MenuRefreshHead;\r
2821\r
2822 CopyMem (&gScreenDimensions, &Context->ScreenDimensions, sizeof (gScreenDimensions));\r
2823 CopyMem (&gMenuOption, &Context->MenuOption, sizeof (gMenuOption));\r
2824\r
2825 //\r
2826 // Remove from FormBrowser context list\r
2827 //\r
2828 RemoveEntryList (&Context->Link);\r
2829 gBS->FreePool (Context);\r
2830}\r