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