]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
Correct Data type conversion.
[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
eccfeab1
LG
2080 \r
2081 //\r
2082 // Check whether EfiVarstore with CallBack can be got.\r
2083 //\r
13ad1def
LG
2084 if ((FormSet->ConfigAccess != NULL) &&\r
2085 (Selection->Action != UI_ACTION_REFRESH_FORMSET) &&\r
2086 (Question->QuestionId != 0) && \r
2087 (Question->Storage != NULL) &&\r
eccfeab1
LG
2088 (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) && \r
2089 ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) {\r
13ad1def 2090\r
eccfeab1
LG
2091 //\r
2092 // Check QuestionValue does exist.\r
2093 //\r
2094 StorageWidth = Question->StorageWidth;\r
2095 if (Question->BufferValue != NULL) {\r
2096 BufferValue = Question->BufferValue;\r
2097 } else {\r
2098 BufferValue = (UINT8 *) &Question->HiiValue.Value;\r
2099 }\r
2100 Status = gRT->GetVariable (\r
2101 Question->VariableName,\r
2102 &Question->Storage->Guid,\r
2103 NULL,\r
2104 &StorageWidth,\r
2105 BufferValue\r
2106 );\r
2107\r
2108 if (!EFI_ERROR (Status)) {\r
2109 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2110 HiiValue = &Question->HiiValue;\r
2111 BufferValue = (UINT8 *) &Question->HiiValue.Value;\r
2112 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
2113 //\r
2114 // Create String in HII database for Configuration Driver to retrieve\r
2115 //\r
2116 HiiValue->Value.string = NewString ((CHAR16 *) Question->BufferValue, FormSet->HiiHandle);\r
2117 } else if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
2118 BufferValue = Question->BufferValue;\r
2119 }\r
2120\r
2121 Status = FormSet->ConfigAccess->Callback (\r
2122 FormSet->ConfigAccess,\r
2123 EFI_BROWSER_ACTION_RETRIEVE,\r
2124 Question->QuestionId,\r
2125 HiiValue->Type,\r
2126 (EFI_IFR_TYPE_VALUE *) BufferValue,\r
2127 &ActionRequest\r
2128 );\r
2129\r
2130 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
2131 //\r
2132 // Clean the String in HII Database\r
2133 //\r
2134 DeleteString (HiiValue->Value.string, FormSet->HiiHandle);\r
2135 }\r
2136\r
2137 if (!EFI_ERROR (Status)) {\r
2138 switch (ActionRequest) {\r
2139 case EFI_BROWSER_ACTION_REQUEST_RESET:\r
2140 gResetRequired = TRUE;\r
2141 break;\r
2142\r
2143 case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
2144 //\r
2145 // Till now there is no uncommitted data, so ignore this request\r
2146 //\r
2147 break;\r
2148\r
2149 case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
2150 Selection->Action = UI_ACTION_EXIT;\r
2151 break;\r
2152\r
2153 default:\r
2154 break;\r
2155 }\r
2156 }\r
2157 }\r
2158 }\r
7936fb6a 2159\r
2160 Link = GetNextNode (&Form->StatementListHead, Link);\r
2161 }\r
2162\r
2163 return EFI_SUCCESS;\r
2164}\r
2165\r
d66e6c16 2166/**\r
2167 Initialize Question's Edit copy from Storage for the whole Formset.\r
2168\r
eccfeab1
LG
2169 @param Selection Selection contains the information about \r
2170 the Selection, form and formset to be displayed.\r
2171 Selection action may be updated in retrieve callback.\r
d66e6c16 2172 @param FormSet FormSet data structure.\r
2173\r
2174 @retval EFI_SUCCESS The function completed successfully.\r
2175\r
2176**/\r
2177EFI_STATUS\r
2178LoadFormSetConfig (\r
eccfeab1
LG
2179 IN OUT UI_MENU_SELECTION *Selection,\r
2180 IN FORM_BROWSER_FORMSET *FormSet\r
d66e6c16 2181 )\r
2182{\r
eccfeab1
LG
2183 EFI_STATUS Status;\r
2184 LIST_ENTRY *Link;\r
2185 FORM_BROWSER_FORM *Form;\r
d66e6c16 2186\r
2187 Link = GetFirstNode (&FormSet->FormListHead);\r
2188 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2189 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2190\r
2191 //\r
2192 // Initialize local copy of Value for each Form\r
2193 //\r
eccfeab1 2194 Status = LoadFormConfig (Selection, FormSet, Form);\r
d66e6c16 2195 if (EFI_ERROR (Status)) {\r
2196 return Status;\r
2197 }\r
2198\r
2199 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2200 }\r
2201\r
2202 return EFI_SUCCESS;\r
2203}\r
2204\r
7936fb6a 2205/**\r
2206 Fill storage's edit copy with settings requested from Configuration Driver.\r
2207\r
2208 @param FormSet FormSet data structure.\r
2209 @param Storage Buffer Storage.\r
2210\r
2211 @retval EFI_SUCCESS The function completed successfully.\r
2212\r
2213**/\r
2214EFI_STATUS\r
2215LoadStorage (\r
2216 IN FORM_BROWSER_FORMSET *FormSet,\r
2217 IN FORMSET_STORAGE *Storage\r
2218 )\r
2219{\r
2220 EFI_STATUS Status;\r
2221 EFI_STRING Progress;\r
2222 EFI_STRING Result;\r
2223 CHAR16 *StrPtr;\r
2224\r
2225 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2226 return EFI_SUCCESS;\r
2227 }\r
2228\r
2229 if (FormSet->ConfigAccess == NULL) {\r
2230 return EFI_NOT_FOUND;\r
2231 }\r
2232\r
2233 if (Storage->ElementCount == 0) {\r
2234 //\r
2235 // Skip if there is no RequestElement\r
2236 //\r
2237 return EFI_SUCCESS;\r
2238 }\r
2239\r
2240 //\r
2241 // Request current settings from Configuration Driver\r
2242 //\r
2243 Status = FormSet->ConfigAccess->ExtractConfig (\r
2244 FormSet->ConfigAccess,\r
2245 Storage->ConfigRequest,\r
2246 &Progress,\r
2247 &Result\r
2248 );\r
2249 if (EFI_ERROR (Status)) {\r
2250 return Status;\r
2251 }\r
2252\r
2253 //\r
2254 // Convert Result from <ConfigAltResp> to <ConfigResp>\r
2255 //\r
2256 StrPtr = StrStr (Result, L"ALTCFG");\r
2257 if (StrPtr != NULL) {\r
2258 *StrPtr = L'\0';\r
2259 }\r
2260\r
2261 Status = ConfigRespToStorage (Storage, Result);\r
f4113e1f 2262 FreePool (Result);\r
7936fb6a 2263 return Status;\r
2264}\r
2265\r
2266\r
d66e6c16 2267/**\r
2268 Copy uncommitted data from source Storage to destination Storage.\r
2269\r
2270 @param Dst Target Storage for uncommitted data.\r
2271 @param Src Source Storage for uncommitted data.\r
2272\r
2273 @retval EFI_SUCCESS The function completed successfully.\r
2274 @retval EFI_INVALID_PARAMETER Source and destination Storage is not the same type.\r
2275\r
2276**/\r
2277EFI_STATUS\r
2278CopyStorage (\r
2279 IN OUT FORMSET_STORAGE *Dst,\r
2280 IN FORMSET_STORAGE *Src\r
2281 )\r
2282{\r
2283 LIST_ENTRY *Link;\r
2284 NAME_VALUE_NODE *Node;\r
2285\r
2286 if ((Dst->Type != Src->Type) || (Dst->Size != Src->Size)) {\r
2287 return EFI_INVALID_PARAMETER;\r
2288 }\r
2289\r
2290 switch (Src->Type) {\r
2291 case EFI_HII_VARSTORE_BUFFER:\r
2292 CopyMem (Dst->EditBuffer, Src->EditBuffer, Src->Size);\r
2293 break;\r
2294\r
2295 case EFI_HII_VARSTORE_NAME_VALUE:\r
2296 Link = GetFirstNode (&Src->NameValueListHead);\r
2297 while (!IsNull (&Src->NameValueListHead, Link)) {\r
2298 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
2299\r
2300 SetValueByName (Dst, Node->Name, Node->EditValue);\r
2301\r
2302 Link = GetNextNode (&Src->NameValueListHead, Link);\r
2303 }\r
2304 break;\r
2305\r
2306 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
2307 default:\r
2308 break;\r
2309 }\r
2310\r
2311 return EFI_SUCCESS;\r
2312}\r
2313\r
2314\r
7936fb6a 2315/**\r
2316 Get current setting of Questions.\r
2317\r
2318 @param FormSet FormSet data structure.\r
2319\r
2320 @retval EFI_SUCCESS The function completed successfully.\r
2321\r
2322**/\r
2323EFI_STATUS\r
2324InitializeCurrentSetting (\r
2325 IN OUT FORM_BROWSER_FORMSET *FormSet\r
2326 )\r
2327{\r
2328 LIST_ENTRY *Link;\r
d66e6c16 2329 LIST_ENTRY *Link2;\r
7936fb6a 2330 FORMSET_STORAGE *Storage;\r
d66e6c16 2331 FORMSET_STORAGE *StorageSrc;\r
2332 FORMSET_STORAGE *OldStorage;\r
7936fb6a 2333 FORM_BROWSER_FORM *Form;\r
2334 EFI_STATUS Status;\r
2335\r
2336 //\r
2337 // Extract default from IFR binary\r
2338 //\r
2339 Link = GetFirstNode (&FormSet->FormListHead);\r
2340 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2341 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2342\r
2343 Status = ExtractFormDefault (FormSet, Form, EFI_HII_DEFAULT_CLASS_STANDARD);\r
2344\r
2345 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2346 }\r
2347\r
2348 //\r
2349 // Request current settings from Configuration Driver\r
2350 //\r
2351 Link = GetFirstNode (&FormSet->StorageListHead);\r
2352 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
2353 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
2354\r
d66e6c16 2355 OldStorage = NULL;\r
2356 if (gOldFormSet != NULL) {\r
2357 //\r
2358 // Try to find the Storage in backup formset gOldFormSet\r
2359 //\r
2360 Link2 = GetFirstNode (&gOldFormSet->StorageListHead);\r
2361 while (!IsNull (&gOldFormSet->StorageListHead, Link2)) {\r
2362 StorageSrc = FORMSET_STORAGE_FROM_LINK (Link2);\r
2363\r
2364 if (StorageSrc->VarStoreId == Storage->VarStoreId) {\r
2365 OldStorage = StorageSrc;\r
2366 break;\r
2367 }\r
2368\r
2369 Link2 = GetNextNode (&gOldFormSet->StorageListHead, Link2);\r
2370 }\r
2371 }\r
2372\r
2373 if (OldStorage == NULL) {\r
2374 //\r
2375 // Storage is not found in backup formset, request it from ConfigDriver\r
2376 //\r
2377 Status = LoadStorage (FormSet, Storage);\r
2378 } else {\r
2379 //\r
2380 // Storage found in backup formset, use it\r
2381 //\r
2382 Status = CopyStorage (Storage, OldStorage);\r
2383 }\r
7936fb6a 2384\r
2385 //\r
2386 // Now Edit Buffer is filled with default values(lower priority) and current\r
2387 // settings(higher priority), sychronize it to shadow Buffer\r
2388 //\r
2389 if (!EFI_ERROR (Status)) {\r
2390 SynchronizeStorage (Storage);\r
2391 }\r
2392\r
2393 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
2394 }\r
2395\r
2396 return EFI_SUCCESS;\r
2397}\r
2398\r
2399\r
2400/**\r
2401 Fetch the Ifr binary data of a FormSet.\r
2402\r
2403 @param Handle PackageList Handle\r
f5006bd9 2404 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
2405 specified (NULL or zero GUID), take the first\r
2406 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
2407 found in package list.\r
2408 On output, GUID of the formset found(if not NULL).\r
7936fb6a 2409 @param BinaryLength The length of the FormSet IFR binary.\r
2410 @param BinaryData The buffer designed to receive the FormSet.\r
2411\r
2412 @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
2413 BufferLength was updated.\r
2414 @retval EFI_INVALID_PARAMETER The handle is unknown.\r
2415 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
2416 be found with the requested FormId.\r
2417\r
2418**/\r
2419EFI_STATUS\r
2420GetIfrBinaryData (\r
2421 IN EFI_HII_HANDLE Handle,\r
2422 IN OUT EFI_GUID *FormSetGuid,\r
2423 OUT UINTN *BinaryLength,\r
2424 OUT UINT8 **BinaryData\r
2425 )\r
2426{\r
2427 EFI_STATUS Status;\r
2428 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
2429 UINTN BufferSize;\r
2430 UINT8 *Package;\r
2431 UINT8 *OpCodeData;\r
2432 UINT32 Offset;\r
2433 UINT32 Offset2;\r
7936fb6a 2434 UINT32 PackageListLength;\r
2435 EFI_HII_PACKAGE_HEADER PackageHeader;\r
0a1147ed
LG
2436 UINT8 Index;\r
2437 UINT8 NumberOfClassGuid;\r
f5006bd9 2438 BOOLEAN ClassGuidMatch;\r
0a1147ed 2439 EFI_GUID *ClassGuid;\r
f5006bd9 2440 EFI_GUID *ComparingGuid;\r
7936fb6a 2441\r
2442 OpCodeData = NULL;\r
2443 Package = NULL;\r
0c66bc76 2444 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
7936fb6a 2445\r
2446 //\r
f5006bd9 2447 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list\r
7936fb6a 2448 //\r
2449 if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {\r
f5006bd9 2450 ComparingGuid = &gEfiHiiPlatformSetupFormsetGuid;\r
7936fb6a 2451 } else {\r
f5006bd9 2452 ComparingGuid = FormSetGuid;\r
7936fb6a 2453 }\r
2454\r
2455 //\r
2456 // Get HII PackageList\r
2457 //\r
2458 BufferSize = 0;\r
2459 HiiPackageList = NULL;\r
2460 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
2461 if (Status == EFI_BUFFER_TOO_SMALL) {\r
2462 HiiPackageList = AllocatePool (BufferSize);\r
2463 ASSERT (HiiPackageList != NULL);\r
2464\r
2465 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
2466 }\r
2467 if (EFI_ERROR (Status)) {\r
2468 return Status;\r
2469 }\r
db0bd81c 2470 ASSERT (HiiPackageList != NULL);\r
d66e6c16 2471\r
7936fb6a 2472 //\r
2473 // Get Form package from this HII package List\r
2474 //\r
2475 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
2476 Offset2 = 0;\r
2477 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
2478\r
f5006bd9 2479 ClassGuidMatch = FALSE;\r
7936fb6a 2480 while (Offset < PackageListLength) {\r
2481 Package = ((UINT8 *) HiiPackageList) + Offset;\r
2482 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
2483\r
8d00a0f1 2484 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
7936fb6a 2485 //\r
2486 // Search FormSet in this Form Package\r
2487 //\r
2488 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
2489 while (Offset2 < PackageHeader.Length) {\r
2490 OpCodeData = Package + Offset2;\r
2491\r
2492 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
2493 //\r
f5006bd9 2494 // Try to compare against formset GUID\r
7936fb6a 2495 //\r
f5006bd9 2496 if (CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
2497 break;\r
7936fb6a 2498 }\r
2499\r
d228526f
LG
2500 if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
2501 //\r
2502 // Try to compare against formset class GUID\r
2503 //\r
2504 NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
2505 ClassGuid = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
2506 for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
2507 if (CompareGuid (ComparingGuid, ClassGuid + Index)) {\r
2508 ClassGuidMatch = TRUE;\r
2509 break;\r
2510 }\r
2511 }\r
2512 if (ClassGuidMatch) {\r
f5006bd9 2513 break;\r
2514 }\r
d228526f
LG
2515 } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {\r
2516 ClassGuidMatch = TRUE;\r
7936fb6a 2517 break;\r
2518 }\r
2519 }\r
2520\r
2521 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
2522 }\r
2523\r
2524 if (Offset2 < PackageHeader.Length) {\r
2525 //\r
2526 // Target formset found\r
2527 //\r
2528 break;\r
2529 }\r
2530 }\r
2531\r
2532 Offset += PackageHeader.Length;\r
2533 }\r
2534\r
2535 if (Offset >= PackageListLength) {\r
2536 //\r
2537 // Form package not found in this Package List\r
2538 //\r
f4113e1f 2539 FreePool (HiiPackageList);\r
7936fb6a 2540 return EFI_NOT_FOUND;\r
2541 }\r
2542\r
f5006bd9 2543 if (ClassGuidMatch && (FormSetGuid != NULL)) {\r
7936fb6a 2544 //\r
f5006bd9 2545 // Return the FormSet GUID\r
7936fb6a 2546 //\r
2547 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
2548 }\r
2549\r
2550 //\r
2551 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
2552 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
2553 // of the Form Package.\r
2554 //\r
2555 *BinaryLength = PackageHeader.Length - Offset2;\r
2556 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
2557\r
f4113e1f 2558 FreePool (HiiPackageList);\r
7936fb6a 2559\r
2560 if (*BinaryData == NULL) {\r
2561 return EFI_OUT_OF_RESOURCES;\r
2562 }\r
2563\r
2564 return EFI_SUCCESS;\r
2565}\r
2566\r
2567\r
2568/**\r
2569 Initialize the internal data structure of a FormSet.\r
2570\r
2571 @param Handle PackageList Handle\r
f5006bd9 2572 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
2573 specified (NULL or zero GUID), take the first\r
2574 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
2575 found in package list.\r
2576 On output, GUID of the formset found(if not NULL).\r
7936fb6a 2577 @param FormSet FormSet data structure.\r
2578\r
2579 @retval EFI_SUCCESS The function completed successfully.\r
2580 @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
2581\r
2582**/\r
2583EFI_STATUS\r
2584InitializeFormSet (\r
2585 IN EFI_HII_HANDLE Handle,\r
2586 IN OUT EFI_GUID *FormSetGuid,\r
2587 OUT FORM_BROWSER_FORMSET *FormSet\r
2588 )\r
2589{\r
2590 EFI_STATUS Status;\r
2591 EFI_HANDLE DriverHandle;\r
2592 UINT16 Index;\r
2593\r
2594 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
2595 if (EFI_ERROR (Status)) {\r
2596 return Status;\r
2597 }\r
2598\r
2599 FormSet->HiiHandle = Handle;\r
2600 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
2601\r
2602 //\r
2603 // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
2604 //\r
2605 Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
2606 if (EFI_ERROR (Status)) {\r
2607 return Status;\r
2608 }\r
2609 FormSet->DriverHandle = DriverHandle;\r
2610 Status = gBS->HandleProtocol (\r
2611 DriverHandle,\r
2612 &gEfiHiiConfigAccessProtocolGuid,\r
2613 (VOID **) &FormSet->ConfigAccess\r
2614 );\r
2615 if (EFI_ERROR (Status)) {\r
2616 //\r
2617 // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
2618 // list, then there will be no configuration action required\r
2619 //\r
2620 FormSet->ConfigAccess = NULL;\r
2621 }\r
2622\r
2623 //\r
2624 // Parse the IFR binary OpCodes\r
2625 //\r
2626 Status = ParseOpCodes (FormSet);\r
2627 if (EFI_ERROR (Status)) {\r
2628 return Status;\r
2629 }\r
2630\r
40245175
LG
2631 //\r
2632 // Set VFR type by FormSet SubClass field\r
2633 //\r
0a1147ed
LG
2634 gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP;\r
2635 if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {\r
2636 gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;\r
40245175
LG
2637 }\r
2638 \r
2639 //\r
2640 // Set VFR type by FormSet class guid\r
2641 //\r
2642 for (Index = 0; Index < 3; Index ++) {\r
2643 if (CompareGuid (&FormSet->ClassGuid[Index], &gEfiHiiPlatformSetupFormsetGuid)) {\r
2644 gClassOfVfr |= FORMSET_CLASS_PLATFORM_SETUP;\r
2645 break;\r
2646 }\r
2647 }\r
2648\r
2649 if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {\r
0a1147ed 2650 gFrontPageHandle = FormSet->HiiHandle;\r
7936fb6a 2651 }\r
2652\r
2653 //\r
2654 // Match GUID to find out the function key setting. If match fail, use the default setting.\r
2655 //\r
2656 for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {\r
2657 if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {\r
2658 //\r
2659 // Update the function key setting.\r
2660 //\r
2661 gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;\r
2662 //\r
2663 // Function key prompt can not be displayed if the function key has been disabled.\r
2664 //\r
7936fb6a 2665 if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {\r
2666 gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2667 }\r
2668\r
2669 if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {\r
2670 gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2671 }\r
2672 }\r
2673 }\r
2674\r
2675 return Status;\r
2676}\r
ce6d12cc 2677\r
2678\r
2679/**\r
2680 Save globals used by previous call to SendForm(). SendForm() may be called from \r
2681 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.\r
2682 So, save globals of previous call to SendForm() and restore them upon exit.\r
2683\r
2684**/\r
2685VOID\r
2686SaveBrowserContext (\r
2687 VOID\r
2688 )\r
2689{\r
2690 BROWSER_CONTEXT *Context;\r
2691\r
2692 gBrowserContextCount++;\r
2693 if (gBrowserContextCount == 1) {\r
2694 //\r
2695 // This is not reentry of SendForm(), no context to save\r
2696 //\r
2697 return;\r
2698 }\r
2699\r
2700 Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
2701 ASSERT (Context != NULL);\r
2702\r
2703 Context->Signature = BROWSER_CONTEXT_SIGNATURE;\r
2704\r
2705 //\r
2706 // Save FormBrowser context\r
2707 //\r
2708 Context->BannerData = gBannerData;\r
2709 Context->ClassOfVfr = gClassOfVfr;\r
2710 Context->FunctionKeySetting = gFunctionKeySetting;\r
2711 Context->ResetRequired = gResetRequired;\r
2712 Context->NvUpdateRequired = gNvUpdateRequired;\r
2713 Context->Direction = gDirection;\r
2714 Context->FunctionNineString = gFunctionNineString;\r
2715 Context->FunctionTenString = gFunctionTenString;\r
2716 Context->EnterString = gEnterString;\r
2717 Context->EnterCommitString = gEnterCommitString;\r
2718 Context->EnterEscapeString = gEnterEscapeString;\r
2719 Context->EscapeString = gEscapeString;\r
2720 Context->SaveFailed = gSaveFailed;\r
2721 Context->MoveHighlight = gMoveHighlight;\r
2722 Context->MakeSelection = gMakeSelection;\r
2723 Context->DecNumericInput = gDecNumericInput;\r
2724 Context->HexNumericInput = gHexNumericInput;\r
2725 Context->ToggleCheckBox = gToggleCheckBox;\r
2726 Context->PromptForData = gPromptForData;\r
2727 Context->PromptForPassword = gPromptForPassword;\r
2728 Context->PromptForNewPassword = gPromptForNewPassword;\r
2729 Context->ConfirmPassword = gConfirmPassword;\r
2730 Context->ConfirmError = gConfirmError;\r
2731 Context->PassowordInvalid = gPassowordInvalid;\r
2732 Context->PressEnter = gPressEnter;\r
2733 Context->EmptyString = gEmptyString;\r
2734 Context->AreYouSure = gAreYouSure;\r
2735 Context->YesResponse = gYesResponse;\r
2736 Context->NoResponse = gNoResponse;\r
2737 Context->MiniString = gMiniString;\r
2738 Context->PlusString = gPlusString;\r
2739 Context->MinusString = gMinusString;\r
2740 Context->AdjustNumber = gAdjustNumber;\r
2741 Context->SaveChanges = gSaveChanges;\r
2742 Context->OptionMismatch = gOptionMismatch;\r
2bb526f3 2743 Context->FormSuppress = gFormSuppress;\r
ce6d12cc 2744 Context->PromptBlockWidth = gPromptBlockWidth;\r
2745 Context->OptionBlockWidth = gOptionBlockWidth;\r
2746 Context->HelpBlockWidth = gHelpBlockWidth;\r
2747 Context->OldFormSet = gOldFormSet;\r
2748 Context->MenuRefreshHead = gMenuRefreshHead;\r
2749\r
2750 CopyMem (&Context->ScreenDimensions, &gScreenDimensions, sizeof (gScreenDimensions));\r
2751 CopyMem (&Context->MenuOption, &gMenuOption, sizeof (gMenuOption));\r
2752\r
2753 //\r
2754 // Insert to FormBrowser context list\r
2755 //\r
2756 InsertHeadList (&gBrowserContextList, &Context->Link);\r
2757}\r
2758\r
2759\r
2760/**\r
2761 Restore globals used by previous call to SendForm().\r
2762\r
2763**/\r
2764VOID\r
2765RestoreBrowserContext (\r
2766 VOID\r
2767 )\r
2768{\r
2769 LIST_ENTRY *Link;\r
2770 BROWSER_CONTEXT *Context;\r
2771\r
2772 ASSERT (gBrowserContextCount != 0);\r
2773 gBrowserContextCount--;\r
2774 if (gBrowserContextCount == 0) {\r
2775 //\r
2776 // This is not reentry of SendForm(), no context to restore\r
2777 //\r
2778 return;\r
2779 }\r
2780\r
2781 ASSERT (!IsListEmpty (&gBrowserContextList));\r
2782\r
2783 Link = GetFirstNode (&gBrowserContextList);\r
2784 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
2785\r
2786 //\r
2787 // Restore FormBrowser context\r
2788 //\r
2789 gBannerData = Context->BannerData;\r
2790 gClassOfVfr = Context->ClassOfVfr;\r
2791 gFunctionKeySetting = Context->FunctionKeySetting;\r
2792 gResetRequired = Context->ResetRequired;\r
2793 gNvUpdateRequired = Context->NvUpdateRequired;\r
2794 gDirection = Context->Direction;\r
2795 gFunctionNineString = Context->FunctionNineString;\r
2796 gFunctionTenString = Context->FunctionTenString;\r
2797 gEnterString = Context->EnterString;\r
2798 gEnterCommitString = Context->EnterCommitString;\r
2799 gEnterEscapeString = Context->EnterEscapeString;\r
2800 gEscapeString = Context->EscapeString;\r
2801 gSaveFailed = Context->SaveFailed;\r
2802 gMoveHighlight = Context->MoveHighlight;\r
2803 gMakeSelection = Context->MakeSelection;\r
2804 gDecNumericInput = Context->DecNumericInput;\r
2805 gHexNumericInput = Context->HexNumericInput;\r
2806 gToggleCheckBox = Context->ToggleCheckBox;\r
2807 gPromptForData = Context->PromptForData;\r
2808 gPromptForPassword = Context->PromptForPassword;\r
2809 gPromptForNewPassword = Context->PromptForNewPassword;\r
2810 gConfirmPassword = Context->ConfirmPassword;\r
2811 gConfirmError = Context->ConfirmError;\r
2812 gPassowordInvalid = Context->PassowordInvalid;\r
2813 gPressEnter = Context->PressEnter;\r
2814 gEmptyString = Context->EmptyString;\r
2815 gAreYouSure = Context->AreYouSure;\r
2816 gYesResponse = Context->YesResponse;\r
2817 gNoResponse = Context->NoResponse;\r
2818 gMiniString = Context->MiniString;\r
2819 gPlusString = Context->PlusString;\r
2820 gMinusString = Context->MinusString;\r
2821 gAdjustNumber = Context->AdjustNumber;\r
2822 gSaveChanges = Context->SaveChanges;\r
2823 gOptionMismatch = Context->OptionMismatch;\r
2bb526f3 2824 gFormSuppress = Context->FormSuppress;\r
ce6d12cc 2825 gPromptBlockWidth = Context->PromptBlockWidth;\r
2826 gOptionBlockWidth = Context->OptionBlockWidth;\r
2827 gHelpBlockWidth = Context->HelpBlockWidth;\r
2828 gOldFormSet = Context->OldFormSet;\r
2829 gMenuRefreshHead = Context->MenuRefreshHead;\r
2830\r
2831 CopyMem (&gScreenDimensions, &Context->ScreenDimensions, sizeof (gScreenDimensions));\r
2832 CopyMem (&gMenuOption, &Context->MenuOption, sizeof (gMenuOption));\r
2833\r
2834 //\r
2835 // Remove from FormBrowser context list\r
2836 //\r
2837 RemoveEntryList (&Context->Link);\r
2838 gBS->FreePool (Context);\r
2839}\r