Vishal Bhoj | 82c8071 | 2015-12-15 21:13:33 +0530 | [diff] [blame^] | 1 | /** @file
|
| 2 | Entry and initialization module for the browser.
|
| 3 |
|
| 4 | Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
|
| 5 | This program and the accompanying materials
|
| 6 | are licensed and made available under the terms and conditions of the BSD License
|
| 7 | which accompanies this distribution. The full text of the license may be found at
|
| 8 | http://opensource.org/licenses/bsd-license.php
|
| 9 |
|
| 10 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
| 11 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
| 12 |
|
| 13 | **/
|
| 14 |
|
| 15 | #include "Setup.h"
|
| 16 |
|
| 17 | SETUP_DRIVER_PRIVATE_DATA mPrivateData = {
|
| 18 | SETUP_DRIVER_SIGNATURE,
|
| 19 | NULL,
|
| 20 | {
|
| 21 | SendForm,
|
| 22 | BrowserCallback
|
| 23 | },
|
| 24 | {
|
| 25 | SetScope,
|
| 26 | RegisterHotKey,
|
| 27 | RegiserExitHandler,
|
| 28 | SaveReminder
|
| 29 | },
|
| 30 | {
|
| 31 | BROWSER_EXTENSION2_VERSION_1_1,
|
| 32 | SetScope,
|
| 33 | RegisterHotKey,
|
| 34 | RegiserExitHandler,
|
| 35 | IsBrowserDataModified,
|
| 36 | ExecuteAction,
|
| 37 | {NULL,NULL},
|
| 38 | {NULL,NULL},
|
| 39 | IsResetRequired
|
| 40 | }
|
| 41 | };
|
| 42 |
|
| 43 | EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
|
| 44 | EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;
|
| 45 | EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *mPathFromText;
|
| 46 | EDKII_FORM_DISPLAY_ENGINE_PROTOCOL *mFormDisplay;
|
| 47 |
|
| 48 | UINTN gBrowserContextCount = 0;
|
| 49 | LIST_ENTRY gBrowserContextList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList);
|
| 50 | LIST_ENTRY gBrowserFormSetList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList);
|
| 51 | LIST_ENTRY gBrowserHotKeyList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList);
|
| 52 | LIST_ENTRY gBrowserStorageList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList);
|
| 53 | LIST_ENTRY gBrowserSaveFailFormSetList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserSaveFailFormSetList);
|
| 54 |
|
| 55 | BOOLEAN mSystemSubmit = FALSE;
|
| 56 | BOOLEAN gResetRequired;
|
| 57 | BOOLEAN gExitRequired;
|
| 58 | BROWSER_SETTING_SCOPE gBrowserSettingScope = FormSetLevel;
|
| 59 | BOOLEAN mBrowserScopeFirstSet = TRUE;
|
| 60 | EXIT_HANDLER ExitHandlerFunction = NULL;
|
| 61 | FORM_BROWSER_FORMSET *mSystemLevelFormSet;
|
| 62 |
|
| 63 | //
|
| 64 | // Browser Global Strings
|
| 65 | //
|
| 66 | CHAR16 *gEmptyString;
|
| 67 | CHAR16 *mUnknownString = L"!";
|
| 68 |
|
| 69 | EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
|
| 70 |
|
| 71 | extern EFI_GUID mCurrentFormSetGuid;
|
| 72 | extern EFI_HII_HANDLE mCurrentHiiHandle;
|
| 73 | extern UINT16 mCurrentFormId;
|
| 74 | extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData;
|
| 75 |
|
| 76 | /**
|
| 77 | Create a menu with specified formset GUID and form ID, and add it as a child
|
| 78 | of the given parent menu.
|
| 79 |
|
| 80 | @param HiiHandle Hii handle related to this formset.
|
| 81 | @param FormSetGuid The Formset Guid of menu to be added.
|
| 82 | @param FormId The Form ID of menu to be added.
|
| 83 | @param QuestionId The question id of this menu to be added.
|
| 84 |
|
| 85 | @return A pointer to the newly added menu or NULL if memory is insufficient.
|
| 86 |
|
| 87 | **/
|
| 88 | FORM_ENTRY_INFO *
|
| 89 | UiAddMenuList (
|
| 90 | IN EFI_HII_HANDLE HiiHandle,
|
| 91 | IN EFI_GUID *FormSetGuid,
|
| 92 | IN UINT16 FormId,
|
| 93 | IN UINT16 QuestionId
|
| 94 | )
|
| 95 | {
|
| 96 | FORM_ENTRY_INFO *MenuList;
|
| 97 |
|
| 98 | MenuList = AllocateZeroPool (sizeof (FORM_ENTRY_INFO));
|
| 99 | if (MenuList == NULL) {
|
| 100 | return NULL;
|
| 101 | }
|
| 102 |
|
| 103 | MenuList->Signature = FORM_ENTRY_INFO_SIGNATURE;
|
| 104 |
|
| 105 | MenuList->HiiHandle = HiiHandle;
|
| 106 | CopyMem (&MenuList->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));
|
| 107 | MenuList->FormId = FormId;
|
| 108 | MenuList->QuestionId = QuestionId;
|
| 109 |
|
| 110 | //
|
| 111 | // If parent is not specified, it is the root Form of a Formset
|
| 112 | //
|
| 113 | InsertTailList (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link);
|
| 114 |
|
| 115 | return MenuList;
|
| 116 | }
|
| 117 |
|
| 118 | /**
|
| 119 | Return the form id for the input hiihandle and formset.
|
| 120 |
|
| 121 | @param HiiHandle HiiHandle for FormSet.
|
| 122 | @param FormSetGuid The Formset GUID of the menu to search.
|
| 123 |
|
| 124 | @return First form's id for this form set.
|
| 125 |
|
| 126 | **/
|
| 127 | EFI_FORM_ID
|
| 128 | GetFirstFormId (
|
| 129 | IN EFI_HII_HANDLE HiiHandle,
|
| 130 | IN EFI_GUID *FormSetGuid
|
| 131 | )
|
| 132 | {
|
| 133 | LIST_ENTRY *Link;
|
| 134 | FORM_BROWSER_FORM *Form;
|
| 135 |
|
| 136 | Link = GetFirstNode (&gCurrentSelection->FormSet->FormListHead);
|
| 137 | Form = FORM_BROWSER_FORM_FROM_LINK (Link);
|
| 138 |
|
| 139 | return Form->FormId;
|
| 140 | }
|
| 141 |
|
| 142 | /**
|
| 143 | Search Menu with given FormSetGuid and FormId in all cached menu list.
|
| 144 |
|
| 145 | @param HiiHandle HiiHandle for FormSet.
|
| 146 | @param FormSetGuid The Formset GUID of the menu to search.
|
| 147 | @param FormId The Form ID of menu to search.
|
| 148 |
|
| 149 | @return A pointer to menu found or NULL if not found.
|
| 150 |
|
| 151 | **/
|
| 152 | FORM_ENTRY_INFO *
|
| 153 | UiFindMenuList (
|
| 154 | IN EFI_HII_HANDLE HiiHandle,
|
| 155 | IN EFI_GUID *FormSetGuid,
|
| 156 | IN UINT16 FormId
|
| 157 | )
|
| 158 | {
|
| 159 | LIST_ENTRY *Link;
|
| 160 | FORM_ENTRY_INFO *MenuList;
|
| 161 | FORM_ENTRY_INFO *RetMenu;
|
| 162 | EFI_FORM_ID FirstFormId;
|
| 163 |
|
| 164 | RetMenu = NULL;
|
| 165 |
|
| 166 | Link = GetFirstNode (&mPrivateData.FormBrowserEx2.FormViewHistoryHead);
|
| 167 | while (!IsNull (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, Link)) {
|
| 168 | MenuList = FORM_ENTRY_INFO_FROM_LINK (Link);
|
| 169 | Link = GetNextNode (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, Link);
|
| 170 |
|
| 171 | //
|
| 172 | // If already find the menu, free the menus behind it.
|
| 173 | //
|
| 174 | if (RetMenu != NULL) {
|
| 175 | RemoveEntryList (&MenuList->Link);
|
| 176 | FreePool (MenuList);
|
| 177 | continue;
|
| 178 | }
|
| 179 |
|
| 180 | //
|
| 181 | // Find the same FromSet.
|
| 182 | //
|
| 183 | if (MenuList->HiiHandle == HiiHandle) {
|
| 184 | if (CompareGuid (&MenuList->FormSetGuid, &gZeroGuid)) {
|
| 185 | //
|
| 186 | // FormSetGuid is not specified.
|
| 187 | //
|
| 188 | RetMenu = MenuList;
|
| 189 | } else if (CompareGuid (&MenuList->FormSetGuid, FormSetGuid)) {
|
| 190 | if (MenuList->FormId == FormId) {
|
| 191 | RetMenu = MenuList;
|
| 192 | } else if (FormId == 0 || MenuList->FormId == 0 ) {
|
| 193 | FirstFormId = GetFirstFormId (HiiHandle, FormSetGuid);
|
| 194 | if ((FormId == 0 && FirstFormId == MenuList->FormId) || (MenuList->FormId ==0 && FirstFormId == FormId)) {
|
| 195 | RetMenu = MenuList;
|
| 196 | }
|
| 197 | }
|
| 198 | }
|
| 199 | }
|
| 200 | }
|
| 201 |
|
| 202 | return RetMenu;
|
| 203 | }
|
| 204 |
|
| 205 | /**
|
| 206 | Find parent menu for current menu.
|
| 207 |
|
| 208 | @param CurrentMenu Current Menu
|
| 209 | @param SettingLevel Whether find parent menu in Form Level or Formset level.
|
| 210 | In form level, just find the parent menu;
|
| 211 | In formset level, find the parent menu which has different
|
| 212 | formset guid value.
|
| 213 |
|
| 214 | @retval The parent menu for current menu.
|
| 215 | **/
|
| 216 | FORM_ENTRY_INFO *
|
| 217 | UiFindParentMenu (
|
| 218 | IN FORM_ENTRY_INFO *CurrentMenu,
|
| 219 | IN BROWSER_SETTING_SCOPE SettingLevel
|
| 220 | )
|
| 221 | {
|
| 222 | FORM_ENTRY_INFO *ParentMenu;
|
| 223 | LIST_ENTRY *Link;
|
| 224 |
|
| 225 | ASSERT (SettingLevel == FormLevel || SettingLevel == FormSetLevel);
|
| 226 |
|
| 227 | if (CurrentMenu == NULL) {
|
| 228 | return NULL;
|
| 229 | }
|
| 230 |
|
| 231 | ParentMenu = NULL;
|
| 232 | Link = &CurrentMenu->Link;
|
| 233 |
|
| 234 | while (Link->BackLink != &mPrivateData.FormBrowserEx2.FormViewHistoryHead) {
|
| 235 | ParentMenu = FORM_ENTRY_INFO_FROM_LINK (Link->BackLink);
|
| 236 |
|
| 237 | if (SettingLevel == FormLevel) {
|
| 238 | //
|
| 239 | // For FormLevel, just find the parent menu, return.
|
| 240 | //
|
| 241 | break;
|
| 242 | }
|
| 243 |
|
| 244 | if (!CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {
|
| 245 | //
|
| 246 | // For SystemLevel, must find the menu which has different formset.
|
| 247 | //
|
| 248 | break;
|
| 249 | }
|
| 250 |
|
| 251 | Link = Link->BackLink;
|
| 252 | }
|
| 253 |
|
| 254 | //
|
| 255 | // Not find the parent menu, just return NULL.
|
| 256 | //
|
| 257 | if (Link->BackLink == &mPrivateData.FormBrowserEx2.FormViewHistoryHead) {
|
| 258 | return NULL;
|
| 259 | }
|
| 260 |
|
| 261 | return ParentMenu;
|
| 262 | }
|
| 263 |
|
| 264 | /**
|
| 265 | Free Menu list linked list.
|
| 266 |
|
| 267 | @param MenuListHead One Menu list point in the menu list.
|
| 268 |
|
| 269 | **/
|
| 270 | VOID
|
| 271 | UiFreeMenuList (
|
| 272 | LIST_ENTRY *MenuListHead
|
| 273 | )
|
| 274 | {
|
| 275 | FORM_ENTRY_INFO *MenuList;
|
| 276 |
|
| 277 | while (!IsListEmpty (MenuListHead)) {
|
| 278 | MenuList = FORM_ENTRY_INFO_FROM_LINK (MenuListHead->ForwardLink);
|
| 279 | RemoveEntryList (&MenuList->Link);
|
| 280 |
|
| 281 | FreePool (MenuList);
|
| 282 | }
|
| 283 | }
|
| 284 |
|
| 285 | /**
|
| 286 | Copy current Menu list to the new menu list.
|
| 287 |
|
| 288 | @param NewMenuListHead New create Menu list.
|
| 289 | @param CurrentMenuListHead Current Menu list.
|
| 290 |
|
| 291 | **/
|
| 292 | VOID
|
| 293 | UiCopyMenuList (
|
| 294 | OUT LIST_ENTRY *NewMenuListHead,
|
| 295 | IN LIST_ENTRY *CurrentMenuListHead
|
| 296 | )
|
| 297 | {
|
| 298 | LIST_ENTRY *Link;
|
| 299 | FORM_ENTRY_INFO *MenuList;
|
| 300 | FORM_ENTRY_INFO *NewMenuEntry;
|
| 301 |
|
| 302 | //
|
| 303 | // If new menu list not empty, free it first.
|
| 304 | //
|
| 305 | UiFreeMenuList (NewMenuListHead);
|
| 306 |
|
| 307 | Link = GetFirstNode (CurrentMenuListHead);
|
| 308 | while (!IsNull (CurrentMenuListHead, Link)) {
|
| 309 | MenuList = FORM_ENTRY_INFO_FROM_LINK (Link);
|
| 310 | Link = GetNextNode (CurrentMenuListHead, Link);
|
| 311 |
|
| 312 | NewMenuEntry = AllocateZeroPool (sizeof (FORM_ENTRY_INFO));
|
| 313 | ASSERT (NewMenuEntry != NULL);
|
| 314 | NewMenuEntry->Signature = FORM_ENTRY_INFO_SIGNATURE;
|
| 315 | NewMenuEntry->HiiHandle = MenuList->HiiHandle;
|
| 316 | CopyMem (&NewMenuEntry->FormSetGuid, &MenuList->FormSetGuid, sizeof (EFI_GUID));
|
| 317 | NewMenuEntry->FormId = MenuList->FormId;
|
| 318 | NewMenuEntry->QuestionId = MenuList->QuestionId;
|
| 319 |
|
| 320 | InsertTailList (NewMenuListHead, &NewMenuEntry->Link);
|
| 321 | }
|
| 322 | }
|
| 323 |
|
| 324 | /**
|
| 325 | Load all hii formset to the browser.
|
| 326 |
|
| 327 | **/
|
| 328 | VOID
|
| 329 | LoadAllHiiFormset (
|
| 330 | VOID
|
| 331 | )
|
| 332 | {
|
| 333 | FORM_BROWSER_FORMSET *LocalFormSet;
|
| 334 | EFI_HII_HANDLE *HiiHandles;
|
| 335 | UINTN Index;
|
| 336 | EFI_GUID ZeroGuid;
|
| 337 | EFI_STATUS Status;
|
| 338 | FORM_BROWSER_FORMSET *OldFormset;
|
| 339 |
|
| 340 | OldFormset = mSystemLevelFormSet;
|
| 341 |
|
| 342 | //
|
| 343 | // Get all the Hii handles
|
| 344 | //
|
| 345 | HiiHandles = HiiGetHiiHandles (NULL);
|
| 346 | ASSERT (HiiHandles != NULL);
|
| 347 |
|
| 348 | //
|
| 349 | // Search for formset of each class type
|
| 350 | //
|
| 351 | for (Index = 0; HiiHandles[Index] != NULL; Index++) {
|
| 352 | //
|
| 353 | // Check HiiHandles[Index] does exist in global maintain list.
|
| 354 | //
|
| 355 | if (GetFormSetFromHiiHandle (HiiHandles[Index]) != NULL) {
|
| 356 | continue;
|
| 357 | }
|
| 358 |
|
| 359 | //
|
| 360 | // Initilize FormSet Setting
|
| 361 | //
|
| 362 | LocalFormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
|
| 363 | ASSERT (LocalFormSet != NULL);
|
| 364 | mSystemLevelFormSet = LocalFormSet;
|
| 365 |
|
| 366 | ZeroMem (&ZeroGuid, sizeof (ZeroGuid));
|
| 367 | Status = InitializeFormSet (HiiHandles[Index], &ZeroGuid, LocalFormSet);
|
| 368 | if (EFI_ERROR (Status) || IsListEmpty (&LocalFormSet->FormListHead)) {
|
| 369 | DestroyFormSet (LocalFormSet);
|
| 370 | continue;
|
| 371 | }
|
| 372 | InitializeCurrentSetting (LocalFormSet);
|
| 373 |
|
| 374 | //
|
| 375 | // Initilize Questions' Value
|
| 376 | //
|
| 377 | Status = LoadFormSetConfig (NULL, LocalFormSet);
|
| 378 | if (EFI_ERROR (Status)) {
|
| 379 | DestroyFormSet (LocalFormSet);
|
| 380 | continue;
|
| 381 | }
|
| 382 | }
|
| 383 |
|
| 384 | //
|
| 385 | // Free resources, and restore gOldFormSet and gClassOfVfr
|
| 386 | //
|
| 387 | FreePool (HiiHandles);
|
| 388 |
|
| 389 | mSystemLevelFormSet = OldFormset;
|
| 390 | }
|
| 391 |
|
| 392 | /**
|
| 393 | Pop up the error info.
|
| 394 |
|
| 395 | @param BrowserStatus The input browser status.
|
| 396 | @param HiiHandle The Hiihandle for this opcode.
|
| 397 | @param OpCode The opcode use to get the erro info and timeout value.
|
| 398 | @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.
|
| 399 |
|
| 400 | **/
|
| 401 | UINT32
|
| 402 | PopupErrorMessage (
|
| 403 | IN UINT32 BrowserStatus,
|
| 404 | IN EFI_HII_HANDLE HiiHandle,
|
| 405 | IN EFI_IFR_OP_HEADER *OpCode, OPTIONAL
|
| 406 | IN CHAR16 *ErrorString
|
| 407 | )
|
| 408 | {
|
| 409 | FORM_DISPLAY_ENGINE_STATEMENT *Statement;
|
| 410 | USER_INPUT UserInputData;
|
| 411 |
|
| 412 | Statement = NULL;
|
| 413 |
|
| 414 | if (OpCode != NULL) {
|
| 415 | Statement = AllocateZeroPool (sizeof(FORM_DISPLAY_ENGINE_STATEMENT));
|
| 416 | ASSERT (Statement != NULL);
|
| 417 | Statement->OpCode = OpCode;
|
| 418 | gDisplayFormData.HighLightedStatement = Statement;
|
| 419 | }
|
| 420 |
|
| 421 | //
|
| 422 | // Used to compatible with old display engine.
|
| 423 | // New display engine not use this field.
|
| 424 | //
|
| 425 | gDisplayFormData.ErrorString = ErrorString;
|
| 426 | gDisplayFormData.BrowserStatus = BrowserStatus;
|
| 427 |
|
| 428 | if (HiiHandle != NULL) {
|
| 429 | gDisplayFormData.HiiHandle = HiiHandle;
|
| 430 | }
|
| 431 |
|
| 432 | mFormDisplay->FormDisplay (&gDisplayFormData, &UserInputData);
|
| 433 |
|
| 434 | gDisplayFormData.BrowserStatus = BROWSER_SUCCESS;
|
| 435 | gDisplayFormData.ErrorString = NULL;
|
| 436 |
|
| 437 | if (OpCode != NULL) {
|
| 438 | FreePool (Statement);
|
| 439 | }
|
| 440 |
|
| 441 | return UserInputData.Action;
|
| 442 | }
|
| 443 |
|
| 444 | /**
|
| 445 | This is the routine which an external caller uses to direct the browser
|
| 446 | where to obtain it's information.
|
| 447 |
|
| 448 |
|
| 449 | @param This The Form Browser protocol instanse.
|
| 450 | @param Handles A pointer to an array of Handles. If HandleCount > 1 we
|
| 451 | display a list of the formsets for the handles specified.
|
| 452 | @param HandleCount The number of Handles specified in Handle.
|
| 453 | @param FormSetGuid This field points to the EFI_GUID which must match the Guid
|
| 454 | field in the EFI_IFR_FORM_SET op-code for the specified
|
| 455 | forms-based package. If FormSetGuid is NULL, then this
|
| 456 | function will display the first found forms package.
|
| 457 | @param FormId This field specifies which EFI_IFR_FORM to render as the first
|
| 458 | displayable page. If this field has a value of 0x0000, then
|
| 459 | the forms browser will render the specified forms in their encoded order.
|
| 460 | @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
|
| 461 | characters.
|
| 462 | @param ActionRequest Points to the action recommended by the form.
|
| 463 |
|
| 464 | @retval EFI_SUCCESS The function completed successfully.
|
| 465 | @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
|
| 466 | @retval EFI_NOT_FOUND No valid forms could be found to display.
|
| 467 |
|
| 468 | **/
|
| 469 | EFI_STATUS
|
| 470 | EFIAPI
|
| 471 | SendForm (
|
| 472 | IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,
|
| 473 | IN EFI_HII_HANDLE *Handles,
|
| 474 | IN UINTN HandleCount,
|
| 475 | IN EFI_GUID *FormSetGuid, OPTIONAL
|
| 476 | IN UINT16 FormId, OPTIONAL
|
| 477 | IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL
|
| 478 | OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL
|
| 479 | )
|
| 480 | {
|
| 481 | EFI_STATUS Status;
|
| 482 | UI_MENU_SELECTION *Selection;
|
| 483 | UINTN Index;
|
| 484 | FORM_BROWSER_FORMSET *FormSet;
|
| 485 | FORM_ENTRY_INFO *MenuList;
|
| 486 |
|
| 487 | //
|
| 488 | // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
|
| 489 | //
|
| 490 | if (mFormDisplay == NULL) {
|
| 491 | return EFI_UNSUPPORTED;
|
| 492 | }
|
| 493 |
|
| 494 | //
|
| 495 | // Save globals used by SendForm()
|
| 496 | //
|
| 497 | SaveBrowserContext ();
|
| 498 |
|
| 499 | gResetRequired = FALSE;
|
| 500 | gExitRequired = FALSE;
|
| 501 | Status = EFI_SUCCESS;
|
| 502 | gEmptyString = L"";
|
| 503 | gDisplayFormData.ScreenDimensions = (EFI_SCREEN_DESCRIPTOR *) ScreenDimensions;
|
| 504 |
|
| 505 | for (Index = 0; Index < HandleCount; Index++) {
|
| 506 | Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));
|
| 507 | ASSERT (Selection != NULL);
|
| 508 |
|
| 509 | Selection->Handle = Handles[Index];
|
| 510 | if (FormSetGuid != NULL) {
|
| 511 | CopyMem (&Selection->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));
|
| 512 | Selection->FormId = FormId;
|
| 513 | } else {
|
| 514 | CopyMem (&Selection->FormSetGuid, &gEfiHiiPlatformSetupFormsetGuid, sizeof (EFI_GUID));
|
| 515 | }
|
| 516 |
|
| 517 | do {
|
| 518 | FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
|
| 519 | ASSERT (FormSet != NULL);
|
| 520 |
|
| 521 | //
|
| 522 | // Validate the HiiHandle
|
| 523 | // if validate failed, find the first validate parent HiiHandle.
|
| 524 | //
|
| 525 | if (!ValidateHiiHandle(Selection->Handle)) {
|
| 526 | FindNextMenu (Selection, FormSetLevel);
|
| 527 | }
|
| 528 |
|
| 529 | //
|
| 530 | // Initialize internal data structures of FormSet
|
| 531 | //
|
| 532 | Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet);
|
| 533 | if (EFI_ERROR (Status) || IsListEmpty (&FormSet->FormListHead)) {
|
| 534 | DestroyFormSet (FormSet);
|
| 535 | break;
|
| 536 | }
|
| 537 | Selection->FormSet = FormSet;
|
| 538 | mSystemLevelFormSet = FormSet;
|
| 539 |
|
| 540 | //
|
| 541 | // Display this formset
|
| 542 | //
|
| 543 | gCurrentSelection = Selection;
|
| 544 |
|
| 545 | Status = SetupBrowser (Selection);
|
| 546 |
|
| 547 | gCurrentSelection = NULL;
|
| 548 | mSystemLevelFormSet = NULL;
|
| 549 |
|
| 550 | //
|
| 551 | // If no data is changed, don't need to save current FormSet into the maintain list.
|
| 552 | //
|
| 553 | if (!IsNvUpdateRequiredForFormSet (FormSet)) {
|
| 554 | CleanBrowserStorage(FormSet);
|
| 555 | RemoveEntryList (&FormSet->Link);
|
| 556 | DestroyFormSet (FormSet);
|
| 557 | }
|
| 558 |
|
| 559 | if (EFI_ERROR (Status)) {
|
| 560 | break;
|
| 561 | }
|
| 562 | } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);
|
| 563 |
|
| 564 | FreePool (Selection);
|
| 565 | }
|
| 566 |
|
| 567 | if (ActionRequest != NULL) {
|
| 568 | *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
|
| 569 | if (gResetRequired) {
|
| 570 | *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;
|
| 571 | }
|
| 572 | }
|
| 573 |
|
| 574 | mFormDisplay->ExitDisplay();
|
| 575 |
|
| 576 | //
|
| 577 | // Clear the menu history data.
|
| 578 | //
|
| 579 | while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) {
|
| 580 | MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink);
|
| 581 | RemoveEntryList (&MenuList->Link);
|
| 582 | FreePool (MenuList);
|
| 583 | }
|
| 584 |
|
| 585 | //
|
| 586 | // Restore globals used by SendForm()
|
| 587 | //
|
| 588 | RestoreBrowserContext ();
|
| 589 |
|
| 590 | return Status;
|
| 591 | }
|
| 592 |
|
| 593 | /**
|
| 594 | Get or set data to the storage.
|
| 595 |
|
| 596 | @param ResultsDataSize The size of the buffer associatedwith ResultsData.
|
| 597 | @param ResultsData A string returned from an IFR browser or
|
| 598 | equivalent. The results string will have no
|
| 599 | routing information in them.
|
| 600 | @param RetrieveData A BOOLEAN field which allows an agent to retrieve
|
| 601 | (if RetrieveData = TRUE) data from the uncommitted
|
| 602 | browser state information or set (if RetrieveData
|
| 603 | = FALSE) data in the uncommitted browser state
|
| 604 | information.
|
| 605 | @param Storage The pointer to the storage.
|
| 606 |
|
| 607 | @retval EFI_SUCCESS The results have been distributed or are awaiting
|
| 608 | distribution.
|
| 609 |
|
| 610 | **/
|
| 611 | EFI_STATUS
|
| 612 | ProcessStorage (
|
| 613 | IN OUT UINTN *ResultsDataSize,
|
| 614 | IN OUT EFI_STRING *ResultsData,
|
| 615 | IN BOOLEAN RetrieveData,
|
| 616 | IN BROWSER_STORAGE *Storage
|
| 617 | )
|
| 618 | {
|
| 619 | CHAR16 *ConfigResp;
|
| 620 | EFI_STATUS Status;
|
| 621 | CHAR16 *StrPtr;
|
| 622 | UINTN BufferSize;
|
| 623 | UINTN TmpSize;
|
| 624 | FORMSET_STORAGE *BrowserStorage;
|
| 625 |
|
| 626 | if (RetrieveData) {
|
| 627 | //
|
| 628 | // Generate <ConfigResp>
|
| 629 | //
|
| 630 | Status = StorageToConfigResp (Storage, &ConfigResp, Storage->ConfigRequest, TRUE);
|
| 631 | if (EFI_ERROR (Status)) {
|
| 632 | return Status;
|
| 633 | }
|
| 634 |
|
| 635 | //
|
| 636 | // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
|
| 637 | // Also need to consider add "\0" at first time.
|
| 638 | //
|
| 639 | StrPtr = StrStr (ConfigResp, L"PATH");
|
| 640 | ASSERT (StrPtr != NULL);
|
| 641 | StrPtr = StrStr (StrPtr, L"&");
|
| 642 | StrPtr += 1;
|
| 643 | BufferSize = StrSize (StrPtr);
|
| 644 |
|
| 645 | //
|
| 646 | // Copy the data if the input buffer is bigger enough.
|
| 647 | //
|
| 648 | if (*ResultsDataSize >= BufferSize) {
|
| 649 | StrCpy (*ResultsData, StrPtr);
|
| 650 | }
|
| 651 |
|
| 652 | *ResultsDataSize = BufferSize;
|
| 653 | FreePool (ConfigResp);
|
| 654 | } else {
|
| 655 | //
|
| 656 | // Prepare <ConfigResp>
|
| 657 | //
|
| 658 | BrowserStorage = GetFstStgFromBrsStg (Storage);
|
| 659 | ASSERT (BrowserStorage != NULL);
|
| 660 | TmpSize = StrLen (*ResultsData);
|
| 661 | BufferSize = (TmpSize + StrLen (BrowserStorage->ConfigHdr) + 2) * sizeof (CHAR16);
|
| 662 | ConfigResp = AllocateZeroPool (BufferSize);
|
| 663 | ASSERT (ConfigResp != NULL);
|
| 664 |
|
| 665 | StrCpy (ConfigResp, BrowserStorage->ConfigHdr);
|
| 666 | StrCat (ConfigResp, L"&");
|
| 667 | StrCat (ConfigResp, *ResultsData);
|
| 668 |
|
| 669 | //
|
| 670 | // Update Browser uncommited data
|
| 671 | //
|
| 672 | Status = ConfigRespToStorage (Storage, ConfigResp);
|
| 673 | FreePool (ConfigResp);
|
| 674 | if (EFI_ERROR (Status)) {
|
| 675 | return Status;
|
| 676 | }
|
| 677 | }
|
| 678 |
|
| 679 | return EFI_SUCCESS;
|
| 680 | }
|
| 681 |
|
| 682 | /**
|
| 683 | This routine called this service in the browser to retrieve or set certain uncommitted
|
| 684 | state information that resides in the open formsets.
|
| 685 |
|
| 686 | @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
|
| 687 | instance.
|
| 688 | @param ResultsDataSize A pointer to the size of the buffer associated
|
| 689 | with ResultsData.
|
| 690 | @param ResultsData A string returned from an IFR browser or
|
| 691 | equivalent. The results string will have no
|
| 692 | routing information in them.
|
| 693 | @param RetrieveData A BOOLEAN field which allows an agent to retrieve
|
| 694 | (if RetrieveData = TRUE) data from the uncommitted
|
| 695 | browser state information or set (if RetrieveData
|
| 696 | = FALSE) data in the uncommitted browser state
|
| 697 | information.
|
| 698 | @param VariableGuid An optional field to indicate the target variable
|
| 699 | GUID name to use.
|
| 700 | @param VariableName An optional field to indicate the target
|
| 701 | human-readable variable name.
|
| 702 |
|
| 703 | @retval EFI_SUCCESS The results have been distributed or are awaiting
|
| 704 | distribution.
|
| 705 | @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
|
| 706 | contain the results data.
|
| 707 |
|
| 708 | **/
|
| 709 | EFI_STATUS
|
| 710 | EFIAPI
|
| 711 | BrowserCallback (
|
| 712 | IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,
|
| 713 | IN OUT UINTN *ResultsDataSize,
|
| 714 | IN OUT EFI_STRING ResultsData,
|
| 715 | IN BOOLEAN RetrieveData,
|
| 716 | IN CONST EFI_GUID *VariableGuid, OPTIONAL
|
| 717 | IN CONST CHAR16 *VariableName OPTIONAL
|
| 718 | )
|
| 719 | {
|
| 720 | EFI_STATUS Status;
|
| 721 | LIST_ENTRY *Link;
|
| 722 | BROWSER_STORAGE *Storage;
|
| 723 | FORMSET_STORAGE *FormsetStorage;
|
| 724 | UINTN TotalSize;
|
| 725 | BOOLEAN Found;
|
| 726 |
|
| 727 | if (ResultsDataSize == NULL || ResultsData == NULL) {
|
| 728 | return EFI_INVALID_PARAMETER;
|
| 729 | }
|
| 730 |
|
| 731 | TotalSize = *ResultsDataSize;
|
| 732 | Storage = NULL;
|
| 733 | Found = FALSE;
|
| 734 | Status = EFI_SUCCESS;
|
| 735 |
|
| 736 | if (VariableGuid != NULL) {
|
| 737 | //
|
| 738 | // Try to find target storage in the current formset.
|
| 739 | //
|
| 740 | Link = GetFirstNode (&gBrowserStorageList);
|
| 741 | while (!IsNull (&gBrowserStorageList, Link)) {
|
| 742 | Storage = BROWSER_STORAGE_FROM_LINK (Link);
|
| 743 | Link = GetNextNode (&gBrowserStorageList, Link);
|
| 744 | //
|
| 745 | // Check the current storage.
|
| 746 | //
|
| 747 | if (!CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {
|
| 748 | continue;
|
| 749 | }
|
| 750 |
|
| 751 | if (Storage->Type == EFI_HII_VARSTORE_BUFFER ||
|
| 752 | Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
|
| 753 | //
|
| 754 | // Buffer storage require both GUID and Name
|
| 755 | //
|
| 756 | if (VariableName == NULL) {
|
| 757 | return EFI_NOT_FOUND;
|
| 758 | }
|
| 759 |
|
| 760 | if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {
|
| 761 | continue;
|
| 762 | }
|
| 763 | }
|
| 764 |
|
| 765 | if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE ||
|
| 766 | Storage->Type == EFI_HII_VARSTORE_BUFFER) {
|
| 767 | if (mSystemLevelFormSet == NULL || mSystemLevelFormSet->HiiHandle == NULL) {
|
| 768 | return EFI_NOT_FOUND;
|
| 769 | }
|
| 770 |
|
| 771 | if (Storage->HiiHandle != mSystemLevelFormSet->HiiHandle) {
|
| 772 | continue;
|
| 773 | }
|
| 774 | }
|
| 775 |
|
| 776 | Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, Storage);
|
| 777 | if (EFI_ERROR (Status)) {
|
| 778 | return Status;
|
| 779 | }
|
| 780 |
|
| 781 | if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
|
| 782 | ConfigRequestAdjust (Storage, ResultsData, TRUE);
|
| 783 | }
|
| 784 |
|
| 785 | //
|
| 786 | // Different formsets may have same varstore, so here just set the flag
|
| 787 | // not exit the circle.
|
| 788 | //
|
| 789 | Found = TRUE;
|
| 790 | break;
|
| 791 | }
|
| 792 |
|
| 793 | if (!Found) {
|
| 794 | return EFI_NOT_FOUND;
|
| 795 | }
|
| 796 | } else {
|
| 797 | //
|
| 798 | // GUID/Name is not specified, take the first storage in FormSet
|
| 799 | //
|
| 800 | if (mSystemLevelFormSet == NULL) {
|
| 801 | return EFI_NOT_READY;
|
| 802 | }
|
| 803 |
|
| 804 | //
|
| 805 | // Generate <ConfigResp>
|
| 806 | //
|
| 807 | Link = GetFirstNode (&mSystemLevelFormSet->StorageListHead);
|
| 808 | if (IsNull (&mSystemLevelFormSet->StorageListHead, Link)) {
|
| 809 | return EFI_UNSUPPORTED;
|
| 810 | }
|
| 811 |
|
| 812 | FormsetStorage = FORMSET_STORAGE_FROM_LINK (Link);
|
| 813 |
|
| 814 | Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, FormsetStorage->BrowserStorage);
|
| 815 | if (EFI_ERROR (Status)) {
|
| 816 | return Status;
|
| 817 | }
|
| 818 | }
|
| 819 |
|
| 820 | if (RetrieveData) {
|
| 821 | Status = TotalSize <= *ResultsDataSize ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;
|
| 822 | *ResultsDataSize = TotalSize;
|
| 823 | }
|
| 824 |
|
| 825 | return Status;
|
| 826 |
|
| 827 | }
|
| 828 |
|
| 829 |
|
| 830 | /**
|
| 831 | Callback function for SimpleTextInEx protocol install events
|
| 832 |
|
| 833 | @param Event the event that is signaled.
|
| 834 | @param Context not used here.
|
| 835 |
|
| 836 | **/
|
| 837 | VOID
|
| 838 | EFIAPI
|
| 839 | FormDisplayCallback (
|
| 840 | IN EFI_EVENT Event,
|
| 841 | IN VOID *Context
|
| 842 | )
|
| 843 | {
|
| 844 | if (mFormDisplay != NULL) {
|
| 845 | return;
|
| 846 | }
|
| 847 |
|
| 848 | gBS->LocateProtocol (
|
| 849 | &gEdkiiFormDisplayEngineProtocolGuid,
|
| 850 | NULL,
|
| 851 | (VOID **) &mFormDisplay
|
| 852 | );
|
| 853 | }
|
| 854 |
|
| 855 | /**
|
| 856 | Initialize Setup Browser driver.
|
| 857 |
|
| 858 | @param ImageHandle The image handle.
|
| 859 | @param SystemTable The system table.
|
| 860 |
|
| 861 | @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
|
| 862 | @return Other value if failed to initialize the Setup Browser module.
|
| 863 |
|
| 864 | **/
|
| 865 | EFI_STATUS
|
| 866 | EFIAPI
|
| 867 | InitializeSetup (
|
| 868 | IN EFI_HANDLE ImageHandle,
|
| 869 | IN EFI_SYSTEM_TABLE *SystemTable
|
| 870 | )
|
| 871 | {
|
| 872 | EFI_STATUS Status;
|
| 873 | VOID *Registration;
|
| 874 |
|
| 875 | //
|
| 876 | // Locate required Hii relative protocols
|
| 877 | //
|
| 878 | Status = gBS->LocateProtocol (
|
| 879 | &gEfiHiiDatabaseProtocolGuid,
|
| 880 | NULL,
|
| 881 | (VOID **) &mHiiDatabase
|
| 882 | );
|
| 883 | ASSERT_EFI_ERROR (Status);
|
| 884 |
|
| 885 | Status = gBS->LocateProtocol (
|
| 886 | &gEfiHiiConfigRoutingProtocolGuid,
|
| 887 | NULL,
|
| 888 | (VOID **) &mHiiConfigRouting
|
| 889 | );
|
| 890 | ASSERT_EFI_ERROR (Status);
|
| 891 |
|
| 892 | Status = gBS->LocateProtocol (
|
| 893 | &gEfiDevicePathFromTextProtocolGuid,
|
| 894 | NULL,
|
| 895 | (VOID **) &mPathFromText
|
| 896 | );
|
| 897 |
|
| 898 | //
|
| 899 | // Install FormBrowser2 protocol
|
| 900 | //
|
| 901 | mPrivateData.Handle = NULL;
|
| 902 | Status = gBS->InstallProtocolInterface (
|
| 903 | &mPrivateData.Handle,
|
| 904 | &gEfiFormBrowser2ProtocolGuid,
|
| 905 | EFI_NATIVE_INTERFACE,
|
| 906 | &mPrivateData.FormBrowser2
|
| 907 | );
|
| 908 | ASSERT_EFI_ERROR (Status);
|
| 909 |
|
| 910 | //
|
| 911 | // Install FormBrowserEx2 protocol
|
| 912 | //
|
| 913 | InitializeListHead (&mPrivateData.FormBrowserEx2.FormViewHistoryHead);
|
| 914 | InitializeListHead (&mPrivateData.FormBrowserEx2.OverrideQestListHead);
|
| 915 | mPrivateData.Handle = NULL;
|
| 916 | Status = gBS->InstallProtocolInterface (
|
| 917 | &mPrivateData.Handle,
|
| 918 | &gEdkiiFormBrowserEx2ProtocolGuid,
|
| 919 | EFI_NATIVE_INTERFACE,
|
| 920 | &mPrivateData.FormBrowserEx2
|
| 921 | );
|
| 922 | ASSERT_EFI_ERROR (Status);
|
| 923 |
|
| 924 | Status = gBS->InstallProtocolInterface (
|
| 925 | &mPrivateData.Handle,
|
| 926 | &gEfiFormBrowserExProtocolGuid,
|
| 927 | EFI_NATIVE_INTERFACE,
|
| 928 | &mPrivateData.FormBrowserEx
|
| 929 | );
|
| 930 | ASSERT_EFI_ERROR (Status);
|
| 931 |
|
| 932 | InitializeDisplayFormData ();
|
| 933 |
|
| 934 | Status = gBS->LocateProtocol (
|
| 935 | &gEdkiiFormDisplayEngineProtocolGuid,
|
| 936 | NULL,
|
| 937 | (VOID **) &mFormDisplay
|
| 938 | );
|
| 939 |
|
| 940 | if (EFI_ERROR (Status)) {
|
| 941 | EfiCreateProtocolNotifyEvent (
|
| 942 | &gEdkiiFormDisplayEngineProtocolGuid,
|
| 943 | TPL_CALLBACK,
|
| 944 | FormDisplayCallback,
|
| 945 | NULL,
|
| 946 | &Registration
|
| 947 | );
|
| 948 | }
|
| 949 |
|
| 950 | return EFI_SUCCESS;
|
| 951 | }
|
| 952 |
|
| 953 |
|
| 954 | /**
|
| 955 | Create a new string in HII Package List.
|
| 956 |
|
| 957 | @param String The String to be added
|
| 958 | @param HiiHandle The package list in the HII database to insert the
|
| 959 | specified string.
|
| 960 |
|
| 961 | @return The output string.
|
| 962 |
|
| 963 | **/
|
| 964 | EFI_STRING_ID
|
| 965 | NewString (
|
| 966 | IN CHAR16 *String,
|
| 967 | IN EFI_HII_HANDLE HiiHandle
|
| 968 | )
|
| 969 | {
|
| 970 | EFI_STRING_ID StringId;
|
| 971 |
|
| 972 | StringId = HiiSetString (HiiHandle, 0, String, NULL);
|
| 973 | ASSERT (StringId != 0);
|
| 974 |
|
| 975 | return StringId;
|
| 976 | }
|
| 977 |
|
| 978 |
|
| 979 | /**
|
| 980 | Delete a string from HII Package List.
|
| 981 |
|
| 982 | @param StringId Id of the string in HII database.
|
| 983 | @param HiiHandle The HII package list handle.
|
| 984 |
|
| 985 | @retval EFI_SUCCESS The string was deleted successfully.
|
| 986 |
|
| 987 | **/
|
| 988 | EFI_STATUS
|
| 989 | DeleteString (
|
| 990 | IN EFI_STRING_ID StringId,
|
| 991 | IN EFI_HII_HANDLE HiiHandle
|
| 992 | )
|
| 993 | {
|
| 994 | CHAR16 NullChar;
|
| 995 |
|
| 996 | NullChar = CHAR_NULL;
|
| 997 | HiiSetString (HiiHandle, StringId, &NullChar, NULL);
|
| 998 | return EFI_SUCCESS;
|
| 999 | }
|
| 1000 |
|
| 1001 |
|
| 1002 | /**
|
| 1003 | Get the string based on the StringId and HII Package List Handle.
|
| 1004 |
|
| 1005 | @param Token The String's ID.
|
| 1006 | @param HiiHandle The package list in the HII database to search for
|
| 1007 | the specified string.
|
| 1008 |
|
| 1009 | @return The output string.
|
| 1010 |
|
| 1011 | **/
|
| 1012 | CHAR16 *
|
| 1013 | GetToken (
|
| 1014 | IN EFI_STRING_ID Token,
|
| 1015 | IN EFI_HII_HANDLE HiiHandle
|
| 1016 | )
|
| 1017 | {
|
| 1018 | EFI_STRING String;
|
| 1019 |
|
| 1020 | if (HiiHandle == NULL) {
|
| 1021 | return NULL;
|
| 1022 | }
|
| 1023 |
|
| 1024 | String = HiiGetString (HiiHandle, Token, NULL);
|
| 1025 | if (String == NULL) {
|
| 1026 | String = AllocateCopyPool (StrSize (mUnknownString), mUnknownString);
|
| 1027 | ASSERT (String != NULL);
|
| 1028 | }
|
| 1029 | return (CHAR16 *) String;
|
| 1030 | }
|
| 1031 |
|
| 1032 |
|
| 1033 | /**
|
| 1034 | Allocate new memory and then copy the Unicode string Source to Destination.
|
| 1035 |
|
| 1036 | @param Dest Location to copy string
|
| 1037 | @param Src String to copy
|
| 1038 |
|
| 1039 | **/
|
| 1040 | VOID
|
| 1041 | NewStringCpy (
|
| 1042 | IN OUT CHAR16 **Dest,
|
| 1043 | IN CHAR16 *Src
|
| 1044 | )
|
| 1045 | {
|
| 1046 | if (*Dest != NULL) {
|
| 1047 | FreePool (*Dest);
|
| 1048 | }
|
| 1049 | *Dest = AllocateCopyPool (StrSize (Src), Src);
|
| 1050 | ASSERT (*Dest != NULL);
|
| 1051 | }
|
| 1052 |
|
| 1053 |
|
| 1054 | /**
|
| 1055 | Allocate new memory and concatinate Source on the end of Destination.
|
| 1056 |
|
| 1057 | @param Dest String to added to the end of.
|
| 1058 | @param Src String to concatinate.
|
| 1059 |
|
| 1060 | **/
|
| 1061 | VOID
|
| 1062 | NewStringCat (
|
| 1063 | IN OUT CHAR16 **Dest,
|
| 1064 | IN CHAR16 *Src
|
| 1065 | )
|
| 1066 | {
|
| 1067 | CHAR16 *NewString;
|
| 1068 | UINTN TmpSize;
|
| 1069 |
|
| 1070 | if (*Dest == NULL) {
|
| 1071 | NewStringCpy (Dest, Src);
|
| 1072 | return;
|
| 1073 | }
|
| 1074 |
|
| 1075 | TmpSize = StrSize (*Dest);
|
| 1076 | NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1);
|
| 1077 | ASSERT (NewString != NULL);
|
| 1078 |
|
| 1079 | StrCpy (NewString, *Dest);
|
| 1080 | StrCat (NewString, Src);
|
| 1081 |
|
| 1082 | FreePool (*Dest);
|
| 1083 | *Dest = NewString;
|
| 1084 | }
|
| 1085 |
|
| 1086 | /**
|
| 1087 | Get Value for given Name from a NameValue Storage.
|
| 1088 |
|
| 1089 | @param Storage The NameValue Storage.
|
| 1090 | @param Name The Name.
|
| 1091 | @param Value The retured Value.
|
| 1092 | @param GetValueFrom Where to get source value, from EditValue or Value.
|
| 1093 |
|
| 1094 | @retval EFI_SUCCESS Value found for given Name.
|
| 1095 | @retval EFI_NOT_FOUND No such Name found in NameValue storage.
|
| 1096 |
|
| 1097 | **/
|
| 1098 | EFI_STATUS
|
| 1099 | GetValueByName (
|
| 1100 | IN BROWSER_STORAGE *Storage,
|
| 1101 | IN CHAR16 *Name,
|
| 1102 | IN OUT CHAR16 **Value,
|
| 1103 | IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
|
| 1104 | )
|
| 1105 | {
|
| 1106 | LIST_ENTRY *Link;
|
| 1107 | NAME_VALUE_NODE *Node;
|
| 1108 |
|
| 1109 | if (GetValueFrom != GetSetValueWithEditBuffer && GetValueFrom != GetSetValueWithBuffer) {
|
| 1110 | return EFI_INVALID_PARAMETER;
|
| 1111 | }
|
| 1112 |
|
| 1113 | *Value = NULL;
|
| 1114 |
|
| 1115 | Link = GetFirstNode (&Storage->NameValueListHead);
|
| 1116 | while (!IsNull (&Storage->NameValueListHead, Link)) {
|
| 1117 | Node = NAME_VALUE_NODE_FROM_LINK (Link);
|
| 1118 |
|
| 1119 | if (StrCmp (Name, Node->Name) == 0) {
|
| 1120 | if (GetValueFrom == GetSetValueWithEditBuffer) {
|
| 1121 | NewStringCpy (Value, Node->EditValue);
|
| 1122 | } else {
|
| 1123 | NewStringCpy (Value, Node->Value);
|
| 1124 | }
|
| 1125 | return EFI_SUCCESS;
|
| 1126 | }
|
| 1127 |
|
| 1128 | Link = GetNextNode (&Storage->NameValueListHead, Link);
|
| 1129 | }
|
| 1130 |
|
| 1131 | return EFI_NOT_FOUND;
|
| 1132 | }
|
| 1133 |
|
| 1134 |
|
| 1135 | /**
|
| 1136 | Set Value of given Name in a NameValue Storage.
|
| 1137 |
|
| 1138 | @param Storage The NameValue Storage.
|
| 1139 | @param Name The Name.
|
| 1140 | @param Value The Value to set.
|
| 1141 | @param SetValueTo Whether update editValue or Value.
|
| 1142 | @param ReturnNode The node use the input name.
|
| 1143 |
|
| 1144 | @retval EFI_SUCCESS Value found for given Name.
|
| 1145 | @retval EFI_NOT_FOUND No such Name found in NameValue storage.
|
| 1146 |
|
| 1147 | **/
|
| 1148 | EFI_STATUS
|
| 1149 | SetValueByName (
|
| 1150 | IN BROWSER_STORAGE *Storage,
|
| 1151 | IN CHAR16 *Name,
|
| 1152 | IN CHAR16 *Value,
|
| 1153 | IN GET_SET_QUESTION_VALUE_WITH SetValueTo,
|
| 1154 | OUT NAME_VALUE_NODE **ReturnNode
|
| 1155 | )
|
| 1156 | {
|
| 1157 | LIST_ENTRY *Link;
|
| 1158 | NAME_VALUE_NODE *Node;
|
| 1159 | CHAR16 *Buffer;
|
| 1160 |
|
| 1161 | if (SetValueTo != GetSetValueWithEditBuffer && SetValueTo != GetSetValueWithBuffer) {
|
| 1162 | return EFI_INVALID_PARAMETER;
|
| 1163 | }
|
| 1164 |
|
| 1165 | Link = GetFirstNode (&Storage->NameValueListHead);
|
| 1166 | while (!IsNull (&Storage->NameValueListHead, Link)) {
|
| 1167 | Node = NAME_VALUE_NODE_FROM_LINK (Link);
|
| 1168 |
|
| 1169 | if (StrCmp (Name, Node->Name) == 0) {
|
| 1170 | if (SetValueTo == GetSetValueWithEditBuffer) {
|
| 1171 | Buffer = Node->EditValue;
|
| 1172 | } else {
|
| 1173 | Buffer = Node->Value;
|
| 1174 | }
|
| 1175 | if (Buffer != NULL) {
|
| 1176 | FreePool (Buffer);
|
| 1177 | }
|
| 1178 | Buffer = AllocateCopyPool (StrSize (Value), Value);
|
| 1179 | ASSERT (Buffer != NULL);
|
| 1180 | if (SetValueTo == GetSetValueWithEditBuffer) {
|
| 1181 | Node->EditValue = Buffer;
|
| 1182 | } else {
|
| 1183 | Node->Value = Buffer;
|
| 1184 | }
|
| 1185 |
|
| 1186 | if (ReturnNode != NULL) {
|
| 1187 | *ReturnNode = Node;
|
| 1188 | }
|
| 1189 |
|
| 1190 | return EFI_SUCCESS;
|
| 1191 | }
|
| 1192 |
|
| 1193 | Link = GetNextNode (&Storage->NameValueListHead, Link);
|
| 1194 | }
|
| 1195 |
|
| 1196 | return EFI_NOT_FOUND;
|
| 1197 | }
|
| 1198 |
|
| 1199 |
|
| 1200 | /**
|
| 1201 | Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
|
| 1202 |
|
| 1203 | @param Storage The Storage to be conveted.
|
| 1204 | @param ConfigResp The returned <ConfigResp>.
|
| 1205 | @param ConfigRequest The ConfigRequest string.
|
| 1206 | @param GetEditBuf Get the data from editbuffer or buffer.
|
| 1207 |
|
| 1208 | @retval EFI_SUCCESS Convert success.
|
| 1209 | @retval EFI_INVALID_PARAMETER Incorrect storage type.
|
| 1210 |
|
| 1211 | **/
|
| 1212 | EFI_STATUS
|
| 1213 | StorageToConfigResp (
|
| 1214 | IN BROWSER_STORAGE *Storage,
|
| 1215 | IN CHAR16 **ConfigResp,
|
| 1216 | IN CHAR16 *ConfigRequest,
|
| 1217 | IN BOOLEAN GetEditBuf
|
| 1218 | )
|
| 1219 | {
|
| 1220 | EFI_STATUS Status;
|
| 1221 | EFI_STRING Progress;
|
| 1222 | LIST_ENTRY *Link;
|
| 1223 | NAME_VALUE_NODE *Node;
|
| 1224 | UINT8 *SourceBuf;
|
| 1225 | FORMSET_STORAGE *FormsetStorage;
|
| 1226 |
|
| 1227 | Status = EFI_SUCCESS;
|
| 1228 |
|
| 1229 | switch (Storage->Type) {
|
| 1230 | case EFI_HII_VARSTORE_BUFFER:
|
| 1231 | case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
|
| 1232 | SourceBuf = GetEditBuf ? Storage->EditBuffer : Storage->Buffer;
|
| 1233 | Status = mHiiConfigRouting->BlockToConfig (
|
| 1234 | mHiiConfigRouting,
|
| 1235 | ConfigRequest,
|
| 1236 | SourceBuf,
|
| 1237 | Storage->Size,
|
| 1238 | ConfigResp,
|
| 1239 | &Progress
|
| 1240 | );
|
| 1241 | break;
|
| 1242 |
|
| 1243 | case EFI_HII_VARSTORE_NAME_VALUE:
|
| 1244 | *ConfigResp = NULL;
|
| 1245 | FormsetStorage = GetFstStgFromBrsStg(Storage);
|
| 1246 | ASSERT (FormsetStorage != NULL);
|
| 1247 | NewStringCat (ConfigResp, FormsetStorage->ConfigHdr);
|
| 1248 |
|
| 1249 | Link = GetFirstNode (&Storage->NameValueListHead);
|
| 1250 | while (!IsNull (&Storage->NameValueListHead, Link)) {
|
| 1251 | Node = NAME_VALUE_NODE_FROM_LINK (Link);
|
| 1252 |
|
| 1253 | if (StrStr (ConfigRequest, Node->Name) != NULL) {
|
| 1254 | NewStringCat (ConfigResp, L"&");
|
| 1255 | NewStringCat (ConfigResp, Node->Name);
|
| 1256 | NewStringCat (ConfigResp, L"=");
|
| 1257 | if (GetEditBuf) {
|
| 1258 | NewStringCat (ConfigResp, Node->EditValue);
|
| 1259 | } else {
|
| 1260 | NewStringCat (ConfigResp, Node->Value);
|
| 1261 | }
|
| 1262 | }
|
| 1263 | Link = GetNextNode (&Storage->NameValueListHead, Link);
|
| 1264 | }
|
| 1265 | break;
|
| 1266 |
|
| 1267 | case EFI_HII_VARSTORE_EFI_VARIABLE:
|
| 1268 | default:
|
| 1269 | Status = EFI_INVALID_PARAMETER;
|
| 1270 | break;
|
| 1271 | }
|
| 1272 |
|
| 1273 | return Status;
|
| 1274 | }
|
| 1275 |
|
| 1276 |
|
| 1277 | /**
|
| 1278 | Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
|
| 1279 |
|
| 1280 | @param Storage The Storage to receive the settings.
|
| 1281 | @param ConfigResp The <ConfigResp> to be converted.
|
| 1282 |
|
| 1283 | @retval EFI_SUCCESS Convert success.
|
| 1284 | @retval EFI_INVALID_PARAMETER Incorrect storage type.
|
| 1285 |
|
| 1286 | **/
|
| 1287 | EFI_STATUS
|
| 1288 | ConfigRespToStorage (
|
| 1289 | IN BROWSER_STORAGE *Storage,
|
| 1290 | IN CHAR16 *ConfigResp
|
| 1291 | )
|
| 1292 | {
|
| 1293 | EFI_STATUS Status;
|
| 1294 | EFI_STRING Progress;
|
| 1295 | UINTN BufferSize;
|
| 1296 | CHAR16 *StrPtr;
|
| 1297 | CHAR16 *Name;
|
| 1298 | CHAR16 *Value;
|
| 1299 |
|
| 1300 | Status = EFI_SUCCESS;
|
| 1301 |
|
| 1302 | switch (Storage->Type) {
|
| 1303 | case EFI_HII_VARSTORE_BUFFER:
|
| 1304 | case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
|
| 1305 | BufferSize = Storage->Size;
|
| 1306 | Status = mHiiConfigRouting->ConfigToBlock (
|
| 1307 | mHiiConfigRouting,
|
| 1308 | ConfigResp,
|
| 1309 | Storage->EditBuffer,
|
| 1310 | &BufferSize,
|
| 1311 | &Progress
|
| 1312 | );
|
| 1313 | break;
|
| 1314 |
|
| 1315 | case EFI_HII_VARSTORE_NAME_VALUE:
|
| 1316 | StrPtr = StrStr (ConfigResp, L"PATH");
|
| 1317 | if (StrPtr == NULL) {
|
| 1318 | break;
|
| 1319 | }
|
| 1320 | StrPtr = StrStr (ConfigResp, L"&");
|
| 1321 | while (StrPtr != NULL) {
|
| 1322 | //
|
| 1323 | // Skip '&'
|
| 1324 | //
|
| 1325 | StrPtr = StrPtr + 1;
|
| 1326 | Name = StrPtr;
|
| 1327 | StrPtr = StrStr (StrPtr, L"=");
|
| 1328 | if (StrPtr == NULL) {
|
| 1329 | break;
|
| 1330 | }
|
| 1331 | *StrPtr = 0;
|
| 1332 |
|
| 1333 | //
|
| 1334 | // Skip '='
|
| 1335 | //
|
| 1336 | StrPtr = StrPtr + 1;
|
| 1337 | Value = StrPtr;
|
| 1338 | StrPtr = StrStr (StrPtr, L"&");
|
| 1339 | if (StrPtr != NULL) {
|
| 1340 | *StrPtr = 0;
|
| 1341 | }
|
| 1342 | SetValueByName (Storage, Name, Value, GetSetValueWithEditBuffer, NULL);
|
| 1343 | }
|
| 1344 | break;
|
| 1345 |
|
| 1346 | case EFI_HII_VARSTORE_EFI_VARIABLE:
|
| 1347 | default:
|
| 1348 | Status = EFI_INVALID_PARAMETER;
|
| 1349 | break;
|
| 1350 | }
|
| 1351 |
|
| 1352 | return Status;
|
| 1353 | }
|
| 1354 |
|
| 1355 | /**
|
| 1356 | Convert the buffer value to HiiValue.
|
| 1357 |
|
| 1358 | @param Question The question.
|
| 1359 | @param Value Unicode buffer save the question value.
|
| 1360 |
|
| 1361 | @retval Status whether convert the value success.
|
| 1362 |
|
| 1363 | **/
|
| 1364 | EFI_STATUS
|
| 1365 | BufferToValue (
|
| 1366 | IN OUT FORM_BROWSER_STATEMENT *Question,
|
| 1367 | IN CHAR16 *Value
|
| 1368 | )
|
| 1369 | {
|
| 1370 | CHAR16 *StringPtr;
|
| 1371 | BOOLEAN IsBufferStorage;
|
| 1372 | CHAR16 *DstBuf;
|
| 1373 | CHAR16 TempChar;
|
| 1374 | UINTN LengthStr;
|
| 1375 | UINT8 *Dst;
|
| 1376 | CHAR16 TemStr[5];
|
| 1377 | UINTN Index;
|
| 1378 | UINT8 DigitUint8;
|
| 1379 | BOOLEAN IsString;
|
| 1380 | UINTN Length;
|
| 1381 | EFI_STATUS Status;
|
| 1382 |
|
| 1383 | IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);
|
| 1384 | if (Question->Storage->Type == EFI_HII_VARSTORE_BUFFER ||
|
| 1385 | Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
|
| 1386 | IsBufferStorage = TRUE;
|
| 1387 | } else {
|
| 1388 | IsBufferStorage = FALSE;
|
| 1389 | }
|
| 1390 |
|
| 1391 | //
|
| 1392 | // Question Value is provided by Buffer Storage or NameValue Storage
|
| 1393 | //
|
| 1394 | if (Question->BufferValue != NULL) {
|
| 1395 | //
|
| 1396 | // This Question is password or orderedlist
|
| 1397 | //
|
| 1398 | Dst = Question->BufferValue;
|
| 1399 | } else {
|
| 1400 | //
|
| 1401 | // Other type of Questions
|
| 1402 | //
|
| 1403 | Dst = (UINT8 *) &Question->HiiValue.Value;
|
| 1404 | }
|
| 1405 |
|
| 1406 | //
|
| 1407 | // Temp cut at the end of this section, end with '\0' or '&'.
|
| 1408 | //
|
| 1409 | StringPtr = Value;
|
| 1410 | while (*StringPtr != L'\0' && *StringPtr != L'&') {
|
| 1411 | StringPtr++;
|
| 1412 | }
|
| 1413 | TempChar = *StringPtr;
|
| 1414 | *StringPtr = L'\0';
|
| 1415 |
|
| 1416 | LengthStr = StrLen (Value);
|
| 1417 | Status = EFI_SUCCESS;
|
| 1418 | if (!IsBufferStorage && IsString) {
|
| 1419 | //
|
| 1420 | // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
|
| 1421 | // Add string tail char L'\0' into Length
|
| 1422 | //
|
| 1423 | Length = Question->StorageWidth + sizeof (CHAR16);
|
| 1424 | if (Length < ((LengthStr / 4 + 1) * 2)) {
|
| 1425 | Status = EFI_BUFFER_TOO_SMALL;
|
| 1426 | } else {
|
| 1427 | DstBuf = (CHAR16 *) Dst;
|
| 1428 | ZeroMem (TemStr, sizeof (TemStr));
|
| 1429 | for (Index = 0; Index < LengthStr; Index += 4) {
|
| 1430 | StrnCpy (TemStr, Value + Index, 4);
|
| 1431 | DstBuf[Index/4] = (CHAR16) StrHexToUint64 (TemStr);
|
| 1432 | }
|
| 1433 | //
|
| 1434 | // Add tailing L'\0' character
|
| 1435 | //
|
| 1436 | DstBuf[Index/4] = L'\0';
|
| 1437 | }
|
| 1438 | } else {
|
| 1439 | if (Question->StorageWidth < ((LengthStr + 1) / 2)) {
|
| 1440 | Status = EFI_BUFFER_TOO_SMALL;
|
| 1441 | } else {
|
| 1442 | ZeroMem (TemStr, sizeof (TemStr));
|
| 1443 | for (Index = 0; Index < LengthStr; Index ++) {
|
| 1444 | TemStr[0] = Value[LengthStr - Index - 1];
|
| 1445 | DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
|
| 1446 | if ((Index & 1) == 0) {
|
| 1447 | Dst [Index/2] = DigitUint8;
|
| 1448 | } else {
|
| 1449 | Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);
|
| 1450 | }
|
| 1451 | }
|
| 1452 | }
|
| 1453 | }
|
| 1454 |
|
| 1455 | *StringPtr = TempChar;
|
| 1456 |
|
| 1457 | return Status;
|
| 1458 | }
|
| 1459 |
|
| 1460 | /**
|
| 1461 | Get Question's current Value.
|
| 1462 |
|
| 1463 | @param FormSet FormSet data structure.
|
| 1464 | @param Form Form data structure.
|
| 1465 | @param Question Question to be initialized.
|
| 1466 | @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
|
| 1467 |
|
| 1468 | @retval EFI_SUCCESS The function completed successfully.
|
| 1469 |
|
| 1470 | **/
|
| 1471 | EFI_STATUS
|
| 1472 | GetQuestionValue (
|
| 1473 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 1474 | IN FORM_BROWSER_FORM *Form,
|
| 1475 | IN OUT FORM_BROWSER_STATEMENT *Question,
|
| 1476 | IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
|
| 1477 | )
|
| 1478 | {
|
| 1479 | EFI_STATUS Status;
|
| 1480 | BOOLEAN Enabled;
|
| 1481 | BOOLEAN Pending;
|
| 1482 | UINT8 *Dst;
|
| 1483 | UINTN StorageWidth;
|
| 1484 | EFI_TIME EfiTime;
|
| 1485 | BROWSER_STORAGE *Storage;
|
| 1486 | FORMSET_STORAGE *FormsetStorage;
|
| 1487 | EFI_IFR_TYPE_VALUE *QuestionValue;
|
| 1488 | CHAR16 *ConfigRequest;
|
| 1489 | CHAR16 *Progress;
|
| 1490 | CHAR16 *Result;
|
| 1491 | CHAR16 *Value;
|
| 1492 | UINTN Length;
|
| 1493 | BOOLEAN IsBufferStorage;
|
| 1494 |
|
| 1495 | Status = EFI_SUCCESS;
|
| 1496 | Value = NULL;
|
| 1497 | Result = NULL;
|
| 1498 |
|
| 1499 | if (GetValueFrom >= GetSetValueWithMax) {
|
| 1500 | return EFI_INVALID_PARAMETER;
|
| 1501 | }
|
| 1502 |
|
| 1503 | //
|
| 1504 | // Question value is provided by an Expression, evaluate it
|
| 1505 | //
|
| 1506 | if (Question->ValueExpression != NULL) {
|
| 1507 | Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);
|
| 1508 | if (!EFI_ERROR (Status)) {
|
| 1509 | if (Question->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {
|
| 1510 | ASSERT (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER && Question->HiiValue.Buffer != NULL);
|
| 1511 | if (Question->StorageWidth > Question->ValueExpression->Result.BufferLen) {
|
| 1512 | CopyMem (Question->HiiValue.Buffer, Question->ValueExpression->Result.Buffer, Question->ValueExpression->Result.BufferLen);
|
| 1513 | Question->HiiValue.BufferLen = Question->ValueExpression->Result.BufferLen;
|
| 1514 | } else {
|
| 1515 | CopyMem (Question->HiiValue.Buffer, Question->ValueExpression->Result.Buffer, Question->StorageWidth);
|
| 1516 | Question->HiiValue.BufferLen = Question->StorageWidth;
|
| 1517 | }
|
| 1518 | FreePool (Question->ValueExpression->Result.Buffer);
|
| 1519 | }
|
| 1520 | Question->HiiValue.Type = Question->ValueExpression->Result.Type;
|
| 1521 | CopyMem (&Question->HiiValue.Value, &Question->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));
|
| 1522 | }
|
| 1523 | return Status;
|
| 1524 | }
|
| 1525 |
|
| 1526 | //
|
| 1527 | // Get question value by read expression.
|
| 1528 | //
|
| 1529 | if (Question->ReadExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {
|
| 1530 | Status = EvaluateExpression (FormSet, Form, Question->ReadExpression);
|
| 1531 | if (!EFI_ERROR (Status) &&
|
| 1532 | ((Question->ReadExpression->Result.Type < EFI_IFR_TYPE_OTHER) || (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER))) {
|
| 1533 | //
|
| 1534 | // Only update question value to the valid result.
|
| 1535 | //
|
| 1536 | if (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {
|
| 1537 | ASSERT (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER && Question->HiiValue.Buffer != NULL);
|
| 1538 | if (Question->StorageWidth > Question->ReadExpression->Result.BufferLen) {
|
| 1539 | CopyMem (Question->HiiValue.Buffer, Question->ReadExpression->Result.Buffer, Question->ReadExpression->Result.BufferLen);
|
| 1540 | Question->HiiValue.BufferLen = Question->ReadExpression->Result.BufferLen;
|
| 1541 | } else {
|
| 1542 | CopyMem (Question->HiiValue.Buffer, Question->ReadExpression->Result.Buffer, Question->StorageWidth);
|
| 1543 | Question->HiiValue.BufferLen = Question->StorageWidth;
|
| 1544 | }
|
| 1545 | FreePool (Question->ReadExpression->Result.Buffer);
|
| 1546 | }
|
| 1547 | Question->HiiValue.Type = Question->ReadExpression->Result.Type;
|
| 1548 | CopyMem (&Question->HiiValue.Value, &Question->ReadExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));
|
| 1549 | return EFI_SUCCESS;
|
| 1550 | }
|
| 1551 | }
|
| 1552 |
|
| 1553 | //
|
| 1554 | // Question value is provided by RTC
|
| 1555 | //
|
| 1556 | Storage = Question->Storage;
|
| 1557 | QuestionValue = &Question->HiiValue.Value;
|
| 1558 | if (Storage == NULL) {
|
| 1559 | //
|
| 1560 | // It's a Question without storage, or RTC date/time
|
| 1561 | //
|
| 1562 | if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {
|
| 1563 | //
|
| 1564 | // Date and time define the same Flags bit
|
| 1565 | //
|
| 1566 | switch (Question->Flags & EFI_QF_DATE_STORAGE) {
|
| 1567 | case QF_DATE_STORAGE_TIME:
|
| 1568 | Status = gRT->GetTime (&EfiTime, NULL);
|
| 1569 | break;
|
| 1570 |
|
| 1571 | case QF_DATE_STORAGE_WAKEUP:
|
| 1572 | Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);
|
| 1573 | break;
|
| 1574 |
|
| 1575 | case QF_DATE_STORAGE_NORMAL:
|
| 1576 | default:
|
| 1577 | //
|
| 1578 | // For date/time without storage
|
| 1579 | //
|
| 1580 | return EFI_SUCCESS;
|
| 1581 | }
|
| 1582 |
|
| 1583 | if (EFI_ERROR (Status)) {
|
| 1584 | return Status;
|
| 1585 | }
|
| 1586 |
|
| 1587 | if (Question->Operand == EFI_IFR_DATE_OP) {
|
| 1588 | QuestionValue->date.Year = EfiTime.Year;
|
| 1589 | QuestionValue->date.Month = EfiTime.Month;
|
| 1590 | QuestionValue->date.Day = EfiTime.Day;
|
| 1591 | } else {
|
| 1592 | QuestionValue->time.Hour = EfiTime.Hour;
|
| 1593 | QuestionValue->time.Minute = EfiTime.Minute;
|
| 1594 | QuestionValue->time.Second = EfiTime.Second;
|
| 1595 | }
|
| 1596 | }
|
| 1597 |
|
| 1598 | return EFI_SUCCESS;
|
| 1599 | }
|
| 1600 |
|
| 1601 | //
|
| 1602 | // Question value is provided by EFI variable
|
| 1603 | //
|
| 1604 | StorageWidth = Question->StorageWidth;
|
| 1605 | if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
|
| 1606 | if (Question->BufferValue != NULL) {
|
| 1607 | Dst = Question->BufferValue;
|
| 1608 | } else {
|
| 1609 | Dst = (UINT8 *) QuestionValue;
|
| 1610 | }
|
| 1611 |
|
| 1612 | Status = gRT->GetVariable (
|
| 1613 | Question->VariableName,
|
| 1614 | &Storage->Guid,
|
| 1615 | NULL,
|
| 1616 | &StorageWidth,
|
| 1617 | Dst
|
| 1618 | );
|
| 1619 | //
|
| 1620 | // Always return success, even this EFI variable doesn't exist
|
| 1621 | //
|
| 1622 | return EFI_SUCCESS;
|
| 1623 | }
|
| 1624 |
|
| 1625 | //
|
| 1626 | // Question Value is provided by Buffer Storage or NameValue Storage
|
| 1627 | //
|
| 1628 | if (Question->BufferValue != NULL) {
|
| 1629 | //
|
| 1630 | // This Question is password or orderedlist
|
| 1631 | //
|
| 1632 | Dst = Question->BufferValue;
|
| 1633 | } else {
|
| 1634 | //
|
| 1635 | // Other type of Questions
|
| 1636 | //
|
| 1637 | Dst = (UINT8 *) &Question->HiiValue.Value;
|
| 1638 | }
|
| 1639 |
|
| 1640 | if (Storage->Type == EFI_HII_VARSTORE_BUFFER ||
|
| 1641 | Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
|
| 1642 | IsBufferStorage = TRUE;
|
| 1643 | } else {
|
| 1644 | IsBufferStorage = FALSE;
|
| 1645 | }
|
| 1646 | if (GetValueFrom == GetSetValueWithEditBuffer || GetValueFrom == GetSetValueWithBuffer ) {
|
| 1647 | if (IsBufferStorage) {
|
| 1648 | if (GetValueFrom == GetSetValueWithEditBuffer) {
|
| 1649 | //
|
| 1650 | // Copy from storage Edit buffer
|
| 1651 | //
|
| 1652 | CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);
|
| 1653 | } else {
|
| 1654 | //
|
| 1655 | // Copy from storage Edit buffer
|
| 1656 | //
|
| 1657 | CopyMem (Dst, Storage->Buffer + Question->VarStoreInfo.VarOffset, StorageWidth);
|
| 1658 | }
|
| 1659 | } else {
|
| 1660 | Value = NULL;
|
| 1661 | Status = GetValueByName (Storage, Question->VariableName, &Value, GetValueFrom);
|
| 1662 | if (EFI_ERROR (Status)) {
|
| 1663 | return Status;
|
| 1664 | }
|
| 1665 |
|
| 1666 | ASSERT (Value != NULL);
|
| 1667 | Status = BufferToValue (Question, Value);
|
| 1668 | FreePool (Value);
|
| 1669 | }
|
| 1670 | } else {
|
| 1671 | FormsetStorage = GetFstStgFromVarId(FormSet, Question->VarStoreId);
|
| 1672 | ASSERT (FormsetStorage != NULL);
|
| 1673 | //
|
| 1674 | // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
|
| 1675 | // <ConfigHdr> + "&" + <VariableName>
|
| 1676 | //
|
| 1677 | if (IsBufferStorage) {
|
| 1678 | Length = StrLen (FormsetStorage->ConfigHdr);
|
| 1679 | Length += StrLen (Question->BlockName);
|
| 1680 | } else {
|
| 1681 | Length = StrLen (FormsetStorage->ConfigHdr);
|
| 1682 | Length += StrLen (Question->VariableName) + 1;
|
| 1683 | }
|
| 1684 | ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));
|
| 1685 | ASSERT (ConfigRequest != NULL);
|
| 1686 |
|
| 1687 | StrCpy (ConfigRequest, FormsetStorage->ConfigHdr);
|
| 1688 | if (IsBufferStorage) {
|
| 1689 | StrCat (ConfigRequest, Question->BlockName);
|
| 1690 | } else {
|
| 1691 | StrCat (ConfigRequest, L"&");
|
| 1692 | StrCat (ConfigRequest, Question->VariableName);
|
| 1693 | }
|
| 1694 |
|
| 1695 | //
|
| 1696 | // Request current settings from Configuration Driver
|
| 1697 | //
|
| 1698 | Status = mHiiConfigRouting->ExtractConfig (
|
| 1699 | mHiiConfigRouting,
|
| 1700 | ConfigRequest,
|
| 1701 | &Progress,
|
| 1702 | &Result
|
| 1703 | );
|
| 1704 | FreePool (ConfigRequest);
|
| 1705 | if (EFI_ERROR (Status)) {
|
| 1706 | return Status;
|
| 1707 | }
|
| 1708 |
|
| 1709 | //
|
| 1710 | // Skip <ConfigRequest>
|
| 1711 | //
|
| 1712 | if (IsBufferStorage) {
|
| 1713 | Value = StrStr (Result, L"&VALUE");
|
| 1714 | if (Value == NULL) {
|
| 1715 | FreePool (Result);
|
| 1716 | return EFI_NOT_FOUND;
|
| 1717 | }
|
| 1718 | //
|
| 1719 | // Skip "&VALUE"
|
| 1720 | //
|
| 1721 | Value = Value + 6;
|
| 1722 | } else {
|
| 1723 | Value = Result + Length;
|
| 1724 | }
|
| 1725 | if (*Value != '=') {
|
| 1726 | FreePool (Result);
|
| 1727 | return EFI_NOT_FOUND;
|
| 1728 | }
|
| 1729 | //
|
| 1730 | // Skip '=', point to value
|
| 1731 | //
|
| 1732 | Value = Value + 1;
|
| 1733 |
|
| 1734 | Status = BufferToValue (Question, Value);
|
| 1735 | if (EFI_ERROR (Status)) {
|
| 1736 | FreePool (Result);
|
| 1737 | return Status;
|
| 1738 | }
|
| 1739 |
|
| 1740 | //
|
| 1741 | // Synchronize Edit Buffer
|
| 1742 | //
|
| 1743 | if (IsBufferStorage) {
|
| 1744 | CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);
|
| 1745 | } else {
|
| 1746 | SetValueByName (Storage, Question->VariableName, Value, GetSetValueWithEditBuffer, NULL);
|
| 1747 | }
|
| 1748 |
|
| 1749 | if (Result != NULL) {
|
| 1750 | FreePool (Result);
|
| 1751 | }
|
| 1752 | }
|
| 1753 |
|
| 1754 | return Status;
|
| 1755 | }
|
| 1756 |
|
| 1757 |
|
| 1758 | /**
|
| 1759 | Save Question Value to edit copy(cached) or Storage(uncached).
|
| 1760 |
|
| 1761 | @param FormSet FormSet data structure.
|
| 1762 | @param Form Form data structure.
|
| 1763 | @param Question Pointer to the Question.
|
| 1764 | @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
|
| 1765 |
|
| 1766 | @retval EFI_SUCCESS The function completed successfully.
|
| 1767 |
|
| 1768 | **/
|
| 1769 | EFI_STATUS
|
| 1770 | SetQuestionValue (
|
| 1771 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 1772 | IN FORM_BROWSER_FORM *Form,
|
| 1773 | IN OUT FORM_BROWSER_STATEMENT *Question,
|
| 1774 | IN GET_SET_QUESTION_VALUE_WITH SetValueTo
|
| 1775 | )
|
| 1776 | {
|
| 1777 | EFI_STATUS Status;
|
| 1778 | BOOLEAN Enabled;
|
| 1779 | BOOLEAN Pending;
|
| 1780 | UINT8 *Src;
|
| 1781 | EFI_TIME EfiTime;
|
| 1782 | UINTN BufferLen;
|
| 1783 | UINTN StorageWidth;
|
| 1784 | BROWSER_STORAGE *Storage;
|
| 1785 | FORMSET_STORAGE *FormsetStorage;
|
| 1786 | EFI_IFR_TYPE_VALUE *QuestionValue;
|
| 1787 | CHAR16 *ConfigResp;
|
| 1788 | CHAR16 *Progress;
|
| 1789 | CHAR16 *Value;
|
| 1790 | UINTN Length;
|
| 1791 | BOOLEAN IsBufferStorage;
|
| 1792 | BOOLEAN IsString;
|
| 1793 | UINT8 *TemBuffer;
|
| 1794 | CHAR16 *TemName;
|
| 1795 | CHAR16 *TemString;
|
| 1796 | UINTN Index;
|
| 1797 | NAME_VALUE_NODE *Node;
|
| 1798 |
|
| 1799 | Status = EFI_SUCCESS;
|
| 1800 | Node = NULL;
|
| 1801 |
|
| 1802 | if (SetValueTo >= GetSetValueWithMax) {
|
| 1803 | return EFI_INVALID_PARAMETER;
|
| 1804 | }
|
| 1805 |
|
| 1806 | //
|
| 1807 | // If Question value is provided by an Expression, then it is read only
|
| 1808 | //
|
| 1809 | if (Question->ValueExpression != NULL) {
|
| 1810 | return Status;
|
| 1811 | }
|
| 1812 |
|
| 1813 | //
|
| 1814 | // Before set question value, evaluate its write expression.
|
| 1815 | //
|
| 1816 | if (Question->WriteExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {
|
| 1817 | Status = EvaluateExpression (FormSet, Form, Question->WriteExpression);
|
| 1818 | if (EFI_ERROR (Status)) {
|
| 1819 | return Status;
|
| 1820 | }
|
| 1821 | }
|
| 1822 |
|
| 1823 | //
|
| 1824 | // Question value is provided by RTC
|
| 1825 | //
|
| 1826 | Storage = Question->Storage;
|
| 1827 | QuestionValue = &Question->HiiValue.Value;
|
| 1828 | if (Storage == NULL) {
|
| 1829 | //
|
| 1830 | // It's a Question without storage, or RTC date/time
|
| 1831 | //
|
| 1832 | if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {
|
| 1833 | //
|
| 1834 | // Date and time define the same Flags bit
|
| 1835 | //
|
| 1836 | switch (Question->Flags & EFI_QF_DATE_STORAGE) {
|
| 1837 | case QF_DATE_STORAGE_TIME:
|
| 1838 | Status = gRT->GetTime (&EfiTime, NULL);
|
| 1839 | break;
|
| 1840 |
|
| 1841 | case QF_DATE_STORAGE_WAKEUP:
|
| 1842 | Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);
|
| 1843 | break;
|
| 1844 |
|
| 1845 | case QF_DATE_STORAGE_NORMAL:
|
| 1846 | default:
|
| 1847 | //
|
| 1848 | // For date/time without storage
|
| 1849 | //
|
| 1850 | return EFI_SUCCESS;
|
| 1851 | }
|
| 1852 |
|
| 1853 | if (EFI_ERROR (Status)) {
|
| 1854 | return Status;
|
| 1855 | }
|
| 1856 |
|
| 1857 | if (Question->Operand == EFI_IFR_DATE_OP) {
|
| 1858 | EfiTime.Year = QuestionValue->date.Year;
|
| 1859 | EfiTime.Month = QuestionValue->date.Month;
|
| 1860 | EfiTime.Day = QuestionValue->date.Day;
|
| 1861 | } else {
|
| 1862 | EfiTime.Hour = QuestionValue->time.Hour;
|
| 1863 | EfiTime.Minute = QuestionValue->time.Minute;
|
| 1864 | EfiTime.Second = QuestionValue->time.Second;
|
| 1865 | }
|
| 1866 |
|
| 1867 | if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {
|
| 1868 | Status = gRT->SetTime (&EfiTime);
|
| 1869 | } else {
|
| 1870 | Status = gRT->SetWakeupTime (TRUE, &EfiTime);
|
| 1871 | }
|
| 1872 | }
|
| 1873 |
|
| 1874 | return Status;
|
| 1875 | }
|
| 1876 |
|
| 1877 | //
|
| 1878 | // Question value is provided by EFI variable
|
| 1879 | //
|
| 1880 | StorageWidth = Question->StorageWidth;
|
| 1881 | if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
|
| 1882 | if (Question->BufferValue != NULL) {
|
| 1883 | Src = Question->BufferValue;
|
| 1884 | } else {
|
| 1885 | Src = (UINT8 *) QuestionValue;
|
| 1886 | }
|
| 1887 |
|
| 1888 | Status = gRT->SetVariable (
|
| 1889 | Question->VariableName,
|
| 1890 | &Storage->Guid,
|
| 1891 | Storage->Attributes,
|
| 1892 | StorageWidth,
|
| 1893 | Src
|
| 1894 | );
|
| 1895 | return Status;
|
| 1896 | }
|
| 1897 |
|
| 1898 | //
|
| 1899 | // Question Value is provided by Buffer Storage or NameValue Storage
|
| 1900 | //
|
| 1901 | if (Question->BufferValue != NULL) {
|
| 1902 | Src = Question->BufferValue;
|
| 1903 | } else {
|
| 1904 | Src = (UINT8 *) &Question->HiiValue.Value;
|
| 1905 | }
|
| 1906 |
|
| 1907 | if (Storage->Type == EFI_HII_VARSTORE_BUFFER ||
|
| 1908 | Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
|
| 1909 | IsBufferStorage = TRUE;
|
| 1910 | } else {
|
| 1911 | IsBufferStorage = FALSE;
|
| 1912 | }
|
| 1913 | IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);
|
| 1914 |
|
| 1915 | if (SetValueTo == GetSetValueWithEditBuffer || SetValueTo == GetSetValueWithBuffer) {
|
| 1916 | if (IsBufferStorage) {
|
| 1917 | if (SetValueTo == GetSetValueWithEditBuffer) {
|
| 1918 | //
|
| 1919 | // Copy to storage edit buffer
|
| 1920 | //
|
| 1921 | CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);
|
| 1922 | } else if (SetValueTo == GetSetValueWithBuffer) {
|
| 1923 | //
|
| 1924 | // Copy to storage edit buffer
|
| 1925 | //
|
| 1926 | CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);
|
| 1927 | }
|
| 1928 | } else {
|
| 1929 | if (IsString) {
|
| 1930 | //
|
| 1931 | // Allocate enough string buffer.
|
| 1932 | //
|
| 1933 | Value = NULL;
|
| 1934 | BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);
|
| 1935 | Value = AllocateZeroPool (BufferLen);
|
| 1936 | ASSERT (Value != NULL);
|
| 1937 | //
|
| 1938 | // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
|
| 1939 | //
|
| 1940 | TemName = (CHAR16 *) Src;
|
| 1941 | TemString = Value;
|
| 1942 | for (; *TemName != L'\0'; TemName++) {
|
| 1943 | TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);
|
| 1944 | }
|
| 1945 | } else {
|
| 1946 | BufferLen = StorageWidth * 2 + 1;
|
| 1947 | Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));
|
| 1948 | ASSERT (Value != NULL);
|
| 1949 | //
|
| 1950 | // Convert Buffer to Hex String
|
| 1951 | //
|
| 1952 | TemBuffer = Src + StorageWidth - 1;
|
| 1953 | TemString = Value;
|
| 1954 | for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {
|
| 1955 | TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
|
| 1956 | }
|
| 1957 | }
|
| 1958 |
|
| 1959 | Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo, &Node);
|
| 1960 | FreePool (Value);
|
| 1961 | if (EFI_ERROR (Status)) {
|
| 1962 | return Status;
|
| 1963 | }
|
| 1964 | }
|
| 1965 | } else if (SetValueTo == GetSetValueWithHiiDriver) {
|
| 1966 | //
|
| 1967 | // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
|
| 1968 | // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
|
| 1969 | //
|
| 1970 | if (IsBufferStorage) {
|
| 1971 | Length = StrLen (Question->BlockName) + 7;
|
| 1972 | } else {
|
| 1973 | Length = StrLen (Question->VariableName) + 2;
|
| 1974 | }
|
| 1975 | if (!IsBufferStorage && IsString) {
|
| 1976 | Length += (StrLen ((CHAR16 *) Src) * 4);
|
| 1977 | } else {
|
| 1978 | Length += (StorageWidth * 2);
|
| 1979 | }
|
| 1980 | FormsetStorage = GetFstStgFromVarId(FormSet, Question->VarStoreId);
|
| 1981 | ASSERT (FormsetStorage != NULL);
|
| 1982 | ConfigResp = AllocateZeroPool ((StrLen (FormsetStorage->ConfigHdr) + Length + 1) * sizeof (CHAR16));
|
| 1983 | ASSERT (ConfigResp != NULL);
|
| 1984 |
|
| 1985 | StrCpy (ConfigResp, FormsetStorage->ConfigHdr);
|
| 1986 | if (IsBufferStorage) {
|
| 1987 | StrCat (ConfigResp, Question->BlockName);
|
| 1988 | StrCat (ConfigResp, L"&VALUE=");
|
| 1989 | } else {
|
| 1990 | StrCat (ConfigResp, L"&");
|
| 1991 | StrCat (ConfigResp, Question->VariableName);
|
| 1992 | StrCat (ConfigResp, L"=");
|
| 1993 | }
|
| 1994 |
|
| 1995 | Value = ConfigResp + StrLen (ConfigResp);
|
| 1996 |
|
| 1997 | if (!IsBufferStorage && IsString) {
|
| 1998 | //
|
| 1999 | // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
|
| 2000 | //
|
| 2001 | TemName = (CHAR16 *) Src;
|
| 2002 | TemString = Value;
|
| 2003 | for (; *TemName != L'\0'; TemName++) {
|
| 2004 | TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);
|
| 2005 | }
|
| 2006 | } else {
|
| 2007 | //
|
| 2008 | // Convert Buffer to Hex String
|
| 2009 | //
|
| 2010 | TemBuffer = Src + StorageWidth - 1;
|
| 2011 | TemString = Value;
|
| 2012 | for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {
|
| 2013 | TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
|
| 2014 | }
|
| 2015 | }
|
| 2016 |
|
| 2017 | //
|
| 2018 | // Convert to lower char.
|
| 2019 | //
|
| 2020 | for (TemString = Value; *Value != L'\0'; Value++) {
|
| 2021 | if (*Value >= L'A' && *Value <= L'Z') {
|
| 2022 | *Value = (CHAR16) (*Value - L'A' + L'a');
|
| 2023 | }
|
| 2024 | }
|
| 2025 |
|
| 2026 | //
|
| 2027 | // Submit Question Value to Configuration Driver
|
| 2028 | //
|
| 2029 | Status = mHiiConfigRouting->RouteConfig (
|
| 2030 | mHiiConfigRouting,
|
| 2031 | ConfigResp,
|
| 2032 | &Progress
|
| 2033 | );
|
| 2034 | if (EFI_ERROR (Status)) {
|
| 2035 | FreePool (ConfigResp);
|
| 2036 | return Status;
|
| 2037 | }
|
| 2038 | FreePool (ConfigResp);
|
| 2039 |
|
| 2040 | //
|
| 2041 | // Sync storage, from editbuffer to buffer.
|
| 2042 | //
|
| 2043 | CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);
|
| 2044 | }
|
| 2045 |
|
| 2046 | return Status;
|
| 2047 | }
|
| 2048 |
|
| 2049 |
|
| 2050 | /**
|
| 2051 | Perform nosubmitif check for a Form.
|
| 2052 |
|
| 2053 | @param FormSet FormSet data structure.
|
| 2054 | @param Form Form data structure.
|
| 2055 | @param Question The Question to be validated.
|
| 2056 | @param Type Validation type: NoSubmit
|
| 2057 |
|
| 2058 | @retval EFI_SUCCESS Form validation pass.
|
| 2059 | @retval other Form validation failed.
|
| 2060 |
|
| 2061 | **/
|
| 2062 | EFI_STATUS
|
| 2063 | ValidateQuestion (
|
| 2064 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 2065 | IN FORM_BROWSER_FORM *Form,
|
| 2066 | IN FORM_BROWSER_STATEMENT *Question,
|
| 2067 | IN UINTN Type
|
| 2068 | )
|
| 2069 | {
|
| 2070 | EFI_STATUS Status;
|
| 2071 | LIST_ENTRY *Link;
|
| 2072 | LIST_ENTRY *ListHead;
|
| 2073 | FORM_EXPRESSION *Expression;
|
| 2074 | UINT32 BrowserStatus;
|
| 2075 | CHAR16 *ErrorStr;
|
| 2076 |
|
| 2077 | BrowserStatus = BROWSER_SUCCESS;
|
| 2078 | ErrorStr = NULL;
|
| 2079 |
|
| 2080 | switch (Type) {
|
| 2081 | case EFI_HII_EXPRESSION_INCONSISTENT_IF:
|
| 2082 | ListHead = &Question->InconsistentListHead;
|
| 2083 | break;
|
| 2084 |
|
| 2085 | case EFI_HII_EXPRESSION_WARNING_IF:
|
| 2086 | ListHead = &Question->WarningListHead;
|
| 2087 | break;
|
| 2088 |
|
| 2089 | case EFI_HII_EXPRESSION_NO_SUBMIT_IF:
|
| 2090 | ListHead = &Question->NoSubmitListHead;
|
| 2091 | break;
|
| 2092 |
|
| 2093 | default:
|
| 2094 | ASSERT (FALSE);
|
| 2095 | return EFI_UNSUPPORTED;
|
| 2096 | }
|
| 2097 |
|
| 2098 | Link = GetFirstNode (ListHead);
|
| 2099 | while (!IsNull (ListHead, Link)) {
|
| 2100 | Expression = FORM_EXPRESSION_FROM_LINK (Link);
|
| 2101 |
|
| 2102 | //
|
| 2103 | // Evaluate the expression
|
| 2104 | //
|
| 2105 | Status = EvaluateExpression (FormSet, Form, Expression);
|
| 2106 | if (EFI_ERROR (Status)) {
|
| 2107 | return Status;
|
| 2108 | }
|
| 2109 |
|
| 2110 | if (IsTrue (&Expression->Result)) {
|
| 2111 | switch (Type) {
|
| 2112 | case EFI_HII_EXPRESSION_INCONSISTENT_IF:
|
| 2113 | BrowserStatus = BROWSER_INCONSISTENT_IF;
|
| 2114 | break;
|
| 2115 |
|
| 2116 | case EFI_HII_EXPRESSION_WARNING_IF:
|
| 2117 | BrowserStatus = BROWSER_WARNING_IF;
|
| 2118 | break;
|
| 2119 |
|
| 2120 | case EFI_HII_EXPRESSION_NO_SUBMIT_IF:
|
| 2121 | BrowserStatus = BROWSER_NO_SUBMIT_IF;
|
| 2122 | //
|
| 2123 | // This code only used to compatible with old display engine,
|
| 2124 | // New display engine will not use this field.
|
| 2125 | //
|
| 2126 | if (Expression->Error != 0) {
|
| 2127 | ErrorStr = GetToken (Expression->Error, FormSet->HiiHandle);
|
| 2128 | }
|
| 2129 | break;
|
| 2130 |
|
| 2131 | default:
|
| 2132 | ASSERT (FALSE);
|
| 2133 | break;
|
| 2134 | }
|
| 2135 |
|
| 2136 | if (!((Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) && mSystemSubmit)) {
|
| 2137 | //
|
| 2138 | // If in system submit process and for no_submit_if check, not popup this error message.
|
| 2139 | // Will process this fail again later in not system submit process.
|
| 2140 | //
|
| 2141 | PopupErrorMessage(BrowserStatus, FormSet->HiiHandle, Expression->OpCode, ErrorStr);
|
| 2142 | }
|
| 2143 |
|
| 2144 | if (ErrorStr != NULL) {
|
| 2145 | FreePool (ErrorStr);
|
| 2146 | }
|
| 2147 |
|
| 2148 | if (Type == EFI_HII_EXPRESSION_WARNING_IF) {
|
| 2149 | return EFI_SUCCESS;
|
| 2150 | } else {
|
| 2151 | return EFI_NOT_READY;
|
| 2152 | }
|
| 2153 | }
|
| 2154 |
|
| 2155 | Link = GetNextNode (ListHead, Link);
|
| 2156 | }
|
| 2157 |
|
| 2158 | return EFI_SUCCESS;
|
| 2159 | }
|
| 2160 |
|
| 2161 | /**
|
| 2162 | Perform question check.
|
| 2163 |
|
| 2164 | If one question has more than one check, process form high priority to low.
|
| 2165 | Only one error info will be popup.
|
| 2166 |
|
| 2167 | @param FormSet FormSet data structure.
|
| 2168 | @param Form Form data structure.
|
| 2169 | @param Question The Question to be validated.
|
| 2170 |
|
| 2171 | @retval EFI_SUCCESS Form validation pass.
|
| 2172 | @retval other Form validation failed.
|
| 2173 |
|
| 2174 | **/
|
| 2175 | EFI_STATUS
|
| 2176 | ValueChangedValidation (
|
| 2177 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 2178 | IN FORM_BROWSER_FORM *Form,
|
| 2179 | IN FORM_BROWSER_STATEMENT *Question
|
| 2180 | )
|
| 2181 | {
|
| 2182 | EFI_STATUS Status;
|
| 2183 |
|
| 2184 | Status = EFI_SUCCESS;
|
| 2185 |
|
| 2186 | //
|
| 2187 | // Do the inconsistentif check.
|
| 2188 | //
|
| 2189 | if (!IsListEmpty (&Question->InconsistentListHead)) {
|
| 2190 | Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);
|
| 2191 | if (EFI_ERROR (Status)) {
|
| 2192 | return Status;
|
| 2193 | }
|
| 2194 | }
|
| 2195 |
|
| 2196 | //
|
| 2197 | // Do the warningif check.
|
| 2198 | //
|
| 2199 | if (!IsListEmpty (&Question->WarningListHead)) {
|
| 2200 | Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_WARNING_IF);
|
| 2201 | }
|
| 2202 |
|
| 2203 | return Status;
|
| 2204 | }
|
| 2205 |
|
| 2206 | /**
|
| 2207 | Perform NoSubmit check for each Form in FormSet.
|
| 2208 |
|
| 2209 | @param FormSet FormSet data structure.
|
| 2210 | @param CurrentForm Current input form data structure.
|
| 2211 | @param Statement The statement for this check.
|
| 2212 |
|
| 2213 | @retval EFI_SUCCESS Form validation pass.
|
| 2214 | @retval other Form validation failed.
|
| 2215 |
|
| 2216 | **/
|
| 2217 | EFI_STATUS
|
| 2218 | NoSubmitCheck (
|
| 2219 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 2220 | IN OUT FORM_BROWSER_FORM **CurrentForm,
|
| 2221 | OUT FORM_BROWSER_STATEMENT **Statement
|
| 2222 | )
|
| 2223 | {
|
| 2224 | EFI_STATUS Status;
|
| 2225 | LIST_ENTRY *Link;
|
| 2226 | FORM_BROWSER_STATEMENT *Question;
|
| 2227 | FORM_BROWSER_FORM *Form;
|
| 2228 | LIST_ENTRY *LinkForm;
|
| 2229 |
|
| 2230 | LinkForm = GetFirstNode (&FormSet->FormListHead);
|
| 2231 | while (!IsNull (&FormSet->FormListHead, LinkForm)) {
|
| 2232 | Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);
|
| 2233 | LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);
|
| 2234 |
|
| 2235 | if (*CurrentForm != NULL && *CurrentForm != Form) {
|
| 2236 | continue;
|
| 2237 | }
|
| 2238 |
|
| 2239 | Link = GetFirstNode (&Form->StatementListHead);
|
| 2240 | while (!IsNull (&Form->StatementListHead, Link)) {
|
| 2241 | Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
|
| 2242 | Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);
|
| 2243 | if (EFI_ERROR (Status)) {
|
| 2244 | if (*CurrentForm == NULL) {
|
| 2245 | *CurrentForm = Form;
|
| 2246 | }
|
| 2247 | if (Statement != NULL) {
|
| 2248 | *Statement = Question;
|
| 2249 | }
|
| 2250 | return Status;
|
| 2251 | }
|
| 2252 |
|
| 2253 | Link = GetNextNode (&Form->StatementListHead, Link);
|
| 2254 | }
|
| 2255 | }
|
| 2256 |
|
| 2257 | return EFI_SUCCESS;
|
| 2258 | }
|
| 2259 |
|
| 2260 | /**
|
| 2261 | Fill storage's edit copy with settings requested from Configuration Driver.
|
| 2262 |
|
| 2263 | @param Storage The storage which need to sync.
|
| 2264 | @param ConfigRequest The config request string which used to sync storage.
|
| 2265 | @param SyncOrRestore Sync the buffer to editbuffer or Restore the
|
| 2266 | editbuffer to buffer
|
| 2267 | if TRUE, copy the editbuffer to the buffer.
|
| 2268 | if FALSE, copy the buffer to the editbuffer.
|
| 2269 |
|
| 2270 | @retval EFI_SUCCESS The function completed successfully.
|
| 2271 |
|
| 2272 | **/
|
| 2273 | EFI_STATUS
|
| 2274 | SynchronizeStorage (
|
| 2275 | OUT BROWSER_STORAGE *Storage,
|
| 2276 | IN CHAR16 *ConfigRequest,
|
| 2277 | IN BOOLEAN SyncOrRestore
|
| 2278 | )
|
| 2279 | {
|
| 2280 | EFI_STATUS Status;
|
| 2281 | EFI_STRING Progress;
|
| 2282 | EFI_STRING Result;
|
| 2283 | UINTN BufferSize;
|
| 2284 | LIST_ENTRY *Link;
|
| 2285 | NAME_VALUE_NODE *Node;
|
| 2286 | UINT8 *Src;
|
| 2287 | UINT8 *Dst;
|
| 2288 |
|
| 2289 | Status = EFI_SUCCESS;
|
| 2290 | Result = NULL;
|
| 2291 |
|
| 2292 | if (Storage->Type == EFI_HII_VARSTORE_BUFFER ||
|
| 2293 | (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
|
| 2294 | BufferSize = Storage->Size;
|
| 2295 |
|
| 2296 | if (SyncOrRestore) {
|
| 2297 | Src = Storage->EditBuffer;
|
| 2298 | Dst = Storage->Buffer;
|
| 2299 | } else {
|
| 2300 | Src = Storage->Buffer;
|
| 2301 | Dst = Storage->EditBuffer;
|
| 2302 | }
|
| 2303 |
|
| 2304 | if (ConfigRequest != NULL) {
|
| 2305 | Status = mHiiConfigRouting->BlockToConfig(
|
| 2306 | mHiiConfigRouting,
|
| 2307 | ConfigRequest,
|
| 2308 | Src,
|
| 2309 | BufferSize,
|
| 2310 | &Result,
|
| 2311 | &Progress
|
| 2312 | );
|
| 2313 | if (EFI_ERROR (Status)) {
|
| 2314 | return Status;
|
| 2315 | }
|
| 2316 |
|
| 2317 | Status = mHiiConfigRouting->ConfigToBlock (
|
| 2318 | mHiiConfigRouting,
|
| 2319 | Result,
|
| 2320 | Dst,
|
| 2321 | &BufferSize,
|
| 2322 | &Progress
|
| 2323 | );
|
| 2324 | if (Result != NULL) {
|
| 2325 | FreePool (Result);
|
| 2326 | }
|
| 2327 | } else {
|
| 2328 | CopyMem (Dst, Src, BufferSize);
|
| 2329 | }
|
| 2330 | } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
|
| 2331 | Link = GetFirstNode (&Storage->NameValueListHead);
|
| 2332 | while (!IsNull (&Storage->NameValueListHead, Link)) {
|
| 2333 | Node = NAME_VALUE_NODE_FROM_LINK (Link);
|
| 2334 |
|
| 2335 | if ((ConfigRequest != NULL && StrStr (ConfigRequest, Node->Name) != NULL) ||
|
| 2336 | (ConfigRequest == NULL)) {
|
| 2337 | if (SyncOrRestore) {
|
| 2338 | NewStringCpy (&Node->Value, Node->EditValue);
|
| 2339 | } else {
|
| 2340 | NewStringCpy (&Node->EditValue, Node->Value);
|
| 2341 | }
|
| 2342 | }
|
| 2343 |
|
| 2344 | Link = GetNextNode (&Storage->NameValueListHead, Link);
|
| 2345 | }
|
| 2346 | }
|
| 2347 |
|
| 2348 | return Status;
|
| 2349 | }
|
| 2350 |
|
| 2351 | /**
|
| 2352 | When discard the question value, call the callback function with Changed type
|
| 2353 | to inform the hii driver.
|
| 2354 |
|
| 2355 | @param FormSet FormSet data structure.
|
| 2356 | @param Form Form data structure.
|
| 2357 |
|
| 2358 | **/
|
| 2359 | VOID
|
| 2360 | SendDiscardInfoToDriver (
|
| 2361 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 2362 | IN FORM_BROWSER_FORM *Form
|
| 2363 | )
|
| 2364 | {
|
| 2365 | LIST_ENTRY *Link;
|
| 2366 | FORM_BROWSER_STATEMENT *Question;
|
| 2367 | EFI_IFR_TYPE_VALUE *TypeValue;
|
| 2368 | EFI_BROWSER_ACTION_REQUEST ActionRequest;
|
| 2369 |
|
| 2370 | if (FormSet->ConfigAccess == NULL) {
|
| 2371 | return;
|
| 2372 | }
|
| 2373 |
|
| 2374 | Link = GetFirstNode (&Form->StatementListHead);
|
| 2375 | while (!IsNull (&Form->StatementListHead, Link)) {
|
| 2376 | Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
|
| 2377 | Link = GetNextNode (&Form->StatementListHead, Link);
|
| 2378 |
|
| 2379 | if (Question->Storage == NULL || Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
|
| 2380 | continue;
|
| 2381 | }
|
| 2382 |
|
| 2383 | if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {
|
| 2384 | continue;
|
| 2385 | }
|
| 2386 |
|
| 2387 | if (Question->Operand == EFI_IFR_PASSWORD_OP) {
|
| 2388 | continue;
|
| 2389 | }
|
| 2390 |
|
| 2391 | if (!Question->ValueChanged) {
|
| 2392 | continue;
|
| 2393 | }
|
| 2394 |
|
| 2395 | //
|
| 2396 | // Restore the question value before call the CHANGED callback type.
|
| 2397 | //
|
| 2398 | GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);
|
| 2399 |
|
| 2400 | if (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {
|
| 2401 | TypeValue = (EFI_IFR_TYPE_VALUE *) Question->BufferValue;
|
| 2402 | } else {
|
| 2403 | TypeValue = &Question->HiiValue.Value;
|
| 2404 | }
|
| 2405 |
|
| 2406 | ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
|
| 2407 | FormSet->ConfigAccess->Callback (
|
| 2408 | FormSet->ConfigAccess,
|
| 2409 | EFI_BROWSER_ACTION_CHANGED,
|
| 2410 | Question->QuestionId,
|
| 2411 | Question->HiiValue.Type,
|
| 2412 | TypeValue,
|
| 2413 | &ActionRequest
|
| 2414 | );
|
| 2415 | }
|
| 2416 | }
|
| 2417 |
|
| 2418 | /**
|
| 2419 | Validate the HiiHandle.
|
| 2420 |
|
| 2421 | @param HiiHandle The input HiiHandle which need to validate.
|
| 2422 |
|
| 2423 | @retval TRUE The handle is validate.
|
| 2424 | @retval FALSE The handle is invalidate.
|
| 2425 |
|
| 2426 | **/
|
| 2427 | BOOLEAN
|
| 2428 | ValidateHiiHandle (
|
| 2429 | EFI_HII_HANDLE HiiHandle
|
| 2430 | )
|
| 2431 | {
|
| 2432 | EFI_HII_HANDLE *HiiHandles;
|
| 2433 | UINTN Index;
|
| 2434 | BOOLEAN Find;
|
| 2435 |
|
| 2436 | if (HiiHandle == NULL) {
|
| 2437 | return FALSE;
|
| 2438 | }
|
| 2439 |
|
| 2440 | Find = FALSE;
|
| 2441 |
|
| 2442 | HiiHandles = HiiGetHiiHandles (NULL);
|
| 2443 | ASSERT (HiiHandles != NULL);
|
| 2444 |
|
| 2445 | for (Index = 0; HiiHandles[Index] != NULL; Index++) {
|
| 2446 | if (HiiHandles[Index] == HiiHandle) {
|
| 2447 | Find = TRUE;
|
| 2448 | break;
|
| 2449 | }
|
| 2450 | }
|
| 2451 |
|
| 2452 | FreePool (HiiHandles);
|
| 2453 |
|
| 2454 | return Find;
|
| 2455 | }
|
| 2456 |
|
| 2457 | /**
|
| 2458 | Validate the FormSet. If the formset is not validate, remove it from the list.
|
| 2459 |
|
| 2460 | @param FormSet The input FormSet which need to validate.
|
| 2461 |
|
| 2462 | @retval TRUE The handle is validate.
|
| 2463 | @retval FALSE The handle is invalidate.
|
| 2464 |
|
| 2465 | **/
|
| 2466 | BOOLEAN
|
| 2467 | ValidateFormSet (
|
| 2468 | FORM_BROWSER_FORMSET *FormSet
|
| 2469 | )
|
| 2470 | {
|
| 2471 | BOOLEAN Find;
|
| 2472 |
|
| 2473 | ASSERT (FormSet != NULL);
|
| 2474 |
|
| 2475 | Find = ValidateHiiHandle(FormSet->HiiHandle);
|
| 2476 | //
|
| 2477 | // Should not remove the formset which is being used.
|
| 2478 | //
|
| 2479 | if (!Find && (FormSet != gCurrentSelection->FormSet)) {
|
| 2480 | CleanBrowserStorage(FormSet);
|
| 2481 | RemoveEntryList (&FormSet->Link);
|
| 2482 | DestroyFormSet (FormSet);
|
| 2483 | }
|
| 2484 |
|
| 2485 | return Find;
|
| 2486 | }
|
| 2487 | /**
|
| 2488 | Check whether need to enable the reset flag in form level.
|
| 2489 | Also clean all ValueChanged flag in question.
|
| 2490 |
|
| 2491 | @param SetFlag Whether need to set the Reset Flag.
|
| 2492 | @param FormSet FormSet data structure.
|
| 2493 | @param Form Form data structure.
|
| 2494 |
|
| 2495 | **/
|
| 2496 | VOID
|
| 2497 | UpdateFlagForForm (
|
| 2498 | IN BOOLEAN SetFlag,
|
| 2499 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 2500 | IN FORM_BROWSER_FORM *Form
|
| 2501 | )
|
| 2502 | {
|
| 2503 | LIST_ENTRY *Link;
|
| 2504 | FORM_BROWSER_STATEMENT *Question;
|
| 2505 | BOOLEAN OldValue;
|
| 2506 |
|
| 2507 | Link = GetFirstNode (&Form->StatementListHead);
|
| 2508 | while (!IsNull (&Form->StatementListHead, Link)) {
|
| 2509 | Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
|
| 2510 | Link = GetNextNode (&Form->StatementListHead, Link);
|
| 2511 |
|
| 2512 | if (!Question->ValueChanged) {
|
| 2513 | continue;
|
| 2514 | }
|
| 2515 |
|
| 2516 | OldValue = Question->ValueChanged;
|
| 2517 |
|
| 2518 | //
|
| 2519 | // Compare the buffer and editbuffer data to see whether the data has been saved.
|
| 2520 | //
|
| 2521 | Question->ValueChanged = IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBothBuffer);
|
| 2522 |
|
| 2523 | //
|
| 2524 | // Only the changed data has been saved, then need to set the reset flag.
|
| 2525 | //
|
| 2526 | if (SetFlag && OldValue && !Question->ValueChanged && ((Question->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0)) {
|
| 2527 | gResetRequired = TRUE;
|
| 2528 | }
|
| 2529 | }
|
| 2530 | }
|
| 2531 |
|
| 2532 | /**
|
| 2533 | Check whether need to enable the reset flag.
|
| 2534 | Also clean ValueChanged flag for all statements.
|
| 2535 |
|
| 2536 | Form level or formset level, only one.
|
| 2537 |
|
| 2538 | @param SetFlag Whether need to set the Reset Flag.
|
| 2539 | @param FormSet FormSet data structure.
|
| 2540 | @param Form Form data structure.
|
| 2541 |
|
| 2542 | **/
|
| 2543 | VOID
|
| 2544 | ValueChangeResetFlagUpdate (
|
| 2545 | IN BOOLEAN SetFlag,
|
| 2546 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 2547 | IN FORM_BROWSER_FORM *Form
|
| 2548 | )
|
| 2549 | {
|
| 2550 | FORM_BROWSER_FORM *CurrentForm;
|
| 2551 | LIST_ENTRY *Link;
|
| 2552 |
|
| 2553 | if (Form != NULL) {
|
| 2554 | UpdateFlagForForm(SetFlag, FormSet, Form);
|
| 2555 | return;
|
| 2556 | }
|
| 2557 |
|
| 2558 | Link = GetFirstNode (&FormSet->FormListHead);
|
| 2559 | while (!IsNull (&FormSet->FormListHead, Link)) {
|
| 2560 | CurrentForm = FORM_BROWSER_FORM_FROM_LINK (Link);
|
| 2561 | Link = GetNextNode (&FormSet->FormListHead, Link);
|
| 2562 |
|
| 2563 | UpdateFlagForForm(SetFlag, FormSet, CurrentForm);
|
| 2564 | }
|
| 2565 | }
|
| 2566 |
|
| 2567 | /**
|
| 2568 | Base on the return Progress string to find the form.
|
| 2569 |
|
| 2570 | Base on the first return Offset/Width (Name) string to find the form
|
| 2571 | which keep this string.
|
| 2572 |
|
| 2573 | @param FormSet FormSet data structure.
|
| 2574 | @param Storage Storage which has this Progress string.
|
| 2575 | @param Progress The Progress string which has the first fail string.
|
| 2576 | @param RetForm The return form for this progress string.
|
| 2577 | @param RetQuestion The return question for the error progress string.
|
| 2578 |
|
| 2579 | @retval TRUE Find the error form and statement for this error progress string.
|
| 2580 | @retval FALSE Not find the error form.
|
| 2581 |
|
| 2582 | **/
|
| 2583 | BOOLEAN
|
| 2584 | FindQuestionFromProgress (
|
| 2585 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 2586 | IN BROWSER_STORAGE *Storage,
|
| 2587 | IN EFI_STRING Progress,
|
| 2588 | OUT FORM_BROWSER_FORM **RetForm,
|
| 2589 | OUT FORM_BROWSER_STATEMENT **RetQuestion
|
| 2590 | )
|
| 2591 | {
|
| 2592 | LIST_ENTRY *Link;
|
| 2593 | LIST_ENTRY *LinkStorage;
|
| 2594 | LIST_ENTRY *LinkStatement;
|
| 2595 | FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;
|
| 2596 | FORM_BROWSER_FORM *Form;
|
| 2597 | EFI_STRING EndStr;
|
| 2598 | FORM_BROWSER_STATEMENT *Statement;
|
| 2599 |
|
| 2600 | ASSERT ((*Progress == '&') || (*Progress == 'G'));
|
| 2601 |
|
| 2602 | ConfigInfo = NULL;
|
| 2603 | *RetForm = NULL;
|
| 2604 | *RetQuestion = NULL;
|
| 2605 |
|
| 2606 | //
|
| 2607 | // Skip the first "&" or the ConfigHdr part.
|
| 2608 | //
|
| 2609 | if (*Progress == '&') {
|
| 2610 | Progress++;
|
| 2611 | } else {
|
| 2612 | //
|
| 2613 | // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
|
| 2614 | //
|
| 2615 | if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
|
| 2616 | //
|
| 2617 | // For Name/Value type, Skip the ConfigHdr part.
|
| 2618 | //
|
| 2619 | EndStr = StrStr (Progress, L"PATH=");
|
| 2620 | ASSERT (EndStr != NULL);
|
| 2621 | while (*EndStr != '&') {
|
| 2622 | EndStr++;
|
| 2623 | }
|
| 2624 |
|
| 2625 | *EndStr = '\0';
|
| 2626 | } else {
|
| 2627 | //
|
| 2628 | // For Buffer type, Skip the ConfigHdr part.
|
| 2629 | //
|
| 2630 | EndStr = StrStr (Progress, L"&OFFSET=");
|
| 2631 | ASSERT (EndStr != NULL);
|
| 2632 | *EndStr = '\0';
|
| 2633 | }
|
| 2634 |
|
| 2635 | Progress = EndStr + 1;
|
| 2636 | }
|
| 2637 |
|
| 2638 | //
|
| 2639 | // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
|
| 2640 | //
|
| 2641 | if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
|
| 2642 | //
|
| 2643 | // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
|
| 2644 | // here, just keep the "Fred" string.
|
| 2645 | //
|
| 2646 | EndStr = StrStr (Progress, L"=");
|
| 2647 | ASSERT (EndStr != NULL);
|
| 2648 | *EndStr = '\0';
|
| 2649 | } else {
|
| 2650 | //
|
| 2651 | // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
|
| 2652 | // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
|
| 2653 | //
|
| 2654 | EndStr = StrStr (Progress, L"&VALUE=");
|
| 2655 | ASSERT (EndStr != NULL);
|
| 2656 | *EndStr = '\0';
|
| 2657 | }
|
| 2658 |
|
| 2659 | //
|
| 2660 | // Search in the form list.
|
| 2661 | //
|
| 2662 | Link = GetFirstNode (&FormSet->FormListHead);
|
| 2663 | while (!IsNull (&FormSet->FormListHead, Link)) {
|
| 2664 | Form = FORM_BROWSER_FORM_FROM_LINK (Link);
|
| 2665 | Link = GetNextNode (&FormSet->FormListHead, Link);
|
| 2666 |
|
| 2667 | //
|
| 2668 | // Search in the ConfigReqeust list in this form.
|
| 2669 | //
|
| 2670 | LinkStorage = GetFirstNode (&Form->ConfigRequestHead);
|
| 2671 | while (!IsNull (&Form->ConfigRequestHead, LinkStorage)) {
|
| 2672 | ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage);
|
| 2673 | LinkStorage = GetNextNode (&Form->ConfigRequestHead, LinkStorage);
|
| 2674 |
|
| 2675 | if (Storage != ConfigInfo->Storage) {
|
| 2676 | continue;
|
| 2677 | }
|
| 2678 |
|
| 2679 | if (StrStr (ConfigInfo->ConfigRequest, Progress) != NULL) {
|
| 2680 | //
|
| 2681 | // Find the OffsetWidth string in this form.
|
| 2682 | //
|
| 2683 | *RetForm = Form;
|
| 2684 | break;
|
| 2685 | }
|
| 2686 | }
|
| 2687 |
|
| 2688 | if (*RetForm != NULL) {
|
| 2689 | LinkStatement = GetFirstNode (&Form->StatementListHead);
|
| 2690 | while (!IsNull (&Form->StatementListHead, LinkStatement)) {
|
| 2691 | Statement = FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement);
|
| 2692 | LinkStatement = GetNextNode (&Form->StatementListHead, LinkStatement);
|
| 2693 |
|
| 2694 | if (Statement->BlockName != NULL && StrStr (Statement->BlockName, Progress) != NULL) {
|
| 2695 | *RetQuestion = Statement;
|
| 2696 | break;
|
| 2697 | }
|
| 2698 |
|
| 2699 | if (Statement->VariableName != NULL && StrStr (Statement->VariableName, Progress) != NULL) {
|
| 2700 | *RetQuestion = Statement;
|
| 2701 | break;
|
| 2702 | }
|
| 2703 | }
|
| 2704 | }
|
| 2705 |
|
| 2706 | if (*RetForm != NULL) {
|
| 2707 | break;
|
| 2708 | }
|
| 2709 | }
|
| 2710 |
|
| 2711 | //
|
| 2712 | // restore the OffsetWidth string to the original format.
|
| 2713 | //
|
| 2714 | if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
|
| 2715 | *EndStr = '=';
|
| 2716 | } else {
|
| 2717 | *EndStr = '&';
|
| 2718 | }
|
| 2719 |
|
| 2720 | return (BOOLEAN) (*RetForm != NULL);
|
| 2721 | }
|
| 2722 |
|
| 2723 | /**
|
| 2724 | Popup an save error info and get user input.
|
| 2725 |
|
| 2726 | @param TitleId The form title id.
|
| 2727 | @param HiiHandle The hii handle for this package.
|
| 2728 |
|
| 2729 | @retval UINT32 The user select option for the save fail.
|
| 2730 | BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
|
| 2731 | **/
|
| 2732 | UINT32
|
| 2733 | ConfirmSaveFail (
|
| 2734 | IN EFI_STRING_ID TitleId,
|
| 2735 | IN EFI_HII_HANDLE HiiHandle
|
| 2736 | )
|
| 2737 | {
|
| 2738 | CHAR16 *FormTitle;
|
| 2739 | CHAR16 *StringBuffer;
|
| 2740 | UINT32 RetVal;
|
| 2741 |
|
| 2742 | FormTitle = GetToken (TitleId, HiiHandle);
|
| 2743 |
|
| 2744 | StringBuffer = AllocateZeroPool (256 * sizeof (CHAR16));
|
| 2745 | ASSERT (StringBuffer != NULL);
|
| 2746 |
|
| 2747 | UnicodeSPrint (
|
| 2748 | StringBuffer,
|
| 2749 | 24 * sizeof (CHAR16) + StrSize (FormTitle),
|
| 2750 | L"Submit Fail For Form: %s.",
|
| 2751 | FormTitle
|
| 2752 | );
|
| 2753 |
|
| 2754 | RetVal = PopupErrorMessage(BROWSER_SUBMIT_FAIL, NULL, NULL, StringBuffer);
|
| 2755 |
|
| 2756 | FreePool (StringBuffer);
|
| 2757 | FreePool (FormTitle);
|
| 2758 |
|
| 2759 | return RetVal;
|
| 2760 | }
|
| 2761 |
|
| 2762 | /**
|
| 2763 | Popup an NO_SUBMIT_IF error info and get user input.
|
| 2764 |
|
| 2765 | @param TitleId The form title id.
|
| 2766 | @param HiiHandle The hii handle for this package.
|
| 2767 |
|
| 2768 | @retval UINT32 The user select option for the save fail.
|
| 2769 | BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
|
| 2770 | **/
|
| 2771 | UINT32
|
| 2772 | ConfirmNoSubmitFail (
|
| 2773 | IN EFI_STRING_ID TitleId,
|
| 2774 | IN EFI_HII_HANDLE HiiHandle
|
| 2775 | )
|
| 2776 | {
|
| 2777 | CHAR16 *FormTitle;
|
| 2778 | CHAR16 *StringBuffer;
|
| 2779 | UINT32 RetVal;
|
| 2780 |
|
| 2781 | FormTitle = GetToken (TitleId, HiiHandle);
|
| 2782 |
|
| 2783 | StringBuffer = AllocateZeroPool (256 * sizeof (CHAR16));
|
| 2784 | ASSERT (StringBuffer != NULL);
|
| 2785 |
|
| 2786 | UnicodeSPrint (
|
| 2787 | StringBuffer,
|
| 2788 | 24 * sizeof (CHAR16) + StrSize (FormTitle),
|
| 2789 | L"NO_SUBMIT_IF error For Form: %s.",
|
| 2790 | FormTitle
|
| 2791 | );
|
| 2792 |
|
| 2793 | RetVal = PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF, NULL, NULL, StringBuffer);
|
| 2794 |
|
| 2795 | FreePool (StringBuffer);
|
| 2796 | FreePool (FormTitle);
|
| 2797 |
|
| 2798 | return RetVal;
|
| 2799 | }
|
| 2800 |
|
| 2801 | /**
|
| 2802 | Discard data based on the input setting scope (Form, FormSet or System).
|
| 2803 |
|
| 2804 | @param FormSet FormSet data structure.
|
| 2805 | @param Form Form data structure.
|
| 2806 | @param SettingScope Setting Scope for Discard action.
|
| 2807 |
|
| 2808 | @retval EFI_SUCCESS The function completed successfully.
|
| 2809 | @retval EFI_UNSUPPORTED Unsupport SettingScope.
|
| 2810 |
|
| 2811 | **/
|
| 2812 | EFI_STATUS
|
| 2813 | DiscardForm (
|
| 2814 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 2815 | IN FORM_BROWSER_FORM *Form,
|
| 2816 | IN BROWSER_SETTING_SCOPE SettingScope
|
| 2817 | )
|
| 2818 | {
|
| 2819 | LIST_ENTRY *Link;
|
| 2820 | FORMSET_STORAGE *Storage;
|
| 2821 | FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;
|
| 2822 | FORM_BROWSER_FORMSET *LocalFormSet;
|
| 2823 | FORM_BROWSER_FORMSET *OldFormSet;
|
| 2824 |
|
| 2825 | //
|
| 2826 | // Check the supported setting level.
|
| 2827 | //
|
| 2828 | if (SettingScope >= MaxLevel) {
|
| 2829 | return EFI_UNSUPPORTED;
|
| 2830 | }
|
| 2831 |
|
| 2832 | if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) {
|
| 2833 | ConfigInfo = NULL;
|
| 2834 | Link = GetFirstNode (&Form->ConfigRequestHead);
|
| 2835 | while (!IsNull (&Form->ConfigRequestHead, Link)) {
|
| 2836 | ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);
|
| 2837 | Link = GetNextNode (&Form->ConfigRequestHead, Link);
|
| 2838 |
|
| 2839 | if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
|
| 2840 | continue;
|
| 2841 | }
|
| 2842 |
|
| 2843 | //
|
| 2844 | // Skip if there is no RequestElement
|
| 2845 | //
|
| 2846 | if (ConfigInfo->ElementCount == 0) {
|
| 2847 | continue;
|
| 2848 | }
|
| 2849 |
|
| 2850 | //
|
| 2851 | // Prepare <ConfigResp>
|
| 2852 | //
|
| 2853 | SynchronizeStorage(ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);
|
| 2854 |
|
| 2855 | //
|
| 2856 | // Call callback with Changed type to inform the driver.
|
| 2857 | //
|
| 2858 | SendDiscardInfoToDriver (FormSet, Form);
|
| 2859 | }
|
| 2860 |
|
| 2861 | ValueChangeResetFlagUpdate (FALSE, FormSet, Form);
|
| 2862 | } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) {
|
| 2863 |
|
| 2864 | //
|
| 2865 | // Discard Buffer storage or Name/Value storage
|
| 2866 | //
|
| 2867 | Link = GetFirstNode (&FormSet->StorageListHead);
|
| 2868 | while (!IsNull (&FormSet->StorageListHead, Link)) {
|
| 2869 | Storage = FORMSET_STORAGE_FROM_LINK (Link);
|
| 2870 | Link = GetNextNode (&FormSet->StorageListHead, Link);
|
| 2871 |
|
| 2872 | if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
|
| 2873 | continue;
|
| 2874 | }
|
| 2875 |
|
| 2876 | //
|
| 2877 | // Skip if there is no RequestElement
|
| 2878 | //
|
| 2879 | if (Storage->ElementCount == 0) {
|
| 2880 | continue;
|
| 2881 | }
|
| 2882 |
|
| 2883 | SynchronizeStorage(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);
|
| 2884 | }
|
| 2885 |
|
| 2886 | Link = GetFirstNode (&FormSet->FormListHead);
|
| 2887 | while (!IsNull (&FormSet->FormListHead, Link)) {
|
| 2888 | Form = FORM_BROWSER_FORM_FROM_LINK (Link);
|
| 2889 | Link = GetNextNode (&FormSet->FormListHead, Link);
|
| 2890 |
|
| 2891 | //
|
| 2892 | // Call callback with Changed type to inform the driver.
|
| 2893 | //
|
| 2894 | SendDiscardInfoToDriver (FormSet, Form);
|
| 2895 | }
|
| 2896 |
|
| 2897 | ValueChangeResetFlagUpdate(FALSE, FormSet, NULL);
|
| 2898 | } else if (SettingScope == SystemLevel) {
|
| 2899 | //
|
| 2900 | // System Level Discard.
|
| 2901 | //
|
| 2902 | OldFormSet = mSystemLevelFormSet;
|
| 2903 |
|
| 2904 | //
|
| 2905 | // Discard changed value for each FormSet in the maintain list.
|
| 2906 | //
|
| 2907 | Link = GetFirstNode (&gBrowserFormSetList);
|
| 2908 | while (!IsNull (&gBrowserFormSetList, Link)) {
|
| 2909 | LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);
|
| 2910 | Link = GetNextNode (&gBrowserFormSetList, Link);
|
| 2911 | if (!ValidateFormSet(LocalFormSet)) {
|
| 2912 | continue;
|
| 2913 | }
|
| 2914 |
|
| 2915 | mSystemLevelFormSet = LocalFormSet;
|
| 2916 |
|
| 2917 | DiscardForm (LocalFormSet, NULL, FormSetLevel);
|
| 2918 | if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {
|
| 2919 | //
|
| 2920 | // Remove maintain backup list after discard except for the current using FormSet.
|
| 2921 | //
|
| 2922 | CleanBrowserStorage(LocalFormSet);
|
| 2923 | RemoveEntryList (&LocalFormSet->Link);
|
| 2924 | DestroyFormSet (LocalFormSet);
|
| 2925 | }
|
| 2926 | }
|
| 2927 |
|
| 2928 | mSystemLevelFormSet = OldFormSet;
|
| 2929 | }
|
| 2930 |
|
| 2931 | return EFI_SUCCESS;
|
| 2932 | }
|
| 2933 |
|
| 2934 | /**
|
| 2935 | Submit data for a form.
|
| 2936 |
|
| 2937 | @param FormSet FormSet data structure.
|
| 2938 | @param Form Form data structure.
|
| 2939 |
|
| 2940 | @retval EFI_SUCCESS The function completed successfully.
|
| 2941 | @retval EFI_UNSUPPORTED Unsupport SettingScope.
|
| 2942 |
|
| 2943 | **/
|
| 2944 | EFI_STATUS
|
| 2945 | SubmitForForm (
|
| 2946 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 2947 | IN FORM_BROWSER_FORM *Form
|
| 2948 | )
|
| 2949 | {
|
| 2950 | EFI_STATUS Status;
|
| 2951 | LIST_ENTRY *Link;
|
| 2952 | EFI_STRING ConfigResp;
|
| 2953 | EFI_STRING Progress;
|
| 2954 | BROWSER_STORAGE *Storage;
|
| 2955 | FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;
|
| 2956 |
|
| 2957 | if (!IsNvUpdateRequiredForForm (Form)) {
|
| 2958 | return EFI_SUCCESS;
|
| 2959 | }
|
| 2960 |
|
| 2961 | Status = NoSubmitCheck (FormSet, &Form, NULL);
|
| 2962 | if (EFI_ERROR (Status)) {
|
| 2963 | return Status;
|
| 2964 | }
|
| 2965 |
|
| 2966 | Link = GetFirstNode (&Form->ConfigRequestHead);
|
| 2967 | while (!IsNull (&Form->ConfigRequestHead, Link)) {
|
| 2968 | ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);
|
| 2969 | Link = GetNextNode (&Form->ConfigRequestHead, Link);
|
| 2970 |
|
| 2971 | Storage = ConfigInfo->Storage;
|
| 2972 | if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
|
| 2973 | continue;
|
| 2974 | }
|
| 2975 |
|
| 2976 | //
|
| 2977 | // Skip if there is no RequestElement
|
| 2978 | //
|
| 2979 | if (ConfigInfo->ElementCount == 0) {
|
| 2980 | continue;
|
| 2981 | }
|
| 2982 |
|
| 2983 | //
|
| 2984 | // 1. Prepare <ConfigResp>
|
| 2985 | //
|
| 2986 | Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest, TRUE);
|
| 2987 | if (EFI_ERROR (Status)) {
|
| 2988 | return Status;
|
| 2989 | }
|
| 2990 |
|
| 2991 | //
|
| 2992 | // 2. Set value to hii config routine protocol.
|
| 2993 | //
|
| 2994 | Status = mHiiConfigRouting->RouteConfig (
|
| 2995 | mHiiConfigRouting,
|
| 2996 | ConfigResp,
|
| 2997 | &Progress
|
| 2998 | );
|
| 2999 | FreePool (ConfigResp);
|
| 3000 |
|
| 3001 | if (EFI_ERROR (Status)) {
|
| 3002 | InsertTailList (&gBrowserSaveFailFormSetList, &ConfigInfo->SaveFailLink);
|
| 3003 | continue;
|
| 3004 | }
|
| 3005 |
|
| 3006 | //
|
| 3007 | // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
|
| 3008 | //
|
| 3009 | SynchronizeStorage (ConfigInfo->Storage, ConfigInfo->ConfigRequest, TRUE);
|
| 3010 | }
|
| 3011 |
|
| 3012 | //
|
| 3013 | // 4. Process the save failed storage.
|
| 3014 | //
|
| 3015 | if (!IsListEmpty (&gBrowserSaveFailFormSetList)) {
|
| 3016 | if (ConfirmSaveFail (Form->FormTitle, FormSet->HiiHandle) == BROWSER_ACTION_DISCARD) {
|
| 3017 | Link = GetFirstNode (&gBrowserSaveFailFormSetList);
|
| 3018 | while (!IsNull (&gBrowserSaveFailFormSetList, Link)) {
|
| 3019 | ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link);
|
| 3020 | Link = GetNextNode (&gBrowserSaveFailFormSetList, Link);
|
| 3021 |
|
| 3022 | SynchronizeStorage(ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);
|
| 3023 |
|
| 3024 | Status = EFI_SUCCESS;
|
| 3025 | }
|
| 3026 | } else {
|
| 3027 | Status = EFI_UNSUPPORTED;
|
| 3028 | }
|
| 3029 |
|
| 3030 | //
|
| 3031 | // Free Form save fail list.
|
| 3032 | //
|
| 3033 | while (!IsListEmpty (&gBrowserSaveFailFormSetList)) {
|
| 3034 | Link = GetFirstNode (&gBrowserSaveFailFormSetList);
|
| 3035 | ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link);
|
| 3036 | RemoveEntryList (&ConfigInfo->SaveFailLink);
|
| 3037 | }
|
| 3038 | }
|
| 3039 |
|
| 3040 | //
|
| 3041 | // 5. Update the NV flag.
|
| 3042 | //
|
| 3043 | ValueChangeResetFlagUpdate(TRUE, FormSet, Form);
|
| 3044 |
|
| 3045 | return Status;
|
| 3046 | }
|
| 3047 |
|
| 3048 | /**
|
| 3049 | Submit data for a formset.
|
| 3050 |
|
| 3051 | @param FormSet FormSet data structure.
|
| 3052 | @param SkipProcessFail Whether skip to process the save failed storage.
|
| 3053 | If submit formset is called when do system level save,
|
| 3054 | set this value to true and process the failed formset
|
| 3055 | together.
|
| 3056 | if submit formset is called when do formset level save,
|
| 3057 | set the value to false and process the failed storage
|
| 3058 | right after process all storages for this formset.
|
| 3059 |
|
| 3060 | @retval EFI_SUCCESS The function completed successfully.
|
| 3061 | @retval EFI_UNSUPPORTED Unsupport SettingScope.
|
| 3062 |
|
| 3063 | **/
|
| 3064 | EFI_STATUS
|
| 3065 | SubmitForFormSet (
|
| 3066 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 3067 | IN BOOLEAN SkipProcessFail
|
| 3068 | )
|
| 3069 | {
|
| 3070 | EFI_STATUS Status;
|
| 3071 | LIST_ENTRY *Link;
|
| 3072 | EFI_STRING ConfigResp;
|
| 3073 | EFI_STRING Progress;
|
| 3074 | BROWSER_STORAGE *Storage;
|
| 3075 | FORMSET_STORAGE *FormSetStorage;
|
| 3076 | FORM_BROWSER_FORM *Form;
|
| 3077 | BOOLEAN HasInserted;
|
| 3078 | FORM_BROWSER_STATEMENT *Question;
|
| 3079 |
|
| 3080 | HasInserted = FALSE;
|
| 3081 |
|
| 3082 | if (!IsNvUpdateRequiredForFormSet (FormSet)) {
|
| 3083 | return EFI_SUCCESS;
|
| 3084 | }
|
| 3085 |
|
| 3086 | Form = NULL;
|
| 3087 | Status = NoSubmitCheck (FormSet, &Form, &Question);
|
| 3088 | if (EFI_ERROR (Status)) {
|
| 3089 | if (SkipProcessFail) {
|
| 3090 | //
|
| 3091 | // Process NO_SUBMIT check first, so insert it at head.
|
| 3092 | //
|
| 3093 | FormSet->SaveFailForm = Form;
|
| 3094 | FormSet->SaveFailStatement = Question;
|
| 3095 | InsertHeadList (&gBrowserSaveFailFormSetList, &FormSet->SaveFailLink);
|
| 3096 | }
|
| 3097 |
|
| 3098 | return Status;
|
| 3099 | }
|
| 3100 |
|
| 3101 | Form = NULL;
|
| 3102 | Question = NULL;
|
| 3103 | //
|
| 3104 | // Submit Buffer storage or Name/Value storage
|
| 3105 | //
|
| 3106 | Link = GetFirstNode (&FormSet->StorageListHead);
|
| 3107 | while (!IsNull (&FormSet->StorageListHead, Link)) {
|
| 3108 | FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);
|
| 3109 | Storage = FormSetStorage->BrowserStorage;
|
| 3110 | Link = GetNextNode (&FormSet->StorageListHead, Link);
|
| 3111 |
|
| 3112 | if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
|
| 3113 | continue;
|
| 3114 | }
|
| 3115 |
|
| 3116 | //
|
| 3117 | // Skip if there is no RequestElement
|
| 3118 | //
|
| 3119 | if (FormSetStorage->ElementCount == 0) {
|
| 3120 | continue;
|
| 3121 | }
|
| 3122 |
|
| 3123 | //
|
| 3124 | // 1. Prepare <ConfigResp>
|
| 3125 | //
|
| 3126 | Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest, TRUE);
|
| 3127 | if (EFI_ERROR (Status)) {
|
| 3128 | return Status;
|
| 3129 | }
|
| 3130 |
|
| 3131 | //
|
| 3132 | // 2. Send <ConfigResp> to Routine config Protocol.
|
| 3133 | //
|
| 3134 | Status = mHiiConfigRouting->RouteConfig (
|
| 3135 | mHiiConfigRouting,
|
| 3136 | ConfigResp,
|
| 3137 | &Progress
|
| 3138 | );
|
| 3139 | if (EFI_ERROR (Status)) {
|
| 3140 | InsertTailList (&FormSet->SaveFailStorageListHead, &FormSetStorage->SaveFailLink);
|
| 3141 | if (!HasInserted) {
|
| 3142 | //
|
| 3143 | // Call submit formset for system level, save the formset info
|
| 3144 | // and process later.
|
| 3145 | //
|
| 3146 | FindQuestionFromProgress(FormSet, Storage, Progress, &Form, &Question);
|
| 3147 | ASSERT (Form != NULL && Question != NULL);
|
| 3148 | FormSet->SaveFailForm = Form;
|
| 3149 | FormSet->SaveFailStatement = Question;
|
| 3150 | if (SkipProcessFail) {
|
| 3151 | InsertTailList (&gBrowserSaveFailFormSetList, &FormSet->SaveFailLink);
|
| 3152 | }
|
| 3153 | HasInserted = TRUE;
|
| 3154 | }
|
| 3155 |
|
| 3156 | FreePool (ConfigResp);
|
| 3157 | continue;
|
| 3158 | }
|
| 3159 |
|
| 3160 | FreePool (ConfigResp);
|
| 3161 | //
|
| 3162 | // 3. Config success, update storage shadow Buffer
|
| 3163 | //
|
| 3164 | SynchronizeStorage (Storage, FormSetStorage->ConfigRequest, TRUE);
|
| 3165 | }
|
| 3166 |
|
| 3167 | //
|
| 3168 | // 4. Has save fail storage need to handle.
|
| 3169 | //
|
| 3170 | if (Form != NULL) {
|
| 3171 | if (!SkipProcessFail) {
|
| 3172 | //
|
| 3173 | // If not in system level, just handl the save failed storage here.
|
| 3174 | //
|
| 3175 | if (ConfirmSaveFail (Form->FormTitle, FormSet->HiiHandle) == BROWSER_ACTION_DISCARD) {
|
| 3176 | Link = GetFirstNode (&FormSet->SaveFailStorageListHead);
|
| 3177 | while (!IsNull (&FormSet->SaveFailStorageListHead, Link)) {
|
| 3178 | FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link);
|
| 3179 | Storage = FormSetStorage->BrowserStorage;
|
| 3180 | Link = GetNextNode (&FormSet->SaveFailStorageListHead, Link);
|
| 3181 |
|
| 3182 | SynchronizeStorage(FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, FALSE);
|
| 3183 |
|
| 3184 | Status = EFI_SUCCESS;
|
| 3185 | }
|
| 3186 | } else {
|
| 3187 | UiCopyMenuList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &Form->FormViewListHead);
|
| 3188 |
|
| 3189 | gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;
|
| 3190 | gCurrentSelection->Handle = FormSet->HiiHandle;
|
| 3191 | CopyGuid (&gCurrentSelection->FormSetGuid, &FormSet->Guid);
|
| 3192 | gCurrentSelection->FormId = Form->FormId;
|
| 3193 | gCurrentSelection->QuestionId = Question->QuestionId;
|
| 3194 |
|
| 3195 | Status = EFI_UNSUPPORTED;
|
| 3196 | }
|
| 3197 |
|
| 3198 | //
|
| 3199 | // Free FormSet save fail list.
|
| 3200 | //
|
| 3201 | while (!IsListEmpty (&FormSet->SaveFailStorageListHead)) {
|
| 3202 | Link = GetFirstNode (&FormSet->SaveFailStorageListHead);
|
| 3203 | FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link);
|
| 3204 | RemoveEntryList (&FormSetStorage->SaveFailLink);
|
| 3205 | }
|
| 3206 | } else {
|
| 3207 | //
|
| 3208 | // If in system level, just return error and handle the failed formset later.
|
| 3209 | //
|
| 3210 | Status = EFI_UNSUPPORTED;
|
| 3211 | }
|
| 3212 | }
|
| 3213 |
|
| 3214 | //
|
| 3215 | // 5. Update the NV flag.
|
| 3216 | //
|
| 3217 | ValueChangeResetFlagUpdate(TRUE, FormSet, NULL);
|
| 3218 |
|
| 3219 | return Status;
|
| 3220 | }
|
| 3221 |
|
| 3222 | /**
|
| 3223 | Submit data for all formsets.
|
| 3224 |
|
| 3225 | @retval EFI_SUCCESS The function completed successfully.
|
| 3226 | @retval EFI_UNSUPPORTED Unsupport SettingScope.
|
| 3227 |
|
| 3228 | **/
|
| 3229 | EFI_STATUS
|
| 3230 | SubmitForSystem (
|
| 3231 | VOID
|
| 3232 | )
|
| 3233 | {
|
| 3234 | EFI_STATUS Status;
|
| 3235 | LIST_ENTRY *Link;
|
| 3236 | LIST_ENTRY *StorageLink;
|
| 3237 | FORMSET_STORAGE *FormSetStorage;
|
| 3238 | FORM_BROWSER_FORM *Form;
|
| 3239 | FORM_BROWSER_FORMSET *LocalFormSet;
|
| 3240 | UINT32 UserSelection;
|
| 3241 | FORM_BROWSER_STATEMENT *Question;
|
| 3242 |
|
| 3243 | mSystemSubmit = TRUE;
|
| 3244 | Link = GetFirstNode (&gBrowserFormSetList);
|
| 3245 | while (!IsNull (&gBrowserFormSetList, Link)) {
|
| 3246 | LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);
|
| 3247 | Link = GetNextNode (&gBrowserFormSetList, Link);
|
| 3248 | if (!ValidateFormSet(LocalFormSet)) {
|
| 3249 | continue;
|
| 3250 | }
|
| 3251 |
|
| 3252 | Status = SubmitForFormSet (LocalFormSet, TRUE);
|
| 3253 | if (EFI_ERROR (Status)) {
|
| 3254 | continue;
|
| 3255 | }
|
| 3256 |
|
| 3257 | //
|
| 3258 | // Remove maintain backup list after save except for the current using FormSet.
|
| 3259 | //
|
| 3260 | if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {
|
| 3261 | CleanBrowserStorage(LocalFormSet);
|
| 3262 | RemoveEntryList (&LocalFormSet->Link);
|
| 3263 | DestroyFormSet (LocalFormSet);
|
| 3264 | }
|
| 3265 | }
|
| 3266 | mSystemSubmit = FALSE;
|
| 3267 |
|
| 3268 | Status = EFI_SUCCESS;
|
| 3269 |
|
| 3270 | //
|
| 3271 | // Process the save failed formsets.
|
| 3272 | //
|
| 3273 | Link = GetFirstNode (&gBrowserSaveFailFormSetList);
|
| 3274 | while (!IsNull (&gBrowserSaveFailFormSetList, Link)) {
|
| 3275 | LocalFormSet = FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link);
|
| 3276 | Link = GetNextNode (&gBrowserSaveFailFormSetList, Link);
|
| 3277 |
|
| 3278 | if (!ValidateFormSet(LocalFormSet)) {
|
| 3279 | continue;
|
| 3280 | }
|
| 3281 |
|
| 3282 | Form = LocalFormSet->SaveFailForm;
|
| 3283 | Question= LocalFormSet->SaveFailStatement;
|
| 3284 |
|
| 3285 | //
|
| 3286 | // Confirm with user, get user input.
|
| 3287 | //
|
| 3288 | if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {
|
| 3289 | //
|
| 3290 | // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.
|
| 3291 | //
|
| 3292 | UserSelection = ConfirmNoSubmitFail (Form->FormTitle, LocalFormSet->HiiHandle);
|
| 3293 | } else {
|
| 3294 | UserSelection = ConfirmSaveFail (Form->FormTitle, LocalFormSet->HiiHandle);
|
| 3295 | }
|
| 3296 |
|
| 3297 | if (UserSelection == BROWSER_ACTION_DISCARD) {
|
| 3298 | if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {
|
| 3299 | StorageLink = GetFirstNode (&LocalFormSet->StorageListHead);
|
| 3300 | while (!IsNull (&LocalFormSet->StorageListHead, StorageLink)) {
|
| 3301 | FormSetStorage = FORMSET_STORAGE_FROM_LINK (StorageLink);
|
| 3302 | StorageLink = GetNextNode (&LocalFormSet->StorageListHead, StorageLink);
|
| 3303 |
|
| 3304 | SynchronizeStorage(FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, FALSE);
|
| 3305 | }
|
| 3306 | } else {
|
| 3307 | StorageLink = GetFirstNode (&LocalFormSet->SaveFailStorageListHead);
|
| 3308 | while (!IsNull (&LocalFormSet->SaveFailStorageListHead, StorageLink)) {
|
| 3309 | FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink);
|
| 3310 | StorageLink = GetNextNode (&LocalFormSet->SaveFailStorageListHead, StorageLink);
|
| 3311 |
|
| 3312 | SynchronizeStorage(FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, FALSE);
|
| 3313 | }
|
| 3314 | }
|
| 3315 |
|
| 3316 | if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {
|
| 3317 | CleanBrowserStorage(LocalFormSet);
|
| 3318 | RemoveEntryList (&LocalFormSet->Link);
|
| 3319 | RemoveEntryList (&LocalFormSet->SaveFailLink);
|
| 3320 | DestroyFormSet (LocalFormSet);
|
| 3321 | } else {
|
| 3322 | ValueChangeResetFlagUpdate(FALSE, LocalFormSet, NULL);
|
| 3323 | }
|
| 3324 | } else {
|
| 3325 | if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {
|
| 3326 | NoSubmitCheck (LocalFormSet, &Form, &Question);
|
| 3327 | }
|
| 3328 |
|
| 3329 | UiCopyMenuList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &Form->FormViewListHead);
|
| 3330 |
|
| 3331 | gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;
|
| 3332 | gCurrentSelection->Handle = LocalFormSet->HiiHandle;
|
| 3333 | CopyGuid (&gCurrentSelection->FormSetGuid, &LocalFormSet->Guid);
|
| 3334 | gCurrentSelection->FormId = Form->FormId;
|
| 3335 | gCurrentSelection->QuestionId = Question->QuestionId;
|
| 3336 |
|
| 3337 | Status = EFI_UNSUPPORTED;
|
| 3338 | break;
|
| 3339 | }
|
| 3340 | }
|
| 3341 |
|
| 3342 | //
|
| 3343 | // Clean the list which will not process.
|
| 3344 | //
|
| 3345 | while (!IsListEmpty (&gBrowserSaveFailFormSetList)) {
|
| 3346 | Link = GetFirstNode (&gBrowserSaveFailFormSetList);
|
| 3347 | LocalFormSet = FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link);
|
| 3348 | RemoveEntryList (&LocalFormSet->SaveFailLink);
|
| 3349 |
|
| 3350 | while (!IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {
|
| 3351 | StorageLink = GetFirstNode (&LocalFormSet->SaveFailStorageListHead);
|
| 3352 | FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink);
|
| 3353 | RemoveEntryList (&FormSetStorage->SaveFailLink);
|
| 3354 | }
|
| 3355 | }
|
| 3356 |
|
| 3357 | return Status;
|
| 3358 | }
|
| 3359 |
|
| 3360 | /**
|
| 3361 | Submit data based on the input Setting level (Form, FormSet or System).
|
| 3362 |
|
| 3363 | @param FormSet FormSet data structure.
|
| 3364 | @param Form Form data structure.
|
| 3365 | @param SettingScope Setting Scope for Submit action.
|
| 3366 |
|
| 3367 | @retval EFI_SUCCESS The function completed successfully.
|
| 3368 | @retval EFI_UNSUPPORTED Unsupport SettingScope.
|
| 3369 |
|
| 3370 | **/
|
| 3371 | EFI_STATUS
|
| 3372 | SubmitForm (
|
| 3373 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 3374 | IN FORM_BROWSER_FORM *Form,
|
| 3375 | IN BROWSER_SETTING_SCOPE SettingScope
|
| 3376 | )
|
| 3377 | {
|
| 3378 | EFI_STATUS Status;
|
| 3379 |
|
| 3380 | switch (SettingScope) {
|
| 3381 | case FormLevel:
|
| 3382 | Status = SubmitForForm(FormSet, Form);
|
| 3383 | break;
|
| 3384 |
|
| 3385 | case FormSetLevel:
|
| 3386 | Status = SubmitForFormSet (FormSet, FALSE);
|
| 3387 | break;
|
| 3388 |
|
| 3389 | case SystemLevel:
|
| 3390 | Status = SubmitForSystem ();
|
| 3391 | break;
|
| 3392 |
|
| 3393 | default:
|
| 3394 | Status = EFI_UNSUPPORTED;
|
| 3395 | break;
|
| 3396 | }
|
| 3397 |
|
| 3398 | return Status;
|
| 3399 | }
|
| 3400 |
|
| 3401 | /**
|
| 3402 | Converts the unicode character of the string from uppercase to lowercase.
|
| 3403 | This is a internal function.
|
| 3404 |
|
| 3405 | @param ConfigString String to be converted
|
| 3406 |
|
| 3407 | **/
|
| 3408 | VOID
|
| 3409 | EFIAPI
|
| 3410 | HiiToLower (
|
| 3411 | IN EFI_STRING ConfigString
|
| 3412 | )
|
| 3413 | {
|
| 3414 | EFI_STRING String;
|
| 3415 | BOOLEAN Lower;
|
| 3416 |
|
| 3417 | ASSERT (ConfigString != NULL);
|
| 3418 |
|
| 3419 | //
|
| 3420 | // Convert all hex digits in range [A-F] in the configuration header to [a-f]
|
| 3421 | //
|
| 3422 | for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {
|
| 3423 | if (*String == L'=') {
|
| 3424 | Lower = TRUE;
|
| 3425 | } else if (*String == L'&') {
|
| 3426 | Lower = FALSE;
|
| 3427 | } else if (Lower && *String >= L'A' && *String <= L'F') {
|
| 3428 | *String = (CHAR16) (*String - L'A' + L'a');
|
| 3429 | }
|
| 3430 | }
|
| 3431 | }
|
| 3432 |
|
| 3433 | /**
|
| 3434 | Find the point in the ConfigResp string for this question.
|
| 3435 |
|
| 3436 | @param Question The question.
|
| 3437 | @param ConfigResp Get ConfigResp string.
|
| 3438 |
|
| 3439 | @retval point to the offset where is for this question.
|
| 3440 |
|
| 3441 | **/
|
| 3442 | CHAR16 *
|
| 3443 | GetOffsetFromConfigResp (
|
| 3444 | IN FORM_BROWSER_STATEMENT *Question,
|
| 3445 | IN CHAR16 *ConfigResp
|
| 3446 | )
|
| 3447 | {
|
| 3448 | CHAR16 *RequestElement;
|
| 3449 | CHAR16 *BlockData;
|
| 3450 |
|
| 3451 | //
|
| 3452 | // Type is EFI_HII_VARSTORE_NAME_VALUE.
|
| 3453 | //
|
| 3454 | if (Question->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
|
| 3455 | RequestElement = StrStr (ConfigResp, Question->VariableName);
|
| 3456 | if (RequestElement != NULL) {
|
| 3457 | //
|
| 3458 | // Skip the "VariableName=" field.
|
| 3459 | //
|
| 3460 | RequestElement += StrLen (Question->VariableName) + 1;
|
| 3461 | }
|
| 3462 |
|
| 3463 | return RequestElement;
|
| 3464 | }
|
| 3465 |
|
| 3466 | //
|
| 3467 | // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
|
| 3468 | //
|
| 3469 |
|
| 3470 | //
|
| 3471 | // 1. Directly use Question->BlockName to find.
|
| 3472 | //
|
| 3473 | RequestElement = StrStr (ConfigResp, Question->BlockName);
|
| 3474 | if (RequestElement != NULL) {
|
| 3475 | //
|
| 3476 | // Skip the "Question->BlockName&VALUE=" field.
|
| 3477 | //
|
| 3478 | RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");
|
| 3479 | return RequestElement;
|
| 3480 | }
|
| 3481 |
|
| 3482 | //
|
| 3483 | // 2. Change all hex digits in Question->BlockName to lower and compare again.
|
| 3484 | //
|
| 3485 | BlockData = AllocateCopyPool (StrSize(Question->BlockName), Question->BlockName);
|
| 3486 | ASSERT (BlockData != NULL);
|
| 3487 | HiiToLower (BlockData);
|
| 3488 | RequestElement = StrStr (ConfigResp, BlockData);
|
| 3489 | FreePool (BlockData);
|
| 3490 |
|
| 3491 | if (RequestElement != NULL) {
|
| 3492 | //
|
| 3493 | // Skip the "Question->BlockName&VALUE=" field.
|
| 3494 | //
|
| 3495 | RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");
|
| 3496 | }
|
| 3497 |
|
| 3498 | return RequestElement;
|
| 3499 | }
|
| 3500 |
|
| 3501 | /**
|
| 3502 | Get Question default value from AltCfg string.
|
| 3503 |
|
| 3504 | @param FormSet The form set.
|
| 3505 | @param Form The form
|
| 3506 | @param Question The question.
|
| 3507 |
|
| 3508 | @retval EFI_SUCCESS Question is reset to default value.
|
| 3509 |
|
| 3510 | **/
|
| 3511 | EFI_STATUS
|
| 3512 | GetDefaultValueFromAltCfg (
|
| 3513 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 3514 | IN FORM_BROWSER_FORM *Form,
|
| 3515 | IN OUT FORM_BROWSER_STATEMENT *Question
|
| 3516 | )
|
| 3517 | {
|
| 3518 | BROWSER_STORAGE *Storage;
|
| 3519 | FORMSET_STORAGE *FormSetStorage;
|
| 3520 | CHAR16 *ConfigResp;
|
| 3521 | CHAR16 *Value;
|
| 3522 | LIST_ENTRY *Link;
|
| 3523 | FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;
|
| 3524 |
|
| 3525 | Storage = Question->Storage;
|
| 3526 | if ((Storage == NULL) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {
|
| 3527 | return EFI_NOT_FOUND;
|
| 3528 | }
|
| 3529 |
|
| 3530 | //
|
| 3531 | // Try to get AltCfg string from form. If not found it, then
|
| 3532 | // try to get it from formset.
|
| 3533 | //
|
| 3534 | ConfigResp = NULL;
|
| 3535 | Link = GetFirstNode (&Form->ConfigRequestHead);
|
| 3536 | while (!IsNull (&Form->ConfigRequestHead, Link)) {
|
| 3537 | ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);
|
| 3538 | Link = GetNextNode (&Form->ConfigRequestHead, Link);
|
| 3539 |
|
| 3540 | if (Storage == ConfigInfo->Storage) {
|
| 3541 | ConfigResp = ConfigInfo->ConfigAltResp;
|
| 3542 | break;
|
| 3543 | }
|
| 3544 | }
|
| 3545 |
|
| 3546 | if (ConfigResp == NULL) {
|
| 3547 | Link = GetFirstNode (&FormSet->StorageListHead);
|
| 3548 | while (!IsNull (&FormSet->StorageListHead, Link)) {
|
| 3549 | FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);
|
| 3550 | Link = GetNextNode (&FormSet->StorageListHead, Link);
|
| 3551 |
|
| 3552 | if (Storage == FormSetStorage->BrowserStorage) {
|
| 3553 | ConfigResp = FormSetStorage->ConfigAltResp;
|
| 3554 | break;
|
| 3555 | }
|
| 3556 | }
|
| 3557 | }
|
| 3558 |
|
| 3559 | if (ConfigResp == NULL) {
|
| 3560 | return EFI_NOT_FOUND;
|
| 3561 | }
|
| 3562 |
|
| 3563 | Value = GetOffsetFromConfigResp (Question, ConfigResp);
|
| 3564 | if (Value == NULL) {
|
| 3565 | return EFI_NOT_FOUND;
|
| 3566 | }
|
| 3567 |
|
| 3568 | return BufferToValue (Question, Value);
|
| 3569 | }
|
| 3570 |
|
| 3571 | /**
|
| 3572 | Get default Id value used for browser.
|
| 3573 |
|
| 3574 | @param DefaultId The default id value used by hii.
|
| 3575 |
|
| 3576 | @retval Browser used default value.
|
| 3577 |
|
| 3578 | **/
|
| 3579 | INTN
|
| 3580 | GetDefaultIdForCallBack (
|
| 3581 | UINTN DefaultId
|
| 3582 | )
|
| 3583 | {
|
| 3584 | if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {
|
| 3585 | return EFI_BROWSER_ACTION_DEFAULT_STANDARD;
|
| 3586 | } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
|
| 3587 | return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;
|
| 3588 | } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {
|
| 3589 | return EFI_BROWSER_ACTION_DEFAULT_SAFE;
|
| 3590 | } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000) {
|
| 3591 | return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;
|
| 3592 | } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000) {
|
| 3593 | return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;
|
| 3594 | } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000) {
|
| 3595 | return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;
|
| 3596 | } else {
|
| 3597 | return -1;
|
| 3598 | }
|
| 3599 | }
|
| 3600 |
|
| 3601 |
|
| 3602 |
|
| 3603 | /**
|
| 3604 | Return data element in an Array by its Index.
|
| 3605 |
|
| 3606 | @param Array The data array.
|
| 3607 | @param Type Type of the data in this array.
|
| 3608 | @param Index Zero based index for data in this array.
|
| 3609 |
|
| 3610 | @retval Value The data to be returned
|
| 3611 |
|
| 3612 | **/
|
| 3613 | UINT64
|
| 3614 | GetArrayData (
|
| 3615 | IN VOID *Array,
|
| 3616 | IN UINT8 Type,
|
| 3617 | IN UINTN Index
|
| 3618 | )
|
| 3619 | {
|
| 3620 | UINT64 Data;
|
| 3621 |
|
| 3622 | ASSERT (Array != NULL);
|
| 3623 |
|
| 3624 | Data = 0;
|
| 3625 | switch (Type) {
|
| 3626 | case EFI_IFR_TYPE_NUM_SIZE_8:
|
| 3627 | Data = (UINT64) *(((UINT8 *) Array) + Index);
|
| 3628 | break;
|
| 3629 |
|
| 3630 | case EFI_IFR_TYPE_NUM_SIZE_16:
|
| 3631 | Data = (UINT64) *(((UINT16 *) Array) + Index);
|
| 3632 | break;
|
| 3633 |
|
| 3634 | case EFI_IFR_TYPE_NUM_SIZE_32:
|
| 3635 | Data = (UINT64) *(((UINT32 *) Array) + Index);
|
| 3636 | break;
|
| 3637 |
|
| 3638 | case EFI_IFR_TYPE_NUM_SIZE_64:
|
| 3639 | Data = (UINT64) *(((UINT64 *) Array) + Index);
|
| 3640 | break;
|
| 3641 |
|
| 3642 | default:
|
| 3643 | break;
|
| 3644 | }
|
| 3645 |
|
| 3646 | return Data;
|
| 3647 | }
|
| 3648 |
|
| 3649 |
|
| 3650 | /**
|
| 3651 | Set value of a data element in an Array by its Index.
|
| 3652 |
|
| 3653 | @param Array The data array.
|
| 3654 | @param Type Type of the data in this array.
|
| 3655 | @param Index Zero based index for data in this array.
|
| 3656 | @param Value The value to be set.
|
| 3657 |
|
| 3658 | **/
|
| 3659 | VOID
|
| 3660 | SetArrayData (
|
| 3661 | IN VOID *Array,
|
| 3662 | IN UINT8 Type,
|
| 3663 | IN UINTN Index,
|
| 3664 | IN UINT64 Value
|
| 3665 | )
|
| 3666 | {
|
| 3667 |
|
| 3668 | ASSERT (Array != NULL);
|
| 3669 |
|
| 3670 | switch (Type) {
|
| 3671 | case EFI_IFR_TYPE_NUM_SIZE_8:
|
| 3672 | *(((UINT8 *) Array) + Index) = (UINT8) Value;
|
| 3673 | break;
|
| 3674 |
|
| 3675 | case EFI_IFR_TYPE_NUM_SIZE_16:
|
| 3676 | *(((UINT16 *) Array) + Index) = (UINT16) Value;
|
| 3677 | break;
|
| 3678 |
|
| 3679 | case EFI_IFR_TYPE_NUM_SIZE_32:
|
| 3680 | *(((UINT32 *) Array) + Index) = (UINT32) Value;
|
| 3681 | break;
|
| 3682 |
|
| 3683 | case EFI_IFR_TYPE_NUM_SIZE_64:
|
| 3684 | *(((UINT64 *) Array) + Index) = (UINT64) Value;
|
| 3685 | break;
|
| 3686 |
|
| 3687 | default:
|
| 3688 | break;
|
| 3689 | }
|
| 3690 | }
|
| 3691 |
|
| 3692 | /**
|
| 3693 | Search an Option of a Question by its value.
|
| 3694 |
|
| 3695 | @param Question The Question
|
| 3696 | @param OptionValue Value for Option to be searched.
|
| 3697 |
|
| 3698 | @retval Pointer Pointer to the found Option.
|
| 3699 | @retval NULL Option not found.
|
| 3700 |
|
| 3701 | **/
|
| 3702 | QUESTION_OPTION *
|
| 3703 | ValueToOption (
|
| 3704 | IN FORM_BROWSER_STATEMENT *Question,
|
| 3705 | IN EFI_HII_VALUE *OptionValue
|
| 3706 | )
|
| 3707 | {
|
| 3708 | LIST_ENTRY *Link;
|
| 3709 | QUESTION_OPTION *Option;
|
| 3710 | INTN Result;
|
| 3711 |
|
| 3712 | Link = GetFirstNode (&Question->OptionListHead);
|
| 3713 | while (!IsNull (&Question->OptionListHead, Link)) {
|
| 3714 | Option = QUESTION_OPTION_FROM_LINK (Link);
|
| 3715 |
|
| 3716 | if ((CompareHiiValue (&Option->Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {
|
| 3717 | //
|
| 3718 | // Check the suppressif condition, only a valid option can be return.
|
| 3719 | //
|
| 3720 | if ((Option->SuppressExpression == NULL) ||
|
| 3721 | ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse))) {
|
| 3722 | return Option;
|
| 3723 | }
|
| 3724 | }
|
| 3725 |
|
| 3726 | Link = GetNextNode (&Question->OptionListHead, Link);
|
| 3727 | }
|
| 3728 |
|
| 3729 | return NULL;
|
| 3730 | }
|
| 3731 |
|
| 3732 |
|
| 3733 | /**
|
| 3734 | Reset Question to its default value.
|
| 3735 |
|
| 3736 | @param FormSet The form set.
|
| 3737 | @param Form The form.
|
| 3738 | @param Question The question.
|
| 3739 | @param DefaultId The Class of the default.
|
| 3740 |
|
| 3741 | @retval EFI_SUCCESS Question is reset to default value.
|
| 3742 |
|
| 3743 | **/
|
| 3744 | EFI_STATUS
|
| 3745 | GetQuestionDefault (
|
| 3746 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 3747 | IN FORM_BROWSER_FORM *Form,
|
| 3748 | IN FORM_BROWSER_STATEMENT *Question,
|
| 3749 | IN UINT16 DefaultId
|
| 3750 | )
|
| 3751 | {
|
| 3752 | EFI_STATUS Status;
|
| 3753 | LIST_ENTRY *Link;
|
| 3754 | QUESTION_DEFAULT *Default;
|
| 3755 | QUESTION_OPTION *Option;
|
| 3756 | EFI_HII_VALUE *HiiValue;
|
| 3757 | UINT8 Index;
|
| 3758 | EFI_STRING StrValue;
|
| 3759 | EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
|
| 3760 | EFI_BROWSER_ACTION_REQUEST ActionRequest;
|
| 3761 | INTN Action;
|
| 3762 | CHAR16 *NewString;
|
| 3763 |
|
| 3764 | Status = EFI_NOT_FOUND;
|
| 3765 | StrValue = NULL;
|
| 3766 |
|
| 3767 | //
|
| 3768 | // Statement don't have storage, skip them
|
| 3769 | //
|
| 3770 | if (Question->QuestionId == 0) {
|
| 3771 | return Status;
|
| 3772 | }
|
| 3773 |
|
| 3774 | //
|
| 3775 | // There are Five ways to specify default value for a Question:
|
| 3776 | // 1, use call back function (highest priority)
|
| 3777 | // 2, use ExtractConfig function
|
| 3778 | // 3, use nested EFI_IFR_DEFAULT
|
| 3779 | // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
|
| 3780 | // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
|
| 3781 | //
|
| 3782 | HiiValue = &Question->HiiValue;
|
| 3783 |
|
| 3784 | //
|
| 3785 | // Get Question defaut value from call back function.
|
| 3786 | //
|
| 3787 | ConfigAccess = FormSet->ConfigAccess;
|
| 3788 | Action = GetDefaultIdForCallBack (DefaultId);
|
| 3789 | if ((Action > 0) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {
|
| 3790 | ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
|
| 3791 | Status = ConfigAccess->Callback (
|
| 3792 | ConfigAccess,
|
| 3793 | Action,
|
| 3794 | Question->QuestionId,
|
| 3795 | HiiValue->Type,
|
| 3796 | &HiiValue->Value,
|
| 3797 | &ActionRequest
|
| 3798 | );
|
| 3799 | if (!EFI_ERROR (Status)) {
|
| 3800 | if (HiiValue->Type == EFI_IFR_TYPE_STRING) {
|
| 3801 | NewString = GetToken (Question->HiiValue.Value.string, FormSet->HiiHandle);
|
| 3802 | ASSERT (NewString != NULL);
|
| 3803 |
|
| 3804 | ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Question->StorageWidth);
|
| 3805 | if (StrLen (NewString) * sizeof (CHAR16) <= Question->StorageWidth) {
|
| 3806 | CopyMem (Question->BufferValue, NewString, StrSize (NewString));
|
| 3807 | } else {
|
| 3808 | CopyMem (Question->BufferValue, NewString, Question->StorageWidth);
|
| 3809 | }
|
| 3810 |
|
| 3811 | FreePool (NewString);
|
| 3812 | }
|
| 3813 | return Status;
|
| 3814 | }
|
| 3815 | }
|
| 3816 |
|
| 3817 | //
|
| 3818 | // Get default value from altcfg string.
|
| 3819 | //
|
| 3820 | if (ConfigAccess != NULL) {
|
| 3821 | Status = GetDefaultValueFromAltCfg(FormSet, Form, Question);
|
| 3822 | if (!EFI_ERROR (Status)) {
|
| 3823 | return Status;
|
| 3824 | }
|
| 3825 | }
|
| 3826 |
|
| 3827 | //
|
| 3828 | // EFI_IFR_DEFAULT has highest priority
|
| 3829 | //
|
| 3830 | if (!IsListEmpty (&Question->DefaultListHead)) {
|
| 3831 | Link = GetFirstNode (&Question->DefaultListHead);
|
| 3832 | while (!IsNull (&Question->DefaultListHead, Link)) {
|
| 3833 | Default = QUESTION_DEFAULT_FROM_LINK (Link);
|
| 3834 |
|
| 3835 | if (Default->DefaultId == DefaultId) {
|
| 3836 | if (Default->ValueExpression != NULL) {
|
| 3837 | //
|
| 3838 | // Default is provided by an Expression, evaluate it
|
| 3839 | //
|
| 3840 | Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);
|
| 3841 | if (EFI_ERROR (Status)) {
|
| 3842 | return Status;
|
| 3843 | }
|
| 3844 |
|
| 3845 | if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {
|
| 3846 | ASSERT (HiiValue->Type == EFI_IFR_TYPE_BUFFER && Question->BufferValue != NULL);
|
| 3847 | if (Question->StorageWidth > Default->ValueExpression->Result.BufferLen) {
|
| 3848 | CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Default->ValueExpression->Result.BufferLen);
|
| 3849 | Question->HiiValue.BufferLen = Default->ValueExpression->Result.BufferLen;
|
| 3850 | } else {
|
| 3851 | CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Question->StorageWidth);
|
| 3852 | Question->HiiValue.BufferLen = Question->StorageWidth;
|
| 3853 | }
|
| 3854 | FreePool (Default->ValueExpression->Result.Buffer);
|
| 3855 | }
|
| 3856 | HiiValue->Type = Default->ValueExpression->Result.Type;
|
| 3857 | CopyMem (&HiiValue->Value, &Default->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));
|
| 3858 | } else {
|
| 3859 | //
|
| 3860 | // Default value is embedded in EFI_IFR_DEFAULT
|
| 3861 | //
|
| 3862 | CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));
|
| 3863 | }
|
| 3864 |
|
| 3865 | if (HiiValue->Type == EFI_IFR_TYPE_STRING) {
|
| 3866 | StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);
|
| 3867 | if (StrValue == NULL) {
|
| 3868 | return EFI_NOT_FOUND;
|
| 3869 | }
|
| 3870 | if (Question->StorageWidth > StrSize (StrValue)) {
|
| 3871 | CopyMem (Question->BufferValue, StrValue, StrSize (StrValue));
|
| 3872 | } else {
|
| 3873 | CopyMem (Question->BufferValue, StrValue, Question->StorageWidth);
|
| 3874 | }
|
| 3875 | }
|
| 3876 |
|
| 3877 | return EFI_SUCCESS;
|
| 3878 | }
|
| 3879 |
|
| 3880 | Link = GetNextNode (&Question->DefaultListHead, Link);
|
| 3881 | }
|
| 3882 | }
|
| 3883 |
|
| 3884 | //
|
| 3885 | // EFI_ONE_OF_OPTION
|
| 3886 | //
|
| 3887 | if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {
|
| 3888 | if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
|
| 3889 | //
|
| 3890 | // OneOfOption could only provide Standard and Manufacturing default
|
| 3891 | //
|
| 3892 | Link = GetFirstNode (&Question->OptionListHead);
|
| 3893 | while (!IsNull (&Question->OptionListHead, Link)) {
|
| 3894 | Option = QUESTION_OPTION_FROM_LINK (Link);
|
| 3895 | Link = GetNextNode (&Question->OptionListHead, Link);
|
| 3896 |
|
| 3897 | if ((Option->SuppressExpression != NULL) &&
|
| 3898 | EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {
|
| 3899 | continue;
|
| 3900 | }
|
| 3901 |
|
| 3902 | if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||
|
| 3903 | ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))
|
| 3904 | ) {
|
| 3905 | CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
|
| 3906 |
|
| 3907 | return EFI_SUCCESS;
|
| 3908 | }
|
| 3909 | }
|
| 3910 | }
|
| 3911 | }
|
| 3912 |
|
| 3913 | //
|
| 3914 | // EFI_IFR_CHECKBOX - lowest priority
|
| 3915 | //
|
| 3916 | if (Question->Operand == EFI_IFR_CHECKBOX_OP) {
|
| 3917 | if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
|
| 3918 | //
|
| 3919 | // Checkbox could only provide Standard and Manufacturing default
|
| 3920 | //
|
| 3921 | if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||
|
| 3922 | ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))
|
| 3923 | ) {
|
| 3924 | HiiValue->Value.b = TRUE;
|
| 3925 | } else {
|
| 3926 | HiiValue->Value.b = FALSE;
|
| 3927 | }
|
| 3928 |
|
| 3929 | return EFI_SUCCESS;
|
| 3930 | }
|
| 3931 | }
|
| 3932 |
|
| 3933 | //
|
| 3934 | // For Questions without default
|
| 3935 | //
|
| 3936 | Status = EFI_NOT_FOUND;
|
| 3937 | switch (Question->Operand) {
|
| 3938 | case EFI_IFR_NUMERIC_OP:
|
| 3939 | //
|
| 3940 | // Take minimum value as numeric default value
|
| 3941 | //
|
| 3942 | if ((HiiValue->Value.u64 < Question->Minimum) || (HiiValue->Value.u64 > Question->Maximum)) {
|
| 3943 | HiiValue->Value.u64 = Question->Minimum;
|
| 3944 | Status = EFI_SUCCESS;
|
| 3945 | }
|
| 3946 | break;
|
| 3947 |
|
| 3948 | case EFI_IFR_ONE_OF_OP:
|
| 3949 | //
|
| 3950 | // Take first oneof option as oneof's default value
|
| 3951 | //
|
| 3952 | if (ValueToOption (Question, HiiValue) == NULL) {
|
| 3953 | Link = GetFirstNode (&Question->OptionListHead);
|
| 3954 | while (!IsNull (&Question->OptionListHead, Link)) {
|
| 3955 | Option = QUESTION_OPTION_FROM_LINK (Link);
|
| 3956 | Link = GetNextNode (&Question->OptionListHead, Link);
|
| 3957 |
|
| 3958 | if ((Option->SuppressExpression != NULL) &&
|
| 3959 | EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {
|
| 3960 | continue;
|
| 3961 | }
|
| 3962 |
|
| 3963 | CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
|
| 3964 | Status = EFI_SUCCESS;
|
| 3965 | break;
|
| 3966 | }
|
| 3967 | }
|
| 3968 | break;
|
| 3969 |
|
| 3970 | case EFI_IFR_ORDERED_LIST_OP:
|
| 3971 | //
|
| 3972 | // Take option sequence in IFR as ordered list's default value
|
| 3973 | //
|
| 3974 | Index = 0;
|
| 3975 | Link = GetFirstNode (&Question->OptionListHead);
|
| 3976 | while (!IsNull (&Question->OptionListHead, Link)) {
|
| 3977 | Status = EFI_SUCCESS;
|
| 3978 | Option = QUESTION_OPTION_FROM_LINK (Link);
|
| 3979 | Link = GetNextNode (&Question->OptionListHead, Link);
|
| 3980 |
|
| 3981 | if ((Option->SuppressExpression != NULL) &&
|
| 3982 | EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {
|
| 3983 | continue;
|
| 3984 | }
|
| 3985 |
|
| 3986 | SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);
|
| 3987 |
|
| 3988 | Index++;
|
| 3989 | if (Index >= Question->MaxContainers) {
|
| 3990 | break;
|
| 3991 | }
|
| 3992 | }
|
| 3993 | break;
|
| 3994 |
|
| 3995 | default:
|
| 3996 | break;
|
| 3997 | }
|
| 3998 |
|
| 3999 | return Status;
|
| 4000 | }
|
| 4001 |
|
| 4002 | /**
|
| 4003 | Get AltCfg string for current form.
|
| 4004 |
|
| 4005 | @param FormSet Form data structure.
|
| 4006 | @param Form Form data structure.
|
| 4007 | @param DefaultId The Class of the default.
|
| 4008 | @param BrowserStorage The input request storage for the questions.
|
| 4009 |
|
| 4010 | **/
|
| 4011 | VOID
|
| 4012 | ExtractAltCfgForForm (
|
| 4013 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 4014 | IN FORM_BROWSER_FORM *Form,
|
| 4015 | IN UINT16 DefaultId,
|
| 4016 | IN BROWSER_STORAGE *BrowserStorage
|
| 4017 | )
|
| 4018 | {
|
| 4019 | EFI_STATUS Status;
|
| 4020 | LIST_ENTRY *Link;
|
| 4021 | CHAR16 *ConfigResp;
|
| 4022 | CHAR16 *Progress;
|
| 4023 | CHAR16 *Result;
|
| 4024 | BROWSER_STORAGE *Storage;
|
| 4025 | FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;
|
| 4026 | FORMSET_STORAGE *FormSetStorage;
|
| 4027 |
|
| 4028 | //
|
| 4029 | // Check whether has get AltCfg string for this formset.
|
| 4030 | // If yes, no need to get AltCfg for form.
|
| 4031 | //
|
| 4032 | Link = GetFirstNode (&FormSet->StorageListHead);
|
| 4033 | while (!IsNull (&FormSet->StorageListHead, Link)) {
|
| 4034 | FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);
|
| 4035 | Storage = FormSetStorage->BrowserStorage;
|
| 4036 | Link = GetNextNode (&FormSet->StorageListHead, Link);
|
| 4037 | if (BrowserStorage != NULL && BrowserStorage != Storage) {
|
| 4038 | continue;
|
| 4039 | }
|
| 4040 |
|
| 4041 | if (Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE &&
|
| 4042 | FormSetStorage->ElementCount != 0 &&
|
| 4043 | FormSetStorage->HasCallAltCfg) {
|
| 4044 | return;
|
| 4045 | }
|
| 4046 | }
|
| 4047 |
|
| 4048 | //
|
| 4049 | // Get AltCfg string for each form.
|
| 4050 | //
|
| 4051 | Link = GetFirstNode (&Form->ConfigRequestHead);
|
| 4052 | while (!IsNull (&Form->ConfigRequestHead, Link)) {
|
| 4053 | ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);
|
| 4054 | Link = GetNextNode (&Form->ConfigRequestHead, Link);
|
| 4055 |
|
| 4056 | Storage = ConfigInfo->Storage;
|
| 4057 | if (BrowserStorage != NULL && BrowserStorage != Storage) {
|
| 4058 | continue;
|
| 4059 | }
|
| 4060 |
|
| 4061 | if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
|
| 4062 | continue;
|
| 4063 | }
|
| 4064 |
|
| 4065 | //
|
| 4066 | // 1. Skip if there is no RequestElement
|
| 4067 | //
|
| 4068 | if (ConfigInfo->ElementCount == 0) {
|
| 4069 | continue;
|
| 4070 | }
|
| 4071 |
|
| 4072 | //
|
| 4073 | // 2. Get value through hii config routine protocol.
|
| 4074 | //
|
| 4075 | Status = mHiiConfigRouting->ExtractConfig (
|
| 4076 | mHiiConfigRouting,
|
| 4077 | ConfigInfo->ConfigRequest,
|
| 4078 | &Progress,
|
| 4079 | &Result
|
| 4080 | );
|
| 4081 | if (EFI_ERROR (Status)) {
|
| 4082 | continue;
|
| 4083 | }
|
| 4084 |
|
| 4085 | //
|
| 4086 | // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
|
| 4087 | // Get the default configuration string according to the default ID.
|
| 4088 | //
|
| 4089 | Status = mHiiConfigRouting->GetAltConfig (
|
| 4090 | mHiiConfigRouting,
|
| 4091 | Result,
|
| 4092 | &Storage->Guid,
|
| 4093 | Storage->Name,
|
| 4094 | NULL,
|
| 4095 | &DefaultId, // it can be NULL to get the current setting.
|
| 4096 | &ConfigResp
|
| 4097 | );
|
| 4098 | FreePool (Result);
|
| 4099 | if (EFI_ERROR (Status)) {
|
| 4100 | continue;
|
| 4101 | }
|
| 4102 |
|
| 4103 | ConfigInfo->ConfigAltResp = ConfigResp;
|
| 4104 | }
|
| 4105 | }
|
| 4106 |
|
| 4107 | /**
|
| 4108 | Clean AltCfg string for current form.
|
| 4109 |
|
| 4110 | @param Form Form data structure.
|
| 4111 |
|
| 4112 | **/
|
| 4113 | VOID
|
| 4114 | CleanAltCfgForForm (
|
| 4115 | IN FORM_BROWSER_FORM *Form
|
| 4116 | )
|
| 4117 | {
|
| 4118 | LIST_ENTRY *Link;
|
| 4119 | FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;
|
| 4120 |
|
| 4121 | Link = GetFirstNode (&Form->ConfigRequestHead);
|
| 4122 | while (!IsNull (&Form->ConfigRequestHead, Link)) {
|
| 4123 | ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);
|
| 4124 | Link = GetNextNode (&Form->ConfigRequestHead, Link);
|
| 4125 |
|
| 4126 | if (ConfigInfo->ConfigAltResp != NULL) {
|
| 4127 | FreePool (ConfigInfo->ConfigAltResp);
|
| 4128 | ConfigInfo->ConfigAltResp = NULL;
|
| 4129 | }
|
| 4130 | }
|
| 4131 | }
|
| 4132 |
|
| 4133 | /**
|
| 4134 | Get AltCfg string for current formset.
|
| 4135 |
|
| 4136 | @param FormSet Form data structure.
|
| 4137 | @param DefaultId The Class of the default.
|
| 4138 | @param BrowserStorage The input request storage for the questions.
|
| 4139 |
|
| 4140 | **/
|
| 4141 | VOID
|
| 4142 | ExtractAltCfgForFormSet (
|
| 4143 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 4144 | IN UINT16 DefaultId,
|
| 4145 | IN BROWSER_STORAGE *BrowserStorage
|
| 4146 | )
|
| 4147 | {
|
| 4148 | EFI_STATUS Status;
|
| 4149 | LIST_ENTRY *Link;
|
| 4150 | CHAR16 *ConfigResp;
|
| 4151 | CHAR16 *Progress;
|
| 4152 | CHAR16 *Result;
|
| 4153 | BROWSER_STORAGE *Storage;
|
| 4154 | FORMSET_STORAGE *FormSetStorage;
|
| 4155 |
|
| 4156 | Link = GetFirstNode (&FormSet->StorageListHead);
|
| 4157 | while (!IsNull (&FormSet->StorageListHead, Link)) {
|
| 4158 | FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);
|
| 4159 | Storage = FormSetStorage->BrowserStorage;
|
| 4160 | Link = GetNextNode (&FormSet->StorageListHead, Link);
|
| 4161 |
|
| 4162 | if (BrowserStorage != NULL && BrowserStorage != Storage) {
|
| 4163 | continue;
|
| 4164 | }
|
| 4165 |
|
| 4166 | if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
|
| 4167 | continue;
|
| 4168 | }
|
| 4169 |
|
| 4170 | //
|
| 4171 | // 1. Skip if there is no RequestElement
|
| 4172 | //
|
| 4173 | if (FormSetStorage->ElementCount == 0) {
|
| 4174 | continue;
|
| 4175 | }
|
| 4176 |
|
| 4177 | FormSetStorage->HasCallAltCfg = TRUE;
|
| 4178 |
|
| 4179 | //
|
| 4180 | // 2. Get value through hii config routine protocol.
|
| 4181 | //
|
| 4182 | Status = mHiiConfigRouting->ExtractConfig (
|
| 4183 | mHiiConfigRouting,
|
| 4184 | FormSetStorage->ConfigRequest,
|
| 4185 | &Progress,
|
| 4186 | &Result
|
| 4187 | );
|
| 4188 | if (EFI_ERROR (Status)) {
|
| 4189 | continue;
|
| 4190 | }
|
| 4191 |
|
| 4192 | //
|
| 4193 | // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
|
| 4194 | // Get the default configuration string according to the default ID.
|
| 4195 | //
|
| 4196 | Status = mHiiConfigRouting->GetAltConfig (
|
| 4197 | mHiiConfigRouting,
|
| 4198 | Result,
|
| 4199 | &Storage->Guid,
|
| 4200 | Storage->Name,
|
| 4201 | NULL,
|
| 4202 | &DefaultId, // it can be NULL to get the current setting.
|
| 4203 | &ConfigResp
|
| 4204 | );
|
| 4205 |
|
| 4206 | FreePool (Result);
|
| 4207 | if (EFI_ERROR (Status)) {
|
| 4208 | continue;
|
| 4209 | }
|
| 4210 |
|
| 4211 | FormSetStorage->ConfigAltResp = ConfigResp;
|
| 4212 | }
|
| 4213 |
|
| 4214 | }
|
| 4215 |
|
| 4216 | /**
|
| 4217 | Clean AltCfg string for current formset.
|
| 4218 |
|
| 4219 | @param FormSet Form data structure.
|
| 4220 |
|
| 4221 | **/
|
| 4222 | VOID
|
| 4223 | CleanAltCfgForFormSet (
|
| 4224 | IN FORM_BROWSER_FORMSET *FormSet
|
| 4225 | )
|
| 4226 | {
|
| 4227 | LIST_ENTRY *Link;
|
| 4228 | FORMSET_STORAGE *FormSetStorage;
|
| 4229 |
|
| 4230 | Link = GetFirstNode (&FormSet->StorageListHead);
|
| 4231 | while (!IsNull (&FormSet->StorageListHead, Link)) {
|
| 4232 | FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);
|
| 4233 | Link = GetNextNode (&FormSet->StorageListHead, Link);
|
| 4234 |
|
| 4235 | if (FormSetStorage->ConfigAltResp != NULL) {
|
| 4236 | FreePool (FormSetStorage->ConfigAltResp);
|
| 4237 | FormSetStorage->ConfigAltResp = NULL;
|
| 4238 | }
|
| 4239 |
|
| 4240 | FormSetStorage->HasCallAltCfg = FALSE;
|
| 4241 | }
|
| 4242 | }
|
| 4243 |
|
| 4244 | /**
|
| 4245 | Reset Questions to their initial value or default value in a Form, Formset or System.
|
| 4246 |
|
| 4247 | GetDefaultValueScope parameter decides which questions will reset
|
| 4248 | to its default value.
|
| 4249 |
|
| 4250 | @param FormSet FormSet data structure.
|
| 4251 | @param Form Form data structure.
|
| 4252 | @param DefaultId The Class of the default.
|
| 4253 | @param SettingScope Setting Scope for Default action.
|
| 4254 | @param GetDefaultValueScope Get default value scope.
|
| 4255 | @param Storage Get default value only for this storage.
|
| 4256 | @param RetrieveValueFirst Whether call the retrieve call back to
|
| 4257 | get the initial value before get default
|
| 4258 | value.
|
| 4259 | @param SkipGetAltCfg Whether skip the get altcfg string process.
|
| 4260 |
|
| 4261 | @retval EFI_SUCCESS The function completed successfully.
|
| 4262 | @retval EFI_UNSUPPORTED Unsupport SettingScope.
|
| 4263 |
|
| 4264 | **/
|
| 4265 | EFI_STATUS
|
| 4266 | ExtractDefault (
|
| 4267 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 4268 | IN FORM_BROWSER_FORM *Form,
|
| 4269 | IN UINT16 DefaultId,
|
| 4270 | IN BROWSER_SETTING_SCOPE SettingScope,
|
| 4271 | IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope,
|
| 4272 | IN BROWSER_STORAGE *Storage OPTIONAL,
|
| 4273 | IN BOOLEAN RetrieveValueFirst,
|
| 4274 | IN BOOLEAN SkipGetAltCfg
|
| 4275 | )
|
| 4276 | {
|
| 4277 | EFI_STATUS Status;
|
| 4278 | LIST_ENTRY *FormLink;
|
| 4279 | LIST_ENTRY *Link;
|
| 4280 | FORM_BROWSER_STATEMENT *Question;
|
| 4281 | FORM_BROWSER_FORMSET *LocalFormSet;
|
| 4282 | FORM_BROWSER_FORMSET *OldFormSet;
|
| 4283 |
|
| 4284 | Status = EFI_SUCCESS;
|
| 4285 |
|
| 4286 | //
|
| 4287 | // Check the supported setting level.
|
| 4288 | //
|
| 4289 | if (SettingScope >= MaxLevel || GetDefaultValueScope >= GetDefaultForMax) {
|
| 4290 | return EFI_UNSUPPORTED;
|
| 4291 | }
|
| 4292 |
|
| 4293 | if (GetDefaultValueScope == GetDefaultForStorage && Storage == NULL) {
|
| 4294 | return EFI_UNSUPPORTED;
|
| 4295 | }
|
| 4296 |
|
| 4297 | if (SettingScope == FormLevel) {
|
| 4298 | //
|
| 4299 | // Prepare the AltCfg String for form.
|
| 4300 | //
|
| 4301 | if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {
|
| 4302 | ExtractAltCfgForForm (FormSet, Form, DefaultId, Storage);
|
| 4303 | }
|
| 4304 |
|
| 4305 | //
|
| 4306 | // Extract Form default
|
| 4307 | //
|
| 4308 | Link = GetFirstNode (&Form->StatementListHead);
|
| 4309 | while (!IsNull (&Form->StatementListHead, Link)) {
|
| 4310 | Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
|
| 4311 | Link = GetNextNode (&Form->StatementListHead, Link);
|
| 4312 |
|
| 4313 | //
|
| 4314 | // If get default value only for this storage, check the storage first.
|
| 4315 | //
|
| 4316 | if ((GetDefaultValueScope == GetDefaultForStorage) && (Question->Storage != Storage)) {
|
| 4317 | continue;
|
| 4318 | }
|
| 4319 |
|
| 4320 | //
|
| 4321 | // If get default value only for no storage question, just skip the question which has storage.
|
| 4322 | //
|
| 4323 | if ((GetDefaultValueScope == GetDefaultForNoStorage) && (Question->Storage != NULL)) {
|
| 4324 | continue;
|
| 4325 | }
|
| 4326 |
|
| 4327 | //
|
| 4328 | // If Question is disabled, don't reset it to default
|
| 4329 | //
|
| 4330 | if (Question->Expression != NULL) {
|
| 4331 | if (EvaluateExpressionList(Question->Expression, TRUE, FormSet, Form) == ExpressDisable) {
|
| 4332 | continue;
|
| 4333 | }
|
| 4334 | }
|
| 4335 |
|
| 4336 | if (RetrieveValueFirst) {
|
| 4337 | //
|
| 4338 | // Call the Retrieve call back to get the initial question value.
|
| 4339 | //
|
| 4340 | Status = ProcessRetrieveForQuestion(FormSet->ConfigAccess, Question, FormSet);
|
| 4341 | }
|
| 4342 |
|
| 4343 | //
|
| 4344 | // If not request to get the initial value or get initial value fail, then get default value.
|
| 4345 | //
|
| 4346 | if (!RetrieveValueFirst || EFI_ERROR (Status)) {
|
| 4347 | Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);
|
| 4348 | if (EFI_ERROR (Status)) {
|
| 4349 | continue;
|
| 4350 | }
|
| 4351 | }
|
| 4352 |
|
| 4353 | //
|
| 4354 | // Synchronize Buffer storage's Edit buffer
|
| 4355 | //
|
| 4356 | if ((Question->Storage != NULL) &&
|
| 4357 | (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {
|
| 4358 | SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);
|
| 4359 | }
|
| 4360 | }
|
| 4361 |
|
| 4362 | //
|
| 4363 | // Clean the AltCfg String.
|
| 4364 | //
|
| 4365 | if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {
|
| 4366 | CleanAltCfgForForm(Form);
|
| 4367 | }
|
| 4368 | } else if (SettingScope == FormSetLevel) {
|
| 4369 | //
|
| 4370 | // Prepare the AltCfg String for formset.
|
| 4371 | //
|
| 4372 | if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {
|
| 4373 | ExtractAltCfgForFormSet (FormSet, DefaultId, Storage);
|
| 4374 | }
|
| 4375 |
|
| 4376 | FormLink = GetFirstNode (&FormSet->FormListHead);
|
| 4377 | while (!IsNull (&FormSet->FormListHead, FormLink)) {
|
| 4378 | Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
|
| 4379 | ExtractDefault (FormSet, Form, DefaultId, FormLevel, GetDefaultValueScope, Storage, RetrieveValueFirst, SkipGetAltCfg);
|
| 4380 | FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
|
| 4381 | }
|
| 4382 |
|
| 4383 | //
|
| 4384 | // Clean the AltCfg String.
|
| 4385 | //
|
| 4386 | if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {
|
| 4387 | CleanAltCfgForFormSet (FormSet);
|
| 4388 | }
|
| 4389 | } else if (SettingScope == SystemLevel) {
|
| 4390 | //
|
| 4391 | // Preload all Hii formset.
|
| 4392 | //
|
| 4393 | LoadAllHiiFormset();
|
| 4394 |
|
| 4395 | OldFormSet = mSystemLevelFormSet;
|
| 4396 |
|
| 4397 | //
|
| 4398 | // Set Default Value for each FormSet in the maintain list.
|
| 4399 | //
|
| 4400 | Link = GetFirstNode (&gBrowserFormSetList);
|
| 4401 | while (!IsNull (&gBrowserFormSetList, Link)) {
|
| 4402 | LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);
|
| 4403 | Link = GetNextNode (&gBrowserFormSetList, Link);
|
| 4404 | if (!ValidateFormSet(LocalFormSet)) {
|
| 4405 | continue;
|
| 4406 | }
|
| 4407 |
|
| 4408 | mSystemLevelFormSet = LocalFormSet;
|
| 4409 |
|
| 4410 | ExtractDefault (LocalFormSet, NULL, DefaultId, FormSetLevel, GetDefaultValueScope, Storage, RetrieveValueFirst, SkipGetAltCfg);
|
| 4411 | }
|
| 4412 |
|
| 4413 | mSystemLevelFormSet = OldFormSet;
|
| 4414 | }
|
| 4415 |
|
| 4416 | return EFI_SUCCESS;
|
| 4417 | }
|
| 4418 |
|
| 4419 |
|
| 4420 | /**
|
| 4421 | Validate whether this question's value has changed.
|
| 4422 |
|
| 4423 | @param FormSet FormSet data structure.
|
| 4424 | @param Form Form data structure.
|
| 4425 | @param Question Question to be initialized.
|
| 4426 | @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
|
| 4427 |
|
| 4428 | @retval TRUE Question's value has changed.
|
| 4429 | @retval FALSE Question's value has not changed
|
| 4430 |
|
| 4431 | **/
|
| 4432 | BOOLEAN
|
| 4433 | IsQuestionValueChanged (
|
| 4434 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 4435 | IN FORM_BROWSER_FORM *Form,
|
| 4436 | IN OUT FORM_BROWSER_STATEMENT *Question,
|
| 4437 | IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
|
| 4438 | )
|
| 4439 | {
|
| 4440 | EFI_HII_VALUE BackUpValue;
|
| 4441 | CHAR8 *BackUpBuffer;
|
| 4442 | EFI_HII_VALUE BackUpValue2;
|
| 4443 | CHAR8 *BackUpBuffer2;
|
| 4444 | EFI_STATUS Status;
|
| 4445 | BOOLEAN ValueChanged;
|
| 4446 | UINTN BufferWidth;
|
| 4447 |
|
| 4448 | //
|
| 4449 | // For quetion without storage, always mark it as data not changed.
|
| 4450 | //
|
| 4451 | if (Question->Storage == NULL && Question->Operand != EFI_IFR_TIME_OP && Question->Operand != EFI_IFR_DATE_OP) {
|
| 4452 | return FALSE;
|
| 4453 | }
|
| 4454 |
|
| 4455 | BackUpBuffer = NULL;
|
| 4456 | BackUpBuffer2 = NULL;
|
| 4457 | ValueChanged = FALSE;
|
| 4458 |
|
| 4459 | switch (Question->Operand) {
|
| 4460 | case EFI_IFR_ORDERED_LIST_OP:
|
| 4461 | BufferWidth = Question->StorageWidth;
|
| 4462 | BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);
|
| 4463 | ASSERT (BackUpBuffer != NULL);
|
| 4464 | break;
|
| 4465 |
|
| 4466 | case EFI_IFR_STRING_OP:
|
| 4467 | case EFI_IFR_PASSWORD_OP:
|
| 4468 | BufferWidth = (UINTN) Question->Maximum * sizeof (CHAR16);
|
| 4469 | BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);
|
| 4470 | ASSERT (BackUpBuffer != NULL);
|
| 4471 | break;
|
| 4472 |
|
| 4473 | default:
|
| 4474 | BufferWidth = 0;
|
| 4475 | break;
|
| 4476 | }
|
| 4477 | CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));
|
| 4478 |
|
| 4479 | if (GetValueFrom == GetSetValueWithBothBuffer) {
|
| 4480 | Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);
|
| 4481 | ASSERT_EFI_ERROR(Status);
|
| 4482 |
|
| 4483 | switch (Question->Operand) {
|
| 4484 | case EFI_IFR_ORDERED_LIST_OP:
|
| 4485 | BufferWidth = Question->StorageWidth;
|
| 4486 | BackUpBuffer2 = AllocateCopyPool (BufferWidth, Question->BufferValue);
|
| 4487 | ASSERT (BackUpBuffer2 != NULL);
|
| 4488 | break;
|
| 4489 |
|
| 4490 | case EFI_IFR_STRING_OP:
|
| 4491 | case EFI_IFR_PASSWORD_OP:
|
| 4492 | BufferWidth = (UINTN) Question->Maximum * sizeof (CHAR16);
|
| 4493 | BackUpBuffer2 = AllocateCopyPool (BufferWidth, Question->BufferValue);
|
| 4494 | ASSERT (BackUpBuffer2 != NULL);
|
| 4495 | break;
|
| 4496 |
|
| 4497 | default:
|
| 4498 | BufferWidth = 0;
|
| 4499 | break;
|
| 4500 | }
|
| 4501 | CopyMem (&BackUpValue2, &Question->HiiValue, sizeof (EFI_HII_VALUE));
|
| 4502 |
|
| 4503 | Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);
|
| 4504 | ASSERT_EFI_ERROR(Status);
|
| 4505 |
|
| 4506 | if (CompareMem (&BackUpValue2, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 ||
|
| 4507 | CompareMem (BackUpBuffer2, Question->BufferValue, BufferWidth) != 0) {
|
| 4508 | ValueChanged = TRUE;
|
| 4509 | }
|
| 4510 | } else {
|
| 4511 | Status = GetQuestionValue (FormSet, Form, Question, GetValueFrom);
|
| 4512 | ASSERT_EFI_ERROR(Status);
|
| 4513 |
|
| 4514 | if (CompareMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 ||
|
| 4515 | CompareMem (BackUpBuffer, Question->BufferValue, BufferWidth) != 0) {
|
| 4516 | ValueChanged = TRUE;
|
| 4517 | }
|
| 4518 | }
|
| 4519 |
|
| 4520 | CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE));
|
| 4521 | if (BackUpBuffer != NULL) {
|
| 4522 | CopyMem (Question->BufferValue, BackUpBuffer, BufferWidth);
|
| 4523 | FreePool (BackUpBuffer);
|
| 4524 | }
|
| 4525 |
|
| 4526 | if (BackUpBuffer2 != NULL) {
|
| 4527 | FreePool (BackUpBuffer2);
|
| 4528 | }
|
| 4529 |
|
| 4530 | Question->ValueChanged = ValueChanged;
|
| 4531 |
|
| 4532 | return ValueChanged;
|
| 4533 | }
|
| 4534 |
|
| 4535 | /**
|
| 4536 | Initialize Question's Edit copy from Storage.
|
| 4537 |
|
| 4538 | @param Selection Selection contains the information about
|
| 4539 | the Selection, form and formset to be displayed.
|
| 4540 | Selection action may be updated in retrieve callback.
|
| 4541 | If Selection is NULL, only initialize Question value.
|
| 4542 | @param FormSet FormSet data structure.
|
| 4543 | @param Form Form data structure.
|
| 4544 |
|
| 4545 | @retval EFI_SUCCESS The function completed successfully.
|
| 4546 |
|
| 4547 | **/
|
| 4548 | EFI_STATUS
|
| 4549 | LoadFormConfig (
|
| 4550 | IN OUT UI_MENU_SELECTION *Selection,
|
| 4551 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 4552 | IN FORM_BROWSER_FORM *Form
|
| 4553 | )
|
| 4554 | {
|
| 4555 | EFI_STATUS Status;
|
| 4556 | LIST_ENTRY *Link;
|
| 4557 | FORM_BROWSER_STATEMENT *Question;
|
| 4558 |
|
| 4559 | Link = GetFirstNode (&Form->StatementListHead);
|
| 4560 | while (!IsNull (&Form->StatementListHead, Link)) {
|
| 4561 | Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
|
| 4562 |
|
| 4563 | //
|
| 4564 | // Initialize local copy of Value for each Question
|
| 4565 | //
|
| 4566 | if (Question->Operand == EFI_IFR_PASSWORD_OP && (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK)== 0) {
|
| 4567 | Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);
|
| 4568 | } else {
|
| 4569 | Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);
|
| 4570 | }
|
| 4571 | if (EFI_ERROR (Status)) {
|
| 4572 | return Status;
|
| 4573 | }
|
| 4574 |
|
| 4575 | if ((Question->Operand == EFI_IFR_STRING_OP) || (Question->Operand == EFI_IFR_PASSWORD_OP)) {
|
| 4576 | HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);
|
| 4577 | }
|
| 4578 |
|
| 4579 | Link = GetNextNode (&Form->StatementListHead, Link);
|
| 4580 | }
|
| 4581 |
|
| 4582 | return EFI_SUCCESS;
|
| 4583 | }
|
| 4584 |
|
| 4585 | /**
|
| 4586 | Initialize Question's Edit copy from Storage for the whole Formset.
|
| 4587 |
|
| 4588 | @param Selection Selection contains the information about
|
| 4589 | the Selection, form and formset to be displayed.
|
| 4590 | Selection action may be updated in retrieve callback.
|
| 4591 | If Selection is NULL, only initialize Question value.
|
| 4592 | @param FormSet FormSet data structure.
|
| 4593 |
|
| 4594 | @retval EFI_SUCCESS The function completed successfully.
|
| 4595 |
|
| 4596 | **/
|
| 4597 | EFI_STATUS
|
| 4598 | LoadFormSetConfig (
|
| 4599 | IN OUT UI_MENU_SELECTION *Selection,
|
| 4600 | IN FORM_BROWSER_FORMSET *FormSet
|
| 4601 | )
|
| 4602 | {
|
| 4603 | EFI_STATUS Status;
|
| 4604 | LIST_ENTRY *Link;
|
| 4605 | FORM_BROWSER_FORM *Form;
|
| 4606 |
|
| 4607 | Link = GetFirstNode (&FormSet->FormListHead);
|
| 4608 | while (!IsNull (&FormSet->FormListHead, Link)) {
|
| 4609 | Form = FORM_BROWSER_FORM_FROM_LINK (Link);
|
| 4610 |
|
| 4611 | //
|
| 4612 | // Initialize local copy of Value for each Form
|
| 4613 | //
|
| 4614 | Status = LoadFormConfig (Selection, FormSet, Form);
|
| 4615 | if (EFI_ERROR (Status)) {
|
| 4616 | return Status;
|
| 4617 | }
|
| 4618 |
|
| 4619 | Link = GetNextNode (&FormSet->FormListHead, Link);
|
| 4620 | }
|
| 4621 |
|
| 4622 | //
|
| 4623 | // Finished question initialization.
|
| 4624 | //
|
| 4625 | FormSet->QuestionInited = TRUE;
|
| 4626 |
|
| 4627 | return EFI_SUCCESS;
|
| 4628 | }
|
| 4629 |
|
| 4630 | /**
|
| 4631 | Remove the Request element from the Config Request.
|
| 4632 |
|
| 4633 | @param Storage Pointer to the browser storage.
|
| 4634 | @param RequestElement The pointer to the Request element.
|
| 4635 |
|
| 4636 | **/
|
| 4637 | VOID
|
| 4638 | RemoveElement (
|
| 4639 | IN OUT BROWSER_STORAGE *Storage,
|
| 4640 | IN CHAR16 *RequestElement
|
| 4641 | )
|
| 4642 | {
|
| 4643 | CHAR16 *NewStr;
|
| 4644 | CHAR16 *DestStr;
|
| 4645 |
|
| 4646 | ASSERT (Storage->ConfigRequest != NULL && RequestElement != NULL);
|
| 4647 |
|
| 4648 | NewStr = StrStr (Storage->ConfigRequest, RequestElement);
|
| 4649 |
|
| 4650 | if (NewStr == NULL) {
|
| 4651 | return;
|
| 4652 | }
|
| 4653 |
|
| 4654 | //
|
| 4655 | // Remove this element from this ConfigRequest.
|
| 4656 | //
|
| 4657 | DestStr = NewStr;
|
| 4658 | NewStr += StrLen (RequestElement);
|
| 4659 | CopyMem (DestStr, NewStr, StrSize (NewStr));
|
| 4660 |
|
| 4661 | Storage->SpareStrLen += StrLen (RequestElement);
|
| 4662 | }
|
| 4663 |
|
| 4664 | /**
|
| 4665 | Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
|
| 4666 |
|
| 4667 | @param Storage Pointer to the formset storage.
|
| 4668 | @param ConfigRequest The pointer to the Request element.
|
| 4669 |
|
| 4670 | **/
|
| 4671 | VOID
|
| 4672 | RemoveConfigRequest (
|
| 4673 | FORMSET_STORAGE *Storage,
|
| 4674 | CHAR16 *ConfigRequest
|
| 4675 | )
|
| 4676 | {
|
| 4677 | CHAR16 *RequestElement;
|
| 4678 | CHAR16 *NextRequestElement;
|
| 4679 | CHAR16 *SearchKey;
|
| 4680 |
|
| 4681 | //
|
| 4682 | // No request element in it, just return.
|
| 4683 | //
|
| 4684 | if (ConfigRequest == NULL) {
|
| 4685 | return;
|
| 4686 | }
|
| 4687 |
|
| 4688 | if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
|
| 4689 | //
|
| 4690 | // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
|
| 4691 | //
|
| 4692 | SearchKey = L"&";
|
| 4693 | } else {
|
| 4694 | //
|
| 4695 | // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
|
| 4696 | //
|
| 4697 | SearchKey = L"&OFFSET";
|
| 4698 | }
|
| 4699 |
|
| 4700 | //
|
| 4701 | // Find SearchKey storage
|
| 4702 | //
|
| 4703 | if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
|
| 4704 | RequestElement = StrStr (ConfigRequest, L"PATH");
|
| 4705 | ASSERT (RequestElement != NULL);
|
| 4706 | RequestElement = StrStr (RequestElement, SearchKey);
|
| 4707 | } else {
|
| 4708 | RequestElement = StrStr (ConfigRequest, SearchKey);
|
| 4709 | }
|
| 4710 |
|
| 4711 | while (RequestElement != NULL) {
|
| 4712 | //
|
| 4713 | // +1 to avoid find header itself.
|
| 4714 | //
|
| 4715 | NextRequestElement = StrStr (RequestElement + 1, SearchKey);
|
| 4716 |
|
| 4717 | //
|
| 4718 | // The last Request element in configRequest string.
|
| 4719 | //
|
| 4720 | if (NextRequestElement != NULL) {
|
| 4721 | //
|
| 4722 | // Replace "&" with '\0'.
|
| 4723 | //
|
| 4724 | *NextRequestElement = L'\0';
|
| 4725 | }
|
| 4726 |
|
| 4727 | RemoveElement (Storage->BrowserStorage, RequestElement);
|
| 4728 |
|
| 4729 | if (NextRequestElement != NULL) {
|
| 4730 | //
|
| 4731 | // Restore '&' with '\0' for later used.
|
| 4732 | //
|
| 4733 | *NextRequestElement = L'&';
|
| 4734 | }
|
| 4735 |
|
| 4736 | RequestElement = NextRequestElement;
|
| 4737 | }
|
| 4738 |
|
| 4739 | //
|
| 4740 | // If no request element remain, just remove the ConfigRequest string.
|
| 4741 | //
|
| 4742 | if (StrCmp (Storage->BrowserStorage->ConfigRequest, Storage->ConfigHdr) == 0) {
|
| 4743 | FreePool (Storage->BrowserStorage->ConfigRequest);
|
| 4744 | Storage->BrowserStorage->ConfigRequest = NULL;
|
| 4745 | Storage->BrowserStorage->SpareStrLen = 0;
|
| 4746 | }
|
| 4747 | }
|
| 4748 |
|
| 4749 | /**
|
| 4750 | Base on the current formset info, clean the ConfigRequest string in browser storage.
|
| 4751 |
|
| 4752 | @param FormSet Pointer of the FormSet
|
| 4753 |
|
| 4754 | **/
|
| 4755 | VOID
|
| 4756 | CleanBrowserStorage (
|
| 4757 | IN OUT FORM_BROWSER_FORMSET *FormSet
|
| 4758 | )
|
| 4759 | {
|
| 4760 | LIST_ENTRY *Link;
|
| 4761 | FORMSET_STORAGE *Storage;
|
| 4762 |
|
| 4763 | Link = GetFirstNode (&FormSet->StorageListHead);
|
| 4764 | while (!IsNull (&FormSet->StorageListHead, Link)) {
|
| 4765 | Storage = FORMSET_STORAGE_FROM_LINK (Link);
|
| 4766 | Link = GetNextNode (&FormSet->StorageListHead, Link);
|
| 4767 |
|
| 4768 | if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
|
| 4769 | if (Storage->ConfigRequest == NULL || Storage->BrowserStorage->ConfigRequest == NULL) {
|
| 4770 | continue;
|
| 4771 | }
|
| 4772 |
|
| 4773 | RemoveConfigRequest (Storage, Storage->ConfigRequest);
|
| 4774 | } else if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_BUFFER ||
|
| 4775 | Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
|
| 4776 | if (Storage->BrowserStorage->ConfigRequest != NULL) {
|
| 4777 | FreePool (Storage->BrowserStorage->ConfigRequest);
|
| 4778 | Storage->BrowserStorage->ConfigRequest = NULL;
|
| 4779 | }
|
| 4780 | Storage->BrowserStorage->Initialized = FALSE;
|
| 4781 | }
|
| 4782 | }
|
| 4783 | }
|
| 4784 |
|
| 4785 | /**
|
| 4786 | Check whether current element in the ConfigReqeust string.
|
| 4787 |
|
| 4788 | @param BrowserStorage Storage which includes ConfigReqeust.
|
| 4789 | @param RequestElement New element need to check.
|
| 4790 |
|
| 4791 | @retval TRUE The Element is in the ConfigReqeust string.
|
| 4792 | @retval FALSE The Element not in the configReqeust String.
|
| 4793 |
|
| 4794 | **/
|
| 4795 | BOOLEAN
|
| 4796 | ElementValidation (
|
| 4797 | BROWSER_STORAGE *BrowserStorage,
|
| 4798 | CHAR16 *RequestElement
|
| 4799 | )
|
| 4800 | {
|
| 4801 | return StrStr (BrowserStorage->ConfigRequest, RequestElement) != NULL ? TRUE : FALSE;
|
| 4802 | }
|
| 4803 |
|
| 4804 | /**
|
| 4805 | Append the Request element to the Config Request.
|
| 4806 |
|
| 4807 | @param ConfigRequest Current ConfigRequest info.
|
| 4808 | @param SpareStrLen Current remain free buffer for config reqeust.
|
| 4809 | @param RequestElement New Request element.
|
| 4810 |
|
| 4811 | **/
|
| 4812 | VOID
|
| 4813 | AppendConfigRequest (
|
| 4814 | IN OUT CHAR16 **ConfigRequest,
|
| 4815 | IN OUT UINTN *SpareStrLen,
|
| 4816 | IN CHAR16 *RequestElement
|
| 4817 | )
|
| 4818 | {
|
| 4819 | CHAR16 *NewStr;
|
| 4820 | UINTN StringSize;
|
| 4821 | UINTN StrLength;
|
| 4822 |
|
| 4823 | StrLength = StrLen (RequestElement);
|
| 4824 |
|
| 4825 | //
|
| 4826 | // Append <RequestElement> to <ConfigRequest>
|
| 4827 | //
|
| 4828 | if (StrLength > *SpareStrLen) {
|
| 4829 | //
|
| 4830 | // Old String buffer is not sufficient for RequestElement, allocate a new one
|
| 4831 | //
|
| 4832 | StringSize = (*ConfigRequest != NULL) ? StrSize (*ConfigRequest) : sizeof (CHAR16);
|
| 4833 | NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16));
|
| 4834 | ASSERT (NewStr != NULL);
|
| 4835 |
|
| 4836 | if (*ConfigRequest != NULL) {
|
| 4837 | CopyMem (NewStr, *ConfigRequest, StringSize);
|
| 4838 | FreePool (*ConfigRequest);
|
| 4839 | }
|
| 4840 | *ConfigRequest = NewStr;
|
| 4841 | *SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;
|
| 4842 | }
|
| 4843 |
|
| 4844 | StrCat (*ConfigRequest, RequestElement);
|
| 4845 | *SpareStrLen -= StrLength;
|
| 4846 | }
|
| 4847 |
|
| 4848 | /**
|
| 4849 | Adjust the config request info, remove the request elements which already in AllConfigRequest string.
|
| 4850 |
|
| 4851 | @param Storage Form set Storage.
|
| 4852 | @param Request The input request string.
|
| 4853 | @param RespString Whether the input is ConfigRequest or ConfigResp format.
|
| 4854 |
|
| 4855 | @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
|
| 4856 | @retval FALSE All elements covered by current used elements.
|
| 4857 |
|
| 4858 | **/
|
| 4859 | BOOLEAN
|
| 4860 | ConfigRequestAdjust (
|
| 4861 | IN BROWSER_STORAGE *Storage,
|
| 4862 | IN CHAR16 *Request,
|
| 4863 | IN BOOLEAN RespString
|
| 4864 | )
|
| 4865 | {
|
| 4866 | CHAR16 *RequestElement;
|
| 4867 | CHAR16 *NextRequestElement;
|
| 4868 | CHAR16 *NextElementBakup;
|
| 4869 | CHAR16 *SearchKey;
|
| 4870 | CHAR16 *ValueKey;
|
| 4871 | BOOLEAN RetVal;
|
| 4872 | CHAR16 *ConfigRequest;
|
| 4873 |
|
| 4874 | RetVal = FALSE;
|
| 4875 | NextElementBakup = NULL;
|
| 4876 | ValueKey = NULL;
|
| 4877 |
|
| 4878 | if (Request != NULL) {
|
| 4879 | ConfigRequest = Request;
|
| 4880 | } else {
|
| 4881 | ConfigRequest = Storage->ConfigRequest;
|
| 4882 | }
|
| 4883 |
|
| 4884 | if (Storage->ConfigRequest == NULL) {
|
| 4885 | Storage->ConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);
|
| 4886 | return TRUE;
|
| 4887 | }
|
| 4888 |
|
| 4889 | if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
|
| 4890 | //
|
| 4891 | // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
|
| 4892 | //
|
| 4893 | SearchKey = L"&";
|
| 4894 | } else {
|
| 4895 | //
|
| 4896 | // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
|
| 4897 | //
|
| 4898 | SearchKey = L"&OFFSET";
|
| 4899 | ValueKey = L"&VALUE";
|
| 4900 | }
|
| 4901 |
|
| 4902 | //
|
| 4903 | // Find SearchKey storage
|
| 4904 | //
|
| 4905 | if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
|
| 4906 | RequestElement = StrStr (ConfigRequest, L"PATH");
|
| 4907 | ASSERT (RequestElement != NULL);
|
| 4908 | RequestElement = StrStr (RequestElement, SearchKey);
|
| 4909 | } else {
|
| 4910 | RequestElement = StrStr (ConfigRequest, SearchKey);
|
| 4911 | }
|
| 4912 |
|
| 4913 | while (RequestElement != NULL) {
|
| 4914 |
|
| 4915 | //
|
| 4916 | // +1 to avoid find header itself.
|
| 4917 | //
|
| 4918 | NextRequestElement = StrStr (RequestElement + 1, SearchKey);
|
| 4919 |
|
| 4920 | //
|
| 4921 | // The last Request element in configRequest string.
|
| 4922 | //
|
| 4923 | if (NextRequestElement != NULL) {
|
| 4924 | if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
|
| 4925 | NextElementBakup = NextRequestElement;
|
| 4926 | NextRequestElement = StrStr (RequestElement, ValueKey);
|
| 4927 | ASSERT (NextRequestElement != NULL);
|
| 4928 | }
|
| 4929 | //
|
| 4930 | // Replace "&" with '\0'.
|
| 4931 | //
|
| 4932 | *NextRequestElement = L'\0';
|
| 4933 | } else {
|
| 4934 | if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
|
| 4935 | NextElementBakup = NextRequestElement;
|
| 4936 | NextRequestElement = StrStr (RequestElement, ValueKey);
|
| 4937 | ASSERT (NextRequestElement != NULL);
|
| 4938 | //
|
| 4939 | // Replace "&" with '\0'.
|
| 4940 | //
|
| 4941 | *NextRequestElement = L'\0';
|
| 4942 | }
|
| 4943 | }
|
| 4944 |
|
| 4945 | if (!ElementValidation (Storage, RequestElement)) {
|
| 4946 | //
|
| 4947 | // Add this element to the Storage->BrowserStorage->AllRequestElement.
|
| 4948 | //
|
| 4949 | AppendConfigRequest(&Storage->ConfigRequest, &Storage->SpareStrLen, RequestElement);
|
| 4950 | RetVal = TRUE;
|
| 4951 | }
|
| 4952 |
|
| 4953 | if (NextRequestElement != NULL) {
|
| 4954 | //
|
| 4955 | // Restore '&' with '\0' for later used.
|
| 4956 | //
|
| 4957 | *NextRequestElement = L'&';
|
| 4958 | }
|
| 4959 |
|
| 4960 | if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
|
| 4961 | RequestElement = NextElementBakup;
|
| 4962 | } else {
|
| 4963 | RequestElement = NextRequestElement;
|
| 4964 | }
|
| 4965 | }
|
| 4966 |
|
| 4967 | return RetVal;
|
| 4968 | }
|
| 4969 |
|
| 4970 | /**
|
| 4971 | Fill storage's edit copy with settings requested from Configuration Driver.
|
| 4972 |
|
| 4973 | @param FormSet FormSet data structure.
|
| 4974 | @param Storage Buffer Storage.
|
| 4975 |
|
| 4976 | **/
|
| 4977 | VOID
|
| 4978 | LoadStorage (
|
| 4979 | IN FORM_BROWSER_FORMSET *FormSet,
|
| 4980 | IN FORMSET_STORAGE *Storage
|
| 4981 | )
|
| 4982 | {
|
| 4983 | EFI_STATUS Status;
|
| 4984 | EFI_STRING Progress;
|
| 4985 | EFI_STRING Result;
|
| 4986 | CHAR16 *StrPtr;
|
| 4987 | EFI_STRING ConfigRequest;
|
| 4988 | UINTN StrLen;
|
| 4989 |
|
| 4990 | ConfigRequest = NULL;
|
| 4991 |
|
| 4992 | switch (Storage->BrowserStorage->Type) {
|
| 4993 | case EFI_HII_VARSTORE_EFI_VARIABLE:
|
| 4994 | return;
|
| 4995 |
|
| 4996 | case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
|
| 4997 | if (Storage->BrowserStorage->ConfigRequest != NULL) {
|
| 4998 | ConfigRequestAdjust(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);
|
| 4999 | return;
|
| 5000 | }
|
| 5001 | break;
|
| 5002 |
|
| 5003 | case EFI_HII_VARSTORE_BUFFER:
|
| 5004 | case EFI_HII_VARSTORE_NAME_VALUE:
|
| 5005 | //
|
| 5006 | // Skip if there is no RequestElement.
|
| 5007 | //
|
| 5008 | if (Storage->ElementCount == 0) {
|
| 5009 | return;
|
| 5010 | }
|
| 5011 |
|
| 5012 | //
|
| 5013 | // Just update the ConfigRequest, if storage already initialized.
|
| 5014 | //
|
| 5015 | if (Storage->BrowserStorage->Initialized) {
|
| 5016 | ConfigRequestAdjust(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);
|
| 5017 | return;
|
| 5018 | }
|
| 5019 |
|
| 5020 | Storage->BrowserStorage->Initialized = TRUE;
|
| 5021 | break;
|
| 5022 |
|
| 5023 | default:
|
| 5024 | return;
|
| 5025 | }
|
| 5026 |
|
| 5027 | if (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) {
|
| 5028 | //
|
| 5029 | // Create the config request string to get all fields for this storage.
|
| 5030 | // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
|
| 5031 | // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
|
| 5032 | //
|
| 5033 | StrLen = StrSize (Storage->ConfigHdr) + 20 * sizeof (CHAR16);
|
| 5034 | ConfigRequest = AllocateZeroPool (StrLen);
|
| 5035 | ASSERT (ConfigRequest != NULL);
|
| 5036 | UnicodeSPrint (
|
| 5037 | ConfigRequest,
|
| 5038 | StrLen,
|
| 5039 | L"%s&OFFSET=0&WIDTH=%04x",
|
| 5040 | Storage->ConfigHdr,
|
| 5041 | Storage->BrowserStorage->Size);
|
| 5042 | } else {
|
| 5043 | ConfigRequest = Storage->ConfigRequest;
|
| 5044 | }
|
| 5045 |
|
| 5046 | //
|
| 5047 | // Request current settings from Configuration Driver
|
| 5048 | //
|
| 5049 | Status = mHiiConfigRouting->ExtractConfig (
|
| 5050 | mHiiConfigRouting,
|
| 5051 | ConfigRequest,
|
| 5052 | &Progress,
|
| 5053 | &Result
|
| 5054 | );
|
| 5055 |
|
| 5056 | //
|
| 5057 | // If get value fail, extract default from IFR binary
|
| 5058 | //
|
| 5059 | if (EFI_ERROR (Status)) {
|
| 5060 | ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage->BrowserStorage, TRUE, TRUE);
|
| 5061 | } else {
|
| 5062 | //
|
| 5063 | // Convert Result from <ConfigAltResp> to <ConfigResp>
|
| 5064 | //
|
| 5065 | StrPtr = StrStr (Result, L"&GUID=");
|
| 5066 | if (StrPtr != NULL) {
|
| 5067 | *StrPtr = L'\0';
|
| 5068 | }
|
| 5069 |
|
| 5070 | Status = ConfigRespToStorage (Storage->BrowserStorage, Result);
|
| 5071 | FreePool (Result);
|
| 5072 | }
|
| 5073 |
|
| 5074 | Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);
|
| 5075 |
|
| 5076 | //
|
| 5077 | // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
|
| 5078 | //
|
| 5079 | SynchronizeStorage(Storage->BrowserStorage, NULL, TRUE);
|
| 5080 |
|
| 5081 | if (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) {
|
| 5082 | if (ConfigRequest != NULL) {
|
| 5083 | FreePool (ConfigRequest);
|
| 5084 | }
|
| 5085 | }
|
| 5086 | }
|
| 5087 |
|
| 5088 | /**
|
| 5089 | Get Value changed status from old question.
|
| 5090 |
|
| 5091 | @param NewFormSet FormSet data structure.
|
| 5092 | @param OldQuestion Old question which has value changed.
|
| 5093 |
|
| 5094 | **/
|
| 5095 | VOID
|
| 5096 | SyncStatusForQuestion (
|
| 5097 | IN OUT FORM_BROWSER_FORMSET *NewFormSet,
|
| 5098 | IN FORM_BROWSER_STATEMENT *OldQuestion
|
| 5099 | )
|
| 5100 | {
|
| 5101 | LIST_ENTRY *Link;
|
| 5102 | LIST_ENTRY *QuestionLink;
|
| 5103 | FORM_BROWSER_FORM *Form;
|
| 5104 | FORM_BROWSER_STATEMENT *Question;
|
| 5105 |
|
| 5106 | //
|
| 5107 | // For each form in one formset.
|
| 5108 | //
|
| 5109 | Link = GetFirstNode (&NewFormSet->FormListHead);
|
| 5110 | while (!IsNull (&NewFormSet->FormListHead, Link)) {
|
| 5111 | Form = FORM_BROWSER_FORM_FROM_LINK (Link);
|
| 5112 | Link = GetNextNode (&NewFormSet->FormListHead, Link);
|
| 5113 |
|
| 5114 | //
|
| 5115 | // for each question in one form.
|
| 5116 | //
|
| 5117 | QuestionLink = GetFirstNode (&Form->StatementListHead);
|
| 5118 | while (!IsNull (&Form->StatementListHead, QuestionLink)) {
|
| 5119 | Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);
|
| 5120 | QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
|
| 5121 |
|
| 5122 | if (Question->QuestionId == OldQuestion->QuestionId) {
|
| 5123 | Question->ValueChanged = TRUE;
|
| 5124 | return;
|
| 5125 | }
|
| 5126 | }
|
| 5127 | }
|
| 5128 | }
|
| 5129 |
|
| 5130 | /**
|
| 5131 | Get Value changed status from old formset.
|
| 5132 |
|
| 5133 | @param NewFormSet FormSet data structure.
|
| 5134 | @param OldFormSet FormSet data structure.
|
| 5135 |
|
| 5136 | **/
|
| 5137 | VOID
|
| 5138 | SyncStatusForFormSet (
|
| 5139 | IN OUT FORM_BROWSER_FORMSET *NewFormSet,
|
| 5140 | IN FORM_BROWSER_FORMSET *OldFormSet
|
| 5141 | )
|
| 5142 | {
|
| 5143 | LIST_ENTRY *Link;
|
| 5144 | LIST_ENTRY *QuestionLink;
|
| 5145 | FORM_BROWSER_FORM *Form;
|
| 5146 | FORM_BROWSER_STATEMENT *Question;
|
| 5147 |
|
| 5148 | //
|
| 5149 | // For each form in one formset.
|
| 5150 | //
|
| 5151 | Link = GetFirstNode (&OldFormSet->FormListHead);
|
| 5152 | while (!IsNull (&OldFormSet->FormListHead, Link)) {
|
| 5153 | Form = FORM_BROWSER_FORM_FROM_LINK (Link);
|
| 5154 | Link = GetNextNode (&OldFormSet->FormListHead, Link);
|
| 5155 |
|
| 5156 | //
|
| 5157 | // for each question in one form.
|
| 5158 | //
|
| 5159 | QuestionLink = GetFirstNode (&Form->StatementListHead);
|
| 5160 | while (!IsNull (&Form->StatementListHead, QuestionLink)) {
|
| 5161 | Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);
|
| 5162 | QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
|
| 5163 |
|
| 5164 | if (!Question->ValueChanged) {
|
| 5165 | continue;
|
| 5166 | }
|
| 5167 |
|
| 5168 | //
|
| 5169 | // Find the same question in new formset and update the value changed flag.
|
| 5170 | //
|
| 5171 | SyncStatusForQuestion (NewFormSet, Question);
|
| 5172 | }
|
| 5173 | }
|
| 5174 | }
|
| 5175 |
|
| 5176 | /**
|
| 5177 | Get current setting of Questions.
|
| 5178 |
|
| 5179 | @param FormSet FormSet data structure.
|
| 5180 |
|
| 5181 | **/
|
| 5182 | VOID
|
| 5183 | InitializeCurrentSetting (
|
| 5184 | IN OUT FORM_BROWSER_FORMSET *FormSet
|
| 5185 | )
|
| 5186 | {
|
| 5187 | LIST_ENTRY *Link;
|
| 5188 | FORMSET_STORAGE *Storage;
|
| 5189 | FORM_BROWSER_FORMSET *OldFormSet;
|
| 5190 |
|
| 5191 | //
|
| 5192 | // Try to find pre FormSet in the maintain backup list.
|
| 5193 | // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
|
| 5194 | //
|
| 5195 | OldFormSet = GetFormSetFromHiiHandle (FormSet->HiiHandle);
|
| 5196 | if (OldFormSet != NULL) {
|
| 5197 | SyncStatusForFormSet (FormSet, OldFormSet);
|
| 5198 | RemoveEntryList (&OldFormSet->Link);
|
| 5199 | DestroyFormSet (OldFormSet);
|
| 5200 | }
|
| 5201 | InsertTailList (&gBrowserFormSetList, &FormSet->Link);
|
| 5202 |
|
| 5203 | //
|
| 5204 | // Extract default from IFR binary for no storage questions.
|
| 5205 | //
|
| 5206 | ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForNoStorage, NULL, TRUE, FALSE);
|
| 5207 |
|
| 5208 | //
|
| 5209 | // Request current settings from Configuration Driver
|
| 5210 | //
|
| 5211 | Link = GetFirstNode (&FormSet->StorageListHead);
|
| 5212 | while (!IsNull (&FormSet->StorageListHead, Link)) {
|
| 5213 | Storage = FORMSET_STORAGE_FROM_LINK (Link);
|
| 5214 |
|
| 5215 | LoadStorage (FormSet, Storage);
|
| 5216 |
|
| 5217 | Link = GetNextNode (&FormSet->StorageListHead, Link);
|
| 5218 | }
|
| 5219 | }
|
| 5220 |
|
| 5221 |
|
| 5222 | /**
|
| 5223 | Fetch the Ifr binary data of a FormSet.
|
| 5224 |
|
| 5225 | @param Handle PackageList Handle
|
| 5226 | @param FormSetGuid On input, GUID or class GUID of a formset. If not
|
| 5227 | specified (NULL or zero GUID), take the first
|
| 5228 | FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
|
| 5229 | found in package list.
|
| 5230 | On output, GUID of the formset found(if not NULL).
|
| 5231 | @param BinaryLength The length of the FormSet IFR binary.
|
| 5232 | @param BinaryData The buffer designed to receive the FormSet.
|
| 5233 |
|
| 5234 | @retval EFI_SUCCESS Buffer filled with the requested FormSet.
|
| 5235 | BufferLength was updated.
|
| 5236 | @retval EFI_INVALID_PARAMETER The handle is unknown.
|
| 5237 | @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
|
| 5238 | be found with the requested FormId.
|
| 5239 |
|
| 5240 | **/
|
| 5241 | EFI_STATUS
|
| 5242 | GetIfrBinaryData (
|
| 5243 | IN EFI_HII_HANDLE Handle,
|
| 5244 | IN OUT EFI_GUID *FormSetGuid,
|
| 5245 | OUT UINTN *BinaryLength,
|
| 5246 | OUT UINT8 **BinaryData
|
| 5247 | )
|
| 5248 | {
|
| 5249 | EFI_STATUS Status;
|
| 5250 | EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
|
| 5251 | UINTN BufferSize;
|
| 5252 | UINT8 *Package;
|
| 5253 | UINT8 *OpCodeData;
|
| 5254 | UINT32 Offset;
|
| 5255 | UINT32 Offset2;
|
| 5256 | UINT32 PackageListLength;
|
| 5257 | EFI_HII_PACKAGE_HEADER PackageHeader;
|
| 5258 | UINT8 Index;
|
| 5259 | UINT8 NumberOfClassGuid;
|
| 5260 | BOOLEAN ClassGuidMatch;
|
| 5261 | EFI_GUID *ClassGuid;
|
| 5262 | EFI_GUID *ComparingGuid;
|
| 5263 |
|
| 5264 | OpCodeData = NULL;
|
| 5265 | Package = NULL;
|
| 5266 | ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
|
| 5267 |
|
| 5268 | //
|
| 5269 | // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
|
| 5270 | //
|
| 5271 | if (FormSetGuid == NULL) {
|
| 5272 | ComparingGuid = &gZeroGuid;
|
| 5273 | } else {
|
| 5274 | ComparingGuid = FormSetGuid;
|
| 5275 | }
|
| 5276 |
|
| 5277 | //
|
| 5278 | // Get HII PackageList
|
| 5279 | //
|
| 5280 | BufferSize = 0;
|
| 5281 | HiiPackageList = NULL;
|
| 5282 | Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
|
| 5283 | if (Status == EFI_BUFFER_TOO_SMALL) {
|
| 5284 | HiiPackageList = AllocatePool (BufferSize);
|
| 5285 | ASSERT (HiiPackageList != NULL);
|
| 5286 |
|
| 5287 | Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
|
| 5288 | }
|
| 5289 | if (EFI_ERROR (Status)) {
|
| 5290 | return Status;
|
| 5291 | }
|
| 5292 | ASSERT (HiiPackageList != NULL);
|
| 5293 |
|
| 5294 | //
|
| 5295 | // Get Form package from this HII package List
|
| 5296 | //
|
| 5297 | Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
|
| 5298 | Offset2 = 0;
|
| 5299 | CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
|
| 5300 |
|
| 5301 | ClassGuidMatch = FALSE;
|
| 5302 | while (Offset < PackageListLength) {
|
| 5303 | Package = ((UINT8 *) HiiPackageList) + Offset;
|
| 5304 | CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
|
| 5305 |
|
| 5306 | if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
|
| 5307 | //
|
| 5308 | // Search FormSet in this Form Package
|
| 5309 | //
|
| 5310 | Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
|
| 5311 | while (Offset2 < PackageHeader.Length) {
|
| 5312 | OpCodeData = Package + Offset2;
|
| 5313 |
|
| 5314 | if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
|
| 5315 | //
|
| 5316 | // Try to compare against formset GUID
|
| 5317 | //
|
| 5318 | if (CompareGuid (FormSetGuid, &gZeroGuid) ||
|
| 5319 | CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
|
| 5320 | break;
|
| 5321 | }
|
| 5322 |
|
| 5323 | if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {
|
| 5324 | //
|
| 5325 | // Try to compare against formset class GUID
|
| 5326 | //
|
| 5327 | NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);
|
| 5328 | ClassGuid = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET));
|
| 5329 | for (Index = 0; Index < NumberOfClassGuid; Index++) {
|
| 5330 | if (CompareGuid (ComparingGuid, ClassGuid + Index)) {
|
| 5331 | ClassGuidMatch = TRUE;
|
| 5332 | break;
|
| 5333 | }
|
| 5334 | }
|
| 5335 | if (ClassGuidMatch) {
|
| 5336 | break;
|
| 5337 | }
|
| 5338 | } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {
|
| 5339 | ClassGuidMatch = TRUE;
|
| 5340 | break;
|
| 5341 | }
|
| 5342 | }
|
| 5343 |
|
| 5344 | Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
|
| 5345 | }
|
| 5346 |
|
| 5347 | if (Offset2 < PackageHeader.Length) {
|
| 5348 | //
|
| 5349 | // Target formset found
|
| 5350 | //
|
| 5351 | break;
|
| 5352 | }
|
| 5353 | }
|
| 5354 |
|
| 5355 | Offset += PackageHeader.Length;
|
| 5356 | }
|
| 5357 |
|
| 5358 | if (Offset >= PackageListLength) {
|
| 5359 | //
|
| 5360 | // Form package not found in this Package List
|
| 5361 | //
|
| 5362 | FreePool (HiiPackageList);
|
| 5363 | return EFI_NOT_FOUND;
|
| 5364 | }
|
| 5365 |
|
| 5366 | if (FormSetGuid != NULL) {
|
| 5367 | //
|
| 5368 | // Return the FormSet GUID
|
| 5369 | //
|
| 5370 | CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));
|
| 5371 | }
|
| 5372 |
|
| 5373 | //
|
| 5374 | // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
|
| 5375 | // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
|
| 5376 | // of the Form Package.
|
| 5377 | //
|
| 5378 | *BinaryLength = PackageHeader.Length - Offset2;
|
| 5379 | *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);
|
| 5380 |
|
| 5381 | FreePool (HiiPackageList);
|
| 5382 |
|
| 5383 | if (*BinaryData == NULL) {
|
| 5384 | return EFI_OUT_OF_RESOURCES;
|
| 5385 | }
|
| 5386 |
|
| 5387 | return EFI_SUCCESS;
|
| 5388 | }
|
| 5389 |
|
| 5390 |
|
| 5391 | /**
|
| 5392 | Initialize the internal data structure of a FormSet.
|
| 5393 |
|
| 5394 | @param Handle PackageList Handle
|
| 5395 | @param FormSetGuid On input, GUID or class GUID of a formset. If not
|
| 5396 | specified (NULL or zero GUID), take the first
|
| 5397 | FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
|
| 5398 | found in package list.
|
| 5399 | On output, GUID of the formset found(if not NULL).
|
| 5400 | @param FormSet FormSet data structure.
|
| 5401 |
|
| 5402 | @retval EFI_SUCCESS The function completed successfully.
|
| 5403 | @retval EFI_NOT_FOUND The specified FormSet could not be found.
|
| 5404 |
|
| 5405 | **/
|
| 5406 | EFI_STATUS
|
| 5407 | InitializeFormSet (
|
| 5408 | IN EFI_HII_HANDLE Handle,
|
| 5409 | IN OUT EFI_GUID *FormSetGuid,
|
| 5410 | OUT FORM_BROWSER_FORMSET *FormSet
|
| 5411 | )
|
| 5412 | {
|
| 5413 | EFI_STATUS Status;
|
| 5414 | EFI_HANDLE DriverHandle;
|
| 5415 |
|
| 5416 | Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);
|
| 5417 | if (EFI_ERROR (Status)) {
|
| 5418 | return Status;
|
| 5419 | }
|
| 5420 |
|
| 5421 | FormSet->Signature = FORM_BROWSER_FORMSET_SIGNATURE;
|
| 5422 | FormSet->HiiHandle = Handle;
|
| 5423 | CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));
|
| 5424 | FormSet->QuestionInited = FALSE;
|
| 5425 |
|
| 5426 | //
|
| 5427 | // Retrieve ConfigAccess Protocol associated with this HiiPackageList
|
| 5428 | //
|
| 5429 | Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);
|
| 5430 | if (EFI_ERROR (Status)) {
|
| 5431 | return Status;
|
| 5432 | }
|
| 5433 | FormSet->DriverHandle = DriverHandle;
|
| 5434 | Status = gBS->HandleProtocol (
|
| 5435 | DriverHandle,
|
| 5436 | &gEfiHiiConfigAccessProtocolGuid,
|
| 5437 | (VOID **) &FormSet->ConfigAccess
|
| 5438 | );
|
| 5439 | if (EFI_ERROR (Status)) {
|
| 5440 | //
|
| 5441 | // Configuration Driver don't attach ConfigAccess protocol to its HII package
|
| 5442 | // list, then there will be no configuration action required
|
| 5443 | //
|
| 5444 | FormSet->ConfigAccess = NULL;
|
| 5445 | }
|
| 5446 |
|
| 5447 | //
|
| 5448 | // Parse the IFR binary OpCodes
|
| 5449 | //
|
| 5450 | Status = ParseOpCodes (FormSet);
|
| 5451 |
|
| 5452 | return Status;
|
| 5453 | }
|
| 5454 |
|
| 5455 |
|
| 5456 | /**
|
| 5457 | Save globals used by previous call to SendForm(). SendForm() may be called from
|
| 5458 | HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
|
| 5459 | So, save globals of previous call to SendForm() and restore them upon exit.
|
| 5460 |
|
| 5461 | **/
|
| 5462 | VOID
|
| 5463 | SaveBrowserContext (
|
| 5464 | VOID
|
| 5465 | )
|
| 5466 | {
|
| 5467 | BROWSER_CONTEXT *Context;
|
| 5468 | FORM_ENTRY_INFO *MenuList;
|
| 5469 |
|
| 5470 | gBrowserContextCount++;
|
| 5471 | if (gBrowserContextCount == 1) {
|
| 5472 | //
|
| 5473 | // This is not reentry of SendForm(), no context to save
|
| 5474 | //
|
| 5475 | return;
|
| 5476 | }
|
| 5477 |
|
| 5478 | Context = AllocatePool (sizeof (BROWSER_CONTEXT));
|
| 5479 | ASSERT (Context != NULL);
|
| 5480 |
|
| 5481 | Context->Signature = BROWSER_CONTEXT_SIGNATURE;
|
| 5482 |
|
| 5483 | //
|
| 5484 | // Save FormBrowser context
|
| 5485 | //
|
| 5486 | Context->Selection = gCurrentSelection;
|
| 5487 | Context->ResetRequired = gResetRequired;
|
| 5488 | Context->ExitRequired = gExitRequired;
|
| 5489 | Context->HiiHandle = mCurrentHiiHandle;
|
| 5490 | Context->FormId = mCurrentFormId;
|
| 5491 | CopyGuid (&Context->FormSetGuid, &mCurrentFormSetGuid);
|
| 5492 |
|
| 5493 | //
|
| 5494 | // Save the menu history data.
|
| 5495 | //
|
| 5496 | InitializeListHead(&Context->FormHistoryList);
|
| 5497 | while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) {
|
| 5498 | MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink);
|
| 5499 | RemoveEntryList (&MenuList->Link);
|
| 5500 |
|
| 5501 | InsertTailList(&Context->FormHistoryList, &MenuList->Link);
|
| 5502 | }
|
| 5503 |
|
| 5504 | //
|
| 5505 | // Insert to FormBrowser context list
|
| 5506 | //
|
| 5507 | InsertHeadList (&gBrowserContextList, &Context->Link);
|
| 5508 | }
|
| 5509 |
|
| 5510 |
|
| 5511 | /**
|
| 5512 | Restore globals used by previous call to SendForm().
|
| 5513 |
|
| 5514 | **/
|
| 5515 | VOID
|
| 5516 | RestoreBrowserContext (
|
| 5517 | VOID
|
| 5518 | )
|
| 5519 | {
|
| 5520 | LIST_ENTRY *Link;
|
| 5521 | BROWSER_CONTEXT *Context;
|
| 5522 | FORM_ENTRY_INFO *MenuList;
|
| 5523 |
|
| 5524 | ASSERT (gBrowserContextCount != 0);
|
| 5525 | gBrowserContextCount--;
|
| 5526 | if (gBrowserContextCount == 0) {
|
| 5527 | //
|
| 5528 | // This is not reentry of SendForm(), no context to restore
|
| 5529 | //
|
| 5530 | return;
|
| 5531 | }
|
| 5532 |
|
| 5533 | ASSERT (!IsListEmpty (&gBrowserContextList));
|
| 5534 |
|
| 5535 | Link = GetFirstNode (&gBrowserContextList);
|
| 5536 | Context = BROWSER_CONTEXT_FROM_LINK (Link);
|
| 5537 |
|
| 5538 | //
|
| 5539 | // Restore FormBrowser context
|
| 5540 | //
|
| 5541 | gCurrentSelection = Context->Selection;
|
| 5542 | gResetRequired = Context->ResetRequired;
|
| 5543 | gExitRequired = Context->ExitRequired;
|
| 5544 | mCurrentHiiHandle = Context->HiiHandle;
|
| 5545 | mCurrentFormId = Context->FormId;
|
| 5546 | CopyGuid (&mCurrentFormSetGuid, &Context->FormSetGuid);
|
| 5547 |
|
| 5548 | //
|
| 5549 | // Restore the menu history data.
|
| 5550 | //
|
| 5551 | while (!IsListEmpty (&Context->FormHistoryList)) {
|
| 5552 | MenuList = FORM_ENTRY_INFO_FROM_LINK (Context->FormHistoryList.ForwardLink);
|
| 5553 | RemoveEntryList (&MenuList->Link);
|
| 5554 |
|
| 5555 | InsertTailList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link);
|
| 5556 | }
|
| 5557 |
|
| 5558 | //
|
| 5559 | // Remove from FormBrowser context list
|
| 5560 | //
|
| 5561 | RemoveEntryList (&Context->Link);
|
| 5562 | gBS->FreePool (Context);
|
| 5563 | }
|
| 5564 |
|
| 5565 | /**
|
| 5566 | Find the matched FormSet context in the backup maintain list based on HiiHandle.
|
| 5567 |
|
| 5568 | @param Handle The Hii Handle.
|
| 5569 |
|
| 5570 | @return the found FormSet context. If no found, NULL will return.
|
| 5571 |
|
| 5572 | **/
|
| 5573 | FORM_BROWSER_FORMSET *
|
| 5574 | GetFormSetFromHiiHandle (
|
| 5575 | EFI_HII_HANDLE Handle
|
| 5576 | )
|
| 5577 | {
|
| 5578 | LIST_ENTRY *Link;
|
| 5579 | FORM_BROWSER_FORMSET *FormSet;
|
| 5580 |
|
| 5581 | Link = GetFirstNode (&gBrowserFormSetList);
|
| 5582 | while (!IsNull (&gBrowserFormSetList, Link)) {
|
| 5583 | FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);
|
| 5584 | Link = GetNextNode (&gBrowserFormSetList, Link);
|
| 5585 | if (!ValidateFormSet(FormSet)) {
|
| 5586 | continue;
|
| 5587 | }
|
| 5588 | if (FormSet->HiiHandle == Handle) {
|
| 5589 | return FormSet;
|
| 5590 | }
|
| 5591 | }
|
| 5592 |
|
| 5593 | return NULL;
|
| 5594 | }
|
| 5595 |
|
| 5596 | /**
|
| 5597 | Check whether the input HII handle is the FormSet that is being used.
|
| 5598 |
|
| 5599 | @param Handle The Hii Handle.
|
| 5600 |
|
| 5601 | @retval TRUE HII handle is being used.
|
| 5602 | @retval FALSE HII handle is not being used.
|
| 5603 |
|
| 5604 | **/
|
| 5605 | BOOLEAN
|
| 5606 | IsHiiHandleInBrowserContext (
|
| 5607 | EFI_HII_HANDLE Handle
|
| 5608 | )
|
| 5609 | {
|
| 5610 | LIST_ENTRY *Link;
|
| 5611 | BROWSER_CONTEXT *Context;
|
| 5612 |
|
| 5613 | //
|
| 5614 | // HiiHandle is Current FormSet.
|
| 5615 | //
|
| 5616 | if (mCurrentHiiHandle == Handle) {
|
| 5617 | return TRUE;
|
| 5618 | }
|
| 5619 |
|
| 5620 | //
|
| 5621 | // Check whether HiiHandle is in BrowserContext.
|
| 5622 | //
|
| 5623 | Link = GetFirstNode (&gBrowserContextList);
|
| 5624 | while (!IsNull (&gBrowserContextList, Link)) {
|
| 5625 | Context = BROWSER_CONTEXT_FROM_LINK (Link);
|
| 5626 | if (Context->HiiHandle == Handle) {
|
| 5627 | //
|
| 5628 | // HiiHandle is in BrowserContext
|
| 5629 | //
|
| 5630 | return TRUE;
|
| 5631 | }
|
| 5632 | Link = GetNextNode (&gBrowserContextList, Link);
|
| 5633 | }
|
| 5634 |
|
| 5635 | return FALSE;
|
| 5636 | }
|
| 5637 |
|
| 5638 | /**
|
| 5639 | Perform Password check.
|
| 5640 | Passwork may be encrypted by driver that requires the specific check.
|
| 5641 |
|
| 5642 | @param Form Form where Password Statement is in.
|
| 5643 | @param Statement Password statement
|
| 5644 | @param PasswordString Password string to be checked. It may be NULL.
|
| 5645 | NULL means to restore password.
|
| 5646 | "" string can be used to checked whether old password does exist.
|
| 5647 |
|
| 5648 | @return Status Status of Password check.
|
| 5649 | **/
|
| 5650 | EFI_STATUS
|
| 5651 | EFIAPI
|
| 5652 | PasswordCheck (
|
| 5653 | IN FORM_DISPLAY_ENGINE_FORM *Form,
|
| 5654 | IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,
|
| 5655 | IN EFI_STRING PasswordString OPTIONAL
|
| 5656 | )
|
| 5657 | {
|
| 5658 | EFI_STATUS Status;
|
| 5659 | EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
|
| 5660 | EFI_BROWSER_ACTION_REQUEST ActionRequest;
|
| 5661 | EFI_IFR_TYPE_VALUE IfrTypeValue;
|
| 5662 | FORM_BROWSER_STATEMENT *Question;
|
| 5663 |
|
| 5664 | ConfigAccess = gCurrentSelection->FormSet->ConfigAccess;
|
| 5665 | Question = GetBrowserStatement(Statement);
|
| 5666 | ASSERT (Question != NULL);
|
| 5667 |
|
| 5668 | if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) {
|
| 5669 | if (ConfigAccess == NULL) {
|
| 5670 | return EFI_UNSUPPORTED;
|
| 5671 | }
|
| 5672 | } else {
|
| 5673 | if (PasswordString == NULL) {
|
| 5674 | return EFI_SUCCESS;
|
| 5675 | }
|
| 5676 |
|
| 5677 | //
|
| 5678 | // Check whether has preexisted password.
|
| 5679 | //
|
| 5680 | if (PasswordString[0] == 0) {
|
| 5681 | if (*((CHAR16 *) Question->BufferValue) == 0) {
|
| 5682 | return EFI_SUCCESS;
|
| 5683 | } else {
|
| 5684 | return EFI_NOT_READY;
|
| 5685 | }
|
| 5686 | }
|
| 5687 |
|
| 5688 | //
|
| 5689 | // Check whether the input password is same as preexisted password.
|
| 5690 | //
|
| 5691 | if (StrnCmp (PasswordString, (CHAR16 *) Question->BufferValue, Question->StorageWidth/sizeof (CHAR16)) == 0) {
|
| 5692 | return EFI_SUCCESS;
|
| 5693 | } else {
|
| 5694 | return EFI_NOT_READY;
|
| 5695 | }
|
| 5696 | }
|
| 5697 |
|
| 5698 | //
|
| 5699 | // Prepare password string in HII database
|
| 5700 | //
|
| 5701 | if (PasswordString != NULL) {
|
| 5702 | IfrTypeValue.string = NewString (PasswordString, gCurrentSelection->FormSet->HiiHandle);
|
| 5703 | } else {
|
| 5704 | IfrTypeValue.string = 0;
|
| 5705 | }
|
| 5706 |
|
| 5707 | //
|
| 5708 | // Send password to Configuration Driver for validation
|
| 5709 | //
|
| 5710 | Status = ConfigAccess->Callback (
|
| 5711 | ConfigAccess,
|
| 5712 | EFI_BROWSER_ACTION_CHANGING,
|
| 5713 | Question->QuestionId,
|
| 5714 | Question->HiiValue.Type,
|
| 5715 | &IfrTypeValue,
|
| 5716 | &ActionRequest
|
| 5717 | );
|
| 5718 |
|
| 5719 | //
|
| 5720 | // Remove password string from HII database
|
| 5721 | //
|
| 5722 | if (PasswordString != NULL) {
|
| 5723 | DeleteString (IfrTypeValue.string, gCurrentSelection->FormSet->HiiHandle);
|
| 5724 | }
|
| 5725 |
|
| 5726 | return Status;
|
| 5727 | }
|
| 5728 |
|
| 5729 | /**
|
| 5730 | Find the registered HotKey based on KeyData.
|
| 5731 |
|
| 5732 | @param[in] KeyData A pointer to a buffer that describes the keystroke
|
| 5733 | information for the hot key.
|
| 5734 |
|
| 5735 | @return The registered HotKey context. If no found, NULL will return.
|
| 5736 | **/
|
| 5737 | BROWSER_HOT_KEY *
|
| 5738 | GetHotKeyFromRegisterList (
|
| 5739 | IN EFI_INPUT_KEY *KeyData
|
| 5740 | )
|
| 5741 | {
|
| 5742 | LIST_ENTRY *Link;
|
| 5743 | BROWSER_HOT_KEY *HotKey;
|
| 5744 |
|
| 5745 | Link = GetFirstNode (&gBrowserHotKeyList);
|
| 5746 | while (!IsNull (&gBrowserHotKeyList, Link)) {
|
| 5747 | HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);
|
| 5748 | if (HotKey->KeyData->ScanCode == KeyData->ScanCode) {
|
| 5749 | return HotKey;
|
| 5750 | }
|
| 5751 | Link = GetNextNode (&gBrowserHotKeyList, Link);
|
| 5752 | }
|
| 5753 |
|
| 5754 | return NULL;
|
| 5755 | }
|
| 5756 |
|
| 5757 | /**
|
| 5758 | Configure what scope the hot key will impact.
|
| 5759 | All hot keys have the same scope. The mixed hot keys with the different level are not supported.
|
| 5760 | If no scope is set, the default scope will be FormSet level.
|
| 5761 | After all registered hot keys are removed, previous Scope can reset to another level.
|
| 5762 |
|
| 5763 | @param[in] Scope Scope level to be set.
|
| 5764 |
|
| 5765 | @retval EFI_SUCCESS Scope is set correctly.
|
| 5766 | @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
|
| 5767 | @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
|
| 5768 |
|
| 5769 | **/
|
| 5770 | EFI_STATUS
|
| 5771 | EFIAPI
|
| 5772 | SetScope (
|
| 5773 | IN BROWSER_SETTING_SCOPE Scope
|
| 5774 | )
|
| 5775 | {
|
| 5776 | if (Scope >= MaxLevel) {
|
| 5777 | return EFI_INVALID_PARAMETER;
|
| 5778 | }
|
| 5779 |
|
| 5780 | //
|
| 5781 | // When no hot key registered in system or on the first setting,
|
| 5782 | // Scope can be set.
|
| 5783 | //
|
| 5784 | if (mBrowserScopeFirstSet || IsListEmpty (&gBrowserHotKeyList)) {
|
| 5785 | gBrowserSettingScope = Scope;
|
| 5786 | mBrowserScopeFirstSet = FALSE;
|
| 5787 | } else if (Scope != gBrowserSettingScope) {
|
| 5788 | return EFI_UNSUPPORTED;
|
| 5789 | }
|
| 5790 |
|
| 5791 | return EFI_SUCCESS;
|
| 5792 | }
|
| 5793 |
|
| 5794 | /**
|
| 5795 | Register the hot key with its browser action, or unregistered the hot key.
|
| 5796 | Only support hot key that is not printable character (control key, function key, etc.).
|
| 5797 | If the action value is zero, the hot key will be unregistered if it has been registered.
|
| 5798 | If the same hot key has been registered, the new action and help string will override the previous ones.
|
| 5799 |
|
| 5800 | @param[in] KeyData A pointer to a buffer that describes the keystroke
|
| 5801 | information for the hot key. Its type is EFI_INPUT_KEY to
|
| 5802 | be supported by all ConsoleIn devices.
|
| 5803 | @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
|
| 5804 | @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
|
| 5805 | @param[in] HelpString Help string that describes the hot key information.
|
| 5806 | Its value may be NULL for the unregistered hot key.
|
| 5807 |
|
| 5808 | @retval EFI_SUCCESS Hot key is registered or unregistered.
|
| 5809 | @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
|
| 5810 | @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
|
| 5811 | @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
|
| 5812 | **/
|
| 5813 | EFI_STATUS
|
| 5814 | EFIAPI
|
| 5815 | RegisterHotKey (
|
| 5816 | IN EFI_INPUT_KEY *KeyData,
|
| 5817 | IN UINT32 Action,
|
| 5818 | IN UINT16 DefaultId,
|
| 5819 | IN EFI_STRING HelpString OPTIONAL
|
| 5820 | )
|
| 5821 | {
|
| 5822 | BROWSER_HOT_KEY *HotKey;
|
| 5823 |
|
| 5824 | //
|
| 5825 | // Check input parameters.
|
| 5826 | //
|
| 5827 | if (KeyData == NULL || KeyData->UnicodeChar != CHAR_NULL ||
|
| 5828 | (Action != BROWSER_ACTION_UNREGISTER && HelpString == NULL)) {
|
| 5829 | return EFI_INVALID_PARAMETER;
|
| 5830 | }
|
| 5831 |
|
| 5832 | //
|
| 5833 | // Check whether the input KeyData is in BrowserHotKeyList.
|
| 5834 | //
|
| 5835 | HotKey = GetHotKeyFromRegisterList (KeyData);
|
| 5836 |
|
| 5837 | //
|
| 5838 | // Unregister HotKey
|
| 5839 | //
|
| 5840 | if (Action == BROWSER_ACTION_UNREGISTER) {
|
| 5841 | if (HotKey != NULL) {
|
| 5842 | //
|
| 5843 | // The registered HotKey is found.
|
| 5844 | // Remove it from List, and free its resource.
|
| 5845 | //
|
| 5846 | RemoveEntryList (&HotKey->Link);
|
| 5847 | FreePool (HotKey->KeyData);
|
| 5848 | FreePool (HotKey->HelpString);
|
| 5849 | return EFI_SUCCESS;
|
| 5850 | } else {
|
| 5851 | //
|
| 5852 | // The registered HotKey is not found.
|
| 5853 | //
|
| 5854 | return EFI_NOT_FOUND;
|
| 5855 | }
|
| 5856 | }
|
| 5857 |
|
| 5858 | //
|
| 5859 | // Register HotKey into List.
|
| 5860 | //
|
| 5861 | if (HotKey == NULL) {
|
| 5862 | //
|
| 5863 | // Create new Key, and add it into List.
|
| 5864 | //
|
| 5865 | HotKey = AllocateZeroPool (sizeof (BROWSER_HOT_KEY));
|
| 5866 | ASSERT (HotKey != NULL);
|
| 5867 | HotKey->Signature = BROWSER_HOT_KEY_SIGNATURE;
|
| 5868 | HotKey->KeyData = AllocateCopyPool (sizeof (EFI_INPUT_KEY), KeyData);
|
| 5869 | InsertTailList (&gBrowserHotKeyList, &HotKey->Link);
|
| 5870 | }
|
| 5871 |
|
| 5872 | //
|
| 5873 | // Fill HotKey information.
|
| 5874 | //
|
| 5875 | HotKey->Action = Action;
|
| 5876 | HotKey->DefaultId = DefaultId;
|
| 5877 | if (HotKey->HelpString != NULL) {
|
| 5878 | FreePool (HotKey->HelpString);
|
| 5879 | }
|
| 5880 | HotKey->HelpString = AllocateCopyPool (StrSize (HelpString), HelpString);
|
| 5881 |
|
| 5882 | return EFI_SUCCESS;
|
| 5883 | }
|
| 5884 |
|
| 5885 | /**
|
| 5886 | Register Exit handler function.
|
| 5887 | When more than one handler function is registered, the latter one will override the previous one.
|
| 5888 | When NULL handler is specified, the previous Exit handler will be unregistered.
|
| 5889 |
|
| 5890 | @param[in] Handler Pointer to handler function.
|
| 5891 |
|
| 5892 | **/
|
| 5893 | VOID
|
| 5894 | EFIAPI
|
| 5895 | RegiserExitHandler (
|
| 5896 | IN EXIT_HANDLER Handler
|
| 5897 | )
|
| 5898 | {
|
| 5899 | ExitHandlerFunction = Handler;
|
| 5900 | return;
|
| 5901 | }
|
| 5902 |
|
| 5903 | /**
|
| 5904 | Check whether the browser data has been modified.
|
| 5905 |
|
| 5906 | @retval TRUE Browser data is modified.
|
| 5907 | @retval FALSE No browser data is modified.
|
| 5908 |
|
| 5909 | **/
|
| 5910 | BOOLEAN
|
| 5911 | EFIAPI
|
| 5912 | IsBrowserDataModified (
|
| 5913 | VOID
|
| 5914 | )
|
| 5915 | {
|
| 5916 | LIST_ENTRY *Link;
|
| 5917 | FORM_BROWSER_FORMSET *FormSet;
|
| 5918 |
|
| 5919 | switch (gBrowserSettingScope) {
|
| 5920 | case FormLevel:
|
| 5921 | if (gCurrentSelection == NULL) {
|
| 5922 | return FALSE;
|
| 5923 | }
|
| 5924 | return IsNvUpdateRequiredForForm (gCurrentSelection->Form);
|
| 5925 |
|
| 5926 | case FormSetLevel:
|
| 5927 | if (gCurrentSelection == NULL) {
|
| 5928 | return FALSE;
|
| 5929 | }
|
| 5930 | return IsNvUpdateRequiredForFormSet (gCurrentSelection->FormSet);
|
| 5931 |
|
| 5932 | case SystemLevel:
|
| 5933 | Link = GetFirstNode (&gBrowserFormSetList);
|
| 5934 | while (!IsNull (&gBrowserFormSetList, Link)) {
|
| 5935 | FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);
|
| 5936 | if (!ValidateFormSet(FormSet)) {
|
| 5937 | continue;
|
| 5938 | }
|
| 5939 |
|
| 5940 | if (IsNvUpdateRequiredForFormSet (FormSet)) {
|
| 5941 | return TRUE;
|
| 5942 | }
|
| 5943 | Link = GetNextNode (&gBrowserFormSetList, Link);
|
| 5944 | }
|
| 5945 | return FALSE;
|
| 5946 |
|
| 5947 | default:
|
| 5948 | return FALSE;
|
| 5949 | }
|
| 5950 | }
|
| 5951 |
|
| 5952 | /**
|
| 5953 | Execute the action requested by the Action parameter.
|
| 5954 |
|
| 5955 | @param[in] Action Execute the request action.
|
| 5956 | @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
|
| 5957 |
|
| 5958 | @retval EFI_SUCCESS Execute the request action succss.
|
| 5959 | @retval EFI_INVALID_PARAMETER The input action value is invalid.
|
| 5960 |
|
| 5961 | **/
|
| 5962 | EFI_STATUS
|
| 5963 | EFIAPI
|
| 5964 | ExecuteAction (
|
| 5965 | IN UINT32 Action,
|
| 5966 | IN UINT16 DefaultId
|
| 5967 | )
|
| 5968 | {
|
| 5969 | EFI_STATUS Status;
|
| 5970 | FORM_BROWSER_FORMSET *FormSet;
|
| 5971 | FORM_BROWSER_FORM *Form;
|
| 5972 |
|
| 5973 | if (gBrowserSettingScope < SystemLevel && gCurrentSelection == NULL) {
|
| 5974 | return EFI_NOT_READY;
|
| 5975 | }
|
| 5976 |
|
| 5977 | Status = EFI_SUCCESS;
|
| 5978 | FormSet = NULL;
|
| 5979 | Form = NULL;
|
| 5980 | if (gBrowserSettingScope < SystemLevel) {
|
| 5981 | FormSet = gCurrentSelection->FormSet;
|
| 5982 | Form = gCurrentSelection->Form;
|
| 5983 | }
|
| 5984 |
|
| 5985 | //
|
| 5986 | // Executet the discard action.
|
| 5987 | //
|
| 5988 | if ((Action & BROWSER_ACTION_DISCARD) != 0) {
|
| 5989 | Status = DiscardForm (FormSet, Form, gBrowserSettingScope);
|
| 5990 | if (EFI_ERROR (Status)) {
|
| 5991 | return Status;
|
| 5992 | }
|
| 5993 | }
|
| 5994 |
|
| 5995 | //
|
| 5996 | // Executet the difault action.
|
| 5997 | //
|
| 5998 | if ((Action & BROWSER_ACTION_DEFAULT) != 0) {
|
| 5999 | Status = ExtractDefault (FormSet, Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE, FALSE);
|
| 6000 | if (EFI_ERROR (Status)) {
|
| 6001 | return Status;
|
| 6002 | }
|
| 6003 | UpdateStatementStatus (FormSet, Form, gBrowserSettingScope);
|
| 6004 | }
|
| 6005 |
|
| 6006 | //
|
| 6007 | // Executet the submit action.
|
| 6008 | //
|
| 6009 | if ((Action & BROWSER_ACTION_SUBMIT) != 0) {
|
| 6010 | Status = SubmitForm (FormSet, Form, gBrowserSettingScope);
|
| 6011 | if (EFI_ERROR (Status)) {
|
| 6012 | return Status;
|
| 6013 | }
|
| 6014 | }
|
| 6015 |
|
| 6016 | //
|
| 6017 | // Executet the reset action.
|
| 6018 | //
|
| 6019 | if ((Action & BROWSER_ACTION_RESET) != 0) {
|
| 6020 | gResetRequired = TRUE;
|
| 6021 | }
|
| 6022 |
|
| 6023 | //
|
| 6024 | // Executet the exit action.
|
| 6025 | //
|
| 6026 | if ((Action & BROWSER_ACTION_EXIT) != 0) {
|
| 6027 | DiscardForm (FormSet, Form, gBrowserSettingScope);
|
| 6028 | if (gBrowserSettingScope == SystemLevel) {
|
| 6029 | if (ExitHandlerFunction != NULL) {
|
| 6030 | ExitHandlerFunction ();
|
| 6031 | }
|
| 6032 | }
|
| 6033 |
|
| 6034 | gExitRequired = TRUE;
|
| 6035 | }
|
| 6036 |
|
| 6037 | return Status;
|
| 6038 | }
|
| 6039 |
|
| 6040 | /**
|
| 6041 | Create reminder to let user to choose save or discard the changed browser data.
|
| 6042 | Caller can use it to actively check the changed browser data.
|
| 6043 |
|
| 6044 | @retval BROWSER_NO_CHANGES No browser data is changed.
|
| 6045 | @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
|
| 6046 | @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
|
| 6047 | @retval BROWSER_KEEP_CURRENT Browser keep current changes.
|
| 6048 |
|
| 6049 | **/
|
| 6050 | UINT32
|
| 6051 | EFIAPI
|
| 6052 | SaveReminder (
|
| 6053 | VOID
|
| 6054 | )
|
| 6055 | {
|
| 6056 | LIST_ENTRY *Link;
|
| 6057 | FORM_BROWSER_FORMSET *FormSet;
|
| 6058 | BOOLEAN IsDataChanged;
|
| 6059 | UINT32 DataSavedAction;
|
| 6060 | UINT32 ConfirmRet;
|
| 6061 |
|
| 6062 | DataSavedAction = BROWSER_NO_CHANGES;
|
| 6063 | IsDataChanged = FALSE;
|
| 6064 | Link = GetFirstNode (&gBrowserFormSetList);
|
| 6065 | while (!IsNull (&gBrowserFormSetList, Link)) {
|
| 6066 | FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);
|
| 6067 | Link = GetNextNode (&gBrowserFormSetList, Link);
|
| 6068 | if (!ValidateFormSet(FormSet)) {
|
| 6069 | continue;
|
| 6070 | }
|
| 6071 | if (IsNvUpdateRequiredForFormSet (FormSet)) {
|
| 6072 | IsDataChanged = TRUE;
|
| 6073 | break;
|
| 6074 | }
|
| 6075 | }
|
| 6076 |
|
| 6077 | //
|
| 6078 | // No data is changed. No save is required.
|
| 6079 | //
|
| 6080 | if (!IsDataChanged) {
|
| 6081 | return DataSavedAction;
|
| 6082 | }
|
| 6083 |
|
| 6084 | //
|
| 6085 | // If data is changed, prompt user to save or discard it.
|
| 6086 | //
|
| 6087 | do {
|
| 6088 | ConfirmRet = (UINT32) mFormDisplay->ConfirmDataChange();
|
| 6089 |
|
| 6090 | if (ConfirmRet == BROWSER_ACTION_SUBMIT) {
|
| 6091 | SubmitForm (NULL, NULL, SystemLevel);
|
| 6092 | DataSavedAction = BROWSER_SAVE_CHANGES;
|
| 6093 | break;
|
| 6094 | } else if (ConfirmRet == BROWSER_ACTION_DISCARD) {
|
| 6095 | DiscardForm (NULL, NULL, SystemLevel);
|
| 6096 | DataSavedAction = BROWSER_DISCARD_CHANGES;
|
| 6097 | break;
|
| 6098 | } else if (ConfirmRet == BROWSER_ACTION_NONE) {
|
| 6099 | DataSavedAction = BROWSER_KEEP_CURRENT;
|
| 6100 | break;
|
| 6101 | }
|
| 6102 | } while (1);
|
| 6103 |
|
| 6104 | return DataSavedAction;
|
| 6105 | }
|
| 6106 |
|
| 6107 | /**
|
| 6108 | Check whether the Reset Required for the browser
|
| 6109 |
|
| 6110 | @retval TRUE Browser required to reset after exit.
|
| 6111 | @retval FALSE Browser not need to reset after exit.
|
| 6112 |
|
| 6113 | **/
|
| 6114 | BOOLEAN
|
| 6115 | EFIAPI
|
| 6116 | IsResetRequired (
|
| 6117 | VOID
|
| 6118 | )
|
| 6119 | {
|
| 6120 | return gResetRequired;
|
| 6121 | }
|
| 6122 |
|