bdsplatform.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,208 行 · 第 1/3 页

C
1,208
字号
/*++

Copyright (c) 2006, Intel Corporation                                                         
All rights reserved. This program and the accompanying materials                          
are licensed and made available under the terms and conditions of the BSD License         
which accompanies this distribution.  The full text of the license may be found at        
http://opensource.org/licenses/bsd-license.php                                            
                                                                                          
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

Module Name:

  BdsPlatform.c

Abstract:

  This file include all platform action which can be customized
  by IBV/OEM.

--*/

#include "BdsPlatform.h"
#include "EfiPrintLib.h"
#include "String.h"
#include "Language.h"
#include "FrontPage.h"
#include EFI_GUID_DEFINITION (SmBios)
#include EFI_GUID_DEFINITION (Acpi)
#include EFI_GUID_DEFINITION (Mps)
#include EFI_GUID_DEFINITION (PciExpressBaseAddress)

CHAR16  mFirmwareVendor[] = L"TianoCore.org";
extern BOOLEAN  gConnectAllHappened;

//
// BDS Platform Functions
//

VOID
GetSystemTablesFromHob (
  VOID
  )
/*++

Routine Description:
  Find GUID'ed HOBs that contain EFI_PHYSICAL_ADDRESS of ACPI, SMBIOS, MPs tables

Arguments:
  None

Returns:
  None.

--*/
{
  EFI_STATUS                  Status;
  EFI_HOB_HANDOFF_INFO_TABLE  *HobList;
  UINTN                       Size;
  EFI_PHYSICAL_ADDRESS       *Table;

  //
  // Get Hob List
  //
  
  Status = EfiLibGetSystemConfigurationTable (&gEfiHobListGuid, (VOID *) &HobList);
  if (EFI_ERROR (Status)) {
    return;
  }

  //
  // If there is an ACPI table in the HOB add it to the EFI System table
  //
  Status = GetNextGuidHob (&HobList, &gEfiAcpi20TableGuid, &Table, &Size);
  if (!EFI_ERROR (Status)) {
    if (*Table != 0) {
      gBS->InstallConfigurationTable (&gEfiAcpi20TableGuid, (VOID *)(UINTN)*Table);
    }
  }
  Status = GetNextGuidHob (&HobList, &gEfiAcpiTableGuid, &Table, &Size);
  if (!EFI_ERROR (Status)) {
    if (*Table != 0) {
      gBS->InstallConfigurationTable (&gEfiAcpiTableGuid, (VOID *)(UINTN)*Table);
    }
  }

  //
  // If there is a SMBIOS table in the HOB add it to the EFI System table
  //
  Status = GetNextGuidHob (&HobList, &gEfiSmbiosTableGuid, &Table, &Size);
  if (!EFI_ERROR (Status)) {
    if (*Table != 0) {
      gBS->InstallConfigurationTable (&gEfiSmbiosTableGuid, (VOID *)(UINTN)*Table);
    }
  }

  //
  // If there is a MPS table in the HOB add it to the EFI System table
  //
  Status = GetNextGuidHob (&HobList, &gEfiMpsTableGuid, &Table, &Size);
  if (!EFI_ERROR (Status)) {
    if (*Table != 0) {
      gBS->InstallConfigurationTable (&gEfiMpsTableGuid, (VOID *)(UINTN)*Table);
    }
  }
}


#define EFI_LDR_MEMORY_DESCRIPTOR_GUID \
  { 0x7701d7e5, 0x7d1d, 0x4432, 0xa4, 0x68, 0x67, 0x3d, 0xab, 0x8a, 0xde, 0x60 }

EFI_GUID gEfiLdrMemoryDescriptorGuid = EFI_LDR_MEMORY_DESCRIPTOR_GUID;

#pragma pack(1)

typedef struct {
  EFI_HOB_GUID_TYPE             Hob;
  UINTN                         MemDescCount;
  EFI_MEMORY_DESCRIPTOR         *MemDesc;
} MEMORY_DESC_HOB;

#pragma pack()

