]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
Update PeiDxeDebugDebugLibReportStatusCode to use CopyMem() in place of AsciiStrnCpy...
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Setup.c
CommitLineData
7936fb6a 1/** @file\r
2Entry and initialization module for the browser.\r
3\r
31585af4 4Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
7936fb6a 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "Setup.h"\r
7936fb6a 16\r
17SETUP_DRIVER_PRIVATE_DATA mPrivateData = {\r
18 SETUP_DRIVER_SIGNATURE,\r
19 NULL,\r
20 {\r
21 SendForm,\r
22 BrowserCallback\r
48a9d5f7
LG
23 },\r
24 {\r
25 SetScope,\r
26 RegisterHotKey,\r
27 RegiserExitHandler,\r
28 SaveReminder\r
7936fb6a 29 }\r
30};\r
31\r
32EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;\r
33EFI_HII_STRING_PROTOCOL *mHiiString;\r
34EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;\r
35\r
ce6d12cc 36UINTN gBrowserContextCount = 0;\r
37LIST_ENTRY gBrowserContextList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList);\r
48a9d5f7
LG
38LIST_ENTRY gBrowserFormSetList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList);\r
39LIST_ENTRY gBrowserHotKeyList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList);\r
ce6d12cc 40\r
0a1147ed
LG
41BANNER_DATA *gBannerData;\r
42EFI_HII_HANDLE gFrontPageHandle;\r
7936fb6a 43UINTN gClassOfVfr;\r
44UINTN gFunctionKeySetting;\r
45BOOLEAN gResetRequired;\r
7936fb6a 46EFI_HII_HANDLE gHiiHandle;\r
7936fb6a 47UINT16 gDirection;\r
48EFI_SCREEN_DESCRIPTOR gScreenDimensions;\r
48a9d5f7
LG
49BROWSER_SETTING_SCOPE gBrowserSettingScope = FormSetLevel;\r
50BOOLEAN mBrowserScopeFirstSet = TRUE;\r
51EXIT_HANDLER ExitHandlerFunction = NULL;\r
52UINTN gFooterHeight;\r
7936fb6a 53\r
54//\r
55// Browser Global Strings\r
56//\r
48a9d5f7
LG
57CHAR16 *gSaveFailed;\r
58CHAR16 *gDiscardFailed;\r
59CHAR16 *gDefaultFailed;\r
7936fb6a 60CHAR16 *gEnterString;\r
61CHAR16 *gEnterCommitString;\r
8d00a0f1 62CHAR16 *gEnterEscapeString;\r
7936fb6a 63CHAR16 *gEscapeString;\r
7936fb6a 64CHAR16 *gMoveHighlight;\r
65CHAR16 *gMakeSelection;\r
66CHAR16 *gDecNumericInput;\r
67CHAR16 *gHexNumericInput;\r
68CHAR16 *gToggleCheckBox;\r
69CHAR16 *gPromptForData;\r
70CHAR16 *gPromptForPassword;\r
71CHAR16 *gPromptForNewPassword;\r
72CHAR16 *gConfirmPassword;\r
73CHAR16 *gConfirmError;\r
74CHAR16 *gPassowordInvalid;\r
75CHAR16 *gPressEnter;\r
76CHAR16 *gEmptyString;\r
77CHAR16 *gAreYouSure;\r
78CHAR16 *gYesResponse;\r
79CHAR16 *gNoResponse;\r
80CHAR16 *gMiniString;\r
81CHAR16 *gPlusString;\r
82CHAR16 *gMinusString;\r
83CHAR16 *gAdjustNumber;\r
ebe43565 84CHAR16 *gSaveChanges;\r
8d00a0f1 85CHAR16 *gOptionMismatch;\r
0c66bc76 86CHAR16 *gFormSuppress;\r
7936fb6a 87\r
0e8e994d 88CHAR16 *mUnknownString = L"!";\r
89\r
7936fb6a 90CHAR16 gPromptBlockWidth;\r
91CHAR16 gOptionBlockWidth;\r
92CHAR16 gHelpBlockWidth;\r
93\r
94EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
95EFI_GUID gSetupBrowserGuid = {\r
96 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}\r
97};\r
98\r
48a9d5f7 99FORM_BROWSER_FORMSET *gOldFormSet = NULL;\r
d66e6c16 100\r
7936fb6a 101FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {\r
102 //\r
103 // Boot Manager\r
104 //\r
105 {\r
106 {\r
107 0x847bc3fe,\r
108 0xb974,\r
109 0x446d,\r
110 {\r
111 0x94,\r
112 0x49,\r
113 0x5a,\r
114 0xd5,\r
115 0x41,\r
116 0x2e,\r
117 0x99,\r
118 0x3b\r
119 }\r
120 },\r
121 NONE_FUNCTION_KEY_SETTING\r
122 },\r
123 //\r
124 // Device Manager\r
125 //\r
126 {\r
127 {\r
128 0x3ebfa8e6,\r
129 0x511d,\r
130 0x4b5b,\r
131 {\r
132 0xa9,\r
133 0x5f,\r
134 0xfb,\r
135 0x38,\r
136 0x26,\r
137 0xf,\r
138 0x1c,\r
139 0x27\r
140 }\r
141 },\r
142 NONE_FUNCTION_KEY_SETTING\r
143 },\r
144 //\r
145 // BMM FormSet.\r
146 //\r
147 {\r
148 {\r
149 0x642237c7,\r
150 0x35d4,\r
151 0x472d,\r
152 {\r
153 0x83,\r
154 0x65,\r
155 0x12,\r
156 0xe0,\r
157 0xcc,\r
158 0xf2,\r
159 0x7a,\r
160 0x22\r
161 }\r
162 },\r
163 NONE_FUNCTION_KEY_SETTING\r
164 },\r
165 //\r
166 // BMM File Explorer FormSet.\r
167 //\r
168 {\r
169 {\r
170 0x1f2d63e1,\r
171 0xfebd,\r
172 0x4dc7,\r
173 {\r
174 0x9c,\r
175 0xc5,\r
176 0xba,\r
177 0x2b,\r
178 0x1c,\r
179 0xef,\r
180 0x9c,\r
181 0x5b\r
182 }\r
183 },\r
184 NONE_FUNCTION_KEY_SETTING\r
185 },\r
186};\r
187\r
188/**\r
189 This is the routine which an external caller uses to direct the browser\r
190 where to obtain it's information.\r
191\r
192\r
193 @param This The Form Browser protocol instanse.\r
194 @param Handles A pointer to an array of Handles. If HandleCount > 1 we\r
195 display a list of the formsets for the handles specified.\r
196 @param HandleCount The number of Handles specified in Handle.\r
197 @param FormSetGuid This field points to the EFI_GUID which must match the Guid\r
198 field in the EFI_IFR_FORM_SET op-code for the specified\r
199 forms-based package. If FormSetGuid is NULL, then this\r
200 function will display the first found forms package.\r
201 @param FormId This field specifies which EFI_IFR_FORM to render as the first\r
202 displayable page. If this field has a value of 0x0000, then\r
203 the forms browser will render the specified forms in their encoded order.\r
d66e6c16 204 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in\r
7936fb6a 205 characters.\r
f02d0c0f 206 @param ActionRequest Points to the action recommended by the form.\r
7936fb6a 207\r
208 @retval EFI_SUCCESS The function completed successfully.\r
209 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
210 @retval EFI_NOT_FOUND No valid forms could be found to display.\r
211\r
212**/\r
213EFI_STATUS\r
214EFIAPI\r
215SendForm (\r
216 IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
217 IN EFI_HII_HANDLE *Handles,\r
218 IN UINTN HandleCount,\r
219 IN EFI_GUID *FormSetGuid, OPTIONAL\r
220 IN UINT16 FormId, OPTIONAL\r
221 IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL\r
222 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL\r
223 )\r
224{\r
519f076a 225 EFI_STATUS Status;\r
226 UI_MENU_SELECTION *Selection;\r
227 UINTN Index;\r
228 FORM_BROWSER_FORMSET *FormSet;\r
48a9d5f7
LG
229 LIST_ENTRY *Link;\r
230\r
231 //\r
232 // Calculate total number of Register HotKeys. \r
233 //\r
234 Index = 0;\r
235 Link = GetFirstNode (&gBrowserHotKeyList);\r
236 while (!IsNull (&gBrowserHotKeyList, Link)) {\r
237 Link = GetNextNode (&gBrowserHotKeyList, Link);\r
238 Index ++;\r
239 }\r
240 //\r
241 // Show three HotKeys help information on one ROW.\r
242 //\r
243 gFooterHeight = FOOTER_HEIGHT + (Index / 3);\r
7936fb6a 244\r
ce6d12cc 245 //\r
246 // Save globals used by SendForm()\r
247 //\r
248 SaveBrowserContext ();\r
249\r
48a9d5f7 250 gResetRequired = FALSE;\r
7936fb6a 251 Status = EFI_SUCCESS;\r
252 ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
253\r
254 //\r
255 // Seed the dimensions in the global\r
256 //\r
257 gST->ConOut->QueryMode (\r
258 gST->ConOut,\r
259 gST->ConOut->Mode->Mode,\r
260 &gScreenDimensions.RightColumn,\r
261 &gScreenDimensions.BottomRow\r
262 );\r
263\r
264 if (ScreenDimensions != NULL) {\r
265 //\r
266 // Check local dimension vs. global dimension.\r
267 //\r
268 if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||\r
269 (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)\r
270 ) {\r
ce6d12cc 271 Status = EFI_INVALID_PARAMETER;\r
272 goto Done;\r
7936fb6a 273 } else {\r
274 //\r
275 // Local dimension validation.\r
276 //\r
277 if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) &&\r
278 (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) &&\r
279 ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) &&\r
280 (\r
281 (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +\r
282 SCROLL_ARROW_HEIGHT *\r
283 2 +\r
284 FRONT_PAGE_HEADER_HEIGHT +\r
48a9d5f7 285 gFooterHeight +\r
7936fb6a 286 1\r
287 )\r
288 ) {\r
289 CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
290 } else {\r
ce6d12cc 291 Status = EFI_INVALID_PARAMETER;\r
292 goto Done;\r
7936fb6a 293 }\r
294 }\r
295 }\r
296\r
297 gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);\r
f7a14a9b 298 gPromptBlockWidth = (CHAR16) (gOptionBlockWidth + LEFT_SKIPPED_COLUMNS);\r
5697f873 299 gHelpBlockWidth = (CHAR16) (gOptionBlockWidth - LEFT_SKIPPED_COLUMNS);\r
7936fb6a 300\r
301 //\r
302 // Initialize the strings for the browser, upon exit of the browser, the strings will be freed\r
303 //\r
304 InitializeBrowserStrings ();\r
305\r
48a9d5f7 306 gFunctionKeySetting = ENABLE_FUNCTION_KEY_SETTING;\r
7936fb6a 307\r
308 //\r
309 // Ensure we are in Text mode\r
310 //\r
ebe43565 311 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
519f076a 312\r
7936fb6a 313 for (Index = 0; Index < HandleCount; Index++) {\r
314 Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));\r
315 ASSERT (Selection != NULL);\r
316\r
317 Selection->Handle = Handles[Index];\r
318 if (FormSetGuid != NULL) {\r
319 CopyMem (&Selection->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));\r
320 Selection->FormId = FormId;\r
48a9d5f7
LG
321 } else {\r
322 CopyMem (&Selection->FormSetGuid, &gEfiHiiPlatformSetupFormsetGuid, sizeof (EFI_GUID));\r
7936fb6a 323 }\r
324\r
325 do {\r
326 FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
327 ASSERT (FormSet != NULL);\r
328\r
329 //\r
330 // Initialize internal data structures of FormSet\r
331 //\r
db40504e 332 Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet, TRUE);\r
e8e36190 333 if (EFI_ERROR (Status) || IsListEmpty (&FormSet->FormListHead)) {\r
7936fb6a 334 DestroyFormSet (FormSet);\r
335 break;\r
336 }\r
337 Selection->FormSet = FormSet;\r
338\r
b2e444aa
ED
339 //\r
340 // Try to find pre FormSet in the maintain backup list.\r
341 //\r
342 gOldFormSet = GetFormSetFromHiiHandle (Selection->Handle);\r
343\r
7936fb6a 344 //\r
345 // Display this formset\r
346 //\r
347 gCurrentSelection = Selection;\r
348\r
349 Status = SetupBrowser (Selection);\r
350\r
351 gCurrentSelection = NULL;\r
7936fb6a 352\r
353 if (EFI_ERROR (Status)) {\r
354 break;\r
355 }\r
356\r
357 } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);\r
358\r
d66e6c16 359 if (gOldFormSet != NULL) {\r
48a9d5f7
LG
360 //\r
361 // If no data is changed, don't need to save current FormSet into the maintain list.\r
362 //\r
363 if (!IsNvUpdateRequired (gOldFormSet)) {\r
364 RemoveEntryList (&gOldFormSet->Link);\r
365 DestroyFormSet (gOldFormSet);\r
366 }\r
d66e6c16 367 gOldFormSet = NULL;\r
368 }\r
369\r
f4113e1f 370 FreePool (Selection);\r
7936fb6a 371 }\r
372\r
373 if (ActionRequest != NULL) {\r
374 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
375 if (gResetRequired) {\r
376 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;\r
377 }\r
378 }\r
379\r
380 FreeBrowserStrings ();\r
381\r
382 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
383 gST->ConOut->ClearScreen (gST->ConOut);\r
384\r
ce6d12cc 385Done:\r
386 //\r
387 // Restore globals used by SendForm()\r
388 //\r
389 RestoreBrowserContext ();\r
390\r
7936fb6a 391 return Status;\r
392}\r
393\r
394\r
395/**\r
396 This function is called by a callback handler to retrieve uncommitted state\r
397 data from the browser.\r
398\r
399 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL\r
400 instance.\r
401 @param ResultsDataSize A pointer to the size of the buffer associated\r
402 with ResultsData.\r
403 @param ResultsData A string returned from an IFR browser or\r
404 equivalent. The results string will have no\r
405 routing information in them.\r
406 @param RetrieveData A BOOLEAN field which allows an agent to retrieve\r
407 (if RetrieveData = TRUE) data from the uncommitted\r
408 browser state information or set (if RetrieveData\r
409 = FALSE) data in the uncommitted browser state\r
410 information.\r
411 @param VariableGuid An optional field to indicate the target variable\r
412 GUID name to use.\r
413 @param VariableName An optional field to indicate the target\r
414 human-readable variable name.\r
415\r
416 @retval EFI_SUCCESS The results have been distributed or are awaiting\r
417 distribution.\r
418 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to\r
419 contain the results data.\r
420\r
421**/\r
422EFI_STATUS\r
423EFIAPI\r
424BrowserCallback (\r
425 IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
426 IN OUT UINTN *ResultsDataSize,\r
427 IN OUT EFI_STRING ResultsData,\r
428 IN BOOLEAN RetrieveData,\r
429 IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
430 IN CONST CHAR16 *VariableName OPTIONAL\r
431 )\r
432{\r
433 EFI_STATUS Status;\r
434 LIST_ENTRY *Link;\r
435 FORMSET_STORAGE *Storage;\r
436 FORM_BROWSER_FORMSET *FormSet;\r
437 BOOLEAN Found;\r
438 CHAR16 *ConfigResp;\r
439 CHAR16 *StrPtr;\r
440 UINTN BufferSize;\r
441 UINTN TmpSize;\r
442\r
443 if (ResultsDataSize == NULL || ResultsData == NULL) {\r
444 return EFI_INVALID_PARAMETER;\r
445 }\r
446\r
447 if (gCurrentSelection == NULL) {\r
448 return EFI_NOT_READY;\r
449 }\r
450\r
451 Storage = NULL;\r
452 ConfigResp = NULL;\r
453 FormSet = gCurrentSelection->FormSet;\r
454\r
455 //\r
456 // Find target storage\r
457 //\r
458 Link = GetFirstNode (&FormSet->StorageListHead);\r
459 if (IsNull (&FormSet->StorageListHead, Link)) {\r
460 return EFI_UNSUPPORTED;\r
461 }\r
462\r
463 if (VariableGuid != NULL) {\r
464 //\r
465 // Try to find target storage\r
466 //\r
467 Found = FALSE;\r
468 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
469 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
470 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
471\r
472 if (CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {\r
cce6230f
ED
473 if (Storage->Type == EFI_HII_VARSTORE_BUFFER ||\r
474 Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
7936fb6a 475 //\r
476 // Buffer storage require both GUID and Name\r
477 //\r
478 if (VariableName == NULL) {\r
479 return EFI_NOT_FOUND;\r
480 }\r
481\r
482 if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {\r
483 continue;\r
484 }\r
485 }\r
486 Found = TRUE;\r
487 break;\r
488 }\r
489 }\r
490\r
491 if (!Found) {\r
492 return EFI_NOT_FOUND;\r
493 }\r
494 } else {\r
495 //\r
496 // GUID/Name is not specified, take the first storage in FormSet\r
497 //\r
498 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
499 }\r
500\r
501 if (RetrieveData) {\r
502 //\r
503 // Skip if there is no RequestElement\r
504 //\r
505 if (Storage->ElementCount == 0) {\r
506 return EFI_SUCCESS;\r
507 }\r
508\r
509 //\r
510 // Generate <ConfigResp>\r
511 //\r
b18e7050 512 Status = StorageToConfigResp (Storage, &ConfigResp, FALSE);\r
7936fb6a 513 if (EFI_ERROR (Status)) {\r
514 return Status;\r
515 }\r
516\r
517 //\r
518 // Skip <ConfigHdr> and '&' to point to <ConfigBody>\r
519 //\r
520 StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1;\r
521\r
522 BufferSize = StrSize (StrPtr);\r
523 if (*ResultsDataSize < BufferSize) {\r
524 *ResultsDataSize = BufferSize;\r
525\r
f4113e1f 526 FreePool (ConfigResp);\r
7936fb6a 527 return EFI_BUFFER_TOO_SMALL;\r
528 }\r
529\r
530 *ResultsDataSize = BufferSize;\r
531 CopyMem (ResultsData, StrPtr, BufferSize);\r
532\r
f4113e1f 533 FreePool (ConfigResp);\r
7936fb6a 534 } else {\r
535 //\r
536 // Prepare <ConfigResp>\r
537 //\r
538 TmpSize = StrLen (ResultsData);\r
539 BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16);\r
540 ConfigResp = AllocateZeroPool (BufferSize);\r
541 ASSERT (ConfigResp != NULL);\r
542\r
543 StrCpy (ConfigResp, Storage->ConfigHdr);\r
544 StrCat (ConfigResp, L"&");\r
545 StrCat (ConfigResp, ResultsData);\r
546\r
547 //\r
548 // Update Browser uncommited data\r
549 //\r
550 Status = ConfigRespToStorage (Storage, ConfigResp);\r
551 if (EFI_ERROR (Status)) {\r
552 return Status;\r
553 }\r
554 }\r
555\r
556 return EFI_SUCCESS;\r
557}\r
558\r
48a9d5f7
LG
559/**\r
560 Notify function will remove the formset in the maintain list \r
561 once this formset is removed.\r
562 \r
563 Functions which are registered to receive notification of\r
564 database events have this prototype. The actual event is encoded\r
565 in NotifyType. The following table describes how PackageType,\r
566 PackageGuid, Handle, and Package are used for each of the\r
567 notification types.\r
568\r
569 @param PackageType Package type of the notification.\r
570\r
571 @param PackageGuid If PackageType is\r
572 EFI_HII_PACKAGE_TYPE_GUID, then this is\r
573 the pointer to the GUID from the Guid\r
574 field of EFI_HII_PACKAGE_GUID_HEADER.\r
575 Otherwise, it must be NULL.\r
576\r
577 @param Package Points to the package referred to by the\r
578 notification Handle The handle of the package\r
579 list which contains the specified package.\r
580\r
581 @param Handle The HII handle.\r
582\r
583 @param NotifyType The type of change concerning the\r
584 database. See\r
585 EFI_HII_DATABASE_NOTIFY_TYPE.\r
586\r
587**/\r
588EFI_STATUS\r
589EFIAPI\r
590FormsetRemoveNotify (\r
591 IN UINT8 PackageType,\r
592 IN CONST EFI_GUID *PackageGuid,\r
593 IN CONST EFI_HII_PACKAGE_HEADER *Package,\r
594 IN EFI_HII_HANDLE Handle,\r
595 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType\r
596 )\r
597{\r
598 FORM_BROWSER_FORMSET *FormSet;\r
599\r
600 //\r
601 // Ignore the update for current using formset, which is handled by another notify function.\r
602 //\r
603 if (IsHiiHandleInBrowserContext (Handle)) {\r
604 return EFI_SUCCESS;\r
605 }\r
606 \r
607 //\r
608 // Remove the backup FormSet data when the Form Package is removed.\r
609 //\r
610 FormSet = GetFormSetFromHiiHandle (Handle);\r
611 if (FormSet != NULL) {\r
612 RemoveEntryList (&FormSet->Link);\r
613 DestroyFormSet (FormSet);\r
614 }\r
615 \r
616 return EFI_SUCCESS;\r
617}\r
7936fb6a 618\r
619/**\r
620 Initialize Setup Browser driver.\r
621\r
622 @param ImageHandle The image handle.\r
623 @param SystemTable The system table.\r
624\r
625 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..\r
626 @return Other value if failed to initialize the Setup Browser module.\r
627\r
628**/\r
629EFI_STATUS\r
630EFIAPI\r
631InitializeSetup (\r
632 IN EFI_HANDLE ImageHandle,\r
633 IN EFI_SYSTEM_TABLE *SystemTable\r
634 )\r
635{\r
636 EFI_STATUS Status;\r
48a9d5f7
LG
637 EFI_HANDLE NotifyHandle;\r
638 EFI_INPUT_KEY DefaultHotKey;\r
639 EFI_STRING HelpString;\r
7936fb6a 640\r
641 //\r
642 // Locate required Hii relative protocols\r
643 //\r
644 Status = gBS->LocateProtocol (\r
645 &gEfiHiiDatabaseProtocolGuid,\r
646 NULL,\r
647 (VOID **) &mHiiDatabase\r
648 );\r
649 ASSERT_EFI_ERROR (Status);\r
650\r
651 Status = gBS->LocateProtocol (\r
652 &gEfiHiiStringProtocolGuid,\r
653 NULL,\r
654 (VOID **) &mHiiString\r
655 );\r
656 ASSERT_EFI_ERROR (Status);\r
657\r
658 Status = gBS->LocateProtocol (\r
659 &gEfiHiiConfigRoutingProtocolGuid,\r
660 NULL,\r
661 (VOID **) &mHiiConfigRouting\r
662 );\r
663 ASSERT_EFI_ERROR (Status);\r
664\r
665 //\r
666 // Publish our HII data\r
667 //\r
cb7d01c0 668 gHiiHandle = HiiAddPackages (\r
669 &gSetupBrowserGuid,\r
670 ImageHandle,\r
671 SetupBrowserStrings,\r
672 NULL\r
673 );\r
674 ASSERT (gHiiHandle != NULL);\r
7936fb6a 675\r
676 //\r
677 // Initialize Driver private data\r
678 //\r
0a1147ed
LG
679 gBannerData = AllocateZeroPool (sizeof (BANNER_DATA));\r
680 ASSERT (gBannerData != NULL);\r
48a9d5f7
LG
681 \r
682 //\r
683 // Initialize generic help strings.\r
684 //\r
685 gSaveFailed = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);\r
686 gDiscardFailed = GetToken (STRING_TOKEN (DISCARD_FAILED), gHiiHandle);\r
687 gDefaultFailed = GetToken (STRING_TOKEN (DEFAULT_FAILED), gHiiHandle);\r
7936fb6a 688\r
689 //\r
690 // Install FormBrowser2 protocol\r
691 //\r
692 mPrivateData.Handle = NULL;\r
693 Status = gBS->InstallProtocolInterface (\r
694 &mPrivateData.Handle,\r
695 &gEfiFormBrowser2ProtocolGuid,\r
696 EFI_NATIVE_INTERFACE,\r
697 &mPrivateData.FormBrowser2\r
698 );\r
699 ASSERT_EFI_ERROR (Status);\r
700\r
48a9d5f7
LG
701 //\r
702 // Install default HotKey F10 for Save\r
703 //\r
704 DefaultHotKey.UnicodeChar = CHAR_NULL;\r
705 HelpString = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle);\r
706 DefaultHotKey.ScanCode = SCAN_F10;\r
707 RegisterHotKey (&DefaultHotKey, BROWSER_ACTION_SUBMIT, 0, HelpString);\r
708 FreePool (HelpString);\r
709 //\r
710 // Install default HotKey F9 for Reset To Defaults\r
711 //\r
712 DefaultHotKey.ScanCode = SCAN_F9;\r
713 HelpString = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle);\r
714 RegisterHotKey (&DefaultHotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, HelpString);\r
715 FreePool (HelpString);\r
716\r
717 //\r
718 // Install FormBrowserEx protocol\r
719 //\r
720 mPrivateData.Handle = NULL;\r
721 Status = gBS->InstallProtocolInterface (\r
722 &mPrivateData.Handle,\r
723 &gEfiFormBrowserExProtocolGuid,\r
724 EFI_NATIVE_INTERFACE,\r
725 &mPrivateData.FormBrowserEx\r
726 );\r
727 ASSERT_EFI_ERROR (Status);\r
728\r
729 //\r
730 // Register notify for Form package remove\r
731 //\r
732 Status = mHiiDatabase->RegisterPackageNotify (\r
733 mHiiDatabase,\r
734 EFI_HII_PACKAGE_FORMS,\r
735 NULL,\r
736 FormsetRemoveNotify,\r
737 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
738 &NotifyHandle\r
739 );\r
740 ASSERT_EFI_ERROR (Status);\r
741\r
7936fb6a 742 return Status;\r
743}\r
744\r
745\r
746/**\r
747 Create a new string in HII Package List.\r
748\r
749 @param String The String to be added\r
750 @param HiiHandle The package list in the HII database to insert the\r
751 specified string.\r
752\r
753 @return The output string.\r
754\r
755**/\r
756EFI_STRING_ID\r
757NewString (\r
758 IN CHAR16 *String,\r
759 IN EFI_HII_HANDLE HiiHandle\r
760 )\r
761{\r
762 EFI_STRING_ID StringId;\r
7936fb6a 763\r
cb7d01c0 764 StringId = HiiSetString (HiiHandle, 0, String, NULL);\r
765 ASSERT (StringId != 0);\r
7936fb6a 766\r
767 return StringId;\r
768}\r
769\r
770\r
771/**\r
772 Delete a string from HII Package List.\r
773\r
774 @param StringId Id of the string in HII database.\r
775 @param HiiHandle The HII package list handle.\r
776\r
777 @retval EFI_SUCCESS The string was deleted successfully.\r
778\r
779**/\r
780EFI_STATUS\r
781DeleteString (\r
782 IN EFI_STRING_ID StringId,\r
783 IN EFI_HII_HANDLE HiiHandle\r
784 )\r
785{\r
786 CHAR16 NullChar;\r
787\r
788 NullChar = CHAR_NULL;\r
cb7d01c0 789 HiiSetString (HiiHandle, StringId, &NullChar, NULL);\r
790 return EFI_SUCCESS;\r
7936fb6a 791}\r
792\r
793\r
794/**\r
795 Get the string based on the StringId and HII Package List Handle.\r
796\r
797 @param Token The String's ID.\r
798 @param HiiHandle The package list in the HII database to search for\r
799 the specified string.\r
800\r
801 @return The output string.\r
802\r
803**/\r
804CHAR16 *\r
805GetToken (\r
806 IN EFI_STRING_ID Token,\r
807 IN EFI_HII_HANDLE HiiHandle\r
808 )\r
809{\r
cb7d01c0 810 EFI_STRING String;\r
7936fb6a 811\r
2573712e
LG
812 if (HiiHandle == NULL) {\r
813 return NULL;\r
814 }\r
815\r
cb7d01c0 816 String = HiiGetString (HiiHandle, Token, NULL);\r
0e8e994d 817 if (String == NULL) {\r
818 String = AllocateCopyPool (sizeof (mUnknownString), mUnknownString);\r
819 ASSERT (String != NULL);\r
820 }\r
cb7d01c0 821 return (CHAR16 *) String;\r
7936fb6a 822}\r
823\r
824\r
825/**\r
826 Allocate new memory and then copy the Unicode string Source to Destination.\r
827\r
828 @param Dest Location to copy string\r
829 @param Src String to copy\r
830\r
831**/\r
832VOID\r
833NewStringCpy (\r
834 IN OUT CHAR16 **Dest,\r
835 IN CHAR16 *Src\r
836 )\r
837{\r
676df92c 838 if (*Dest != NULL) {\r
839 FreePool (*Dest);\r
840 }\r
7936fb6a 841 *Dest = AllocateCopyPool (StrSize (Src), Src);\r
842 ASSERT (*Dest != NULL);\r
843}\r
844\r
845\r
846/**\r
847 Allocate new memory and concatinate Source on the end of Destination.\r
848\r
849 @param Dest String to added to the end of.\r
850 @param Src String to concatinate.\r
851\r
852**/\r
853VOID\r
854NewStringCat (\r
855 IN OUT CHAR16 **Dest,\r
856 IN CHAR16 *Src\r
857 )\r
858{\r
859 CHAR16 *NewString;\r
860 UINTN TmpSize;\r
861\r
862 if (*Dest == NULL) {\r
863 NewStringCpy (Dest, Src);\r
864 return;\r
865 }\r
866\r
867 TmpSize = StrSize (*Dest);\r
868 NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1);\r
869 ASSERT (NewString != NULL);\r
870\r
871 StrCpy (NewString, *Dest);\r
872 StrCat (NewString, Src);\r
873\r
f4113e1f 874 FreePool (*Dest);\r
7936fb6a 875 *Dest = NewString;\r
876}\r
877\r
878\r
879/**\r
cce6230f 880 Synchronize or restore Storage's Edit copy and Shadow copy.\r
7936fb6a 881\r
cce6230f
ED
882 @param Storage The Storage to be synchronized.\r
883 @param SyncOrRestore Sync the buffer to editbuffer or Restore the \r
884 editbuffer to buffer\r
885 if TRUE, copy the editbuffer to the buffer.\r
886 if FALSE, copy the buffer to the editbuffer.\r
7936fb6a 887\r
888**/\r
889VOID\r
890SynchronizeStorage (\r
cce6230f
ED
891 IN FORMSET_STORAGE *Storage,\r
892 IN BOOLEAN SyncOrRestore\r
7936fb6a 893 )\r
894{\r
895 LIST_ENTRY *Link;\r
896 NAME_VALUE_NODE *Node;\r
897\r
898 switch (Storage->Type) {\r
899 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f
ED
900 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
901 if (SyncOrRestore) {\r
902 CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);\r
903 } else {\r
904 CopyMem (Storage->EditBuffer, Storage->Buffer, Storage->Size);\r
905 }\r
7936fb6a 906 break;\r
907\r
908 case EFI_HII_VARSTORE_NAME_VALUE:\r
909 Link = GetFirstNode (&Storage->NameValueListHead);\r
910 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
911 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
912\r
cce6230f
ED
913 if (SyncOrRestore) {\r
914 NewStringCpy (&Node->Value, Node->EditValue);\r
915 } else {\r
916 NewStringCpy (&Node->EditValue, Node->Value);\r
917 }\r
7936fb6a 918\r
919 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
920 }\r
921 break;\r
922\r
923 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
924 default:\r
925 break;\r
926 }\r
927}\r
928\r
929\r
930/**\r
931 Get Value for given Name from a NameValue Storage.\r
932\r
933 @param Storage The NameValue Storage.\r
934 @param Name The Name.\r
935 @param Value The retured Value.\r
936\r
937 @retval EFI_SUCCESS Value found for given Name.\r
938 @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
939\r
940**/\r
941EFI_STATUS\r
942GetValueByName (\r
943 IN FORMSET_STORAGE *Storage,\r
944 IN CHAR16 *Name,\r
945 IN OUT CHAR16 **Value\r
946 )\r
947{\r
948 LIST_ENTRY *Link;\r
949 NAME_VALUE_NODE *Node;\r
950\r
951 *Value = NULL;\r
952\r
953 Link = GetFirstNode (&Storage->NameValueListHead);\r
954 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
955 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
956\r
957 if (StrCmp (Name, Node->Name) == 0) {\r
958 NewStringCpy (Value, Node->EditValue);\r
959 return EFI_SUCCESS;\r
960 }\r
961\r
962 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
963 }\r
964\r
965 return EFI_NOT_FOUND;\r
966}\r
967\r
968\r
969/**\r
970 Set Value of given Name in a NameValue Storage.\r
971\r
972 @param Storage The NameValue Storage.\r
973 @param Name The Name.\r
974 @param Value The Value to set.\r
b18e7050 975 @param Edit Whether update editValue or Value.\r
7936fb6a 976\r
977 @retval EFI_SUCCESS Value found for given Name.\r
978 @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
979\r
980**/\r
981EFI_STATUS\r
982SetValueByName (\r
983 IN FORMSET_STORAGE *Storage,\r
984 IN CHAR16 *Name,\r
b18e7050
ED
985 IN CHAR16 *Value,\r
986 IN BOOLEAN Edit\r
7936fb6a 987 )\r
988{\r
989 LIST_ENTRY *Link;\r
990 NAME_VALUE_NODE *Node;\r
b18e7050 991 CHAR16 *Buffer;\r
7936fb6a 992\r
993 Link = GetFirstNode (&Storage->NameValueListHead);\r
994 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
995 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
996\r
997 if (StrCmp (Name, Node->Name) == 0) {\r
b18e7050
ED
998 if (Edit) {\r
999 Buffer = Node->EditValue;\r
1000 } else {\r
1001 Buffer = Node->Value;\r
1002 }\r
1003 if (Buffer != NULL) {\r
1004 FreePool (Buffer);\r
1005 }\r
1006 Buffer = AllocateCopyPool (StrSize (Value), Value);\r
1007 ASSERT (Buffer != NULL);\r
1008 if (Edit) {\r
1009 Node->EditValue = Buffer;\r
1010 } else {\r
1011 Node->Value = Buffer;\r
676df92c 1012 }\r
7936fb6a 1013 return EFI_SUCCESS;\r
1014 }\r
1015\r
1016 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
1017 }\r
1018\r
1019 return EFI_NOT_FOUND;\r
1020}\r
1021\r
1022\r
1023/**\r
1024 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
1025\r
b18e7050 1026 @param Buffer The Storage to be conveted.\r
7936fb6a 1027 @param ConfigResp The returned <ConfigResp>.\r
b18e7050 1028 @param SingleForm Whether update data for single form or formset level.\r
7936fb6a 1029\r
1030 @retval EFI_SUCCESS Convert success.\r
1031 @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
1032\r
1033**/\r
1034EFI_STATUS\r
1035StorageToConfigResp (\r
b18e7050
ED
1036 IN VOID *Buffer,\r
1037 IN CHAR16 **ConfigResp,\r
1038 IN BOOLEAN SingleForm\r
7936fb6a 1039 )\r
1040{\r
1041 EFI_STATUS Status;\r
1042 EFI_STRING Progress;\r
1043 LIST_ENTRY *Link;\r
1044 NAME_VALUE_NODE *Node;\r
b18e7050
ED
1045 CHAR16 *ConfigRequest;\r
1046 FORMSET_STORAGE *Storage;\r
1047 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
7936fb6a 1048\r
1049 Status = EFI_SUCCESS;\r
b18e7050
ED
1050 if (SingleForm) {\r
1051 ConfigInfo = (FORM_BROWSER_CONFIG_REQUEST *) Buffer;\r
1052 Storage = ConfigInfo->Storage;\r
1053 ConfigRequest = ConfigInfo->ConfigRequest;\r
1054 } else {\r
1055 Storage = (FORMSET_STORAGE *) Buffer;\r
1056 ConfigRequest = Storage->ConfigRequest;\r
1057 }\r
7936fb6a 1058\r
1059 switch (Storage->Type) {\r
1060 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 1061 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
7936fb6a 1062 Status = mHiiConfigRouting->BlockToConfig (\r
1063 mHiiConfigRouting,\r
b18e7050 1064 ConfigRequest,\r
7936fb6a 1065 Storage->EditBuffer,\r
1066 Storage->Size,\r
1067 ConfigResp,\r
1068 &Progress\r
1069 );\r
1070 break;\r
1071\r
1072 case EFI_HII_VARSTORE_NAME_VALUE:\r
1073 *ConfigResp = NULL;\r
1074 NewStringCat (ConfigResp, Storage->ConfigHdr);\r
1075\r
1076 Link = GetFirstNode (&Storage->NameValueListHead);\r
1077 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
1078 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
1079\r
b18e7050
ED
1080 if (StrStr (ConfigRequest, Node->Name) != NULL) {\r
1081 NewStringCat (ConfigResp, L"&");\r
1082 NewStringCat (ConfigResp, Node->Name);\r
1083 NewStringCat (ConfigResp, L"=");\r
1084 NewStringCat (ConfigResp, Node->EditValue);\r
1085 }\r
7936fb6a 1086 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
1087 }\r
1088 break;\r
1089\r
1090 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
1091 default:\r
1092 Status = EFI_INVALID_PARAMETER;\r
1093 break;\r
1094 }\r
1095\r
1096 return Status;\r
1097}\r
1098\r
1099\r
1100/**\r
1101 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.\r
1102\r
1103 @param Storage The Storage to receive the settings.\r
1104 @param ConfigResp The <ConfigResp> to be converted.\r
1105\r
1106 @retval EFI_SUCCESS Convert success.\r
1107 @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
1108\r
1109**/\r
1110EFI_STATUS\r
1111ConfigRespToStorage (\r
1112 IN FORMSET_STORAGE *Storage,\r
1113 IN CHAR16 *ConfigResp\r
1114 )\r
1115{\r
1116 EFI_STATUS Status;\r
1117 EFI_STRING Progress;\r
1118 UINTN BufferSize;\r
1119 CHAR16 *StrPtr;\r
1120 CHAR16 *Name;\r
1121 CHAR16 *Value;\r
1122\r
1123 Status = EFI_SUCCESS;\r
1124\r
1125 switch (Storage->Type) {\r
1126 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 1127 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
7936fb6a 1128 BufferSize = Storage->Size;\r
1129 Status = mHiiConfigRouting->ConfigToBlock (\r
1130 mHiiConfigRouting,\r
1131 ConfigResp,\r
1132 Storage->EditBuffer,\r
1133 &BufferSize,\r
1134 &Progress\r
1135 );\r
1136 break;\r
1137\r
1138 case EFI_HII_VARSTORE_NAME_VALUE:\r
40245175
LG
1139 StrPtr = StrStr (ConfigResp, L"PATH");\r
1140 if (StrPtr == NULL) {\r
1141 break;\r
1142 }\r
7936fb6a 1143 StrPtr = StrStr (ConfigResp, L"&");\r
1144 while (StrPtr != NULL) {\r
1145 //\r
1146 // Skip '&'\r
1147 //\r
1148 StrPtr = StrPtr + 1;\r
1149 Name = StrPtr;\r
1150 StrPtr = StrStr (StrPtr, L"=");\r
1151 if (StrPtr == NULL) {\r
1152 break;\r
1153 }\r
1154 *StrPtr = 0;\r
1155\r
1156 //\r
1157 // Skip '='\r
1158 //\r
1159 StrPtr = StrPtr + 1;\r
1160 Value = StrPtr;\r
1161 StrPtr = StrStr (StrPtr, L"&");\r
1162 if (StrPtr != NULL) {\r
1163 *StrPtr = 0;\r
1164 }\r
b18e7050 1165 SetValueByName (Storage, Name, Value, TRUE);\r
7936fb6a 1166 }\r
1167 break;\r
1168\r
1169 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
1170 default:\r
1171 Status = EFI_INVALID_PARAMETER;\r
1172 break;\r
1173 }\r
1174\r
1175 return Status;\r
1176}\r
1177\r
1178\r
1179/**\r
1180 Get Question's current Value.\r
1181\r
1182 @param FormSet FormSet data structure.\r
1183 @param Form Form data structure.\r
1184 @param Question Question to be initialized.\r
1185 @param Cached TRUE: get from Edit copy FALSE: get from original\r
1186 Storage\r
1187\r
1188 @retval EFI_SUCCESS The function completed successfully.\r
1189\r
1190**/\r
1191EFI_STATUS\r
1192GetQuestionValue (\r
1193 IN FORM_BROWSER_FORMSET *FormSet,\r
1194 IN FORM_BROWSER_FORM *Form,\r
1195 IN OUT FORM_BROWSER_STATEMENT *Question,\r
1196 IN BOOLEAN Cached\r
1197 )\r
1198{\r
1199 EFI_STATUS Status;\r
1200 BOOLEAN Enabled;\r
1201 BOOLEAN Pending;\r
1202 UINT8 *Dst;\r
1203 UINTN StorageWidth;\r
1204 EFI_TIME EfiTime;\r
1205 FORMSET_STORAGE *Storage;\r
1206 EFI_IFR_TYPE_VALUE *QuestionValue;\r
1207 CHAR16 *ConfigRequest;\r
1208 CHAR16 *Progress;\r
1209 CHAR16 *Result;\r
1210 CHAR16 *Value;\r
8d00a0f1 1211 CHAR16 *StringPtr;\r
7936fb6a 1212 UINTN Length;\r
63d55bb9
LG
1213 UINTN Index;\r
1214 UINTN LengthStr;\r
7936fb6a 1215 BOOLEAN IsBufferStorage;\r
1216 BOOLEAN IsString;\r
63d55bb9
LG
1217 CHAR16 TemStr[5];\r
1218 UINT8 DigitUint8;\r
cce6230f 1219 UINT8 *TemBuffer;\r
7936fb6a 1220\r
1221 Status = EFI_SUCCESS;\r
cce6230f 1222 Value = NULL;\r
db40504e 1223 Result = NULL;\r
7936fb6a 1224\r
1225 //\r
1226 // Statement don't have storage, skip them\r
1227 //\r
1228 if (Question->QuestionId == 0) {\r
1229 return Status;\r
1230 }\r
1231\r
1232 //\r
1233 // Question value is provided by an Expression, evaluate it\r
1234 //\r
1235 if (Question->ValueExpression != NULL) {\r
1236 Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);\r
1237 if (!EFI_ERROR (Status)) {\r
901ba0e7
ED
1238 if (Question->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
1239 ASSERT (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER && Question->HiiValue.Buffer != NULL);\r
1240 if (Question->StorageWidth > Question->ValueExpression->Result.BufferLen) {\r
1241 CopyMem (Question->HiiValue.Buffer, Question->ValueExpression->Result.Buffer, Question->ValueExpression->Result.BufferLen);\r
1242 Question->HiiValue.BufferLen = Question->ValueExpression->Result.BufferLen;\r
1243 } else {\r
1244 CopyMem (Question->HiiValue.Buffer, Question->ValueExpression->Result.Buffer, Question->StorageWidth);\r
1245 Question->HiiValue.BufferLen = Question->StorageWidth;\r
1246 }\r
1247 FreePool (Question->ValueExpression->Result.Buffer);\r
1248 }\r
1249 Question->HiiValue.Type = Question->ValueExpression->Result.Type;\r
1250 CopyMem (&Question->HiiValue.Value, &Question->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE)); \r
7936fb6a 1251 }\r
1252 return Status;\r
1253 }\r
2573712e
LG
1254 \r
1255 //\r
1256 // Get question value by read expression.\r
1257 //\r
1258 if (Question->ReadExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {\r
1259 Status = EvaluateExpression (FormSet, Form, Question->ReadExpression);\r
901ba0e7
ED
1260 if (!EFI_ERROR (Status) && \r
1261 ((Question->ReadExpression->Result.Type < EFI_IFR_TYPE_OTHER) || (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER))) {\r
2573712e
LG
1262 //\r
1263 // Only update question value to the valid result.\r
1264 //\r
901ba0e7
ED
1265 if (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
1266 ASSERT (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER && Question->HiiValue.Buffer != NULL);\r
1267 if (Question->StorageWidth > Question->ReadExpression->Result.BufferLen) {\r
1268 CopyMem (Question->HiiValue.Buffer, Question->ReadExpression->Result.Buffer, Question->ReadExpression->Result.BufferLen);\r
1269 Question->HiiValue.BufferLen = Question->ReadExpression->Result.BufferLen;\r
1270 } else {\r
1271 CopyMem (Question->HiiValue.Buffer, Question->ReadExpression->Result.Buffer, Question->StorageWidth);\r
1272 Question->HiiValue.BufferLen = Question->StorageWidth;\r
1273 }\r
1274 FreePool (Question->ReadExpression->Result.Buffer);\r
1275 }\r
1276 Question->HiiValue.Type = Question->ReadExpression->Result.Type;\r
1277 CopyMem (&Question->HiiValue.Value, &Question->ReadExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE)); \r
2573712e
LG
1278 return EFI_SUCCESS;\r
1279 }\r
1280 }\r
7936fb6a 1281\r
1282 //\r
1283 // Question value is provided by RTC\r
1284 //\r
1285 Storage = Question->Storage;\r
1286 QuestionValue = &Question->HiiValue.Value;\r
1287 if (Storage == NULL) {\r
1288 //\r
1289 // It's a Question without storage, or RTC date/time\r
1290 //\r
1291 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1292 //\r
1293 // Date and time define the same Flags bit\r
1294 //\r
1295 switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
1296 case QF_DATE_STORAGE_TIME:\r
1297 Status = gRT->GetTime (&EfiTime, NULL);\r
1298 break;\r
1299\r
1300 case QF_DATE_STORAGE_WAKEUP:\r
1301 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
1302 break;\r
1303\r
1304 case QF_DATE_STORAGE_NORMAL:\r
1305 default:\r
1306 //\r
1307 // For date/time without storage\r
1308 //\r
1309 return EFI_SUCCESS;\r
1310 }\r
1311\r
1312 if (EFI_ERROR (Status)) {\r
1313 return Status;\r
1314 }\r
1315\r
1316 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1317 QuestionValue->date.Year = EfiTime.Year;\r
1318 QuestionValue->date.Month = EfiTime.Month;\r
1319 QuestionValue->date.Day = EfiTime.Day;\r
1320 } else {\r
1321 QuestionValue->time.Hour = EfiTime.Hour;\r
1322 QuestionValue->time.Minute = EfiTime.Minute;\r
1323 QuestionValue->time.Second = EfiTime.Second;\r
1324 }\r
1325 }\r
1326\r
1327 return EFI_SUCCESS;\r
1328 }\r
1329\r
1330 //\r
1331 // Question value is provided by EFI variable\r
1332 //\r
1333 StorageWidth = Question->StorageWidth;\r
1334 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1335 if (Question->BufferValue != NULL) {\r
1336 Dst = Question->BufferValue;\r
1337 } else {\r
1338 Dst = (UINT8 *) QuestionValue;\r
1339 }\r
1340\r
1341 Status = gRT->GetVariable (\r
1342 Question->VariableName,\r
1343 &Storage->Guid,\r
1344 NULL,\r
1345 &StorageWidth,\r
1346 Dst\r
1347 );\r
1348 //\r
1349 // Always return success, even this EFI variable doesn't exist\r
1350 //\r
1351 return EFI_SUCCESS;\r
1352 }\r
1353\r
1354 //\r
1355 // Question Value is provided by Buffer Storage or NameValue Storage\r
1356 //\r
1357 if (Question->BufferValue != NULL) {\r
1358 //\r
1359 // This Question is password or orderedlist\r
1360 //\r
1361 Dst = Question->BufferValue;\r
1362 } else {\r
1363 //\r
1364 // Other type of Questions\r
1365 //\r
1366 Dst = (UINT8 *) &Question->HiiValue.Value;\r
1367 }\r
1368\r
cce6230f
ED
1369 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
1370 Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
1371 IsBufferStorage = TRUE;\r
1372 } else {\r
1373 IsBufferStorage = FALSE;\r
1374 }\r
7936fb6a 1375 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
1376 if (Cached) {\r
1377 if (IsBufferStorage) {\r
1378 //\r
1379 // Copy from storage Edit buffer\r
1380 //\r
1381 CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
1382 } else {\r
1b2bf3ca 1383 Value = NULL;\r
7936fb6a 1384 Status = GetValueByName (Storage, Question->VariableName, &Value);\r
1385 if (EFI_ERROR (Status)) {\r
1386 return Status;\r
1387 }\r
d66e6c16 1388\r
1b2bf3ca 1389 ASSERT (Value != NULL);\r
63d55bb9
LG
1390 LengthStr = StrLen (Value);\r
1391 Status = EFI_SUCCESS;\r
7936fb6a 1392 if (IsString) {\r
1393 //\r
1394 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
63d55bb9 1395 // Add string tail char L'\0' into Length\r
7936fb6a 1396 //\r
63d55bb9
LG
1397 Length = StorageWidth + sizeof (CHAR16);\r
1398 if (Length < ((LengthStr / 4 + 1) * 2)) {\r
1399 Status = EFI_BUFFER_TOO_SMALL;\r
1400 } else {\r
1401 StringPtr = (CHAR16 *) Dst;\r
1402 ZeroMem (TemStr, sizeof (TemStr));\r
1403 for (Index = 0; Index < LengthStr; Index += 4) {\r
1404 StrnCpy (TemStr, Value + Index, 4);\r
1405 StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
1406 }\r
1407 //\r
1408 // Add tailing L'\0' character\r
1409 //\r
1410 StringPtr[Index/4] = L'\0';\r
1411 }\r
7936fb6a 1412 } else {\r
63d55bb9
LG
1413 if (StorageWidth < ((LengthStr + 1) / 2)) {\r
1414 Status = EFI_BUFFER_TOO_SMALL;\r
1415 } else {\r
1416 ZeroMem (TemStr, sizeof (TemStr));\r
1417 for (Index = 0; Index < LengthStr; Index ++) {\r
1418 TemStr[0] = Value[LengthStr - Index - 1];\r
1419 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
1420 if ((Index & 1) == 0) {\r
1421 Dst [Index/2] = DigitUint8;\r
1422 } else {\r
634303c9 1423 Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
63d55bb9
LG
1424 }\r
1425 }\r
1426 }\r
7936fb6a 1427 }\r
1428\r
f4113e1f 1429 FreePool (Value);\r
7936fb6a 1430 }\r
1431 } else {\r
db40504e 1432 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
cce6230f
ED
1433 //\r
1434 // Request current settings from Configuration Driver\r
1435 //\r
1436 if (FormSet->ConfigAccess == NULL) {\r
1437 return EFI_NOT_FOUND;\r
1438 }\r
7936fb6a 1439\r
cce6230f
ED
1440 //\r
1441 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
1442 // <ConfigHdr> + "&" + <VariableName>\r
1443 //\r
1444 if (IsBufferStorage) {\r
1445 Length = StrLen (Storage->ConfigHdr);\r
1446 Length += StrLen (Question->BlockName);\r
1447 } else {\r
1448 Length = StrLen (Storage->ConfigHdr);\r
1449 Length += StrLen (Question->VariableName) + 1;\r
1450 }\r
1451 ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
1452 ASSERT (ConfigRequest != NULL);\r
7936fb6a 1453\r
cce6230f
ED
1454 StrCpy (ConfigRequest, Storage->ConfigHdr);\r
1455 if (IsBufferStorage) {\r
1456 StrCat (ConfigRequest, Question->BlockName);\r
1457 } else {\r
1458 StrCat (ConfigRequest, L"&");\r
1459 StrCat (ConfigRequest, Question->VariableName);\r
1460 }\r
7936fb6a 1461\r
cce6230f
ED
1462 Status = FormSet->ConfigAccess->ExtractConfig (\r
1463 FormSet->ConfigAccess,\r
1464 ConfigRequest,\r
1465 &Progress,\r
1466 &Result\r
1467 );\r
1468 FreePool (ConfigRequest);\r
1469 if (EFI_ERROR (Status)) {\r
1470 return Status;\r
1471 }\r
7936fb6a 1472\r
7936fb6a 1473 //\r
cce6230f 1474 // Skip <ConfigRequest>\r
7936fb6a 1475 //\r
cce6230f 1476 if (IsBufferStorage) {\r
e4f95ca5
ED
1477 Value = StrStr (Result, L"&VALUE");\r
1478 if (Value == NULL) {\r
1479 FreePool (Result);\r
1480 return EFI_NOT_FOUND;\r
1481 }\r
cce6230f
ED
1482 //\r
1483 // Skip "&VALUE"\r
1484 //\r
1485 Value = Value + 6;\r
e4f95ca5
ED
1486 } else {\r
1487 Value = Result + Length;\r
cce6230f
ED
1488 }\r
1489 if (*Value != '=') {\r
1490 FreePool (Result);\r
1491 return EFI_NOT_FOUND;\r
1492 }\r
1493 //\r
1494 // Skip '=', point to value\r
1495 //\r
1496 Value = Value + 1;\r
8d00a0f1 1497\r
7936fb6a 1498 //\r
cce6230f 1499 // Suppress <AltResp> if any\r
7936fb6a 1500 //\r
cce6230f
ED
1501 StringPtr = Value;\r
1502 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
1503 StringPtr++;\r
1504 }\r
1505 *StringPtr = L'\0';\r
1506\r
1507 LengthStr = StrLen (Value);\r
1508 Status = EFI_SUCCESS;\r
1509 if (!IsBufferStorage && IsString) {\r
63d55bb9 1510 //\r
cce6230f
ED
1511 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
1512 // Add string tail char L'\0' into Length\r
63d55bb9 1513 //\r
cce6230f
ED
1514 Length = StorageWidth + sizeof (CHAR16);\r
1515 if (Length < ((LengthStr / 4 + 1) * 2)) {\r
1516 Status = EFI_BUFFER_TOO_SMALL;\r
1517 } else {\r
1518 StringPtr = (CHAR16 *) Dst;\r
1519 ZeroMem (TemStr, sizeof (TemStr));\r
1520 for (Index = 0; Index < LengthStr; Index += 4) {\r
1521 StrnCpy (TemStr, Value + Index, 4);\r
1522 StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
1523 }\r
1524 //\r
1525 // Add tailing L'\0' character\r
1526 //\r
1527 StringPtr[Index/4] = L'\0';\r
1528 }\r
63d55bb9 1529 } else {\r
cce6230f
ED
1530 if (StorageWidth < ((LengthStr + 1) / 2)) {\r
1531 Status = EFI_BUFFER_TOO_SMALL;\r
1532 } else {\r
1533 ZeroMem (TemStr, sizeof (TemStr));\r
1534 for (Index = 0; Index < LengthStr; Index ++) {\r
1535 TemStr[0] = Value[LengthStr - Index - 1];\r
1536 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
1537 if ((Index & 1) == 0) {\r
1538 Dst [Index/2] = DigitUint8;\r
1539 } else {\r
1540 Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
1541 }\r
63d55bb9
LG
1542 }\r
1543 }\r
7936fb6a 1544 }\r
cce6230f
ED
1545\r
1546 if (EFI_ERROR (Status)) {\r
db40504e 1547 FreePool (Result);\r
cce6230f
ED
1548 return Status;\r
1549 }\r
1550 } else if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
1551 TemBuffer = NULL;\r
1552 TemBuffer = AllocateZeroPool (Storage->Size);\r
1553 if (TemBuffer == NULL) {\r
1554 Status = EFI_OUT_OF_RESOURCES;\r
1555 return Status;\r
1556 }\r
1557 Length = Storage->Size;\r
1558 Status = gRT->GetVariable (\r
1559 Storage->Name,\r
1560 &Storage->Guid,\r
1561 NULL,\r
1562 &Length,\r
1563 TemBuffer\r
1564 );\r
1565 if (EFI_ERROR (Status)) {\r
1566 FreePool (TemBuffer);\r
1567 return Status;\r
1568 }\r
1569\r
1570 CopyMem (Dst, TemBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
1571\r
1572 FreePool (TemBuffer);\r
63d55bb9
LG
1573 }\r
1574\r
7936fb6a 1575 //\r
1576 // Synchronize Edit Buffer\r
1577 //\r
1578 if (IsBufferStorage) {\r
1579 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
1580 } else {\r
b18e7050 1581 SetValueByName (Storage, Question->VariableName, Value, TRUE);\r
7936fb6a 1582 }\r
db40504e
ED
1583\r
1584 if (Result != NULL) {\r
1585 FreePool (Result);\r
1586 }\r
7936fb6a 1587 }\r
1588\r
1589 return Status;\r
1590}\r
1591\r
1592\r
1593/**\r
1594 Save Question Value to edit copy(cached) or Storage(uncached).\r
1595\r
1596 @param FormSet FormSet data structure.\r
1597 @param Form Form data structure.\r
1598 @param Question Pointer to the Question.\r
1599 @param Cached TRUE: set to Edit copy FALSE: set to original\r
1600 Storage\r
1601\r
1602 @retval EFI_SUCCESS The function completed successfully.\r
1603\r
1604**/\r
1605EFI_STATUS\r
1606SetQuestionValue (\r
1607 IN FORM_BROWSER_FORMSET *FormSet,\r
1608 IN FORM_BROWSER_FORM *Form,\r
1609 IN OUT FORM_BROWSER_STATEMENT *Question,\r
1610 IN BOOLEAN Cached\r
1611 )\r
1612{\r
1613 EFI_STATUS Status;\r
1614 BOOLEAN Enabled;\r
1615 BOOLEAN Pending;\r
1616 UINT8 *Src;\r
1617 EFI_TIME EfiTime;\r
1618 UINTN BufferLen;\r
1619 UINTN StorageWidth;\r
1620 FORMSET_STORAGE *Storage;\r
1621 EFI_IFR_TYPE_VALUE *QuestionValue;\r
1622 CHAR16 *ConfigResp;\r
1623 CHAR16 *Progress;\r
1624 CHAR16 *Value;\r
1625 UINTN Length;\r
1626 BOOLEAN IsBufferStorage;\r
1627 BOOLEAN IsString;\r
63d55bb9
LG
1628 UINT8 *TemBuffer;\r
1629 CHAR16 *TemName;\r
1630 CHAR16 *TemString;\r
1631 UINTN Index;\r
7936fb6a 1632\r
1633 Status = EFI_SUCCESS;\r
1634\r
1635 //\r
1636 // Statement don't have storage, skip them\r
1637 //\r
1638 if (Question->QuestionId == 0) {\r
1639 return Status;\r
1640 }\r
1641\r
1642 //\r
1643 // If Question value is provided by an Expression, then it is read only\r
1644 //\r
1645 if (Question->ValueExpression != NULL) {\r
1646 return Status;\r
1647 }\r
2573712e
LG
1648 \r
1649 //\r
1650 // Before set question value, evaluate its write expression.\r
1651 //\r
1652 if (Question->WriteExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {\r
1653 Status = EvaluateExpression (FormSet, Form, Question->WriteExpression);\r
1654 if (EFI_ERROR (Status)) {\r
1655 return Status;\r
1656 }\r
1657 }\r
7936fb6a 1658\r
1659 //\r
1660 // Question value is provided by RTC\r
1661 //\r
1662 Storage = Question->Storage;\r
1663 QuestionValue = &Question->HiiValue.Value;\r
1664 if (Storage == NULL) {\r
1665 //\r
1666 // It's a Question without storage, or RTC date/time\r
1667 //\r
1668 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1669 //\r
1670 // Date and time define the same Flags bit\r
1671 //\r
1672 switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
1673 case QF_DATE_STORAGE_TIME:\r
1674 Status = gRT->GetTime (&EfiTime, NULL);\r
1675 break;\r
1676\r
1677 case QF_DATE_STORAGE_WAKEUP:\r
1678 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
1679 break;\r
1680\r
1681 case QF_DATE_STORAGE_NORMAL:\r
1682 default:\r
1683 //\r
1684 // For date/time without storage\r
1685 //\r
1686 return EFI_SUCCESS;\r
1687 }\r
1688\r
1689 if (EFI_ERROR (Status)) {\r
1690 return Status;\r
1691 }\r
1692\r
1693 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1694 EfiTime.Year = QuestionValue->date.Year;\r
1695 EfiTime.Month = QuestionValue->date.Month;\r
1696 EfiTime.Day = QuestionValue->date.Day;\r
1697 } else {\r
1698 EfiTime.Hour = QuestionValue->time.Hour;\r
1699 EfiTime.Minute = QuestionValue->time.Minute;\r
1700 EfiTime.Second = QuestionValue->time.Second;\r
1701 }\r
1702\r
1703 if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {\r
1704 Status = gRT->SetTime (&EfiTime);\r
1705 } else {\r
1706 Status = gRT->SetWakeupTime (TRUE, &EfiTime);\r
1707 }\r
1708 }\r
1709\r
1710 return Status;\r
1711 }\r
1712\r
1713 //\r
1714 // Question value is provided by EFI variable\r
1715 //\r
1716 StorageWidth = Question->StorageWidth;\r
1717 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1718 if (Question->BufferValue != NULL) {\r
1719 Src = Question->BufferValue;\r
1720 } else {\r
1721 Src = (UINT8 *) QuestionValue;\r
1722 }\r
1723\r
1724 Status = gRT->SetVariable (\r
1725 Question->VariableName,\r
1726 &Storage->Guid,\r
1727 Storage->Attributes,\r
1728 StorageWidth,\r
1729 Src\r
1730 );\r
1731 return Status;\r
1732 }\r
1733\r
1734 //\r
1735 // Question Value is provided by Buffer Storage or NameValue Storage\r
1736 //\r
1737 if (Question->BufferValue != NULL) {\r
1738 Src = Question->BufferValue;\r
1739 } else {\r
1740 Src = (UINT8 *) &Question->HiiValue.Value;\r
1741 }\r
1742\r
cce6230f
ED
1743 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
1744 Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
1745 IsBufferStorage = TRUE;\r
1746 } else {\r
1747 IsBufferStorage = FALSE;\r
1748 }\r
7936fb6a 1749 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
1750 if (IsBufferStorage) {\r
1751 //\r
1752 // Copy to storage edit buffer\r
1753 //\r
1754 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
1755 } else {\r
1756 if (IsString) {\r
1757 //\r
63d55bb9 1758 // Allocate enough string buffer.\r
7936fb6a 1759 //\r
1760 Value = NULL;\r
1761 BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
1762 Value = AllocateZeroPool (BufferLen);\r
1763 ASSERT (Value != NULL);\r
63d55bb9
LG
1764 //\r
1765 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
1766 //\r
1767 TemName = (CHAR16 *) Src;\r
1768 TemString = Value;\r
1769 for (; *TemName != L'\0'; TemName++) {\r
1770 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
1771 }\r
7936fb6a 1772 } else {\r
1773 BufferLen = StorageWidth * 2 + 1;\r
1774 Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
1775 ASSERT (Value != NULL);\r
63d55bb9
LG
1776 //\r
1777 // Convert Buffer to Hex String\r
1778 //\r
1779 TemBuffer = Src + StorageWidth - 1;\r
1780 TemString = Value;\r
1781 for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
1782 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
1783 }\r
7936fb6a 1784 }\r
1785\r
b18e7050 1786 Status = SetValueByName (Storage, Question->VariableName, Value, TRUE);\r
f4113e1f 1787 FreePool (Value);\r
7936fb6a 1788 }\r
1789\r
1790 if (!Cached) {\r
db40504e 1791 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
cce6230f
ED
1792 //\r
1793 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||\r
1794 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"\r
1795 //\r
1796 if (IsBufferStorage) {\r
1797 Length = StrLen (Question->BlockName) + 7;\r
1798 } else {\r
1799 Length = StrLen (Question->VariableName) + 2;\r
1800 }\r
1801 if (!IsBufferStorage && IsString) {\r
1802 Length += (StrLen ((CHAR16 *) Src) * 4);\r
1803 } else {\r
1804 Length += (StorageWidth * 2);\r
1805 }\r
1806 ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16));\r
1807 ASSERT (ConfigResp != NULL);\r
7936fb6a 1808\r
cce6230f
ED
1809 StrCpy (ConfigResp, Storage->ConfigHdr);\r
1810 if (IsBufferStorage) {\r
1811 StrCat (ConfigResp, Question->BlockName);\r
1812 StrCat (ConfigResp, L"&VALUE=");\r
1813 } else {\r
1814 StrCat (ConfigResp, L"&");\r
1815 StrCat (ConfigResp, Question->VariableName);\r
1816 StrCat (ConfigResp, L"=");\r
1817 }\r
1818\r
1819 Value = ConfigResp + StrLen (ConfigResp);\r
7936fb6a 1820\r
cce6230f
ED
1821 if (!IsBufferStorage && IsString) {\r
1822 //\r
1823 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
1824 //\r
1825 TemName = (CHAR16 *) Src;\r
1826 TemString = Value;\r
1827 for (; *TemName != L'\0'; TemName++) {\r
1828 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
1829 }\r
1830 } else {\r
1831 //\r
1832 // Convert Buffer to Hex String\r
1833 //\r
1834 TemBuffer = Src + StorageWidth - 1;\r
1835 TemString = Value;\r
1836 for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
1837 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
1838 }\r
1839 }\r
63d55bb9 1840\r
7936fb6a 1841 //\r
cce6230f 1842 // Convert to lower char.\r
7936fb6a 1843 //\r
cce6230f
ED
1844 for (TemString = Value; *Value != L'\0'; Value++) {\r
1845 if (*Value >= L'A' && *Value <= L'Z') {\r
1846 *Value = (CHAR16) (*Value - L'A' + L'a');\r
1847 }\r
63d55bb9 1848 }\r
cce6230f 1849\r
63d55bb9 1850 //\r
cce6230f 1851 // Submit Question Value to Configuration Driver\r
63d55bb9 1852 //\r
cce6230f
ED
1853 if (FormSet->ConfigAccess != NULL) {\r
1854 Status = FormSet->ConfigAccess->RouteConfig (\r
1855 FormSet->ConfigAccess,\r
1856 ConfigResp,\r
1857 &Progress\r
1858 );\r
1859 if (EFI_ERROR (Status)) {\r
1860 FreePool (ConfigResp);\r
1861 return Status;\r
1862 }\r
63d55bb9 1863 }\r
cce6230f
ED
1864 FreePool (ConfigResp);\r
1865 \r
1866 } else if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
1867 TemBuffer = NULL;\r
1868 TemBuffer = AllocateZeroPool(Storage->Size);\r
1869 if (TemBuffer == NULL) {\r
1870 Status = EFI_OUT_OF_RESOURCES;\r
1871 return Status;\r
63d55bb9 1872 }\r
cce6230f
ED
1873 Length = Storage->Size;\r
1874 Status = gRT->GetVariable (\r
1875 Storage->Name,\r
1876 &Storage->Guid,\r
1877 NULL,\r
1878 &Length,\r
1879 TemBuffer\r
1880 );\r
7936fb6a 1881\r
cce6230f
ED
1882 CopyMem (TemBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
1883 \r
1884 Status = gRT->SetVariable (\r
1885 Storage->Name,\r
1886 &Storage->Guid,\r
1887 Storage->Attributes,\r
1888 Storage->Size,\r
1889 TemBuffer\r
1890 );\r
1891 FreePool (TemBuffer);\r
1892 if (EFI_ERROR (Status)){\r
7936fb6a 1893 return Status;\r
1894 }\r
1895 }\r
7936fb6a 1896 //\r
cce6230f 1897 // Sync storage, from editbuffer to buffer.\r
7936fb6a 1898 //\r
cce6230f 1899 CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
7936fb6a 1900 }\r
1901\r
1902 return Status;\r
1903}\r
1904\r
1905\r
1906/**\r
1907 Perform inconsistent check for a Form.\r
1908\r
1909 @param FormSet FormSet data structure.\r
1910 @param Form Form data structure.\r
1911 @param Question The Question to be validated.\r
1912 @param Type Validation type: InConsistent or NoSubmit\r
1913\r
1914 @retval EFI_SUCCESS Form validation pass.\r
1915 @retval other Form validation failed.\r
1916\r
1917**/\r
1918EFI_STATUS\r
1919ValidateQuestion (\r
1920 IN FORM_BROWSER_FORMSET *FormSet,\r
1921 IN FORM_BROWSER_FORM *Form,\r
1922 IN FORM_BROWSER_STATEMENT *Question,\r
1923 IN UINTN Type\r
1924 )\r
1925{\r
1926 EFI_STATUS Status;\r
1927 LIST_ENTRY *Link;\r
1928 LIST_ENTRY *ListHead;\r
1929 EFI_STRING PopUp;\r
1930 EFI_INPUT_KEY Key;\r
1931 FORM_EXPRESSION *Expression;\r
1932\r
1933 if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {\r
1934 ListHead = &Question->InconsistentListHead;\r
1935 } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
1936 ListHead = &Question->NoSubmitListHead;\r
1937 } else {\r
1938 return EFI_UNSUPPORTED;\r
1939 }\r
1940\r
1941 Link = GetFirstNode (ListHead);\r
1942 while (!IsNull (ListHead, Link)) {\r
1943 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
1944\r
1945 //\r
1946 // Evaluate the expression\r
1947 //\r
1948 Status = EvaluateExpression (FormSet, Form, Expression);\r
1949 if (EFI_ERROR (Status)) {\r
1950 return Status;\r
1951 }\r
1952\r
8f420676 1953 if ((Expression->Result.Type == EFI_IFR_TYPE_BOOLEAN) && Expression->Result.Value.b) {\r
7936fb6a 1954 //\r
1955 // Condition meet, show up error message\r
1956 //\r
1957 if (Expression->Error != 0) {\r
1958 PopUp = GetToken (Expression->Error, FormSet->HiiHandle);\r
1959 do {\r
1960 CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);\r
1961 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
f4113e1f 1962 FreePool (PopUp);\r
7936fb6a 1963 }\r
1964\r
1965 return EFI_NOT_READY;\r
1966 }\r
1967\r
1968 Link = GetNextNode (ListHead, Link);\r
1969 }\r
1970\r
1971 return EFI_SUCCESS;\r
1972}\r
1973\r
1974\r
1975/**\r
5adb8db7 1976 Perform NoSubmit check for each Form in FormSet.\r
7936fb6a 1977\r
1978 @param FormSet FormSet data structure.\r
b18e7050 1979 @param CurrentForm Current input form data structure.\r
7936fb6a 1980\r
1981 @retval EFI_SUCCESS Form validation pass.\r
1982 @retval other Form validation failed.\r
1983\r
1984**/\r
1985EFI_STATUS\r
1986NoSubmitCheck (\r
b18e7050
ED
1987 IN FORM_BROWSER_FORMSET *FormSet,\r
1988 IN FORM_BROWSER_FORM *CurrentForm\r
7936fb6a 1989 )\r
1990{\r
1991 EFI_STATUS Status;\r
1992 LIST_ENTRY *Link;\r
1993 FORM_BROWSER_STATEMENT *Question;\r
5adb8db7
LG
1994 FORM_BROWSER_FORM *Form;\r
1995 LIST_ENTRY *LinkForm;\r
7936fb6a 1996\r
5adb8db7
LG
1997 LinkForm = GetFirstNode (&FormSet->FormListHead);\r
1998 while (!IsNull (&FormSet->FormListHead, LinkForm)) {\r
1999 Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);\r
b18e7050
ED
2000 LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);\r
2001\r
2002 if (CurrentForm != NULL && CurrentForm != Form) {\r
2003 continue;\r
2004 }\r
7936fb6a 2005\r
5adb8db7
LG
2006 Link = GetFirstNode (&Form->StatementListHead);\r
2007 while (!IsNull (&Form->StatementListHead, Link)) {\r
2008 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
2009\r
2010 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);\r
2011 if (EFI_ERROR (Status)) {\r
2012 return Status;\r
2013 }\r
2014\r
2015 Link = GetNextNode (&Form->StatementListHead, Link);\r
7936fb6a 2016 }\r
7936fb6a 2017 }\r
2018\r
2019 return EFI_SUCCESS;\r
2020}\r
2021\r
7936fb6a 2022/**\r
b18e7050
ED
2023 Fill storage's edit copy with settings requested from Configuration Driver.\r
2024\r
2025 @param FormSet FormSet data structure.\r
2026 @param ConfigInfo The config info related to this form.\r
cce6230f
ED
2027 @param SyncOrRestore Sync the buffer to editbuffer or Restore the \r
2028 editbuffer to buffer\r
2029 if TRUE, copy the editbuffer to the buffer.\r
2030 if FALSE, copy the buffer to the editbuffer.\r
b18e7050
ED
2031\r
2032 @retval EFI_SUCCESS The function completed successfully.\r
2033\r
2034**/\r
2035EFI_STATUS\r
cce6230f 2036SynchronizeStorageForForm (\r
b18e7050 2037 IN FORM_BROWSER_FORMSET *FormSet,\r
cce6230f
ED
2038 IN FORM_BROWSER_CONFIG_REQUEST *ConfigInfo,\r
2039 IN BOOLEAN SyncOrRestore\r
b18e7050
ED
2040 )\r
2041{\r
2042 EFI_STATUS Status;\r
2043 EFI_STRING Progress;\r
2044 EFI_STRING Result;\r
2045 UINTN BufferSize;\r
2046 LIST_ENTRY *Link;\r
2047 NAME_VALUE_NODE *Node;\r
cce6230f
ED
2048 UINT8 *Src;\r
2049 UINT8 *Dst;\r
b18e7050
ED
2050\r
2051 Status = EFI_SUCCESS;\r
2052 Result = NULL;\r
cce6230f 2053 if (FormSet->ConfigAccess == NULL && ConfigInfo->Storage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
b18e7050
ED
2054 return EFI_NOT_FOUND;\r
2055 }\r
2056\r
2057 if (ConfigInfo->ElementCount == 0) {\r
2058 //\r
2059 // Skip if there is no RequestElement\r
2060 //\r
2061 return EFI_SUCCESS;\r
2062 }\r
2063\r
cce6230f
ED
2064 if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
2065 (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
b18e7050 2066 BufferSize = ConfigInfo->Storage->Size;\r
cce6230f
ED
2067\r
2068 if (SyncOrRestore) {\r
2069 Src = ConfigInfo->Storage->EditBuffer;\r
2070 Dst = ConfigInfo->Storage->Buffer;\r
2071 } else {\r
2072 Src = ConfigInfo->Storage->Buffer;\r
2073 Dst = ConfigInfo->Storage->EditBuffer;\r
2074 }\r
2075\r
b18e7050
ED
2076 Status = mHiiConfigRouting->BlockToConfig(\r
2077 mHiiConfigRouting,\r
2078 ConfigInfo->ConfigRequest,\r
cce6230f 2079 Src,\r
b18e7050
ED
2080 BufferSize,\r
2081 &Result,\r
2082 &Progress\r
2083 );\r
2084 if (EFI_ERROR (Status)) {\r
2085 return Status;\r
2086 }\r
2087\r
2088 Status = mHiiConfigRouting->ConfigToBlock (\r
2089 mHiiConfigRouting,\r
2090 Result,\r
cce6230f 2091 Dst,\r
b18e7050
ED
2092 &BufferSize,\r
2093 &Progress\r
2094 );\r
2095 if (Result != NULL) {\r
2096 FreePool (Result);\r
2097 }\r
b18e7050
ED
2098 } else if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2099 Link = GetFirstNode (&ConfigInfo->Storage->NameValueListHead);\r
2100 while (!IsNull (&ConfigInfo->Storage->NameValueListHead, Link)) {\r
2101 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
2102\r
2103 if (StrStr (ConfigInfo->ConfigRequest, Node->Name) != NULL) {\r
cce6230f
ED
2104 if (SyncOrRestore) {\r
2105 NewStringCpy (&Node->Value, Node->EditValue);\r
2106 } else {\r
2107 NewStringCpy (&Node->EditValue, Node->Value);\r
b18e7050 2108 }\r
b18e7050
ED
2109 }\r
2110\r
2111 Link = GetNextNode (&ConfigInfo->Storage->NameValueListHead, Link);\r
2112 }\r
2113 }\r
2114\r
2115 return Status;\r
2116}\r
2117\r
2118\r
2119/**\r
48a9d5f7 2120 Discard data based on the input setting scope (Form, FormSet or System).\r
7936fb6a 2121\r
2122 @param FormSet FormSet data structure.\r
2123 @param Form Form data structure.\r
48a9d5f7 2124 @param SettingScope Setting Scope for Discard action.\r
b18e7050
ED
2125\r
2126 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 2127 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
b18e7050
ED
2128\r
2129**/\r
2130EFI_STATUS\r
2131DiscardForm (\r
2132 IN FORM_BROWSER_FORMSET *FormSet,\r
2133 IN FORM_BROWSER_FORM *Form,\r
48a9d5f7 2134 IN BROWSER_SETTING_SCOPE SettingScope\r
b18e7050
ED
2135 )\r
2136{\r
48a9d5f7
LG
2137 LIST_ENTRY *Link;\r
2138 FORMSET_STORAGE *Storage;\r
b18e7050 2139 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
48a9d5f7 2140 FORM_BROWSER_FORMSET *LocalFormSet;\r
b18e7050 2141\r
48a9d5f7
LG
2142 //\r
2143 // Check the supported setting level.\r
2144 //\r
2145 if (SettingScope >= MaxLevel) {\r
2146 return EFI_UNSUPPORTED;\r
2147 }\r
b18e7050 2148\r
48a9d5f7
LG
2149 if (SettingScope == FormLevel && Form->NvUpdateRequired) {\r
2150 ConfigInfo = NULL;\r
2151 Link = GetFirstNode (&Form->ConfigRequestHead);\r
2152 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
2153 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
2154 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
b18e7050 2155\r
48a9d5f7
LG
2156 if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2157 continue;\r
2158 }\r
2159\r
2160 //\r
2161 // Skip if there is no RequestElement\r
2162 //\r
2163 if (ConfigInfo->ElementCount == 0) {\r
2164 continue;\r
b18e7050
ED
2165 }\r
2166\r
48a9d5f7
LG
2167 //\r
2168 // Prepare <ConfigResp>\r
2169 //\r
2170 SynchronizeStorageForForm(FormSet, ConfigInfo, FALSE);\r
b18e7050 2171 }\r
48a9d5f7
LG
2172\r
2173 Form->NvUpdateRequired = FALSE;\r
2174 } else if (SettingScope == FormSetLevel && IsNvUpdateRequired(FormSet)) {\r
2175 //\r
2176 // Discard Buffer storage or Name/Value storage\r
2177 //\r
2178 Link = GetFirstNode (&FormSet->StorageListHead);\r
2179 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
2180 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
2181 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
2182\r
2183 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2184 continue;\r
2185 }\r
2186\r
b18e7050 2187 //\r
48a9d5f7 2188 // Skip if there is no RequestElement\r
b18e7050 2189 //\r
48a9d5f7
LG
2190 if (Storage->ElementCount == 0) {\r
2191 continue;\r
2192 }\r
b18e7050 2193\r
48a9d5f7
LG
2194 SynchronizeStorage(Storage, FALSE);\r
2195 }\r
b18e7050 2196\r
48a9d5f7
LG
2197 UpdateNvInfoInForm (FormSet, FALSE); \r
2198 } else if (SettingScope == SystemLevel) {\r
2199 //\r
2200 // System Level Discard.\r
2201 //\r
2202 \r
2203 //\r
2204 // Discard changed value for each FormSet in the maintain list.\r
2205 //\r
2206 Link = GetFirstNode (&gBrowserFormSetList);\r
2207 while (!IsNull (&gBrowserFormSetList, Link)) {\r
2208 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
2209 DiscardForm (LocalFormSet, NULL, FormSetLevel);\r
2210 Link = GetNextNode (&gBrowserFormSetList, Link);\r
2211 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
b18e7050 2212 //\r
48a9d5f7 2213 // Remove maintain backup list after discard except for the current using FormSet.\r
b18e7050 2214 //\r
48a9d5f7
LG
2215 RemoveEntryList (&LocalFormSet->Link);\r
2216 DestroyFormSet (LocalFormSet);\r
b18e7050 2217 }\r
b18e7050
ED
2218 }\r
2219 }\r
2220\r
2221 return EFI_SUCCESS; \r
2222}\r
2223\r
2224/**\r
48a9d5f7 2225 Submit data based on the input Setting level (Form, FormSet or System).\r
b18e7050
ED
2226\r
2227 @param FormSet FormSet data structure.\r
2228 @param Form Form data structure.\r
48a9d5f7 2229 @param SettingScope Setting Scope for Submit action.\r
7936fb6a 2230\r
2231 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 2232 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
7936fb6a 2233\r
2234**/\r
2235EFI_STATUS\r
2236SubmitForm (\r
2237 IN FORM_BROWSER_FORMSET *FormSet,\r
b18e7050 2238 IN FORM_BROWSER_FORM *Form,\r
48a9d5f7 2239 IN BROWSER_SETTING_SCOPE SettingScope\r
7936fb6a 2240 )\r
2241{\r
2242 EFI_STATUS Status;\r
2243 LIST_ENTRY *Link;\r
2244 EFI_STRING ConfigResp;\r
2245 EFI_STRING Progress;\r
2246 FORMSET_STORAGE *Storage;\r
cce6230f 2247 UINTN BufferSize;\r
48a9d5f7
LG
2248 UINT8 *TmpBuf; \r
2249 FORM_BROWSER_FORMSET *LocalFormSet;\r
b18e7050 2250 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
7936fb6a 2251\r
48a9d5f7
LG
2252 //\r
2253 // Check the supported setting level.\r
2254 //\r
2255 if (SettingScope >= MaxLevel) {\r
2256 return EFI_UNSUPPORTED;\r
2257 }\r
2258\r
7936fb6a 2259 //\r
2260 // Validate the Form by NoSubmit check\r
2261 //\r
48a9d5f7
LG
2262 Status = EFI_SUCCESS;\r
2263 if (SettingScope == FormLevel) {\r
b18e7050 2264 Status = NoSubmitCheck (FormSet, Form);\r
48a9d5f7 2265 } else if (SettingScope == FormSetLevel) {\r
b18e7050
ED
2266 Status = NoSubmitCheck (FormSet, NULL);\r
2267 }\r
7936fb6a 2268 if (EFI_ERROR (Status)) {\r
2269 return Status;\r
2270 }\r
2271\r
48a9d5f7 2272 if (SettingScope == FormLevel && Form->NvUpdateRequired) {\r
b18e7050
ED
2273 ConfigInfo = NULL;\r
2274 Link = GetFirstNode (&Form->ConfigRequestHead);\r
2275 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
2276 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
2277 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
7936fb6a 2278\r
cce6230f
ED
2279 Storage = ConfigInfo->Storage;\r
2280 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
b18e7050
ED
2281 continue;\r
2282 }\r
7936fb6a 2283\r
b18e7050
ED
2284 //\r
2285 // Skip if there is no RequestElement\r
2286 //\r
2287 if (ConfigInfo->ElementCount == 0) {\r
2288 continue;\r
2289 }\r
7936fb6a 2290\r
b18e7050 2291 //\r
cce6230f 2292 // 1. Prepare <ConfigResp>\r
b18e7050
ED
2293 //\r
2294 Status = StorageToConfigResp (ConfigInfo, &ConfigResp, TRUE);\r
2295 if (EFI_ERROR (Status)) {\r
2296 return Status;\r
2297 }\r
2298\r
2299 //\r
cce6230f 2300 // 2. Set value to hii driver or efi variable.\r
b18e7050 2301 //\r
cce6230f
ED
2302 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
2303 Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2304 //\r
2305 // Send <ConfigResp> to Configuration Driver\r
2306 //\r
2307 if (FormSet->ConfigAccess != NULL) {\r
2308 Status = FormSet->ConfigAccess->RouteConfig (\r
2309 FormSet->ConfigAccess,\r
2310 ConfigResp,\r
2311 &Progress\r
2312 );\r
2313 if (EFI_ERROR (Status)) {\r
2314 FreePool (ConfigResp);\r
2315 return Status;\r
2316 }\r
2317 }\r
2318 } else if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
2319 TmpBuf = NULL;\r
2320 TmpBuf = AllocateZeroPool(Storage->Size);\r
2321 if (TmpBuf == NULL) {\r
2322 Status = EFI_OUT_OF_RESOURCES;\r
2323 return Status;\r
2324 }\r
2325\r
2326 BufferSize = Storage->Size;\r
2327 Status = gRT->GetVariable (\r
2328 Storage->Name,\r
2329 &Storage->Guid,\r
2330 NULL,\r
2331 &BufferSize,\r
2332 TmpBuf\r
2333 );\r
2334 if (EFI_ERROR (Status)) {\r
2335 FreePool (TmpBuf);\r
2336 FreePool (ConfigResp);\r
2337 return Status;\r
2338 }\r
2339 ASSERT (BufferSize == Storage->Size); \r
2340 Status = mHiiConfigRouting->ConfigToBlock (\r
2341 mHiiConfigRouting,\r
2342 ConfigResp,\r
2343 TmpBuf,\r
2344 &BufferSize,\r
2345 &Progress\r
2346 );\r
2347 if (EFI_ERROR (Status)) {\r
2348 FreePool (TmpBuf);\r
2349 FreePool (ConfigResp);\r
2350 return Status;\r
2351 }\r
2352\r
2353 Status = gRT->SetVariable (\r
2354 Storage->Name,\r
2355 &Storage->Guid,\r
2356 Storage->Attributes,\r
2357 Storage->Size,\r
2358 TmpBuf\r
2359 );\r
2360 FreePool (TmpBuf);\r
b18e7050
ED
2361 if (EFI_ERROR (Status)) {\r
2362 FreePool (ConfigResp);\r
2363 return Status;\r
2364 }\r
2365 }\r
2366 FreePool (ConfigResp);\r
b18e7050 2367 //\r
cce6230f 2368 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.\r
b18e7050 2369 //\r
cce6230f 2370 SynchronizeStorageForForm(FormSet, ConfigInfo, TRUE);\r
7936fb6a 2371 }\r
2372\r
cce6230f
ED
2373 //\r
2374 // 4. Update the NV flag.\r
2375 // \r
b18e7050 2376 Form->NvUpdateRequired = FALSE;\r
48a9d5f7 2377 } else if (SettingScope == FormSetLevel && IsNvUpdateRequired(FormSet)) {\r
7936fb6a 2378 //\r
b18e7050 2379 // Submit Buffer storage or Name/Value storage\r
7936fb6a 2380 //\r
b18e7050
ED
2381 Link = GetFirstNode (&FormSet->StorageListHead);\r
2382 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
2383 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
2384 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
2385\r
2386 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2387 continue;\r
2388 }\r
2389\r
2390 //\r
2391 // Skip if there is no RequestElement\r
2392 //\r
2393 if (Storage->ElementCount == 0) {\r
2394 continue;\r
2395 }\r
2396\r
2397 //\r
cce6230f 2398 // 1. Prepare <ConfigResp>\r
b18e7050
ED
2399 //\r
2400 Status = StorageToConfigResp (Storage, &ConfigResp, FALSE);\r
7936fb6a 2401 if (EFI_ERROR (Status)) {\r
7936fb6a 2402 return Status;\r
2403 }\r
b18e7050 2404\r
cce6230f
ED
2405 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
2406 Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2407\r
2408 //\r
2409 // 2. Send <ConfigResp> to Configuration Driver\r
2410 //\r
2411 if (FormSet->ConfigAccess != NULL) {\r
2412 Status = FormSet->ConfigAccess->RouteConfig (\r
2413 FormSet->ConfigAccess,\r
2414 ConfigResp,\r
2415 &Progress\r
2416 );\r
2417 if (EFI_ERROR (Status)) {\r
2418 FreePool (ConfigResp);\r
2419 return Status;\r
2420 }\r
2421 }\r
2422 } else if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
2423 //\r
2424 // 1&2. Set the edit data to the variable.\r
2425 //\r
2426 TmpBuf = NULL;\r
2427 TmpBuf = AllocateZeroPool (Storage->Size);\r
2428 if (TmpBuf == NULL) {\r
2429 Status = EFI_OUT_OF_RESOURCES;\r
2430 return Status;\r
2431 } \r
2432 BufferSize = Storage->Size;\r
2433 Status = gRT->GetVariable (\r
2434 Storage->Name,\r
2435 &Storage->Guid,\r
2436 NULL,\r
2437 &BufferSize,\r
2438 TmpBuf\r
2439 );\r
2440 ASSERT (BufferSize == Storage->Size); \r
2441 Status = mHiiConfigRouting->ConfigToBlock (\r
2442 mHiiConfigRouting,\r
2443 ConfigResp,\r
2444 TmpBuf,\r
2445 &BufferSize,\r
2446 &Progress\r
2447 );\r
2448 if (EFI_ERROR (Status)) {\r
2449 FreePool (TmpBuf);\r
2450 FreePool (ConfigResp);\r
2451 return Status;\r
2452 }\r
2453\r
2454 Status = gRT->SetVariable (\r
2455 Storage->Name,\r
2456 &Storage->Guid,\r
2457 Storage->Attributes,\r
2458 Storage->Size,\r
2459 TmpBuf\r
2460 );\r
b18e7050 2461 if (EFI_ERROR (Status)) {\r
cce6230f 2462 FreePool (TmpBuf);\r
b18e7050
ED
2463 FreePool (ConfigResp);\r
2464 return Status;\r
2465 }\r
cce6230f 2466 FreePool (TmpBuf);\r
b18e7050
ED
2467 }\r
2468 FreePool (ConfigResp);\r
b18e7050 2469 //\r
cce6230f 2470 // 3. Config success, update storage shadow Buffer\r
b18e7050 2471 //\r
cce6230f 2472 SynchronizeStorage (Storage, TRUE);\r
7936fb6a 2473 }\r
7936fb6a 2474\r
cce6230f
ED
2475 //\r
2476 // 4. Update the NV flag.\r
2477 // \r
48a9d5f7
LG
2478 UpdateNvInfoInForm (FormSet, FALSE);\r
2479 } else if (SettingScope == SystemLevel) {\r
2480 //\r
2481 // System Level Save.\r
2482 //\r
2483\r
2484 //\r
2485 // Save changed value for each FormSet in the maintain list.\r
2486 //\r
2487 Link = GetFirstNode (&gBrowserFormSetList);\r
2488 while (!IsNull (&gBrowserFormSetList, Link)) {\r
2489 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
2490 SubmitForm (LocalFormSet, NULL, FormSetLevel);\r
2491 Link = GetNextNode (&gBrowserFormSetList, Link);\r
2492 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
2493 //\r
2494 // Remove maintain backup list after save except for the current using FormSet.\r
2495 //\r
2496 RemoveEntryList (&LocalFormSet->Link);\r
2497 DestroyFormSet (LocalFormSet);\r
2498 }\r
2499 }\r
7936fb6a 2500 }\r
2501\r
7936fb6a 2502 return EFI_SUCCESS;\r
2503}\r
2504\r
ee31d1be
ED
2505/**\r
2506 Get Question default value from AltCfg string.\r
2507\r
2508 @param FormSet The form set.\r
2509 @param Question The question.\r
2510 @param DefaultId The default Id.\r
2511\r
2512 @retval EFI_SUCCESS Question is reset to default value.\r
2513\r
2514**/\r
2515EFI_STATUS\r
2516GetDefaultValueFromAltCfg (\r
2517 IN FORM_BROWSER_FORMSET *FormSet,\r
2518 IN OUT FORM_BROWSER_STATEMENT *Question,\r
2519 IN UINT16 DefaultId\r
2520 )\r
2521{\r
2522 BOOLEAN IsBufferStorage;\r
2523 BOOLEAN IsString; \r
2524 UINTN Length;\r
2525 FORMSET_STORAGE *Storage;\r
2526 CHAR16 *ConfigRequest;\r
2527 CHAR16 *Progress;\r
2528 CHAR16 *Result;\r
2529 CHAR16 *ConfigResp;\r
2530 CHAR16 *Value;\r
2531 CHAR16 *StringPtr;\r
2532 UINTN LengthStr;\r
2533 UINT8 *Dst;\r
2534 CHAR16 TemStr[5];\r
2535 UINTN Index;\r
2536 UINT8 DigitUint8;\r
2537 EFI_STATUS Status;\r
2538\r
2539 Status = EFI_NOT_FOUND;\r
2540 Length = 0;\r
2541 Dst = NULL;\r
2542 ConfigRequest = NULL;\r
2543 Result = NULL;\r
2544 ConfigResp = NULL;\r
0194d26c 2545 Value = NULL;\r
ee31d1be
ED
2546 Storage = Question->Storage;\r
2547\r
cce6230f
ED
2548 if ((Storage == NULL) || \r
2549 (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) || \r
2550 (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
ee31d1be
ED
2551 return Status;\r
2552 }\r
2553\r
2554 //\r
2555 // Question Value is provided by Buffer Storage or NameValue Storage\r
2556 //\r
2557 if (Question->BufferValue != NULL) {\r
2558 //\r
2559 // This Question is password or orderedlist\r
2560 //\r
2561 Dst = Question->BufferValue;\r
2562 } else {\r
2563 //\r
2564 // Other type of Questions\r
2565 //\r
2566 Dst = (UINT8 *) &Question->HiiValue.Value;\r
2567 }\r
2568\r
2569 IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
2570 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
2571\r
2572 //\r
2573 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
2574 // <ConfigHdr> + "&" + <VariableName>\r
2575 //\r
2576 if (IsBufferStorage) {\r
2577 Length = StrLen (Storage->ConfigHdr);\r
2578 Length += StrLen (Question->BlockName);\r
2579 } else {\r
2580 Length = StrLen (Storage->ConfigHdr);\r
2581 Length += StrLen (Question->VariableName) + 1;\r
2582 }\r
2583 ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
2584 ASSERT (ConfigRequest != NULL);\r
2585\r
2586 StrCpy (ConfigRequest, Storage->ConfigHdr);\r
2587 if (IsBufferStorage) {\r
2588 StrCat (ConfigRequest, Question->BlockName);\r
2589 } else {\r
2590 StrCat (ConfigRequest, L"&");\r
2591 StrCat (ConfigRequest, Question->VariableName);\r
2592 }\r
2593\r
2594 Status = FormSet->ConfigAccess->ExtractConfig (\r
2595 FormSet->ConfigAccess,\r
2596 ConfigRequest,\r
2597 &Progress,\r
2598 &Result\r
2599 );\r
2600 if (EFI_ERROR (Status)) {\r
2601 goto Done;\r
2602 }\r
2603\r
2604 //\r
2605 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
2606 // Get the default configuration string according to the default ID.\r
2607 //\r
2608 Status = mHiiConfigRouting->GetAltConfig (\r
2609 mHiiConfigRouting,\r
2610 Result,\r
2611 &Storage->Guid,\r
2612 Storage->Name,\r
2613 NULL,\r
2614 &DefaultId, // it can be NULL to get the current setting.\r
2615 &ConfigResp\r
2616 );\r
2617 \r
2618 //\r
2619 // The required setting can't be found. So, it is not required to be validated and set.\r
2620 //\r
2621 if (EFI_ERROR (Status)) {\r
2622 goto Done;\r
2623 }\r
2624\r
2625 //\r
2626 // Skip <ConfigRequest>\r
2627 //\r
ee31d1be 2628 if (IsBufferStorage) {\r
0194d26c
ED
2629 Value = StrStr (ConfigResp, L"&VALUE");\r
2630 ASSERT (Value != NULL);\r
ee31d1be
ED
2631 //\r
2632 // Skip "&VALUE"\r
2633 //\r
2634 Value = Value + 6;\r
0194d26c
ED
2635 } else {\r
2636 Value = StrStr (ConfigResp, Question->VariableName);\r
2637 ASSERT (Value != NULL);\r
2638\r
2639 Value = Value + StrLen (Question->VariableName);\r
ee31d1be
ED
2640 }\r
2641 if (*Value != '=') {\r
2642 Status = EFI_NOT_FOUND;\r
2643 goto Done;\r
2644 }\r
2645 //\r
2646 // Skip '=', point to value\r
2647 //\r
2648 Value = Value + 1;\r
2649\r
2650 //\r
2651 // Suppress <AltResp> if any\r
2652 //\r
2653 StringPtr = Value;\r
2654 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
2655 StringPtr++;\r
2656 }\r
2657 *StringPtr = L'\0';\r
2658\r
2659 LengthStr = StrLen (Value);\r
2660 if (!IsBufferStorage && IsString) {\r
2661 StringPtr = (CHAR16 *) Dst;\r
2662 ZeroMem (TemStr, sizeof (TemStr));\r
2663 for (Index = 0; Index < LengthStr; Index += 4) {\r
2664 StrnCpy (TemStr, Value + Index, 4);\r
2665 StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
2666 }\r
2667 //\r
2668 // Add tailing L'\0' character\r
2669 //\r
2670 StringPtr[Index/4] = L'\0';\r
2671 } else {\r
2672 ZeroMem (TemStr, sizeof (TemStr));\r
2673 for (Index = 0; Index < LengthStr; Index ++) {\r
2674 TemStr[0] = Value[LengthStr - Index - 1];\r
2675 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
2676 if ((Index & 1) == 0) {\r
2677 Dst [Index/2] = DigitUint8;\r
2678 } else {\r
2679 Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
2680 }\r
2681 }\r
2682 }\r
2683\r
2684Done:\r
2685 if (ConfigRequest != NULL){\r
2686 FreePool (ConfigRequest);\r
2687 }\r
2688\r
2689 if (ConfigResp != NULL) {\r
2690 FreePool (ConfigResp);\r
2691 }\r
2692 \r
2693 if (Result != NULL) {\r
2694 FreePool (Result);\r
2695 }\r
2696\r
2697 return Status;\r
2698}\r
2699\r
2700/**\r
2701 Get default Id value used for browser.\r
2702\r
2703 @param DefaultId The default id value used by hii.\r
2704\r
2705 @retval Browser used default value.\r
2706\r
2707**/\r
2708INTN\r
2709GetDefaultIdForCallBack (\r
2710 UINTN DefaultId\r
2711 )\r
2712{ \r
2713 if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
2714 return EFI_BROWSER_ACTION_DEFAULT_STANDARD;\r
2715 } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
2716 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;\r
2717 } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {\r
2718 return EFI_BROWSER_ACTION_DEFAULT_SAFE;\r
2719 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000) {\r
2720 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;\r
2721 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000) {\r
2722 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;\r
2723 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000) {\r
2724 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;\r
2725 } else {\r
2726 return -1;\r
2727 }\r
2728}\r
7936fb6a 2729\r
2730/**\r
2731 Reset Question to its default value.\r
2732\r
2733 @param FormSet The form set.\r
2734 @param Form The form.\r
2735 @param Question The question.\r
2736 @param DefaultId The Class of the default.\r
2737\r
2738 @retval EFI_SUCCESS Question is reset to default value.\r
2739\r
2740**/\r
2741EFI_STATUS\r
2742GetQuestionDefault (\r
2743 IN FORM_BROWSER_FORMSET *FormSet,\r
2744 IN FORM_BROWSER_FORM *Form,\r
2745 IN FORM_BROWSER_STATEMENT *Question,\r
2746 IN UINT16 DefaultId\r
2747 )\r
2748{\r
2749 EFI_STATUS Status;\r
2750 LIST_ENTRY *Link;\r
2751 QUESTION_DEFAULT *Default;\r
2752 QUESTION_OPTION *Option;\r
2753 EFI_HII_VALUE *HiiValue;\r
2754 UINT8 Index;\r
086cd2c8 2755 EFI_STRING StrValue;\r
ee31d1be
ED
2756 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2757 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
2758 INTN Action;\r
7936fb6a 2759\r
48a9d5f7 2760 Status = EFI_NOT_FOUND;\r
086cd2c8 2761 StrValue = NULL;\r
7936fb6a 2762\r
2763 //\r
2764 // Statement don't have storage, skip them\r
2765 //\r
2766 if (Question->QuestionId == 0) {\r
2767 return Status;\r
2768 }\r
2769\r
2770 //\r
ee31d1be
ED
2771 // There are Five ways to specify default value for a Question:\r
2772 // 1, use call back function (highest priority)\r
2773 // 2, use ExtractConfig function\r
2774 // 3, use nested EFI_IFR_DEFAULT \r
2775 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
2776 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
7936fb6a 2777 //\r
2778 HiiValue = &Question->HiiValue;\r
2779\r
ee31d1be
ED
2780 //\r
2781 // Get Question defaut value from call back function.\r
2782 //\r
2783 ConfigAccess = FormSet->ConfigAccess;\r
2784 Action = GetDefaultIdForCallBack (DefaultId);\r
2785 if ((Action > 0) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {\r
2786 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2787 Status = ConfigAccess->Callback (\r
2788 ConfigAccess,\r
2789 Action,\r
2790 Question->QuestionId,\r
2791 HiiValue->Type,\r
2792 &HiiValue->Value,\r
2793 &ActionRequest\r
2794 );\r
2795 if (!EFI_ERROR (Status)) {\r
2796 return Status;\r
2797 }\r
2798 }\r
2799\r
2800 //\r
2801 // Get default value from altcfg string.\r
2802 //\r
2803 if (ConfigAccess != NULL) { \r
2804 Status = GetDefaultValueFromAltCfg(FormSet, Question, DefaultId);\r
2805 if (!EFI_ERROR (Status)) {\r
2806 return Status;\r
2807 }\r
2808 }\r
2809\r
7936fb6a 2810 //\r
2811 // EFI_IFR_DEFAULT has highest priority\r
2812 //\r
2813 if (!IsListEmpty (&Question->DefaultListHead)) {\r
2814 Link = GetFirstNode (&Question->DefaultListHead);\r
2815 while (!IsNull (&Question->DefaultListHead, Link)) {\r
2816 Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
2817\r
2818 if (Default->DefaultId == DefaultId) {\r
2819 if (Default->ValueExpression != NULL) {\r
2820 //\r
2821 // Default is provided by an Expression, evaluate it\r
2822 //\r
2823 Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
2824 if (EFI_ERROR (Status)) {\r
2825 return Status;\r
2826 }\r
2827\r
901ba0e7
ED
2828 if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
2829 ASSERT (HiiValue->Type == EFI_IFR_TYPE_BUFFER && Question->BufferValue != NULL);\r
2830 if (Question->StorageWidth > Default->ValueExpression->Result.BufferLen) {\r
2831 CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Default->ValueExpression->Result.BufferLen);\r
2832 Question->HiiValue.BufferLen = Default->ValueExpression->Result.BufferLen;\r
2833 } else {\r
2834 CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Question->StorageWidth);\r
2835 Question->HiiValue.BufferLen = Question->StorageWidth;\r
2836 }\r
2837 FreePool (Default->ValueExpression->Result.Buffer);\r
2838 }\r
2839 HiiValue->Type = Default->ValueExpression->Result.Type;\r
2840 CopyMem (&HiiValue->Value, &Default->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE)); \r
7936fb6a 2841 } else {\r
2842 //\r
2843 // Default value is embedded in EFI_IFR_DEFAULT\r
2844 //\r
2845 CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
2846 }\r
2847\r
086cd2c8
LG
2848 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
2849 StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);\r
2850 if (StrValue == NULL) {\r
2851 return EFI_NOT_FOUND;\r
2852 }\r
ba944801
ED
2853 if (Question->StorageWidth > StrSize (StrValue)) {\r
2854 CopyMem (Question->BufferValue, StrValue, StrSize (StrValue));\r
2855 } else {\r
2856 CopyMem (Question->BufferValue, StrValue, Question->StorageWidth);\r
2857 }\r
086cd2c8
LG
2858 }\r
2859\r
7936fb6a 2860 return EFI_SUCCESS;\r
2861 }\r
2862\r
2863 Link = GetNextNode (&Question->DefaultListHead, Link);\r
2864 }\r
2865 }\r
2866\r
2867 //\r
2868 // EFI_ONE_OF_OPTION\r
2869 //\r
2870 if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
2871 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
2872 //\r
2873 // OneOfOption could only provide Standard and Manufacturing default\r
2874 //\r
2875 Link = GetFirstNode (&Question->OptionListHead);\r
2876 while (!IsNull (&Question->OptionListHead, Link)) {\r
2877 Option = QUESTION_OPTION_FROM_LINK (Link);\r
2878\r
2879 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
2880 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
2881 ) {\r
2882 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
2883\r
2884 return EFI_SUCCESS;\r
2885 }\r
2886\r
2887 Link = GetNextNode (&Question->OptionListHead, Link);\r
2888 }\r
2889 }\r
2890 }\r
2891\r
2892 //\r
2893 // EFI_IFR_CHECKBOX - lowest priority\r
2894 //\r
2895 if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
2896 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
2897 //\r
2898 // Checkbox could only provide Standard and Manufacturing default\r
2899 //\r
2900 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
2901 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
2902 ) {\r
2903 HiiValue->Value.b = TRUE;\r
2904 } else {\r
2905 HiiValue->Value.b = FALSE;\r
2906 }\r
2907\r
2908 return EFI_SUCCESS;\r
2909 }\r
2910 }\r
2911\r
2912 //\r
2913 // For Questions without default\r
2914 //\r
48a9d5f7 2915 Status = EFI_NOT_FOUND;\r
7936fb6a 2916 switch (Question->Operand) {\r
cf4c5a42
LG
2917 case EFI_IFR_NUMERIC_OP:\r
2918 //\r
2919 // Take minimum value as numeric default value\r
2920 //\r
2921 if ((HiiValue->Value.u64 < Question->Minimum) || (HiiValue->Value.u64 > Question->Maximum)) {\r
2922 HiiValue->Value.u64 = Question->Minimum;\r
48a9d5f7 2923 Status = EFI_SUCCESS;\r
cf4c5a42
LG
2924 }\r
2925 break;\r
2926\r
7936fb6a 2927 case EFI_IFR_ONE_OF_OP:\r
2928 //\r
2929 // Take first oneof option as oneof's default value\r
2930 //\r
d66e6c16 2931 if (ValueToOption (Question, HiiValue) == NULL) {\r
0a1147ed
LG
2932 Link = GetFirstNode (&Question->OptionListHead);\r
2933 if (!IsNull (&Question->OptionListHead, Link)) {\r
2934 Option = QUESTION_OPTION_FROM_LINK (Link);\r
2935 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
48a9d5f7 2936 Status = EFI_SUCCESS;\r
0a1147ed 2937 }\r
7936fb6a 2938 }\r
2939 break;\r
2940\r
2941 case EFI_IFR_ORDERED_LIST_OP:\r
2942 //\r
2943 // Take option sequence in IFR as ordered list's default value\r
2944 //\r
2945 Index = 0;\r
2946 Link = GetFirstNode (&Question->OptionListHead);\r
2947 while (!IsNull (&Question->OptionListHead, Link)) {\r
48a9d5f7 2948 Status = EFI_SUCCESS;\r
7936fb6a 2949 Option = QUESTION_OPTION_FROM_LINK (Link);\r
2950\r
d02847d3 2951 SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);\r
7936fb6a 2952\r
2953 Index++;\r
2954 if (Index >= Question->MaxContainers) {\r
2955 break;\r
2956 }\r
2957\r
2958 Link = GetNextNode (&Question->OptionListHead, Link);\r
2959 }\r
2960 break;\r
2961\r
2962 default:\r
7936fb6a 2963 break;\r
2964 }\r
2965\r
2966 return Status;\r
2967}\r
2968\r
2969\r
2970/**\r
48a9d5f7 2971 Reset Questions to their default value in a Form, Formset or System.\r
7936fb6a 2972\r
2973 @param FormSet FormSet data structure.\r
48a9d5f7 2974 @param Form Form data structure.\r
7936fb6a 2975 @param DefaultId The Class of the default.\r
48a9d5f7 2976 @param SettingScope Setting Scope for Default action.\r
7936fb6a 2977\r
2978 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 2979 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
7936fb6a 2980\r
2981**/\r
2982EFI_STATUS\r
48a9d5f7 2983ExtractDefault (\r
7936fb6a 2984 IN FORM_BROWSER_FORMSET *FormSet,\r
48a9d5f7
LG
2985 IN FORM_BROWSER_FORM *Form,\r
2986 IN UINT16 DefaultId,\r
2987 IN BROWSER_SETTING_SCOPE SettingScope\r
7936fb6a 2988 )\r
2989{\r
2990 EFI_STATUS Status;\r
4f33c838 2991 LIST_ENTRY *FormLink;\r
48a9d5f7 2992 LIST_ENTRY *Link;\r
7936fb6a 2993 FORM_BROWSER_STATEMENT *Question;\r
48a9d5f7
LG
2994 FORM_BROWSER_FORMSET *BackUpFormSet;\r
2995 FORM_BROWSER_FORMSET *LocalFormSet;\r
2996 EFI_HII_HANDLE *HiiHandles;\r
2997 UINTN Index;\r
2998 EFI_GUID ZeroGuid;\r
7936fb6a 2999\r
48a9d5f7
LG
3000 //\r
3001 // Check the supported setting level.\r
3002 //\r
3003 if (SettingScope >= MaxLevel) {\r
3004 return EFI_UNSUPPORTED;\r
3005 }\r
3006 \r
3007 if (SettingScope == FormLevel) {\r
8d00a0f1 3008 //\r
4f33c838 3009 // Extract Form default\r
8d00a0f1 3010 //\r
48a9d5f7
LG
3011 Link = GetFirstNode (&Form->StatementListHead);\r
3012 while (!IsNull (&Form->StatementListHead, Link)) {\r
3013 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
3014 Link = GetNextNode (&Form->StatementListHead, Link);\r
3015 \r
4f33c838
ED
3016 //\r
3017 // If Question is disabled, don't reset it to default\r
3018 //\r
31585af4
ED
3019 if (Question->Expression != NULL) {\r
3020 if (EvaluateExpressionList(Question->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
4f33c838
ED
3021 continue;\r
3022 }\r
8d00a0f1 3023 }\r
48a9d5f7 3024 \r
4f33c838
ED
3025 //\r
3026 // Reset Question to its default value\r
3027 //\r
3028 Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
3029 if (EFI_ERROR (Status)) {\r
3030 continue;\r
3031 }\r
48a9d5f7 3032 \r
4f33c838
ED
3033 //\r
3034 // Synchronize Buffer storage's Edit buffer\r
3035 //\r
3036 if ((Question->Storage != NULL) &&\r
3037 (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
3038 SetQuestionValue (FormSet, Form, Question, TRUE);\r
48a9d5f7
LG
3039 //\r
3040 // Update Form NV flag.\r
3041 //\r
3042 Form->NvUpdateRequired = TRUE;\r
3043 }\r
3044 }\r
3045 } else if (SettingScope == FormSetLevel) {\r
3046 FormLink = GetFirstNode (&FormSet->FormListHead);\r
3047 while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
3048 Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
3049 ExtractDefault (FormSet, Form, DefaultId, FormLevel);\r
3050 FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
3051 }\r
3052 } else if (SettingScope == SystemLevel) {\r
3053 //\r
3054 // Open all FormSet by locate HII packages.\r
3055 // Initiliaze the maintain FormSet to store default data as back up data.\r
3056 //\r
48a9d5f7
LG
3057 BackUpFormSet = gOldFormSet;\r
3058 gOldFormSet = NULL;\r
3059\r
3060 //\r
3061 // Get all the Hii handles\r
3062 //\r
3063 HiiHandles = HiiGetHiiHandles (NULL);\r
3064 ASSERT (HiiHandles != NULL);\r
3065\r
3066 //\r
3067 // Search for formset of each class type\r
3068 //\r
3069 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
3070 //\r
3071 // Check HiiHandles[Index] does exist in global maintain list. \r
3072 //\r
3073 if (GetFormSetFromHiiHandle (HiiHandles[Index]) != NULL) {\r
3074 continue;\r
4f33c838 3075 }\r
48a9d5f7
LG
3076 \r
3077 //\r
3078 // Initilize FormSet Setting\r
3079 //\r
3080 LocalFormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
3081 ASSERT (LocalFormSet != NULL);\r
3082 ZeroMem (&ZeroGuid, sizeof (ZeroGuid));\r
db40504e 3083 Status = InitializeFormSet (HiiHandles[Index], &ZeroGuid, LocalFormSet, FALSE);\r
48a9d5f7
LG
3084 if (EFI_ERROR (Status) || IsListEmpty (&LocalFormSet->FormListHead)) {\r
3085 DestroyFormSet (LocalFormSet);\r
3086 continue;\r
3087 }\r
3088 Status = InitializeCurrentSetting (LocalFormSet);\r
3089 if (EFI_ERROR (Status)) {\r
3090 DestroyFormSet (LocalFormSet);\r
3091 continue;\r
3092 }\r
7d1b202d
LG
3093 //\r
3094 // Initilize Questions' Value\r
3095 //\r
3096 LoadFormSetConfig (NULL, LocalFormSet);\r
3097 if (EFI_ERROR (Status)) {\r
3098 DestroyFormSet (LocalFormSet);\r
3099 continue;\r
3100 }\r
3101\r
48a9d5f7
LG
3102 //\r
3103 // Add FormSet into the maintain list.\r
3104 //\r
3105 InsertTailList (&gBrowserFormSetList, &LocalFormSet->Link);\r
3106 }\r
3107 \r
3108 //\r
3109 // Free resources, and restore gOldFormSet and gClassOfVfr\r
3110 //\r
3111 FreePool (HiiHandles);\r
3112 gOldFormSet = BackUpFormSet;\r
48a9d5f7
LG
3113 \r
3114 //\r
3115 // Set Default Value for each FormSet in the maintain list.\r
3116 //\r
3117 Link = GetFirstNode (&gBrowserFormSetList);\r
3118 while (!IsNull (&gBrowserFormSetList, Link)) {\r
3119 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
3120 ExtractDefault (LocalFormSet, NULL, DefaultId, FormSetLevel);\r
3121 Link = GetNextNode (&gBrowserFormSetList, Link);\r
7936fb6a 3122 }\r
3123 }\r
3124\r
3125 return EFI_SUCCESS;\r
3126}\r
3127\r
7936fb6a 3128/**\r
3129 Initialize Question's Edit copy from Storage.\r
3130\r
eccfeab1
LG
3131 @param Selection Selection contains the information about \r
3132 the Selection, form and formset to be displayed.\r
3133 Selection action may be updated in retrieve callback.\r
7d1b202d 3134 If Selection is NULL, only initialize Question value.\r
7936fb6a 3135 @param FormSet FormSet data structure.\r
3136 @param Form Form data structure.\r
3137\r
3138 @retval EFI_SUCCESS The function completed successfully.\r
3139\r
3140**/\r
3141EFI_STATUS\r
3142LoadFormConfig (\r
eccfeab1
LG
3143 IN OUT UI_MENU_SELECTION *Selection,\r
3144 IN FORM_BROWSER_FORMSET *FormSet,\r
3145 IN FORM_BROWSER_FORM *Form\r
7936fb6a 3146 )\r
3147{\r
eccfeab1
LG
3148 EFI_STATUS Status;\r
3149 LIST_ENTRY *Link;\r
3150 FORM_BROWSER_STATEMENT *Question;\r
3151 UINT8 *BufferValue;\r
3152 UINTN StorageWidth;\r
eccfeab1 3153 \r
7936fb6a 3154 Link = GetFirstNode (&Form->StatementListHead);\r
3155 while (!IsNull (&Form->StatementListHead, Link)) {\r
3156 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
3157\r
3158 //\r
3159 // Initialize local copy of Value for each Question\r
3160 //\r
3161 Status = GetQuestionValue (FormSet, Form, Question, TRUE);\r
3162 if (EFI_ERROR (Status)) {\r
3163 return Status;\r
3164 }\r
e2100bfa
ED
3165\r
3166 if ((Question->Operand == EFI_IFR_STRING_OP) || (Question->Operand == EFI_IFR_PASSWORD_OP)) {\r
3167 HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);\r
3168 }\r
3169\r
8ca6180f
ED
3170 //\r
3171 // According the spec, ref opcode try to get value from call back with "retrieve" type.\r
3172 //\r
7d1b202d 3173 if ((Question->Operand == EFI_IFR_REF_OP) && (FormSet->ConfigAccess != NULL) && (Selection != NULL)) {\r
8ca6180f
ED
3174 Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE);\r
3175 if (EFI_ERROR (Status)) {\r
3176 return Status;\r
3177 }\r
3178 }\r
3179\r
eccfeab1
LG
3180 //\r
3181 // Check whether EfiVarstore with CallBack can be got.\r
3182 //\r
13ad1def 3183 if ((FormSet->ConfigAccess != NULL) &&\r
7d1b202d 3184 (Selection != NULL) &&\r
13ad1def
LG
3185 (Selection->Action != UI_ACTION_REFRESH_FORMSET) &&\r
3186 (Question->QuestionId != 0) && \r
3187 (Question->Storage != NULL) &&\r
eccfeab1
LG
3188 (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) && \r
3189 ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) {\r
13ad1def 3190\r
eccfeab1
LG
3191 //\r
3192 // Check QuestionValue does exist.\r
3193 //\r
3194 StorageWidth = Question->StorageWidth;\r
3195 if (Question->BufferValue != NULL) {\r
3196 BufferValue = Question->BufferValue;\r
3197 } else {\r
3198 BufferValue = (UINT8 *) &Question->HiiValue.Value;\r
3199 }\r
3200 Status = gRT->GetVariable (\r
3201 Question->VariableName,\r
3202 &Question->Storage->Guid,\r
3203 NULL,\r
3204 &StorageWidth,\r
3205 BufferValue\r
3206 );\r
3207\r
3208 if (!EFI_ERROR (Status)) {\r
b18e7050 3209 Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE);\r
eccfeab1
LG
3210 }\r
3211 }\r
7936fb6a 3212\r
3213 Link = GetNextNode (&Form->StatementListHead, Link);\r
3214 }\r
3215\r
3216 return EFI_SUCCESS;\r
3217}\r
3218\r
d66e6c16 3219/**\r
3220 Initialize Question's Edit copy from Storage for the whole Formset.\r
3221\r
eccfeab1
LG
3222 @param Selection Selection contains the information about \r
3223 the Selection, form and formset to be displayed.\r
3224 Selection action may be updated in retrieve callback.\r
7d1b202d 3225 If Selection is NULL, only initialize Question value.\r
d66e6c16 3226 @param FormSet FormSet data structure.\r
3227\r
3228 @retval EFI_SUCCESS The function completed successfully.\r
3229\r
3230**/\r
3231EFI_STATUS\r
3232LoadFormSetConfig (\r
eccfeab1
LG
3233 IN OUT UI_MENU_SELECTION *Selection,\r
3234 IN FORM_BROWSER_FORMSET *FormSet\r
d66e6c16 3235 )\r
3236{\r
eccfeab1
LG
3237 EFI_STATUS Status;\r
3238 LIST_ENTRY *Link;\r
3239 FORM_BROWSER_FORM *Form;\r
d66e6c16 3240\r
3241 Link = GetFirstNode (&FormSet->FormListHead);\r
3242 while (!IsNull (&FormSet->FormListHead, Link)) {\r
3243 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
3244\r
3245 //\r
3246 // Initialize local copy of Value for each Form\r
3247 //\r
eccfeab1 3248 Status = LoadFormConfig (Selection, FormSet, Form);\r
d66e6c16 3249 if (EFI_ERROR (Status)) {\r
3250 return Status;\r
3251 }\r
3252\r
3253 Link = GetNextNode (&FormSet->FormListHead, Link);\r
3254 }\r
3255\r
3256 return EFI_SUCCESS;\r
3257}\r
3258\r
7936fb6a 3259/**\r
3260 Fill storage's edit copy with settings requested from Configuration Driver.\r
3261\r
3262 @param FormSet FormSet data structure.\r
3263 @param Storage Buffer Storage.\r
3264\r
3265 @retval EFI_SUCCESS The function completed successfully.\r
3266\r
3267**/\r
3268EFI_STATUS\r
3269LoadStorage (\r
3270 IN FORM_BROWSER_FORMSET *FormSet,\r
3271 IN FORMSET_STORAGE *Storage\r
3272 )\r
3273{\r
3274 EFI_STATUS Status;\r
3275 EFI_STRING Progress;\r
3276 EFI_STRING Result;\r
3277 CHAR16 *StrPtr;\r
3278\r
3279 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
3280 return EFI_SUCCESS;\r
3281 }\r
3282\r
cce6230f
ED
3283 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
3284 Status = gRT->GetVariable (\r
3285 Storage->Name,\r
3286 &Storage->Guid,\r
3287 NULL,\r
3288 (UINTN*)&Storage->Size,\r
3289 Storage->EditBuffer\r
3290 );\r
3291 return Status;\r
3292 }\r
3293\r
7936fb6a 3294 if (FormSet->ConfigAccess == NULL) {\r
3295 return EFI_NOT_FOUND;\r
3296 }\r
3297\r
3298 if (Storage->ElementCount == 0) {\r
3299 //\r
3300 // Skip if there is no RequestElement\r
3301 //\r
3302 return EFI_SUCCESS;\r
3303 }\r
3304\r
3305 //\r
3306 // Request current settings from Configuration Driver\r
3307 //\r
3308 Status = FormSet->ConfigAccess->ExtractConfig (\r
3309 FormSet->ConfigAccess,\r
3310 Storage->ConfigRequest,\r
3311 &Progress,\r
3312 &Result\r
3313 );\r
3314 if (EFI_ERROR (Status)) {\r
3315 return Status;\r
3316 }\r
3317\r
3318 //\r
3319 // Convert Result from <ConfigAltResp> to <ConfigResp>\r
3320 //\r
3321 StrPtr = StrStr (Result, L"ALTCFG");\r
3322 if (StrPtr != NULL) {\r
3323 *StrPtr = L'\0';\r
3324 }\r
3325\r
3326 Status = ConfigRespToStorage (Storage, Result);\r
f4113e1f 3327 FreePool (Result);\r
7936fb6a 3328 return Status;\r
3329}\r
3330\r
3331\r
d66e6c16 3332/**\r
3333 Copy uncommitted data from source Storage to destination Storage.\r
3334\r
3335 @param Dst Target Storage for uncommitted data.\r
3336 @param Src Source Storage for uncommitted data.\r
3337\r
3338 @retval EFI_SUCCESS The function completed successfully.\r
3339 @retval EFI_INVALID_PARAMETER Source and destination Storage is not the same type.\r
3340\r
3341**/\r
3342EFI_STATUS\r
3343CopyStorage (\r
3344 IN OUT FORMSET_STORAGE *Dst,\r
3345 IN FORMSET_STORAGE *Src\r
3346 )\r
3347{\r
3348 LIST_ENTRY *Link;\r
3349 NAME_VALUE_NODE *Node;\r
3350\r
3351 if ((Dst->Type != Src->Type) || (Dst->Size != Src->Size)) {\r
3352 return EFI_INVALID_PARAMETER;\r
3353 }\r
3354\r
3355 switch (Src->Type) {\r
3356 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 3357 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
d66e6c16 3358 CopyMem (Dst->EditBuffer, Src->EditBuffer, Src->Size);\r
b18e7050 3359 CopyMem (Dst->Buffer, Src->Buffer, Src->Size);\r
d66e6c16 3360 break;\r
3361\r
3362 case EFI_HII_VARSTORE_NAME_VALUE:\r
3363 Link = GetFirstNode (&Src->NameValueListHead);\r
3364 while (!IsNull (&Src->NameValueListHead, Link)) {\r
3365 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
3366\r
b18e7050
ED
3367 SetValueByName (Dst, Node->Name, Node->EditValue, TRUE);\r
3368 SetValueByName (Dst, Node->Name, Node->Value, FALSE);\r
d66e6c16 3369\r
3370 Link = GetNextNode (&Src->NameValueListHead, Link);\r
3371 }\r
3372 break;\r
3373\r
3374 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
3375 default:\r
3376 break;\r
3377 }\r
3378\r
3379 return EFI_SUCCESS;\r
3380}\r
3381\r
3382\r
7936fb6a 3383/**\r
3384 Get current setting of Questions.\r
3385\r
3386 @param FormSet FormSet data structure.\r
3387\r
3388 @retval EFI_SUCCESS The function completed successfully.\r
3389\r
3390**/\r
3391EFI_STATUS\r
3392InitializeCurrentSetting (\r
3393 IN OUT FORM_BROWSER_FORMSET *FormSet\r
3394 )\r
3395{\r
3396 LIST_ENTRY *Link;\r
d66e6c16 3397 LIST_ENTRY *Link2;\r
7936fb6a 3398 FORMSET_STORAGE *Storage;\r
d66e6c16 3399 FORMSET_STORAGE *StorageSrc;\r
3400 FORMSET_STORAGE *OldStorage;\r
7936fb6a 3401 FORM_BROWSER_FORM *Form;\r
b00964a9 3402 FORM_BROWSER_FORM *Form2;\r
7936fb6a 3403 EFI_STATUS Status;\r
3404\r
3405 //\r
3406 // Extract default from IFR binary\r
3407 //\r
48a9d5f7
LG
3408 ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel);\r
3409 UpdateNvInfoInForm (FormSet, FALSE);\r
7936fb6a 3410\r
3411 //\r
3412 // Request current settings from Configuration Driver\r
3413 //\r
3414 Link = GetFirstNode (&FormSet->StorageListHead);\r
3415 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
3416 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
3417\r
d66e6c16 3418 OldStorage = NULL;\r
3419 if (gOldFormSet != NULL) {\r
3420 //\r
3421 // Try to find the Storage in backup formset gOldFormSet\r
3422 //\r
3423 Link2 = GetFirstNode (&gOldFormSet->StorageListHead);\r
3424 while (!IsNull (&gOldFormSet->StorageListHead, Link2)) {\r
3425 StorageSrc = FORMSET_STORAGE_FROM_LINK (Link2);\r
3426\r
3427 if (StorageSrc->VarStoreId == Storage->VarStoreId) {\r
3428 OldStorage = StorageSrc;\r
3429 break;\r
3430 }\r
3431\r
3432 Link2 = GetNextNode (&gOldFormSet->StorageListHead, Link2);\r
3433 }\r
3434 }\r
3435\r
3436 if (OldStorage == NULL) {\r
3437 //\r
3438 // Storage is not found in backup formset, request it from ConfigDriver\r
3439 //\r
3440 Status = LoadStorage (FormSet, Storage);\r
b18e7050
ED
3441 //\r
3442 // Now Edit Buffer is filled with default values(lower priority) and current\r
3443 // settings(higher priority), sychronize it to shadow Buffer\r
3444 //\r
3445 if (!EFI_ERROR (Status)) {\r
cce6230f 3446 SynchronizeStorage (Storage, TRUE);\r
b18e7050 3447 }\r
d66e6c16 3448 } else {\r
3449 //\r
3450 // Storage found in backup formset, use it\r
3451 //\r
3452 Status = CopyStorage (Storage, OldStorage);\r
3453 }\r
7936fb6a 3454\r
7936fb6a 3455 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
3456 }\r
3457\r
b00964a9
ED
3458 //\r
3459 // If has old formset, get the old nv update status.\r
3460 //\r
3461 if (gOldFormSet != NULL) {\r
3462 Link = GetFirstNode (&FormSet->FormListHead);\r
3463 while (!IsNull (&FormSet->FormListHead, Link)) {\r
3464 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
3465\r
3466 Link2 = GetFirstNode (&gOldFormSet->FormListHead);\r
3467 while (!IsNull (&gOldFormSet->FormListHead, Link2)) {\r
3468 Form2 = FORM_BROWSER_FORM_FROM_LINK (Link2);\r
3469\r
3470 if (Form->FormId == Form2->FormId) {\r
3471 Form->NvUpdateRequired = Form2->NvUpdateRequired;\r
3472 break;\r
3473 }\r
3474\r
3475 Link2 = GetNextNode (&gOldFormSet->FormListHead, Link2);\r
3476 }\r
3477 Link = GetNextNode (&FormSet->FormListHead, Link);\r
3478 }\r
3479 }\r
3480\r
7936fb6a 3481 return EFI_SUCCESS;\r
3482}\r
3483\r
3484\r
3485/**\r
3486 Fetch the Ifr binary data of a FormSet.\r
3487\r
3488 @param Handle PackageList Handle\r
f5006bd9 3489 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
3490 specified (NULL or zero GUID), take the first\r
3491 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
3492 found in package list.\r
3493 On output, GUID of the formset found(if not NULL).\r
7936fb6a 3494 @param BinaryLength The length of the FormSet IFR binary.\r
3495 @param BinaryData The buffer designed to receive the FormSet.\r
3496\r
3497 @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
3498 BufferLength was updated.\r
3499 @retval EFI_INVALID_PARAMETER The handle is unknown.\r
3500 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
3501 be found with the requested FormId.\r
3502\r
3503**/\r
3504EFI_STATUS\r
3505GetIfrBinaryData (\r
3506 IN EFI_HII_HANDLE Handle,\r
3507 IN OUT EFI_GUID *FormSetGuid,\r
3508 OUT UINTN *BinaryLength,\r
3509 OUT UINT8 **BinaryData\r
3510 )\r
3511{\r
3512 EFI_STATUS Status;\r
3513 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
3514 UINTN BufferSize;\r
3515 UINT8 *Package;\r
3516 UINT8 *OpCodeData;\r
3517 UINT32 Offset;\r
3518 UINT32 Offset2;\r
7936fb6a 3519 UINT32 PackageListLength;\r
3520 EFI_HII_PACKAGE_HEADER PackageHeader;\r
0a1147ed
LG
3521 UINT8 Index;\r
3522 UINT8 NumberOfClassGuid;\r
f5006bd9 3523 BOOLEAN ClassGuidMatch;\r
0a1147ed 3524 EFI_GUID *ClassGuid;\r
f5006bd9 3525 EFI_GUID *ComparingGuid;\r
7936fb6a 3526\r
3527 OpCodeData = NULL;\r
3528 Package = NULL;\r
0c66bc76 3529 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
7936fb6a 3530\r
3531 //\r
f5006bd9 3532 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list\r
7936fb6a 3533 //\r
48a9d5f7
LG
3534 if (FormSetGuid == NULL) {\r
3535 ComparingGuid = &gZeroGuid;\r
7936fb6a 3536 } else {\r
f5006bd9 3537 ComparingGuid = FormSetGuid;\r
7936fb6a 3538 }\r
3539\r
3540 //\r
3541 // Get HII PackageList\r
3542 //\r
3543 BufferSize = 0;\r
3544 HiiPackageList = NULL;\r
3545 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
3546 if (Status == EFI_BUFFER_TOO_SMALL) {\r
3547 HiiPackageList = AllocatePool (BufferSize);\r
3548 ASSERT (HiiPackageList != NULL);\r
3549\r
3550 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
3551 }\r
3552 if (EFI_ERROR (Status)) {\r
3553 return Status;\r
3554 }\r
db0bd81c 3555 ASSERT (HiiPackageList != NULL);\r
d66e6c16 3556\r
7936fb6a 3557 //\r
3558 // Get Form package from this HII package List\r
3559 //\r
3560 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
3561 Offset2 = 0;\r
3562 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
3563\r
f5006bd9 3564 ClassGuidMatch = FALSE;\r
7936fb6a 3565 while (Offset < PackageListLength) {\r
3566 Package = ((UINT8 *) HiiPackageList) + Offset;\r
3567 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
3568\r
8d00a0f1 3569 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
7936fb6a 3570 //\r
3571 // Search FormSet in this Form Package\r
3572 //\r
3573 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
3574 while (Offset2 < PackageHeader.Length) {\r
3575 OpCodeData = Package + Offset2;\r
3576\r
3577 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
3578 //\r
f5006bd9 3579 // Try to compare against formset GUID\r
7936fb6a 3580 //\r
48a9d5f7
LG
3581 if (CompareGuid (FormSetGuid, &gZeroGuid) || \r
3582 CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
f5006bd9 3583 break;\r
7936fb6a 3584 }\r
3585\r
d228526f
LG
3586 if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
3587 //\r
3588 // Try to compare against formset class GUID\r
3589 //\r
3590 NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
3591 ClassGuid = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
3592 for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
3593 if (CompareGuid (ComparingGuid, ClassGuid + Index)) {\r
3594 ClassGuidMatch = TRUE;\r
3595 break;\r
3596 }\r
3597 }\r
3598 if (ClassGuidMatch) {\r
f5006bd9 3599 break;\r
3600 }\r
d228526f
LG
3601 } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {\r
3602 ClassGuidMatch = TRUE;\r
7936fb6a 3603 break;\r
3604 }\r
3605 }\r
3606\r
3607 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
3608 }\r
3609\r
3610 if (Offset2 < PackageHeader.Length) {\r
3611 //\r
3612 // Target formset found\r
3613 //\r
3614 break;\r
3615 }\r
3616 }\r
3617\r
3618 Offset += PackageHeader.Length;\r
3619 }\r
3620\r
3621 if (Offset >= PackageListLength) {\r
3622 //\r
3623 // Form package not found in this Package List\r
3624 //\r
f4113e1f 3625 FreePool (HiiPackageList);\r
7936fb6a 3626 return EFI_NOT_FOUND;\r
3627 }\r
3628\r
48a9d5f7 3629 if (FormSetGuid != NULL) {\r
7936fb6a 3630 //\r
f5006bd9 3631 // Return the FormSet GUID\r
7936fb6a 3632 //\r
3633 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
3634 }\r
3635\r
3636 //\r
3637 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
3638 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
3639 // of the Form Package.\r
3640 //\r
3641 *BinaryLength = PackageHeader.Length - Offset2;\r
3642 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
3643\r
f4113e1f 3644 FreePool (HiiPackageList);\r
7936fb6a 3645\r
3646 if (*BinaryData == NULL) {\r
3647 return EFI_OUT_OF_RESOURCES;\r
3648 }\r
3649\r
3650 return EFI_SUCCESS;\r
3651}\r
3652\r
3653\r
3654/**\r
3655 Initialize the internal data structure of a FormSet.\r
3656\r
3657 @param Handle PackageList Handle\r
f5006bd9 3658 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
3659 specified (NULL or zero GUID), take the first\r
3660 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
3661 found in package list.\r
3662 On output, GUID of the formset found(if not NULL).\r
7936fb6a 3663 @param FormSet FormSet data structure.\r
db40504e 3664 @param UpdateGlobalVar Whether need to update the global variable.\r
7936fb6a 3665\r
3666 @retval EFI_SUCCESS The function completed successfully.\r
3667 @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
3668\r
3669**/\r
3670EFI_STATUS\r
3671InitializeFormSet (\r
3672 IN EFI_HII_HANDLE Handle,\r
3673 IN OUT EFI_GUID *FormSetGuid,\r
db40504e
ED
3674 OUT FORM_BROWSER_FORMSET *FormSet,\r
3675 IN BOOLEAN UpdateGlobalVar \r
7936fb6a 3676 )\r
3677{\r
3678 EFI_STATUS Status;\r
3679 EFI_HANDLE DriverHandle;\r
3680 UINT16 Index;\r
3681\r
3682 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
3683 if (EFI_ERROR (Status)) {\r
3684 return Status;\r
3685 }\r
3686\r
48a9d5f7 3687 FormSet->Signature = FORM_BROWSER_FORMSET_SIGNATURE;\r
7936fb6a 3688 FormSet->HiiHandle = Handle;\r
3689 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
3690\r
3691 //\r
3692 // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
3693 //\r
3694 Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
3695 if (EFI_ERROR (Status)) {\r
3696 return Status;\r
3697 }\r
3698 FormSet->DriverHandle = DriverHandle;\r
3699 Status = gBS->HandleProtocol (\r
3700 DriverHandle,\r
3701 &gEfiHiiConfigAccessProtocolGuid,\r
3702 (VOID **) &FormSet->ConfigAccess\r
3703 );\r
3704 if (EFI_ERROR (Status)) {\r
3705 //\r
3706 // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
3707 // list, then there will be no configuration action required\r
3708 //\r
3709 FormSet->ConfigAccess = NULL;\r
3710 }\r
3711\r
3712 //\r
3713 // Parse the IFR binary OpCodes\r
3714 //\r
3715 Status = ParseOpCodes (FormSet);\r
3716 if (EFI_ERROR (Status)) {\r
3717 return Status;\r
3718 }\r
3719\r
db40504e
ED
3720 // \r
3721 // If not need to update the global variable, just return.\r
3722 //\r
3723 if (!UpdateGlobalVar) {\r
3724 return Status;\r
3725 }\r
3726\r
40245175
LG
3727 //\r
3728 // Set VFR type by FormSet SubClass field\r
3729 //\r
0a1147ed
LG
3730 gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP;\r
3731 if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {\r
3732 gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;\r
40245175
LG
3733 }\r
3734 \r
3735 //\r
3736 // Set VFR type by FormSet class guid\r
3737 //\r
3738 for (Index = 0; Index < 3; Index ++) {\r
3739 if (CompareGuid (&FormSet->ClassGuid[Index], &gEfiHiiPlatformSetupFormsetGuid)) {\r
3740 gClassOfVfr |= FORMSET_CLASS_PLATFORM_SETUP;\r
3741 break;\r
3742 }\r
3743 }\r
3744\r
3745 if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {\r
0a1147ed 3746 gFrontPageHandle = FormSet->HiiHandle;\r
48a9d5f7 3747 gFunctionKeySetting = NONE_FUNCTION_KEY_SETTING;\r
7936fb6a 3748 }\r
3749\r
3750 //\r
3751 // Match GUID to find out the function key setting. If match fail, use the default setting.\r
3752 //\r
3753 for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {\r
3754 if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {\r
3755 //\r
3756 // Update the function key setting.\r
3757 //\r
3758 gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;\r
7936fb6a 3759 }\r
3760 }\r
3761\r
48a9d5f7 3762 return EFI_SUCCESS;\r
7936fb6a 3763}\r
ce6d12cc 3764\r
3765\r
3766/**\r
3767 Save globals used by previous call to SendForm(). SendForm() may be called from \r
3768 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.\r
3769 So, save globals of previous call to SendForm() and restore them upon exit.\r
3770\r
3771**/\r
3772VOID\r
3773SaveBrowserContext (\r
3774 VOID\r
3775 )\r
3776{\r
3777 BROWSER_CONTEXT *Context;\r
3778\r
3779 gBrowserContextCount++;\r
3780 if (gBrowserContextCount == 1) {\r
3781 //\r
3782 // This is not reentry of SendForm(), no context to save\r
3783 //\r
3784 return;\r
3785 }\r
3786\r
3787 Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
3788 ASSERT (Context != NULL);\r
3789\r
3790 Context->Signature = BROWSER_CONTEXT_SIGNATURE;\r
3791\r
3792 //\r
3793 // Save FormBrowser context\r
3794 //\r
3795 Context->BannerData = gBannerData;\r
3796 Context->ClassOfVfr = gClassOfVfr;\r
3797 Context->FunctionKeySetting = gFunctionKeySetting;\r
3798 Context->ResetRequired = gResetRequired;\r
ce6d12cc 3799 Context->Direction = gDirection;\r
ce6d12cc 3800 Context->EnterString = gEnterString;\r
3801 Context->EnterCommitString = gEnterCommitString;\r
3802 Context->EnterEscapeString = gEnterEscapeString;\r
3803 Context->EscapeString = gEscapeString;\r
ce6d12cc 3804 Context->MoveHighlight = gMoveHighlight;\r
3805 Context->MakeSelection = gMakeSelection;\r
3806 Context->DecNumericInput = gDecNumericInput;\r
3807 Context->HexNumericInput = gHexNumericInput;\r
3808 Context->ToggleCheckBox = gToggleCheckBox;\r
3809 Context->PromptForData = gPromptForData;\r
3810 Context->PromptForPassword = gPromptForPassword;\r
3811 Context->PromptForNewPassword = gPromptForNewPassword;\r
3812 Context->ConfirmPassword = gConfirmPassword;\r
3813 Context->ConfirmError = gConfirmError;\r
3814 Context->PassowordInvalid = gPassowordInvalid;\r
3815 Context->PressEnter = gPressEnter;\r
3816 Context->EmptyString = gEmptyString;\r
3817 Context->AreYouSure = gAreYouSure;\r
3818 Context->YesResponse = gYesResponse;\r
3819 Context->NoResponse = gNoResponse;\r
3820 Context->MiniString = gMiniString;\r
3821 Context->PlusString = gPlusString;\r
3822 Context->MinusString = gMinusString;\r
3823 Context->AdjustNumber = gAdjustNumber;\r
3824 Context->SaveChanges = gSaveChanges;\r
3825 Context->OptionMismatch = gOptionMismatch;\r
2bb526f3 3826 Context->FormSuppress = gFormSuppress;\r
ce6d12cc 3827 Context->PromptBlockWidth = gPromptBlockWidth;\r
3828 Context->OptionBlockWidth = gOptionBlockWidth;\r
3829 Context->HelpBlockWidth = gHelpBlockWidth;\r
3830 Context->OldFormSet = gOldFormSet;\r
3831 Context->MenuRefreshHead = gMenuRefreshHead;\r
3832\r
3833 CopyMem (&Context->ScreenDimensions, &gScreenDimensions, sizeof (gScreenDimensions));\r
3834 CopyMem (&Context->MenuOption, &gMenuOption, sizeof (gMenuOption));\r
3835\r
3836 //\r
3837 // Insert to FormBrowser context list\r
3838 //\r
3839 InsertHeadList (&gBrowserContextList, &Context->Link);\r
3840}\r
3841\r
3842\r
3843/**\r
3844 Restore globals used by previous call to SendForm().\r
3845\r
3846**/\r
3847VOID\r
3848RestoreBrowserContext (\r
3849 VOID\r
3850 )\r
3851{\r
3852 LIST_ENTRY *Link;\r
3853 BROWSER_CONTEXT *Context;\r
3854\r
3855 ASSERT (gBrowserContextCount != 0);\r
3856 gBrowserContextCount--;\r
3857 if (gBrowserContextCount == 0) {\r
3858 //\r
3859 // This is not reentry of SendForm(), no context to restore\r
3860 //\r
3861 return;\r
3862 }\r
3863\r
3864 ASSERT (!IsListEmpty (&gBrowserContextList));\r
3865\r
3866 Link = GetFirstNode (&gBrowserContextList);\r
3867 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
3868\r
3869 //\r
3870 // Restore FormBrowser context\r
3871 //\r
3872 gBannerData = Context->BannerData;\r
3873 gClassOfVfr = Context->ClassOfVfr;\r
3874 gFunctionKeySetting = Context->FunctionKeySetting;\r
3875 gResetRequired = Context->ResetRequired;\r
ce6d12cc 3876 gDirection = Context->Direction;\r
ce6d12cc 3877 gEnterString = Context->EnterString;\r
3878 gEnterCommitString = Context->EnterCommitString;\r
3879 gEnterEscapeString = Context->EnterEscapeString;\r
3880 gEscapeString = Context->EscapeString;\r
ce6d12cc 3881 gMoveHighlight = Context->MoveHighlight;\r
3882 gMakeSelection = Context->MakeSelection;\r
3883 gDecNumericInput = Context->DecNumericInput;\r
3884 gHexNumericInput = Context->HexNumericInput;\r
3885 gToggleCheckBox = Context->ToggleCheckBox;\r
3886 gPromptForData = Context->PromptForData;\r
3887 gPromptForPassword = Context->PromptForPassword;\r
3888 gPromptForNewPassword = Context->PromptForNewPassword;\r
3889 gConfirmPassword = Context->ConfirmPassword;\r
3890 gConfirmError = Context->ConfirmError;\r
3891 gPassowordInvalid = Context->PassowordInvalid;\r
3892 gPressEnter = Context->PressEnter;\r
3893 gEmptyString = Context->EmptyString;\r
3894 gAreYouSure = Context->AreYouSure;\r
3895 gYesResponse = Context->YesResponse;\r
3896 gNoResponse = Context->NoResponse;\r
3897 gMiniString = Context->MiniString;\r
3898 gPlusString = Context->PlusString;\r
3899 gMinusString = Context->MinusString;\r
3900 gAdjustNumber = Context->AdjustNumber;\r
3901 gSaveChanges = Context->SaveChanges;\r
3902 gOptionMismatch = Context->OptionMismatch;\r
2bb526f3 3903 gFormSuppress = Context->FormSuppress;\r
ce6d12cc 3904 gPromptBlockWidth = Context->PromptBlockWidth;\r
3905 gOptionBlockWidth = Context->OptionBlockWidth;\r
3906 gHelpBlockWidth = Context->HelpBlockWidth;\r
3907 gOldFormSet = Context->OldFormSet;\r
3908 gMenuRefreshHead = Context->MenuRefreshHead;\r
3909\r
3910 CopyMem (&gScreenDimensions, &Context->ScreenDimensions, sizeof (gScreenDimensions));\r
3911 CopyMem (&gMenuOption, &Context->MenuOption, sizeof (gMenuOption));\r
3912\r
3913 //\r
3914 // Remove from FormBrowser context list\r
3915 //\r
3916 RemoveEntryList (&Context->Link);\r
3917 gBS->FreePool (Context);\r
3918}\r
48a9d5f7
LG
3919\r
3920/**\r
3921 Find the matched FormSet context in the backup maintain list based on HiiHandle.\r
3922 \r
3923 @param Handle The Hii Handle.\r
3924 \r
3925 @return the found FormSet context. If no found, NULL will return.\r
3926\r
3927**/\r
3928FORM_BROWSER_FORMSET * \r
3929GetFormSetFromHiiHandle (\r
3930 EFI_HII_HANDLE Handle\r
3931 )\r
3932{\r
3933 LIST_ENTRY *Link;\r
3934 FORM_BROWSER_FORMSET *FormSet;\r
3935\r
3936 Link = GetFirstNode (&gBrowserFormSetList);\r
3937 while (!IsNull (&gBrowserFormSetList, Link)) {\r
3938 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
3939 if (FormSet->HiiHandle == Handle) {\r
3940 return FormSet;\r
3941 }\r
3942 Link = GetNextNode (&gBrowserFormSetList, Link);\r
3943 }\r
3944 \r
3945 return NULL;\r
3946}\r
3947\r
3948/**\r
3949 Check whether the input HII handle is the FormSet that is being used.\r
3950 \r
3951 @param Handle The Hii Handle.\r
3952 \r
3953 @retval TRUE HII handle is being used.\r
3954 @retval FALSE HII handle is not being used.\r
3955\r
3956**/\r
3957BOOLEAN\r
3958IsHiiHandleInBrowserContext (\r
3959 EFI_HII_HANDLE Handle\r
3960 )\r
3961{\r
3962 LIST_ENTRY *Link;\r
3963 BROWSER_CONTEXT *Context;\r
3964\r
3965 //\r
3966 // HiiHandle is Current FormSet.\r
3967 //\r
3968 if ((gOldFormSet != NULL) && (gOldFormSet->HiiHandle == Handle)) {\r
3969 return TRUE;\r
3970 }\r
3971\r
3972 //\r
3973 // Check whether HiiHandle is in BrowserContext.\r
3974 //\r
3975 Link = GetFirstNode (&gBrowserContextList);\r
3976 while (!IsNull (&gBrowserContextList, Link)) {\r
3977 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
3978 if (Context->OldFormSet->HiiHandle == Handle) {\r
3979 //\r
3980 // HiiHandle is in BrowserContext\r
3981 //\r
3982 return TRUE;\r
3983 }\r
3984 Link = GetNextNode (&gBrowserContextList, Link);\r
3985 }\r
3986 \r
3987 return FALSE;\r
3988}\r
3989\r
3990/**\r
3991 Find the registered HotKey based on KeyData.\r
3992 \r
3993 @param[in] KeyData A pointer to a buffer that describes the keystroke\r
3994 information for the hot key.\r
3995\r
3996 @return The registered HotKey context. If no found, NULL will return.\r
3997**/\r
3998BROWSER_HOT_KEY *\r
3999GetHotKeyFromRegisterList (\r
4000 IN EFI_INPUT_KEY *KeyData\r
4001 )\r
4002{\r
4003 LIST_ENTRY *Link;\r
4004 BROWSER_HOT_KEY *HotKey;\r
4005\r
4006 Link = GetFirstNode (&gBrowserHotKeyList);\r
4007 while (!IsNull (&gBrowserHotKeyList, Link)) {\r
4008 HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
4009 if (HotKey->KeyData->ScanCode == KeyData->ScanCode) {\r
4010 return HotKey;\r
4011 }\r
4012 Link = GetNextNode (&gBrowserHotKeyList, Link);\r
4013 }\r
4014 \r
4015 return NULL;\r
4016}\r
4017\r
4018/**\r
4019 Configure what scope the hot key will impact.\r
4020 All hot keys have the same scope. The mixed hot keys with the different level are not supported.\r
4021 If no scope is set, the default scope will be FormSet level.\r
4022 After all registered hot keys are removed, previous Scope can reset to another level.\r
4023 \r
4024 @param[in] Scope Scope level to be set. \r
4025 \r
4026 @retval EFI_SUCCESS Scope is set correctly.\r
4027 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE. \r
4028 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.\r
4029\r
4030**/\r
4031EFI_STATUS\r
4032EFIAPI\r
4033SetScope (\r
4034 IN BROWSER_SETTING_SCOPE Scope\r
4035 )\r
4036{\r
4037 if (Scope >= MaxLevel) {\r
4038 return EFI_INVALID_PARAMETER;\r
4039 }\r
4040 \r
4041 //\r
4042 // When no hot key registered in system or on the first setting,\r
4043 // Scope can be set.\r
4044 //\r
4045 if (mBrowserScopeFirstSet || IsListEmpty (&gBrowserHotKeyList)) {\r
4046 gBrowserSettingScope = Scope;\r
4047 mBrowserScopeFirstSet = FALSE;\r
4048 } else if (Scope != gBrowserSettingScope) {\r
4049 return EFI_UNSUPPORTED;\r
4050 }\r
4051\r
4052 return EFI_SUCCESS;\r
4053}\r
4054\r
4055/**\r
4056 Register the hot key with its browser action, or unregistered the hot key.\r
4057 Only support hot key that is not printable character (control key, function key, etc.).\r
4058 If the action value is zero, the hot key will be unregistered if it has been registered.\r
4059 If the same hot key has been registered, the new action and help string will override the previous ones.\r
4060 \r
4061 @param[in] KeyData A pointer to a buffer that describes the keystroke\r
4062 information for the hot key. Its type is EFI_INPUT_KEY to \r
4063 be supported by all ConsoleIn devices.\r
4064 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed. \r
4065 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.\r
4066 @param[in] HelpString Help string that describes the hot key information.\r
4067 Its value may be NULL for the unregistered hot key.\r
4068 \r
4069 @retval EFI_SUCCESS Hot key is registered or unregistered.\r
4070 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.\r
4071 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.\r
4072 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.\r
4073**/\r
4074EFI_STATUS\r
4075EFIAPI\r
4076RegisterHotKey (\r
4077 IN EFI_INPUT_KEY *KeyData,\r
4078 IN UINT32 Action,\r
4079 IN UINT16 DefaultId,\r
4080 IN EFI_STRING HelpString OPTIONAL\r
4081 )\r
4082{\r
4083 BROWSER_HOT_KEY *HotKey;\r
4084\r
4085 //\r
4086 // Check input parameters.\r
4087 //\r
4088 if (KeyData == NULL || KeyData->UnicodeChar != CHAR_NULL || \r
4089 (Action != BROWSER_ACTION_UNREGISTER && HelpString == NULL)) {\r
4090 return EFI_INVALID_PARAMETER;\r
4091 }\r
4092\r
4093 //\r
4094 // Check whether the input KeyData is in BrowserHotKeyList.\r
4095 //\r
4096 HotKey = GetHotKeyFromRegisterList (KeyData);\r
4097 \r
4098 //\r
4099 // Unregister HotKey\r
4100 //\r
4101 if (Action == BROWSER_ACTION_UNREGISTER) {\r
4102 if (HotKey != NULL) {\r
4103 //\r
4104 // The registered HotKey is found. \r
4105 // Remove it from List, and free its resource.\r
4106 //\r
4107 RemoveEntryList (&HotKey->Link);\r
4108 FreePool (HotKey->KeyData);\r
4109 FreePool (HotKey->HelpString);\r
4110 return EFI_SUCCESS;\r
4111 } else {\r
4112 //\r
4113 // The registered HotKey is not found. \r
4114 //\r
4115 return EFI_NOT_FOUND;\r
4116 }\r
4117 }\r
4118 \r
4119 //\r
4120 // Register HotKey into List.\r
4121 //\r
4122 if (HotKey == NULL) {\r
4123 //\r
4124 // Create new Key, and add it into List.\r
4125 //\r
4126 HotKey = AllocateZeroPool (sizeof (BROWSER_HOT_KEY));\r
4127 ASSERT (HotKey != NULL);\r
4128 HotKey->Signature = BROWSER_HOT_KEY_SIGNATURE;\r
4129 HotKey->KeyData = AllocateCopyPool (sizeof (EFI_INPUT_KEY), KeyData);\r
4130 InsertTailList (&gBrowserHotKeyList, &HotKey->Link);\r
4131 }\r
4132\r
4133 //\r
4134 // Fill HotKey information.\r
4135 //\r
4136 HotKey->Action = Action;\r
4137 HotKey->DefaultId = DefaultId;\r
4138 if (HotKey->HelpString != NULL) {\r
4139 FreePool (HotKey->HelpString);\r
4140 }\r
4141 HotKey->HelpString = AllocateCopyPool (StrSize (HelpString), HelpString);\r
4142\r
4143 return EFI_SUCCESS;\r
4144}\r
4145\r
4146/**\r
4147 Register Exit handler function. \r
4148 When more than one handler function is registered, the latter one will override the previous one. \r
4149 When NULL handler is specified, the previous Exit handler will be unregistered. \r
4150 \r
4151 @param[in] Handler Pointer to handler function. \r
4152\r
4153**/\r
4154VOID\r
4155EFIAPI\r
4156RegiserExitHandler (\r
4157 IN EXIT_HANDLER Handler\r
4158 )\r
4159{\r
4160 ExitHandlerFunction = Handler;\r
4161 return;\r
4162}\r
4163\r
4164/**\r
4165 Create reminder to let user to choose save or discard the changed browser data.\r
4166 Caller can use it to actively check the changed browser data.\r
4167\r
4168 @retval BROWSER_NO_CHANGES No browser data is changed.\r
4169 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.\r
4170 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.\r
4171\r
4172**/\r
4173UINT32\r
4174EFIAPI\r
4175SaveReminder (\r
4176 VOID\r
4177 )\r
4178{\r
4179 LIST_ENTRY *Link;\r
4180 FORM_BROWSER_FORMSET *FormSet;\r
4181 BOOLEAN IsDataChanged;\r
4182 UINT32 DataSavedAction;\r
4183 CHAR16 *YesResponse;\r
4184 CHAR16 *NoResponse;\r
4185 CHAR16 *EmptyString;\r
4186 CHAR16 *ChangeReminderString;\r
4187 CHAR16 *SaveConfirmString;\r
4188 EFI_INPUT_KEY Key;\r
48a9d5f7
LG
4189\r
4190 DataSavedAction = BROWSER_NO_CHANGES;\r
4191 IsDataChanged = FALSE;\r
4192 Link = GetFirstNode (&gBrowserFormSetList);\r
4193 while (!IsNull (&gBrowserFormSetList, Link)) {\r
4194 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
4195 if (IsNvUpdateRequired (FormSet)) {\r
4196 IsDataChanged = TRUE;\r
4197 break;\r
4198 }\r
4199 Link = GetNextNode (&gBrowserFormSetList, Link);\r
4200 }\r
4201 \r
4202 //\r
4203 // No data is changed. No save is required. \r
4204 //\r
4205 if (!IsDataChanged) {\r
4206 return DataSavedAction;\r
4207 }\r
4208 \r
4209 //\r
4210 // If data is changed, prompt user\r
4211 //\r
7538d536 4212 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
48a9d5f7
LG
4213\r
4214 YesResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);\r
4215 ASSERT (YesResponse != NULL);\r
4216 NoResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);\r
4217 ASSERT (NoResponse != NULL);\r
4218 EmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
4219 ChangeReminderString = GetToken (STRING_TOKEN (CHANGE_REMINDER), gHiiHandle);\r
4220 SaveConfirmString = GetToken (STRING_TOKEN (SAVE_CONFIRM), gHiiHandle);\r
4221\r
4222 do {\r
4223 CreateDialog (4, TRUE, 0, NULL, &Key, EmptyString, ChangeReminderString, SaveConfirmString, EmptyString);\r
4224 } while\r
4225 (((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse[0] | UPPER_LOWER_CASE_OFFSET)) &&\r
4226 ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse[0] | UPPER_LOWER_CASE_OFFSET))\r
4227 );\r
4228\r
4229 //\r
4230 // If the user hits the YesResponse key\r
4231 //\r
4232 if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse[0] | UPPER_LOWER_CASE_OFFSET)) {\r
4233 SubmitForm (NULL, NULL, SystemLevel);\r
4234 DataSavedAction = BROWSER_SAVE_CHANGES;\r
4235 } else {\r
4236 DiscardForm (NULL, NULL, SystemLevel);\r
4237 DataSavedAction = BROWSER_DISCARD_CHANGES;\r
4238 gResetRequired = FALSE;\r
4239 }\r
4240\r
4241 FreePool (YesResponse);\r
4242 FreePool (NoResponse);\r
4243 FreePool (EmptyString);\r
4244 FreePool (SaveConfirmString);\r
4245 FreePool (ChangeReminderString);\r
4246\r
4247 return DataSavedAction;\r
4248}\r