1 /** @file 2 The functions for Boot Maintainence Main menu. 3 4 Copyright (c) 2004 - 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 "BootMaint.h" 16 #include "FormGuid.h" 17 #include "Bds.h" 18 #include "FrontPage.h" 19 20 EFI_DEVICE_PATH_PROTOCOL EndDevicePath[] = { 21 { 22 END_DEVICE_PATH_TYPE, 23 END_ENTIRE_DEVICE_PATH_SUBTYPE, 24 { 25 END_DEVICE_PATH_LENGTH, 26 0 27 } 28 } 29 }; 30 31 HII_VENDOR_DEVICE_PATH mBmmHiiVendorDevicePath = { 32 { 33 { 34 HARDWARE_DEVICE_PATH, 35 HW_VENDOR_DP, 36 { 37 (UINT8) (sizeof (VENDOR_DEVICE_PATH)), 38 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) 39 } 40 }, 41 BOOT_MAINT_FORMSET_GUID 42 }, 43 { 44 END_DEVICE_PATH_TYPE, 45 END_ENTIRE_DEVICE_PATH_SUBTYPE, 46 { 47 (UINT8) (END_DEVICE_PATH_LENGTH), 48 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) 49 } 50 } 51 }; 52 53 HII_VENDOR_DEVICE_PATH mFeHiiVendorDevicePath = { 54 { 55 { 56 HARDWARE_DEVICE_PATH, 57 HW_VENDOR_DP, 58 { 59 (UINT8) (sizeof (VENDOR_DEVICE_PATH)), 60 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) 61 } 62 }, 63 FILE_EXPLORE_FORMSET_GUID 64 }, 65 { 66 END_DEVICE_PATH_TYPE, 67 END_ENTIRE_DEVICE_PATH_SUBTYPE, 68 { 69 (UINT8) (END_DEVICE_PATH_LENGTH), 70 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) 71 } 72 } 73 }; 74 75 CHAR16 mBootMaintStorageName[] = L"BmmData"; 76 CHAR16 mFileExplorerStorageName[] = L"FeData"; 77 BMM_CALLBACK_DATA *mBmmCallbackInfo = NULL; 78 79 /** 80 Init all memu. 81 82 @param CallbackData The BMM context data. 83 84 **/ 85 VOID 86 InitAllMenu ( 87 IN BMM_CALLBACK_DATA *CallbackData 88 ); 89 90 /** 91 Free up all Menu Option list. 92 93 **/ 94 VOID 95 FreeAllMenu ( 96 VOID 97 ); 98 99 /** 100 Initialize all of BMM configuration data in BmmFakeNvData and BmmOldFakeNVData member 101 in BMM context data and create all of dynamic OP code for BMM. 102 103 @param CallbackData The BMM context data. 104 105 **/ 106 VOID 107 InitializeBmmConfig ( 108 IN BMM_CALLBACK_DATA *CallbackData 109 ) 110 { 111 BM_MENU_ENTRY *NewMenuEntry; 112 BM_LOAD_CONTEXT *NewLoadContext; 113 UINT16 Index; 114 115 ASSERT (CallbackData != NULL); 116 117 // 118 // Initialize data which located in BMM main page 119 // 120 CallbackData->BmmFakeNvData.BootNext = (UINT16) (BootOptionMenu.MenuNumber); 121 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { 122 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); 123 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; 124 125 if (NewLoadContext->IsBootNext) { 126 CallbackData->BmmFakeNvData.BootNext = Index; 127 break; 128 } 129 } 130 131 CallbackData->BmmFakeNvData.BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut); 132 133 // 134 // Initialize data which located in Boot Options Menu 135 // 136 GetBootOrder (CallbackData); 137 GetLegacyDeviceOrder (CallbackData); 138 139 // 140 // Initialize data which located in Driver Options Menu 141 // 142 GetDriverOrder (CallbackData); 143 144 // 145 // Initialize data which located in Console Options Menu 146 // 147 GetConsoleOutMode (CallbackData); 148 GetConsoleInCheck (CallbackData); 149 GetConsoleOutCheck (CallbackData); 150 GetConsoleErrCheck (CallbackData); 151 GetTerminalAttribute (CallbackData); 152 153 // 154 // Backup Initialize BMM configuartion data to BmmOldFakeNVData 155 // 156 CopyMem (&CallbackData->BmmOldFakeNVData, &CallbackData->BmmFakeNvData, sizeof (BMM_FAKE_NV_DATA)); 157 } 158 159 /** 160 Create string tokens for a menu from its help strings and display strings 161 162 @param CallbackData The BMM context data. 163 @param HiiHandle Hii Handle of the package to be updated. 164 @param MenuOption The Menu whose string tokens need to be created 165 166 @retval EFI_SUCCESS String tokens created successfully 167 @retval others contain some errors 168 **/ 169 EFI_STATUS 170 CreateMenuStringToken ( 171 IN BMM_CALLBACK_DATA *CallbackData, 172 IN EFI_HII_HANDLE HiiHandle, 173 IN BM_MENU_OPTION *MenuOption 174 ) 175 { 176 BM_MENU_ENTRY *NewMenuEntry; 177 UINTN Index; 178 179 for (Index = 0; Index < MenuOption->MenuNumber; Index++) { 180 NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index); 181 182 NewMenuEntry->DisplayStringToken = HiiSetString ( 183 HiiHandle, 184 0, 185 NewMenuEntry->DisplayString, 186 NULL 187 ); 188 189 if (NULL == NewMenuEntry->HelpString) { 190 NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken; 191 } else { 192 NewMenuEntry->HelpStringToken = HiiSetString ( 193 HiiHandle, 194 0, 195 NewMenuEntry->HelpString, 196 NULL 197 ); 198 } 199 } 200 201 return EFI_SUCCESS; 202 } 203 204 /** 205 This function allows a caller to extract the current configuration for one 206 or more named elements from the target driver. 207 208 209 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. 210 @param Request A null-terminated Unicode string in <ConfigRequest> format. 211 @param Progress On return, points to a character in the Request string. 212 Points to the string's null terminator if request was successful. 213 Points to the most recent '&' before the first failing name/value 214 pair (or the beginning of the string if the failure is in the 215 first name/value pair) if the request was not successful. 216 @param Results A null-terminated Unicode string in <ConfigAltResp> format which 217 has all values filled in for the names in the Request string. 218 String to be allocated by the called function. 219 220 @retval EFI_SUCCESS The Results is filled with the requested values. 221 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. 222 @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name. 223 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. 224 225 **/ 226 EFI_STATUS 227 EFIAPI 228 BootMaintExtractConfig ( 229 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, 230 IN CONST EFI_STRING Request, 231 OUT EFI_STRING *Progress, 232 OUT EFI_STRING *Results 233 ) 234 { 235 EFI_STATUS Status; 236 UINTN BufferSize; 237 BMM_CALLBACK_DATA *Private; 238 EFI_STRING ConfigRequestHdr; 239 EFI_STRING ConfigRequest; 240 BOOLEAN AllocatedRequest; 241 UINTN Size; 242 243 if (Progress == NULL || Results == NULL) { 244 return EFI_INVALID_PARAMETER; 245 } 246 247 *Progress = Request; 248 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gBootMaintFormSetGuid, mBootMaintStorageName)) { 249 return EFI_NOT_FOUND; 250 } 251 252 ConfigRequestHdr = NULL; 253 ConfigRequest = NULL; 254 AllocatedRequest = FALSE; 255 Size = 0; 256 257 Private = BMM_CALLBACK_DATA_FROM_THIS (This); 258 // 259 // Convert buffer data to <ConfigResp> by helper function BlockToConfig() 260 // 261 BufferSize = sizeof (BMM_FAKE_NV_DATA); 262 ConfigRequest = Request; 263 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) { 264 // 265 // Request has no request element, construct full request string. 266 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template 267 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator 268 // 269 ConfigRequestHdr = HiiConstructConfigHdr (&gBootMaintFormSetGuid, mBootMaintStorageName, Private->BmmDriverHandle); 270 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); 271 ConfigRequest = AllocateZeroPool (Size); 272 ASSERT (ConfigRequest != NULL); 273 AllocatedRequest = TRUE; 274 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize); 275 FreePool (ConfigRequestHdr); 276 } 277 278 Status = gHiiConfigRouting->BlockToConfig ( 279 gHiiConfigRouting, 280 ConfigRequest, 281 (UINT8 *) &Private->BmmFakeNvData, 282 BufferSize, 283 Results, 284 Progress 285 ); 286 // 287 // Free the allocated config request string. 288 // 289 if (AllocatedRequest) { 290 FreePool (ConfigRequest); 291 ConfigRequest = NULL; 292 } 293 // 294 // Set Progress string to the original request string. 295 // 296 if (Request == NULL) { 297 *Progress = NULL; 298 } else if (StrStr (Request, L"OFFSET") == NULL) { 299 *Progress = Request + StrLen (Request); 300 } 301 302 return Status; 303 } 304 305 /** 306 This function applies changes in a driver's configuration. 307 Input is a Configuration, which has the routing data for this 308 driver followed by name / value configuration pairs. The driver 309 must apply those pairs to its configurable storage. If the 310 driver's configuration is stored in a linear block of data 311 and the driver's name / value pairs are in <BlockConfig> 312 format, it may use the ConfigToBlock helper function (above) to 313 simplify the job. Currently not implemented. 314 315 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. 316 @param[in] Configuration A null-terminated Unicode string in 317 <ConfigString> format. 318 @param[out] Progress A pointer to a string filled in with the 319 offset of the most recent '&' before the 320 first failing name / value pair (or the 321 beginn ing of the string if the failure 322 is in the first name / value pair) or 323 the terminating NULL if all was 324 successful. 325 326 @retval EFI_SUCCESS The results have been distributed or are 327 awaiting distribution. 328 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the 329 parts of the results that must be 330 stored awaiting possible future 331 protocols. 332 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the 333 Results parameter would result 334 in this type of error. 335 @retval EFI_NOT_FOUND Target for the specified routing data 336 was not found. 337 **/ 338 EFI_STATUS 339 EFIAPI 340 BootMaintRouteConfig ( 341 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, 342 IN CONST EFI_STRING Configuration, 343 OUT EFI_STRING *Progress 344 ) 345 { 346 EFI_STATUS Status; 347 UINTN BufferSize; 348 EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting; 349 BMM_FAKE_NV_DATA *NewBmmData; 350 BMM_FAKE_NV_DATA *OldBmmData; 351 BM_CONSOLE_CONTEXT *NewConsoleContext; 352 BM_TERMINAL_CONTEXT *NewTerminalContext; 353 BM_MENU_ENTRY *NewMenuEntry; 354 BM_LOAD_CONTEXT *NewLoadContext; 355 UINT16 Index; 356 BOOLEAN TerminalAttChange; 357 BMM_CALLBACK_DATA *Private; 358 359 if (Progress == NULL) { 360 return EFI_INVALID_PARAMETER; 361 } 362 *Progress = Configuration; 363 364 if (Configuration == NULL) { 365 return EFI_INVALID_PARAMETER; 366 } 367 368 // 369 // Check routing data in <ConfigHdr>. 370 // Note: there is no name for Name/Value storage, only GUID will be checked 371 // 372 if (!HiiIsConfigHdrMatch (Configuration, &gBootMaintFormSetGuid, mBootMaintStorageName)) { 373 return EFI_NOT_FOUND; 374 } 375 376 Status = gBS->LocateProtocol ( 377 &gEfiHiiConfigRoutingProtocolGuid, 378 NULL, 379 (VOID**) &ConfigRouting 380 ); 381 if (EFI_ERROR (Status)) { 382 return Status; 383 } 384 385 Private = BMM_CALLBACK_DATA_FROM_THIS (This); 386 // 387 // Get Buffer Storage data from EFI variable 388 // 389 BufferSize = sizeof (BMM_FAKE_NV_DATA); 390 OldBmmData = &Private->BmmOldFakeNVData; 391 NewBmmData = &Private->BmmFakeNvData; 392 // 393 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock() 394 // 395 Status = ConfigRouting->ConfigToBlock ( 396 ConfigRouting, 397 Configuration, 398 (UINT8 *) NewBmmData, 399 &BufferSize, 400 Progress 401 ); 402 ASSERT_EFI_ERROR (Status); 403 // 404 // Compare new and old BMM configuration data and only do action for modified item to 405 // avoid setting unnecessary non-volatile variable 406 // 407 408 // 409 // Check data which located in BMM main page and save the settings if need 410 // 411 if (CompareMem (NewBmmData->LegacyFD, OldBmmData->LegacyFD, sizeof (NewBmmData->LegacyFD)) != 0) { 412 Var_UpdateBBSOption (Private, FORM_SET_FD_ORDER_ID); 413 } 414 415 if (CompareMem (NewBmmData->LegacyHD, OldBmmData->LegacyHD, sizeof (NewBmmData->LegacyHD)) != 0) { 416 Var_UpdateBBSOption (Private, FORM_SET_HD_ORDER_ID); 417 } 418 419 if (CompareMem (NewBmmData->LegacyCD, OldBmmData->LegacyCD, sizeof (NewBmmData->LegacyCD)) != 0) { 420 Var_UpdateBBSOption (Private, FORM_SET_CD_ORDER_ID); 421 } 422 423 if (CompareMem (NewBmmData->LegacyNET, OldBmmData->LegacyNET, sizeof (NewBmmData->LegacyNET)) != 0) { 424 Var_UpdateBBSOption (Private, FORM_SET_NET_ORDER_ID); 425 } 426 427 if (CompareMem (NewBmmData->LegacyBEV, OldBmmData->LegacyBEV, sizeof (NewBmmData->LegacyBEV)) != 0) { 428 Var_UpdateBBSOption (Private, FORM_SET_BEV_ORDER_ID); 429 } 430 431 // 432 // Change for "delete boot option" page need update NewBmmData->BootOptionOrder, so process 433 // NewBmmData->BootOptionOrder before NewBmmData->BootOptionDel 434 // 435 if (CompareMem (NewBmmData->BootOptionOrder, OldBmmData->BootOptionOrder, sizeof (NewBmmData->BootOptionOrder)) != 0) { 436 Status = Var_UpdateBootOrder (Private); 437 } 438 439 // 440 // Change for "delete driver option" page need update NewBmmData->DriverOptionOrder, so process 441 // NewBmmData->DriverOptionOrder before NewBmmData->DriverOptionDel 442 // 443 if (CompareMem (NewBmmData->DriverOptionOrder, OldBmmData->DriverOptionOrder, sizeof (NewBmmData->DriverOptionOrder)) != 0) { 444 Status = Var_UpdateDriverOrder (Private); 445 } 446 447 // 448 // Check data which located in Boot Options Menu and save the settings if need 449 // 450 if (CompareMem (NewBmmData->BootOptionDel, OldBmmData->BootOptionDel, sizeof (NewBmmData->BootOptionDel)) != 0) { 451 for (Index = 0; 452 ((Index < BootOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->BootOptionDel) / sizeof (NewBmmData->BootOptionDel[0])))); 453 Index ++) { 454 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); 455 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; 456 NewLoadContext->Deleted = NewBmmData->BootOptionDel[Index]; 457 NewBmmData->BootOptionDel[Index] = FALSE; 458 NewBmmData->BootOptionDelMark[Index] = FALSE; 459 } 460 461 Var_DelBootOption (); 462 } 463 464 // 465 // Check data which located in Driver Options Menu and save the settings if need 466 // 467 if (CompareMem (NewBmmData->DriverOptionDel, OldBmmData->DriverOptionDel, sizeof (NewBmmData->DriverOptionDel)) != 0) { 468 for (Index = 0; 469 ((Index < DriverOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->DriverOptionDel) / sizeof (NewBmmData->DriverOptionDel[0])))); 470 Index++) { 471 NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); 472 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; 473 NewLoadContext->Deleted = NewBmmData->DriverOptionDel[Index]; 474 NewBmmData->DriverOptionDel[Index] = FALSE; 475 NewBmmData->DriverOptionDelMark[Index] = FALSE; 476 } 477 Var_DelDriverOption (); 478 } 479 480 if (CompareMem (&NewBmmData->BootTimeOut, &OldBmmData->BootTimeOut, sizeof (NewBmmData->BootTimeOut)) != 0) { 481 Status = gRT->SetVariable ( 482 L"Timeout", 483 &gEfiGlobalVariableGuid, 484 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, 485 sizeof (UINT16), 486 &(NewBmmData->BootTimeOut) 487 ); 488 ASSERT_EFI_ERROR(Status); 489 490 // 491 // Bugbug: code not exit in UiApp but in IntelFrameworkModulePkg, need do more check. 492 // 493 Private->BmmOldFakeNVData.BootTimeOut = NewBmmData->BootTimeOut; 494 } 495 496 if (CompareMem (&NewBmmData->BootNext, &OldBmmData->BootNext, sizeof (NewBmmData->BootNext)) != 0) { 497 Status = Var_UpdateBootNext (Private); 498 } 499 500 if (CompareMem (&NewBmmData->ConsoleOutMode, &OldBmmData->ConsoleOutMode, sizeof (NewBmmData->ConsoleOutMode)) != 0) { 501 Var_UpdateConMode (Private); 502 } 503 504 TerminalAttChange = FALSE; 505 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { 506 507 // 508 // only need update modified items 509 // 510 if (CompareMem (&NewBmmData->COMBaudRate[Index], &OldBmmData->COMBaudRate[Index], sizeof (NewBmmData->COMBaudRate[Index])) == 0 && 511 CompareMem (&NewBmmData->COMDataRate[Index], &OldBmmData->COMDataRate[Index], sizeof (NewBmmData->COMDataRate[Index])) == 0 && 512 CompareMem (&NewBmmData->COMStopBits[Index], &OldBmmData->COMStopBits[Index], sizeof (NewBmmData->COMStopBits[Index])) == 0 && 513 CompareMem (&NewBmmData->COMParity[Index], &OldBmmData->COMParity[Index], sizeof (NewBmmData->COMParity[Index])) == 0 && 514 CompareMem (&NewBmmData->COMTerminalType[Index], &OldBmmData->COMTerminalType[Index], sizeof (NewBmmData->COMTerminalType[Index])) == 0 && 515 CompareMem (&NewBmmData->COMFlowControl[Index], &OldBmmData->COMFlowControl[Index], sizeof (NewBmmData->COMFlowControl[Index])) == 0) { 516 continue; 517 } 518 519 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); 520 ASSERT (NewMenuEntry != NULL); 521 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; 522 NewTerminalContext->BaudRateIndex = NewBmmData->COMBaudRate[Index]; 523 ASSERT (NewBmmData->COMBaudRate[Index] < (ARRAY_SIZE (BaudRateList))); 524 NewTerminalContext->BaudRate = BaudRateList[NewBmmData->COMBaudRate[Index]].Value; 525 NewTerminalContext->DataBitsIndex = NewBmmData->COMDataRate[Index]; 526 ASSERT (NewBmmData->COMDataRate[Index] < (ARRAY_SIZE (DataBitsList))); 527 NewTerminalContext->DataBits = (UINT8) DataBitsList[NewBmmData->COMDataRate[Index]].Value; 528 NewTerminalContext->StopBitsIndex = NewBmmData->COMStopBits[Index]; 529 ASSERT (NewBmmData->COMStopBits[Index] < (ARRAY_SIZE (StopBitsList))); 530 NewTerminalContext->StopBits = (UINT8) StopBitsList[NewBmmData->COMStopBits[Index]].Value; 531 NewTerminalContext->ParityIndex = NewBmmData->COMParity[Index]; 532 ASSERT (NewBmmData->COMParity[Index] < (ARRAY_SIZE (ParityList))); 533 NewTerminalContext->Parity = (UINT8) ParityList[NewBmmData->COMParity[Index]].Value; 534 NewTerminalContext->TerminalType = NewBmmData->COMTerminalType[Index]; 535 NewTerminalContext->FlowControl = NewBmmData->COMFlowControl[Index]; 536 ChangeTerminalDevicePath ( 537 &(NewTerminalContext->DevicePath), 538 FALSE 539 ); 540 TerminalAttChange = TRUE; 541 } 542 if (TerminalAttChange) { 543 Var_UpdateConsoleInpOption (); 544 Var_UpdateConsoleOutOption (); 545 Var_UpdateErrorOutOption (); 546 } 547 548 // 549 // Check data which located in Console Options Menu and save the settings if need 550 // 551 if (CompareMem (NewBmmData->ConsoleInCheck, OldBmmData->ConsoleInCheck, sizeof (NewBmmData->ConsoleInCheck)) != 0) { 552 for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++) { 553 NewMenuEntry = BOpt_GetMenuEntry (&ConsoleInpMenu, Index); 554 NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; 555 ASSERT (Index < MAX_MENU_NUMBER); 556 NewConsoleContext->IsActive = NewBmmData->ConsoleInCheck[Index]; 557 } 558 559 Var_UpdateConsoleInpOption (); 560 } 561 562 if (CompareMem (NewBmmData->ConsoleOutCheck, OldBmmData->ConsoleOutCheck, sizeof (NewBmmData->ConsoleOutCheck)) != 0) { 563 for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++) { 564 NewMenuEntry = BOpt_GetMenuEntry (&ConsoleOutMenu, Index); 565 NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; 566 ASSERT (Index < MAX_MENU_NUMBER); 567 NewConsoleContext->IsActive = NewBmmData->ConsoleOutCheck[Index]; 568 } 569 570 Var_UpdateConsoleOutOption (); 571 } 572 573 if (CompareMem (NewBmmData->ConsoleErrCheck, OldBmmData->ConsoleErrCheck, sizeof (NewBmmData->ConsoleErrCheck)) != 0) { 574 for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++) { 575 NewMenuEntry = BOpt_GetMenuEntry (&ConsoleErrMenu, Index); 576 NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; 577 ASSERT (Index < MAX_MENU_NUMBER); 578 NewConsoleContext->IsActive = NewBmmData->ConsoleErrCheck[Index]; 579 } 580 581 Var_UpdateErrorOutOption (); 582 } 583 584 // 585 // After user do the save action, need to update OldBmmData. 586 // 587 CopyMem (OldBmmData, NewBmmData, sizeof (BMM_FAKE_NV_DATA)); 588 589 return EFI_SUCCESS; 590 } 591 592 /** 593 Create GoTo OP code into FORM_BOOT_LEGACY_DEVICE label for legacy boot option. 594 595 **/ 596 EFI_STATUS 597 InitializeLegacyBootOption ( 598 VOID 599 ) 600 { 601 RefreshUpdateData (); 602 mStartLabel->Number = FORM_BOOT_LEGACY_DEVICE_ID; 603 604 // 605 // If LegacyBios Protocol is installed, add 3 tags about legacy boot option 606 // in BootOption form: legacy FD/HD/CD/NET/BEV 607 // 608 HiiCreateGotoOpCode ( 609 mStartOpCodeHandle, 610 FORM_SET_FD_ORDER_ID, 611 STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE), 612 STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE), 613 EFI_IFR_FLAG_CALLBACK, 614 FORM_SET_FD_ORDER_ID 615 ); 616 617 HiiCreateGotoOpCode ( 618 mStartOpCodeHandle, 619 FORM_SET_HD_ORDER_ID, 620 STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE), 621 STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE), 622 EFI_IFR_FLAG_CALLBACK, 623 FORM_SET_HD_ORDER_ID 624 ); 625 626 HiiCreateGotoOpCode ( 627 mStartOpCodeHandle, 628 FORM_SET_CD_ORDER_ID, 629 STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE), 630 STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE), 631 EFI_IFR_FLAG_CALLBACK, 632 FORM_SET_CD_ORDER_ID 633 ); 634 635 HiiCreateGotoOpCode ( 636 mStartOpCodeHandle, 637 FORM_SET_NET_ORDER_ID, 638 STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE), 639 STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE), 640 EFI_IFR_FLAG_CALLBACK, 641 FORM_SET_NET_ORDER_ID 642 ); 643 644 HiiCreateGotoOpCode ( 645 mStartOpCodeHandle, 646 FORM_SET_BEV_ORDER_ID, 647 STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE), 648 STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE), 649 EFI_IFR_FLAG_CALLBACK, 650 FORM_SET_BEV_ORDER_ID 651 ); 652 653 HiiUpdateForm ( 654 mBmmCallbackInfo->BmmHiiHandle, 655 &gBootMaintFormSetGuid, 656 FORM_BOOT_SETUP_ID, 657 mStartOpCodeHandle, // Label FORM_BOOT_LEGACY_DEVICE_ID 658 mEndOpCodeHandle // LABEL_END 659 ); 660 661 return EFI_SUCCESS; 662 } 663 664 /** 665 This function processes the results of changes in configuration. 666 667 668 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. 669 @param Action Specifies the type of action taken by the browser. 670 @param QuestionId A unique value which is sent to the original exporting driver 671 so that it can identify the type of data to expect. 672 @param Type The type of value for the question. 673 @param Value A pointer to the data being sent to the original exporting driver. 674 @param ActionRequest On return, points to the action requested by the callback function. 675 676 @retval EFI_SUCCESS The callback successfully handled the action. 677 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. 678 @retval EFI_DEVICE_ERROR The variable could not be saved. 679 @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. 680 @retval EFI_INVALID_PARAMETER The parameter of Value or ActionRequest is invalid. 681 **/ 682 EFI_STATUS 683 EFIAPI 684 BootMaintCallback ( 685 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, 686 IN EFI_BROWSER_ACTION Action, 687 IN EFI_QUESTION_ID QuestionId, 688 IN UINT8 Type, 689 IN EFI_IFR_TYPE_VALUE *Value, 690 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest 691 ) 692 { 693 BMM_CALLBACK_DATA *Private; 694 BM_MENU_ENTRY *NewMenuEntry; 695 BMM_FAKE_NV_DATA *CurrentFakeNVMap; 696 EFI_STATUS Status; 697 UINTN OldValue; 698 UINTN NewValue; 699 UINTN Number; 700 UINTN Pos; 701 UINTN Bit; 702 UINT16 NewValuePos; 703 UINT16 Index3; 704 UINT16 Index2; 705 UINT16 Index; 706 UINT8 *OldLegacyDev; 707 UINT8 *NewLegacyDev; 708 UINT8 *DisMap; 709 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; 710 711 Private = BMM_CALLBACK_DATA_FROM_THIS (This); 712 if (Action == EFI_BROWSER_ACTION_FORM_OPEN && QuestionId == FORM_BOOT_SETUP_ID) { 713 // 714 // Initilize Form for legacy boot option. 715 // 716 Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios); 717 if (!EFI_ERROR (Status)) { 718 InitializeLegacyBootOption (); 719 } 720 721 return EFI_SUCCESS; 722 } 723 724 if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) { 725 // 726 // All other action return unsupported. 727 // 728 return EFI_UNSUPPORTED; 729 } 730 731 Status = EFI_SUCCESS; 732 OldValue = 0; 733 NewValue = 0; 734 Number = 0; 735 OldLegacyDev = NULL; 736 NewLegacyDev = NULL; 737 NewValuePos = 0; 738 DisMap = NULL; 739 740 Private = BMM_CALLBACK_DATA_FROM_THIS (This); 741 // 742 // Retrieve uncommitted data from Form Browser 743 // 744 CurrentFakeNVMap = &Private->BmmFakeNvData; 745 HiiGetBrowserData (&gBootMaintFormSetGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap); 746 if (Action == EFI_BROWSER_ACTION_CHANGING) { 747 if (Value == NULL) { 748 return EFI_INVALID_PARAMETER; 749 } 750 751 UpdatePageId (Private, QuestionId); 752 753 if (QuestionId < FILE_OPTION_OFFSET) { 754 if (QuestionId < CONFIG_OPTION_OFFSET) { 755 switch (QuestionId) { 756 case KEY_VALUE_BOOT_FROM_FILE: 757 Private->FeCurrentState = FileExplorerStateBootFromFile; 758 break; 759 760 case FORM_BOOT_ADD_ID: 761 Private->FeCurrentState = FileExplorerStateAddBootOption; 762 break; 763 764 case FORM_DRV_ADD_FILE_ID: 765 Private->FeCurrentState = FileExplorerStateAddDriverOptionState; 766 break; 767 768 case FORM_DRV_ADD_HANDLE_ID: 769 CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private); 770 UpdateDrvAddHandlePage (Private); 771 break; 772 773 case FORM_BOOT_DEL_ID: 774 CleanUpPage (FORM_BOOT_DEL_ID, Private); 775 UpdateBootDelPage (Private); 776 break; 777 778 case FORM_BOOT_CHG_ID: 779 case FORM_DRV_CHG_ID: 780 UpdatePageBody (QuestionId, Private); 781 break; 782 783 case FORM_DRV_DEL_ID: 784 CleanUpPage (FORM_DRV_DEL_ID, Private); 785 UpdateDrvDelPage (Private); 786 break; 787 788 case FORM_BOOT_NEXT_ID: 789 CleanUpPage (FORM_BOOT_NEXT_ID, Private); 790 UpdateBootNextPage (Private); 791 break; 792 793 case FORM_TIME_OUT_ID: 794 CleanUpPage (FORM_TIME_OUT_ID, Private); 795 UpdateTimeOutPage (Private); 796 break; 797 798 case FORM_CON_IN_ID: 799 case FORM_CON_OUT_ID: 800 case FORM_CON_ERR_ID: 801 UpdatePageBody (QuestionId, Private); 802 break; 803 804 case FORM_CON_MODE_ID: 805 CleanUpPage (FORM_CON_MODE_ID, Private); 806 UpdateConModePage (Private); 807 break; 808 809 case FORM_CON_COM_ID: 810 CleanUpPage (FORM_CON_COM_ID, Private); 811 UpdateConCOMPage (Private); 812 break; 813 814 case FORM_SET_FD_ORDER_ID: 815 case FORM_SET_HD_ORDER_ID: 816 case FORM_SET_CD_ORDER_ID: 817 case FORM_SET_NET_ORDER_ID: 818 case FORM_SET_BEV_ORDER_ID: 819 CleanUpPage (QuestionId, Private); 820 UpdateSetLegacyDeviceOrderPage (QuestionId, Private); 821 break; 822 823 default: 824 break; 825 } 826 } else if ((QuestionId >= TERMINAL_OPTION_OFFSET) && (QuestionId < CONSOLE_OPTION_OFFSET)) { 827 Index2 = (UINT16) (QuestionId - TERMINAL_OPTION_OFFSET); 828 Private->CurrentTerminal = Index2; 829 830 CleanUpPage (FORM_CON_COM_SETUP_ID, Private); 831 UpdateTerminalPage (Private); 832 833 } else if (QuestionId >= HANDLE_OPTION_OFFSET) { 834 Index2 = (UINT16) (QuestionId - HANDLE_OPTION_OFFSET); 835 836 NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index2); 837 ASSERT (NewMenuEntry != NULL); 838 Private->HandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext; 839 840 CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private); 841 842 Private->MenuEntry = NewMenuEntry; 843 Private->LoadContext->FilePathList = Private->HandleContext->DevicePath; 844 845 UpdateDriverAddHandleDescPage (Private); 846 } 847 } 848 } else if (Action == EFI_BROWSER_ACTION_CHANGED) { 849 if ((Value == NULL) || (ActionRequest == NULL)) { 850 return EFI_INVALID_PARAMETER; 851 } 852 if ((QuestionId >= BOOT_OPTION_DEL_QUESTION_ID) && (QuestionId < BOOT_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) { 853 if (Value->b){ 854 // 855 // Means user try to delete this boot option but not press F10 or "Commit Changes and Exit" menu. 856 // 857 CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = TRUE; 858 } else { 859 // 860 // Means user remove the old check status. 861 // 862 CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = FALSE; 863 } 864 } else if ((QuestionId >= DRIVER_OPTION_DEL_QUESTION_ID) && (QuestionId < DRIVER_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) { 865 if (Value->b){ 866 CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = TRUE; 867 } else { 868 CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = FALSE; 869 } 870 } else if ((QuestionId >= LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER)) { 871 // 872 // Update Select FD/HD/CD/NET/BEV Order Form 873 // 874 875 DisMap = Private->BmmOldFakeNVData.DisableMap; 876 877 if (QuestionId >= LEGACY_FD_QUESTION_ID && QuestionId < LEGACY_FD_QUESTION_ID + MAX_MENU_NUMBER) { 878 Number = (UINT16) LegacyFDMenu.MenuNumber; 879 OldLegacyDev = Private->BmmOldFakeNVData.LegacyFD; 880 NewLegacyDev = CurrentFakeNVMap->LegacyFD; 881 } else if (QuestionId >= LEGACY_HD_QUESTION_ID && QuestionId < LEGACY_HD_QUESTION_ID + MAX_MENU_NUMBER) { 882 Number = (UINT16) LegacyHDMenu.MenuNumber; 883 OldLegacyDev = Private->BmmOldFakeNVData.LegacyHD; 884 NewLegacyDev = CurrentFakeNVMap->LegacyHD; 885 } else if (QuestionId >= LEGACY_CD_QUESTION_ID && QuestionId < LEGACY_CD_QUESTION_ID + MAX_MENU_NUMBER) { 886 Number = (UINT16) LegacyCDMenu.MenuNumber; 887 OldLegacyDev = Private->BmmOldFakeNVData.LegacyCD; 888 NewLegacyDev = CurrentFakeNVMap->LegacyCD; 889 } else if (QuestionId >= LEGACY_NET_QUESTION_ID && QuestionId < LEGACY_NET_QUESTION_ID + MAX_MENU_NUMBER) { 890 Number = (UINT16) LegacyNETMenu.MenuNumber; 891 OldLegacyDev = Private->BmmOldFakeNVData.LegacyNET; 892 NewLegacyDev = CurrentFakeNVMap->LegacyNET; 893 } else if (QuestionId >= LEGACY_BEV_QUESTION_ID && QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER) { 894 Number = (UINT16) LegacyBEVMenu.MenuNumber; 895 OldLegacyDev = Private->BmmOldFakeNVData.LegacyBEV; 896 NewLegacyDev = CurrentFakeNVMap->LegacyBEV; 897 } 898 // 899 // First, find the different position 900 // if there is change, it should be only one 901 // 902 for (Index = 0; Index < Number; Index++) { 903 if (OldLegacyDev[Index] != NewLegacyDev[Index]) { 904 OldValue = OldLegacyDev[Index]; 905 NewValue = NewLegacyDev[Index]; 906 break; 907 } 908 } 909 910 if (Index != Number) { 911 // 912 // there is change, now process 913 // 914 if (0xFF == NewValue) { 915 // 916 // This item will be disable 917 // Just move the items behind this forward to overlap it 918 // 919 Pos = OldValue / 8; 920 Bit = 7 - (OldValue % 8); 921 DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); 922 for (Index2 = Index; Index2 < Number - 1; Index2++) { 923 NewLegacyDev[Index2] = NewLegacyDev[Index2 + 1]; 924 } 925 926 NewLegacyDev[Index2] = 0xFF; 927 } else { 928 for (Index2 = 0; Index2 < Number; Index2++) { 929 if (Index2 == Index) { 930 continue; 931 } 932 933 if (OldLegacyDev[Index2] == NewValue) { 934 // 935 // If NewValue is in OldLegacyDev array 936 // remember its old position 937 // 938 NewValuePos = Index2; 939 break; 940 } 941 } 942 943 if (Index2 != Number) { 944 // 945 // We will change current item to an existing item 946 // (It's hard to describe here, please read code, it's like a cycle-moving) 947 // 948 for (Index2 = NewValuePos; Index2 != Index;) { 949 if (NewValuePos < Index) { 950 NewLegacyDev[Index2] = OldLegacyDev[Index2 + 1]; 951 Index2++; 952 } else { 953 NewLegacyDev[Index2] = OldLegacyDev[Index2 - 1]; 954 Index2--; 955 } 956 } 957 } else { 958 // 959 // If NewValue is not in OldlegacyDev array, we are changing to a disabled item 960 // so we should modify DisMap to reflect the change 961 // 962 Pos = NewValue / 8; 963 Bit = 7 - (NewValue % 8); 964 DisMap[Pos] = (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit))); 965 if (0xFF != OldValue) { 966 // 967 // Because NewValue is a item that was disabled before 968 // so after changing the OldValue should be disabled 969 // actually we are doing a swap of enable-disable states of two items 970 // 971 Pos = OldValue / 8; 972 Bit = 7 - (OldValue % 8); 973 DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); 974 } 975 } 976 } 977 // 978 // To prevent DISABLE appears in the middle of the list 979 // we should perform a re-ordering 980 // 981 Index3 = Index; 982 Index = 0; 983 while (Index < Number) { 984 if (0xFF != NewLegacyDev[Index]) { 985 Index++; 986 continue; 987 } 988 989 Index2 = Index; 990 Index2++; 991 while (Index2 < Number) { 992 if (0xFF != NewLegacyDev[Index2]) { 993 break; 994 } 995 996 Index2++; 997 } 998 999 if (Index2 < Number) { 1000 NewLegacyDev[Index] = NewLegacyDev[Index2]; 1001 NewLegacyDev[Index2] = 0xFF; 1002 } 1003 1004 Index++; 1005 } 1006 1007 // 1008 // Return correct question value. 1009 // 1010 Value->u8 = NewLegacyDev[Index3]; 1011 } 1012 } else { 1013 switch (QuestionId) { 1014 case KEY_VALUE_SAVE_AND_EXIT: 1015 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; 1016 break; 1017 1018 case KEY_VALUE_NO_SAVE_AND_EXIT: 1019 // 1020 // Restore local maintain data. 1021 // 1022 DiscardChangeHandler (Private, CurrentFakeNVMap); 1023 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT; 1024 break; 1025 1026 case FORM_RESET: 1027 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); 1028 return EFI_UNSUPPORTED; 1029 1030 default: 1031 break; 1032 } 1033 } 1034 } 1035 1036 // 1037 // Pass changed uncommitted data back to Form Browser 1038 // 1039 HiiSetBrowserData (&gBootMaintFormSetGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap, NULL); 1040 return EFI_SUCCESS; 1041 } 1042 1043 /** 1044 Discard all changes done to the BMM pages such as Boot Order change, 1045 Driver order change. 1046 1047 @param Private The BMM context data. 1048 @param CurrentFakeNVMap The current Fack NV Map. 1049 1050 **/ 1051 VOID 1052 DiscardChangeHandler ( 1053 IN BMM_CALLBACK_DATA *Private, 1054 IN BMM_FAKE_NV_DATA *CurrentFakeNVMap 1055 ) 1056 { 1057 UINT16 Index; 1058 1059 switch (Private->BmmPreviousPageId) { 1060 case FORM_BOOT_CHG_ID: 1061 CopyMem (CurrentFakeNVMap->BootOptionOrder, Private->BmmOldFakeNVData.BootOptionOrder, sizeof (CurrentFakeNVMap->BootOptionOrder)); 1062 break; 1063 1064 case FORM_DRV_CHG_ID: 1065 CopyMem (CurrentFakeNVMap->DriverOptionOrder, Private->BmmOldFakeNVData.DriverOptionOrder, sizeof (CurrentFakeNVMap->DriverOptionOrder)); 1066 break; 1067 1068 case FORM_BOOT_DEL_ID: 1069 ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->BootOptionDel) / sizeof (CurrentFakeNVMap->BootOptionDel[0]))); 1070 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { 1071 CurrentFakeNVMap->BootOptionDel[Index] = FALSE; 1072 CurrentFakeNVMap->BootOptionDelMark[Index] = FALSE; 1073 } 1074 break; 1075 1076 case FORM_DRV_DEL_ID: 1077 ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->DriverOptionDel) / sizeof (CurrentFakeNVMap->DriverOptionDel[0]))); 1078 for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { 1079 CurrentFakeNVMap->DriverOptionDel[Index] = FALSE; 1080 CurrentFakeNVMap->DriverOptionDelMark[Index] = FALSE; 1081 } 1082 break; 1083 1084 case FORM_BOOT_NEXT_ID: 1085 CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext; 1086 break; 1087 1088 case FORM_TIME_OUT_ID: 1089 CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut; 1090 break; 1091 1092 case FORM_DRV_ADD_HANDLE_DESC_ID: 1093 case FORM_DRV_ADD_FILE_ID: 1094 case FORM_DRV_ADD_HANDLE_ID: 1095 CurrentFakeNVMap->DriverAddHandleDesc[0] = 0x0000; 1096 CurrentFakeNVMap->DriverAddHandleOptionalData[0] = 0x0000; 1097 break; 1098 1099 default: 1100 break; 1101 } 1102 } 1103 1104 /** 1105 Initialize the Boot Maintenance Utitliy. 1106 1107 1108 @retval EFI_SUCCESS utility ended successfully 1109 @retval others contain some errors 1110 1111 **/ 1112 EFI_STATUS 1113 InitializeBM ( 1114 VOID 1115 ) 1116 { 1117 BMM_CALLBACK_DATA *BmmCallbackInfo; 1118 EFI_STATUS Status; 1119 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader; 1120 UINT32 Length; 1121 UINT8 *Data; 1122 1123 Status = EFI_SUCCESS; 1124 BmmCallbackInfo = mBmmCallbackInfo; 1125 1126 BmmCallbackInfo->BmmPreviousPageId = FORM_MAIN_ID; 1127 BmmCallbackInfo->BmmCurrentPageId = FORM_MAIN_ID; 1128 BmmCallbackInfo->FeCurrentState = FileExplorerStateInActive; 1129 BmmCallbackInfo->FeDisplayContext = FileExplorerDisplayUnknown; 1130 1131 // 1132 // Reinstall String packages to include more new strings. 1133 // 1134 1135 // 1136 // String package size 1137 // 1138 Length = ReadUnaligned32 ((UINT32 *) BdsDxeStrings) - sizeof (UINT32); 1139 1140 // 1141 // Add the length of the Package List Header and the terminating Package Header 1142 // 1143 Length += sizeof (EFI_HII_PACKAGE_LIST_HEADER) + sizeof (EFI_HII_PACKAGE_HEADER); 1144 1145 // 1146 // Allocate the storage for the entire Package List 1147 // 1148 PackageListHeader = AllocateZeroPool (Length); 1149 1150 // 1151 // If the Package List can not be allocated, then return a NULL HII Handle 1152 // 1153 if (PackageListHeader == NULL) { 1154 return EFI_OUT_OF_RESOURCES; 1155 } 1156 1157 // 1158 // Fill in the GUID and Length of the Package List Header 1159 // 1160 PackageListHeader->PackageLength = Length; 1161 1162 // 1163 // Copy String Data into Package list. 1164 // 1165 Data = (UINT8 *)(PackageListHeader + 1); 1166 Length = ReadUnaligned32 ((UINT32 *) BdsDxeStrings) - sizeof (UINT32); 1167 CopyMem (Data, (UINT8 *) BdsDxeStrings + sizeof (UINT32), Length); 1168 1169 // 1170 // Add End type HII package. 1171 // 1172 Data += Length; 1173 ((EFI_HII_PACKAGE_HEADER *) Data)->Type = EFI_HII_PACKAGE_END; 1174 ((EFI_HII_PACKAGE_HEADER *) Data)->Length = sizeof (EFI_HII_PACKAGE_HEADER); 1175 1176 // 1177 // Update String package for BM 1178 // 1179 CopyGuid (&PackageListHeader->PackageListGuid, &gBootMaintFormSetGuid); 1180 Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, BmmCallbackInfo->BmmHiiHandle, PackageListHeader); 1181 1182 // 1183 // Update String package for FE. 1184 // 1185 CopyGuid (&PackageListHeader->PackageListGuid, &gFileExploreFormSetGuid); 1186 Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, BmmCallbackInfo->FeHiiHandle, PackageListHeader); 1187 1188 FreePool (PackageListHeader); 1189 1190 // 1191 // Init OpCode Handle and Allocate space for creation of Buffer 1192 // 1193 mStartOpCodeHandle = HiiAllocateOpCodeHandle (); 1194 if (mStartOpCodeHandle == NULL) { 1195 Status = EFI_OUT_OF_RESOURCES; 1196 goto Exit; 1197 } 1198 1199 mEndOpCodeHandle = HiiAllocateOpCodeHandle (); 1200 if (mEndOpCodeHandle == NULL) { 1201 Status = EFI_OUT_OF_RESOURCES; 1202 goto Exit; 1203 } 1204 1205 // 1206 // Create Hii Extend Label OpCode as the start opcode 1207 // 1208 mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mStartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); 1209 mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; 1210 1211 // 1212 // Create Hii Extend Label OpCode as the end opcode 1213 // 1214 mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mEndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); 1215 mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; 1216 mEndLabel->Number = LABEL_END; 1217 1218 InitializeStringDepository (); 1219 1220 InitAllMenu (BmmCallbackInfo); 1221 1222 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleInpMenu); 1223 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleOutMenu); 1224 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleErrMenu); 1225 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &BootOptionMenu); 1226 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverOptionMenu); 1227 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &TerminalMenu); 1228 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverMenu); 1229 1230 InitializeBmmConfig (BmmCallbackInfo); 1231 1232 // 1233 // Dispatch BMM main formset and File Explorer formset. 1234 // 1235 FormSetDispatcher (BmmCallbackInfo); 1236 1237 // 1238 // Clean up. 1239 // 1240 CleanUpStringDepository (); 1241 1242 FreeAllMenu (); 1243 1244 Exit: 1245 if (mStartOpCodeHandle != NULL) { 1246 HiiFreeOpCodeHandle (mStartOpCodeHandle); 1247 } 1248 1249 if (mEndOpCodeHandle != NULL) { 1250 HiiFreeOpCodeHandle (mEndOpCodeHandle); 1251 } 1252 1253 return Status; 1254 } 1255 1256 1257 /** 1258 Initialized all Menu Option List. 1259 1260 @param CallbackData The BMM context data. 1261 1262 **/ 1263 VOID 1264 InitAllMenu ( 1265 IN BMM_CALLBACK_DATA *CallbackData 1266 ) 1267 { 1268 InitializeListHead (&BootOptionMenu.Head); 1269 InitializeListHead (&DriverOptionMenu.Head); 1270 BOpt_GetBootOptions (CallbackData); 1271 BOpt_GetDriverOptions (CallbackData); 1272 BOpt_GetLegacyOptions (); 1273 InitializeListHead (&FsOptionMenu.Head); 1274 BOpt_FindDrivers (); 1275 InitializeListHead (&DirectoryMenu.Head); 1276 InitializeListHead (&ConsoleInpMenu.Head); 1277 InitializeListHead (&ConsoleOutMenu.Head); 1278 InitializeListHead (&ConsoleErrMenu.Head); 1279 InitializeListHead (&TerminalMenu.Head); 1280 LocateSerialIo (); 1281 GetAllConsoles (); 1282 } 1283 1284 /** 1285 Free up all Menu Option list. 1286 1287 **/ 1288 VOID 1289 FreeAllMenu ( 1290 VOID 1291 ) 1292 { 1293 BOpt_FreeMenu (&DirectoryMenu); 1294 BOpt_FreeMenu (&FsOptionMenu); 1295 BOpt_FreeMenu (&BootOptionMenu); 1296 BOpt_FreeMenu (&DriverOptionMenu); 1297 BOpt_FreeMenu (&DriverMenu); 1298 BOpt_FreeLegacyOptions (); 1299 FreeAllConsoles (); 1300 } 1301 1302 /** 1303 Initialize all the string depositories. 1304 1305 **/ 1306 VOID 1307 InitializeStringDepository ( 1308 VOID 1309 ) 1310 { 1311 STRING_DEPOSITORY *StringDepository; 1312 StringDepository = AllocateZeroPool (sizeof (STRING_DEPOSITORY) * STRING_DEPOSITORY_NUMBER); 1313 FileOptionStrDepository = StringDepository++; 1314 ConsoleOptionStrDepository = StringDepository++; 1315 BootOptionStrDepository = StringDepository++; 1316 BootOptionHelpStrDepository = StringDepository++; 1317 DriverOptionStrDepository = StringDepository++; 1318 DriverOptionHelpStrDepository = StringDepository++; 1319 TerminalStrDepository = StringDepository; 1320 } 1321 1322 /** 1323 Fetch a usable string node from the string depository and return the string token. 1324 1325 @param CallbackData The BMM context data. 1326 @param StringDepository The string repository. 1327 1328 @retval EFI_STRING_ID String token. 1329 1330 **/ 1331 EFI_STRING_ID 1332 GetStringTokenFromDepository ( 1333 IN BMM_CALLBACK_DATA *CallbackData, 1334 IN STRING_DEPOSITORY *StringDepository 1335 ) 1336 { 1337 STRING_LIST_NODE *CurrentListNode; 1338 STRING_LIST_NODE *NextListNode; 1339 1340 CurrentListNode = StringDepository->CurrentNode; 1341 1342 if ((NULL != CurrentListNode) && (NULL != CurrentListNode->Next)) { 1343 // 1344 // Fetch one reclaimed node from the list. 1345 // 1346 NextListNode = StringDepository->CurrentNode->Next; 1347 } else { 1348 // 1349 // If there is no usable node in the list, update the list. 1350 // 1351 NextListNode = AllocateZeroPool (sizeof (STRING_LIST_NODE)); 1352 ASSERT (NextListNode != NULL); 1353 NextListNode->StringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, L" ", NULL); 1354 ASSERT (NextListNode->StringToken != 0); 1355 1356 StringDepository->TotalNodeNumber++; 1357 1358 if (NULL == CurrentListNode) { 1359 StringDepository->ListHead = NextListNode; 1360 } else { 1361 CurrentListNode->Next = NextListNode; 1362 } 1363 } 1364 1365 StringDepository->CurrentNode = NextListNode; 1366 1367 return StringDepository->CurrentNode->StringToken; 1368 } 1369 1370 /** 1371 Reclaim string depositories by moving the current node pointer to list head.. 1372 1373 **/ 1374 VOID 1375 ReclaimStringDepository ( 1376 VOID 1377 ) 1378 { 1379 UINTN DepositoryIndex; 1380 STRING_DEPOSITORY *StringDepository; 1381 1382 StringDepository = FileOptionStrDepository; 1383 for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) { 1384 StringDepository->CurrentNode = StringDepository->ListHead; 1385 StringDepository++; 1386 } 1387 } 1388 1389 /** 1390 Release resource for all the string depositories. 1391 1392 **/ 1393 VOID 1394 CleanUpStringDepository ( 1395 VOID 1396 ) 1397 { 1398 UINTN NodeIndex; 1399 UINTN DepositoryIndex; 1400 STRING_LIST_NODE *CurrentListNode; 1401 STRING_LIST_NODE *NextListNode; 1402 STRING_DEPOSITORY *StringDepository; 1403 1404 // 1405 // Release string list nodes. 1406 // 1407 StringDepository = FileOptionStrDepository; 1408 for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) { 1409 CurrentListNode = StringDepository->ListHead; 1410 for (NodeIndex = 0; NodeIndex < StringDepository->TotalNodeNumber; NodeIndex++) { 1411 NextListNode = CurrentListNode->Next; 1412 FreePool (CurrentListNode); 1413 CurrentListNode = NextListNode; 1414 } 1415 1416 StringDepository++; 1417 } 1418 // 1419 // Release string depository. 1420 // 1421 FreePool (FileOptionStrDepository); 1422 } 1423 1424 /** 1425 Start boot maintenance manager 1426 1427 @retval EFI_SUCCESS If BMM is invoked successfully. 1428 @return Other value if BMM return unsuccessfully. 1429 1430 **/ 1431 EFI_STATUS 1432 BdsStartBootMaint ( 1433 VOID 1434 ) 1435 { 1436 EFI_STATUS Status; 1437 LIST_ENTRY BdsBootOptionList; 1438 1439 InitializeListHead (&BdsBootOptionList); 1440 1441 // 1442 // Connect all prior to entering the platform setup menu. 1443 // 1444 if (!gConnectAllHappened) { 1445 BdsLibConnectAllDriversToAllControllers (); 1446 gConnectAllHappened = TRUE; 1447 } 1448 // 1449 // Have chance to enumerate boot device 1450 // 1451 BdsLibEnumerateAllBootOption (&BdsBootOptionList); 1452 1453 // 1454 // Group the legacy boot options for the same device type 1455 // 1456 GroupMultipleLegacyBootOption4SameType (); 1457 1458 // 1459 // Init the BMM 1460 // 1461 Status = InitializeBM (); 1462 1463 return Status; 1464 } 1465 1466 /** 1467 Dispatch BMM formset and FileExplorer formset. 1468 1469 1470 @param CallbackData The BMM context data. 1471 1472 @retval EFI_SUCCESS If function complete successfully. 1473 @return Other value if the Setup Browser process BMM's pages and 1474 return unsuccessfully. 1475 1476 **/ 1477 EFI_STATUS 1478 FormSetDispatcher ( 1479 IN BMM_CALLBACK_DATA *CallbackData 1480 ) 1481 { 1482 EFI_STATUS Status; 1483 EFI_BROWSER_ACTION_REQUEST ActionRequest; 1484 1485 while (TRUE) { 1486 UpdatePageId (CallbackData, FORM_MAIN_ID); 1487 1488 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; 1489 Status = gFormBrowser2->SendForm ( 1490 gFormBrowser2, 1491 &CallbackData->BmmHiiHandle, 1492 1, 1493 &gBootMaintFormSetGuid, 1494 0, 1495 NULL, 1496 &ActionRequest 1497 ); 1498 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { 1499 EnableResetRequired (); 1500 } 1501 1502 ReclaimStringDepository (); 1503 1504 // 1505 // When this Formset returns, check if we are going to explore files. 1506 // 1507 if (FileExplorerStateInActive != CallbackData->FeCurrentState) { 1508 UpdateFileExplorer (CallbackData, 0); 1509 1510 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; 1511 Status = gFormBrowser2->SendForm ( 1512 gFormBrowser2, 1513 &CallbackData->FeHiiHandle, 1514 1, 1515 &gFileExploreFormSetGuid, 1516 0, 1517 NULL, 1518 &ActionRequest 1519 ); 1520 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { 1521 EnableResetRequired (); 1522 } 1523 1524 CallbackData->FeCurrentState = FileExplorerStateInActive; 1525 CallbackData->FeDisplayContext = FileExplorerDisplayUnknown; 1526 ReclaimStringDepository (); 1527 } else { 1528 break; 1529 } 1530 } 1531 1532 return Status; 1533 } 1534 1535 /** 1536 Intall BootMaint and FileExplorer HiiPackages. 1537 1538 **/ 1539 EFI_STATUS 1540 InitBMPackage ( 1541 VOID 1542 ) 1543 { 1544 BMM_CALLBACK_DATA *BmmCallbackInfo; 1545 EFI_STATUS Status; 1546 UINT8 *Ptr; 1547 1548 // 1549 // Create CallbackData structures for Driver Callback 1550 // 1551 BmmCallbackInfo = AllocateZeroPool (sizeof (BMM_CALLBACK_DATA)); 1552 if (BmmCallbackInfo == NULL) { 1553 return EFI_OUT_OF_RESOURCES; 1554 } 1555 1556 // 1557 // Create LoadOption in BmmCallbackInfo for Driver Callback 1558 // 1559 Ptr = AllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY)); 1560 if (Ptr == NULL) { 1561 FreePool (BmmCallbackInfo); 1562 BmmCallbackInfo = NULL; 1563 return EFI_OUT_OF_RESOURCES; 1564 } 1565 // 1566 // Initialize Bmm callback data. 1567 // 1568 BmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr; 1569 Ptr += sizeof (BM_LOAD_CONTEXT); 1570 1571 BmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr; 1572 Ptr += sizeof (BM_FILE_CONTEXT); 1573 1574 BmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr; 1575 Ptr += sizeof (BM_HANDLE_CONTEXT); 1576 1577 BmmCallbackInfo->MenuEntry = (BM_MENU_ENTRY *) Ptr; 1578 1579 BmmCallbackInfo->Signature = BMM_CALLBACK_DATA_SIGNATURE; 1580 BmmCallbackInfo->BmmConfigAccess.ExtractConfig = BootMaintExtractConfig; 1581 BmmCallbackInfo->BmmConfigAccess.RouteConfig = BootMaintRouteConfig; 1582 BmmCallbackInfo->BmmConfigAccess.Callback = BootMaintCallback; 1583 BmmCallbackInfo->FeConfigAccess.ExtractConfig = FakeExtractConfig; 1584 BmmCallbackInfo->FeConfigAccess.RouteConfig = FileExplorerRouteConfig; 1585 BmmCallbackInfo->FeConfigAccess.Callback = FileExplorerCallback; 1586 1587 // 1588 // Install Device Path Protocol and Config Access protocol to driver handle 1589 // 1590 Status = gBS->InstallMultipleProtocolInterfaces ( 1591 &BmmCallbackInfo->BmmDriverHandle, 1592 &gEfiDevicePathProtocolGuid, 1593 &mBmmHiiVendorDevicePath, 1594 &gEfiHiiConfigAccessProtocolGuid, 1595 &BmmCallbackInfo->BmmConfigAccess, 1596 NULL 1597 ); 1598 ASSERT_EFI_ERROR (Status); 1599 1600 // 1601 // Install Device Path Protocol and Config Access protocol to driver handle 1602 // 1603 Status = gBS->InstallMultipleProtocolInterfaces ( 1604 &BmmCallbackInfo->FeDriverHandle, 1605 &gEfiDevicePathProtocolGuid, 1606 &mFeHiiVendorDevicePath, 1607 &gEfiHiiConfigAccessProtocolGuid, 1608 &BmmCallbackInfo->FeConfigAccess, 1609 NULL 1610 ); 1611 ASSERT_EFI_ERROR (Status); 1612 1613 // 1614 // Post our Boot Maint VFR binary to the HII database. 1615 // 1616 BmmCallbackInfo->BmmHiiHandle = HiiAddPackages ( 1617 &gBootMaintFormSetGuid, 1618 BmmCallbackInfo->BmmDriverHandle, 1619 BmBin, 1620 BdsDxeStrings, 1621 NULL 1622 ); 1623 ASSERT (BmmCallbackInfo->BmmHiiHandle != NULL); 1624 1625 // 1626 // Post our File Explorer VFR binary to the HII database. 1627 // 1628 BmmCallbackInfo->FeHiiHandle = HiiAddPackages ( 1629 &gFileExploreFormSetGuid, 1630 BmmCallbackInfo->FeDriverHandle, 1631 FEBin, 1632 BdsDxeStrings, 1633 NULL 1634 ); 1635 ASSERT (BmmCallbackInfo->FeHiiHandle != NULL); 1636 1637 mBmmCallbackInfo = BmmCallbackInfo; 1638 1639 return EFI_SUCCESS; 1640 } 1641 1642 /** 1643 Remvoe the intalled BootMaint and FileExplorer HiiPackages. 1644 1645 **/ 1646 VOID 1647 FreeBMPackage ( 1648 VOID 1649 ) 1650 { 1651 BMM_CALLBACK_DATA *BmmCallbackInfo; 1652 1653 BmmCallbackInfo = mBmmCallbackInfo; 1654 1655 // 1656 // Remove our IFR data from HII database 1657 // 1658 HiiRemovePackages (BmmCallbackInfo->BmmHiiHandle); 1659 HiiRemovePackages (BmmCallbackInfo->FeHiiHandle); 1660 1661 if (BmmCallbackInfo->FeDriverHandle != NULL) { 1662 gBS->UninstallMultipleProtocolInterfaces ( 1663 BmmCallbackInfo->FeDriverHandle, 1664 &gEfiDevicePathProtocolGuid, 1665 &mFeHiiVendorDevicePath, 1666 &gEfiHiiConfigAccessProtocolGuid, 1667 &BmmCallbackInfo->FeConfigAccess, 1668 NULL 1669 ); 1670 } 1671 1672 if (BmmCallbackInfo->BmmDriverHandle != NULL) { 1673 gBS->UninstallMultipleProtocolInterfaces ( 1674 BmmCallbackInfo->BmmDriverHandle, 1675 &gEfiDevicePathProtocolGuid, 1676 &mBmmHiiVendorDevicePath, 1677 &gEfiHiiConfigAccessProtocolGuid, 1678 &BmmCallbackInfo->BmmConfigAccess, 1679 NULL 1680 ); 1681 } 1682 1683 FreePool (BmmCallbackInfo->LoadContext); 1684 FreePool (BmmCallbackInfo); 1685 1686 mBmmCallbackInfo = NULL; 1687 1688 return; 1689 } 1690 1691