VOID
UpdateMemoryMap (
  VOID
  )
{
  EFI_STATUS                  Status;
  EFI_HOB_HANDOFF_INFO_TABLE  *HobList;
  UINTN                       Size;
  VOID                        *Table;
  MEMORY_DESC_HOB             MemoryDescHob;
  UINTN                       Index;
  EFI_PHYSICAL_ADDRESS        Memory;

  //
  // Get Hob List
  //
  Status = EfiLibGetSystemConfigurationTable (&gEfiHobListGuid, (VOID *) &HobList);
  if (EFI_ERROR (Status)) {
    return;
  }

  Status = GetNextGuidHob (&HobList, &gEfiLdrMemoryDescriptorGuid, &Table, &Size);
  if (EFI_ERROR (Status)) {
    return;
  }
  MemoryDescHob.MemDescCount = *(UINTN *)Table;
  MemoryDescHob.MemDesc      = *(EFI_MEMORY_DESCRIPTOR **)((UINTN)Table + sizeof(UINTN));

  //
  // Add ACPINVS, ACPIReclaim, and Reserved memory to MemoryMap
  //
  for (Index = 0; Index < MemoryDescHob.MemDescCount; Index++) {
    if (MemoryDescHob.MemDesc[Index].PhysicalStart < 0x100000) {
      continue;
    }
    if (MemoryDescHob.MemDesc[Index].PhysicalStart >= 0x100000000) {
      continue;
    }
    if ((MemoryDescHob.MemDesc[Index].Type == EfiReservedMemoryType) ||
        (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesData) ||
        (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesCode) ||
        (MemoryDescHob.MemDesc[Index].Type == EfiACPIReclaimMemory) ||
        (MemoryDescHob.MemDesc[Index].Type == EfiACPIMemoryNVS)) {
      DEBUG ((EFI_D_ERROR, "PhysicalStart - 0x%x, ", MemoryDescHob.MemDesc[Index].PhysicalStart));
      DEBUG ((EFI_D_ERROR, "PageNumber    - 0x%x, ", MemoryDescHob.MemDesc[Index].NumberOfPages));
      DEBUG ((EFI_D_ERROR, "Type          - 0x%x\n", MemoryDescHob.MemDesc[Index].Type));
      if ((MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesData) ||
          (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesCode)) {
        //
        // Skip RuntimeSevicesData and RuntimeServicesCode, they are BFV
        //
        continue;
      }
      Status = gDS->AddMemorySpace (
                      EfiGcdMemoryTypeSystemMemory,
                      MemoryDescHob.MemDesc[Index].PhysicalStart,
                      LShiftU64 (MemoryDescHob.MemDesc[Index].NumberOfPages, EFI_PAGE_SHIFT),
                      MemoryDescHob.MemDesc[Index].Attribute
                      );
      if (EFI_ERROR (Status)) {
        DEBUG ((EFI_D_ERROR, "AddMemorySpace fail!\n"));
        if ((MemoryDescHob.MemDesc[Index].Type == EfiACPIReclaimMemory) ||
            (MemoryDescHob.MemDesc[Index].Type == EfiACPIMemoryNVS)) {
          //
          // For EfiACPIReclaimMemory and EfiACPIMemoryNVS, it must success.
          // For EfiReservedMemoryType, there maybe overlap. So skip check here.
          //
//          ASSERT_EFI_ERROR (Status);
        }
        continue;
      }

      Memory = MemoryDescHob.MemDesc[Index].PhysicalStart;
      Status = gBS->AllocatePages (
                      AllocateAddress,
                      MemoryDescHob.MemDesc[Index].Type,
                      (UINTN)MemoryDescHob.MemDesc[Index].NumberOfPages,
                      &Memory
                      );
      if (EFI_ERROR (Status)) {
        DEBUG ((EFI_D_ERROR, "AllocatePages fail!\n"));
        //
        // For the page added, it must be allocated.
        //
//        ASSERT_EFI_ERROR (Status);
        continue;
      }
    }
  }
  
}

VOID
PlatformBdsInit (
  IN EFI_BDS_ARCH_PROTOCOL_INSTANCE  *PrivateData
  )
