1 /** @file 2 Provide boot option support for Application "BootMaint" 3 4 Include file system navigation, system handle selection 5 6 Boot option manipulation 7 8 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR> 9 This program and the accompanying materials 10 are licensed and made available under the terms and conditions of the BSD License 11 which accompanies this distribution. The full text of the license may be found at 12 http://opensource.org/licenses/bsd-license.php 13 14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 16 17 **/ 18 19 #include "BootMaintenanceManager.h" 20 21 /// 22 /// Define the maximum characters that will be accepted. 23 /// 24 #define MAX_CHAR 480 25 26 /** 27 Create a menu entry by given menu type. 28 29 @param MenuType The Menu type to be created. 30 31 @retval NULL If failed to create the menu. 32 @return the new menu entry. 33 34 **/ 35 BM_MENU_ENTRY * 36 BOpt_CreateMenuEntry ( 37 UINTN MenuType 38 ) 39 { 40 BM_MENU_ENTRY *MenuEntry; 41 UINTN ContextSize; 42 43 // 44 // Get context size according to menu type 45 // 46 switch (MenuType) { 47 case BM_LOAD_CONTEXT_SELECT: 48 ContextSize = sizeof (BM_LOAD_CONTEXT); 49 break; 50 51 case BM_FILE_CONTEXT_SELECT: 52 ContextSize = sizeof (BM_FILE_CONTEXT); 53 break; 54 55 case BM_CONSOLE_CONTEXT_SELECT: 56 ContextSize = sizeof (BM_CONSOLE_CONTEXT); 57 break; 58 59 case BM_TERMINAL_CONTEXT_SELECT: 60 ContextSize = sizeof (BM_TERMINAL_CONTEXT); 61 break; 62 63 case BM_HANDLE_CONTEXT_SELECT: 64 ContextSize = sizeof (BM_HANDLE_CONTEXT); 65 break; 66 67 default: 68 ContextSize = 0; 69 break; 70 } 71 72 if (ContextSize == 0) { 73 return NULL; 74 } 75 76 // 77 // Create new menu entry 78 // 79 MenuEntry = AllocateZeroPool (sizeof (BM_MENU_ENTRY)); 80 if (MenuEntry == NULL) { 81 return NULL; 82 } 83 84 MenuEntry->VariableContext = AllocateZeroPool (ContextSize); 85 if (MenuEntry->VariableContext == NULL) { 86 FreePool (MenuEntry); 87 return NULL; 88 } 89 90 MenuEntry->Signature = BM_MENU_ENTRY_SIGNATURE; 91 MenuEntry->ContextSelection = MenuType; 92 return MenuEntry; 93 } 94 95 /** 96 Free up all resource allocated for a BM_MENU_ENTRY. 97 98 @param MenuEntry A pointer to BM_MENU_ENTRY. 99 100 **/ 101 VOID 102 BOpt_DestroyMenuEntry ( 103 BM_MENU_ENTRY *MenuEntry 104 ) 105 { 106 BM_LOAD_CONTEXT *LoadContext; 107 BM_FILE_CONTEXT *FileContext; 108 BM_CONSOLE_CONTEXT *ConsoleContext; 109 BM_TERMINAL_CONTEXT *TerminalContext; 110 BM_HANDLE_CONTEXT *HandleContext; 111 112 // 113 // Select by the type in Menu entry for current context type 114 // 115 switch (MenuEntry->ContextSelection) { 116 case BM_LOAD_CONTEXT_SELECT: 117 LoadContext = (BM_LOAD_CONTEXT *) MenuEntry->VariableContext; 118 FreePool (LoadContext->FilePathList); 119 if (LoadContext->OptionalData != NULL) { 120 FreePool (LoadContext->OptionalData); 121 } 122 FreePool (LoadContext); 123 break; 124 125 case BM_FILE_CONTEXT_SELECT: 126 FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; 127 128 if (!FileContext->IsRoot) { 129 FreePool (FileContext->DevicePath); 130 } else { 131 if (FileContext->FHandle != NULL) { 132 FileContext->FHandle->Close (FileContext->FHandle); 133 } 134 } 135 136 if (FileContext->FileName != NULL) { 137 FreePool (FileContext->FileName); 138 } 139 if (FileContext->Info != NULL) { 140 FreePool (FileContext->Info); 141 } 142 FreePool (FileContext); 143 break; 144 145 case BM_CONSOLE_CONTEXT_SELECT: 146 ConsoleContext = (BM_CONSOLE_CONTEXT *) MenuEntry->VariableContext; 147 FreePool (ConsoleContext->DevicePath); 148 FreePool (ConsoleContext); 149 break; 150 151 case BM_TERMINAL_CONTEXT_SELECT: 152 TerminalContext = (BM_TERMINAL_CONTEXT *) MenuEntry->VariableContext; 153 FreePool (TerminalContext->DevicePath); 154 FreePool (TerminalContext); 155 break; 156 157 case BM_HANDLE_CONTEXT_SELECT: 158 HandleContext = (BM_HANDLE_CONTEXT *) MenuEntry->VariableContext; 159 FreePool (HandleContext); 160 break; 161 162 default: 163 break; 164 } 165 166 FreePool (MenuEntry->DisplayString); 167 if (MenuEntry->HelpString != NULL) { 168 FreePool (MenuEntry->HelpString); 169 } 170 171 FreePool (MenuEntry); 172 } 173 174 /** 175 Get the Menu Entry from the list in Menu Entry List. 176 177 If MenuNumber is great or equal to the number of Menu 178 Entry in the list, then ASSERT. 179 180 @param MenuOption The Menu Entry List to read the menu entry. 181 @param MenuNumber The index of Menu Entry. 182 183 @return The Menu Entry. 184 185 **/ 186 BM_MENU_ENTRY * 187 BOpt_GetMenuEntry ( 188 BM_MENU_OPTION *MenuOption, 189 UINTN MenuNumber 190 ) 191 { 192 BM_MENU_ENTRY *NewMenuEntry; 193 UINTN Index; 194 LIST_ENTRY *List; 195 196 ASSERT (MenuNumber < MenuOption->MenuNumber); 197 198 List = MenuOption->Head.ForwardLink; 199 for (Index = 0; Index < MenuNumber; Index++) { 200 List = List->ForwardLink; 201 } 202 203 NewMenuEntry = CR (List, BM_MENU_ENTRY, Link, BM_MENU_ENTRY_SIGNATURE); 204 205 return NewMenuEntry; 206 } 207 208 /** 209 Free resources allocated in Allocate Rountine. 210 211 @param FreeMenu Menu to be freed 212 **/ 213 VOID 214 BOpt_FreeMenu ( 215 BM_MENU_OPTION *FreeMenu 216 ) 217 { 218 BM_MENU_ENTRY *MenuEntry; 219 while (!IsListEmpty (&FreeMenu->Head)) { 220 MenuEntry = CR ( 221 FreeMenu->Head.ForwardLink, 222 BM_MENU_ENTRY, 223 Link, 224 BM_MENU_ENTRY_SIGNATURE 225 ); 226 RemoveEntryList (&MenuEntry->Link); 227 BOpt_DestroyMenuEntry (MenuEntry); 228 } 229 FreeMenu->MenuNumber = 0; 230 } 231 232 /** 233 234 Build the BootOptionMenu according to BootOrder Variable. 235 This Routine will access the Boot#### to get EFI_LOAD_OPTION. 236 237 @param CallbackData The BMM context data. 238 239 @return EFI_NOT_FOUND Fail to find "BootOrder" variable. 240 @return EFI_SUCESS Success build boot option menu. 241 242 **/ 243 EFI_STATUS 244 BOpt_GetBootOptions ( 245 IN BMM_CALLBACK_DATA *CallbackData 246 ) 247 { 248 UINTN Index; 249 UINT16 BootString[10]; 250 UINT8 *LoadOptionFromVar; 251 UINTN BootOptionSize; 252 BOOLEAN BootNextFlag; 253 UINT16 *BootOrderList; 254 UINTN BootOrderListSize; 255 UINT16 *BootNext; 256 UINTN BootNextSize; 257 BM_MENU_ENTRY *NewMenuEntry; 258 BM_LOAD_CONTEXT *NewLoadContext; 259 UINT8 *LoadOptionPtr; 260 UINTN StringSize; 261 UINTN OptionalDataSize; 262 UINT8 *LoadOptionEnd; 263 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 264 UINTN MenuCount; 265 UINT8 *Ptr; 266 EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; 267 UINTN BootOptionCount; 268 269 MenuCount = 0; 270 BootOrderListSize = 0; 271 BootNextSize = 0; 272 BootOrderList = NULL; 273 BootNext = NULL; 274 LoadOptionFromVar = NULL; 275 BOpt_FreeMenu (&BootOptionMenu); 276 InitializeListHead (&BootOptionMenu.Head); 277 278 // 279 // Get the BootOrder from the Var 280 // 281 GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrderList, &BootOrderListSize); 282 if (BootOrderList == NULL) { 283 return EFI_NOT_FOUND; 284 } 285 286 // 287 // Get the BootNext from the Var 288 // 289 GetEfiGlobalVariable2 (L"BootNext", (VOID **) &BootNext, &BootNextSize); 290 if (BootNext != NULL) { 291 if (BootNextSize != sizeof (UINT16)) { 292 FreePool (BootNext); 293 BootNext = NULL; 294 } 295 } 296 BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); 297 for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) { 298 // 299 // Don't display the hidden/inactive boot option 300 // 301 if (((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) { 302 continue; 303 } 304 305 UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]); 306 // 307 // Get all loadoptions from the VAR 308 // 309 GetEfiGlobalVariable2 (BootString, (VOID **) &LoadOptionFromVar, &BootOptionSize); 310 if (LoadOptionFromVar == NULL) { 311 continue; 312 } 313 314 if (BootNext != NULL) { 315 BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]); 316 } else { 317 BootNextFlag = FALSE; 318 } 319 320 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); 321 ASSERT (NULL != NewMenuEntry); 322 323 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; 324 325 LoadOptionPtr = LoadOptionFromVar; 326 LoadOptionEnd = LoadOptionFromVar + BootOptionSize; 327 328 NewMenuEntry->OptionNumber = BootOrderList[Index]; 329 NewLoadContext->Deleted = FALSE; 330 NewLoadContext->IsBootNext = BootNextFlag; 331 332 // 333 // Is a Legacy Device? 334 // 335 Ptr = (UINT8 *) LoadOptionFromVar; 336 337 // 338 // Attribute = *(UINT32 *)Ptr; 339 // 340 Ptr += sizeof (UINT32); 341 342 // 343 // FilePathSize = *(UINT16 *)Ptr; 344 // 345 Ptr += sizeof (UINT16); 346 347 // 348 // Description = (CHAR16 *)Ptr; 349 // 350 Ptr += StrSize ((CHAR16 *) Ptr); 351 352 // 353 // Now Ptr point to Device Path 354 // 355 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr; 356 if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) { 357 NewLoadContext->IsLegacy = TRUE; 358 } else { 359 NewLoadContext->IsLegacy = FALSE; 360 } 361 // 362 // LoadOption is a pointer type of UINT8 363 // for easy use with following LOAD_OPTION 364 // embedded in this struct 365 // 366 367 NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr; 368 369 LoadOptionPtr += sizeof (UINT32); 370 371 NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr; 372 LoadOptionPtr += sizeof (UINT16); 373 374 StringSize = StrSize((UINT16*)LoadOptionPtr); 375 376 NewLoadContext->Description = AllocateZeroPool (StrSize((UINT16*)LoadOptionPtr)); 377 ASSERT (NewLoadContext->Description != NULL); 378 StrCpyS (NewLoadContext->Description, StrSize((UINT16*)LoadOptionPtr) / sizeof (UINT16), (UINT16*)LoadOptionPtr); 379 380 ASSERT (NewLoadContext->Description != NULL); 381 NewMenuEntry->DisplayString = NewLoadContext->Description; 382 NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL); 383 384 LoadOptionPtr += StringSize; 385 386 NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength); 387 ASSERT (NewLoadContext->FilePathList != NULL); 388 CopyMem ( 389 NewLoadContext->FilePathList, 390 (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr, 391 NewLoadContext->FilePathListLength 392 ); 393 394 NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList); 395 NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->HelpString, NULL); 396 397 LoadOptionPtr += NewLoadContext->FilePathListLength; 398 399 if (LoadOptionPtr < LoadOptionEnd) { 400 OptionalDataSize = BootOptionSize - 401 sizeof (UINT32) - 402 sizeof (UINT16) - 403 StringSize - 404 NewLoadContext->FilePathListLength; 405 406 NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize); 407 ASSERT (NewLoadContext->OptionalData != NULL); 408 CopyMem ( 409 NewLoadContext->OptionalData, 410 LoadOptionPtr, 411 OptionalDataSize 412 ); 413 } 414 415 InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link); 416 MenuCount++; 417 FreePool (LoadOptionFromVar); 418 } 419 EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount); 420 421 if (BootNext != NULL) { 422 FreePool (BootNext); 423 } 424 if (BootOrderList != NULL) { 425 FreePool (BootOrderList); 426 } 427 428 BootOptionMenu.MenuNumber = MenuCount; 429 return EFI_SUCCESS; 430 } 431 432 /** 433 434 Find drivers that will be added as Driver#### variables from handles 435 in current system environment 436 All valid handles in the system except those consume SimpleFs, LoadFile 437 are stored in DriverMenu for future use. 438 439 @retval EFI_SUCCESS The function complets successfully. 440 @return Other value if failed to build the DriverMenu. 441 442 **/ 443 EFI_STATUS 444 BOpt_FindDrivers ( 445 VOID 446 ) 447 { 448 UINTN NoDevicePathHandles; 449 EFI_HANDLE *DevicePathHandle; 450 UINTN Index; 451 EFI_STATUS Status; 452 BM_MENU_ENTRY *NewMenuEntry; 453 BM_HANDLE_CONTEXT *NewHandleContext; 454 EFI_HANDLE CurHandle; 455 UINTN OptionNumber; 456 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs; 457 EFI_LOAD_FILE_PROTOCOL *LoadFile; 458 459 SimpleFs = NULL; 460 LoadFile = NULL; 461 462 InitializeListHead (&DriverMenu.Head); 463 464 // 465 // At first, get all handles that support Device Path 466 // protocol which is the basic requirement for 467 // Driver#### 468 // 469 Status = gBS->LocateHandleBuffer ( 470 ByProtocol, 471 &gEfiDevicePathProtocolGuid, 472 NULL, 473 &NoDevicePathHandles, 474 &DevicePathHandle 475 ); 476 if (EFI_ERROR (Status)) { 477 return Status; 478 } 479 480 OptionNumber = 0; 481 for (Index = 0; Index < NoDevicePathHandles; Index++) { 482 CurHandle = DevicePathHandle[Index]; 483 484 Status = gBS->HandleProtocol ( 485 CurHandle, 486 &gEfiSimpleFileSystemProtocolGuid, 487 (VOID **) &SimpleFs 488 ); 489 if (Status == EFI_SUCCESS) { 490 continue; 491 } 492 493 Status = gBS->HandleProtocol ( 494 CurHandle, 495 &gEfiLoadFileProtocolGuid, 496 (VOID **) &LoadFile 497 ); 498 if (Status == EFI_SUCCESS) { 499 continue; 500 } 501 502 NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT); 503 if (NULL == NewMenuEntry) { 504 FreePool (DevicePathHandle); 505 return EFI_OUT_OF_RESOURCES; 506 } 507 508 NewHandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext; 509 NewHandleContext->Handle = CurHandle; 510 NewHandleContext->DevicePath = DevicePathFromHandle (CurHandle); 511 NewMenuEntry->DisplayString = UiDevicePathToStr (NewHandleContext->DevicePath); 512 NewMenuEntry->DisplayStringToken = HiiSetString (mBmmCallbackInfo->BmmHiiHandle,0,NewMenuEntry->DisplayString,NULL); 513 NewMenuEntry->HelpString = NULL; 514 NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken; 515 NewMenuEntry->OptionNumber = OptionNumber; 516 OptionNumber++; 517 InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link); 518 519 } 520 521 if (DevicePathHandle != NULL) { 522 FreePool (DevicePathHandle); 523 } 524 525 DriverMenu.MenuNumber = OptionNumber; 526 return EFI_SUCCESS; 527 } 528 529 /** 530 531 Get the Option Number that has not been allocated for use. 532 533 @param Type The type of Option. 534 535 @return The available Option Number. 536 537 **/ 538 UINT16 539 BOpt_GetOptionNumber ( 540 CHAR16 *Type 541 ) 542 { 543 UINT16 *OrderList; 544 UINTN OrderListSize; 545 UINTN Index; 546 CHAR16 StrTemp[20]; 547 UINT16 *OptionBuffer; 548 UINT16 OptionNumber; 549 UINTN OptionSize; 550 551 OrderListSize = 0; 552 OrderList = NULL; 553 OptionNumber = 0; 554 Index = 0; 555 556 UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%sOrder", Type); 557 558 GetEfiGlobalVariable2 (StrTemp, (VOID **) &OrderList, &OrderListSize); 559 for (OptionNumber = 0; ; OptionNumber++) { 560 if (OrderList != NULL) { 561 for (Index = 0; Index < OrderListSize / sizeof (UINT16); Index++) { 562 if (OptionNumber == OrderList[Index]) { 563 break; 564 } 565 } 566 } 567 568 if (Index < OrderListSize / sizeof (UINT16)) { 569 // 570 // The OptionNumber occurs in the OrderList, continue to use next one 571 // 572 continue; 573 } 574 UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%s%04x", Type, (UINTN) OptionNumber); 575 DEBUG((EFI_D_ERROR,"Option = %s\n", StrTemp)); 576 GetEfiGlobalVariable2 (StrTemp, (VOID **) &OptionBuffer, &OptionSize); 577 if (NULL == OptionBuffer) { 578 // 579 // The Boot[OptionNumber] / Driver[OptionNumber] NOT occurs, we found it 580 // 581 break; 582 } 583 } 584 585 return OptionNumber; 586 } 587 588 /** 589 590 Get the Option Number for Boot#### that does not used. 591 592 @return The available Option Number. 593 594 **/ 595 UINT16 596 BOpt_GetBootOptionNumber ( 597 VOID 598 ) 599 { 600 return BOpt_GetOptionNumber (L"Boot"); 601 } 602 603 /** 604 605 Get the Option Number for Driver#### that does not used. 606 607 @return The unused Option Number. 608 609 **/ 610 UINT16 611 BOpt_GetDriverOptionNumber ( 612 VOID 613 ) 614 { 615 return BOpt_GetOptionNumber (L"Driver"); 616 } 617 618 /** 619 620 Build up all DriverOptionMenu 621 622 @param CallbackData The BMM context data. 623 624 @retval EFI_SUCESS The functin completes successfully. 625 @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation. 626 @retval EFI_NOT_FOUND Fail to get "DriverOrder" variable. 627 628 **/ 629 EFI_STATUS 630 BOpt_GetDriverOptions ( 631 IN BMM_CALLBACK_DATA *CallbackData 632 ) 633 { 634 UINTN Index; 635 UINT16 DriverString[12]; 636 UINT8 *LoadOptionFromVar; 637 UINTN DriverOptionSize; 638 639 UINT16 *DriverOrderList; 640 UINTN DriverOrderListSize; 641 BM_MENU_ENTRY *NewMenuEntry; 642 BM_LOAD_CONTEXT *NewLoadContext; 643 UINT8 *LoadOptionPtr; 644 UINTN StringSize; 645 UINTN OptionalDataSize; 646 UINT8 *LoadOptionEnd; 647 648 DriverOrderListSize = 0; 649 DriverOrderList = NULL; 650 DriverOptionSize = 0; 651 LoadOptionFromVar = NULL; 652 BOpt_FreeMenu (&DriverOptionMenu); 653 InitializeListHead (&DriverOptionMenu.Head); 654 // 655 // Get the DriverOrder from the Var 656 // 657 GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize); 658 if (DriverOrderList == NULL) { 659 return EFI_NOT_FOUND; 660 } 661 662 for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) { 663 UnicodeSPrint ( 664 DriverString, 665 sizeof (DriverString), 666 L"Driver%04x", 667 DriverOrderList[Index] 668 ); 669 // 670 // Get all loadoptions from the VAR 671 // 672 GetEfiGlobalVariable2 (DriverString, (VOID **) &LoadOptionFromVar, &DriverOptionSize); 673 if (LoadOptionFromVar == NULL) { 674 continue; 675 } 676 677 678 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); 679 if (NULL == NewMenuEntry) { 680 return EFI_OUT_OF_RESOURCES; 681 } 682 683 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; 684 LoadOptionPtr = LoadOptionFromVar; 685 LoadOptionEnd = LoadOptionFromVar + DriverOptionSize; 686 NewMenuEntry->OptionNumber = DriverOrderList[Index]; 687 NewLoadContext->Deleted = FALSE; 688 NewLoadContext->IsLegacy = FALSE; 689 690 // 691 // LoadOption is a pointer type of UINT8 692 // for easy use with following LOAD_OPTION 693 // embedded in this struct 694 // 695 696 NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr; 697 698 LoadOptionPtr += sizeof (UINT32); 699 700 NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr; 701 LoadOptionPtr += sizeof (UINT16); 702 703 StringSize = StrSize ((UINT16 *) LoadOptionPtr); 704 NewLoadContext->Description = AllocateZeroPool (StringSize); 705 ASSERT (NewLoadContext->Description != NULL); 706 CopyMem ( 707 NewLoadContext->Description, 708 (UINT16 *) LoadOptionPtr, 709 StringSize 710 ); 711 NewMenuEntry->DisplayString = NewLoadContext->Description; 712 NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL); 713 714 LoadOptionPtr += StringSize; 715 716 NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength); 717 ASSERT (NewLoadContext->FilePathList != NULL); 718 CopyMem ( 719 NewLoadContext->FilePathList, 720 (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr, 721 NewLoadContext->FilePathListLength 722 ); 723 724 NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList); 725 NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->HelpString, NULL); 726 727 LoadOptionPtr += NewLoadContext->FilePathListLength; 728 729 if (LoadOptionPtr < LoadOptionEnd) { 730 OptionalDataSize = DriverOptionSize - 731 sizeof (UINT32) - 732 sizeof (UINT16) - 733 StringSize - 734 NewLoadContext->FilePathListLength; 735 736 NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize); 737 ASSERT (NewLoadContext->OptionalData != NULL); 738 CopyMem ( 739 NewLoadContext->OptionalData, 740 LoadOptionPtr, 741 OptionalDataSize 742 ); 743 744 } 745 746 InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link); 747 FreePool (LoadOptionFromVar); 748 749 } 750 751 if (DriverOrderList != NULL) { 752 FreePool (DriverOrderList); 753 } 754 755 DriverOptionMenu.MenuNumber = Index; 756 return EFI_SUCCESS; 757 758 } 759 760 /** 761 Get option number according to Boot#### and BootOrder variable. 762 The value is saved as #### + 1. 763 764 @param CallbackData The BMM context data. 765 **/ 766 VOID 767 GetBootOrder ( 768 IN BMM_CALLBACK_DATA *CallbackData 769 ) 770 { 771 BMM_FAKE_NV_DATA *BmmConfig; 772 UINT16 Index; 773 UINT16 OptionOrderIndex; 774 UINTN DeviceType; 775 BM_MENU_ENTRY *NewMenuEntry; 776 BM_LOAD_CONTEXT *NewLoadContext; 777 778 ASSERT (CallbackData != NULL); 779 780 DeviceType = (UINTN) -1; 781 BmmConfig = &CallbackData->BmmFakeNvData; 782 ZeroMem (BmmConfig->BootOptionOrder, sizeof (BmmConfig->BootOptionOrder)); 783 784 for (Index = 0, OptionOrderIndex = 0; ((Index < BootOptionMenu.MenuNumber) && 785 (OptionOrderIndex < (sizeof (BmmConfig->BootOptionOrder) / sizeof (BmmConfig->BootOptionOrder[0])))); 786 Index++) { 787 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); 788 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; 789 790 if (NewLoadContext->IsLegacy) { 791 if (((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType != DeviceType) { 792 DeviceType = ((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType; 793 } else { 794 // 795 // Only show one legacy boot option for the same device type 796 // assuming the boot options are grouped by the device type 797 // 798 continue; 799 } 800 } 801 BmmConfig->BootOptionOrder[OptionOrderIndex++] = (UINT32) (NewMenuEntry->OptionNumber + 1); 802 } 803 } 804 805 /** 806 Get driver option order from globalc DriverOptionMenu. 807 808 @param CallbackData The BMM context data. 809 810 **/ 811 VOID 812 GetDriverOrder ( 813 IN BMM_CALLBACK_DATA *CallbackData 814 ) 815 { 816 BMM_FAKE_NV_DATA *BmmConfig; 817 UINT16 Index; 818 UINT16 OptionOrderIndex; 819 UINTN DeviceType; 820 BM_MENU_ENTRY *NewMenuEntry; 821 BM_LOAD_CONTEXT *NewLoadContext; 822 823 824 ASSERT (CallbackData != NULL); 825 826 DeviceType = (UINTN) -1; 827 BmmConfig = &CallbackData->BmmFakeNvData; 828 ZeroMem (BmmConfig->DriverOptionOrder, sizeof (BmmConfig->DriverOptionOrder)); 829 830 for (Index = 0, OptionOrderIndex = 0; ((Index < DriverOptionMenu.MenuNumber) && 831 (OptionOrderIndex < (sizeof (BmmConfig->DriverOptionOrder) / sizeof (BmmConfig->DriverOptionOrder[0])))); 832 Index++) { 833 NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); 834 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; 835 836 if (NewLoadContext->IsLegacy) { 837 if (((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType != DeviceType) { 838 DeviceType = ((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType; 839 } else { 840 // 841 // Only show one legacy boot option for the same device type 842 // assuming the boot options are grouped by the device type 843 // 844 continue; 845 } 846 } 847 BmmConfig->DriverOptionOrder[OptionOrderIndex++] = (UINT32) (NewMenuEntry->OptionNumber + 1); 848 } 849 } 850 851 /** 852 Boot the file specified by the input file path info. 853 854 @param FilePath Point to the file path. 855 856 @retval TRUE Exit caller function. 857 @retval FALSE Not exit caller function. 858 **/ 859 BOOLEAN 860 EFIAPI 861 BootFromFile ( 862 IN EFI_DEVICE_PATH_PROTOCOL *FilePath 863 ) 864 { 865 EFI_BOOT_MANAGER_LOAD_OPTION BootOption; 866 CHAR16 *FileName; 867 868 FileName = NULL; 869 870 FileName = ExtractFileNameFromDevicePath(FilePath); 871 if (FileName != NULL) { 872 EfiBootManagerInitializeLoadOption ( 873 &BootOption, 874 0, 875 LoadOptionTypeBoot, 876 LOAD_OPTION_ACTIVE, 877 FileName, 878 FilePath, 879 NULL, 880 0 881 ); 882 // 883 // Since current no boot from removable media directly is allowed */ 884 // 885 gST->ConOut->ClearScreen (gST->ConOut); 886 887 BmmSetConsoleMode (FALSE); 888 EfiBootManagerBoot (&BootOption); 889 BmmSetConsoleMode (TRUE); 890 891 FreePool(FileName); 892 893 EfiBootManagerFreeLoadOption (&BootOption); 894 } 895 896 return FALSE; 897 } 898 899 /** 900 Display the form base on the selected file. 901 902 @param FilePath Point to the file path. 903 @param FormId The form need to display. 904 905 **/ 906 BOOLEAN 907 ReSendForm( 908 IN EFI_DEVICE_PATH_PROTOCOL *FilePath, 909 IN EFI_FORM_ID FormId 910 ) 911 { 912 gBootMaintenancePrivate.LoadContext->FilePathList = FilePath; 913 914 UpdateOptionPage(&gBootMaintenancePrivate, FormId, FilePath); 915 916 gBootMaintenancePrivate.FormBrowser2->SendForm ( 917 gBootMaintenancePrivate.FormBrowser2, 918 &gBootMaintenancePrivate.BmmHiiHandle, 919 1, 920 &mBootMaintGuid, 921 FormId, 922 NULL, 923 NULL 924 ); 925 return TRUE; 926 } 927 928 /** 929 Create boot option base on the input file path info. 930 931 @param FilePath Point to the file path. 932 933 @retval TRUE Exit caller function. 934 @retval FALSE Not exit caller function. 935 **/ 936 BOOLEAN 937 EFIAPI 938 CreateBootOptionFromFile ( 939 IN EFI_DEVICE_PATH_PROTOCOL *FilePath 940 ) 941 { 942 return ReSendForm(FilePath, FORM_BOOT_ADD_ID); 943 } 944 945 /** 946 Create driver option base on the input file path info. 947 948 @param FilePath Point to the file path. 949 950 @retval TRUE Exit caller function. 951 @retval FALSE Not exit caller function. 952 953 **/ 954 BOOLEAN 955 EFIAPI 956 CreateDriverOptionFromFile ( 957 IN EFI_DEVICE_PATH_PROTOCOL *FilePath 958 ) 959 { 960 return ReSendForm(FilePath, FORM_DRV_ADD_FILE_ID); 961 } 962 963