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