1 /** @file 2 Legacy Boot Maintainence UI implementation. 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 16 #include "LegacyBootMaintUi.h" 17 18 LEGACY_BOOT_OPTION_CALLBACK_DATA *mLegacyBootOptionPrivate; 19 EFI_GUID mLegacyBootOptionGuid = LEGACY_BOOT_OPTION_FORMSET_GUID; 20 CHAR16 mLegacyBootStorageName[] = L"LegacyBootData"; 21 BBS_TYPE mBbsType[] = {BBS_FLOPPY, BBS_HARDDISK, BBS_CDROM, BBS_EMBED_NETWORK, BBS_BEV_DEVICE, BBS_UNKNOWN}; 22 23 24 /// 25 /// Legacy FD Info from LegacyBios.GetBbsInfo() 26 /// 27 LEGACY_MENU_OPTION LegacyFDMenu = { 28 LEGACY_MENU_OPTION_SIGNATURE, 29 {NULL}, 30 0 31 }; 32 33 /// 34 /// Legacy HD Info from LegacyBios.GetBbsInfo() 35 /// 36 LEGACY_MENU_OPTION LegacyHDMenu = { 37 LEGACY_MENU_OPTION_SIGNATURE, 38 {NULL}, 39 0 40 }; 41 42 /// 43 /// Legacy CD Info from LegacyBios.GetBbsInfo() 44 /// 45 LEGACY_MENU_OPTION LegacyCDMenu = { 46 LEGACY_MENU_OPTION_SIGNATURE, 47 {NULL}, 48 0 49 }; 50 51 /// 52 /// Legacy NET Info from LegacyBios.GetBbsInfo() 53 /// 54 LEGACY_MENU_OPTION LegacyNETMenu = { 55 LEGACY_MENU_OPTION_SIGNATURE, 56 {NULL}, 57 0 58 }; 59 60 /// 61 /// Legacy NET Info from LegacyBios.GetBbsInfo() 62 /// 63 LEGACY_MENU_OPTION LegacyBEVMenu = { 64 LEGACY_MENU_OPTION_SIGNATURE, 65 {NULL}, 66 0 67 }; 68 69 70 VOID *mLegacyStartOpCodeHandle = NULL; 71 VOID *mLegacyEndOpCodeHandle = NULL; 72 EFI_IFR_GUID_LABEL *mLegacyStartLabel = NULL; 73 EFI_IFR_GUID_LABEL *mLegacyEndLabel = NULL; 74 75 76 HII_VENDOR_DEVICE_PATH mLegacyBootOptionHiiVendorDevicePath = { 77 { 78 { 79 HARDWARE_DEVICE_PATH, 80 HW_VENDOR_DP, 81 { 82 (UINT8) (sizeof (VENDOR_DEVICE_PATH)), 83 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) 84 } 85 }, 86 { 0x6bc75598, 0x89b4, 0x483d, { 0x91, 0x60, 0x7f, 0x46, 0x9a, 0x96, 0x35, 0x31 } } 87 }, 88 { 89 END_DEVICE_PATH_TYPE, 90 END_ENTIRE_DEVICE_PATH_SUBTYPE, 91 { 92 (UINT8) (END_DEVICE_PATH_LENGTH), 93 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) 94 } 95 } 96 }; 97 98 99 /** 100 Re-order the Boot Option according to the DevOrder. 101 102 The routine re-orders the Boot Option in BootOption array according to 103 the order specified by DevOrder. 104 105 @param DevOrder Pointer to buffer containing the BBS Index, 106 high 8-bit value 0xFF indicating a disabled boot option 107 @param DevOrderCount Count of the BBS Index 108 @param EnBootOption Callee allocated buffer containing the enabled Boot Option Numbers 109 @param EnBootOptionCount Count of the enabled Boot Option Numbers 110 @param DisBootOption Callee allocated buffer containing the disabled Boot Option Numbers 111 @param DisBootOptionCount Count of the disabled Boot Option Numbers 112 **/ 113 VOID 114 OrderLegacyBootOption4SameType ( 115 UINT16 *DevOrder, 116 UINTN DevOrderCount, 117 UINT16 **EnBootOption, 118 UINTN *EnBootOptionCount, 119 UINT16 **DisBootOption, 120 UINTN *DisBootOptionCount 121 ) 122 { 123 EFI_STATUS Status; 124 UINT16 *NewBootOption; 125 UINT16 *BootOrder; 126 UINTN BootOrderSize; 127 UINTN Index; 128 UINTN StartPosition; 129 130 EFI_BOOT_MANAGER_LOAD_OPTION BootOption; 131 132 CHAR16 OptionName[sizeof ("Boot####")]; 133 UINT16 *BbsIndexArray; 134 UINT16 *DeviceTypeArray; 135 136 GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize); 137 ASSERT (BootOrder != NULL); 138 139 BbsIndexArray = AllocatePool (BootOrderSize); 140 DeviceTypeArray = AllocatePool (BootOrderSize); 141 *EnBootOption = AllocatePool (BootOrderSize); 142 *DisBootOption = AllocatePool (BootOrderSize); 143 *DisBootOptionCount = 0; 144 *EnBootOptionCount = 0; 145 Index = 0; 146 147 ASSERT (BbsIndexArray != NULL); 148 ASSERT (DeviceTypeArray != NULL); 149 ASSERT (*EnBootOption != NULL); 150 ASSERT (*DisBootOption != NULL); 151 152 for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { 153 154 UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]); 155 Status = EfiBootManagerVariableToLoadOption (OptionName, &BootOption); 156 ASSERT_EFI_ERROR (Status); 157 158 if ((DevicePathType (BootOption.FilePath) == BBS_DEVICE_PATH) && 159 (DevicePathSubType (BootOption.FilePath) == BBS_BBS_DP)) { 160 // 161 // Legacy Boot Option 162 // 163 ASSERT (BootOption.OptionalDataSize == sizeof (LEGACY_BOOT_OPTION_BBS_DATA)); 164 165 DeviceTypeArray[Index] = ((BBS_BBS_DEVICE_PATH *) BootOption.FilePath)->DeviceType; 166 BbsIndexArray [Index] = ((LEGACY_BOOT_OPTION_BBS_DATA *) BootOption.OptionalData)->BbsIndex; 167 } else { 168 DeviceTypeArray[Index] = BBS_TYPE_UNKNOWN; 169 BbsIndexArray [Index] = 0xFFFF; 170 } 171 EfiBootManagerFreeLoadOption (&BootOption); 172 } 173 174 // 175 // Record the corresponding Boot Option Numbers according to the DevOrder 176 // Record the EnBootOption and DisBootOption according to the DevOrder 177 // 178 StartPosition = BootOrderSize / sizeof (UINT16); 179 NewBootOption = AllocatePool (DevOrderCount * sizeof (UINT16)); 180 ASSERT (NewBootOption != NULL); 181 while (DevOrderCount-- != 0) { 182 for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { 183 if (BbsIndexArray[Index] == (DevOrder[DevOrderCount] & 0xFF)) { 184 StartPosition = MIN (StartPosition, Index); 185 NewBootOption[DevOrderCount] = BootOrder[Index]; 186 187 if ((DevOrder[DevOrderCount] & 0xFF00) == 0xFF00) { 188 (*DisBootOption)[*DisBootOptionCount] = BootOrder[Index]; 189 (*DisBootOptionCount)++; 190 } else { 191 (*EnBootOption)[*EnBootOptionCount] = BootOrder[Index]; 192 (*EnBootOptionCount)++; 193 } 194 break; 195 } 196 } 197 } 198 199 // 200 // Overwrite the old BootOption 201 // 202 CopyMem (&BootOrder[StartPosition], NewBootOption, (*DisBootOptionCount + *EnBootOptionCount) * sizeof (UINT16)); 203 Status = gRT->SetVariable ( 204 L"BootOrder", 205 &gEfiGlobalVariableGuid, 206 VAR_FLAG, 207 BootOrderSize, 208 BootOrder 209 ); 210 ASSERT_EFI_ERROR (Status); 211 212 FreePool (NewBootOption); 213 FreePool (DeviceTypeArray); 214 FreePool (BbsIndexArray); 215 } 216 217 /** 218 Update the legacy BBS boot option. L"LegacyDevOrder" and gEfiLegacyDevOrderVariableGuid EFI Variable 219 is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid 220 is also updated. 221 222 @param NVMapData The data for egacy BBS boot. 223 224 @return EFI_SUCCESS The function completed successfully. 225 @retval EFI_NOT_FOUND If L"LegacyDevOrder" and gEfiLegacyDevOrderVariableGuid EFI Variable can be found. 226 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource 227 **/ 228 EFI_STATUS 229 UpdateBBSOption ( 230 IN LEGACY_BOOT_NV_DATA *NVMapData 231 ) 232 { 233 UINTN Index; 234 UINTN Index2; 235 UINTN CurrentType; 236 VOID *BootOptionVar; 237 CHAR16 VarName[100]; 238 UINTN OptionSize; 239 EFI_STATUS Status; 240 UINT32 *Attribute; 241 LEGACY_MENU_OPTION *OptionMenu; 242 UINT16 *LegacyDev; 243 UINT16 *InitialLegacyDev; 244 UINT8 *VarData; 245 UINTN VarSize; 246 LEGACY_DEV_ORDER_ENTRY *DevOrder; 247 UINT8 *OriginalPtr; 248 UINT8 *DisMap; 249 UINTN Pos; 250 UINTN Bit; 251 UINT16 *NewOrder; 252 UINT16 Tmp; 253 UINT16 *EnBootOption; 254 UINTN EnBootOptionCount; 255 UINT16 *DisBootOption; 256 UINTN DisBootOptionCount; 257 UINTN BufferSize; 258 259 260 DisMap = NULL; 261 NewOrder = NULL; 262 CurrentType = 0; 263 264 265 DisMap = mLegacyBootOptionPrivate->MaintainMapData->DisableMap; 266 Status = EFI_SUCCESS; 267 268 // 269 // Update the Variable "LegacyDevOrder" 270 // 271 GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &VarData, &VarSize); 272 if (VarData == NULL) { 273 return EFI_NOT_FOUND; 274 } 275 OriginalPtr = VarData; 276 277 while (mBbsType[CurrentType] != BBS_UNKNOWN) { 278 switch (mBbsType[CurrentType]) { 279 case BBS_FLOPPY: 280 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyFDMenu; 281 LegacyDev = NVMapData->LegacyFD; 282 InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyFD; 283 BufferSize = sizeof (NVMapData->LegacyFD); 284 break; 285 286 case BBS_HARDDISK: 287 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyHDMenu; 288 LegacyDev = NVMapData->LegacyHD; 289 InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyHD; 290 291 BufferSize = sizeof (NVMapData->LegacyHD); 292 break; 293 294 case BBS_CDROM: 295 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyCDMenu; 296 LegacyDev = NVMapData->LegacyCD; 297 InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyCD; 298 BufferSize = sizeof (NVMapData->LegacyCD); 299 break; 300 301 case BBS_EMBED_NETWORK: 302 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyNETMenu; 303 LegacyDev = NVMapData->LegacyNET; 304 InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyNET; 305 BufferSize = sizeof (NVMapData->LegacyNET); 306 break; 307 308 default: 309 ASSERT (mBbsType[CurrentType] == BBS_BEV_DEVICE); 310 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyBEVMenu; 311 LegacyDev = NVMapData->LegacyBEV; 312 InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyBEV; 313 BufferSize = sizeof (NVMapData->LegacyBEV); 314 break; 315 } 316 317 // 318 // Check whether has value changed. 319 // 320 if (CompareMem (LegacyDev, InitialLegacyDev, BufferSize) == 0) { 321 CurrentType++; 322 continue; 323 } 324 325 DevOrder = (LEGACY_DEV_ORDER_ENTRY *) OriginalPtr; 326 while (VarData < OriginalPtr + VarSize) { 327 if (DevOrder->BbsType == mBbsType[CurrentType]) { 328 break; 329 } 330 331 VarData += sizeof (BBS_TYPE) + DevOrder->Length; 332 DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; 333 } 334 335 if (VarData >= OriginalPtr + VarSize) { 336 FreePool (OriginalPtr); 337 return EFI_NOT_FOUND; 338 } 339 340 NewOrder = AllocateZeroPool (DevOrder->Length - sizeof (DevOrder->Length)); 341 if (NewOrder == NULL) { 342 FreePool (OriginalPtr); 343 return EFI_OUT_OF_RESOURCES; 344 } 345 346 for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { 347 if (0xFF == LegacyDev[Index]) { 348 break; 349 } 350 351 NewOrder[Index] = LegacyDev[Index]; 352 } 353 354 // 355 // Only the enable/disable state of each boot device with same device type can be changed, 356 // so we can count on the index information in DevOrder. 357 // DisMap bit array is the only reliable source to check a device's en/dis state, 358 // so we use DisMap to set en/dis state of each item in NewOrder array 359 // 360 for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) { 361 Tmp = (UINT16) (DevOrder->Data[Index2] & 0xFF); 362 Pos = Tmp / 8; 363 Bit = 7 - (Tmp % 8); 364 if ((DisMap[Pos] & (1 << Bit)) != 0) { 365 NewOrder[Index] = (UINT16) (0xFF00 | Tmp); 366 Index++; 367 } 368 } 369 370 CopyMem ( 371 DevOrder->Data, 372 NewOrder, 373 DevOrder->Length - sizeof (DevOrder->Length) 374 ); 375 FreePool (NewOrder); 376 377 // 378 // Update BootOrder and Boot####.Attribute 379 // 380 // 1. Re-order the Option Number in BootOrder according to Legacy Dev Order 381 // 382 ASSERT (OptionMenu->MenuNumber == DevOrder->Length / sizeof (UINT16) - 1); 383 384 OrderLegacyBootOption4SameType ( 385 DevOrder->Data, 386 DevOrder->Length / sizeof (UINT16) - 1, 387 &EnBootOption, 388 &EnBootOptionCount, 389 &DisBootOption, 390 &DisBootOptionCount 391 ); 392 393 // 394 // 2. Deactivate the DisBootOption and activate the EnBootOption 395 // 396 for (Index = 0; Index < DisBootOptionCount; Index++) { 397 UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", DisBootOption[Index]); 398 GetEfiGlobalVariable2 (VarName, (VOID **) &BootOptionVar, &OptionSize); 399 if (BootOptionVar != NULL) { 400 Attribute = (UINT32 *) BootOptionVar; 401 *Attribute &= ~LOAD_OPTION_ACTIVE; 402 403 Status = gRT->SetVariable ( 404 VarName, 405 &gEfiGlobalVariableGuid, 406 VAR_FLAG, 407 OptionSize, 408 BootOptionVar 409 ); 410 411 FreePool (BootOptionVar); 412 } 413 } 414 415 for (Index = 0; Index < EnBootOptionCount; Index++) { 416 UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", EnBootOption[Index]); 417 GetEfiGlobalVariable2 (VarName, (VOID **) &BootOptionVar, &OptionSize); 418 if (BootOptionVar != NULL) { 419 Attribute = (UINT32 *) BootOptionVar; 420 *Attribute |= LOAD_OPTION_ACTIVE; 421 422 Status = gRT->SetVariable ( 423 VarName, 424 &gEfiGlobalVariableGuid, 425 VAR_FLAG, 426 OptionSize, 427 BootOptionVar 428 ); 429 430 FreePool (BootOptionVar); 431 } 432 } 433 434 435 FreePool (EnBootOption); 436 FreePool (DisBootOption); 437 438 CurrentType++; 439 } 440 441 Status = gRT->SetVariable ( 442 VAR_LEGACY_DEV_ORDER, 443 &gEfiLegacyDevOrderVariableGuid, 444 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, 445 VarSize, 446 OriginalPtr 447 ); 448 449 FreePool (OriginalPtr); 450 return Status; 451 } 452 453 /** 454 This function allows a caller to extract the current configuration for one 455 or more named elements from the target driver. 456 457 458 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. 459 @param Request A null-terminated Unicode string in <ConfigRequest> format. 460 @param Progress On return, points to a character in the Request string. 461 Points to the string's null terminator if request was successful. 462 Points to the most recent '&' before the first failing name/value 463 pair (or the beginning of the string if the failure is in the 464 first name/value pair) if the request was not successful. 465 @param Results A null-terminated Unicode string in <ConfigAltResp> format which 466 has all values filled in for the names in the Request string. 467 String to be allocated by the called function. 468 469 @retval EFI_SUCCESS The Results is filled with the requested values. 470 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. 471 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. 472 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. 473 474 **/ 475 EFI_STATUS 476 EFIAPI 477 LegacyBootOptionExtractConfig ( 478 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, 479 IN CONST EFI_STRING Request, 480 OUT EFI_STRING *Progress, 481 OUT EFI_STRING *Results 482 ) 483 { 484 if (Progress == NULL || Results == NULL) { 485 return EFI_INVALID_PARAMETER; 486 } 487 *Progress = Request; 488 return EFI_NOT_FOUND; 489 } 490 491 /** 492 This function processes the results of changes in configuration. 493 494 495 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. 496 @param Configuration A null-terminated Unicode string in <ConfigResp> format. 497 @param Progress A pointer to a string filled in with the offset of the most 498 recent '&' before the first failing name/value pair (or the 499 beginning of the string if the failure is in the first 500 name/value pair) or the terminating NULL if all was successful. 501 502 @retval EFI_SUCCESS The Results is processed successfully. 503 @retval EFI_INVALID_PARAMETER Configuration is NULL. 504 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. 505 506 **/ 507 EFI_STATUS 508 EFIAPI 509 LegacyBootOptionRouteConfig ( 510 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, 511 IN CONST EFI_STRING Configuration, 512 OUT EFI_STRING *Progress 513 ) 514 { 515 EFI_STATUS Status; 516 EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting; 517 LEGACY_BOOT_NV_DATA *CurrentNVMapData; 518 UINTN BufferSize; 519 520 521 if (Configuration == NULL || Progress == NULL) { 522 return EFI_INVALID_PARAMETER; 523 } 524 525 // 526 // Check routing data in <ConfigHdr>. 527 // Note: there is no name for Name/Value storage, only GUID will be checked 528 // 529 if (!HiiIsConfigHdrMatch (Configuration, &mLegacyBootOptionGuid, mLegacyBootStorageName)) { 530 return EFI_NOT_FOUND; 531 } 532 533 Status = gBS->LocateProtocol ( 534 &gEfiHiiConfigRoutingProtocolGuid, 535 NULL, 536 (VOID **) &ConfigRouting 537 ); 538 if (EFI_ERROR (Status)) { 539 return Status; 540 } 541 542 // 543 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock() 544 // 545 CurrentNVMapData = &mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData; 546 Status = ConfigRouting->ConfigToBlock ( 547 ConfigRouting, 548 Configuration, 549 (UINT8 *) CurrentNVMapData, 550 &BufferSize, 551 Progress 552 ); 553 ASSERT_EFI_ERROR (Status); 554 555 Status = UpdateBBSOption (CurrentNVMapData); 556 557 return Status; 558 } 559 560 /** 561 Refresh the global UpdateData structure. 562 563 **/ 564 VOID 565 RefreshLegacyUpdateData ( 566 VOID 567 ) 568 { 569 // 570 // Free current updated date 571 // 572 if (mLegacyStartOpCodeHandle != NULL) { 573 HiiFreeOpCodeHandle (mLegacyStartOpCodeHandle); 574 } 575 if (mLegacyEndOpCodeHandle != NULL) { 576 HiiFreeOpCodeHandle (mLegacyEndOpCodeHandle); 577 } 578 579 // 580 // Create new OpCode Handle 581 // 582 mLegacyStartOpCodeHandle = HiiAllocateOpCodeHandle (); 583 mLegacyEndOpCodeHandle = HiiAllocateOpCodeHandle (); 584 585 // 586 // Create Hii Extend Label OpCode as the start opcode 587 // 588 mLegacyStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( 589 mLegacyStartOpCodeHandle, 590 &gEfiIfrTianoGuid, 591 NULL, 592 sizeof (EFI_IFR_GUID_LABEL) 593 ); 594 mLegacyStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; 595 596 mLegacyStartLabel->Number = FORM_BOOT_LEGACY_DEVICE_ID; 597 598 // 599 // Create Hii Extend Label OpCode as the start opcode 600 // 601 mLegacyEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( 602 mLegacyEndOpCodeHandle, 603 &gEfiIfrTianoGuid, 604 NULL, 605 sizeof (EFI_IFR_GUID_LABEL) 606 ); 607 mLegacyEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; 608 609 mLegacyEndLabel->Number = FORM_BOOT_LEGACY_LABEL_END; 610 611 } 612 613 /** 614 Get the Menu Entry from the list in Menu Entry List. 615 616 If MenuNumber is great or equal to the number of Menu 617 Entry in the list, then ASSERT. 618 619 @param MenuOption The Menu Entry List to read the menu entry. 620 @param MenuNumber The index of Menu Entry. 621 622 @return The Menu Entry. 623 624 **/ 625 LEGACY_MENU_ENTRY * 626 GetMenuEntry ( 627 LEGACY_MENU_OPTION *MenuOption, 628 UINTN MenuNumber 629 ) 630 { 631 LEGACY_MENU_ENTRY *NewMenuEntry; 632 UINTN Index; 633 LIST_ENTRY *List; 634 635 ASSERT (MenuNumber < MenuOption->MenuNumber); 636 637 List = MenuOption->Head.ForwardLink; 638 for (Index = 0; Index < MenuNumber; Index++) { 639 List = List->ForwardLink; 640 } 641 642 NewMenuEntry = CR (List, LEGACY_MENU_ENTRY, Link, LEGACY_MENU_ENTRY_SIGNATURE); 643 644 return NewMenuEntry; 645 } 646 647 /** 648 Create string tokens for a menu from its help strings and display strings 649 650 @param HiiHandle Hii Handle of the package to be updated. 651 @param MenuOption The Menu whose string tokens need to be created 652 653 **/ 654 VOID 655 CreateLegacyMenuStringToken ( 656 IN EFI_HII_HANDLE HiiHandle, 657 IN LEGACY_MENU_OPTION *MenuOption 658 ) 659 { 660 LEGACY_MENU_ENTRY *NewMenuEntry; 661 UINTN Index; 662 663 for (Index = 0; Index < MenuOption->MenuNumber; Index++) { 664 NewMenuEntry = GetMenuEntry (MenuOption, Index); 665 666 NewMenuEntry->DisplayStringToken = HiiSetString ( 667 HiiHandle, 668 0, 669 NewMenuEntry->DisplayString, 670 NULL 671 ); 672 673 if (NULL == NewMenuEntry->HelpString) { 674 NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken; 675 } else { 676 NewMenuEntry->HelpStringToken = HiiSetString ( 677 HiiHandle, 678 0, 679 NewMenuEntry->HelpString, 680 NULL 681 ); 682 } 683 } 684 } 685 686 /** 687 Create a dynamic page so that Legacy Device boot order 688 can be set for specified device type. 689 690 @param UpdatePageId The form ID. It also spefies the legacy device type. 691 692 693 **/ 694 VOID 695 UpdateLegacyDeviceOrderPage ( 696 IN UINT16 UpdatePageId 697 ) 698 { 699 LEGACY_MENU_OPTION *OptionMenu; 700 LEGACY_MENU_ENTRY *NewMenuEntry; 701 EFI_STRING_ID StrRef; 702 EFI_STRING_ID StrRefHelp; 703 BBS_TYPE BbsType; 704 UINT16 *Default; 705 UINT16 Index; 706 UINT16 Key; 707 CHAR16 String[100]; 708 CHAR16 *TypeStr; 709 CHAR16 *TypeStrHelp; 710 CHAR16 *FormTitle; 711 VOID *OptionsOpCodeHandle; 712 VOID *DefaultOpCodeHandle; 713 714 Key = 0; 715 StrRef = 0; 716 StrRefHelp = 0; 717 OptionMenu = NULL; 718 TypeStr = NULL; 719 TypeStrHelp = NULL; 720 Default = NULL; 721 BbsType = BBS_FLOPPY; 722 723 RefreshLegacyUpdateData(); 724 725 // 726 // Create oneof option list 727 // 728 switch (UpdatePageId) { 729 case FORM_FLOPPY_BOOT_ID: 730 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyFDMenu; 731 Key = (UINT16) LEGACY_FD_QUESTION_ID; 732 TypeStr = STR_FLOPPY; 733 TypeStrHelp = STR_FLOPPY_HELP; 734 FormTitle = STR_FLOPPY_TITLE; 735 BbsType = BBS_FLOPPY; 736 Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyFD; 737 break; 738 739 case FORM_HARDDISK_BOOT_ID: 740 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyHDMenu; 741 Key = (UINT16) LEGACY_HD_QUESTION_ID; 742 TypeStr = STR_HARDDISK; 743 TypeStrHelp = STR_HARDDISK_HELP; 744 FormTitle = STR_HARDDISK_TITLE; 745 BbsType = BBS_HARDDISK; 746 Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyHD; 747 break; 748 749 case FORM_CDROM_BOOT_ID: 750 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyCDMenu; 751 Key = (UINT16) LEGACY_CD_QUESTION_ID; 752 TypeStr = STR_CDROM; 753 TypeStrHelp = STR_CDROM_HELP; 754 FormTitle = STR_CDROM_TITLE; 755 BbsType = BBS_CDROM; 756 Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyCD; 757 break; 758 759 case FORM_NET_BOOT_ID: 760 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyNETMenu; 761 Key = (UINT16) LEGACY_NET_QUESTION_ID; 762 TypeStr = STR_NET; 763 TypeStrHelp = STR_NET_HELP; 764 FormTitle = STR_NET_TITLE; 765 BbsType = BBS_EMBED_NETWORK; 766 Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyNET; 767 break; 768 769 case FORM_BEV_BOOT_ID: 770 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyBEVMenu; 771 Key = (UINT16) LEGACY_BEV_QUESTION_ID; 772 TypeStr = STR_BEV; 773 TypeStrHelp = STR_BEV_HELP; 774 FormTitle = STR_BEV_TITLE; 775 BbsType = BBS_BEV_DEVICE; 776 Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyBEV; 777 break; 778 779 default: 780 DEBUG ((EFI_D_ERROR, "Invalid command ID for updating page!\n")); 781 return; 782 } 783 784 HiiSetString (mLegacyBootOptionPrivate->HiiHandle, STRING_TOKEN(STR_ORDER_CHANGE_PROMPT), FormTitle, NULL); 785 786 CreateLegacyMenuStringToken (mLegacyBootOptionPrivate->HiiHandle, OptionMenu); 787 788 OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); 789 ASSERT (OptionsOpCodeHandle != NULL); 790 791 792 for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { 793 NewMenuEntry = GetMenuEntry (OptionMenu, Index); 794 // 795 // Create OneOf for each legacy device 796 // 797 HiiCreateOneOfOptionOpCode ( 798 OptionsOpCodeHandle, 799 NewMenuEntry->DisplayStringToken, 800 0, 801 EFI_IFR_TYPE_NUM_SIZE_16, 802 ((LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext)->BbsIndex 803 ); 804 } 805 806 // 807 // Create OneOf for item "Disabled" 808 // 809 HiiCreateOneOfOptionOpCode ( 810 OptionsOpCodeHandle, 811 STRING_TOKEN (STR_DISABLE_LEGACY_DEVICE), 812 0, 813 EFI_IFR_TYPE_NUM_SIZE_16, 814 0xFF 815 ); 816 817 // 818 // Create oneof tag here for FD/HD/CD #1 #2 819 // 820 for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { 821 DefaultOpCodeHandle = HiiAllocateOpCodeHandle (); 822 ASSERT (DefaultOpCodeHandle != NULL); 823 824 HiiCreateDefaultOpCode ( 825 DefaultOpCodeHandle, 826 EFI_HII_DEFAULT_CLASS_STANDARD, 827 EFI_IFR_TYPE_NUM_SIZE_16, 828 *Default++ 829 ); 830 831 // 832 // Create the string for oneof tag 833 // 834 UnicodeSPrint (String, sizeof (String), TypeStr, Index); 835 StrRef = HiiSetString (mLegacyBootOptionPrivate->HiiHandle, 0, String, NULL); 836 837 UnicodeSPrint (String, sizeof (String), TypeStrHelp, Index); 838 StrRefHelp = HiiSetString (mLegacyBootOptionPrivate->HiiHandle, 0, String, NULL); 839 840 HiiCreateOneOfOpCode ( 841 mLegacyStartOpCodeHandle, 842 (EFI_QUESTION_ID) (Key + Index), 843 VARSTORE_ID_LEGACY_BOOT, 844 (UINT16) (Key + Index * 2 - CONFIG_OPTION_OFFSET), 845 StrRef, 846 StrRefHelp, 847 EFI_IFR_FLAG_CALLBACK, 848 EFI_IFR_NUMERIC_SIZE_2, 849 OptionsOpCodeHandle, 850 DefaultOpCodeHandle //NULL // 851 ); 852 853 HiiFreeOpCodeHandle (DefaultOpCodeHandle); 854 } 855 856 HiiUpdateForm ( 857 mLegacyBootOptionPrivate->HiiHandle, 858 &mLegacyBootOptionGuid, 859 LEGACY_ORDER_CHANGE_FORM_ID, 860 mLegacyStartOpCodeHandle, 861 mLegacyEndOpCodeHandle 862 ); 863 864 HiiFreeOpCodeHandle (OptionsOpCodeHandle); 865 } 866 867 868 /** 869 Adjust question value when one question value has been changed. 870 871 @param QuestionId The question id for the value changed question. 872 @param Value The value for the changed question. 873 874 **/ 875 VOID 876 AdjustOptionValue ( 877 IN UINT16 QuestionId, 878 IN EFI_IFR_TYPE_VALUE *Value 879 ) 880 { 881 UINTN Number; 882 BBS_TYPE BbsType; 883 LEGACY_DEV_ORDER_ENTRY *DevOrder; 884 UINT16 *Default; 885 LEGACY_BOOT_NV_DATA *CurrentNVMap; 886 UINT16 *CurrentVal; 887 UINTN Index; 888 UINTN Index2; 889 UINTN Index3; 890 UINTN NewValuePos; 891 UINTN OldValue; 892 UINTN NewValue; 893 UINT8 *DisMap; 894 UINTN Pos; 895 UINTN Bit; 896 897 Number = 0; 898 BbsType = BBS_UNKNOWN; 899 CurrentVal = 0; 900 DevOrder = NULL; 901 Default = NULL; 902 NewValue = 0; 903 NewValuePos = 0; 904 OldValue = 0; 905 906 // 907 // Update Select FD/HD/CD/NET/BEV Order Form 908 // 909 ASSERT ((QuestionId >= LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER)); 910 911 CurrentNVMap = &mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData; 912 HiiGetBrowserData (&mLegacyBootOptionGuid, mLegacyBootStorageName, sizeof (LEGACY_BOOT_NV_DATA), (UINT8 *) CurrentNVMap); 913 DisMap = mLegacyBootOptionPrivate->MaintainMapData->DisableMap; 914 915 if (QuestionId >= LEGACY_FD_QUESTION_ID && QuestionId < LEGACY_FD_QUESTION_ID + MAX_MENU_NUMBER) { 916 Number = (UINT16) LegacyFDMenu.MenuNumber; 917 BbsType = BBS_FLOPPY; 918 CurrentVal = CurrentNVMap->LegacyFD; 919 Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyFD; 920 } else if (QuestionId >= LEGACY_HD_QUESTION_ID && QuestionId < LEGACY_HD_QUESTION_ID + MAX_MENU_NUMBER) { 921 Number = (UINT16) LegacyHDMenu.MenuNumber; 922 BbsType = BBS_HARDDISK; 923 CurrentVal = CurrentNVMap->LegacyHD; 924 Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyHD; 925 } else if (QuestionId >= LEGACY_CD_QUESTION_ID && QuestionId < LEGACY_CD_QUESTION_ID + MAX_MENU_NUMBER) { 926 Number = (UINT16) LegacyCDMenu.MenuNumber; 927 BbsType = BBS_CDROM; 928 CurrentVal = CurrentNVMap->LegacyCD; 929 Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyCD; 930 } else if (QuestionId >= LEGACY_NET_QUESTION_ID && QuestionId < LEGACY_NET_QUESTION_ID + MAX_MENU_NUMBER) { 931 Number = (UINT16) LegacyNETMenu.MenuNumber; 932 BbsType = BBS_EMBED_NETWORK; 933 CurrentVal = CurrentNVMap->LegacyNET; 934 Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyNET; 935 } else if (QuestionId >= LEGACY_BEV_QUESTION_ID && QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER) { 936 Number = (UINT16) LegacyBEVMenu.MenuNumber; 937 BbsType = BBS_BEV_DEVICE; 938 CurrentVal = CurrentNVMap->LegacyBEV; 939 Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyBEV; 940 } 941 942 // 943 // First, find the different position 944 // if there is change, it should be only one 945 // 946 for (Index = 0; Index < Number; Index++) { 947 if (CurrentVal[Index] != Default[Index]) { 948 OldValue = Default[Index]; 949 NewValue = CurrentVal[Index]; 950 break; 951 } 952 } 953 954 if (Index != Number) { 955 // 956 // there is change, now process 957 // 958 if (0xFF == NewValue) { 959 // 960 // This item will be disable 961 // Just move the items behind this forward to overlap it 962 // 963 Pos = OldValue / 8; 964 Bit = 7 - (OldValue % 8); 965 DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); 966 for (Index2 = Index; Index2 < Number - 1; Index2++) { 967 CurrentVal[Index2] = CurrentVal[Index2 + 1]; 968 } 969 970 CurrentVal[Index2] = 0xFF; 971 } else { 972 for (Index2 = 0; Index2 < Number; Index2++) { 973 if (Index2 == Index) { 974 continue; 975 } 976 977 if (Default[Index2] == NewValue) { 978 // 979 // If NewValue is in OldLegacyDev array 980 // remember its old position 981 // 982 NewValuePos = Index2; 983 break; 984 } 985 } 986 987 if (Index2 != Number) { 988 // 989 // We will change current item to an existing item 990 // (It's hard to describe here, please read code, it's like a cycle-moving) 991 // 992 for (Index2 = NewValuePos; Index2 != Index;) { 993 if (NewValuePos < Index) { 994 CurrentVal[Index2] = Default[Index2 + 1]; 995 Index2++; 996 } else { 997 CurrentVal[Index2] = Default[Index2 - 1]; 998 Index2--; 999 } 1000 } 1001 } else { 1002 // 1003 // If NewValue is not in OldlegacyDev array, we are changing to a disabled item 1004 // so we should modify DisMap to reflect the change 1005 // 1006 Pos = NewValue / 8; 1007 Bit = 7 - (NewValue % 8); 1008 DisMap[Pos] = (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit))); 1009 if (0xFF != OldValue) { 1010 // 1011 // Because NewValue is a item that was disabled before 1012 // so after changing the OldValue should be disabled 1013 // actually we are doing a swap of enable-disable states of two items 1014 // 1015 Pos = OldValue / 8; 1016 Bit = 7 - (OldValue % 8); 1017 DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); 1018 } 1019 } 1020 } 1021 // 1022 // To prevent DISABLE appears in the middle of the list 1023 // we should perform a re-ordering 1024 // 1025 Index3 = Index; 1026 Index = 0; 1027 while (Index < Number) { 1028 if (0xFF != CurrentVal[Index]) { 1029 Index++; 1030 continue; 1031 } 1032 1033 Index2 = Index; 1034 Index2++; 1035 while (Index2 < Number) { 1036 if (0xFF != CurrentVal[Index2]) { 1037 break; 1038 } 1039 1040 Index2++; 1041 } 1042 1043 if (Index2 < Number) { 1044 CurrentVal[Index] = CurrentVal[Index2]; 1045 CurrentVal[Index2] = 0xFF; 1046 } 1047 1048 Index++; 1049 } 1050 1051 // 1052 // Return correct question value. 1053 // 1054 Value->u16 = CurrentVal[Index3]; 1055 CopyMem (Default, CurrentVal, sizeof (UINT16) * Number); 1056 } 1057 1058 // 1059 // Pass changed uncommitted data back to Form Browser 1060 // 1061 HiiSetBrowserData (&mLegacyBootOptionGuid, mLegacyBootStorageName, sizeof (LEGACY_BOOT_NV_DATA), (UINT8 *) CurrentNVMap, NULL); 1062 } 1063 1064 /** 1065 This call back function is registered with Boot Manager formset. 1066 When user selects a boot option, this call back function will 1067 be triggered. The boot option is saved for later processing. 1068 1069 1070 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. 1071 @param Action Specifies the type of action taken by the browser. 1072 @param QuestionId A unique value which is sent to the original exporting driver 1073 so that it can identify the type of data to expect. 1074 @param Type The type of value for the question. 1075 @param Value A pointer to the data being sent to the original exporting driver. 1076 @param ActionRequest On return, points to the action requested by the callback function. 1077 1078 @retval EFI_SUCCESS The callback successfully handled the action. 1079 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. 1080 1081 **/ 1082 EFI_STATUS 1083 EFIAPI 1084 LegacyBootOptionCallback ( 1085 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, 1086 IN EFI_BROWSER_ACTION Action, 1087 IN EFI_QUESTION_ID QuestionId, 1088 IN UINT8 Type, 1089 IN EFI_IFR_TYPE_VALUE *Value, 1090 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest 1091 ) 1092 { 1093 if (Action != EFI_BROWSER_ACTION_CHANGED && Action != EFI_BROWSER_ACTION_CHANGING) { 1094 // 1095 // Do nothing for other UEFI Action. Only do call back when data is changed. 1096 // 1097 return EFI_UNSUPPORTED; 1098 } 1099 1100 if ((Value == NULL) || (ActionRequest == NULL)) { 1101 return EFI_INVALID_PARAMETER; 1102 } 1103 1104 if (Action == EFI_BROWSER_ACTION_CHANGING) { 1105 switch (QuestionId) { 1106 case FORM_FLOPPY_BOOT_ID: 1107 case FORM_HARDDISK_BOOT_ID: 1108 case FORM_CDROM_BOOT_ID: 1109 case FORM_NET_BOOT_ID: 1110 case FORM_BEV_BOOT_ID: 1111 UpdateLegacyDeviceOrderPage (QuestionId); 1112 break; 1113 1114 default: 1115 break; 1116 } 1117 } else if (Action == EFI_BROWSER_ACTION_CHANGED) { 1118 if ((Value == NULL) || (ActionRequest == NULL)) { 1119 return EFI_INVALID_PARAMETER; 1120 } 1121 1122 if ((QuestionId >= LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER)) { 1123 AdjustOptionValue(QuestionId, Value); 1124 } 1125 } 1126 return EFI_SUCCESS; 1127 } 1128 1129 1130 /** 1131 Create a menu entry by given menu type. 1132 1133 @param MenuType The Menu type to be created. 1134 1135 @retval NULL If failed to create the menu. 1136 @return the new menu entry. 1137 1138 **/ 1139 LEGACY_MENU_ENTRY * 1140 CreateMenuEntry ( 1141 VOID 1142 ) 1143 { 1144 LEGACY_MENU_ENTRY *MenuEntry; 1145 1146 // 1147 // Create new menu entry 1148 // 1149 MenuEntry = AllocateZeroPool (sizeof (LEGACY_MENU_ENTRY)); 1150 if (MenuEntry == NULL) { 1151 return NULL; 1152 } 1153 1154 MenuEntry->VariableContext = AllocateZeroPool (sizeof (LEGACY_DEVICE_CONTEXT)); 1155 if (MenuEntry->VariableContext == NULL) { 1156 FreePool (MenuEntry); 1157 return NULL; 1158 } 1159 1160 MenuEntry->Signature = LEGACY_MENU_ENTRY_SIGNATURE; 1161 return MenuEntry; 1162 } 1163 1164 /** 1165 1166 Base on the L"LegacyDevOrder" variable to build the current order data. 1167 1168 **/ 1169 VOID 1170 GetLegacyOptionsOrder ( 1171 VOID 1172 ) 1173 { 1174 UINTN VarSize; 1175 UINT8 *VarData; 1176 UINT8 *VarTmp; 1177 LEGACY_DEV_ORDER_ENTRY *DevOrder; 1178 UINT16 *LegacyDev; 1179 UINTN Index; 1180 LEGACY_MENU_OPTION *OptionMenu; 1181 UINT16 VarDevOrder; 1182 UINTN Pos; 1183 UINTN Bit; 1184 UINT8 *DisMap; 1185 UINTN TotalLength; 1186 1187 LegacyDev = NULL; 1188 OptionMenu = NULL; 1189 1190 DisMap = ZeroMem (mLegacyBootOptionPrivate->MaintainMapData->DisableMap, sizeof (mLegacyBootOptionPrivate->MaintainMapData->DisableMap)); 1191 1192 // 1193 // Get Device Order from variable 1194 // 1195 GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &VarData, &VarSize); 1196 VarTmp = VarData; 1197 if (NULL != VarData) { 1198 DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; 1199 while (VarData < VarTmp + VarSize) { 1200 switch (DevOrder->BbsType) { 1201 case BBS_FLOPPY: 1202 LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyFD; 1203 OptionMenu = &LegacyFDMenu; 1204 break; 1205 1206 case BBS_HARDDISK: 1207 LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyHD; 1208 OptionMenu = &LegacyHDMenu; 1209 break; 1210 1211 case BBS_CDROM: 1212 LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyCD; 1213 OptionMenu = &LegacyCDMenu; 1214 break; 1215 1216 case BBS_EMBED_NETWORK: 1217 LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyNET; 1218 OptionMenu = &LegacyNETMenu; 1219 break; 1220 1221 case BBS_BEV_DEVICE: 1222 LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyBEV; 1223 OptionMenu = &LegacyBEVMenu; 1224 break; 1225 1226 case BBS_UNKNOWN: 1227 default: 1228 ASSERT (FALSE); 1229 DEBUG ((DEBUG_ERROR, "Unsupported device type found!\n")); 1230 break; 1231 } 1232 1233 // 1234 // Create oneof tag here for FD/HD/CD #1 #2 1235 // 1236 for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { 1237 TotalLength = sizeof (BBS_TYPE) + sizeof (UINT16) + Index * sizeof (UINT16); 1238 VarDevOrder = *(UINT16 *) ((UINT8 *) DevOrder + TotalLength); 1239 1240 if (0xFF00 == (VarDevOrder & 0xFF00)) { 1241 LegacyDev[Index] = 0xFF; 1242 Pos = (VarDevOrder & 0xFF) / 8; 1243 Bit = 7 - ((VarDevOrder & 0xFF) % 8); 1244 DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); 1245 } else { 1246 LegacyDev[Index] = VarDevOrder & 0xFF; 1247 } 1248 } 1249 1250 VarData ++; 1251 VarData += *(UINT16 *) VarData; 1252 DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; 1253 } 1254 } 1255 1256 CopyMem (&mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData, &mLegacyBootOptionPrivate->MaintainMapData->InitialNvData, sizeof (LEGACY_BOOT_NV_DATA)); 1257 CopyMem (&mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData, &mLegacyBootOptionPrivate->MaintainMapData->InitialNvData, sizeof (LEGACY_BOOT_NV_DATA)); 1258 } 1259 1260 /** 1261 1262 Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo(). 1263 1264 **/ 1265 VOID 1266 GetLegacyOptions ( 1267 VOID 1268 ) 1269 { 1270 LEGACY_MENU_ENTRY *NewMenuEntry; 1271 LEGACY_DEVICE_CONTEXT *NewLegacyDevContext; 1272 EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; 1273 UINTN BootOptionCount; 1274 UINT16 Index; 1275 UINTN FDNum; 1276 UINTN HDNum; 1277 UINTN CDNum; 1278 UINTN NETNum; 1279 UINTN BEVNum; 1280 1281 // 1282 // Initialize Bbs Table Context from BBS info data 1283 // 1284 InitializeListHead (&LegacyFDMenu.Head); 1285 InitializeListHead (&LegacyHDMenu.Head); 1286 InitializeListHead (&LegacyCDMenu.Head); 1287 InitializeListHead (&LegacyNETMenu.Head); 1288 InitializeListHead (&LegacyBEVMenu.Head); 1289 1290 FDNum = 0; 1291 HDNum = 0; 1292 CDNum = 0; 1293 NETNum = 0; 1294 BEVNum = 0; 1295 1296 EfiBootManagerConnectAll (); 1297 1298 // 1299 // for better user experience 1300 // 1. User changes HD configuration (e.g.: unplug HDD), here we have a chance to remove the HDD boot option 1301 // 2. User enables/disables UEFI PXE, here we have a chance to add/remove EFI Network boot option 1302 // 1303 EfiBootManagerRefreshAllBootOption (); 1304 1305 BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); 1306 for (Index = 0; Index < BootOptionCount; Index++) { 1307 if ((DevicePathType (BootOption[Index].FilePath) != BBS_DEVICE_PATH) || 1308 (DevicePathSubType (BootOption[Index].FilePath) != BBS_BBS_DP) 1309 ) { 1310 continue; 1311 } 1312 ASSERT (BootOption[Index].OptionalDataSize == sizeof (LEGACY_BOOT_OPTION_BBS_DATA)); 1313 NewMenuEntry = CreateMenuEntry (); 1314 ASSERT (NewMenuEntry != NULL); 1315 1316 NewLegacyDevContext = (LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext; 1317 NewLegacyDevContext->BbsIndex = ((LEGACY_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex; 1318 NewLegacyDevContext->Description = AllocateCopyPool (StrSize (BootOption[Index].Description), BootOption[Index].Description); 1319 ASSERT (NewLegacyDevContext->Description != NULL); 1320 1321 NewMenuEntry->DisplayString = NewLegacyDevContext->Description; 1322 NewMenuEntry->HelpString = NULL; 1323 1324 switch (((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType) { 1325 case BBS_TYPE_FLOPPY: 1326 InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link); 1327 FDNum++; 1328 break; 1329 1330 case BBS_TYPE_HARDDRIVE: 1331 InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link); 1332 HDNum++; 1333 break; 1334 1335 case BBS_TYPE_CDROM: 1336 InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link); 1337 CDNum++; 1338 break; 1339 1340 case BBS_TYPE_EMBEDDED_NETWORK: 1341 InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link); 1342 NETNum++; 1343 break; 1344 1345 case BBS_TYPE_BEV: 1346 InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link); 1347 BEVNum++; 1348 break; 1349 } 1350 } 1351 1352 EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount); 1353 1354 LegacyFDMenu.MenuNumber = FDNum; 1355 LegacyHDMenu.MenuNumber = HDNum; 1356 LegacyCDMenu.MenuNumber = CDNum; 1357 LegacyNETMenu.MenuNumber = NETNum; 1358 LegacyBEVMenu.MenuNumber = BEVNum; 1359 } 1360 1361 1362 /** 1363 1364 Install Boot Manager Menu driver. 1365 1366 @param ImageHandle The image handle. 1367 @param SystemTable The system table. 1368 1369 @retval EFI_SUCEESS Install Boot manager menu success. 1370 @retval Other Return error status. 1371 1372 **/ 1373 EFI_STATUS 1374 EFIAPI 1375 LegacyBootMaintUiLibConstructor ( 1376 IN EFI_HANDLE ImageHandle, 1377 IN EFI_SYSTEM_TABLE *SystemTable 1378 ) 1379 { 1380 EFI_STATUS Status; 1381 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; 1382 LEGACY_BOOT_OPTION_CALLBACK_DATA *LegacyBootOptionData; 1383 1384 Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); 1385 if (!EFI_ERROR (Status)) { 1386 // 1387 // Create LegacyBootOptionData structures for Driver Callback 1388 // 1389 LegacyBootOptionData = AllocateZeroPool (sizeof (LEGACY_BOOT_OPTION_CALLBACK_DATA)); 1390 ASSERT (LegacyBootOptionData != NULL); 1391 1392 LegacyBootOptionData->MaintainMapData = AllocateZeroPool (sizeof (LEGACY_BOOT_MAINTAIN_DATA)); 1393 ASSERT (LegacyBootOptionData->MaintainMapData != NULL); 1394 1395 LegacyBootOptionData->ConfigAccess.ExtractConfig = LegacyBootOptionExtractConfig; 1396 LegacyBootOptionData->ConfigAccess.RouteConfig = LegacyBootOptionRouteConfig; 1397 LegacyBootOptionData->ConfigAccess.Callback = LegacyBootOptionCallback; 1398 1399 // 1400 // Install Device Path Protocol and Config Access protocol to driver handle 1401 // 1402 Status = gBS->InstallMultipleProtocolInterfaces ( 1403 &LegacyBootOptionData->DriverHandle, 1404 &gEfiDevicePathProtocolGuid, 1405 &mLegacyBootOptionHiiVendorDevicePath, 1406 &gEfiHiiConfigAccessProtocolGuid, 1407 &LegacyBootOptionData->ConfigAccess, 1408 NULL 1409 ); 1410 ASSERT_EFI_ERROR (Status); 1411 1412 // 1413 // Publish our HII data 1414 // 1415 LegacyBootOptionData->HiiHandle = HiiAddPackages ( 1416 &mLegacyBootOptionGuid, 1417 LegacyBootOptionData->DriverHandle, 1418 LegacyBootMaintUiVfrBin, 1419 LegacyBootMaintUiLibStrings, 1420 NULL 1421 ); 1422 ASSERT (LegacyBootOptionData->HiiHandle != NULL); 1423 1424 mLegacyBootOptionPrivate = LegacyBootOptionData; 1425 1426 GetLegacyOptions (); 1427 1428 GetLegacyOptionsOrder(); 1429 } 1430 1431 return EFI_SUCCESS; 1432 } 1433 1434 /** 1435 Destructor of Customized Display Library Instance. 1436 1437 @param ImageHandle The firmware allocated handle for the EFI image. 1438 @param SystemTable A pointer to the EFI System Table. 1439 1440 @retval EFI_SUCCESS The destructor completed successfully. 1441 @retval Other value The destructor did not complete successfully. 1442 1443 **/ 1444 EFI_STATUS 1445 EFIAPI 1446 LegacyBootMaintUiLibDestructor ( 1447 IN EFI_HANDLE ImageHandle, 1448 IN EFI_SYSTEM_TABLE *SystemTable 1449 ) 1450 { 1451 EFI_STATUS Status; 1452 1453 if (mLegacyBootOptionPrivate->DriverHandle != NULL) { 1454 Status = gBS->UninstallMultipleProtocolInterfaces ( 1455 mLegacyBootOptionPrivate->DriverHandle, 1456 &gEfiDevicePathProtocolGuid, 1457 &mLegacyBootOptionHiiVendorDevicePath, 1458 &gEfiHiiConfigAccessProtocolGuid, 1459 &mLegacyBootOptionPrivate->ConfigAccess, 1460 NULL 1461 ); 1462 ASSERT_EFI_ERROR (Status); 1463 1464 HiiRemovePackages (mLegacyBootOptionPrivate->HiiHandle); 1465 1466 FreePool (mLegacyBootOptionPrivate->MaintainMapData); 1467 FreePool (mLegacyBootOptionPrivate); 1468 } 1469 1470 return EFI_SUCCESS; 1471 } 1472 1473