/*++

Routine Description:

  Platform Bds init. Incude the platform firmware vendor, revision
  and so crc check.

Arguments:

  PrivateData  - The EFI_BDS_ARCH_PROTOCOL_INSTANCE instance

Returns:

  None.

--*/
{
  //
  // set firmwarevendor, here can be IBV/OEM customize
  //
  gST->FirmwareVendor = EfiLibAllocateRuntimeCopyPool (
                          sizeof (mFirmwareVendor),
                          &mFirmwareVendor
                          );
  ASSERT (gST->FirmwareVendor != NULL);

  gST->FirmwareRevision = EFI_FIRMWARE_REVISION;

  //
  // Fixup Tasble CRC after we updated Firmware Vendor and Revision
  //
  gBS->CalculateCrc32 ((VOID *) gST, sizeof (EFI_SYSTEM_TABLE), &gST->Hdr.CRC32);

  //
  // Initialize the platform specific string and language
  //
  InitializeStringSupport ();
  InitializeLanguage (TRUE);
  InitializeFrontPage (FALSE);

  GetSystemTablesFromHob ();

  UpdateMemoryMap ();
}

UINT64
GetPciExpressBaseAddressForRootBridge (
  IN UINTN    HostBridgeNumber,
  IN UINTN    RootBridgeNumber
  )
/*++

Routine Description:
  This routine is to get PciExpress Base Address for this RootBridge

Arguments:
  HostBridgeNumber - The number of HostBridge
  RootBridgeNumber - The number of RootBridge
    
Returns:
  UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge

--*/
{
  EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION *PciExpressBaseAddressInfo;
  UINTN                                    BufferSize;
  UINT32                                   Index;
  UINT32                                   Number;
  VOID                                     *HobList;
  EFI_STATUS                               Status;

  //
  // Get Hob List from configuration table
  //
  Status = EfiLibGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);
  if (EFI_ERROR (Status)) {
    return 0;
  }

  //
  // Get PciExpressAddressInfo Hob
  //
  PciExpressBaseAddressInfo = NULL;
  Status = GetNextGuidHob (&HobList, &gEfiPciExpressBaseAddressGuid, &PciExpressBaseAddressInfo, &BufferSize);
  if (EFI_ERROR (Status)) {
    return 0;
  }

  //
  // Search the PciExpress Base Address in the Hob for current RootBridge
  //
  Number = (UINT32)(BufferSize / sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION));
  for (Index = 0; Index < Number; Index++) {
    if ((PciExpressBaseAddressInfo[Index].HostBridgeNumber == HostBridgeNumber) &&
        (PciExpressBaseAddressInfo[Index].RootBridgeNumber == RootBridgeNumber)) {
      return PciExpressBaseAddressInfo[Index].PciExpressBaseAddress;
    }
  }

  //
  // Do not find the PciExpress Base Address in the Hob
  //
  return 0;
}

VOID
PatchPciRootBridgeDevicePath (
  IN UINTN    HostBridgeNumber,
  IN UINTN    RootBridgeNumber,
  IN PLATFORM_ROOT_BRIDGE_DEVICE_PATH  *RootBridge
  )
{
  UINT64  PciExpressBase;

  PciExpressBase = GetPciExpressBaseAddressForRootBridge (HostBridgeNumber, RootBridgeNumber);

  if (PciExpressBase != 0) {
    RootBridge->PciRootBridge.HID = EISA_PNP_ID(0x0A08);
  }
}

EFI_STATUS
ConnectRootBridge (
  VOID
  )
/*++

Routine Description:

  Connect RootBridge

Arguments:

  None.
 
Returns:

  EFI_SUCCESS             - Connect RootBridge successfully.
  EFI_STATUS              - Connect RootBridge fail.

--*/
{
  EFI_STATUS                Status;
  EFI_HANDLE                RootHandle;

  //
  // Patch Pci Root Bridge Device Path
  //
  PatchPciRootBridgeDevicePath (0, 0, &gPlatformRootBridge0);

  //
  // Make all the PCI_IO protocols on PCI Seg 0 show up
  //
  BdsLibConnectDevicePath (gPlatformRootBridges[0]);

  Status = gBS->LocateDevicePath (
                  &gEfiDevicePathProtocolGuid, 
                  &gPlatformRootBridges[0], 
                  &RootHandle
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  return EFI_SUCCESS;
}

EFI_STATUS
PrepareLpcBridgeDevicePath (
  IN EFI_HANDLE                DeviceHandle
  )
/*++

Routine Description:

  Add IsaKeyboard to ConIn,
  add IsaSerial to ConOut, ConIn, ErrOut.
  LPC Bridge: 06 01 00

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?