1 /*++ 2 3 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR> 4 This program and the accompanying materials 5 are licensed and made available under the terms and conditions of the BSD License 6 which accompanies this distribution. The full text of the license may be found at 7 http://opensource.org/licenses/bsd-license.php 8 9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 12 Module Name: 13 14 BdsPlatform.c 15 16 Abstract: 17 18 This file include all platform action which can be customized 19 by IBV/OEM. 20 21 --*/ 22 23 #include "BdsPlatform.h" 24 25 #define IS_PCI_ISA_PDECODE(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0) 26 27 extern BOOLEAN gConnectAllHappened; 28 extern USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath; 29 30 EFI_GUID *gTableGuidArray[] = { 31 &gEfiAcpi20TableGuid, &gEfiAcpiTableGuid, &gEfiSmbiosTableGuid, &gEfiMpsTableGuid 32 }; 33 34 // 35 // BDS Platform Functions 36 // 37 38 VOID 39 GetSystemTablesFromHob ( 40 VOID 41 ) 42 /*++ 43 44 Routine Description: 45 Find GUID'ed HOBs that contain EFI_PHYSICAL_ADDRESS of ACPI, SMBIOS, MPs tables 46 47 Arguments: 48 None 49 50 Returns: 51 None. 52 53 --*/ 54 { 55 EFI_PEI_HOB_POINTERS GuidHob; 56 EFI_PEI_HOB_POINTERS HobStart; 57 EFI_PHYSICAL_ADDRESS *Table; 58 UINTN Index; 59 60 // 61 // Get Hob List 62 // 63 HobStart.Raw = GetHobList (); 64 // 65 // Iteratively add ACPI Table, SMBIOS Table, MPS Table to EFI System Table 66 // 67 for (Index = 0; Index < ARRAY_SIZE (gTableGuidArray); ++Index) { 68 GuidHob.Raw = GetNextGuidHob (gTableGuidArray[Index], HobStart.Raw); 69 if (GuidHob.Raw != NULL) { 70 Table = GET_GUID_HOB_DATA (GuidHob.Guid); 71 if (Table != NULL) { 72 // 73 // Check if Mps Table/Smbios Table/Acpi Table exists in E/F seg, 74 // According to UEFI Spec, we should make sure Smbios table, 75 // ACPI table and Mps tables kept in memory of specified type 76 // 77 ConvertSystemTable(gTableGuidArray[Index], (VOID**)&Table); 78 gBS->InstallConfigurationTable (gTableGuidArray[Index], (VOID *)Table); 79 } 80 } 81 } 82 83 return ; 84 } 85 86 #if 0 87 VOID 88 PrintMemoryMap ( 89 VOID 90 ) 91 { 92 EFI_MEMORY_DESCRIPTOR *MemMap; 93 EFI_MEMORY_DESCRIPTOR *MemMapPtr; 94 UINTN MemMapSize; 95 UINTN MapKey, DescriptorSize; 96 UINTN Index; 97 UINT32 DescriptorVersion; 98 UINT64 Bytes; 99 EFI_STATUS Status; 100 101 MemMapSize = 0; 102 MemMap = NULL; 103 Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion); 104 ASSERT (Status == EFI_BUFFER_TOO_SMALL); 105 MemMapSize += EFI_PAGE_SIZE; 106 Status = gBS->AllocatePool (EfiBootServicesData, MemMapSize, &MemMap); 107 ASSERT (Status == EFI_SUCCESS); 108 Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion); 109 ASSERT (Status == EFI_SUCCESS); 110 MemMapPtr = MemMap; 111 112 ASSERT (DescriptorVersion == EFI_MEMORY_DESCRIPTOR_VERSION); 113 114 for (Index = 0; Index < MemMapSize / DescriptorSize; Index ++) { 115 Bytes = LShiftU64 (MemMap->NumberOfPages, 12); 116 DEBUG ((EFI_D_ERROR, "%lX-%lX %lX %lX %X\n", 117 MemMap->PhysicalStart, 118 MemMap->PhysicalStart + Bytes - 1, 119 MemMap->NumberOfPages, 120 MemMap->Attribute, 121 (UINTN)MemMap->Type)); 122 MemMap = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemMap + DescriptorSize); 123 } 124 125 gBS->FreePool (MemMapPtr); 126 } 127 #endif 128 129 VOID 130 UpdateMemoryMap ( 131 VOID 132 ) 133 { 134 EFI_STATUS Status; 135 EFI_PEI_HOB_POINTERS GuidHob; 136 VOID *Table; 137 MEMORY_DESC_HOB MemoryDescHob; 138 UINTN Index; 139 EFI_PHYSICAL_ADDRESS Memory; 140 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; 141 142 GuidHob.Raw = GetFirstGuidHob (&gLdrMemoryDescriptorGuid); 143 if (GuidHob.Raw == NULL) { 144 DEBUG ((EFI_D_ERROR, "Fail to get gEfiLdrMemoryDescriptorGuid from GUID HOB LIST!\n")); 145 return; 146 } 147 Table = GET_GUID_HOB_DATA (GuidHob.Guid); 148 if (Table == NULL) { 149 DEBUG ((EFI_D_ERROR, "Fail to get gEfiLdrMemoryDescriptorGuid from GUID HOB LIST!\n")); 150 return; 151 } 152 MemoryDescHob.MemDescCount = *(UINTN *)Table; 153 MemoryDescHob.MemDesc = *(EFI_MEMORY_DESCRIPTOR **)((UINTN)Table + sizeof(UINTN)); 154 155 // 156 // Add ACPINVS, ACPIReclaim, and Reserved memory to MemoryMap 157 // 158 for (Index = 0; Index < MemoryDescHob.MemDescCount; Index++) { 159 if (MemoryDescHob.MemDesc[Index].PhysicalStart < 0x100000) { 160 continue; 161 } 162 if (MemoryDescHob.MemDesc[Index].PhysicalStart >= 0x100000000ULL) { 163 continue; 164 } 165 if ((MemoryDescHob.MemDesc[Index].Type == EfiReservedMemoryType) || 166 (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesData) || 167 (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesCode) || 168 (MemoryDescHob.MemDesc[Index].Type == EfiACPIReclaimMemory) || 169 (MemoryDescHob.MemDesc[Index].Type == EfiACPIMemoryNVS)) { 170 DEBUG ((EFI_D_ERROR, "PhysicalStart - 0x%016lx, ", MemoryDescHob.MemDesc[Index].PhysicalStart)); 171 DEBUG ((EFI_D_ERROR, "PageNumber - 0x%016lx, ", MemoryDescHob.MemDesc[Index].NumberOfPages)); 172 DEBUG ((EFI_D_ERROR, "Attribute - 0x%016lx, ", MemoryDescHob.MemDesc[Index].Attribute)); 173 DEBUG ((EFI_D_ERROR, "Type - 0x%08x\n", MemoryDescHob.MemDesc[Index].Type)); 174 if ((MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesData) || 175 (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesCode)) { 176 // 177 // For RuntimeSevicesData and RuntimeServicesCode, they are BFV or DxeCore. 178 // The memory type is assigned in EfiLdr 179 // 180 Status = gDS->GetMemorySpaceDescriptor (MemoryDescHob.MemDesc[Index].PhysicalStart, &Descriptor); 181 if (EFI_ERROR (Status)) { 182 continue; 183 } 184 if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeReserved) { 185 // 186 // BFV or tested DXE core 187 // 188 continue; 189 } 190 // 191 // Untested DXE Core region, free and remove 192 // 193 Status = gDS->FreeMemorySpace ( 194 MemoryDescHob.MemDesc[Index].PhysicalStart, 195 LShiftU64 (MemoryDescHob.MemDesc[Index].NumberOfPages, EFI_PAGE_SHIFT) 196 ); 197 if (EFI_ERROR (Status)) { 198 DEBUG ((EFI_D_ERROR, "FreeMemorySpace fail - %r!\n", Status)); 199 continue; 200 } 201 Status = gDS->RemoveMemorySpace ( 202 MemoryDescHob.MemDesc[Index].PhysicalStart, 203 LShiftU64 (MemoryDescHob.MemDesc[Index].NumberOfPages, EFI_PAGE_SHIFT) 204 ); 205 if (EFI_ERROR (Status)) { 206 DEBUG ((EFI_D_ERROR, "RemoveMemorySpace fail - %r!\n", Status)); 207 continue; 208 } 209 210 // 211 // Convert Runtime type to BootTime type 212 // 213 if (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesData) { 214 MemoryDescHob.MemDesc[Index].Type = EfiBootServicesData; 215 } else { 216 MemoryDescHob.MemDesc[Index].Type = EfiBootServicesCode; 217 } 218 219 // 220 // PassThrough, let below code add and alloate. 221 // 222 } 223 // 224 // ACPI or reserved memory 225 // 226 Status = gDS->AddMemorySpace ( 227 EfiGcdMemoryTypeSystemMemory, 228 MemoryDescHob.MemDesc[Index].PhysicalStart, 229 LShiftU64 (MemoryDescHob.MemDesc[Index].NumberOfPages, EFI_PAGE_SHIFT), 230 MemoryDescHob.MemDesc[Index].Attribute 231 ); 232 if (EFI_ERROR (Status)) { 233 DEBUG ((EFI_D_ERROR, "AddMemorySpace fail - %r!\n", Status)); 234 if ((MemoryDescHob.MemDesc[Index].Type == EfiACPIReclaimMemory) || 235 (MemoryDescHob.MemDesc[Index].Type == EfiACPIMemoryNVS)) { 236 // 237 // For EfiACPIReclaimMemory and EfiACPIMemoryNVS, it must success. 238 // For EfiReservedMemoryType, there maybe overlap. So skip check here. 239 // 240 // ASSERT_EFI_ERROR (Status); 241 } 242 continue; 243 } 244 245 Memory = MemoryDescHob.MemDesc[Index].PhysicalStart; 246 Status = gBS->AllocatePages ( 247 AllocateAddress, 248 (EFI_MEMORY_TYPE)MemoryDescHob.MemDesc[Index].Type, 249 (UINTN)MemoryDescHob.MemDesc[Index].NumberOfPages, 250 &Memory 251 ); 252 if (EFI_ERROR (Status)) { 253 DEBUG ((EFI_D_ERROR, "AllocatePages fail - %r!\n", Status)); 254 // 255 // For the page added, it must be allocated. 256 // 257 // ASSERT_EFI_ERROR (Status); 258 continue; 259 } 260 } 261 } 262 263 } 264 265 EFI_STATUS 266 DisableUsbLegacySupport( 267 void 268 ) 269 /*++ 270 271 Routine Description: 272 Disabble the USB legacy Support in all Ehci and Uhci. 273 This function assume all PciIo handles have been created in system. 274 275 Arguments: 276 None 277 278 Returns: 279 EFI_SUCCESS 280 EFI_NOT_FOUND 281 --*/ 282 { 283 EFI_STATUS Status; 284 EFI_HANDLE *HandleArray; 285 UINTN HandleArrayCount; 286 UINTN Index; 287 EFI_PCI_IO_PROTOCOL *PciIo; 288 UINT8 Class[3]; 289 UINT16 Command; 290 UINT32 HcCapParams; 291 UINT32 ExtendCap; 292 UINT32 Value; 293 UINT32 TimeOut; 294 295 // 296 // Find the usb host controller 297 // 298 Status = gBS->LocateHandleBuffer ( 299 ByProtocol, 300 &gEfiPciIoProtocolGuid, 301 NULL, 302 &HandleArrayCount, 303 &HandleArray 304 ); 305 if (!EFI_ERROR (Status)) { 306 for (Index = 0; Index < HandleArrayCount; Index++) { 307 Status = gBS->HandleProtocol ( 308 HandleArray[Index], 309 &gEfiPciIoProtocolGuid, 310 (VOID **)&PciIo 311 ); 312 if (!EFI_ERROR (Status)) { 313 // 314 // Find the USB host controller controller 315 // 316 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class); 317 if (!EFI_ERROR (Status)) { 318 if ((PCI_CLASS_SERIAL == Class[2]) && 319 (PCI_CLASS_SERIAL_USB == Class[1])) { 320 if (PCI_IF_UHCI == Class[0]) { 321 // 322 // Found the UHCI, then disable the legacy support 323 // 324 Command = 0; 325 Status = PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0xC0, 1, &Command); 326 } else if (PCI_IF_EHCI == Class[0]) { 327 // 328 // Found the EHCI, then disable the legacy support 329 // 330 Status = PciIo->Mem.Read ( 331 PciIo, 332 EfiPciIoWidthUint32, 333 0, //EHC_BAR_INDEX 334 (UINT64) 0x08, //EHC_HCCPARAMS_OFFSET 335 1, 336 &HcCapParams 337 ); 338 339 ExtendCap = (HcCapParams >> 8) & 0xFF; 340 // 341 // Disable the SMI in USBLEGCTLSTS firstly 342 // 343 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value); 344 Value &= 0xFFFF0000; 345 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value); 346 347 // 348 // Get EHCI Ownership from legacy bios 349 // 350 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value); 351 Value |= (0x1 << 24); 352 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value); 353 354 TimeOut = 40; 355 while (TimeOut--) { 356 gBS->Stall (500); 357 358 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value); 359 360 if ((Value & 0x01010000) == 0x01000000) { 361 break; 362 } 363 } 364 } 365 } 366 } 367 } 368 } 369 } else { 370 return Status; 371 } 372 gBS->FreePool (HandleArray); 373 return EFI_SUCCESS; 374 } 375 376 377 VOID 378 EFIAPI 379 PlatformBdsInit ( 380 VOID 381 ) 382 /*++ 383 384 Routine Description: 385 386 Platform Bds init. Include the platform firmware vendor, revision 387 and so crc check. 388 389 Arguments: 390 391 Returns: 392 393 None. 394 395 --*/ 396 { 397 GetSystemTablesFromHob (); 398 399 UpdateMemoryMap (); 400 401 // 402 // Append Usb Keyboard short form DevicePath into "ConInDev" 403 // 404 BdsLibUpdateConsoleVariable ( 405 VarConsoleInpDev, 406 (EFI_DEVICE_PATH_PROTOCOL *) &gUsbClassKeyboardDevicePath, 407 NULL 408 ); 409 } 410 411 UINT64 412 GetPciExpressBaseAddressForRootBridge ( 413 IN UINTN HostBridgeNumber, 414 IN UINTN RootBridgeNumber 415 ) 416 /*++ 417 418 Routine Description: 419 This routine is to get PciExpress Base Address for this RootBridge 420 421 Arguments: 422 HostBridgeNumber - The number of HostBridge 423 RootBridgeNumber - The number of RootBridge 424 425 Returns: 426 UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge 427 428 --*/ 429 { 430 EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION *PciExpressBaseAddressInfo; 431 UINTN BufferSize; 432 UINT32 Index; 433 UINT32 Number; 434 EFI_PEI_HOB_POINTERS GuidHob; 435 436 // 437 // Get PciExpressAddressInfo Hob 438 // 439 PciExpressBaseAddressInfo = NULL; 440 BufferSize = 0; 441 GuidHob.Raw = GetFirstGuidHob (&gEfiPciExpressBaseAddressGuid); 442 if (GuidHob.Raw != NULL) { 443 PciExpressBaseAddressInfo = GET_GUID_HOB_DATA (GuidHob.Guid); 444 BufferSize = GET_GUID_HOB_DATA_SIZE (GuidHob.Guid); 445 } else { 446 return 0; 447 } 448 449 // 450 // Search the PciExpress Base Address in the Hob for current RootBridge 451 // 452 Number = (UINT32)(BufferSize / sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION)); 453 for (Index = 0; Index < Number; Index++) { 454 if ((PciExpressBaseAddressInfo[Index].HostBridgeNumber == HostBridgeNumber) && 455 (PciExpressBaseAddressInfo[Index].RootBridgeNumber == RootBridgeNumber)) { 456 return PciExpressBaseAddressInfo[Index].PciExpressBaseAddress; 457 } 458 } 459 460 // 461 // Do not find the PciExpress Base Address in the Hob 462 // 463 return 0; 464 } 465 466 VOID 467 PatchPciRootBridgeDevicePath ( 468 IN UINTN HostBridgeNumber, 469 IN UINTN RootBridgeNumber, 470 IN PLATFORM_ROOT_BRIDGE_DEVICE_PATH *RootBridge 471 ) 472 { 473 UINT64 PciExpressBase; 474 475 PciExpressBase = GetPciExpressBaseAddressForRootBridge (HostBridgeNumber, RootBridgeNumber); 476 477 DEBUG ((EFI_D_INFO, "Get PciExpress Address from Hob: 0x%X\n", PciExpressBase)); 478 479 if (PciExpressBase != 0) { 480 RootBridge->PciRootBridge.HID = EISA_PNP_ID(0x0A08); 481 } 482 } 483 484 EFI_STATUS 485 ConnectRootBridge ( 486 VOID 487 ) 488 /*++ 489 490 Routine Description: 491 492 Connect RootBridge 493 494 Arguments: 495 496 None. 497 498 Returns: 499 500 EFI_SUCCESS - Connect RootBridge successfully. 501 EFI_STATUS - Connect RootBridge fail. 502 503 --*/ 504 { 505 EFI_STATUS Status; 506 EFI_HANDLE RootHandle; 507 508 // 509 // Patch Pci Root Bridge Device Path 510 // 511 PatchPciRootBridgeDevicePath (0, 0, &gPlatformRootBridge0); 512 513 // 514 // Make all the PCI_IO protocols on PCI Seg 0 show up 515 // 516 BdsLibConnectDevicePath (gPlatformRootBridges[0]); 517 518 Status = gBS->LocateDevicePath ( 519 &gEfiDevicePathProtocolGuid, 520 &gPlatformRootBridges[0], 521 &RootHandle 522 ); 523 DEBUG ((EFI_D_INFO, "Pci Root bridge handle is 0x%X\n", RootHandle)); 524 525 if (EFI_ERROR (Status)) { 526 return Status; 527 } 528 529 Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE); 530 if (EFI_ERROR (Status)) { 531 return Status; 532 } 533 534 return EFI_SUCCESS; 535 } 536 537 EFI_STATUS 538 PrepareLpcBridgeDevicePath ( 539 IN EFI_HANDLE DeviceHandle 540 ) 541 /*++ 542 543 Routine Description: 544 545 Add IsaKeyboard to ConIn, 546 add IsaSerial to ConOut, ConIn, ErrOut. 547 LPC Bridge: 06 01 00 548 549 Arguments: 550 551 DeviceHandle - Handle of PCIIO protocol. 552 553 Returns: 554 555 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut. 556 EFI_STATUS - No LPC bridge is added. 557 558 --*/ 559 { 560 EFI_STATUS Status; 561 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 562 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; 563 564 DevicePath = NULL; 565 Status = gBS->HandleProtocol ( 566 DeviceHandle, 567 &gEfiDevicePathProtocolGuid, 568 (VOID*)&DevicePath 569 ); 570 if (EFI_ERROR (Status)) { 571 return Status; 572 } 573 TempDevicePath = DevicePath; 574 575 // 576 // Register Keyboard 577 // 578 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode); 579 580 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL); 581 582 // 583 // Register COM1 584 // 585 DevicePath = TempDevicePath; 586 gPnp16550ComPortDeviceNode.UID = 0; 587 588 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode); 589 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode); 590 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode); 591 592 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL); 593 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL); 594 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL); 595 596 // 597 // Register COM2 598 // 599 DevicePath = TempDevicePath; 600 gPnp16550ComPortDeviceNode.UID = 1; 601 602 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode); 603 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode); 604 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode); 605 606 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL); 607 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL); 608 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL); 609 610 return EFI_SUCCESS; 611 } 612 613 EFI_STATUS 614 GetGopDevicePath ( 615 IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath, 616 OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath 617 ) 618 { 619 UINTN Index; 620 EFI_STATUS Status; 621 EFI_HANDLE PciDeviceHandle; 622 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; 623 EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath; 624 UINTN GopHandleCount; 625 EFI_HANDLE *GopHandleBuffer; 626 627 if (PciDevicePath == NULL || GopDevicePath == NULL) { 628 return EFI_INVALID_PARAMETER; 629 } 630 631 // 632 // Initialize the GopDevicePath to be PciDevicePath 633 // 634 *GopDevicePath = PciDevicePath; 635 TempPciDevicePath = PciDevicePath; 636 637 Status = gBS->LocateDevicePath ( 638 &gEfiDevicePathProtocolGuid, 639 &TempPciDevicePath, 640 &PciDeviceHandle 641 ); 642 if (EFI_ERROR (Status)) { 643 return Status; 644 } 645 646 // 647 // Try to connect this handle, so that GOP driver could start on this 648 // device and create child handles with GraphicsOutput Protocol installed 649 // on them, then we get device paths of these child handles and select 650 // them as possible console device. 651 // 652 gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE); 653 654 Status = gBS->LocateHandleBuffer ( 655 ByProtocol, 656 &gEfiGraphicsOutputProtocolGuid, 657 NULL, 658 &GopHandleCount, 659 &GopHandleBuffer 660 ); 661 if (!EFI_ERROR (Status)) { 662 // 663 // Add all the child handles as possible Console Device 664 // 665 for (Index = 0; Index < GopHandleCount; Index++) { 666 Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath); 667 if (EFI_ERROR (Status)) { 668 continue; 669 } 670 if (CompareMem ( 671 PciDevicePath, 672 TempDevicePath, 673 GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH 674 ) == 0) { 675 // 676 // In current implementation, we only enable one of the child handles 677 // as console device, i.e. sotre one of the child handle's device 678 // path to variable "ConOut" 679 // In future, we could select all child handles to be console device 680 // 681 682 *GopDevicePath = TempDevicePath; 683 684 // 685 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath() 686 // Add the integrity GOP device path. 687 // 688 BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath); 689 BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL); 690 } 691 } 692 gBS->FreePool (GopHandleBuffer); 693 } 694 695 return EFI_SUCCESS; 696 } 697 698 EFI_STATUS 699 PreparePciVgaDevicePath ( 700 IN EFI_HANDLE DeviceHandle 701 ) 702 /*++ 703 704 Routine Description: 705 706 Add PCI VGA to ConOut. 707 PCI VGA: 03 00 00 708 709 Arguments: 710 711 DeviceHandle - Handle of PCIIO protocol. 712 713 Returns: 714 715 EFI_SUCCESS - PCI VGA is added to ConOut. 716 EFI_STATUS - No PCI VGA device is added. 717 718 --*/ 719 { 720 EFI_STATUS Status; 721 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 722 EFI_DEVICE_PATH_PROTOCOL *GopDevicePath; 723 724 DevicePath = NULL; 725 GopDevicePath = NULL; 726 Status = gBS->HandleProtocol ( 727 DeviceHandle, 728 &gEfiDevicePathProtocolGuid, 729 (VOID*)&DevicePath 730 ); 731 if (EFI_ERROR (Status)) { 732 return Status; 733 } 734 735 GetGopDevicePath (DevicePath, &GopDevicePath); 736 DevicePath = GopDevicePath; 737 738 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL); 739 740 return EFI_SUCCESS; 741 } 742 743 EFI_STATUS 744 PreparePciSerialDevicePath ( 745 IN EFI_HANDLE DeviceHandle 746 ) 747 /*++ 748 749 Routine Description: 750 751 Add PCI Serial to ConOut, ConIn, ErrOut. 752 PCI Serial: 07 00 02 753 754 Arguments: 755 756 DeviceHandle - Handle of PCIIO protocol. 757 758 Returns: 759 760 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut. 761 EFI_STATUS - No PCI Serial device is added. 762 763 --*/ 764 { 765 EFI_STATUS Status; 766 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 767 768 DevicePath = NULL; 769 Status = gBS->HandleProtocol ( 770 DeviceHandle, 771 &gEfiDevicePathProtocolGuid, 772 (VOID*)&DevicePath 773 ); 774 if (EFI_ERROR (Status)) { 775 return Status; 776 } 777 778 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode); 779 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode); 780 781 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL); 782 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL); 783 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL); 784 785 return EFI_SUCCESS; 786 } 787 788 EFI_STATUS 789 DetectAndPreparePlatformPciDevicePath ( 790 BOOLEAN DetectVgaOnly 791 ) 792 /*++ 793 794 Routine Description: 795 796 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut 797 798 Arguments: 799 800 DetectVgaOnly - Only detect VGA device if it's TRUE. 801 802 Returns: 803 804 EFI_SUCCESS - PCI Device check and Console variable update successfully. 805 EFI_STATUS - PCI Device check or Console variable update fail. 806 807 --*/ 808 { 809 EFI_STATUS Status; 810 UINTN HandleCount; 811 EFI_HANDLE *HandleBuffer; 812 UINTN Index; 813 EFI_PCI_IO_PROTOCOL *PciIo; 814 PCI_TYPE00 Pci; 815 816 // 817 // Start to check all the PciIo to find all possible device 818 // 819 HandleCount = 0; 820 HandleBuffer = NULL; 821 Status = gBS->LocateHandleBuffer ( 822 ByProtocol, 823 &gEfiPciIoProtocolGuid, 824 NULL, 825 &HandleCount, 826 &HandleBuffer 827 ); 828 if (EFI_ERROR (Status)) { 829 return Status; 830 } 831 832 for (Index = 0; Index < HandleCount; Index++) { 833 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID*)&PciIo); 834 if (EFI_ERROR (Status)) { 835 continue; 836 } 837 838 // 839 // Check for all PCI device 840 // 841 Status = PciIo->Pci.Read ( 842 PciIo, 843 EfiPciIoWidthUint32, 844 0, 845 sizeof (Pci) / sizeof (UINT32), 846 &Pci 847 ); 848 if (EFI_ERROR (Status)) { 849 continue; 850 } 851 852 if (!DetectVgaOnly) { 853 // 854 // Here we decide whether it is LPC Bridge 855 // 856 if ((IS_PCI_LPC (&Pci)) || 857 ((IS_PCI_ISA_PDECODE (&Pci)) && (Pci.Hdr.VendorId == 0x8086) && (Pci.Hdr.DeviceId == 0x7110))) { 858 // 859 // Add IsaKeyboard to ConIn, 860 // add IsaSerial to ConOut, ConIn, ErrOut 861 // 862 DEBUG ((EFI_D_INFO, "Find the LPC Bridge device\n")); 863 PrepareLpcBridgeDevicePath (HandleBuffer[Index]); 864 continue; 865 } 866 // 867 // Here we decide which Serial device to enable in PCI bus 868 // 869 if (IS_PCI_16550SERIAL (&Pci)) { 870 // 871 // Add them to ConOut, ConIn, ErrOut. 872 // 873 DEBUG ((EFI_D_INFO, "Find the 16550 SERIAL device\n")); 874 PreparePciSerialDevicePath (HandleBuffer[Index]); 875 continue; 876 } 877 } 878 879 // 880 // Here we decide which VGA device to enable in PCI bus 881 // 882 if (IS_PCI_VGA (&Pci)) { 883 // 884 // Add them to ConOut. 885 // 886 DEBUG ((EFI_D_INFO, "Find the VGA device\n")); 887 PreparePciVgaDevicePath (HandleBuffer[Index]); 888 continue; 889 } 890 } 891 892 gBS->FreePool (HandleBuffer); 893 894 return EFI_SUCCESS; 895 } 896 897 EFI_STATUS 898 PlatformBdsConnectConsole ( 899 IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole 900 ) 901 /*++ 902 903 Routine Description: 904 905 Connect the predefined platform default console device. Always try to find 906 and enable the vga device if have. 907 908 Arguments: 909 910 PlatformConsole - Predefined platform default console device array. 911 912 Returns: 913 914 EFI_SUCCESS - Success connect at least one ConIn and ConOut 915 device, there must have one ConOut device is 916 active vga device. 917 918 EFI_STATUS - Return the status of 919 BdsLibConnectAllDefaultConsoles () 920 921 --*/ 922 { 923 EFI_STATUS Status; 924 UINTN Index; 925 EFI_DEVICE_PATH_PROTOCOL *VarConout; 926 EFI_DEVICE_PATH_PROTOCOL *VarConin; 927 UINTN DevicePathSize; 928 929 // 930 // Connect RootBridge 931 // 932 ConnectRootBridge (); 933 934 VarConout = BdsLibGetVariableAndSize ( 935 VarConsoleOut, 936 &gEfiGlobalVariableGuid, 937 &DevicePathSize 938 ); 939 VarConin = BdsLibGetVariableAndSize ( 940 VarConsoleInp, 941 &gEfiGlobalVariableGuid, 942 &DevicePathSize 943 ); 944 945 if (VarConout == NULL || VarConin == NULL) { 946 // 947 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut 948 // 949 DetectAndPreparePlatformPciDevicePath (FALSE); 950 951 // 952 // Have chance to connect the platform default console, 953 // the platform default console is the minimum device group 954 // the platform should support 955 // 956 for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) { 957 // 958 // Update the console variable with the connect type 959 // 960 if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) { 961 BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL); 962 } 963 if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) { 964 BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL); 965 } 966 if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) { 967 BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL); 968 } 969 } 970 } else { 971 // 972 // Only detect VGA device and add them to ConOut 973 // 974 DetectAndPreparePlatformPciDevicePath (TRUE); 975 } 976 977 // 978 // The ConIn devices connection will start the USB bus, should disable all 979 // Usb legacy support firstly. 980 // Caution: Must ensure the PCI bus driver has been started. Since the 981 // ConnectRootBridge() will create all the PciIo protocol, it's safe here now 982 // 983 Status = DisableUsbLegacySupport(); 984 985 // 986 // Connect the all the default console with current cosole variable 987 // 988 Status = BdsLibConnectAllDefaultConsoles (); 989 if (EFI_ERROR (Status)) { 990 return Status; 991 } 992 993 return EFI_SUCCESS; 994 } 995 996 VOID 997 PlatformBdsConnectSequence ( 998 VOID 999 ) 1000 /*++ 1001 1002 Routine Description: 1003 1004 Connect with predefined platform connect sequence, 1005 the OEM/IBV can customize with their own connect sequence. 1006 1007 Arguments: 1008 1009 None. 1010 1011 Returns: 1012 1013 None. 1014 1015 --*/ 1016 { 1017 UINTN Index; 1018 1019 Index = 0; 1020 1021 // 1022 // Here we can get the customized platform connect sequence 1023 // Notes: we can connect with new variable which record the 1024 // last time boots connect device path sequence 1025 // 1026 while (gPlatformConnectSequence[Index] != NULL) { 1027 // 1028 // Build the platform boot option 1029 // 1030 BdsLibConnectDevicePath (gPlatformConnectSequence[Index]); 1031 Index++; 1032 } 1033 1034 } 1035 1036 VOID 1037 PlatformBdsGetDriverOption ( 1038 IN OUT LIST_ENTRY *BdsDriverLists 1039 ) 1040 /*++ 1041 1042 Routine Description: 1043 1044 Load the predefined driver option, OEM/IBV can customize this 1045 to load their own drivers 1046 1047 Arguments: 1048 1049 BdsDriverLists - The header of the driver option link list. 1050 1051 Returns: 1052 1053 None. 1054 1055 --*/ 1056 { 1057 UINTN Index; 1058 1059 Index = 0; 1060 1061 // 1062 // Here we can get the customized platform driver option 1063 // 1064 while (gPlatformDriverOption[Index] != NULL) { 1065 // 1066 // Build the platform boot option 1067 // 1068 BdsLibRegisterNewOption (BdsDriverLists, gPlatformDriverOption[Index], NULL, L"DriverOrder"); 1069 Index++; 1070 } 1071 1072 } 1073 1074 VOID 1075 PlatformBdsDiagnostics ( 1076 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel, 1077 IN BOOLEAN QuietBoot, 1078 IN BASEM_MEMORY_TEST BaseMemoryTest 1079 ) 1080 /*++ 1081 1082 Routine Description: 1083 1084 Perform the platform diagnostic, such like test memory. OEM/IBV also 1085 can customize this fuction to support specific platform diagnostic. 1086 1087 Arguments: 1088 1089 MemoryTestLevel - The memory test intensive level 1090 1091 QuietBoot - Indicate if need to enable the quiet boot 1092 1093 BaseMemoryTest - A pointer to BdsMemoryTest() 1094 1095 Returns: 1096 1097 None. 1098 1099 --*/ 1100 { 1101 EFI_STATUS Status; 1102 1103 // 1104 // Here we can decide if we need to show 1105 // the diagnostics screen 1106 // Notes: this quiet boot code should be remove 1107 // from the graphic lib 1108 // 1109 if (QuietBoot) { 1110 Status = EnableQuietBoot (PcdGetPtr(PcdLogoFile)); 1111 if (EFI_ERROR (Status)) { 1112 DisableQuietBoot (); 1113 return; 1114 } 1115 1116 // 1117 // Perform system diagnostic 1118 // 1119 Status = BaseMemoryTest (MemoryTestLevel); 1120 if (EFI_ERROR (Status)) { 1121 DisableQuietBoot (); 1122 } 1123 1124 return ; 1125 } 1126 // 1127 // Perform system diagnostic 1128 // 1129 Status = BaseMemoryTest (MemoryTestLevel); 1130 } 1131 1132 VOID 1133 EFIAPI 1134 PlatformBdsPolicyBehavior ( 1135 IN OUT LIST_ENTRY *DriverOptionList, 1136 IN OUT LIST_ENTRY *BootOptionList, 1137 IN PROCESS_CAPSULES ProcessCapsules, 1138 IN BASEM_MEMORY_TEST BaseMemoryTest 1139 ) 1140 /*++ 1141 1142 Routine Description: 1143 1144 The function will execute with as the platform policy, current policy 1145 is driven by boot mode. IBV/OEM can customize this code for their specific 1146 policy action. 1147 1148 Arguments: 1149 1150 DriverOptionList - The header of the driver option link list 1151 1152 BootOptionList - The header of the boot option link list 1153 1154 Returns: 1155 1156 None. 1157 1158 --*/ 1159 { 1160 EFI_STATUS Status; 1161 UINT16 Timeout; 1162 EFI_EVENT UserInputDurationTime; 1163 UINTN Index; 1164 EFI_INPUT_KEY Key; 1165 EFI_BOOT_MODE BootMode; 1166 1167 // 1168 // Init the time out value 1169 // 1170 Timeout = PcdGet16 (PcdPlatformBootTimeOut); 1171 1172 // 1173 // Load the driver option as the driver option list 1174 // 1175 PlatformBdsGetDriverOption (DriverOptionList); 1176 1177 // 1178 // Get current Boot Mode 1179 // 1180 Status = BdsLibGetBootMode (&BootMode); 1181 DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode)); 1182 1183 // 1184 // Go the different platform policy with different boot mode 1185 // Notes: this part code can be change with the table policy 1186 // 1187 ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION); 1188 // 1189 // Connect platform console 1190 // 1191 Status = PlatformBdsConnectConsole (gPlatformConsole); 1192 if (EFI_ERROR (Status)) { 1193 // 1194 // Here OEM/IBV can customize with defined action 1195 // 1196 PlatformBdsNoConsoleAction (); 1197 } 1198 // 1199 // Create a 300ms duration event to ensure user has enough input time to enter Setup 1200 // 1201 Status = gBS->CreateEvent ( 1202 EVT_TIMER, 1203 0, 1204 NULL, 1205 NULL, 1206 &UserInputDurationTime 1207 ); 1208 ASSERT (Status == EFI_SUCCESS); 1209 Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000); 1210 ASSERT (Status == EFI_SUCCESS); 1211 // 1212 // Memory test and Logo show 1213 // 1214 PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest); 1215 1216 // 1217 // Perform some platform specific connect sequence 1218 // 1219 PlatformBdsConnectSequence (); 1220 1221 // 1222 // Give one chance to enter the setup if we 1223 // have the time out 1224 // 1225 // BUGBUG: hard code timeout to 5 second to show logo in graphic mode. 1226 Timeout = 5; 1227 if (Timeout != 0) { 1228 PlatformBdsEnterFrontPage (Timeout, FALSE); 1229 } 1230 1231 // 1232 //BdsLibConnectAll (); 1233 //BdsLibEnumerateAllBootOption (BootOptionList); 1234 1235 // 1236 // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot 1237 // checking code in real production tip. 1238 // 1239 // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device 1240 // and do enumerate all the default boot options. But in development system board, the boot mode 1241 // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box 1242 // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot. 1243 // 1244 Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder"); 1245 if (EFI_ERROR(Status)) { 1246 // 1247 // If cannot find "BootOrder" variable, it may be first boot. 1248 // Try to connect all devices and enumerate all boot options here. 1249 // 1250 BdsLibConnectAll (); 1251 BdsLibEnumerateAllBootOption (BootOptionList); 1252 } 1253 1254 // 1255 // To give the User a chance to enter Setup here, if user set TimeOut is 0. 1256 // BDS should still give user a chance to enter Setup 1257 // Check whether the user input after the duration time has expired 1258 // 1259 gBS->WaitForEvent (1, &UserInputDurationTime, &Index); 1260 gBS->CloseEvent (UserInputDurationTime); 1261 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); 1262 1263 if (!EFI_ERROR (Status)) { 1264 // 1265 // Enter Setup if user input 1266 // 1267 Timeout = 0xffff; 1268 PlatformBdsEnterFrontPage (Timeout, FALSE); 1269 } 1270 1271 return ; 1272 1273 } 1274 1275 VOID 1276 EFIAPI 1277 PlatformBdsBootSuccess ( 1278 IN BDS_COMMON_OPTION *Option 1279 ) 1280 /*++ 1281 1282 Routine Description: 1283 1284 Hook point after a boot attempt succeeds. We don't expect a boot option to 1285 return, so the EFI 1.0 specification defines that you will default to an 1286 interactive mode and stop processing the BootOrder list in this case. This 1287 is alos a platform implementation and can be customized by IBV/OEM. 1288 1289 Arguments: 1290 1291 Option - Pointer to Boot Option that succeeded to boot. 1292 1293 Returns: 1294 1295 None. 1296 1297 --*/ 1298 { 1299 CHAR16 *TmpStr; 1300 1301 // 1302 // If Boot returned with EFI_SUCCESS and there is not in the boot device 1303 // select loop then we need to pop up a UI and wait for user input. 1304 // 1305 TmpStr = Option->StatusString; 1306 if (TmpStr != NULL) { 1307 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL); 1308 gBS->FreePool (TmpStr); 1309 } 1310 } 1311 1312 VOID 1313 EFIAPI 1314 PlatformBdsBootFail ( 1315 IN BDS_COMMON_OPTION *Option, 1316 IN EFI_STATUS Status, 1317 IN CHAR16 *ExitData, 1318 IN UINTN ExitDataSize 1319 ) 1320 /*++ 1321 1322 Routine Description: 1323 1324 Hook point after a boot attempt fails. 1325 1326 Arguments: 1327 1328 Option - Pointer to Boot Option that failed to boot. 1329 1330 Status - Status returned from failed boot. 1331 1332 ExitData - Exit data returned from failed boot. 1333 1334 ExitDataSize - Exit data size returned from failed boot. 1335 1336 Returns: 1337 1338 None. 1339 1340 --*/ 1341 { 1342 CHAR16 *TmpStr; 1343 1344 // 1345 // If Boot returned with failed status then we need to pop up a UI and wait 1346 // for user input. 1347 // 1348 TmpStr = Option->StatusString; 1349 if (TmpStr != NULL) { 1350 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL); 1351 gBS->FreePool (TmpStr); 1352 } 1353 1354 } 1355 1356 EFI_STATUS 1357 PlatformBdsNoConsoleAction ( 1358 VOID 1359 ) 1360 /*++ 1361 1362 Routine Description: 1363 1364 This function is remained for IBV/OEM to do some platform action, 1365 if there no console device can be connected. 1366 1367 Arguments: 1368 1369 None. 1370 1371 Returns: 1372 1373 EFI_SUCCESS - Direct return success now. 1374 1375 --*/ 1376 { 1377 return EFI_SUCCESS; 1378 } 1379 1380 EFI_STATUS 1381 ConvertSystemTable ( 1382 IN EFI_GUID *TableGuid, 1383 IN OUT VOID **Table 1384 ) 1385 /*++ 1386 1387 Routine Description: 1388 Convert ACPI Table /Smbios Table /MP Table if its location is lower than Address:0x100000 1389 Assumption here: 1390 As in legacy Bios, ACPI/Smbios/MP table is required to place in E/F Seg, 1391 So here we just check if the range is E/F seg, 1392 and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS 1393 1394 Arguments: 1395 TableGuid - Guid of the table 1396 Table - pointer to the table 1397 1398 Returns: 1399 EFI_SUCEESS - Convert Table successfully 1400 Other - Failed 1401 1402 --*/ 1403 { 1404 EFI_STATUS Status; 1405 VOID *AcpiHeader; 1406 UINTN AcpiTableLen; 1407 1408 // 1409 // If match acpi guid (1.0, 2.0, or later), Convert ACPI table according to version. 1410 // 1411 AcpiHeader = (VOID*)(UINTN)(*(UINT64 *)(*Table)); 1412 1413 if (CompareGuid(TableGuid, &gEfiAcpiTableGuid) || CompareGuid(TableGuid, &gEfiAcpi20TableGuid)){ 1414 if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved == 0x00){ 1415 // 1416 // If Acpi 1.0 Table, then RSDP structure doesn't contain Length field, use structure size 1417 // 1418 AcpiTableLen = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER); 1419 } else if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved >= 0x02){ 1420 // 1421 // If Acpi 2.0 or later, use RSDP Length fied. 1422 // 1423 AcpiTableLen = ((EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Length; 1424 } else { 1425 // 1426 // Invalid Acpi Version, return 1427 // 1428 return EFI_UNSUPPORTED; 1429 } 1430 Status = ConvertAcpiTable (AcpiTableLen, Table); 1431 return Status; 1432 } 1433 1434 // 1435 // If matches smbios guid, convert Smbios table. 1436 // 1437 if (CompareGuid(TableGuid, &gEfiSmbiosTableGuid)){ 1438 Status = ConvertSmbiosTable (Table); 1439 return Status; 1440 } 1441 1442 // 1443 // If the table is MP table? 1444 // 1445 if (CompareGuid(TableGuid, &gEfiMpsTableGuid)){ 1446 Status = ConvertMpsTable (Table); 1447 return Status; 1448 } 1449 1450 return EFI_UNSUPPORTED; 1451 } 1452 1453 1454 EFI_STATUS 1455 ConvertAcpiTable ( 1456 IN UINTN TableLen, 1457 IN OUT VOID **Table 1458 ) 1459 /*++ 1460 1461 Routine Description: 1462 Convert RSDP of ACPI Table if its location is lower than Address:0x100000 1463 Assumption here: 1464 As in legacy Bios, ACPI table is required to place in E/F Seg, 1465 So here we just check if the range is E/F seg, 1466 and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS 1467 1468 Arguments: 1469 TableLen - Acpi RSDP length 1470 Table - pointer to the table 1471 1472 Returns: 1473 EFI_SUCEESS - Convert Table successfully 1474 Other - Failed 1475 1476 --*/ 1477 { 1478 VOID *AcpiTableOri; 1479 VOID *AcpiTableNew; 1480 EFI_STATUS Status; 1481 EFI_PHYSICAL_ADDRESS BufferPtr; 1482 1483 1484 AcpiTableOri = (VOID *)(UINTN)(*(UINT64*)(*Table)); 1485 if (((UINTN)AcpiTableOri < 0x100000) && ((UINTN)AcpiTableOri > 0xE0000)) { 1486 BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS; 1487 Status = gBS->AllocatePages ( 1488 AllocateMaxAddress, 1489 EfiACPIMemoryNVS, 1490 EFI_SIZE_TO_PAGES(TableLen), 1491 &BufferPtr 1492 ); 1493 ASSERT_EFI_ERROR (Status); 1494 AcpiTableNew = (VOID *)(UINTN)BufferPtr; 1495 CopyMem (AcpiTableNew, AcpiTableOri, TableLen); 1496 } else { 1497 AcpiTableNew = AcpiTableOri; 1498 } 1499 // 1500 // Change configuration table Pointer 1501 // 1502 *Table = AcpiTableNew; 1503 1504 return EFI_SUCCESS; 1505 } 1506 1507 EFI_STATUS 1508 ConvertSmbiosTable ( 1509 IN OUT VOID **Table 1510 ) 1511 /*++ 1512 1513 Routine Description: 1514 1515 Convert Smbios Table if the Location of the SMBios Table is lower than Addres 0x100000 1516 Assumption here: 1517 As in legacy Bios, Smbios table is required to place in E/F Seg, 1518 So here we just check if the range is F seg, 1519 and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData 1520 Arguments: 1521 Table - pointer to the table 1522 1523 Returns: 1524 EFI_SUCEESS - Convert Table successfully 1525 Other - Failed 1526 1527 --*/ 1528 { 1529 SMBIOS_TABLE_ENTRY_POINT *SmbiosTableNew; 1530 SMBIOS_TABLE_ENTRY_POINT *SmbiosTableOri; 1531 EFI_STATUS Status; 1532 UINT32 SmbiosEntryLen; 1533 UINT32 BufferLen; 1534 EFI_PHYSICAL_ADDRESS BufferPtr; 1535 1536 SmbiosTableNew = NULL; 1537 SmbiosTableOri = NULL; 1538 1539 // 1540 // Get Smibos configuration Table 1541 // 1542 SmbiosTableOri = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)(*(UINT64*)(*Table)); 1543 1544 if ((SmbiosTableOri == NULL) || 1545 ((UINTN)SmbiosTableOri > 0x100000) || 1546 ((UINTN)SmbiosTableOri < 0xF0000)){ 1547 return EFI_SUCCESS; 1548 } 1549 // 1550 // Relocate the Smibos memory 1551 // 1552 BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS; 1553 if (SmbiosTableOri->SmbiosBcdRevision != 0x21) { 1554 SmbiosEntryLen = SmbiosTableOri->EntryPointLength; 1555 } else { 1556 // 1557 // According to Smbios Spec 2.4, we should set entry point length as 0x1F if version is 2.1 1558 // 1559 SmbiosEntryLen = 0x1F; 1560 } 1561 BufferLen = SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen) + SmbiosTableOri->TableLength; 1562 Status = gBS->AllocatePages ( 1563 AllocateMaxAddress, 1564 EfiACPIMemoryNVS, 1565 EFI_SIZE_TO_PAGES(BufferLen), 1566 &BufferPtr 1567 ); 1568 ASSERT_EFI_ERROR (Status); 1569 SmbiosTableNew = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)BufferPtr; 1570 CopyMem ( 1571 SmbiosTableNew, 1572 SmbiosTableOri, 1573 SmbiosEntryLen 1574 ); 1575 // 1576 // Get Smbios Structure table address, and make sure the start address is 32-bit align 1577 // 1578 BufferPtr += SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen); 1579 CopyMem ( 1580 (VOID *)(UINTN)BufferPtr, 1581 (VOID *)(UINTN)(SmbiosTableOri->TableAddress), 1582 SmbiosTableOri->TableLength 1583 ); 1584 SmbiosTableNew->TableAddress = (UINT32)BufferPtr; 1585 SmbiosTableNew->IntermediateChecksum = 0; 1586 SmbiosTableNew->IntermediateChecksum = 1587 CalculateCheckSum8 ((UINT8*)SmbiosTableNew + 0x10, SmbiosEntryLen -0x10); 1588 // 1589 // Change the SMBIOS pointer 1590 // 1591 *Table = SmbiosTableNew; 1592 1593 return EFI_SUCCESS; 1594 } 1595 1596 EFI_STATUS 1597 ConvertMpsTable ( 1598 IN OUT VOID **Table 1599 ) 1600 /*++ 1601 1602 Routine Description: 1603 1604 Convert MP Table if the Location of the SMBios Table is lower than Addres 0x100000 1605 Assumption here: 1606 As in legacy Bios, MP table is required to place in E/F Seg, 1607 So here we just check if the range is E/F seg, 1608 and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData 1609 Arguments: 1610 Table - pointer to the table 1611 1612 Returns: 1613 EFI_SUCEESS - Convert Table successfully 1614 Other - Failed 1615 1616 --*/ 1617 { 1618 UINT32 Data32; 1619 UINT32 FPLength; 1620 EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointerOri; 1621 EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointerNew; 1622 EFI_LEGACY_MP_TABLE_HEADER *MpsTableOri; 1623 EFI_LEGACY_MP_TABLE_HEADER *MpsTableNew; 1624 VOID *OemTableOri; 1625 VOID *OemTableNew; 1626 EFI_STATUS Status; 1627 EFI_PHYSICAL_ADDRESS BufferPtr; 1628 1629 // 1630 // Get MP configuration Table 1631 // 1632 MpsFloatingPointerOri = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)(*(UINT64*)(*Table)); 1633 if (!(((UINTN)MpsFloatingPointerOri <= 0x100000) && 1634 ((UINTN)MpsFloatingPointerOri >= 0xF0000))){ 1635 return EFI_SUCCESS; 1636 } 1637 // 1638 // Get Floating pointer structure length 1639 // 1640 FPLength = MpsFloatingPointerOri->Length * 16; 1641 Data32 = FPLength + SYS_TABLE_PAD (FPLength); 1642 MpsTableOri = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)(MpsFloatingPointerOri->PhysicalAddress); 1643 if (MpsTableOri != NULL) { 1644 Data32 += MpsTableOri->BaseTableLength; 1645 Data32 += MpsTableOri->ExtendedTableLength; 1646 if (MpsTableOri->OemTablePointer != 0x00) { 1647 Data32 += SYS_TABLE_PAD (Data32); 1648 Data32 += MpsTableOri->OemTableSize; 1649 } 1650 } else { 1651 return EFI_SUCCESS; 1652 } 1653 // 1654 // Relocate memory 1655 // 1656 BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS; 1657 Status = gBS->AllocatePages ( 1658 AllocateMaxAddress, 1659 EfiACPIMemoryNVS, 1660 EFI_SIZE_TO_PAGES(Data32), 1661 &BufferPtr 1662 ); 1663 ASSERT_EFI_ERROR (Status); 1664 MpsFloatingPointerNew = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)BufferPtr; 1665 CopyMem (MpsFloatingPointerNew, MpsFloatingPointerOri, FPLength); 1666 // 1667 // If Mp Table exists 1668 // 1669 if (MpsTableOri != NULL) { 1670 // 1671 // Get Mps table length, including Ext table 1672 // 1673 BufferPtr = BufferPtr + FPLength + SYS_TABLE_PAD (FPLength); 1674 MpsTableNew = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)BufferPtr; 1675 CopyMem (MpsTableNew, MpsTableOri, MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength); 1676 1677 if ((MpsTableOri->OemTableSize != 0x0000) && (MpsTableOri->OemTablePointer != 0x0000)){ 1678 BufferPtr += MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength; 1679 BufferPtr += SYS_TABLE_PAD (BufferPtr); 1680 OemTableNew = (VOID *)(UINTN)BufferPtr; 1681 OemTableOri = (VOID *)(UINTN)MpsTableOri->OemTablePointer; 1682 CopyMem (OemTableNew, OemTableOri, MpsTableOri->OemTableSize); 1683 MpsTableNew->OemTablePointer = (UINT32)(UINTN)OemTableNew; 1684 } 1685 MpsTableNew->Checksum = 0; 1686 MpsTableNew->Checksum = CalculateCheckSum8 ((UINT8*)MpsTableNew, MpsTableOri->BaseTableLength); 1687 MpsFloatingPointerNew->PhysicalAddress = (UINT32)(UINTN)MpsTableNew; 1688 MpsFloatingPointerNew->Checksum = 0; 1689 MpsFloatingPointerNew->Checksum = CalculateCheckSum8 ((UINT8*)MpsFloatingPointerNew, FPLength); 1690 } 1691 // 1692 // Change the pointer 1693 // 1694 *Table = MpsFloatingPointerNew; 1695 1696 return EFI_SUCCESS; 1697 } 1698 1699 /** 1700 Lock the ConsoleIn device in system table. All key 1701 presses will be ignored until the Password is typed in. The only way to 1702 disable the password is to type it in to a ConIn device. 1703 1704 @param Password Password used to lock ConIn device. 1705 1706 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully. 1707 @retval EFI_UNSUPPORTED Password not found 1708 1709 **/ 1710 EFI_STATUS 1711 EFIAPI 1712 LockKeyboards ( 1713 IN CHAR16 *Password 1714 ) 1715 { 1716 return EFI_UNSUPPORTED; 1717 } 1718 1719 /** 1720 This function locks platform flash that is not allowed to be updated during normal boot path. 1721 The flash layout is platform specific. 1722 1723 **/ 1724 VOID 1725 EFIAPI 1726 PlatformBdsLockNonUpdatableFlash ( 1727 VOID 1728 ) 1729 { 1730 return; 1731 } 1732