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