]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
PcAtChipsetPkg: install RTC ARCH protocol even if RTC h/w is functioning incorrectly.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Setup.c
CommitLineData
7936fb6a 1/** @file\r
2Entry and initialization module for the browser.\r
3\r
5697f873 4Copyright (c) 2007 - 2011, 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
332 Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet);\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
7936fb6a 1223\r
1224 //\r
1225 // Statement don't have storage, skip them\r
1226 //\r
1227 if (Question->QuestionId == 0) {\r
1228 return Status;\r
1229 }\r
1230\r
1231 //\r
1232 // Question value is provided by an Expression, evaluate it\r
1233 //\r
1234 if (Question->ValueExpression != NULL) {\r
1235 Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);\r
1236 if (!EFI_ERROR (Status)) {\r
901ba0e7
ED
1237 if (Question->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
1238 ASSERT (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER && Question->HiiValue.Buffer != NULL);\r
1239 if (Question->StorageWidth > Question->ValueExpression->Result.BufferLen) {\r
1240 CopyMem (Question->HiiValue.Buffer, Question->ValueExpression->Result.Buffer, Question->ValueExpression->Result.BufferLen);\r
1241 Question->HiiValue.BufferLen = Question->ValueExpression->Result.BufferLen;\r
1242 } else {\r
1243 CopyMem (Question->HiiValue.Buffer, Question->ValueExpression->Result.Buffer, Question->StorageWidth);\r
1244 Question->HiiValue.BufferLen = Question->StorageWidth;\r
1245 }\r
1246 FreePool (Question->ValueExpression->Result.Buffer);\r
1247 }\r
1248 Question->HiiValue.Type = Question->ValueExpression->Result.Type;\r
1249 CopyMem (&Question->HiiValue.Value, &Question->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE)); \r
7936fb6a 1250 }\r
1251 return Status;\r
1252 }\r
2573712e
LG
1253 \r
1254 //\r
1255 // Get question value by read expression.\r
1256 //\r
1257 if (Question->ReadExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {\r
1258 Status = EvaluateExpression (FormSet, Form, Question->ReadExpression);\r
901ba0e7
ED
1259 if (!EFI_ERROR (Status) && \r
1260 ((Question->ReadExpression->Result.Type < EFI_IFR_TYPE_OTHER) || (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER))) {\r
2573712e
LG
1261 //\r
1262 // Only update question value to the valid result.\r
1263 //\r
901ba0e7
ED
1264 if (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
1265 ASSERT (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER && Question->HiiValue.Buffer != NULL);\r
1266 if (Question->StorageWidth > Question->ReadExpression->Result.BufferLen) {\r
1267 CopyMem (Question->HiiValue.Buffer, Question->ReadExpression->Result.Buffer, Question->ReadExpression->Result.BufferLen);\r
1268 Question->HiiValue.BufferLen = Question->ReadExpression->Result.BufferLen;\r
1269 } else {\r
1270 CopyMem (Question->HiiValue.Buffer, Question->ReadExpression->Result.Buffer, Question->StorageWidth);\r
1271 Question->HiiValue.BufferLen = Question->StorageWidth;\r
1272 }\r
1273 FreePool (Question->ReadExpression->Result.Buffer);\r
1274 }\r
1275 Question->HiiValue.Type = Question->ReadExpression->Result.Type;\r
1276 CopyMem (&Question->HiiValue.Value, &Question->ReadExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE)); \r
2573712e
LG
1277 return EFI_SUCCESS;\r
1278 }\r
1279 }\r
7936fb6a 1280\r
1281 //\r
1282 // Question value is provided by RTC\r
1283 //\r
1284 Storage = Question->Storage;\r
1285 QuestionValue = &Question->HiiValue.Value;\r
1286 if (Storage == NULL) {\r
1287 //\r
1288 // It's a Question without storage, or RTC date/time\r
1289 //\r
1290 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1291 //\r
1292 // Date and time define the same Flags bit\r
1293 //\r
1294 switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
1295 case QF_DATE_STORAGE_TIME:\r
1296 Status = gRT->GetTime (&EfiTime, NULL);\r
1297 break;\r
1298\r
1299 case QF_DATE_STORAGE_WAKEUP:\r
1300 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
1301 break;\r
1302\r
1303 case QF_DATE_STORAGE_NORMAL:\r
1304 default:\r
1305 //\r
1306 // For date/time without storage\r
1307 //\r
1308 return EFI_SUCCESS;\r
1309 }\r
1310\r
1311 if (EFI_ERROR (Status)) {\r
1312 return Status;\r
1313 }\r
1314\r
1315 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1316 QuestionValue->date.Year = EfiTime.Year;\r
1317 QuestionValue->date.Month = EfiTime.Month;\r
1318 QuestionValue->date.Day = EfiTime.Day;\r
1319 } else {\r
1320 QuestionValue->time.Hour = EfiTime.Hour;\r
1321 QuestionValue->time.Minute = EfiTime.Minute;\r
1322 QuestionValue->time.Second = EfiTime.Second;\r
1323 }\r
1324 }\r
1325\r
1326 return EFI_SUCCESS;\r
1327 }\r
1328\r
1329 //\r
1330 // Question value is provided by EFI variable\r
1331 //\r
1332 StorageWidth = Question->StorageWidth;\r
1333 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1334 if (Question->BufferValue != NULL) {\r
1335 Dst = Question->BufferValue;\r
1336 } else {\r
1337 Dst = (UINT8 *) QuestionValue;\r
1338 }\r
1339\r
1340 Status = gRT->GetVariable (\r
1341 Question->VariableName,\r
1342 &Storage->Guid,\r
1343 NULL,\r
1344 &StorageWidth,\r
1345 Dst\r
1346 );\r
1347 //\r
1348 // Always return success, even this EFI variable doesn't exist\r
1349 //\r
1350 return EFI_SUCCESS;\r
1351 }\r
1352\r
1353 //\r
1354 // Question Value is provided by Buffer Storage or NameValue Storage\r
1355 //\r
1356 if (Question->BufferValue != NULL) {\r
1357 //\r
1358 // This Question is password or orderedlist\r
1359 //\r
1360 Dst = Question->BufferValue;\r
1361 } else {\r
1362 //\r
1363 // Other type of Questions\r
1364 //\r
1365 Dst = (UINT8 *) &Question->HiiValue.Value;\r
1366 }\r
1367\r
cce6230f
ED
1368 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
1369 Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
1370 IsBufferStorage = TRUE;\r
1371 } else {\r
1372 IsBufferStorage = FALSE;\r
1373 }\r
7936fb6a 1374 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
1375 if (Cached) {\r
1376 if (IsBufferStorage) {\r
1377 //\r
1378 // Copy from storage Edit buffer\r
1379 //\r
1380 CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
1381 } else {\r
1b2bf3ca 1382 Value = NULL;\r
7936fb6a 1383 Status = GetValueByName (Storage, Question->VariableName, &Value);\r
1384 if (EFI_ERROR (Status)) {\r
1385 return Status;\r
1386 }\r
d66e6c16 1387\r
1b2bf3ca 1388 ASSERT (Value != NULL);\r
63d55bb9
LG
1389 LengthStr = StrLen (Value);\r
1390 Status = EFI_SUCCESS;\r
7936fb6a 1391 if (IsString) {\r
1392 //\r
1393 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
63d55bb9 1394 // Add string tail char L'\0' into Length\r
7936fb6a 1395 //\r
63d55bb9
LG
1396 Length = StorageWidth + sizeof (CHAR16);\r
1397 if (Length < ((LengthStr / 4 + 1) * 2)) {\r
1398 Status = EFI_BUFFER_TOO_SMALL;\r
1399 } else {\r
1400 StringPtr = (CHAR16 *) Dst;\r
1401 ZeroMem (TemStr, sizeof (TemStr));\r
1402 for (Index = 0; Index < LengthStr; Index += 4) {\r
1403 StrnCpy (TemStr, Value + Index, 4);\r
1404 StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
1405 }\r
1406 //\r
1407 // Add tailing L'\0' character\r
1408 //\r
1409 StringPtr[Index/4] = L'\0';\r
1410 }\r
7936fb6a 1411 } else {\r
63d55bb9
LG
1412 if (StorageWidth < ((LengthStr + 1) / 2)) {\r
1413 Status = EFI_BUFFER_TOO_SMALL;\r
1414 } else {\r
1415 ZeroMem (TemStr, sizeof (TemStr));\r
1416 for (Index = 0; Index < LengthStr; Index ++) {\r
1417 TemStr[0] = Value[LengthStr - Index - 1];\r
1418 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
1419 if ((Index & 1) == 0) {\r
1420 Dst [Index/2] = DigitUint8;\r
1421 } else {\r
634303c9 1422 Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
63d55bb9
LG
1423 }\r
1424 }\r
1425 }\r
7936fb6a 1426 }\r
1427\r
f4113e1f 1428 FreePool (Value);\r
7936fb6a 1429 }\r
1430 } else {\r
cce6230f
ED
1431 if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {\r
1432 //\r
1433 // Request current settings from Configuration Driver\r
1434 //\r
1435 if (FormSet->ConfigAccess == NULL) {\r
1436 return EFI_NOT_FOUND;\r
1437 }\r
7936fb6a 1438\r
cce6230f
ED
1439 //\r
1440 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
1441 // <ConfigHdr> + "&" + <VariableName>\r
1442 //\r
1443 if (IsBufferStorage) {\r
1444 Length = StrLen (Storage->ConfigHdr);\r
1445 Length += StrLen (Question->BlockName);\r
1446 } else {\r
1447 Length = StrLen (Storage->ConfigHdr);\r
1448 Length += StrLen (Question->VariableName) + 1;\r
1449 }\r
1450 ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
1451 ASSERT (ConfigRequest != NULL);\r
7936fb6a 1452\r
cce6230f
ED
1453 StrCpy (ConfigRequest, Storage->ConfigHdr);\r
1454 if (IsBufferStorage) {\r
1455 StrCat (ConfigRequest, Question->BlockName);\r
1456 } else {\r
1457 StrCat (ConfigRequest, L"&");\r
1458 StrCat (ConfigRequest, Question->VariableName);\r
1459 }\r
7936fb6a 1460\r
cce6230f
ED
1461 Status = FormSet->ConfigAccess->ExtractConfig (\r
1462 FormSet->ConfigAccess,\r
1463 ConfigRequest,\r
1464 &Progress,\r
1465 &Result\r
1466 );\r
1467 FreePool (ConfigRequest);\r
1468 if (EFI_ERROR (Status)) {\r
1469 return Status;\r
1470 }\r
7936fb6a 1471\r
7936fb6a 1472 //\r
cce6230f 1473 // Skip <ConfigRequest>\r
7936fb6a 1474 //\r
cce6230f 1475 if (IsBufferStorage) {\r
e4f95ca5
ED
1476 Value = StrStr (Result, L"&VALUE");\r
1477 if (Value == NULL) {\r
1478 FreePool (Result);\r
1479 return EFI_NOT_FOUND;\r
1480 }\r
cce6230f
ED
1481 //\r
1482 // Skip "&VALUE"\r
1483 //\r
1484 Value = Value + 6;\r
e4f95ca5
ED
1485 } else {\r
1486 Value = Result + Length;\r
cce6230f
ED
1487 }\r
1488 if (*Value != '=') {\r
1489 FreePool (Result);\r
1490 return EFI_NOT_FOUND;\r
1491 }\r
1492 //\r
1493 // Skip '=', point to value\r
1494 //\r
1495 Value = Value + 1;\r
8d00a0f1 1496\r
7936fb6a 1497 //\r
cce6230f 1498 // Suppress <AltResp> if any\r
7936fb6a 1499 //\r
cce6230f
ED
1500 StringPtr = Value;\r
1501 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
1502 StringPtr++;\r
1503 }\r
1504 *StringPtr = L'\0';\r
1505\r
1506 LengthStr = StrLen (Value);\r
1507 Status = EFI_SUCCESS;\r
1508 if (!IsBufferStorage && IsString) {\r
63d55bb9 1509 //\r
cce6230f
ED
1510 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
1511 // Add string tail char L'\0' into Length\r
63d55bb9 1512 //\r
cce6230f
ED
1513 Length = StorageWidth + sizeof (CHAR16);\r
1514 if (Length < ((LengthStr / 4 + 1) * 2)) {\r
1515 Status = EFI_BUFFER_TOO_SMALL;\r
1516 } else {\r
1517 StringPtr = (CHAR16 *) Dst;\r
1518 ZeroMem (TemStr, sizeof (TemStr));\r
1519 for (Index = 0; Index < LengthStr; Index += 4) {\r
1520 StrnCpy (TemStr, Value + Index, 4);\r
1521 StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
1522 }\r
1523 //\r
1524 // Add tailing L'\0' character\r
1525 //\r
1526 StringPtr[Index/4] = L'\0';\r
1527 }\r
63d55bb9 1528 } else {\r
cce6230f
ED
1529 if (StorageWidth < ((LengthStr + 1) / 2)) {\r
1530 Status = EFI_BUFFER_TOO_SMALL;\r
1531 } else {\r
1532 ZeroMem (TemStr, sizeof (TemStr));\r
1533 for (Index = 0; Index < LengthStr; Index ++) {\r
1534 TemStr[0] = Value[LengthStr - Index - 1];\r
1535 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
1536 if ((Index & 1) == 0) {\r
1537 Dst [Index/2] = DigitUint8;\r
1538 } else {\r
1539 Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
1540 }\r
63d55bb9
LG
1541 }\r
1542 }\r
7936fb6a 1543 }\r
63d55bb9 1544 FreePool (Result);\r
cce6230f
ED
1545\r
1546 if (EFI_ERROR (Status)) {\r
1547 return Status;\r
1548 }\r
1549 } else if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
1550 TemBuffer = NULL;\r
1551 TemBuffer = AllocateZeroPool (Storage->Size);\r
1552 if (TemBuffer == NULL) {\r
1553 Status = EFI_OUT_OF_RESOURCES;\r
1554 return Status;\r
1555 }\r
1556 Length = Storage->Size;\r
1557 Status = gRT->GetVariable (\r
1558 Storage->Name,\r
1559 &Storage->Guid,\r
1560 NULL,\r
1561 &Length,\r
1562 TemBuffer\r
1563 );\r
1564 if (EFI_ERROR (Status)) {\r
1565 FreePool (TemBuffer);\r
1566 return Status;\r
1567 }\r
1568\r
1569 CopyMem (Dst, TemBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
1570\r
1571 FreePool (TemBuffer);\r
63d55bb9
LG
1572 }\r
1573\r
7936fb6a 1574 //\r
1575 // Synchronize Edit Buffer\r
1576 //\r
1577 if (IsBufferStorage) {\r
1578 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
1579 } else {\r
b18e7050 1580 SetValueByName (Storage, Question->VariableName, Value, TRUE);\r
7936fb6a 1581 }\r
7936fb6a 1582 }\r
1583\r
1584 return Status;\r
1585}\r
1586\r
1587\r
1588/**\r
1589 Save Question Value to edit copy(cached) or Storage(uncached).\r
1590\r
1591 @param FormSet FormSet data structure.\r
1592 @param Form Form data structure.\r
1593 @param Question Pointer to the Question.\r
1594 @param Cached TRUE: set to Edit copy FALSE: set to original\r
1595 Storage\r
1596\r
1597 @retval EFI_SUCCESS The function completed successfully.\r
1598\r
1599**/\r
1600EFI_STATUS\r
1601SetQuestionValue (\r
1602 IN FORM_BROWSER_FORMSET *FormSet,\r
1603 IN FORM_BROWSER_FORM *Form,\r
1604 IN OUT FORM_BROWSER_STATEMENT *Question,\r
1605 IN BOOLEAN Cached\r
1606 )\r
1607{\r
1608 EFI_STATUS Status;\r
1609 BOOLEAN Enabled;\r
1610 BOOLEAN Pending;\r
1611 UINT8 *Src;\r
1612 EFI_TIME EfiTime;\r
1613 UINTN BufferLen;\r
1614 UINTN StorageWidth;\r
1615 FORMSET_STORAGE *Storage;\r
1616 EFI_IFR_TYPE_VALUE *QuestionValue;\r
1617 CHAR16 *ConfigResp;\r
1618 CHAR16 *Progress;\r
1619 CHAR16 *Value;\r
1620 UINTN Length;\r
1621 BOOLEAN IsBufferStorage;\r
1622 BOOLEAN IsString;\r
63d55bb9
LG
1623 UINT8 *TemBuffer;\r
1624 CHAR16 *TemName;\r
1625 CHAR16 *TemString;\r
1626 UINTN Index;\r
7936fb6a 1627\r
1628 Status = EFI_SUCCESS;\r
1629\r
1630 //\r
1631 // Statement don't have storage, skip them\r
1632 //\r
1633 if (Question->QuestionId == 0) {\r
1634 return Status;\r
1635 }\r
1636\r
1637 //\r
1638 // If Question value is provided by an Expression, then it is read only\r
1639 //\r
1640 if (Question->ValueExpression != NULL) {\r
1641 return Status;\r
1642 }\r
2573712e
LG
1643 \r
1644 //\r
1645 // Before set question value, evaluate its write expression.\r
1646 //\r
1647 if (Question->WriteExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {\r
1648 Status = EvaluateExpression (FormSet, Form, Question->WriteExpression);\r
1649 if (EFI_ERROR (Status)) {\r
1650 return Status;\r
1651 }\r
1652 }\r
7936fb6a 1653\r
1654 //\r
1655 // Question value is provided by RTC\r
1656 //\r
1657 Storage = Question->Storage;\r
1658 QuestionValue = &Question->HiiValue.Value;\r
1659 if (Storage == NULL) {\r
1660 //\r
1661 // It's a Question without storage, or RTC date/time\r
1662 //\r
1663 if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1664 //\r
1665 // Date and time define the same Flags bit\r
1666 //\r
1667 switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
1668 case QF_DATE_STORAGE_TIME:\r
1669 Status = gRT->GetTime (&EfiTime, NULL);\r
1670 break;\r
1671\r
1672 case QF_DATE_STORAGE_WAKEUP:\r
1673 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
1674 break;\r
1675\r
1676 case QF_DATE_STORAGE_NORMAL:\r
1677 default:\r
1678 //\r
1679 // For date/time without storage\r
1680 //\r
1681 return EFI_SUCCESS;\r
1682 }\r
1683\r
1684 if (EFI_ERROR (Status)) {\r
1685 return Status;\r
1686 }\r
1687\r
1688 if (Question->Operand == EFI_IFR_DATE_OP) {\r
1689 EfiTime.Year = QuestionValue->date.Year;\r
1690 EfiTime.Month = QuestionValue->date.Month;\r
1691 EfiTime.Day = QuestionValue->date.Day;\r
1692 } else {\r
1693 EfiTime.Hour = QuestionValue->time.Hour;\r
1694 EfiTime.Minute = QuestionValue->time.Minute;\r
1695 EfiTime.Second = QuestionValue->time.Second;\r
1696 }\r
1697\r
1698 if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {\r
1699 Status = gRT->SetTime (&EfiTime);\r
1700 } else {\r
1701 Status = gRT->SetWakeupTime (TRUE, &EfiTime);\r
1702 }\r
1703 }\r
1704\r
1705 return Status;\r
1706 }\r
1707\r
1708 //\r
1709 // Question value is provided by EFI variable\r
1710 //\r
1711 StorageWidth = Question->StorageWidth;\r
1712 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
1713 if (Question->BufferValue != NULL) {\r
1714 Src = Question->BufferValue;\r
1715 } else {\r
1716 Src = (UINT8 *) QuestionValue;\r
1717 }\r
1718\r
1719 Status = gRT->SetVariable (\r
1720 Question->VariableName,\r
1721 &Storage->Guid,\r
1722 Storage->Attributes,\r
1723 StorageWidth,\r
1724 Src\r
1725 );\r
1726 return Status;\r
1727 }\r
1728\r
1729 //\r
1730 // Question Value is provided by Buffer Storage or NameValue Storage\r
1731 //\r
1732 if (Question->BufferValue != NULL) {\r
1733 Src = Question->BufferValue;\r
1734 } else {\r
1735 Src = (UINT8 *) &Question->HiiValue.Value;\r
1736 }\r
1737\r
cce6230f
ED
1738 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
1739 Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
1740 IsBufferStorage = TRUE;\r
1741 } else {\r
1742 IsBufferStorage = FALSE;\r
1743 }\r
7936fb6a 1744 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
1745 if (IsBufferStorage) {\r
1746 //\r
1747 // Copy to storage edit buffer\r
1748 //\r
1749 CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
1750 } else {\r
1751 if (IsString) {\r
1752 //\r
63d55bb9 1753 // Allocate enough string buffer.\r
7936fb6a 1754 //\r
1755 Value = NULL;\r
1756 BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
1757 Value = AllocateZeroPool (BufferLen);\r
1758 ASSERT (Value != NULL);\r
63d55bb9
LG
1759 //\r
1760 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
1761 //\r
1762 TemName = (CHAR16 *) Src;\r
1763 TemString = Value;\r
1764 for (; *TemName != L'\0'; TemName++) {\r
1765 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
1766 }\r
7936fb6a 1767 } else {\r
1768 BufferLen = StorageWidth * 2 + 1;\r
1769 Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
1770 ASSERT (Value != NULL);\r
63d55bb9
LG
1771 //\r
1772 // Convert Buffer to Hex String\r
1773 //\r
1774 TemBuffer = Src + StorageWidth - 1;\r
1775 TemString = Value;\r
1776 for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
1777 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
1778 }\r
7936fb6a 1779 }\r
1780\r
b18e7050 1781 Status = SetValueByName (Storage, Question->VariableName, Value, TRUE);\r
f4113e1f 1782 FreePool (Value);\r
7936fb6a 1783 }\r
1784\r
1785 if (!Cached) {\r
cce6230f
ED
1786 if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {\r
1787 //\r
1788 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||\r
1789 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"\r
1790 //\r
1791 if (IsBufferStorage) {\r
1792 Length = StrLen (Question->BlockName) + 7;\r
1793 } else {\r
1794 Length = StrLen (Question->VariableName) + 2;\r
1795 }\r
1796 if (!IsBufferStorage && IsString) {\r
1797 Length += (StrLen ((CHAR16 *) Src) * 4);\r
1798 } else {\r
1799 Length += (StorageWidth * 2);\r
1800 }\r
1801 ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16));\r
1802 ASSERT (ConfigResp != NULL);\r
7936fb6a 1803\r
cce6230f
ED
1804 StrCpy (ConfigResp, Storage->ConfigHdr);\r
1805 if (IsBufferStorage) {\r
1806 StrCat (ConfigResp, Question->BlockName);\r
1807 StrCat (ConfigResp, L"&VALUE=");\r
1808 } else {\r
1809 StrCat (ConfigResp, L"&");\r
1810 StrCat (ConfigResp, Question->VariableName);\r
1811 StrCat (ConfigResp, L"=");\r
1812 }\r
1813\r
1814 Value = ConfigResp + StrLen (ConfigResp);\r
7936fb6a 1815\r
cce6230f
ED
1816 if (!IsBufferStorage && IsString) {\r
1817 //\r
1818 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
1819 //\r
1820 TemName = (CHAR16 *) Src;\r
1821 TemString = Value;\r
1822 for (; *TemName != L'\0'; TemName++) {\r
1823 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
1824 }\r
1825 } else {\r
1826 //\r
1827 // Convert Buffer to Hex String\r
1828 //\r
1829 TemBuffer = Src + StorageWidth - 1;\r
1830 TemString = Value;\r
1831 for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
1832 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
1833 }\r
1834 }\r
63d55bb9 1835\r
7936fb6a 1836 //\r
cce6230f 1837 // Convert to lower char.\r
7936fb6a 1838 //\r
cce6230f
ED
1839 for (TemString = Value; *Value != L'\0'; Value++) {\r
1840 if (*Value >= L'A' && *Value <= L'Z') {\r
1841 *Value = (CHAR16) (*Value - L'A' + L'a');\r
1842 }\r
63d55bb9 1843 }\r
cce6230f 1844\r
63d55bb9 1845 //\r
cce6230f 1846 // Submit Question Value to Configuration Driver\r
63d55bb9 1847 //\r
cce6230f
ED
1848 if (FormSet->ConfigAccess != NULL) {\r
1849 Status = FormSet->ConfigAccess->RouteConfig (\r
1850 FormSet->ConfigAccess,\r
1851 ConfigResp,\r
1852 &Progress\r
1853 );\r
1854 if (EFI_ERROR (Status)) {\r
1855 FreePool (ConfigResp);\r
1856 return Status;\r
1857 }\r
63d55bb9 1858 }\r
cce6230f
ED
1859 FreePool (ConfigResp);\r
1860 \r
1861 } else if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
1862 TemBuffer = NULL;\r
1863 TemBuffer = AllocateZeroPool(Storage->Size);\r
1864 if (TemBuffer == NULL) {\r
1865 Status = EFI_OUT_OF_RESOURCES;\r
1866 return Status;\r
63d55bb9 1867 }\r
cce6230f
ED
1868 Length = Storage->Size;\r
1869 Status = gRT->GetVariable (\r
1870 Storage->Name,\r
1871 &Storage->Guid,\r
1872 NULL,\r
1873 &Length,\r
1874 TemBuffer\r
1875 );\r
7936fb6a 1876\r
cce6230f
ED
1877 CopyMem (TemBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
1878 \r
1879 Status = gRT->SetVariable (\r
1880 Storage->Name,\r
1881 &Storage->Guid,\r
1882 Storage->Attributes,\r
1883 Storage->Size,\r
1884 TemBuffer\r
1885 );\r
1886 FreePool (TemBuffer);\r
1887 if (EFI_ERROR (Status)){\r
7936fb6a 1888 return Status;\r
1889 }\r
1890 }\r
7936fb6a 1891 //\r
cce6230f 1892 // Sync storage, from editbuffer to buffer.\r
7936fb6a 1893 //\r
cce6230f 1894 CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
7936fb6a 1895 }\r
1896\r
1897 return Status;\r
1898}\r
1899\r
1900\r
1901/**\r
1902 Perform inconsistent check for a Form.\r
1903\r
1904 @param FormSet FormSet data structure.\r
1905 @param Form Form data structure.\r
1906 @param Question The Question to be validated.\r
1907 @param Type Validation type: InConsistent or NoSubmit\r
1908\r
1909 @retval EFI_SUCCESS Form validation pass.\r
1910 @retval other Form validation failed.\r
1911\r
1912**/\r
1913EFI_STATUS\r
1914ValidateQuestion (\r
1915 IN FORM_BROWSER_FORMSET *FormSet,\r
1916 IN FORM_BROWSER_FORM *Form,\r
1917 IN FORM_BROWSER_STATEMENT *Question,\r
1918 IN UINTN Type\r
1919 )\r
1920{\r
1921 EFI_STATUS Status;\r
1922 LIST_ENTRY *Link;\r
1923 LIST_ENTRY *ListHead;\r
1924 EFI_STRING PopUp;\r
1925 EFI_INPUT_KEY Key;\r
1926 FORM_EXPRESSION *Expression;\r
1927\r
1928 if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {\r
1929 ListHead = &Question->InconsistentListHead;\r
1930 } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
1931 ListHead = &Question->NoSubmitListHead;\r
1932 } else {\r
1933 return EFI_UNSUPPORTED;\r
1934 }\r
1935\r
1936 Link = GetFirstNode (ListHead);\r
1937 while (!IsNull (ListHead, Link)) {\r
1938 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
1939\r
1940 //\r
1941 // Evaluate the expression\r
1942 //\r
1943 Status = EvaluateExpression (FormSet, Form, Expression);\r
1944 if (EFI_ERROR (Status)) {\r
1945 return Status;\r
1946 }\r
1947\r
1948 if (Expression->Result.Value.b) {\r
1949 //\r
1950 // Condition meet, show up error message\r
1951 //\r
1952 if (Expression->Error != 0) {\r
1953 PopUp = GetToken (Expression->Error, FormSet->HiiHandle);\r
1954 do {\r
1955 CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);\r
1956 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
f4113e1f 1957 FreePool (PopUp);\r
7936fb6a 1958 }\r
1959\r
1960 return EFI_NOT_READY;\r
1961 }\r
1962\r
1963 Link = GetNextNode (ListHead, Link);\r
1964 }\r
1965\r
1966 return EFI_SUCCESS;\r
1967}\r
1968\r
1969\r
1970/**\r
5adb8db7 1971 Perform NoSubmit check for each Form in FormSet.\r
7936fb6a 1972\r
1973 @param FormSet FormSet data structure.\r
b18e7050 1974 @param CurrentForm Current input form data structure.\r
7936fb6a 1975\r
1976 @retval EFI_SUCCESS Form validation pass.\r
1977 @retval other Form validation failed.\r
1978\r
1979**/\r
1980EFI_STATUS\r
1981NoSubmitCheck (\r
b18e7050
ED
1982 IN FORM_BROWSER_FORMSET *FormSet,\r
1983 IN FORM_BROWSER_FORM *CurrentForm\r
7936fb6a 1984 )\r
1985{\r
1986 EFI_STATUS Status;\r
1987 LIST_ENTRY *Link;\r
1988 FORM_BROWSER_STATEMENT *Question;\r
5adb8db7
LG
1989 FORM_BROWSER_FORM *Form;\r
1990 LIST_ENTRY *LinkForm;\r
7936fb6a 1991\r
5adb8db7
LG
1992 LinkForm = GetFirstNode (&FormSet->FormListHead);\r
1993 while (!IsNull (&FormSet->FormListHead, LinkForm)) {\r
1994 Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);\r
b18e7050
ED
1995 LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);\r
1996\r
1997 if (CurrentForm != NULL && CurrentForm != Form) {\r
1998 continue;\r
1999 }\r
7936fb6a 2000\r
5adb8db7
LG
2001 Link = GetFirstNode (&Form->StatementListHead);\r
2002 while (!IsNull (&Form->StatementListHead, Link)) {\r
2003 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
2004\r
2005 Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);\r
2006 if (EFI_ERROR (Status)) {\r
2007 return Status;\r
2008 }\r
2009\r
2010 Link = GetNextNode (&Form->StatementListHead, Link);\r
7936fb6a 2011 }\r
7936fb6a 2012 }\r
2013\r
2014 return EFI_SUCCESS;\r
2015}\r
2016\r
7936fb6a 2017/**\r
b18e7050
ED
2018 Fill storage's edit copy with settings requested from Configuration Driver.\r
2019\r
2020 @param FormSet FormSet data structure.\r
2021 @param ConfigInfo The config info related to this form.\r
cce6230f
ED
2022 @param SyncOrRestore Sync the buffer to editbuffer or Restore the \r
2023 editbuffer to buffer\r
2024 if TRUE, copy the editbuffer to the buffer.\r
2025 if FALSE, copy the buffer to the editbuffer.\r
b18e7050
ED
2026\r
2027 @retval EFI_SUCCESS The function completed successfully.\r
2028\r
2029**/\r
2030EFI_STATUS\r
cce6230f 2031SynchronizeStorageForForm (\r
b18e7050 2032 IN FORM_BROWSER_FORMSET *FormSet,\r
cce6230f
ED
2033 IN FORM_BROWSER_CONFIG_REQUEST *ConfigInfo,\r
2034 IN BOOLEAN SyncOrRestore\r
b18e7050
ED
2035 )\r
2036{\r
2037 EFI_STATUS Status;\r
2038 EFI_STRING Progress;\r
2039 EFI_STRING Result;\r
2040 UINTN BufferSize;\r
2041 LIST_ENTRY *Link;\r
2042 NAME_VALUE_NODE *Node;\r
cce6230f
ED
2043 UINT8 *Src;\r
2044 UINT8 *Dst;\r
b18e7050
ED
2045\r
2046 Status = EFI_SUCCESS;\r
2047 Result = NULL;\r
cce6230f 2048 if (FormSet->ConfigAccess == NULL && ConfigInfo->Storage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
b18e7050
ED
2049 return EFI_NOT_FOUND;\r
2050 }\r
2051\r
2052 if (ConfigInfo->ElementCount == 0) {\r
2053 //\r
2054 // Skip if there is no RequestElement\r
2055 //\r
2056 return EFI_SUCCESS;\r
2057 }\r
2058\r
cce6230f
ED
2059 if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
2060 (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
b18e7050 2061 BufferSize = ConfigInfo->Storage->Size;\r
cce6230f
ED
2062\r
2063 if (SyncOrRestore) {\r
2064 Src = ConfigInfo->Storage->EditBuffer;\r
2065 Dst = ConfigInfo->Storage->Buffer;\r
2066 } else {\r
2067 Src = ConfigInfo->Storage->Buffer;\r
2068 Dst = ConfigInfo->Storage->EditBuffer;\r
2069 }\r
2070\r
b18e7050
ED
2071 Status = mHiiConfigRouting->BlockToConfig(\r
2072 mHiiConfigRouting,\r
2073 ConfigInfo->ConfigRequest,\r
cce6230f 2074 Src,\r
b18e7050
ED
2075 BufferSize,\r
2076 &Result,\r
2077 &Progress\r
2078 );\r
2079 if (EFI_ERROR (Status)) {\r
2080 return Status;\r
2081 }\r
2082\r
2083 Status = mHiiConfigRouting->ConfigToBlock (\r
2084 mHiiConfigRouting,\r
2085 Result,\r
cce6230f 2086 Dst,\r
b18e7050
ED
2087 &BufferSize,\r
2088 &Progress\r
2089 );\r
2090 if (Result != NULL) {\r
2091 FreePool (Result);\r
2092 }\r
b18e7050
ED
2093 } else if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2094 Link = GetFirstNode (&ConfigInfo->Storage->NameValueListHead);\r
2095 while (!IsNull (&ConfigInfo->Storage->NameValueListHead, Link)) {\r
2096 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
2097\r
2098 if (StrStr (ConfigInfo->ConfigRequest, Node->Name) != NULL) {\r
cce6230f
ED
2099 if (SyncOrRestore) {\r
2100 NewStringCpy (&Node->Value, Node->EditValue);\r
2101 } else {\r
2102 NewStringCpy (&Node->EditValue, Node->Value);\r
b18e7050 2103 }\r
b18e7050
ED
2104 }\r
2105\r
2106 Link = GetNextNode (&ConfigInfo->Storage->NameValueListHead, Link);\r
2107 }\r
2108 }\r
2109\r
2110 return Status;\r
2111}\r
2112\r
2113\r
2114/**\r
48a9d5f7 2115 Discard data based on the input setting scope (Form, FormSet or System).\r
7936fb6a 2116\r
2117 @param FormSet FormSet data structure.\r
2118 @param Form Form data structure.\r
48a9d5f7 2119 @param SettingScope Setting Scope for Discard action.\r
b18e7050
ED
2120\r
2121 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 2122 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
b18e7050
ED
2123\r
2124**/\r
2125EFI_STATUS\r
2126DiscardForm (\r
2127 IN FORM_BROWSER_FORMSET *FormSet,\r
2128 IN FORM_BROWSER_FORM *Form,\r
48a9d5f7 2129 IN BROWSER_SETTING_SCOPE SettingScope\r
b18e7050
ED
2130 )\r
2131{\r
48a9d5f7
LG
2132 LIST_ENTRY *Link;\r
2133 FORMSET_STORAGE *Storage;\r
b18e7050 2134 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
48a9d5f7 2135 FORM_BROWSER_FORMSET *LocalFormSet;\r
b18e7050 2136\r
48a9d5f7
LG
2137 //\r
2138 // Check the supported setting level.\r
2139 //\r
2140 if (SettingScope >= MaxLevel) {\r
2141 return EFI_UNSUPPORTED;\r
2142 }\r
b18e7050 2143\r
48a9d5f7
LG
2144 if (SettingScope == FormLevel && Form->NvUpdateRequired) {\r
2145 ConfigInfo = NULL;\r
2146 Link = GetFirstNode (&Form->ConfigRequestHead);\r
2147 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
2148 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
2149 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
b18e7050 2150\r
48a9d5f7
LG
2151 if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2152 continue;\r
2153 }\r
2154\r
2155 //\r
2156 // Skip if there is no RequestElement\r
2157 //\r
2158 if (ConfigInfo->ElementCount == 0) {\r
2159 continue;\r
b18e7050
ED
2160 }\r
2161\r
48a9d5f7
LG
2162 //\r
2163 // Prepare <ConfigResp>\r
2164 //\r
2165 SynchronizeStorageForForm(FormSet, ConfigInfo, FALSE);\r
b18e7050 2166 }\r
48a9d5f7
LG
2167\r
2168 Form->NvUpdateRequired = FALSE;\r
2169 } else if (SettingScope == FormSetLevel && IsNvUpdateRequired(FormSet)) {\r
2170 //\r
2171 // Discard Buffer storage or Name/Value storage\r
2172 //\r
2173 Link = GetFirstNode (&FormSet->StorageListHead);\r
2174 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
2175 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
2176 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
2177\r
2178 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2179 continue;\r
2180 }\r
2181\r
b18e7050 2182 //\r
48a9d5f7 2183 // Skip if there is no RequestElement\r
b18e7050 2184 //\r
48a9d5f7
LG
2185 if (Storage->ElementCount == 0) {\r
2186 continue;\r
2187 }\r
b18e7050 2188\r
48a9d5f7
LG
2189 SynchronizeStorage(Storage, FALSE);\r
2190 }\r
b18e7050 2191\r
48a9d5f7
LG
2192 UpdateNvInfoInForm (FormSet, FALSE); \r
2193 } else if (SettingScope == SystemLevel) {\r
2194 //\r
2195 // System Level Discard.\r
2196 //\r
2197 \r
2198 //\r
2199 // Discard changed value for each FormSet in the maintain list.\r
2200 //\r
2201 Link = GetFirstNode (&gBrowserFormSetList);\r
2202 while (!IsNull (&gBrowserFormSetList, Link)) {\r
2203 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
2204 DiscardForm (LocalFormSet, NULL, FormSetLevel);\r
2205 Link = GetNextNode (&gBrowserFormSetList, Link);\r
2206 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
b18e7050 2207 //\r
48a9d5f7 2208 // Remove maintain backup list after discard except for the current using FormSet.\r
b18e7050 2209 //\r
48a9d5f7
LG
2210 RemoveEntryList (&LocalFormSet->Link);\r
2211 DestroyFormSet (LocalFormSet);\r
b18e7050 2212 }\r
b18e7050
ED
2213 }\r
2214 }\r
2215\r
2216 return EFI_SUCCESS; \r
2217}\r
2218\r
2219/**\r
48a9d5f7 2220 Submit data based on the input Setting level (Form, FormSet or System).\r
b18e7050
ED
2221\r
2222 @param FormSet FormSet data structure.\r
2223 @param Form Form data structure.\r
48a9d5f7 2224 @param SettingScope Setting Scope for Submit action.\r
7936fb6a 2225\r
2226 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 2227 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
7936fb6a 2228\r
2229**/\r
2230EFI_STATUS\r
2231SubmitForm (\r
2232 IN FORM_BROWSER_FORMSET *FormSet,\r
b18e7050 2233 IN FORM_BROWSER_FORM *Form,\r
48a9d5f7 2234 IN BROWSER_SETTING_SCOPE SettingScope\r
7936fb6a 2235 )\r
2236{\r
2237 EFI_STATUS Status;\r
2238 LIST_ENTRY *Link;\r
2239 EFI_STRING ConfigResp;\r
2240 EFI_STRING Progress;\r
2241 FORMSET_STORAGE *Storage;\r
cce6230f 2242 UINTN BufferSize;\r
48a9d5f7
LG
2243 UINT8 *TmpBuf; \r
2244 FORM_BROWSER_FORMSET *LocalFormSet;\r
b18e7050 2245 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;\r
7936fb6a 2246\r
48a9d5f7
LG
2247 //\r
2248 // Check the supported setting level.\r
2249 //\r
2250 if (SettingScope >= MaxLevel) {\r
2251 return EFI_UNSUPPORTED;\r
2252 }\r
2253\r
7936fb6a 2254 //\r
2255 // Validate the Form by NoSubmit check\r
2256 //\r
48a9d5f7
LG
2257 Status = EFI_SUCCESS;\r
2258 if (SettingScope == FormLevel) {\r
b18e7050 2259 Status = NoSubmitCheck (FormSet, Form);\r
48a9d5f7 2260 } else if (SettingScope == FormSetLevel) {\r
b18e7050
ED
2261 Status = NoSubmitCheck (FormSet, NULL);\r
2262 }\r
7936fb6a 2263 if (EFI_ERROR (Status)) {\r
2264 return Status;\r
2265 }\r
2266\r
48a9d5f7 2267 if (SettingScope == FormLevel && Form->NvUpdateRequired) {\r
b18e7050
ED
2268 ConfigInfo = NULL;\r
2269 Link = GetFirstNode (&Form->ConfigRequestHead);\r
2270 while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
2271 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
2272 Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
7936fb6a 2273\r
cce6230f
ED
2274 Storage = ConfigInfo->Storage;\r
2275 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
b18e7050
ED
2276 continue;\r
2277 }\r
7936fb6a 2278\r
b18e7050
ED
2279 //\r
2280 // Skip if there is no RequestElement\r
2281 //\r
2282 if (ConfigInfo->ElementCount == 0) {\r
2283 continue;\r
2284 }\r
7936fb6a 2285\r
b18e7050 2286 //\r
cce6230f 2287 // 1. Prepare <ConfigResp>\r
b18e7050
ED
2288 //\r
2289 Status = StorageToConfigResp (ConfigInfo, &ConfigResp, TRUE);\r
2290 if (EFI_ERROR (Status)) {\r
2291 return Status;\r
2292 }\r
2293\r
2294 //\r
cce6230f 2295 // 2. Set value to hii driver or efi variable.\r
b18e7050 2296 //\r
cce6230f
ED
2297 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
2298 Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2299 //\r
2300 // Send <ConfigResp> to Configuration Driver\r
2301 //\r
2302 if (FormSet->ConfigAccess != NULL) {\r
2303 Status = FormSet->ConfigAccess->RouteConfig (\r
2304 FormSet->ConfigAccess,\r
2305 ConfigResp,\r
2306 &Progress\r
2307 );\r
2308 if (EFI_ERROR (Status)) {\r
2309 FreePool (ConfigResp);\r
2310 return Status;\r
2311 }\r
2312 }\r
2313 } else if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
2314 TmpBuf = NULL;\r
2315 TmpBuf = AllocateZeroPool(Storage->Size);\r
2316 if (TmpBuf == NULL) {\r
2317 Status = EFI_OUT_OF_RESOURCES;\r
2318 return Status;\r
2319 }\r
2320\r
2321 BufferSize = Storage->Size;\r
2322 Status = gRT->GetVariable (\r
2323 Storage->Name,\r
2324 &Storage->Guid,\r
2325 NULL,\r
2326 &BufferSize,\r
2327 TmpBuf\r
2328 );\r
2329 if (EFI_ERROR (Status)) {\r
2330 FreePool (TmpBuf);\r
2331 FreePool (ConfigResp);\r
2332 return Status;\r
2333 }\r
2334 ASSERT (BufferSize == Storage->Size); \r
2335 Status = mHiiConfigRouting->ConfigToBlock (\r
2336 mHiiConfigRouting,\r
2337 ConfigResp,\r
2338 TmpBuf,\r
2339 &BufferSize,\r
2340 &Progress\r
2341 );\r
2342 if (EFI_ERROR (Status)) {\r
2343 FreePool (TmpBuf);\r
2344 FreePool (ConfigResp);\r
2345 return Status;\r
2346 }\r
2347\r
2348 Status = gRT->SetVariable (\r
2349 Storage->Name,\r
2350 &Storage->Guid,\r
2351 Storage->Attributes,\r
2352 Storage->Size,\r
2353 TmpBuf\r
2354 );\r
2355 FreePool (TmpBuf);\r
b18e7050
ED
2356 if (EFI_ERROR (Status)) {\r
2357 FreePool (ConfigResp);\r
2358 return Status;\r
2359 }\r
2360 }\r
2361 FreePool (ConfigResp);\r
b18e7050 2362 //\r
cce6230f 2363 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.\r
b18e7050 2364 //\r
cce6230f 2365 SynchronizeStorageForForm(FormSet, ConfigInfo, TRUE);\r
7936fb6a 2366 }\r
2367\r
cce6230f
ED
2368 //\r
2369 // 4. Update the NV flag.\r
2370 // \r
b18e7050 2371 Form->NvUpdateRequired = FALSE;\r
48a9d5f7 2372 } else if (SettingScope == FormSetLevel && IsNvUpdateRequired(FormSet)) {\r
7936fb6a 2373 //\r
b18e7050 2374 // Submit Buffer storage or Name/Value storage\r
7936fb6a 2375 //\r
b18e7050
ED
2376 Link = GetFirstNode (&FormSet->StorageListHead);\r
2377 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
2378 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
2379 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
2380\r
2381 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
2382 continue;\r
2383 }\r
2384\r
2385 //\r
2386 // Skip if there is no RequestElement\r
2387 //\r
2388 if (Storage->ElementCount == 0) {\r
2389 continue;\r
2390 }\r
2391\r
2392 //\r
cce6230f 2393 // 1. Prepare <ConfigResp>\r
b18e7050
ED
2394 //\r
2395 Status = StorageToConfigResp (Storage, &ConfigResp, FALSE);\r
7936fb6a 2396 if (EFI_ERROR (Status)) {\r
7936fb6a 2397 return Status;\r
2398 }\r
b18e7050 2399\r
cce6230f
ED
2400 if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
2401 Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
2402\r
2403 //\r
2404 // 2. Send <ConfigResp> to Configuration Driver\r
2405 //\r
2406 if (FormSet->ConfigAccess != NULL) {\r
2407 Status = FormSet->ConfigAccess->RouteConfig (\r
2408 FormSet->ConfigAccess,\r
2409 ConfigResp,\r
2410 &Progress\r
2411 );\r
2412 if (EFI_ERROR (Status)) {\r
2413 FreePool (ConfigResp);\r
2414 return Status;\r
2415 }\r
2416 }\r
2417 } else if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
2418 //\r
2419 // 1&2. Set the edit data to the variable.\r
2420 //\r
2421 TmpBuf = NULL;\r
2422 TmpBuf = AllocateZeroPool (Storage->Size);\r
2423 if (TmpBuf == NULL) {\r
2424 Status = EFI_OUT_OF_RESOURCES;\r
2425 return Status;\r
2426 } \r
2427 BufferSize = Storage->Size;\r
2428 Status = gRT->GetVariable (\r
2429 Storage->Name,\r
2430 &Storage->Guid,\r
2431 NULL,\r
2432 &BufferSize,\r
2433 TmpBuf\r
2434 );\r
2435 ASSERT (BufferSize == Storage->Size); \r
2436 Status = mHiiConfigRouting->ConfigToBlock (\r
2437 mHiiConfigRouting,\r
2438 ConfigResp,\r
2439 TmpBuf,\r
2440 &BufferSize,\r
2441 &Progress\r
2442 );\r
2443 if (EFI_ERROR (Status)) {\r
2444 FreePool (TmpBuf);\r
2445 FreePool (ConfigResp);\r
2446 return Status;\r
2447 }\r
2448\r
2449 Status = gRT->SetVariable (\r
2450 Storage->Name,\r
2451 &Storage->Guid,\r
2452 Storage->Attributes,\r
2453 Storage->Size,\r
2454 TmpBuf\r
2455 );\r
b18e7050 2456 if (EFI_ERROR (Status)) {\r
cce6230f 2457 FreePool (TmpBuf);\r
b18e7050
ED
2458 FreePool (ConfigResp);\r
2459 return Status;\r
2460 }\r
cce6230f 2461 FreePool (TmpBuf);\r
b18e7050
ED
2462 }\r
2463 FreePool (ConfigResp);\r
b18e7050 2464 //\r
cce6230f 2465 // 3. Config success, update storage shadow Buffer\r
b18e7050 2466 //\r
cce6230f 2467 SynchronizeStorage (Storage, TRUE);\r
7936fb6a 2468 }\r
7936fb6a 2469\r
cce6230f
ED
2470 //\r
2471 // 4. Update the NV flag.\r
2472 // \r
48a9d5f7
LG
2473 UpdateNvInfoInForm (FormSet, FALSE);\r
2474 } else if (SettingScope == SystemLevel) {\r
2475 //\r
2476 // System Level Save.\r
2477 //\r
2478\r
2479 //\r
2480 // Save changed value for each FormSet in the maintain list.\r
2481 //\r
2482 Link = GetFirstNode (&gBrowserFormSetList);\r
2483 while (!IsNull (&gBrowserFormSetList, Link)) {\r
2484 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
2485 SubmitForm (LocalFormSet, NULL, FormSetLevel);\r
2486 Link = GetNextNode (&gBrowserFormSetList, Link);\r
2487 if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
2488 //\r
2489 // Remove maintain backup list after save except for the current using FormSet.\r
2490 //\r
2491 RemoveEntryList (&LocalFormSet->Link);\r
2492 DestroyFormSet (LocalFormSet);\r
2493 }\r
2494 }\r
7936fb6a 2495 }\r
2496\r
7936fb6a 2497 return EFI_SUCCESS;\r
2498}\r
2499\r
ee31d1be
ED
2500/**\r
2501 Get Question default value from AltCfg string.\r
2502\r
2503 @param FormSet The form set.\r
2504 @param Question The question.\r
2505 @param DefaultId The default Id.\r
2506\r
2507 @retval EFI_SUCCESS Question is reset to default value.\r
2508\r
2509**/\r
2510EFI_STATUS\r
2511GetDefaultValueFromAltCfg (\r
2512 IN FORM_BROWSER_FORMSET *FormSet,\r
2513 IN OUT FORM_BROWSER_STATEMENT *Question,\r
2514 IN UINT16 DefaultId\r
2515 )\r
2516{\r
2517 BOOLEAN IsBufferStorage;\r
2518 BOOLEAN IsString; \r
2519 UINTN Length;\r
2520 FORMSET_STORAGE *Storage;\r
2521 CHAR16 *ConfigRequest;\r
2522 CHAR16 *Progress;\r
2523 CHAR16 *Result;\r
2524 CHAR16 *ConfigResp;\r
2525 CHAR16 *Value;\r
2526 CHAR16 *StringPtr;\r
2527 UINTN LengthStr;\r
2528 UINT8 *Dst;\r
2529 CHAR16 TemStr[5];\r
2530 UINTN Index;\r
2531 UINT8 DigitUint8;\r
2532 EFI_STATUS Status;\r
2533\r
2534 Status = EFI_NOT_FOUND;\r
2535 Length = 0;\r
2536 Dst = NULL;\r
2537 ConfigRequest = NULL;\r
2538 Result = NULL;\r
2539 ConfigResp = NULL;\r
0194d26c 2540 Value = NULL;\r
ee31d1be
ED
2541 Storage = Question->Storage;\r
2542\r
cce6230f
ED
2543 if ((Storage == NULL) || \r
2544 (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) || \r
2545 (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
ee31d1be
ED
2546 return Status;\r
2547 }\r
2548\r
2549 //\r
2550 // Question Value is provided by Buffer Storage or NameValue Storage\r
2551 //\r
2552 if (Question->BufferValue != NULL) {\r
2553 //\r
2554 // This Question is password or orderedlist\r
2555 //\r
2556 Dst = Question->BufferValue;\r
2557 } else {\r
2558 //\r
2559 // Other type of Questions\r
2560 //\r
2561 Dst = (UINT8 *) &Question->HiiValue.Value;\r
2562 }\r
2563\r
2564 IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
2565 IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
2566\r
2567 //\r
2568 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
2569 // <ConfigHdr> + "&" + <VariableName>\r
2570 //\r
2571 if (IsBufferStorage) {\r
2572 Length = StrLen (Storage->ConfigHdr);\r
2573 Length += StrLen (Question->BlockName);\r
2574 } else {\r
2575 Length = StrLen (Storage->ConfigHdr);\r
2576 Length += StrLen (Question->VariableName) + 1;\r
2577 }\r
2578 ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
2579 ASSERT (ConfigRequest != NULL);\r
2580\r
2581 StrCpy (ConfigRequest, Storage->ConfigHdr);\r
2582 if (IsBufferStorage) {\r
2583 StrCat (ConfigRequest, Question->BlockName);\r
2584 } else {\r
2585 StrCat (ConfigRequest, L"&");\r
2586 StrCat (ConfigRequest, Question->VariableName);\r
2587 }\r
2588\r
2589 Status = FormSet->ConfigAccess->ExtractConfig (\r
2590 FormSet->ConfigAccess,\r
2591 ConfigRequest,\r
2592 &Progress,\r
2593 &Result\r
2594 );\r
2595 if (EFI_ERROR (Status)) {\r
2596 goto Done;\r
2597 }\r
2598\r
2599 //\r
2600 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
2601 // Get the default configuration string according to the default ID.\r
2602 //\r
2603 Status = mHiiConfigRouting->GetAltConfig (\r
2604 mHiiConfigRouting,\r
2605 Result,\r
2606 &Storage->Guid,\r
2607 Storage->Name,\r
2608 NULL,\r
2609 &DefaultId, // it can be NULL to get the current setting.\r
2610 &ConfigResp\r
2611 );\r
2612 \r
2613 //\r
2614 // The required setting can't be found. So, it is not required to be validated and set.\r
2615 //\r
2616 if (EFI_ERROR (Status)) {\r
2617 goto Done;\r
2618 }\r
2619\r
2620 //\r
2621 // Skip <ConfigRequest>\r
2622 //\r
ee31d1be 2623 if (IsBufferStorage) {\r
0194d26c
ED
2624 Value = StrStr (ConfigResp, L"&VALUE");\r
2625 ASSERT (Value != NULL);\r
ee31d1be
ED
2626 //\r
2627 // Skip "&VALUE"\r
2628 //\r
2629 Value = Value + 6;\r
0194d26c
ED
2630 } else {\r
2631 Value = StrStr (ConfigResp, Question->VariableName);\r
2632 ASSERT (Value != NULL);\r
2633\r
2634 Value = Value + StrLen (Question->VariableName);\r
ee31d1be
ED
2635 }\r
2636 if (*Value != '=') {\r
2637 Status = EFI_NOT_FOUND;\r
2638 goto Done;\r
2639 }\r
2640 //\r
2641 // Skip '=', point to value\r
2642 //\r
2643 Value = Value + 1;\r
2644\r
2645 //\r
2646 // Suppress <AltResp> if any\r
2647 //\r
2648 StringPtr = Value;\r
2649 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
2650 StringPtr++;\r
2651 }\r
2652 *StringPtr = L'\0';\r
2653\r
2654 LengthStr = StrLen (Value);\r
2655 if (!IsBufferStorage && IsString) {\r
2656 StringPtr = (CHAR16 *) Dst;\r
2657 ZeroMem (TemStr, sizeof (TemStr));\r
2658 for (Index = 0; Index < LengthStr; Index += 4) {\r
2659 StrnCpy (TemStr, Value + Index, 4);\r
2660 StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
2661 }\r
2662 //\r
2663 // Add tailing L'\0' character\r
2664 //\r
2665 StringPtr[Index/4] = L'\0';\r
2666 } else {\r
2667 ZeroMem (TemStr, sizeof (TemStr));\r
2668 for (Index = 0; Index < LengthStr; Index ++) {\r
2669 TemStr[0] = Value[LengthStr - Index - 1];\r
2670 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
2671 if ((Index & 1) == 0) {\r
2672 Dst [Index/2] = DigitUint8;\r
2673 } else {\r
2674 Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
2675 }\r
2676 }\r
2677 }\r
2678\r
2679Done:\r
2680 if (ConfigRequest != NULL){\r
2681 FreePool (ConfigRequest);\r
2682 }\r
2683\r
2684 if (ConfigResp != NULL) {\r
2685 FreePool (ConfigResp);\r
2686 }\r
2687 \r
2688 if (Result != NULL) {\r
2689 FreePool (Result);\r
2690 }\r
2691\r
2692 return Status;\r
2693}\r
2694\r
2695/**\r
2696 Get default Id value used for browser.\r
2697\r
2698 @param DefaultId The default id value used by hii.\r
2699\r
2700 @retval Browser used default value.\r
2701\r
2702**/\r
2703INTN\r
2704GetDefaultIdForCallBack (\r
2705 UINTN DefaultId\r
2706 )\r
2707{ \r
2708 if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
2709 return EFI_BROWSER_ACTION_DEFAULT_STANDARD;\r
2710 } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
2711 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;\r
2712 } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {\r
2713 return EFI_BROWSER_ACTION_DEFAULT_SAFE;\r
2714 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000) {\r
2715 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;\r
2716 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000) {\r
2717 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;\r
2718 } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000) {\r
2719 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;\r
2720 } else {\r
2721 return -1;\r
2722 }\r
2723}\r
7936fb6a 2724\r
2725/**\r
2726 Reset Question to its default value.\r
2727\r
2728 @param FormSet The form set.\r
2729 @param Form The form.\r
2730 @param Question The question.\r
2731 @param DefaultId The Class of the default.\r
2732\r
2733 @retval EFI_SUCCESS Question is reset to default value.\r
2734\r
2735**/\r
2736EFI_STATUS\r
2737GetQuestionDefault (\r
2738 IN FORM_BROWSER_FORMSET *FormSet,\r
2739 IN FORM_BROWSER_FORM *Form,\r
2740 IN FORM_BROWSER_STATEMENT *Question,\r
2741 IN UINT16 DefaultId\r
2742 )\r
2743{\r
2744 EFI_STATUS Status;\r
2745 LIST_ENTRY *Link;\r
2746 QUESTION_DEFAULT *Default;\r
2747 QUESTION_OPTION *Option;\r
2748 EFI_HII_VALUE *HiiValue;\r
2749 UINT8 Index;\r
086cd2c8 2750 EFI_STRING StrValue;\r
ee31d1be
ED
2751 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
2752 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
2753 INTN Action;\r
7936fb6a 2754\r
48a9d5f7 2755 Status = EFI_NOT_FOUND;\r
086cd2c8 2756 StrValue = NULL;\r
7936fb6a 2757\r
2758 //\r
2759 // Statement don't have storage, skip them\r
2760 //\r
2761 if (Question->QuestionId == 0) {\r
2762 return Status;\r
2763 }\r
2764\r
2765 //\r
ee31d1be
ED
2766 // There are Five ways to specify default value for a Question:\r
2767 // 1, use call back function (highest priority)\r
2768 // 2, use ExtractConfig function\r
2769 // 3, use nested EFI_IFR_DEFAULT \r
2770 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
2771 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
7936fb6a 2772 //\r
2773 HiiValue = &Question->HiiValue;\r
2774\r
ee31d1be
ED
2775 //\r
2776 // Get Question defaut value from call back function.\r
2777 //\r
2778 ConfigAccess = FormSet->ConfigAccess;\r
2779 Action = GetDefaultIdForCallBack (DefaultId);\r
2780 if ((Action > 0) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {\r
2781 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2782 Status = ConfigAccess->Callback (\r
2783 ConfigAccess,\r
2784 Action,\r
2785 Question->QuestionId,\r
2786 HiiValue->Type,\r
2787 &HiiValue->Value,\r
2788 &ActionRequest\r
2789 );\r
2790 if (!EFI_ERROR (Status)) {\r
2791 return Status;\r
2792 }\r
2793 }\r
2794\r
2795 //\r
2796 // Get default value from altcfg string.\r
2797 //\r
2798 if (ConfigAccess != NULL) { \r
2799 Status = GetDefaultValueFromAltCfg(FormSet, Question, DefaultId);\r
2800 if (!EFI_ERROR (Status)) {\r
2801 return Status;\r
2802 }\r
2803 }\r
2804\r
7936fb6a 2805 //\r
2806 // EFI_IFR_DEFAULT has highest priority\r
2807 //\r
2808 if (!IsListEmpty (&Question->DefaultListHead)) {\r
2809 Link = GetFirstNode (&Question->DefaultListHead);\r
2810 while (!IsNull (&Question->DefaultListHead, Link)) {\r
2811 Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
2812\r
2813 if (Default->DefaultId == DefaultId) {\r
2814 if (Default->ValueExpression != NULL) {\r
2815 //\r
2816 // Default is provided by an Expression, evaluate it\r
2817 //\r
2818 Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
2819 if (EFI_ERROR (Status)) {\r
2820 return Status;\r
2821 }\r
2822\r
901ba0e7
ED
2823 if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
2824 ASSERT (HiiValue->Type == EFI_IFR_TYPE_BUFFER && Question->BufferValue != NULL);\r
2825 if (Question->StorageWidth > Default->ValueExpression->Result.BufferLen) {\r
2826 CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Default->ValueExpression->Result.BufferLen);\r
2827 Question->HiiValue.BufferLen = Default->ValueExpression->Result.BufferLen;\r
2828 } else {\r
2829 CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Question->StorageWidth);\r
2830 Question->HiiValue.BufferLen = Question->StorageWidth;\r
2831 }\r
2832 FreePool (Default->ValueExpression->Result.Buffer);\r
2833 }\r
2834 HiiValue->Type = Default->ValueExpression->Result.Type;\r
2835 CopyMem (&HiiValue->Value, &Default->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE)); \r
7936fb6a 2836 } else {\r
2837 //\r
2838 // Default value is embedded in EFI_IFR_DEFAULT\r
2839 //\r
2840 CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
2841 }\r
2842\r
086cd2c8
LG
2843 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
2844 StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);\r
2845 if (StrValue == NULL) {\r
2846 return EFI_NOT_FOUND;\r
2847 }\r
ba944801
ED
2848 if (Question->StorageWidth > StrSize (StrValue)) {\r
2849 CopyMem (Question->BufferValue, StrValue, StrSize (StrValue));\r
2850 } else {\r
2851 CopyMem (Question->BufferValue, StrValue, Question->StorageWidth);\r
2852 }\r
086cd2c8
LG
2853 }\r
2854\r
7936fb6a 2855 return EFI_SUCCESS;\r
2856 }\r
2857\r
2858 Link = GetNextNode (&Question->DefaultListHead, Link);\r
2859 }\r
2860 }\r
2861\r
2862 //\r
2863 // EFI_ONE_OF_OPTION\r
2864 //\r
2865 if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
2866 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
2867 //\r
2868 // OneOfOption could only provide Standard and Manufacturing default\r
2869 //\r
2870 Link = GetFirstNode (&Question->OptionListHead);\r
2871 while (!IsNull (&Question->OptionListHead, Link)) {\r
2872 Option = QUESTION_OPTION_FROM_LINK (Link);\r
2873\r
2874 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
2875 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
2876 ) {\r
2877 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
2878\r
2879 return EFI_SUCCESS;\r
2880 }\r
2881\r
2882 Link = GetNextNode (&Question->OptionListHead, Link);\r
2883 }\r
2884 }\r
2885 }\r
2886\r
2887 //\r
2888 // EFI_IFR_CHECKBOX - lowest priority\r
2889 //\r
2890 if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
2891 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
2892 //\r
2893 // Checkbox could only provide Standard and Manufacturing default\r
2894 //\r
2895 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
2896 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
2897 ) {\r
2898 HiiValue->Value.b = TRUE;\r
2899 } else {\r
2900 HiiValue->Value.b = FALSE;\r
2901 }\r
2902\r
2903 return EFI_SUCCESS;\r
2904 }\r
2905 }\r
2906\r
2907 //\r
2908 // For Questions without default\r
2909 //\r
48a9d5f7 2910 Status = EFI_NOT_FOUND;\r
7936fb6a 2911 switch (Question->Operand) {\r
cf4c5a42
LG
2912 case EFI_IFR_NUMERIC_OP:\r
2913 //\r
2914 // Take minimum value as numeric default value\r
2915 //\r
2916 if ((HiiValue->Value.u64 < Question->Minimum) || (HiiValue->Value.u64 > Question->Maximum)) {\r
2917 HiiValue->Value.u64 = Question->Minimum;\r
48a9d5f7 2918 Status = EFI_SUCCESS;\r
cf4c5a42
LG
2919 }\r
2920 break;\r
2921\r
7936fb6a 2922 case EFI_IFR_ONE_OF_OP:\r
2923 //\r
2924 // Take first oneof option as oneof's default value\r
2925 //\r
d66e6c16 2926 if (ValueToOption (Question, HiiValue) == NULL) {\r
0a1147ed
LG
2927 Link = GetFirstNode (&Question->OptionListHead);\r
2928 if (!IsNull (&Question->OptionListHead, Link)) {\r
2929 Option = QUESTION_OPTION_FROM_LINK (Link);\r
2930 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
48a9d5f7 2931 Status = EFI_SUCCESS;\r
0a1147ed 2932 }\r
7936fb6a 2933 }\r
2934 break;\r
2935\r
2936 case EFI_IFR_ORDERED_LIST_OP:\r
2937 //\r
2938 // Take option sequence in IFR as ordered list's default value\r
2939 //\r
2940 Index = 0;\r
2941 Link = GetFirstNode (&Question->OptionListHead);\r
2942 while (!IsNull (&Question->OptionListHead, Link)) {\r
48a9d5f7 2943 Status = EFI_SUCCESS;\r
7936fb6a 2944 Option = QUESTION_OPTION_FROM_LINK (Link);\r
2945\r
d02847d3 2946 SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);\r
7936fb6a 2947\r
2948 Index++;\r
2949 if (Index >= Question->MaxContainers) {\r
2950 break;\r
2951 }\r
2952\r
2953 Link = GetNextNode (&Question->OptionListHead, Link);\r
2954 }\r
2955 break;\r
2956\r
2957 default:\r
7936fb6a 2958 break;\r
2959 }\r
2960\r
2961 return Status;\r
2962}\r
2963\r
2964\r
2965/**\r
48a9d5f7 2966 Reset Questions to their default value in a Form, Formset or System.\r
7936fb6a 2967\r
2968 @param FormSet FormSet data structure.\r
48a9d5f7 2969 @param Form Form data structure.\r
7936fb6a 2970 @param DefaultId The Class of the default.\r
48a9d5f7 2971 @param SettingScope Setting Scope for Default action.\r
7936fb6a 2972\r
2973 @retval EFI_SUCCESS The function completed successfully.\r
48a9d5f7 2974 @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
7936fb6a 2975\r
2976**/\r
2977EFI_STATUS\r
48a9d5f7 2978ExtractDefault (\r
7936fb6a 2979 IN FORM_BROWSER_FORMSET *FormSet,\r
48a9d5f7
LG
2980 IN FORM_BROWSER_FORM *Form,\r
2981 IN UINT16 DefaultId,\r
2982 IN BROWSER_SETTING_SCOPE SettingScope\r
7936fb6a 2983 )\r
2984{\r
2985 EFI_STATUS Status;\r
4f33c838 2986 LIST_ENTRY *FormLink;\r
48a9d5f7 2987 LIST_ENTRY *Link;\r
7936fb6a 2988 FORM_BROWSER_STATEMENT *Question;\r
48a9d5f7
LG
2989 FORM_BROWSER_FORMSET *BackUpFormSet;\r
2990 FORM_BROWSER_FORMSET *LocalFormSet;\r
2991 EFI_HII_HANDLE *HiiHandles;\r
2992 UINTN Index;\r
2993 EFI_GUID ZeroGuid;\r
2994 UINTN BackUpClassOfVfr;\r
7936fb6a 2995\r
48a9d5f7
LG
2996 //\r
2997 // Check the supported setting level.\r
2998 //\r
2999 if (SettingScope >= MaxLevel) {\r
3000 return EFI_UNSUPPORTED;\r
3001 }\r
3002 \r
3003 if (SettingScope == FormLevel) {\r
8d00a0f1 3004 //\r
4f33c838 3005 // Extract Form default\r
8d00a0f1 3006 //\r
48a9d5f7
LG
3007 Link = GetFirstNode (&Form->StatementListHead);\r
3008 while (!IsNull (&Form->StatementListHead, Link)) {\r
3009 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
3010 Link = GetNextNode (&Form->StatementListHead, Link);\r
3011 \r
4f33c838
ED
3012 //\r
3013 // If Question is disabled, don't reset it to default\r
3014 //\r
3015 if (Question->DisableExpression != NULL) {\r
3016 Status = EvaluateExpression (FormSet, Form, Question->DisableExpression);\r
3017 if (!EFI_ERROR (Status) && Question->DisableExpression->Result.Value.b) {\r
3018 continue;\r
3019 }\r
8d00a0f1 3020 }\r
48a9d5f7 3021 \r
4f33c838
ED
3022 //\r
3023 // Reset Question to its default value\r
3024 //\r
3025 Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
3026 if (EFI_ERROR (Status)) {\r
3027 continue;\r
3028 }\r
48a9d5f7 3029 \r
4f33c838
ED
3030 //\r
3031 // Synchronize Buffer storage's Edit buffer\r
3032 //\r
3033 if ((Question->Storage != NULL) &&\r
3034 (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
3035 SetQuestionValue (FormSet, Form, Question, TRUE);\r
48a9d5f7
LG
3036 //\r
3037 // Update Form NV flag.\r
3038 //\r
3039 Form->NvUpdateRequired = TRUE;\r
3040 }\r
3041 }\r
3042 } else if (SettingScope == FormSetLevel) {\r
3043 FormLink = GetFirstNode (&FormSet->FormListHead);\r
3044 while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
3045 Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
3046 ExtractDefault (FormSet, Form, DefaultId, FormLevel);\r
3047 FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
3048 }\r
3049 } else if (SettingScope == SystemLevel) {\r
3050 //\r
3051 // Open all FormSet by locate HII packages.\r
3052 // Initiliaze the maintain FormSet to store default data as back up data.\r
3053 //\r
3054 BackUpClassOfVfr = gClassOfVfr;\r
3055 BackUpFormSet = gOldFormSet;\r
3056 gOldFormSet = NULL;\r
3057\r
3058 //\r
3059 // Get all the Hii handles\r
3060 //\r
3061 HiiHandles = HiiGetHiiHandles (NULL);\r
3062 ASSERT (HiiHandles != NULL);\r
3063\r
3064 //\r
3065 // Search for formset of each class type\r
3066 //\r
3067 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
3068 //\r
3069 // Check HiiHandles[Index] does exist in global maintain list. \r
3070 //\r
3071 if (GetFormSetFromHiiHandle (HiiHandles[Index]) != NULL) {\r
3072 continue;\r
4f33c838 3073 }\r
48a9d5f7
LG
3074 \r
3075 //\r
3076 // Initilize FormSet Setting\r
3077 //\r
3078 LocalFormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
3079 ASSERT (LocalFormSet != NULL);\r
3080 ZeroMem (&ZeroGuid, sizeof (ZeroGuid));\r
3081 Status = InitializeFormSet (HiiHandles[Index], &ZeroGuid, LocalFormSet);\r
3082 if (EFI_ERROR (Status) || IsListEmpty (&LocalFormSet->FormListHead)) {\r
3083 DestroyFormSet (LocalFormSet);\r
3084 continue;\r
3085 }\r
3086 Status = InitializeCurrentSetting (LocalFormSet);\r
3087 if (EFI_ERROR (Status)) {\r
3088 DestroyFormSet (LocalFormSet);\r
3089 continue;\r
3090 }\r
3091 \r
3092 //\r
3093 // Add FormSet into the maintain list.\r
3094 //\r
3095 InsertTailList (&gBrowserFormSetList, &LocalFormSet->Link);\r
3096 }\r
3097 \r
3098 //\r
3099 // Free resources, and restore gOldFormSet and gClassOfVfr\r
3100 //\r
3101 FreePool (HiiHandles);\r
3102 gOldFormSet = BackUpFormSet;\r
3103 gClassOfVfr = BackUpClassOfVfr;\r
3104 \r
3105 //\r
3106 // Set Default Value for each FormSet in the maintain list.\r
3107 //\r
3108 Link = GetFirstNode (&gBrowserFormSetList);\r
3109 while (!IsNull (&gBrowserFormSetList, Link)) {\r
3110 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
3111 ExtractDefault (LocalFormSet, NULL, DefaultId, FormSetLevel);\r
3112 Link = GetNextNode (&gBrowserFormSetList, Link);\r
7936fb6a 3113 }\r
3114 }\r
3115\r
3116 return EFI_SUCCESS;\r
3117}\r
3118\r
7936fb6a 3119/**\r
3120 Initialize Question's Edit copy from Storage.\r
3121\r
eccfeab1
LG
3122 @param Selection Selection contains the information about \r
3123 the Selection, form and formset to be displayed.\r
3124 Selection action may be updated in retrieve callback.\r
7936fb6a 3125 @param FormSet FormSet data structure.\r
3126 @param Form Form data structure.\r
3127\r
3128 @retval EFI_SUCCESS The function completed successfully.\r
3129\r
3130**/\r
3131EFI_STATUS\r
3132LoadFormConfig (\r
eccfeab1
LG
3133 IN OUT UI_MENU_SELECTION *Selection,\r
3134 IN FORM_BROWSER_FORMSET *FormSet,\r
3135 IN FORM_BROWSER_FORM *Form\r
7936fb6a 3136 )\r
3137{\r
eccfeab1
LG
3138 EFI_STATUS Status;\r
3139 LIST_ENTRY *Link;\r
3140 FORM_BROWSER_STATEMENT *Question;\r
3141 UINT8 *BufferValue;\r
3142 UINTN StorageWidth;\r
eccfeab1 3143 \r
7936fb6a 3144 Link = GetFirstNode (&Form->StatementListHead);\r
3145 while (!IsNull (&Form->StatementListHead, Link)) {\r
3146 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
3147\r
3148 //\r
3149 // Initialize local copy of Value for each Question\r
3150 //\r
3151 Status = GetQuestionValue (FormSet, Form, Question, TRUE);\r
3152 if (EFI_ERROR (Status)) {\r
3153 return Status;\r
3154 }\r
e2100bfa
ED
3155\r
3156 if ((Question->Operand == EFI_IFR_STRING_OP) || (Question->Operand == EFI_IFR_PASSWORD_OP)) {\r
3157 HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);\r
3158 }\r
3159\r
8ca6180f
ED
3160 //\r
3161 // According the spec, ref opcode try to get value from call back with "retrieve" type.\r
3162 //\r
3163 if ((Question->Operand == EFI_IFR_REF_OP) && (FormSet->ConfigAccess != NULL)) {\r
3164 Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE);\r
3165 if (EFI_ERROR (Status)) {\r
3166 return Status;\r
3167 }\r
3168 }\r
3169\r
eccfeab1
LG
3170 //\r
3171 // Check whether EfiVarstore with CallBack can be got.\r
3172 //\r
13ad1def
LG
3173 if ((FormSet->ConfigAccess != NULL) &&\r
3174 (Selection->Action != UI_ACTION_REFRESH_FORMSET) &&\r
3175 (Question->QuestionId != 0) && \r
3176 (Question->Storage != NULL) &&\r
eccfeab1
LG
3177 (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) && \r
3178 ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) {\r
13ad1def 3179\r
eccfeab1
LG
3180 //\r
3181 // Check QuestionValue does exist.\r
3182 //\r
3183 StorageWidth = Question->StorageWidth;\r
3184 if (Question->BufferValue != NULL) {\r
3185 BufferValue = Question->BufferValue;\r
3186 } else {\r
3187 BufferValue = (UINT8 *) &Question->HiiValue.Value;\r
3188 }\r
3189 Status = gRT->GetVariable (\r
3190 Question->VariableName,\r
3191 &Question->Storage->Guid,\r
3192 NULL,\r
3193 &StorageWidth,\r
3194 BufferValue\r
3195 );\r
3196\r
3197 if (!EFI_ERROR (Status)) {\r
b18e7050 3198 Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE);\r
eccfeab1
LG
3199 }\r
3200 }\r
7936fb6a 3201\r
3202 Link = GetNextNode (&Form->StatementListHead, Link);\r
3203 }\r
3204\r
3205 return EFI_SUCCESS;\r
3206}\r
3207\r
d66e6c16 3208/**\r
3209 Initialize Question's Edit copy from Storage for the whole Formset.\r
3210\r
eccfeab1
LG
3211 @param Selection Selection contains the information about \r
3212 the Selection, form and formset to be displayed.\r
3213 Selection action may be updated in retrieve callback.\r
d66e6c16 3214 @param FormSet FormSet data structure.\r
3215\r
3216 @retval EFI_SUCCESS The function completed successfully.\r
3217\r
3218**/\r
3219EFI_STATUS\r
3220LoadFormSetConfig (\r
eccfeab1
LG
3221 IN OUT UI_MENU_SELECTION *Selection,\r
3222 IN FORM_BROWSER_FORMSET *FormSet\r
d66e6c16 3223 )\r
3224{\r
eccfeab1
LG
3225 EFI_STATUS Status;\r
3226 LIST_ENTRY *Link;\r
3227 FORM_BROWSER_FORM *Form;\r
d66e6c16 3228\r
3229 Link = GetFirstNode (&FormSet->FormListHead);\r
3230 while (!IsNull (&FormSet->FormListHead, Link)) {\r
3231 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
3232\r
3233 //\r
3234 // Initialize local copy of Value for each Form\r
3235 //\r
eccfeab1 3236 Status = LoadFormConfig (Selection, FormSet, Form);\r
d66e6c16 3237 if (EFI_ERROR (Status)) {\r
3238 return Status;\r
3239 }\r
3240\r
3241 Link = GetNextNode (&FormSet->FormListHead, Link);\r
3242 }\r
3243\r
3244 return EFI_SUCCESS;\r
3245}\r
3246\r
7936fb6a 3247/**\r
3248 Fill storage's edit copy with settings requested from Configuration Driver.\r
3249\r
3250 @param FormSet FormSet data structure.\r
3251 @param Storage Buffer Storage.\r
3252\r
3253 @retval EFI_SUCCESS The function completed successfully.\r
3254\r
3255**/\r
3256EFI_STATUS\r
3257LoadStorage (\r
3258 IN FORM_BROWSER_FORMSET *FormSet,\r
3259 IN FORMSET_STORAGE *Storage\r
3260 )\r
3261{\r
3262 EFI_STATUS Status;\r
3263 EFI_STRING Progress;\r
3264 EFI_STRING Result;\r
3265 CHAR16 *StrPtr;\r
3266\r
3267 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
3268 return EFI_SUCCESS;\r
3269 }\r
3270\r
cce6230f
ED
3271 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
3272 Status = gRT->GetVariable (\r
3273 Storage->Name,\r
3274 &Storage->Guid,\r
3275 NULL,\r
3276 (UINTN*)&Storage->Size,\r
3277 Storage->EditBuffer\r
3278 );\r
3279 return Status;\r
3280 }\r
3281\r
7936fb6a 3282 if (FormSet->ConfigAccess == NULL) {\r
3283 return EFI_NOT_FOUND;\r
3284 }\r
3285\r
3286 if (Storage->ElementCount == 0) {\r
3287 //\r
3288 // Skip if there is no RequestElement\r
3289 //\r
3290 return EFI_SUCCESS;\r
3291 }\r
3292\r
3293 //\r
3294 // Request current settings from Configuration Driver\r
3295 //\r
3296 Status = FormSet->ConfigAccess->ExtractConfig (\r
3297 FormSet->ConfigAccess,\r
3298 Storage->ConfigRequest,\r
3299 &Progress,\r
3300 &Result\r
3301 );\r
3302 if (EFI_ERROR (Status)) {\r
3303 return Status;\r
3304 }\r
3305\r
3306 //\r
3307 // Convert Result from <ConfigAltResp> to <ConfigResp>\r
3308 //\r
3309 StrPtr = StrStr (Result, L"ALTCFG");\r
3310 if (StrPtr != NULL) {\r
3311 *StrPtr = L'\0';\r
3312 }\r
3313\r
3314 Status = ConfigRespToStorage (Storage, Result);\r
f4113e1f 3315 FreePool (Result);\r
7936fb6a 3316 return Status;\r
3317}\r
3318\r
3319\r
d66e6c16 3320/**\r
3321 Copy uncommitted data from source Storage to destination Storage.\r
3322\r
3323 @param Dst Target Storage for uncommitted data.\r
3324 @param Src Source Storage for uncommitted data.\r
3325\r
3326 @retval EFI_SUCCESS The function completed successfully.\r
3327 @retval EFI_INVALID_PARAMETER Source and destination Storage is not the same type.\r
3328\r
3329**/\r
3330EFI_STATUS\r
3331CopyStorage (\r
3332 IN OUT FORMSET_STORAGE *Dst,\r
3333 IN FORMSET_STORAGE *Src\r
3334 )\r
3335{\r
3336 LIST_ENTRY *Link;\r
3337 NAME_VALUE_NODE *Node;\r
3338\r
3339 if ((Dst->Type != Src->Type) || (Dst->Size != Src->Size)) {\r
3340 return EFI_INVALID_PARAMETER;\r
3341 }\r
3342\r
3343 switch (Src->Type) {\r
3344 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 3345 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
d66e6c16 3346 CopyMem (Dst->EditBuffer, Src->EditBuffer, Src->Size);\r
b18e7050 3347 CopyMem (Dst->Buffer, Src->Buffer, Src->Size);\r
d66e6c16 3348 break;\r
3349\r
3350 case EFI_HII_VARSTORE_NAME_VALUE:\r
3351 Link = GetFirstNode (&Src->NameValueListHead);\r
3352 while (!IsNull (&Src->NameValueListHead, Link)) {\r
3353 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
3354\r
b18e7050
ED
3355 SetValueByName (Dst, Node->Name, Node->EditValue, TRUE);\r
3356 SetValueByName (Dst, Node->Name, Node->Value, FALSE);\r
d66e6c16 3357\r
3358 Link = GetNextNode (&Src->NameValueListHead, Link);\r
3359 }\r
3360 break;\r
3361\r
3362 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
3363 default:\r
3364 break;\r
3365 }\r
3366\r
3367 return EFI_SUCCESS;\r
3368}\r
3369\r
3370\r
7936fb6a 3371/**\r
3372 Get current setting of Questions.\r
3373\r
3374 @param FormSet FormSet data structure.\r
3375\r
3376 @retval EFI_SUCCESS The function completed successfully.\r
3377\r
3378**/\r
3379EFI_STATUS\r
3380InitializeCurrentSetting (\r
3381 IN OUT FORM_BROWSER_FORMSET *FormSet\r
3382 )\r
3383{\r
3384 LIST_ENTRY *Link;\r
d66e6c16 3385 LIST_ENTRY *Link2;\r
7936fb6a 3386 FORMSET_STORAGE *Storage;\r
d66e6c16 3387 FORMSET_STORAGE *StorageSrc;\r
3388 FORMSET_STORAGE *OldStorage;\r
7936fb6a 3389 FORM_BROWSER_FORM *Form;\r
b00964a9 3390 FORM_BROWSER_FORM *Form2;\r
7936fb6a 3391 EFI_STATUS Status;\r
3392\r
3393 //\r
3394 // Extract default from IFR binary\r
3395 //\r
48a9d5f7
LG
3396 ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel);\r
3397 UpdateNvInfoInForm (FormSet, FALSE);\r
7936fb6a 3398\r
3399 //\r
3400 // Request current settings from Configuration Driver\r
3401 //\r
3402 Link = GetFirstNode (&FormSet->StorageListHead);\r
3403 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
3404 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
3405\r
d66e6c16 3406 OldStorage = NULL;\r
3407 if (gOldFormSet != NULL) {\r
3408 //\r
3409 // Try to find the Storage in backup formset gOldFormSet\r
3410 //\r
3411 Link2 = GetFirstNode (&gOldFormSet->StorageListHead);\r
3412 while (!IsNull (&gOldFormSet->StorageListHead, Link2)) {\r
3413 StorageSrc = FORMSET_STORAGE_FROM_LINK (Link2);\r
3414\r
3415 if (StorageSrc->VarStoreId == Storage->VarStoreId) {\r
3416 OldStorage = StorageSrc;\r
3417 break;\r
3418 }\r
3419\r
3420 Link2 = GetNextNode (&gOldFormSet->StorageListHead, Link2);\r
3421 }\r
3422 }\r
3423\r
3424 if (OldStorage == NULL) {\r
3425 //\r
3426 // Storage is not found in backup formset, request it from ConfigDriver\r
3427 //\r
3428 Status = LoadStorage (FormSet, Storage);\r
b18e7050
ED
3429 //\r
3430 // Now Edit Buffer is filled with default values(lower priority) and current\r
3431 // settings(higher priority), sychronize it to shadow Buffer\r
3432 //\r
3433 if (!EFI_ERROR (Status)) {\r
cce6230f 3434 SynchronizeStorage (Storage, TRUE);\r
b18e7050 3435 }\r
d66e6c16 3436 } else {\r
3437 //\r
3438 // Storage found in backup formset, use it\r
3439 //\r
3440 Status = CopyStorage (Storage, OldStorage);\r
3441 }\r
7936fb6a 3442\r
7936fb6a 3443 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
3444 }\r
3445\r
b00964a9
ED
3446 //\r
3447 // If has old formset, get the old nv update status.\r
3448 //\r
3449 if (gOldFormSet != NULL) {\r
3450 Link = GetFirstNode (&FormSet->FormListHead);\r
3451 while (!IsNull (&FormSet->FormListHead, Link)) {\r
3452 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
3453\r
3454 Link2 = GetFirstNode (&gOldFormSet->FormListHead);\r
3455 while (!IsNull (&gOldFormSet->FormListHead, Link2)) {\r
3456 Form2 = FORM_BROWSER_FORM_FROM_LINK (Link2);\r
3457\r
3458 if (Form->FormId == Form2->FormId) {\r
3459 Form->NvUpdateRequired = Form2->NvUpdateRequired;\r
3460 break;\r
3461 }\r
3462\r
3463 Link2 = GetNextNode (&gOldFormSet->FormListHead, Link2);\r
3464 }\r
3465 Link = GetNextNode (&FormSet->FormListHead, Link);\r
3466 }\r
3467 }\r
3468\r
7936fb6a 3469 return EFI_SUCCESS;\r
3470}\r
3471\r
3472\r
3473/**\r
3474 Fetch the Ifr binary data of a FormSet.\r
3475\r
3476 @param Handle PackageList Handle\r
f5006bd9 3477 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
3478 specified (NULL or zero GUID), take the first\r
3479 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
3480 found in package list.\r
3481 On output, GUID of the formset found(if not NULL).\r
7936fb6a 3482 @param BinaryLength The length of the FormSet IFR binary.\r
3483 @param BinaryData The buffer designed to receive the FormSet.\r
3484\r
3485 @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
3486 BufferLength was updated.\r
3487 @retval EFI_INVALID_PARAMETER The handle is unknown.\r
3488 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
3489 be found with the requested FormId.\r
3490\r
3491**/\r
3492EFI_STATUS\r
3493GetIfrBinaryData (\r
3494 IN EFI_HII_HANDLE Handle,\r
3495 IN OUT EFI_GUID *FormSetGuid,\r
3496 OUT UINTN *BinaryLength,\r
3497 OUT UINT8 **BinaryData\r
3498 )\r
3499{\r
3500 EFI_STATUS Status;\r
3501 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
3502 UINTN BufferSize;\r
3503 UINT8 *Package;\r
3504 UINT8 *OpCodeData;\r
3505 UINT32 Offset;\r
3506 UINT32 Offset2;\r
7936fb6a 3507 UINT32 PackageListLength;\r
3508 EFI_HII_PACKAGE_HEADER PackageHeader;\r
0a1147ed
LG
3509 UINT8 Index;\r
3510 UINT8 NumberOfClassGuid;\r
f5006bd9 3511 BOOLEAN ClassGuidMatch;\r
0a1147ed 3512 EFI_GUID *ClassGuid;\r
f5006bd9 3513 EFI_GUID *ComparingGuid;\r
7936fb6a 3514\r
3515 OpCodeData = NULL;\r
3516 Package = NULL;\r
0c66bc76 3517 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
7936fb6a 3518\r
3519 //\r
f5006bd9 3520 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list\r
7936fb6a 3521 //\r
48a9d5f7
LG
3522 if (FormSetGuid == NULL) {\r
3523 ComparingGuid = &gZeroGuid;\r
7936fb6a 3524 } else {\r
f5006bd9 3525 ComparingGuid = FormSetGuid;\r
7936fb6a 3526 }\r
3527\r
3528 //\r
3529 // Get HII PackageList\r
3530 //\r
3531 BufferSize = 0;\r
3532 HiiPackageList = NULL;\r
3533 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
3534 if (Status == EFI_BUFFER_TOO_SMALL) {\r
3535 HiiPackageList = AllocatePool (BufferSize);\r
3536 ASSERT (HiiPackageList != NULL);\r
3537\r
3538 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
3539 }\r
3540 if (EFI_ERROR (Status)) {\r
3541 return Status;\r
3542 }\r
db0bd81c 3543 ASSERT (HiiPackageList != NULL);\r
d66e6c16 3544\r
7936fb6a 3545 //\r
3546 // Get Form package from this HII package List\r
3547 //\r
3548 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
3549 Offset2 = 0;\r
3550 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
3551\r
f5006bd9 3552 ClassGuidMatch = FALSE;\r
7936fb6a 3553 while (Offset < PackageListLength) {\r
3554 Package = ((UINT8 *) HiiPackageList) + Offset;\r
3555 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
3556\r
8d00a0f1 3557 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
7936fb6a 3558 //\r
3559 // Search FormSet in this Form Package\r
3560 //\r
3561 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
3562 while (Offset2 < PackageHeader.Length) {\r
3563 OpCodeData = Package + Offset2;\r
3564\r
3565 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
3566 //\r
f5006bd9 3567 // Try to compare against formset GUID\r
7936fb6a 3568 //\r
48a9d5f7
LG
3569 if (CompareGuid (FormSetGuid, &gZeroGuid) || \r
3570 CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
f5006bd9 3571 break;\r
7936fb6a 3572 }\r
3573\r
d228526f
LG
3574 if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
3575 //\r
3576 // Try to compare against formset class GUID\r
3577 //\r
3578 NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
3579 ClassGuid = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
3580 for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
3581 if (CompareGuid (ComparingGuid, ClassGuid + Index)) {\r
3582 ClassGuidMatch = TRUE;\r
3583 break;\r
3584 }\r
3585 }\r
3586 if (ClassGuidMatch) {\r
f5006bd9 3587 break;\r
3588 }\r
d228526f
LG
3589 } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {\r
3590 ClassGuidMatch = TRUE;\r
7936fb6a 3591 break;\r
3592 }\r
3593 }\r
3594\r
3595 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
3596 }\r
3597\r
3598 if (Offset2 < PackageHeader.Length) {\r
3599 //\r
3600 // Target formset found\r
3601 //\r
3602 break;\r
3603 }\r
3604 }\r
3605\r
3606 Offset += PackageHeader.Length;\r
3607 }\r
3608\r
3609 if (Offset >= PackageListLength) {\r
3610 //\r
3611 // Form package not found in this Package List\r
3612 //\r
f4113e1f 3613 FreePool (HiiPackageList);\r
7936fb6a 3614 return EFI_NOT_FOUND;\r
3615 }\r
3616\r
48a9d5f7 3617 if (FormSetGuid != NULL) {\r
7936fb6a 3618 //\r
f5006bd9 3619 // Return the FormSet GUID\r
7936fb6a 3620 //\r
3621 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
3622 }\r
3623\r
3624 //\r
3625 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
3626 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
3627 // of the Form Package.\r
3628 //\r
3629 *BinaryLength = PackageHeader.Length - Offset2;\r
3630 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
3631\r
f4113e1f 3632 FreePool (HiiPackageList);\r
7936fb6a 3633\r
3634 if (*BinaryData == NULL) {\r
3635 return EFI_OUT_OF_RESOURCES;\r
3636 }\r
3637\r
3638 return EFI_SUCCESS;\r
3639}\r
3640\r
3641\r
3642/**\r
3643 Initialize the internal data structure of a FormSet.\r
3644\r
3645 @param Handle PackageList Handle\r
f5006bd9 3646 @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
3647 specified (NULL or zero GUID), take the first\r
3648 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
3649 found in package list.\r
3650 On output, GUID of the formset found(if not NULL).\r
7936fb6a 3651 @param FormSet FormSet data structure.\r
3652\r
3653 @retval EFI_SUCCESS The function completed successfully.\r
3654 @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
3655\r
3656**/\r
3657EFI_STATUS\r
3658InitializeFormSet (\r
3659 IN EFI_HII_HANDLE Handle,\r
3660 IN OUT EFI_GUID *FormSetGuid,\r
3661 OUT FORM_BROWSER_FORMSET *FormSet\r
3662 )\r
3663{\r
3664 EFI_STATUS Status;\r
3665 EFI_HANDLE DriverHandle;\r
3666 UINT16 Index;\r
3667\r
3668 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
3669 if (EFI_ERROR (Status)) {\r
3670 return Status;\r
3671 }\r
3672\r
48a9d5f7 3673 FormSet->Signature = FORM_BROWSER_FORMSET_SIGNATURE;\r
7936fb6a 3674 FormSet->HiiHandle = Handle;\r
3675 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
3676\r
3677 //\r
3678 // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
3679 //\r
3680 Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
3681 if (EFI_ERROR (Status)) {\r
3682 return Status;\r
3683 }\r
3684 FormSet->DriverHandle = DriverHandle;\r
3685 Status = gBS->HandleProtocol (\r
3686 DriverHandle,\r
3687 &gEfiHiiConfigAccessProtocolGuid,\r
3688 (VOID **) &FormSet->ConfigAccess\r
3689 );\r
3690 if (EFI_ERROR (Status)) {\r
3691 //\r
3692 // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
3693 // list, then there will be no configuration action required\r
3694 //\r
3695 FormSet->ConfigAccess = NULL;\r
3696 }\r
3697\r
3698 //\r
3699 // Parse the IFR binary OpCodes\r
3700 //\r
3701 Status = ParseOpCodes (FormSet);\r
3702 if (EFI_ERROR (Status)) {\r
3703 return Status;\r
3704 }\r
3705\r
40245175
LG
3706 //\r
3707 // Set VFR type by FormSet SubClass field\r
3708 //\r
0a1147ed
LG
3709 gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP;\r
3710 if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {\r
3711 gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;\r
40245175
LG
3712 }\r
3713 \r
3714 //\r
3715 // Set VFR type by FormSet class guid\r
3716 //\r
3717 for (Index = 0; Index < 3; Index ++) {\r
3718 if (CompareGuid (&FormSet->ClassGuid[Index], &gEfiHiiPlatformSetupFormsetGuid)) {\r
3719 gClassOfVfr |= FORMSET_CLASS_PLATFORM_SETUP;\r
3720 break;\r
3721 }\r
3722 }\r
3723\r
3724 if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {\r
0a1147ed 3725 gFrontPageHandle = FormSet->HiiHandle;\r
48a9d5f7 3726 gFunctionKeySetting = NONE_FUNCTION_KEY_SETTING;\r
7936fb6a 3727 }\r
3728\r
3729 //\r
3730 // Match GUID to find out the function key setting. If match fail, use the default setting.\r
3731 //\r
3732 for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {\r
3733 if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {\r
3734 //\r
3735 // Update the function key setting.\r
3736 //\r
3737 gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;\r
7936fb6a 3738 }\r
3739 }\r
3740\r
48a9d5f7 3741 return EFI_SUCCESS;\r
7936fb6a 3742}\r
ce6d12cc 3743\r
3744\r
3745/**\r
3746 Save globals used by previous call to SendForm(). SendForm() may be called from \r
3747 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.\r
3748 So, save globals of previous call to SendForm() and restore them upon exit.\r
3749\r
3750**/\r
3751VOID\r
3752SaveBrowserContext (\r
3753 VOID\r
3754 )\r
3755{\r
3756 BROWSER_CONTEXT *Context;\r
3757\r
3758 gBrowserContextCount++;\r
3759 if (gBrowserContextCount == 1) {\r
3760 //\r
3761 // This is not reentry of SendForm(), no context to save\r
3762 //\r
3763 return;\r
3764 }\r
3765\r
3766 Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
3767 ASSERT (Context != NULL);\r
3768\r
3769 Context->Signature = BROWSER_CONTEXT_SIGNATURE;\r
3770\r
3771 //\r
3772 // Save FormBrowser context\r
3773 //\r
3774 Context->BannerData = gBannerData;\r
3775 Context->ClassOfVfr = gClassOfVfr;\r
3776 Context->FunctionKeySetting = gFunctionKeySetting;\r
3777 Context->ResetRequired = gResetRequired;\r
ce6d12cc 3778 Context->Direction = gDirection;\r
ce6d12cc 3779 Context->EnterString = gEnterString;\r
3780 Context->EnterCommitString = gEnterCommitString;\r
3781 Context->EnterEscapeString = gEnterEscapeString;\r
3782 Context->EscapeString = gEscapeString;\r
ce6d12cc 3783 Context->MoveHighlight = gMoveHighlight;\r
3784 Context->MakeSelection = gMakeSelection;\r
3785 Context->DecNumericInput = gDecNumericInput;\r
3786 Context->HexNumericInput = gHexNumericInput;\r
3787 Context->ToggleCheckBox = gToggleCheckBox;\r
3788 Context->PromptForData = gPromptForData;\r
3789 Context->PromptForPassword = gPromptForPassword;\r
3790 Context->PromptForNewPassword = gPromptForNewPassword;\r
3791 Context->ConfirmPassword = gConfirmPassword;\r
3792 Context->ConfirmError = gConfirmError;\r
3793 Context->PassowordInvalid = gPassowordInvalid;\r
3794 Context->PressEnter = gPressEnter;\r
3795 Context->EmptyString = gEmptyString;\r
3796 Context->AreYouSure = gAreYouSure;\r
3797 Context->YesResponse = gYesResponse;\r
3798 Context->NoResponse = gNoResponse;\r
3799 Context->MiniString = gMiniString;\r
3800 Context->PlusString = gPlusString;\r
3801 Context->MinusString = gMinusString;\r
3802 Context->AdjustNumber = gAdjustNumber;\r
3803 Context->SaveChanges = gSaveChanges;\r
3804 Context->OptionMismatch = gOptionMismatch;\r
2bb526f3 3805 Context->FormSuppress = gFormSuppress;\r
ce6d12cc 3806 Context->PromptBlockWidth = gPromptBlockWidth;\r
3807 Context->OptionBlockWidth = gOptionBlockWidth;\r
3808 Context->HelpBlockWidth = gHelpBlockWidth;\r
3809 Context->OldFormSet = gOldFormSet;\r
3810 Context->MenuRefreshHead = gMenuRefreshHead;\r
3811\r
3812 CopyMem (&Context->ScreenDimensions, &gScreenDimensions, sizeof (gScreenDimensions));\r
3813 CopyMem (&Context->MenuOption, &gMenuOption, sizeof (gMenuOption));\r
3814\r
3815 //\r
3816 // Insert to FormBrowser context list\r
3817 //\r
3818 InsertHeadList (&gBrowserContextList, &Context->Link);\r
3819}\r
3820\r
3821\r
3822/**\r
3823 Restore globals used by previous call to SendForm().\r
3824\r
3825**/\r
3826VOID\r
3827RestoreBrowserContext (\r
3828 VOID\r
3829 )\r
3830{\r
3831 LIST_ENTRY *Link;\r
3832 BROWSER_CONTEXT *Context;\r
3833\r
3834 ASSERT (gBrowserContextCount != 0);\r
3835 gBrowserContextCount--;\r
3836 if (gBrowserContextCount == 0) {\r
3837 //\r
3838 // This is not reentry of SendForm(), no context to restore\r
3839 //\r
3840 return;\r
3841 }\r
3842\r
3843 ASSERT (!IsListEmpty (&gBrowserContextList));\r
3844\r
3845 Link = GetFirstNode (&gBrowserContextList);\r
3846 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
3847\r
3848 //\r
3849 // Restore FormBrowser context\r
3850 //\r
3851 gBannerData = Context->BannerData;\r
3852 gClassOfVfr = Context->ClassOfVfr;\r
3853 gFunctionKeySetting = Context->FunctionKeySetting;\r
3854 gResetRequired = Context->ResetRequired;\r
ce6d12cc 3855 gDirection = Context->Direction;\r
ce6d12cc 3856 gEnterString = Context->EnterString;\r
3857 gEnterCommitString = Context->EnterCommitString;\r
3858 gEnterEscapeString = Context->EnterEscapeString;\r
3859 gEscapeString = Context->EscapeString;\r
ce6d12cc 3860 gMoveHighlight = Context->MoveHighlight;\r
3861 gMakeSelection = Context->MakeSelection;\r
3862 gDecNumericInput = Context->DecNumericInput;\r
3863 gHexNumericInput = Context->HexNumericInput;\r
3864 gToggleCheckBox = Context->ToggleCheckBox;\r
3865 gPromptForData = Context->PromptForData;\r
3866 gPromptForPassword = Context->PromptForPassword;\r
3867 gPromptForNewPassword = Context->PromptForNewPassword;\r
3868 gConfirmPassword = Context->ConfirmPassword;\r
3869 gConfirmError = Context->ConfirmError;\r
3870 gPassowordInvalid = Context->PassowordInvalid;\r
3871 gPressEnter = Context->PressEnter;\r
3872 gEmptyString = Context->EmptyString;\r
3873 gAreYouSure = Context->AreYouSure;\r
3874 gYesResponse = Context->YesResponse;\r
3875 gNoResponse = Context->NoResponse;\r
3876 gMiniString = Context->MiniString;\r
3877 gPlusString = Context->PlusString;\r
3878 gMinusString = Context->MinusString;\r
3879 gAdjustNumber = Context->AdjustNumber;\r
3880 gSaveChanges = Context->SaveChanges;\r
3881 gOptionMismatch = Context->OptionMismatch;\r
2bb526f3 3882 gFormSuppress = Context->FormSuppress;\r
ce6d12cc 3883 gPromptBlockWidth = Context->PromptBlockWidth;\r
3884 gOptionBlockWidth = Context->OptionBlockWidth;\r
3885 gHelpBlockWidth = Context->HelpBlockWidth;\r
3886 gOldFormSet = Context->OldFormSet;\r
3887 gMenuRefreshHead = Context->MenuRefreshHead;\r
3888\r
3889 CopyMem (&gScreenDimensions, &Context->ScreenDimensions, sizeof (gScreenDimensions));\r
3890 CopyMem (&gMenuOption, &Context->MenuOption, sizeof (gMenuOption));\r
3891\r
3892 //\r
3893 // Remove from FormBrowser context list\r
3894 //\r
3895 RemoveEntryList (&Context->Link);\r
3896 gBS->FreePool (Context);\r
3897}\r
48a9d5f7
LG
3898\r
3899/**\r
3900 Find the matched FormSet context in the backup maintain list based on HiiHandle.\r
3901 \r
3902 @param Handle The Hii Handle.\r
3903 \r
3904 @return the found FormSet context. If no found, NULL will return.\r
3905\r
3906**/\r
3907FORM_BROWSER_FORMSET * \r
3908GetFormSetFromHiiHandle (\r
3909 EFI_HII_HANDLE Handle\r
3910 )\r
3911{\r
3912 LIST_ENTRY *Link;\r
3913 FORM_BROWSER_FORMSET *FormSet;\r
3914\r
3915 Link = GetFirstNode (&gBrowserFormSetList);\r
3916 while (!IsNull (&gBrowserFormSetList, Link)) {\r
3917 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
3918 if (FormSet->HiiHandle == Handle) {\r
3919 return FormSet;\r
3920 }\r
3921 Link = GetNextNode (&gBrowserFormSetList, Link);\r
3922 }\r
3923 \r
3924 return NULL;\r
3925}\r
3926\r
3927/**\r
3928 Check whether the input HII handle is the FormSet that is being used.\r
3929 \r
3930 @param Handle The Hii Handle.\r
3931 \r
3932 @retval TRUE HII handle is being used.\r
3933 @retval FALSE HII handle is not being used.\r
3934\r
3935**/\r
3936BOOLEAN\r
3937IsHiiHandleInBrowserContext (\r
3938 EFI_HII_HANDLE Handle\r
3939 )\r
3940{\r
3941 LIST_ENTRY *Link;\r
3942 BROWSER_CONTEXT *Context;\r
3943\r
3944 //\r
3945 // HiiHandle is Current FormSet.\r
3946 //\r
3947 if ((gOldFormSet != NULL) && (gOldFormSet->HiiHandle == Handle)) {\r
3948 return TRUE;\r
3949 }\r
3950\r
3951 //\r
3952 // Check whether HiiHandle is in BrowserContext.\r
3953 //\r
3954 Link = GetFirstNode (&gBrowserContextList);\r
3955 while (!IsNull (&gBrowserContextList, Link)) {\r
3956 Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
3957 if (Context->OldFormSet->HiiHandle == Handle) {\r
3958 //\r
3959 // HiiHandle is in BrowserContext\r
3960 //\r
3961 return TRUE;\r
3962 }\r
3963 Link = GetNextNode (&gBrowserContextList, Link);\r
3964 }\r
3965 \r
3966 return FALSE;\r
3967}\r
3968\r
3969/**\r
3970 Find the registered HotKey based on KeyData.\r
3971 \r
3972 @param[in] KeyData A pointer to a buffer that describes the keystroke\r
3973 information for the hot key.\r
3974\r
3975 @return The registered HotKey context. If no found, NULL will return.\r
3976**/\r
3977BROWSER_HOT_KEY *\r
3978GetHotKeyFromRegisterList (\r
3979 IN EFI_INPUT_KEY *KeyData\r
3980 )\r
3981{\r
3982 LIST_ENTRY *Link;\r
3983 BROWSER_HOT_KEY *HotKey;\r
3984\r
3985 Link = GetFirstNode (&gBrowserHotKeyList);\r
3986 while (!IsNull (&gBrowserHotKeyList, Link)) {\r
3987 HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
3988 if (HotKey->KeyData->ScanCode == KeyData->ScanCode) {\r
3989 return HotKey;\r
3990 }\r
3991 Link = GetNextNode (&gBrowserHotKeyList, Link);\r
3992 }\r
3993 \r
3994 return NULL;\r
3995}\r
3996\r
3997/**\r
3998 Configure what scope the hot key will impact.\r
3999 All hot keys have the same scope. The mixed hot keys with the different level are not supported.\r
4000 If no scope is set, the default scope will be FormSet level.\r
4001 After all registered hot keys are removed, previous Scope can reset to another level.\r
4002 \r
4003 @param[in] Scope Scope level to be set. \r
4004 \r
4005 @retval EFI_SUCCESS Scope is set correctly.\r
4006 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE. \r
4007 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.\r
4008\r
4009**/\r
4010EFI_STATUS\r
4011EFIAPI\r
4012SetScope (\r
4013 IN BROWSER_SETTING_SCOPE Scope\r
4014 )\r
4015{\r
4016 if (Scope >= MaxLevel) {\r
4017 return EFI_INVALID_PARAMETER;\r
4018 }\r
4019 \r
4020 //\r
4021 // When no hot key registered in system or on the first setting,\r
4022 // Scope can be set.\r
4023 //\r
4024 if (mBrowserScopeFirstSet || IsListEmpty (&gBrowserHotKeyList)) {\r
4025 gBrowserSettingScope = Scope;\r
4026 mBrowserScopeFirstSet = FALSE;\r
4027 } else if (Scope != gBrowserSettingScope) {\r
4028 return EFI_UNSUPPORTED;\r
4029 }\r
4030\r
4031 return EFI_SUCCESS;\r
4032}\r
4033\r
4034/**\r
4035 Register the hot key with its browser action, or unregistered the hot key.\r
4036 Only support hot key that is not printable character (control key, function key, etc.).\r
4037 If the action value is zero, the hot key will be unregistered if it has been registered.\r
4038 If the same hot key has been registered, the new action and help string will override the previous ones.\r
4039 \r
4040 @param[in] KeyData A pointer to a buffer that describes the keystroke\r
4041 information for the hot key. Its type is EFI_INPUT_KEY to \r
4042 be supported by all ConsoleIn devices.\r
4043 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed. \r
4044 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.\r
4045 @param[in] HelpString Help string that describes the hot key information.\r
4046 Its value may be NULL for the unregistered hot key.\r
4047 \r
4048 @retval EFI_SUCCESS Hot key is registered or unregistered.\r
4049 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.\r
4050 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.\r
4051 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.\r
4052**/\r
4053EFI_STATUS\r
4054EFIAPI\r
4055RegisterHotKey (\r
4056 IN EFI_INPUT_KEY *KeyData,\r
4057 IN UINT32 Action,\r
4058 IN UINT16 DefaultId,\r
4059 IN EFI_STRING HelpString OPTIONAL\r
4060 )\r
4061{\r
4062 BROWSER_HOT_KEY *HotKey;\r
4063\r
4064 //\r
4065 // Check input parameters.\r
4066 //\r
4067 if (KeyData == NULL || KeyData->UnicodeChar != CHAR_NULL || \r
4068 (Action != BROWSER_ACTION_UNREGISTER && HelpString == NULL)) {\r
4069 return EFI_INVALID_PARAMETER;\r
4070 }\r
4071\r
4072 //\r
4073 // Check whether the input KeyData is in BrowserHotKeyList.\r
4074 //\r
4075 HotKey = GetHotKeyFromRegisterList (KeyData);\r
4076 \r
4077 //\r
4078 // Unregister HotKey\r
4079 //\r
4080 if (Action == BROWSER_ACTION_UNREGISTER) {\r
4081 if (HotKey != NULL) {\r
4082 //\r
4083 // The registered HotKey is found. \r
4084 // Remove it from List, and free its resource.\r
4085 //\r
4086 RemoveEntryList (&HotKey->Link);\r
4087 FreePool (HotKey->KeyData);\r
4088 FreePool (HotKey->HelpString);\r
4089 return EFI_SUCCESS;\r
4090 } else {\r
4091 //\r
4092 // The registered HotKey is not found. \r
4093 //\r
4094 return EFI_NOT_FOUND;\r
4095 }\r
4096 }\r
4097 \r
4098 //\r
4099 // Register HotKey into List.\r
4100 //\r
4101 if (HotKey == NULL) {\r
4102 //\r
4103 // Create new Key, and add it into List.\r
4104 //\r
4105 HotKey = AllocateZeroPool (sizeof (BROWSER_HOT_KEY));\r
4106 ASSERT (HotKey != NULL);\r
4107 HotKey->Signature = BROWSER_HOT_KEY_SIGNATURE;\r
4108 HotKey->KeyData = AllocateCopyPool (sizeof (EFI_INPUT_KEY), KeyData);\r
4109 InsertTailList (&gBrowserHotKeyList, &HotKey->Link);\r
4110 }\r
4111\r
4112 //\r
4113 // Fill HotKey information.\r
4114 //\r
4115 HotKey->Action = Action;\r
4116 HotKey->DefaultId = DefaultId;\r
4117 if (HotKey->HelpString != NULL) {\r
4118 FreePool (HotKey->HelpString);\r
4119 }\r
4120 HotKey->HelpString = AllocateCopyPool (StrSize (HelpString), HelpString);\r
4121\r
4122 return EFI_SUCCESS;\r
4123}\r
4124\r
4125/**\r
4126 Register Exit handler function. \r
4127 When more than one handler function is registered, the latter one will override the previous one. \r
4128 When NULL handler is specified, the previous Exit handler will be unregistered. \r
4129 \r
4130 @param[in] Handler Pointer to handler function. \r
4131\r
4132**/\r
4133VOID\r
4134EFIAPI\r
4135RegiserExitHandler (\r
4136 IN EXIT_HANDLER Handler\r
4137 )\r
4138{\r
4139 ExitHandlerFunction = Handler;\r
4140 return;\r
4141}\r
4142\r
4143/**\r
4144 Create reminder to let user to choose save or discard the changed browser data.\r
4145 Caller can use it to actively check the changed browser data.\r
4146\r
4147 @retval BROWSER_NO_CHANGES No browser data is changed.\r
4148 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.\r
4149 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.\r
4150\r
4151**/\r
4152UINT32\r
4153EFIAPI\r
4154SaveReminder (\r
4155 VOID\r
4156 )\r
4157{\r
4158 LIST_ENTRY *Link;\r
4159 FORM_BROWSER_FORMSET *FormSet;\r
4160 BOOLEAN IsDataChanged;\r
4161 UINT32 DataSavedAction;\r
4162 CHAR16 *YesResponse;\r
4163 CHAR16 *NoResponse;\r
4164 CHAR16 *EmptyString;\r
4165 CHAR16 *ChangeReminderString;\r
4166 CHAR16 *SaveConfirmString;\r
4167 EFI_INPUT_KEY Key;\r
48a9d5f7
LG
4168\r
4169 DataSavedAction = BROWSER_NO_CHANGES;\r
4170 IsDataChanged = FALSE;\r
4171 Link = GetFirstNode (&gBrowserFormSetList);\r
4172 while (!IsNull (&gBrowserFormSetList, Link)) {\r
4173 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
4174 if (IsNvUpdateRequired (FormSet)) {\r
4175 IsDataChanged = TRUE;\r
4176 break;\r
4177 }\r
4178 Link = GetNextNode (&gBrowserFormSetList, Link);\r
4179 }\r
4180 \r
4181 //\r
4182 // No data is changed. No save is required. \r
4183 //\r
4184 if (!IsDataChanged) {\r
4185 return DataSavedAction;\r
4186 }\r
4187 \r
4188 //\r
4189 // If data is changed, prompt user\r
4190 //\r
7538d536 4191 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
48a9d5f7
LG
4192\r
4193 YesResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);\r
4194 ASSERT (YesResponse != NULL);\r
4195 NoResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);\r
4196 ASSERT (NoResponse != NULL);\r
4197 EmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
4198 ChangeReminderString = GetToken (STRING_TOKEN (CHANGE_REMINDER), gHiiHandle);\r
4199 SaveConfirmString = GetToken (STRING_TOKEN (SAVE_CONFIRM), gHiiHandle);\r
4200\r
4201 do {\r
4202 CreateDialog (4, TRUE, 0, NULL, &Key, EmptyString, ChangeReminderString, SaveConfirmString, EmptyString);\r
4203 } while\r
4204 (((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse[0] | UPPER_LOWER_CASE_OFFSET)) &&\r
4205 ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse[0] | UPPER_LOWER_CASE_OFFSET))\r
4206 );\r
4207\r
4208 //\r
4209 // If the user hits the YesResponse key\r
4210 //\r
4211 if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse[0] | UPPER_LOWER_CASE_OFFSET)) {\r
4212 SubmitForm (NULL, NULL, SystemLevel);\r
4213 DataSavedAction = BROWSER_SAVE_CHANGES;\r
4214 } else {\r
4215 DiscardForm (NULL, NULL, SystemLevel);\r
4216 DataSavedAction = BROWSER_DISCARD_CHANGES;\r
4217 gResetRequired = FALSE;\r
4218 }\r
4219\r
4220 FreePool (YesResponse);\r
4221 FreePool (NoResponse);\r
4222 FreePool (EmptyString);\r
4223 FreePool (SaveConfirmString);\r
4224 FreePool (ChangeReminderString);\r
4225\r
4226 return DataSavedAction;\r
4227}\r