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