1 /** @file 2 The boot manager reference implementation 3 4 Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials are licensed and made available under 6 the terms and conditions of the BSD License that accompanies this distribution. 7 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 "BootManager.h" 16 17 UINT16 mKeyInput; 18 EFI_GUID mBootManagerGuid = BOOT_MANAGER_FORMSET_GUID; 19 // 20 // Boot video resolution and text mode. 21 // 22 UINT32 mBmBootHorizontalResolution = 0; 23 UINT32 mBmBootVerticalResolution = 0; 24 UINT32 mBmBootTextModeColumn = 0; 25 UINT32 mBmBootTextModeRow = 0; 26 // 27 // BIOS setup video resolution and text mode. 28 // 29 UINT32 mBmSetupTextModeColumn = 0; 30 UINT32 mBmSetupTextModeRow = 0; 31 UINT32 mBmSetupHorizontalResolution = 0; 32 UINT32 mBmSetupVerticalResolution = 0; 33 34 CHAR16 *mDeviceTypeStr[] = { 35 L"Legacy BEV", 36 L"Legacy Floppy", 37 L"Legacy Hard Drive", 38 L"Legacy CD ROM", 39 L"Legacy PCMCIA", 40 L"Legacy USB", 41 L"Legacy Embedded Network", 42 L"Legacy Unknown Device" 43 }; 44 45 HII_VENDOR_DEVICE_PATH mBootManagerHiiVendorDevicePath = { 46 { 47 { 48 HARDWARE_DEVICE_PATH, 49 HW_VENDOR_DP, 50 { 51 (UINT8) (sizeof (VENDOR_DEVICE_PATH)), 52 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) 53 } 54 }, 55 // 56 // {1DDDBE15-481D-4d2b-8277-B191EAF66525} 57 // 58 { 0x1dddbe15, 0x481d, 0x4d2b, { 0x82, 0x77, 0xb1, 0x91, 0xea, 0xf6, 0x65, 0x25 } } 59 }, 60 { 61 END_DEVICE_PATH_TYPE, 62 END_ENTIRE_DEVICE_PATH_SUBTYPE, 63 { 64 (UINT8) (END_DEVICE_PATH_LENGTH), 65 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) 66 } 67 } 68 }; 69 70 BOOT_MANAGER_CALLBACK_DATA gBootManagerPrivate = { 71 BOOT_MANAGER_CALLBACK_DATA_SIGNATURE, 72 NULL, 73 NULL, 74 { 75 BootManagerExtractConfig, 76 BootManagerRouteConfig, 77 BootManagerCallback 78 } 79 }; 80 81 /** 82 This function will change video resolution and text mode 83 according to defined setup mode or defined boot mode 84 85 @param IsSetupMode Indicate mode is changed to setup mode or boot mode. 86 87 @retval EFI_SUCCESS Mode is changed successfully. 88 @retval Others Mode failed to be changed. 89 90 **/ 91 EFI_STATUS 92 EFIAPI 93 BmBdsSetConsoleMode ( 94 BOOLEAN IsSetupMode 95 ) 96 { 97 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; 98 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut; 99 UINTN SizeOfInfo; 100 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; 101 UINT32 MaxGopMode; 102 UINT32 MaxTextMode; 103 UINT32 ModeNumber; 104 UINT32 NewHorizontalResolution; 105 UINT32 NewVerticalResolution; 106 UINT32 NewColumns; 107 UINT32 NewRows; 108 UINTN HandleCount; 109 EFI_HANDLE *HandleBuffer; 110 EFI_STATUS Status; 111 UINTN Index; 112 UINTN CurrentColumn; 113 UINTN CurrentRow; 114 115 MaxGopMode = 0; 116 MaxTextMode = 0; 117 118 // 119 // Get current video resolution and text mode 120 // 121 Status = gBS->HandleProtocol ( 122 gST->ConsoleOutHandle, 123 &gEfiGraphicsOutputProtocolGuid, 124 (VOID**)&GraphicsOutput 125 ); 126 if (EFI_ERROR (Status)) { 127 GraphicsOutput = NULL; 128 } 129 130 Status = gBS->HandleProtocol ( 131 gST->ConsoleOutHandle, 132 &gEfiSimpleTextOutProtocolGuid, 133 (VOID**)&SimpleTextOut 134 ); 135 if (EFI_ERROR (Status)) { 136 SimpleTextOut = NULL; 137 } 138 139 if ((GraphicsOutput == NULL) || (SimpleTextOut == NULL)) { 140 return EFI_UNSUPPORTED; 141 } 142 143 if (IsSetupMode) { 144 // 145 // The requried resolution and text mode is setup mode. 146 // 147 NewHorizontalResolution = mBmSetupHorizontalResolution; 148 NewVerticalResolution = mBmSetupVerticalResolution; 149 NewColumns = mBmSetupTextModeColumn; 150 NewRows = mBmSetupTextModeRow; 151 } else { 152 // 153 // The required resolution and text mode is boot mode. 154 // 155 NewHorizontalResolution = mBmBootHorizontalResolution; 156 NewVerticalResolution = mBmBootVerticalResolution; 157 NewColumns = mBmBootTextModeColumn; 158 NewRows = mBmBootTextModeRow; 159 } 160 161 if (GraphicsOutput != NULL) { 162 MaxGopMode = GraphicsOutput->Mode->MaxMode; 163 } 164 165 if (SimpleTextOut != NULL) { 166 MaxTextMode = SimpleTextOut->Mode->MaxMode; 167 } 168 169 // 170 // 1. If current video resolution is same with required video resolution, 171 // video resolution need not be changed. 172 // 1.1. If current text mode is same with required text mode, text mode need not be changed. 173 // 1.2. If current text mode is different from required text mode, text mode need be changed. 174 // 2. If current video resolution is different from required video resolution, we need restart whole console drivers. 175 // 176 for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) { 177 Status = GraphicsOutput->QueryMode ( 178 GraphicsOutput, 179 ModeNumber, 180 &SizeOfInfo, 181 &Info 182 ); 183 if (!EFI_ERROR (Status)) { 184 if ((Info->HorizontalResolution == NewHorizontalResolution) && 185 (Info->VerticalResolution == NewVerticalResolution)) { 186 if ((GraphicsOutput->Mode->Info->HorizontalResolution == NewHorizontalResolution) && 187 (GraphicsOutput->Mode->Info->VerticalResolution == NewVerticalResolution)) { 188 // 189 // Current resolution is same with required resolution, check if text mode need be set 190 // 191 Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow); 192 ASSERT_EFI_ERROR (Status); 193 if (CurrentColumn == NewColumns && CurrentRow == NewRows) { 194 // 195 // If current text mode is same with required text mode. Do nothing 196 // 197 FreePool (Info); 198 return EFI_SUCCESS; 199 } else { 200 // 201 // If current text mode is different from requried text mode. Set new video mode 202 // 203 for (Index = 0; Index < MaxTextMode; Index++) { 204 Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow); 205 if (!EFI_ERROR(Status)) { 206 if ((CurrentColumn == NewColumns) && (CurrentRow == NewRows)) { 207 // 208 // Required text mode is supported, set it. 209 // 210 Status = SimpleTextOut->SetMode (SimpleTextOut, Index); 211 ASSERT_EFI_ERROR (Status); 212 // 213 // Update text mode PCD. 214 // 215 Status = PcdSet32S (PcdConOutColumn, mBmSetupTextModeColumn); 216 ASSERT_EFI_ERROR (Status); 217 Status = PcdSet32S (PcdConOutRow, mBmSetupTextModeRow); 218 ASSERT_EFI_ERROR (Status); 219 FreePool (Info); 220 return EFI_SUCCESS; 221 } 222 } 223 } 224 if (Index == MaxTextMode) { 225 // 226 // If requried text mode is not supported, return error. 227 // 228 FreePool (Info); 229 return EFI_UNSUPPORTED; 230 } 231 } 232 } else { 233 // 234 // If current video resolution is not same with the new one, set new video resolution. 235 // In this case, the driver which produces simple text out need be restarted. 236 // 237 Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber); 238 if (!EFI_ERROR (Status)) { 239 FreePool (Info); 240 break; 241 } 242 } 243 } 244 FreePool (Info); 245 } 246 } 247 248 if (ModeNumber == MaxGopMode) { 249 // 250 // If the resolution is not supported, return error. 251 // 252 return EFI_UNSUPPORTED; 253 } 254 255 // 256 // Set PCD to Inform GraphicsConsole to change video resolution. 257 // Set PCD to Inform Consplitter to change text mode. 258 // 259 Status = PcdSet32S (PcdVideoHorizontalResolution, NewHorizontalResolution); 260 ASSERT_EFI_ERROR (Status); 261 Status = PcdSet32S (PcdVideoVerticalResolution, NewVerticalResolution); 262 ASSERT_EFI_ERROR (Status); 263 Status = PcdSet32S (PcdConOutColumn, NewColumns); 264 ASSERT_EFI_ERROR (Status); 265 Status = PcdSet32S (PcdConOutRow, NewRows); 266 ASSERT_EFI_ERROR (Status); 267 268 // 269 // Video mode is changed, so restart graphics console driver and higher level driver. 270 // Reconnect graphics console driver and higher level driver. 271 // Locate all the handles with GOP protocol and reconnect it. 272 // 273 Status = gBS->LocateHandleBuffer ( 274 ByProtocol, 275 &gEfiSimpleTextOutProtocolGuid, 276 NULL, 277 &HandleCount, 278 &HandleBuffer 279 ); 280 if (!EFI_ERROR (Status)) { 281 for (Index = 0; Index < HandleCount; Index++) { 282 gBS->DisconnectController (HandleBuffer[Index], NULL, NULL); 283 } 284 for (Index = 0; Index < HandleCount; Index++) { 285 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); 286 } 287 if (HandleBuffer != NULL) { 288 FreePool (HandleBuffer); 289 } 290 } 291 292 return EFI_SUCCESS; 293 } 294 295 /** 296 Group the legacy boot options in the BootOption. 297 298 The routine assumes the boot options in the beginning that covers all the device 299 types are ordered properly and re-position the following boot options just after 300 the corresponding boot options with the same device type. 301 For example: 302 1. Input = [Harddisk1 CdRom2 Efi1 Harddisk0 CdRom0 CdRom1 Harddisk2 Efi0] 303 Assuming [Harddisk1 CdRom2 Efi1] is ordered properly 304 Output = [Harddisk1 Harddisk0 Harddisk2 CdRom2 CdRom0 CdRom1 Efi1 Efi0] 305 306 2. Input = [Efi1 Efi0 CdRom1 Harddisk0 Harddisk1 Harddisk2 CdRom0 CdRom2] 307 Assuming [Efi1 Efi0 CdRom1 Harddisk0] is ordered properly 308 Output = [Efi1 Efi0 CdRom1 CdRom0 CdRom2 Harddisk0 Harddisk1 Harddisk2] 309 310 **/ 311 VOID 312 GroupMultipleLegacyBootOption4SameType ( 313 VOID 314 ) 315 { 316 EFI_STATUS Status; 317 UINTN Index; 318 UINTN DeviceIndex; 319 UINTN DeviceTypeIndex[7]; 320 UINTN *NextIndex; 321 UINT16 OptionNumber; 322 UINT16 *BootOrder; 323 UINTN BootOrderSize; 324 CHAR16 OptionName[sizeof ("Boot####")]; 325 EFI_BOOT_MANAGER_LOAD_OPTION BootOption; 326 327 SetMem (DeviceTypeIndex, sizeof (DeviceTypeIndex), 0xff); 328 329 GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize); 330 if (BootOrder == NULL) { 331 return; 332 } 333 334 for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { 335 UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]); 336 Status = EfiBootManagerVariableToLoadOption (OptionName, &BootOption); 337 ASSERT_EFI_ERROR (Status); 338 339 if ((DevicePathType (BootOption.FilePath) == BBS_DEVICE_PATH) && 340 (DevicePathSubType (BootOption.FilePath) == BBS_BBS_DP)) { 341 // 342 // Legacy Boot Option 343 // 344 DEBUG ((EFI_D_ERROR, "[BootManagerDxe] ==== Find Legacy Boot Option 0x%x! ==== \n", Index)); 345 ASSERT ((((BBS_BBS_DEVICE_PATH *) BootOption.FilePath)->DeviceType & 0xF) < sizeof (DeviceTypeIndex) / sizeof (DeviceTypeIndex[0])); 346 NextIndex = &DeviceTypeIndex[((BBS_BBS_DEVICE_PATH *) BootOption.FilePath)->DeviceType & 0xF]; 347 348 if (*NextIndex == (UINTN) -1) { 349 // 350 // *NextIndex is the Index in BootOrder to put the next Option Number for the same type 351 // 352 *NextIndex = Index + 1; 353 } else { 354 // 355 // insert the current boot option before *NextIndex, causing [*Next .. Index] shift right one position 356 // 357 OptionNumber = BootOrder[Index]; 358 CopyMem (&BootOrder[*NextIndex + 1], &BootOrder[*NextIndex], (Index - *NextIndex) * sizeof (UINT16)); 359 BootOrder[*NextIndex] = OptionNumber; 360 361 // 362 // Update the DeviceTypeIndex array to reflect the right shift operation 363 // 364 for (DeviceIndex = 0; DeviceIndex < sizeof (DeviceTypeIndex) / sizeof (DeviceTypeIndex[0]); DeviceIndex++) { 365 if (DeviceTypeIndex[DeviceIndex] != (UINTN) -1 && DeviceTypeIndex[DeviceIndex] >= *NextIndex) { 366 DeviceTypeIndex[DeviceIndex]++; 367 } 368 } 369 } 370 } 371 EfiBootManagerFreeLoadOption (&BootOption); 372 } 373 374 gRT->SetVariable ( 375 L"BootOrder", 376 &gEfiGlobalVariableGuid, 377 VAR_FLAG, 378 BootOrderSize, 379 BootOrder 380 ); 381 FreePool (BootOrder); 382 } 383 384 /** 385 This function converts an input device structure to a Unicode string. 386 387 @param DevPath A pointer to the device path structure. 388 389 @return A new allocated Unicode string that represents the device path. 390 391 **/ 392 CHAR16 * 393 BmDevicePathToStr ( 394 IN EFI_DEVICE_PATH_PROTOCOL *DevPath 395 ) 396 { 397 EFI_STATUS Status; 398 CHAR16 *ToText; 399 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText; 400 401 if (DevPath == NULL) { 402 return NULL; 403 } 404 405 Status = gBS->LocateProtocol ( 406 &gEfiDevicePathToTextProtocolGuid, 407 NULL, 408 (VOID **) &DevPathToText 409 ); 410 ASSERT_EFI_ERROR (Status); 411 ToText = DevPathToText->ConvertDevicePathToText ( 412 DevPath, 413 FALSE, 414 TRUE 415 ); 416 ASSERT (ToText != NULL); 417 return ToText; 418 } 419 420 /** 421 This function invokes Boot Manager. If all devices have not a chance to be connected, 422 the connect all will be triggered. It then enumerate all boot options. If 423 a boot option from the Boot Manager page is selected, Boot Manager will boot 424 from this boot option. 425 426 **/ 427 VOID 428 UpdateBootManager ( 429 VOID 430 ) 431 { 432 UINTN Index; 433 EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; 434 UINTN BootOptionCount; 435 EFI_STRING_ID Token; 436 CHAR16 *HelpString; 437 EFI_STRING_ID HelpToken; 438 UINT16 *TempStr; 439 EFI_HII_HANDLE HiiHandle; 440 UINTN TempSize; 441 VOID *StartOpCodeHandle; 442 VOID *EndOpCodeHandle; 443 EFI_IFR_GUID_LABEL *StartLabel; 444 EFI_IFR_GUID_LABEL *EndLabel; 445 UINT16 DeviceType; 446 BOOLEAN IsLegacyOption; 447 BOOLEAN NeedEndOp; 448 UINTN MaxLen; 449 450 DeviceType = (UINT16) -1; 451 452 EfiBootManagerConnectAll (); 453 454 // 455 // for better user experience 456 // 1. User changes HD configuration (e.g.: unplug HDD), here we have a chance to remove the HDD boot option 457 // 2. User enables/disables UEFI PXE, here we have a chance to add/remove EFI Network boot option 458 // 459 EfiBootManagerRefreshAllBootOption (); 460 461 // 462 // BdsDxe doesn't group the legacy boot options for the same device type 463 // It's UI's choice. 464 // 465 GroupMultipleLegacyBootOption4SameType (); 466 467 BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); 468 469 HiiHandle = gBootManagerPrivate.HiiHandle; 470 471 // 472 // Allocate space for creation of UpdateData Buffer 473 // 474 StartOpCodeHandle = HiiAllocateOpCodeHandle (); 475 ASSERT (StartOpCodeHandle != NULL); 476 477 EndOpCodeHandle = HiiAllocateOpCodeHandle (); 478 ASSERT (EndOpCodeHandle != NULL); 479 480 // 481 // Create Hii Extend Label OpCode as the start opcode 482 // 483 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); 484 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; 485 StartLabel->Number = LABEL_BOOT_OPTION; 486 487 // 488 // Create Hii Extend Label OpCode as the end opcode 489 // 490 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); 491 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; 492 EndLabel->Number = LABEL_BOOT_OPTION_END; 493 mKeyInput = 0; 494 NeedEndOp = FALSE; 495 for (Index = 0; Index < BootOptionCount; Index++) { 496 // 497 // At this stage we are creating a menu entry, thus the Keys are reproduceable 498 // 499 mKeyInput++; 500 501 // 502 // Don't display the hidden/inactive boot option 503 // 504 if (((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) { 505 continue; 506 } 507 508 // 509 // Group the legacy boot option in the sub title created dynamically 510 // 511 IsLegacyOption = (BOOLEAN) ( 512 (DevicePathType (BootOption[Index].FilePath) == BBS_DEVICE_PATH) && 513 (DevicePathSubType (BootOption[Index].FilePath) == BBS_BBS_DP) 514 ); 515 516 if (!IsLegacyOption && NeedEndOp) { 517 NeedEndOp = FALSE; 518 HiiCreateEndOpCode (StartOpCodeHandle); 519 } 520 521 if (IsLegacyOption && DeviceType != ((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType) { 522 if (NeedEndOp) { 523 HiiCreateEndOpCode (StartOpCodeHandle); 524 } 525 526 DeviceType = ((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType; 527 Token = HiiSetString ( 528 HiiHandle, 529 0, 530 mDeviceTypeStr[ 531 MIN (DeviceType & 0xF, sizeof (mDeviceTypeStr) / sizeof (mDeviceTypeStr[0]) - 1) 532 ], 533 NULL 534 ); 535 HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1); 536 NeedEndOp = TRUE; 537 } 538 539 ASSERT (BootOption[Index].Description != NULL); 540 541 Token = HiiSetString (HiiHandle, 0, BootOption[Index].Description, NULL); 542 543 TempStr = BmDevicePathToStr (BootOption[Index].FilePath); 544 TempSize = StrSize (TempStr); 545 HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : ")); 546 MaxLen = (TempSize + StrSize (L"Device Path : "))/sizeof(CHAR16); 547 ASSERT (HelpString != NULL); 548 StrCatS (HelpString, MaxLen, L"Device Path : "); 549 StrCatS (HelpString, MaxLen, TempStr); 550 551 HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL); 552 553 HiiCreateActionOpCode ( 554 StartOpCodeHandle, 555 mKeyInput, 556 Token, 557 HelpToken, 558 EFI_IFR_FLAG_CALLBACK, 559 0 560 ); 561 } 562 563 if (NeedEndOp) { 564 HiiCreateEndOpCode (StartOpCodeHandle); 565 } 566 567 HiiUpdateForm ( 568 HiiHandle, 569 &mBootManagerGuid, 570 BOOT_MANAGER_FORM_ID, 571 StartOpCodeHandle, 572 EndOpCodeHandle 573 ); 574 575 HiiFreeOpCodeHandle (StartOpCodeHandle); 576 HiiFreeOpCodeHandle (EndOpCodeHandle); 577 578 EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount); 579 } 580 581 /** 582 This function allows a caller to extract the current configuration for one 583 or more named elements from the target driver. 584 585 586 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. 587 @param Request A null-terminated Unicode string in <ConfigRequest> format. 588 @param Progress On return, points to a character in the Request string. 589 Points to the string's null terminator if request was successful. 590 Points to the most recent '&' before the first failing name/value 591 pair (or the beginning of the string if the failure is in the 592 first name/value pair) if the request was not successful. 593 @param Results A null-terminated Unicode string in <ConfigAltResp> format which 594 has all values filled in for the names in the Request string. 595 String to be allocated by the called function. 596 597 @retval EFI_SUCCESS The Results is filled with the requested values. 598 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. 599 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. 600 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. 601 602 **/ 603 EFI_STATUS 604 EFIAPI 605 BootManagerExtractConfig ( 606 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, 607 IN CONST EFI_STRING Request, 608 OUT EFI_STRING *Progress, 609 OUT EFI_STRING *Results 610 ) 611 { 612 if (Progress == NULL || Results == NULL) { 613 return EFI_INVALID_PARAMETER; 614 } 615 *Progress = Request; 616 return EFI_NOT_FOUND; 617 } 618 619 /** 620 This function processes the results of changes in configuration. 621 622 623 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. 624 @param Configuration A null-terminated Unicode string in <ConfigResp> format. 625 @param Progress A pointer to a string filled in with the offset of the most 626 recent '&' before the first failing name/value pair (or the 627 beginning of the string if the failure is in the first 628 name/value pair) or the terminating NULL if all was successful. 629 630 @retval EFI_SUCCESS The Results is processed successfully. 631 @retval EFI_INVALID_PARAMETER Configuration is NULL. 632 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. 633 634 **/ 635 EFI_STATUS 636 EFIAPI 637 BootManagerRouteConfig ( 638 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, 639 IN CONST EFI_STRING Configuration, 640 OUT EFI_STRING *Progress 641 ) 642 { 643 if (Configuration == NULL || Progress == NULL) { 644 return EFI_INVALID_PARAMETER; 645 } 646 647 *Progress = Configuration; 648 649 return EFI_NOT_FOUND; 650 } 651 652 /** 653 This call back function is registered with Boot Manager formset. 654 When user selects a boot option, this call back function will 655 be triggered. The boot option is saved for later processing. 656 657 658 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. 659 @param Action Specifies the type of action taken by the browser. 660 @param QuestionId A unique value which is sent to the original exporting driver 661 so that it can identify the type of data to expect. 662 @param Type The type of value for the question. 663 @param Value A pointer to the data being sent to the original exporting driver. 664 @param ActionRequest On return, points to the action requested by the callback function. 665 666 @retval EFI_SUCCESS The callback successfully handled the action. 667 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. 668 669 **/ 670 EFI_STATUS 671 EFIAPI 672 BootManagerCallback ( 673 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, 674 IN EFI_BROWSER_ACTION Action, 675 IN EFI_QUESTION_ID QuestionId, 676 IN UINT8 Type, 677 IN EFI_IFR_TYPE_VALUE *Value, 678 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest 679 ) 680 { 681 EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; 682 UINTN BootOptionCount; 683 EFI_INPUT_KEY Key; 684 685 if (Action == EFI_BROWSER_ACTION_FORM_OPEN) { 686 // 687 //Means enter the boot manager form. 688 //Update the boot manage page,because the boot option may changed. 689 // 690 if (QuestionId == 0x1212){ 691 UpdateBootManager(); 692 } 693 return EFI_SUCCESS; 694 } 695 696 if (Action != EFI_BROWSER_ACTION_CHANGED) { 697 // 698 // Do nothing for other UEFI Action. Only do call back when data is changed. 699 // 700 return EFI_UNSUPPORTED; 701 } 702 703 if ((Value == NULL) || (ActionRequest == NULL)) { 704 return EFI_INVALID_PARAMETER; 705 } 706 707 BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); 708 709 // 710 // Clear the screen before. 711 // 712 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); 713 gST->ConOut->ClearScreen (gST->ConOut); 714 715 // 716 // parse the selected option 717 // 718 BmBdsSetConsoleMode (FALSE); 719 EfiBootManagerBoot (&BootOption[QuestionId - 1]); 720 BmBdsSetConsoleMode (TRUE); 721 722 if (EFI_ERROR (BootOption[QuestionId - 1].Status)) { 723 gST->ConOut->OutputString ( 724 gST->ConOut, 725 HiiGetString (gBootManagerPrivate.HiiHandle, STRING_TOKEN (STR_ANY_KEY_CONTINUE), NULL) 726 ); 727 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); 728 } 729 730 EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount); 731 732 return EFI_SUCCESS; 733 } 734 735 /** 736 737 Install Boot Manager Menu driver. 738 739 @param ImageHandle The image handle. 740 @param SystemTable The system table. 741 742 @retval EFI_SUCEESS Install Boot manager menu success. 743 @retval Other Return error status. 744 745 **/ 746 EFI_STATUS 747 EFIAPI 748 BootManagerLibConstructor ( 749 IN EFI_HANDLE ImageHandle, 750 IN EFI_SYSTEM_TABLE *SystemTable 751 ) 752 { 753 EFI_STATUS Status; 754 755 // 756 // Install Device Path Protocol and Config Access protocol to driver handle 757 // 758 gBootManagerPrivate.DriverHandle = NULL; 759 Status = gBS->InstallMultipleProtocolInterfaces ( 760 &gBootManagerPrivate.DriverHandle, 761 &gEfiDevicePathProtocolGuid, 762 &mBootManagerHiiVendorDevicePath, 763 &gEfiHiiConfigAccessProtocolGuid, 764 &gBootManagerPrivate.ConfigAccess, 765 NULL 766 ); 767 ASSERT_EFI_ERROR (Status); 768 769 // 770 // Publish our HII data 771 // 772 gBootManagerPrivate.HiiHandle = HiiAddPackages ( 773 &mBootManagerGuid, 774 gBootManagerPrivate.DriverHandle, 775 BootManagerVfrBin, 776 BootManagerLibStrings, 777 NULL 778 ); 779 ASSERT (gBootManagerPrivate.HiiHandle != NULL); 780 781 782 return EFI_SUCCESS; 783 } 784 785 /** 786 Unloads the application and its installed protocol. 787 788 @param[in] ImageHandle Handle that identifies the image to be unloaded. 789 @param[in] SystemTable System Table 790 791 @retval EFI_SUCCESS The image has been unloaded. 792 **/ 793 EFI_STATUS 794 EFIAPI 795 BootManagerLibDestructor ( 796 IN EFI_HANDLE ImageHandle, 797 IN EFI_SYSTEM_TABLE *SystemTable 798 ) 799 { 800 EFI_STATUS Status; 801 802 Status = gBS->UninstallMultipleProtocolInterfaces ( 803 gBootManagerPrivate.DriverHandle, 804 &gEfiDevicePathProtocolGuid, 805 &mBootManagerHiiVendorDevicePath, 806 &gEfiHiiConfigAccessProtocolGuid, 807 &gBootManagerPrivate.ConfigAccess, 808 NULL 809 ); 810 ASSERT_EFI_ERROR (Status); 811 812 HiiRemovePackages (gBootManagerPrivate.HiiHandle); 813 814 return EFI_SUCCESS; 815 } 816 817