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