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