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