From 8322634459ac602d9fbcca30e96b24ff098acb3c Mon Sep 17 00:00:00 2001 From: Leif Lindholm Date: Wed, 3 May 2017 14:48:15 +0100 Subject: Platform,Silicon: Import Hisilicon D02,D03,D05 and HiKey Imported from commit efd798c1eb of https://git.linaro.org/uefi/OpenPlatformPkg.git Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Leif Lindholm --- .../Drivers/AcpiPlatformDxe/AcpiPlatform.c | 40 + .../Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf | 72 + Silicon/Hisilicon/Drivers/AcpiPlatformDxe/EthMac.c | 508 +++++ Silicon/Hisilicon/Drivers/AcpiPlatformDxe/EthMac.h | 22 + .../Drivers/FlashFvbDxe/FlashBlockIoDxe.c | 109 + .../Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.c | 1243 +++++++++++ .../Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.h | 228 ++ .../Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.inf | 69 + .../Drivers/HisiAcpiPlatformDxe/AcpiPlatform.c | 269 +++ .../Drivers/HisiAcpiPlatformDxe/AcpiPlatform.uni | 22 + .../HisiAcpiPlatformDxe/AcpiPlatformDxe.inf | 62 + .../HisiAcpiPlatformDxe/AcpiPlatformExtra.uni | 20 + .../Drivers/HisiAcpiPlatformDxe/UpdateAcpiTable.c | 137 ++ .../Drivers/HisiAcpiPlatformDxe/UpdateAcpiTable.h | 16 + .../Hisilicon/Drivers/NorFlashDxe/NorFlashConfig.c | 162 ++ .../Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.c | 594 +++++ .../Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.inf | 64 + Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.c | 628 ++++++ Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.h | 116 + .../Drivers/PciHostBridgeDxe/PciHostBridge.c | 1651 ++++++++++++++ .../Drivers/PciHostBridgeDxe/PciHostBridge.h | 521 +++++ .../Drivers/PciHostBridgeDxe/PciHostBridgeDxe.inf | 74 + .../Drivers/PciHostBridgeDxe/PciRootBridgeIo.c | 2313 ++++++++++++++++++++ Silicon/Hisilicon/Drivers/SasV1Dxe/SasV1Dxe.c | 1049 +++++++++ Silicon/Hisilicon/Drivers/SasV1Dxe/SasV1Dxe.inf | 46 + .../Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.c | 205 ++ .../Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.h | 36 + .../Smbios/AddSmbiosType9/AddSmbiosType9.inf | 50 + .../Smbios/MemorySubClassDxe/MemorySubClass.c | 762 +++++++ .../Smbios/MemorySubClassDxe/MemorySubClass.h | 79 + .../Smbios/MemorySubClassDxe/MemorySubClassDxe.inf | 59 + .../MemorySubClassDxe/MemorySubClassStrings.uni | 30 + .../ProcessorSubClassDxe/ProcessorSubClass.c | 728 ++++++ .../ProcessorSubClassDxe/ProcessorSubClass.h | 108 + .../ProcessorSubClassDxe/ProcessorSubClassDxe.inf | 64 + .../ProcessorSubClassStrings.uni | 32 + .../Drivers/Smbios/SmbiosMiscDxe/SmbiosMisc.h | 226 ++ .../Smbios/SmbiosMiscDxe/SmbiosMiscDataTable.c | 58 + .../Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf | 108 + .../Smbios/SmbiosMiscDxe/SmbiosMiscEntryPoint.c | 194 ++ .../Smbios/SmbiosMiscDxe/SmbiosMiscLibString.uni | 28 + .../Smbios/SmbiosMiscDxe/Type00/MiscBiosVendor.uni | 25 + .../SmbiosMiscDxe/Type00/MiscBiosVendorData.c | 105 + .../SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c | 258 +++ .../Type01/MiscSystemManufacturer.uni | 27 + .../Type01/MiscSystemManufacturerData.c | 52 + .../Type01/MiscSystemManufacturerFunction.c | 195 ++ .../Type02/MiscBaseBoardManufacturer.uni | 27 + .../Type02/MiscBaseBoardManufacturerData.c | 56 + .../Type02/MiscBaseBoardManufacturerFunction.c | 198 ++ .../Type03/MiscChassisManufacturer.uni | 24 + .../Type03/MiscChassisManufacturerData.c | 66 + .../Type03/MiscChassisManufacturerFunction.c | 199 ++ .../Type09/MiscSystemSlotDesignation.uni | Bin 0 -> 1592 bytes .../Type09/MiscSystemSlotDesignationData.c | 162 ++ .../Type09/MiscSystemSlotDesignationFunction.c | 201 ++ .../Type13/MiscNumberOfInstallableLanguages.uni | 49 + .../Type13/MiscNumberOfInstallableLanguagesData.c | 46 + .../MiscNumberOfInstallableLanguagesFunction.c | 163 ++ .../SmbiosMiscDxe/Type32/MiscBootInformationData.c | 48 + .../Type32/MiscBootInformationFunction.c | 74 + .../Type38/MiscIpmiDeviceInformationData.c | 42 + .../Type38/MiscIpmiDeviceInformationFunction.c | 87 + .../Hisilicon/Drivers/UpdateFdtDxe/UpdateFdtDxe.c | 158 ++ .../Drivers/UpdateFdtDxe/UpdateFdtDxe.inf | 62 + .../Drivers/VersionInfoPeim/VersionInfoPeim.c | 108 + .../Drivers/VersionInfoPeim/VersionInfoPeim.inf | 53 + .../Drivers/VirtualEhciPciIo/VirtualEhciPciIo.c | 682 ++++++ .../Drivers/VirtualEhciPciIo/VirtualEhciPciIo.h | 82 + .../Drivers/VirtualEhciPciIo/VirtualEhciPciIo.inf | 60 + 70 files changed, 16111 insertions(+) create mode 100644 Silicon/Hisilicon/Drivers/AcpiPlatformDxe/AcpiPlatform.c create mode 100644 Silicon/Hisilicon/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf create mode 100644 Silicon/Hisilicon/Drivers/AcpiPlatformDxe/EthMac.c create mode 100644 Silicon/Hisilicon/Drivers/AcpiPlatformDxe/EthMac.h create mode 100644 Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashBlockIoDxe.c create mode 100644 Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.c create mode 100644 Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.h create mode 100644 Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.inf create mode 100644 Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatform.c create mode 100644 Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatform.uni create mode 100644 Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatformDxe.inf create mode 100644 Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatformExtra.uni create mode 100644 Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/UpdateAcpiTable.c create mode 100644 Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/UpdateAcpiTable.h create mode 100644 Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashConfig.c create mode 100644 Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.c create mode 100644 Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.inf create mode 100644 Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.c create mode 100644 Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.h create mode 100644 Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridge.c create mode 100644 Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridge.h create mode 100644 Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.inf create mode 100644 Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciRootBridgeIo.c create mode 100644 Silicon/Hisilicon/Drivers/SasV1Dxe/SasV1Dxe.c create mode 100644 Silicon/Hisilicon/Drivers/SasV1Dxe/SasV1Dxe.inf create mode 100644 Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.c create mode 100644 Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.h create mode 100644 Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.inf create mode 100644 Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClass.c create mode 100644 Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClass.h create mode 100644 Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClassDxe.inf create mode 100644 Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClassStrings.uni create mode 100644 Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c create mode 100644 Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClass.h create mode 100644 Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf create mode 100644 Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMisc.h create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscDataTable.c create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscEntryPoint.c create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscLibString.uni create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendor.uni create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorData.c create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturer.uni create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerData.c create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerFunction.c create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturer.uni create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerData.c create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerFunction.c create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturer.uni create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerData.c create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerFunction.c create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignation.uni create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignationData.c create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignationFunction.c create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguages.uni create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesData.c create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesFunction.c create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationData.c create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationFunction.c create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type38/MiscIpmiDeviceInformationData.c create mode 100644 Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type38/MiscIpmiDeviceInformationFunction.c create mode 100644 Silicon/Hisilicon/Drivers/UpdateFdtDxe/UpdateFdtDxe.c create mode 100644 Silicon/Hisilicon/Drivers/UpdateFdtDxe/UpdateFdtDxe.inf create mode 100644 Silicon/Hisilicon/Drivers/VersionInfoPeim/VersionInfoPeim.c create mode 100644 Silicon/Hisilicon/Drivers/VersionInfoPeim/VersionInfoPeim.inf create mode 100644 Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.c create mode 100644 Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.h create mode 100644 Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.inf (limited to 'Silicon/Hisilicon/Drivers') diff --git a/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/AcpiPlatform.c b/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/AcpiPlatform.c new file mode 100644 index 0000000000..3d5ae9142a --- /dev/null +++ b/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/AcpiPlatform.c @@ -0,0 +1,40 @@ +/** @file + + Copyright (c) 2014, Applied Micro Curcuit Corporation. All rights reserved.
+ Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+ Copyright (c) 2015, Linaro Limited. 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. + +**/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "EthMac.h" + +EFI_STATUS +EFIAPI +AcpiPlatformEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EthMacInit(); +} diff --git a/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf b/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf new file mode 100644 index 0000000000..5209f31801 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf @@ -0,0 +1,72 @@ +## @file +# +# Copyright (c) 2014, Applied Micro Curcuit Corp. All rights reserved.
+# Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+# Copyright (c) 2015, Linaro Limited. 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = AcpiPlatform + FILE_GUID = e0829681-e9fa-4117-a8d7-84efadff863d + MODULE_TYPE = DXE_DRIVER + #MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = AcpiPlatformEntryPoint + +[Sources] + AcpiPlatform.c + EthMac.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + UefiLib + PcdLib + BaseMemoryLib + DebugLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiDriverEntryPoint + #UefiApplicationEntryPoint + +[Guids] + gShellVariableGuid # ALWAYS_CONSUMED + gArmMpCoreInfoGuid + +[Protocols] + gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gEfiAcpiSdtProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gHisiBoardNicProtocolGuid # PROTOCOL ALWAYS_CONSUMED + +[FeaturePcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol + +[Pcd] + +[FixedPcd] + gArmTokenSpaceGuid.PcdGicDistributorBase + gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision + +[Depex] + gEfiAcpiTableProtocolGuid AND gEfiAcpiSdtProtocolGuid AND gHisiBoardNicProtocolGuid + diff --git a/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/EthMac.c b/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/EthMac.c new file mode 100644 index 0000000000..1f74d312af --- /dev/null +++ b/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/EthMac.c @@ -0,0 +1,508 @@ +/** @file + + Copyright (c) 2014, Applied Micro Curcuit Corporation. All rights reserved.
+ Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+ Copyright (c) 2015, Linaro Limited. 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. + + This driver is called to initialize the FW part of the PHY in preparation + for the OS. + +**/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// Turn on debug message by enabling below define +//#define ACPI_DEBUG + +#ifdef ACPI_DEBUG +#define DBG(arg...) DEBUG((EFI_D_ERROR,## arg)) +#else +#define DBG(arg...) +#endif + +#define EFI_ACPI_MAX_NUM_TABLES 20 +#define DSDT_SIGNATURE 0x54445344 + +#define D02_ACPI_ETH_ID "HISI00C1" +#define D03_ACPI_ETH_ID "HISI00C2" + +#define ACPI_ETH_MAC_KEY "local-mac-address" + +#define PREFIX_VARIABLE_NAME L"MAC" +#define PREFIX_VARIABLE_NAME_COMPAT L"RGMII_MAC" +#define MAC_MAX_LEN 30 + +EFI_STATUS GetEnvMac( + IN UINTN MacNextID, + IN OUT UINT8 *MacBuffer) +{ + EFI_MAC_ADDRESS Mac; + EFI_STATUS Status; + HISI_BOARD_NIC_PROTOCOL *OemNic = NULL; + + Status = gBS->LocateProtocol(&gHisiBoardNicProtocolGuid, NULL, (VOID **)&OemNic); + if(EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] LocateProtocol failed %r\n", __FUNCTION__, __LINE__, Status)); + return Status; + } + + Status = OemNic->GetMac(&Mac, MacNextID); + if(EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] GetMac failed %r\n", __FUNCTION__, __LINE__, Status)); + return Status; + } + + CopyMem (MacBuffer, &Mac, 6); + DEBUG((EFI_D_ERROR, "Port %d MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + MacNextID, + MacBuffer[0], + MacBuffer[1], + MacBuffer[2], + MacBuffer[3], + MacBuffer[4], + MacBuffer[5] + )); + + return EFI_SUCCESS; +} + +EFI_STATUS _SearchReplacePackageMACAddress( + IN EFI_ACPI_SDT_PROTOCOL *AcpiTableProtocol, + IN EFI_ACPI_HANDLE ChildHandle, + IN UINTN Level, + IN OUT BOOLEAN *Found, + IN UINTN MacNextID) +{ + // ASL template for ethernet driver: +/* + * Name (_DSD, Package () { + * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), + * Package () { + * Package (2) {"mac-address", Package (6) { 00, 11, 22, 33, 44, 55 }} + * Package (2) {"phy-channel", 0}, + * Package (2) {"phy-mode", "rgmii"}, + * Package (2) {"max-transfer-unit", 0x5dc}, // MTU of 1500 + * Package (2) {"max-speed", 0x3e8}, // 1000 Mbps + * } + * }) + */ + EFI_STATUS Status; + EFI_ACPI_DATA_TYPE DataType; + CONST UINT8 *Data; + CONST VOID *Buffer; + UINTN DataSize; + UINTN Count; + EFI_ACPI_HANDLE CurrentHandle; + EFI_ACPI_HANDLE NextHandle; + UINT8 MACBuffer[MAC_MAX_LEN]; + + DBG("In Level:%d\n", Level); + Status = EFI_SUCCESS; + for (CurrentHandle = NULL; ;) { + Status = AcpiTableProtocol->GetChild(ChildHandle, &CurrentHandle); + if (Level != 3 && (EFI_ERROR(Status) || CurrentHandle == NULL)) + break; + + Status = AcpiTableProtocol->GetOption(CurrentHandle, 0, &DataType, &Buffer, &DataSize); + Data = Buffer; + DBG("_DSD Child Subnode Store Op Code 0x%02X 0x%02X %02X\n", + DataSize, Data[0], DataSize > 1 ? Data[1] : 0); + + if (Level < 2 && Data[0] != AML_PACKAGE_OP) + continue; + + if (Level == 2 && Data[0] == AML_STRING_PREFIX) { + Status = AcpiTableProtocol->GetOption(CurrentHandle, 1, &DataType, &Buffer, &DataSize); + if (EFI_ERROR(Status)) + break; + + DBG(" _DSD Child Subnode Store Op Code 0x%02X 0x%02X %02X\n", + DataSize, Data[0], DataSize > 1 ? Data[1] : 0); + + Data = Buffer; + if (DataType != EFI_ACPI_DATA_TYPE_STRING + || AsciiStrCmp((CHAR8 *) Data, ACPI_ETH_MAC_KEY) != 0) + continue; + + DBG("_DSD Key Type %d. Found MAC address key\n", DataType); + + // + // We found the node. + // + *Found = TRUE; + continue; + } + + if (Level == 3 && *Found) { + + //Update the MAC + Status = GetEnvMac(MacNextID, MACBuffer); + if (EFI_ERROR(Status)) + break; + + for (Count = 0; Count < 6; Count++) { + Status = AcpiTableProtocol->GetOption(CurrentHandle, 1, &DataType, &Buffer, &DataSize); + if (EFI_ERROR(Status)) + break; + + Data = Buffer; + DBG(" _DSD Child Subnode Store Op Code 0x%02X 0x%02X %02X DataType 0x%X\n", + DataSize, Data[0], DataSize > 1 ? Data[1] : 0, DataType); + + if (DataType != EFI_ACPI_DATA_TYPE_UINT) + break; + + // only need one byte. + // FIXME: Assume the CPU is little endian + Status = AcpiTableProtocol->SetOption(CurrentHandle, 1, (VOID *)&MACBuffer[Count], sizeof(UINT8)); + if (EFI_ERROR(Status)) + break; + Status = AcpiTableProtocol->GetChild(ChildHandle, &CurrentHandle); + if (EFI_ERROR(Status) || CurrentHandle == NULL) + break; + } + break; + } + + if (Level > 3) + break; + + //Search next package + AcpiTableProtocol->Open((VOID *) Buffer, &NextHandle); + Status = _SearchReplacePackageMACAddress(AcpiTableProtocol, NextHandle, Level + 1, Found, MacNextID); + AcpiTableProtocol->Close(NextHandle); + if (!EFI_ERROR(Status)) + break; + } + + return Status; +} + +EFI_STATUS SearchReplacePackageMACAddress( + IN EFI_ACPI_SDT_PROTOCOL *AcpiTableProtocol, + IN EFI_ACPI_HANDLE ChildHandle, + IN UINTN MacNextID) +{ + BOOLEAN Found = FALSE; + UINTN Level = 0; + + return _SearchReplacePackageMACAddress(AcpiTableProtocol, ChildHandle, Level, &Found, MacNextID); +} + +EFI_STATUS +GetEthID ( + EFI_ACPI_SDT_PROTOCOL *AcpiTableProtocol, + EFI_ACPI_HANDLE ChildHandle, + UINTN *EthID + ) +{ + EFI_STATUS Status; + EFI_ACPI_DATA_TYPE DataType; + CHAR8 Data[5]; + CONST VOID *Buffer; + UINTN DataSize; + + // Get NameString ETHx + Status = AcpiTableProtocol->GetOption (ChildHandle, 1, &DataType, &Buffer, &DataSize); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "[%a:%d] Get NameString failed: %r\n", __FUNCTION__, __LINE__, Status)); + return Status; + } + + CopyMem (Data, Buffer, 4); + DBG("Size %p Data %02x %02x %02x %02x\n", DataSize, Data[0], Data[1], Data[2], Data[3]); + + Data[4] = '\0'; + if (DataSize != 4 || + AsciiStrnCmp ("ETH", Data, 3) != 0 || + Data[3] > '9' || Data[3] < '0') { + DEBUG ((EFI_D_ERROR, "[%a:%d] The NameString %a is not ETHn\n", __FUNCTION__, __LINE__, Data)); + return EFI_INVALID_PARAMETER; + } + + *EthID = Data[3] - '0'; + return EFI_SUCCESS; +} + +EFI_STATUS ProcessDSDTDevice ( + EFI_ACPI_SDT_PROTOCOL *AcpiTableProtocol, + EFI_ACPI_HANDLE ChildHandle) +{ + EFI_STATUS Status; + EFI_ACPI_DATA_TYPE DataType; + CONST UINT8 *Data; + CONST VOID *Buffer; + UINTN DataSize; + EFI_ACPI_HANDLE DevHandle; + INTN Found = 0; + UINTN MacNextID; + + Status = AcpiTableProtocol->GetOption(ChildHandle, 0, &DataType, &Buffer, &DataSize); + if (EFI_ERROR(Status)) + return EFI_SUCCESS; + + Data = Buffer; + // + // Skip all non-device type + // + if (DataSize != 2 || Data[0] != AML_EXT_OP || Data[1] != AML_EXT_DEVICE_OP) + return EFI_SUCCESS; + + // + // Walk the device type node + // + for (DevHandle = NULL; ; ) { + Status = AcpiTableProtocol->GetChild(ChildHandle, &DevHandle); + if (EFI_ERROR(Status) || DevHandle == NULL) + break; + + // + // Search for _HID with Ethernet ID + // + Status = AcpiTableProtocol->GetOption(DevHandle, 0, &DataType, &Buffer, &DataSize); + if (EFI_ERROR(Status)) + break; + + Data = Buffer; + DBG("Data Type 0x%02X %02X\n", Data[0], DataSize > 1 ? Data[1] : 0); + if (DataSize == 1 && Data[0] == AML_NAME_OP) { + Status = AcpiTableProtocol->GetOption(DevHandle, 1, &DataType, &Buffer, &DataSize); + if (EFI_ERROR(Status)) + break; + + Data = Buffer; + if (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING) { + if (AsciiStrnCmp((CHAR8 *) Data, "_HID", 4) == 0) { + EFI_ACPI_HANDLE ValueHandle; + + Status = AcpiTableProtocol->GetOption(DevHandle, 2, &DataType, &Buffer, &DataSize); + if (EFI_ERROR(Status)) + break; + + if (DataType != EFI_ACPI_DATA_TYPE_CHILD) + continue; + + AcpiTableProtocol->Open((VOID *) Buffer, &ValueHandle); + Status = AcpiTableProtocol->GetOption(ValueHandle, 1, &DataType, &Buffer, &DataSize); + + Data = Buffer; + DBG("[%a:%d] - _HID = %a\n", __FUNCTION__, __LINE__, Data); + + if (EFI_ERROR(Status) || + DataType != EFI_ACPI_DATA_TYPE_STRING || + ((AsciiStrCmp((CHAR8 *) Data, D02_ACPI_ETH_ID) != 0) && + (AsciiStrCmp((CHAR8 *) Data, D03_ACPI_ETH_ID) != 0))) { + AcpiTableProtocol->Close(ValueHandle); + Found = 0; + continue; + } + + DBG("Found Ethernet device\n"); + AcpiTableProtocol->Close(ValueHandle); + Status = GetEthID (AcpiTableProtocol, ChildHandle, &MacNextID); + if (EFI_ERROR (Status)) { + continue; + } + Found = 1; + } else if (Found == 1 && AsciiStrnCmp((CHAR8 *) Data, "_DSD", 4) == 0) { + // + // Patch MAC address for open source kernel + // + EFI_ACPI_HANDLE PkgHandle; + Status = AcpiTableProtocol->GetOption(DevHandle, 2, &DataType, &Buffer, &DataSize); + if (EFI_ERROR(Status)) + break; + + if (DataType != EFI_ACPI_DATA_TYPE_CHILD) + continue; + + // + // Open package data + // + AcpiTableProtocol->Open((VOID *) Buffer, &PkgHandle); + Status = AcpiTableProtocol->GetOption(PkgHandle, 0, &DataType, &Buffer, &DataSize); + + Data = Buffer; + DBG("_DSD Subnode Store Op Code 0x%02X %02X\n", + Data[0], DataSize > 1 ? Data[1] : 0); + + // + // Walk the _DSD node + // + if (DataSize == 1 && Data[0] == AML_PACKAGE_OP) + Status = SearchReplacePackageMACAddress(AcpiTableProtocol, PkgHandle, MacNextID); + + AcpiTableProtocol->Close(PkgHandle); + } + } + } + } + + return EFI_SUCCESS; +} + + +BOOLEAN +IsSbScope ( + EFI_ACPI_SDT_PROTOCOL *AcpiTableProtocol, + EFI_ACPI_HANDLE ChildHandle + ) +{ + EFI_STATUS Status; + EFI_ACPI_DATA_TYPE DataType; + CONST UINT8 *Data; + CONST VOID *Buffer; + UINTN DataSize; + + Status = AcpiTableProtocol->GetOption (ChildHandle, 0, &DataType, &Buffer, &DataSize); + if (EFI_ERROR(Status)) return FALSE; + + Data = Buffer; + if (DataSize != 1 || Data[0] != AML_SCOPE_OP) { + return FALSE; + } + + return TRUE; +} + +EFI_STATUS ProcessDSDTChild( + EFI_ACPI_SDT_PROTOCOL *AcpiTableProtocol, + EFI_ACPI_HANDLE ChildHandle) +{ + EFI_STATUS Status; + EFI_ACPI_HANDLE DevHandle; + + // Check Scope(_SB) at first + if (!IsSbScope (AcpiTableProtocol, ChildHandle)) { + return ProcessDSDTDevice (AcpiTableProtocol, ChildHandle); + } + + for (DevHandle = NULL; ; ) { + Status = AcpiTableProtocol->GetChild (ChildHandle, &DevHandle); + if (EFI_ERROR(Status) || DevHandle == NULL) { + break; + } + + ProcessDSDTDevice (AcpiTableProtocol, DevHandle); + } + + return EFI_SUCCESS; +} + +static EFI_STATUS ProcessDSDT( + EFI_ACPI_SDT_PROTOCOL *AcpiTableProtocol, + EFI_ACPI_HANDLE TableHandle) +{ + EFI_STATUS Status; + EFI_ACPI_HANDLE ChildHandle; + // + // Parse table for device type + DBG ("[%a:%d] - TableHandle=%p\n", __FUNCTION__, __LINE__, TableHandle); + for (ChildHandle = NULL; ; ) { + Status = AcpiTableProtocol->GetChild(TableHandle, &ChildHandle); + DBG ("[%a:%d] - Child=%p, %r\n", __FUNCTION__, __LINE__, ChildHandle, Status); + if (EFI_ERROR(Status)) + break; + if (ChildHandle == NULL) + break; + + ProcessDSDTChild(AcpiTableProtocol, ChildHandle); + } + + return EFI_SUCCESS; +} + +STATIC +VOID +AcpiCheckSum ( + IN OUT EFI_ACPI_SDT_HEADER *Table + ) +{ + UINTN ChecksumOffset; + UINT8 *Buffer; + + ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum); + Buffer = (UINT8 *)Table; + + // + // set checksum to 0 first + // + Buffer[ChecksumOffset] = 0; + + // + // Update checksum value + // + Buffer[ChecksumOffset] = CalculateCheckSum8 (Buffer, Table->Length); +} + +EFI_STATUS EthMacInit(void) +{ + EFI_STATUS Status; + EFI_ACPI_SDT_PROTOCOL *AcpiTableProtocol; + EFI_ACPI_SDT_HEADER *Table; + EFI_ACPI_TABLE_VERSION TableVersion; + UINTN TableKey; + EFI_ACPI_HANDLE TableHandle; + UINTN i; + + DEBUG ((EFI_D_ERROR, "Updating Ethernet MAC in ACPI DSDT...\n")); + + // + // Find the AcpiTable protocol + Status = gBS->LocateProtocol(&gEfiAcpiSdtProtocolGuid, NULL, (VOID**) &AcpiTableProtocol); + if (EFI_ERROR(Status)) { + DBG("Unable to locate ACPI table protocol\n"); + return EFI_SUCCESS; + } + + // + // Search for DSDT Table + for (i = 0; i < EFI_ACPI_MAX_NUM_TABLES; i++) { + Status = AcpiTableProtocol->GetAcpiTable(i, &Table, &TableVersion, &TableKey); + if (EFI_ERROR(Status)) + break; + if (Table->Signature != DSDT_SIGNATURE) + continue; + + Status = AcpiTableProtocol->OpenSdt(TableKey, &TableHandle); + if (EFI_ERROR(Status)) + break; + + ProcessDSDT(AcpiTableProtocol, TableHandle); + + AcpiTableProtocol->Close(TableHandle); + AcpiCheckSum (Table); + } + + return EFI_SUCCESS; +} diff --git a/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/EthMac.h b/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/EthMac.h new file mode 100644 index 0000000000..bf4cbb1a53 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/EthMac.h @@ -0,0 +1,22 @@ +/* + * + * Copyright (c) 2014, Applied Micro Circuits Corporation + * Copyright (c) 2015, Hisilicon Limited. All rights reserved. + * Copyright (c) 2015, Linaro Limited. All rights reserved. + * Author: Loc Ho + * + * 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. + */ +#ifndef _ETH_MAC_H_ +#define _ETH_MAC_H_ + +EFI_STATUS EthMacInit(VOID); + +#endif + diff --git a/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashBlockIoDxe.c b/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashBlockIoDxe.c new file mode 100644 index 0000000000..91c07338ed --- /dev/null +++ b/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashBlockIoDxe.c @@ -0,0 +1,109 @@ +/** @file +* +* Copyright (c) 2011-2015, ARM Limited. All rights reserved. +* Copyright (c) 2015, Hisilicon Limited. All rights reserved. +* Copyright (c) 2015, Linaro Limited. 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. +* +**/ + +#include "FlashFvbDxe.h" + +// +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks +// +EFI_STATUS +EFIAPI +FlashBlockIoReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL* This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSizeInBytes, + OUT VOID* Buffer +) +{ + FLASH_INSTANCE* Instance; + EFI_STATUS Status; + + Instance = INSTANCE_FROM_BLKIO_THIS(This); + + DEBUG ((EFI_D_INFO, "FlashBlockIoReadBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer)); + + if ( !This->Media->MediaPresent ) + { + Status = EFI_NO_MEDIA; + } + else if ( This->Media->MediaId != MediaId ) + { + Status = EFI_MEDIA_CHANGED; + } + else + { + Status = FlashReadBlocks (Instance, Lba, BufferSizeInBytes, Buffer); + } + + return Status; +} + +// +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks +// +EFI_STATUS +EFIAPI +FlashBlockIoWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL* This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSizeInBytes, + IN VOID* Buffer +) +{ + FLASH_INSTANCE* Instance; + EFI_STATUS Status; + + Instance = INSTANCE_FROM_BLKIO_THIS(This); + + DEBUG ((EFI_D_INFO, "FlashBlockIoWriteBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer)); + + if ( !This->Media->MediaPresent ) + { + Status = EFI_NO_MEDIA; + } + else if ( This->Media->MediaId != MediaId ) + { + Status = EFI_MEDIA_CHANGED; + } + else if ( This->Media->ReadOnly ) + { + Status = EFI_WRITE_PROTECTED; + } + else + { + Status = FlashWriteBlocks (Instance, Lba, BufferSizeInBytes, Buffer); + } + + return Status; +} + +// +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks +// +EFI_STATUS +EFIAPI +FlashBlockIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL* This +) +{ + // No Flush required for the NOR Flash driver + // because cache operations are not permitted. + + // Nothing to do so just return without error + return EFI_SUCCESS; +} diff --git a/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.c b/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.c new file mode 100644 index 0000000000..7c6b64c33e --- /dev/null +++ b/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.c @@ -0,0 +1,1243 @@ +/** @file +* +* Copyright (c) 2011-2015, ARM Limited. All rights reserved. +* Copyright (c) 2015, Hisilicon Limited. All rights reserved. +* Copyright (c) 2015, Linaro Limited. 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. +* +* Based on files under ArmPlatformPkg/Drivers/NorFlashDxe/ +**/ + +#include "FlashFvbDxe.h" +STATIC EFI_EVENT mFlashFvbVirtualAddrChangeEvent; +STATIC UINTN mFlashNvStorageVariableBase; + + +// +// Global variable declarations +// + +FLASH_DESCRIPTION mFlashDevices[FLASH_DEVICE_COUNT] = +{ + { + // UEFI Variable Services non-volatile storage + 0xa4000000, + FixedPcdGet32(PcdFlashNvStorageVariableBase), + 0x20000, + SIZE_64KB, + {0xCC2CBF29, 0x1498, 0x4CDD, {0x81, 0x71, 0xF8, 0xB6, 0xB4, 0x1D, 0x09, 0x09}} + } + +}; + +FLASH_INSTANCE** mFlashInstances; + +FLASH_INSTANCE mFlashInstanceTemplate = +{ + FLASH_SIGNATURE, // Signature + NULL, // Handle ... NEED TO BE FILLED + + FALSE, // Initialized + NULL, // Initialize + + 0, // DeviceBaseAddress ... NEED TO BE FILLED + 0, // RegionBaseAddress ... NEED TO BE FILLED + 0, // Size ... NEED TO BE FILLED + 0, // StartLba + + { + EFI_BLOCK_IO_PROTOCOL_REVISION2, // Revision + NULL, // Media ... NEED TO BE FILLED + NULL, //NorFlashBlockIoReset + FlashBlockIoReadBlocks, + FlashBlockIoWriteBlocks, + FlashBlockIoFlushBlocks + }, // BlockIoProtocol + + { + 0, // MediaId ... NEED TO BE FILLED + FALSE, // RemovableMedia + TRUE, // MediaPresent + FALSE, // LogicalPartition + FALSE, // ReadOnly + FALSE, // WriteCaching; + SIZE_64KB, // BlockSize ... NEED TO BE FILLED + 4, // IoAlign + 0, // LastBlock ... NEED TO BE FILLED + 0, // LowestAlignedLba + 1, // LogicalBlocksPerPhysicalBlock + }, //Media; + + FALSE, // SupportFvb ... NEED TO BE FILLED + { + FvbGetAttributes, + FvbSetAttributes, + FvbGetPhysicalAddress, + FvbGetBlockSize, + FvbRead, + FvbWrite, + FvbEraseBlocks, + NULL, //ParentHandle + }, // FvbProtoccol; + + { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + {(UINT8)(sizeof(VENDOR_DEVICE_PATH)), + (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8)}, + }, + { 0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }}, // GUID ... NEED TO BE FILLED + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + {sizeof (EFI_DEVICE_PATH_PROTOCOL), + 0} + } + } // DevicePath +}; + +HISI_SPI_FLASH_PROTOCOL* mFlash; + +/// +/// The Firmware Volume Block Protocol is the low-level interface +/// to a firmware volume. File-level access to a firmware volume +/// should not be done using the Firmware Volume Block Protocol. +/// Normal access to a firmware volume must use the Firmware +/// Volume Protocol. Typically, only the file system driver that +/// produces the Firmware Volume Protocol will bind to the +/// Firmware Volume Block Protocol. +/// + +/** + Initialises the FV Header and Variable Store Header + to support variable operations. + + @param[in] Ptr - Location to initialise the headers + +**/ +EFI_STATUS +InitializeFvAndVariableStoreHeaders ( + IN FLASH_INSTANCE* Instance +) +{ + EFI_STATUS Status; + VOID* Headers; + UINTN HeadersLength; + EFI_FIRMWARE_VOLUME_HEADER* FirmwareVolumeHeader; + VARIABLE_STORE_HEADER* VariableStoreHeader; + + if (!Instance->Initialized && Instance->Initialize) + { + Instance->Initialize (Instance); + } + + HeadersLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY) + sizeof(VARIABLE_STORE_HEADER); + Headers = AllocateZeroPool(HeadersLength); + + // FirmwareVolumeHeader->FvLength is declared to have the Variable area AND the FTW working area AND the FTW Spare contiguous. + ASSERT(PcdGet32(PcdFlashNvStorageVariableBase) + PcdGet32(PcdFlashNvStorageVariableSize) == PcdGet32(PcdFlashNvStorageFtwWorkingBase)); + ASSERT(PcdGet32(PcdFlashNvStorageFtwWorkingBase) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) == PcdGet32(PcdFlashNvStorageFtwSpareBase)); + + // Check if the size of the area is at least one block size + ASSERT((PcdGet32(PcdFlashNvStorageVariableSize) > 0) && ((UINT32)PcdGet32(PcdFlashNvStorageVariableSize) / Instance->Media.BlockSize > 0)); + ASSERT((PcdGet32(PcdFlashNvStorageFtwWorkingSize) > 0) && ((UINT32)PcdGet32(PcdFlashNvStorageFtwWorkingSize) / Instance->Media.BlockSize > 0)); + ASSERT((PcdGet32(PcdFlashNvStorageFtwSpareSize) > 0) && ((UINT32)PcdGet32(PcdFlashNvStorageFtwSpareSize) / Instance->Media.BlockSize > 0)); + + // Ensure the Variable area Base Addresses are aligned on a block size boundaries + ASSERT((UINT32)PcdGet32(PcdFlashNvStorageVariableBase) % Instance->Media.BlockSize == 0); + ASSERT((UINT32)PcdGet32(PcdFlashNvStorageFtwWorkingBase) % Instance->Media.BlockSize == 0); + ASSERT((UINT32)PcdGet32(PcdFlashNvStorageFtwSpareBase) % Instance->Media.BlockSize == 0); + + // + // EFI_FIRMWARE_VOLUME_HEADER + // + FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Headers; + CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid); + FirmwareVolumeHeader->FvLength = + PcdGet32(PcdFlashNvStorageVariableSize) + + PcdGet32(PcdFlashNvStorageFtwWorkingSize) + + PcdGet32(PcdFlashNvStorageFtwSpareSize); + FirmwareVolumeHeader->Signature = EFI_FVH_SIGNATURE; + FirmwareVolumeHeader->Attributes = (EFI_FVB_ATTRIBUTES_2) ( + EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled + EFI_FVB2_READ_STATUS | // Reads are currently enabled + EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY + EFI_FVB2_MEMORY_MAPPED | // It is memory mapped + EFI_FVB2_ERASE_POLARITY | // After erasure all bits take this value (i.e. '1') + EFI_FVB2_WRITE_STATUS | // Writes are currently enabled + EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled + ); + FirmwareVolumeHeader->HeaderLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY); + FirmwareVolumeHeader->Revision = EFI_FVH_REVISION; + FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->Media.LastBlock + 1; + FirmwareVolumeHeader->BlockMap[0].Length = Instance->Media.BlockSize; + FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0; + FirmwareVolumeHeader->BlockMap[1].Length = 0; + FirmwareVolumeHeader->Checksum = CalculateCheckSum16 ((UINT16*)FirmwareVolumeHeader, FirmwareVolumeHeader->HeaderLength); + + // + // VARIABLE_STORE_HEADER + // + VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)Headers + (UINTN)FirmwareVolumeHeader->HeaderLength); + CopyGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid); + VariableStoreHeader->Size = PcdGet32(PcdFlashNvStorageVariableSize) - FirmwareVolumeHeader->HeaderLength; + VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED; + VariableStoreHeader->State = VARIABLE_STORE_HEALTHY; + + // Install the combined super-header in the NorFlash + Status = FvbWrite (&Instance->FvbProtocol, 0, 0, &HeadersLength, Headers); + + FreePool (Headers); + return Status; +} + +/** + Check the integrity of firmware volume header. + + @param[in] FwVolHeader - A pointer to a firmware volume header + + @retval EFI_SUCCESS - The firmware volume is consistent + @retval EFI_NOT_FOUND - The firmware volume has been corrupted. + +**/ +EFI_STATUS +ValidateFvHeader ( + IN FLASH_INSTANCE* Instance +) +{ + UINT16 Checksum; + EFI_FIRMWARE_VOLUME_HEADER* FwVolHeader; + VARIABLE_STORE_HEADER* VariableStoreHeader; + UINTN VariableStoreLength; + UINTN FvLength; + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Instance->RegionBaseAddress; + + FvLength = PcdGet32(PcdFlashNvStorageVariableSize) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) + + PcdGet32(PcdFlashNvStorageFtwSpareSize); + + // + // Verify the header revision, header signature, length + // Length of FvBlock cannot be 2**64-1 + // HeaderLength cannot be an odd number + // + if ( (FwVolHeader->Revision != EFI_FVH_REVISION) + || (FwVolHeader->Signature != EFI_FVH_SIGNATURE) + || (FwVolHeader->FvLength != FvLength) + ) + { + DEBUG ((EFI_D_ERROR, "ValidateFvHeader: No Firmware Volume header present\n")); + return EFI_NOT_FOUND; + } + + // Check the Firmware Volume Guid + if ( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) == FALSE ) + { + DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Firmware Volume Guid non-compatible\n")); + return EFI_NOT_FOUND; + } + + // Verify the header checksum + Checksum = CalculateSum16((UINT16*)FwVolHeader, FwVolHeader->HeaderLength); + if (Checksum != 0) + { + DEBUG ((EFI_D_ERROR, "ValidateFvHeader: FV checksum is invalid (Checksum:0x%X)\n", Checksum)); + return EFI_NOT_FOUND; + } + + VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)FwVolHeader + (UINTN)FwVolHeader->HeaderLength); + + // Check the Variable Store Guid + if ( CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) == FALSE ) + { + DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Variable Store Guid non-compatible\n")); + return EFI_NOT_FOUND; + } + + VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) - FwVolHeader->HeaderLength; + if (VariableStoreHeader->Size != VariableStoreLength) + { + DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Variable Store Length does not match\n")); + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** + The FvbGetAttributes() function retrieves the attributes and + current settings of the block. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the attributes and + current settings are returned. + Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER. + + @retval EFI_SUCCESS The firmware volume attributes were returned. + + **/ +EFI_STATUS +EFIAPI +FvbGetAttributes( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, + OUT EFI_FVB_ATTRIBUTES_2* Attributes +) +{ + EFI_FVB_ATTRIBUTES_2 FlashFvbAttributes; + FLASH_INSTANCE* Instance; + + Instance = INSTANCE_FROM_FVB_THIS(This); + + FlashFvbAttributes = (EFI_FVB_ATTRIBUTES_2) ( + + EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled + EFI_FVB2_READ_STATUS | // Reads are currently enabled + EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY + EFI_FVB2_MEMORY_MAPPED | // It is memory mapped + EFI_FVB2_ERASE_POLARITY // After erasure all bits take this value (i.e. '1') + + ); + + // Check if it is write protected + if (Instance->Media.ReadOnly != TRUE) + { + + FlashFvbAttributes = FlashFvbAttributes | + EFI_FVB2_WRITE_STATUS | // Writes are currently enabled + EFI_FVB2_WRITE_ENABLED_CAP; // Writes may be enabled + } + + *Attributes = FlashFvbAttributes; + + return EFI_SUCCESS; +} + +/** + The FvbSetAttributes() function sets configurable firmware volume attributes + and returns the new settings of the firmware volume. + + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param Attributes On input, Attributes is a pointer to EFI_FVB_ATTRIBUTES_2 + that contains the desired firmware volume settings. + On successful return, it contains the new settings of + the firmware volume. + Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER. + + @retval EFI_SUCCESS The firmware volume attributes were returned. + + @retval EFI_INVALID_PARAMETER The attributes requested are in conflict with the capabilities + as declared in the firmware volume header. + + **/ +EFI_STATUS +EFIAPI +FvbSetAttributes( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, + IN OUT EFI_FVB_ATTRIBUTES_2* Attributes +) +{ + DEBUG ((EFI_D_ERROR, "FvbSetAttributes(0x%X) is not supported\n", *Attributes)); + return EFI_UNSUPPORTED; +} + +/** + The GetPhysicalAddress() function retrieves the base address of + a memory-mapped firmware volume. This function should be called + only for memory-mapped firmware volumes. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param Address Pointer to a caller-allocated + EFI_PHYSICAL_ADDRESS that, on successful + return from GetPhysicalAddress(), contains the + base address of the firmware volume. + + @retval EFI_SUCCESS The firmware volume base address was returned. + + @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped. + + **/ +EFI_STATUS +EFIAPI +FvbGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, + OUT EFI_PHYSICAL_ADDRESS* Address +) +{ + + if(NULL == Address) + { + return EFI_UNSUPPORTED; + }; + + *Address = mFlashNvStorageVariableBase; + return EFI_SUCCESS; +} + +/** + The GetBlockSize() function retrieves the size of the requested + block. It also returns the number of additional blocks with + the identical size. The GetBlockSize() function is used to + retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER). + + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param Lba Indicates the block for which to return the size. + + @param BlockSize Pointer to a caller-allocated UINTN in which + the size of the block is returned. + + @param NumberOfBlocks Pointer to a caller-allocated UINTN in + which the number of consecutive blocks, + starting with Lba, is returned. All + blocks in this range have a size of + BlockSize. + + + @retval EFI_SUCCESS The firmware volume base address was returned. + + @retval EFI_INVALID_PARAMETER The requested LBA is out of range. + + **/ +EFI_STATUS +EFIAPI +FvbGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, + IN EFI_LBA Lba, + OUT UINTN* BlockSize, + OUT UINTN* NumberOfBlocks +) +{ + EFI_STATUS Status; + FLASH_INSTANCE* Instance; + + Instance = INSTANCE_FROM_FVB_THIS(This); + + if (Lba > Instance->Media.LastBlock) + { + Status = EFI_INVALID_PARAMETER; + } + else + { + // This is easy because in this platform each NorFlash device has equal sized blocks. + *BlockSize = (UINTN) Instance->Media.BlockSize; + *NumberOfBlocks = (UINTN) (Instance->Media.LastBlock - Lba + 1); + + + Status = EFI_SUCCESS; + } + + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +FvbReset( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification +) +{ + return EFI_SUCCESS; +} + + +/** + Reads the specified number of bytes into a buffer from the specified block. + + The Read() function reads the requested number of bytes from the + requested block and stores them in the provided buffer. + Implementations should be mindful that the firmware volume + might be in the ReadDisabled state. If it is in this state, + the Read() function must return the status code + EFI_ACCESS_DENIED without modifying the contents of the + buffer. The Read() function must also prevent spanning block + boundaries. If a read is requested that would span a block + boundary, the read must read up to the boundary but not + beyond. The output parameter NumBytes must be set to correctly + indicate the number of bytes actually read. The caller must be + aware that a read may be partially completed. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param Lba The starting logical block index from which to read. + + @param Offset Offset into the block at which to begin reading. + + @param NumBytes Pointer to a UINTN. + At entry, *NumBytes contains the total size of the buffer. + At exit, *NumBytes contains the total number of bytes read. + + @param Buffer Pointer to a caller-allocated buffer that will be used + to hold the data that is read. + + @retval EFI_SUCCESS The firmware volume was read successfully, and contents are + in Buffer. + + @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA boundary. + On output, NumBytes contains the total number of bytes + returned in Buffer. + + @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state. + + @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be read. + + **/ +EFI_STATUS +EFIAPI +FvbRead ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN* NumBytes, + IN OUT UINT8* Buffer +) +{ + EFI_STATUS Status; + UINTN BlockSize; + FLASH_INSTANCE* Instance; + + UINTN StartAddress; + UINTN ReadAddress; + + Instance = INSTANCE_FROM_FVB_THIS(This); + + if (!Instance->Initialized && Instance->Initialize) + { + if (EfiAtRuntime ()) { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL] Initialize at runtime is not supported!\n", __FUNCTION__, __LINE__)); + return EFI_UNSUPPORTED; + } + + Instance->Initialize(Instance); + } + + Status = EFI_SUCCESS; + + // Cache the block size to avoid de-referencing pointers all the time + BlockSize = Instance->Media.BlockSize; + + // The read must not span block boundaries. + // We need to check each variable individually because adding two large values together overflows. + if ((Offset >= BlockSize) || + (*NumBytes > BlockSize) || + ((Offset + *NumBytes) > BlockSize)) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL] ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", __FUNCTION__, __LINE__, Offset, *NumBytes, BlockSize )); + return EFI_BAD_BUFFER_SIZE; + } + + // We must have some bytes to read + if (*NumBytes == 0) + { + return EFI_BAD_BUFFER_SIZE; + } + + // Get the address to start reading from + StartAddress = GET_BLOCK_ADDRESS (Instance->RegionBaseAddress, + Lba, + BlockSize + ); + ReadAddress = StartAddress - Instance->DeviceBaseAddress + Offset; + + Status = mFlash->Read(mFlash, (UINT32)ReadAddress, Buffer, *NumBytes); + if (EFI_SUCCESS != Status) + { + // Return one of the pre-approved error statuses + Status = EFI_DEVICE_ERROR; + return Status; + } + + + return Status; +} + +/** + Writes the specified number of bytes from the input buffer to the block. + + The Write() function writes the specified number of bytes from + the provided buffer to the specified block and offset. If the + firmware volume is sticky write, the caller must ensure that + all the bits of the specified range to write are in the + EFI_FVB_ERASE_POLARITY state before calling the Write() + function, or else the result will be unpredictable. This + unpredictability arises because, for a sticky-write firmware + volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY + state but cannot flip it back again. Before calling the + Write() function, it is recommended for the caller to first call + the EraseBlocks() function to erase the specified block to + write. A block erase cycle will transition bits from the + (NOT)EFI_FVB_ERASE_POLARITY state back to the + EFI_FVB_ERASE_POLARITY state. Implementations should be + mindful that the firmware volume might be in the WriteDisabled + state. If it is in this state, the Write() function must + return the status code EFI_ACCESS_DENIED without modifying the + contents of the firmware volume. The Write() function must + also prevent spanning block boundaries. If a write is + requested that spans a block boundary, the write must store up + to the boundary but not beyond. The output parameter NumBytes + must be set to correctly indicate the number of bytes actually + written. The caller must be aware that a write may be + partially completed. All writes, partial or otherwise, must be + fully flushed to the hardware before the Write() service + returns. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param Lba The starting logical block index to write to. + + @param Offset Offset into the block at which to begin writing. + + @param NumBytes The pointer to a UINTN. + At entry, *NumBytes contains the total size of the buffer. + At exit, *NumBytes contains the total number of bytes actually written. + + @param Buffer The pointer to a caller-allocated buffer that contains the source for the write. + + @retval EFI_SUCCESS The firmware volume was written successfully. + + @retval EFI_BAD_BUFFER_SIZE The write was attempted across an LBA boundary. + On output, NumBytes contains the total number of bytes + actually written. + + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state. + + @retval EFI_DEVICE_ERROR The block device is malfunctioning and could not be written. + + + **/ +EFI_STATUS +EFIAPI +FvbWrite ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN* NumBytes, + IN UINT8* Buffer +) +{ + EFI_STATUS Status; + UINTN BlockSize; + FLASH_INSTANCE* Instance; + UINTN BlockAddress; + UINTN WriteAddress; + + Instance = INSTANCE_FROM_FVB_THIS(This); + if (NULL == Instance) + { + return EFI_INVALID_PARAMETER; + + } + + if (!Instance->Initialized && Instance->Initialize) + { + if (EfiAtRuntime ()) { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL] Initialize at runtime is not supported!\n", __FUNCTION__, __LINE__)); + return EFI_UNSUPPORTED; + } + + Instance->Initialize(Instance); + } + + Status = EFI_SUCCESS; + + // Detect WriteDisabled state + if (Instance->Media.ReadOnly == TRUE) + { + DEBUG ((EFI_D_ERROR, "FvbWrite: ERROR - Can not write: Device is in WriteDisabled state.\n")); + // It is in WriteDisabled state, return an error right away + return EFI_ACCESS_DENIED; + } + + // Cache the block size to avoid de-referencing pointers all the time + BlockSize = Instance->Media.BlockSize; + + // The write must not span block boundaries. + // We need to check each variable individually because adding two large values together overflows. + if ( ( Offset >= BlockSize ) || + ( *NumBytes > BlockSize ) || + ( (Offset + *NumBytes) > BlockSize ) ) + { + DEBUG ((EFI_D_ERROR, "FvbWrite: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize )); + return EFI_BAD_BUFFER_SIZE; + } + + // We must have some bytes to write + if (*NumBytes == 0) + { + DEBUG ((EFI_D_ERROR, "FvbWrite: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize )); + return EFI_BAD_BUFFER_SIZE; + } + + BlockAddress = GET_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSize); + WriteAddress = BlockAddress - Instance->DeviceBaseAddress + Offset; + + Status = mFlash->Write(mFlash, (UINT32)WriteAddress, (UINT8*)Buffer, *NumBytes); + if (EFI_SUCCESS != Status) + { + DEBUG((EFI_D_ERROR, "%s - %d Status=%r\n", __FILE__, __LINE__, Status)); + return Status; + } + + return Status; + +} + +/** + Erases and initialises a firmware volume block. + + The EraseBlocks() function erases one or more blocks as denoted + by the variable argument list. The entire parameter list of + blocks must be verified before erasing any blocks. If a block is + requested that does not exist within the associated firmware + volume (it has a larger index than the last block of the + firmware volume), the EraseBlocks() function must return the + status code EFI_INVALID_PARAMETER without modifying the contents + of the firmware volume. Implementations should be mindful that + the firmware volume might be in the WriteDisabled state. If it + is in this state, the EraseBlocks() function must return the + status code EFI_ACCESS_DENIED without modifying the contents of + the firmware volume. All calls to EraseBlocks() must be fully + flushed to the hardware before the EraseBlocks() service + returns. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL + instance. + + @param ... The variable argument list is a list of tuples. + Each tuple describes a range of LBAs to erase + and consists of the following: + - An EFI_LBA that indicates the starting LBA + - A UINTN that indicates the number of blocks to erase. + + The list is terminated with an EFI_LBA_LIST_TERMINATOR. + For example, the following indicates that two ranges of blocks + (5-7 and 10-11) are to be erased: + EraseBlocks (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR); + + @retval EFI_SUCCESS The erase request successfully completed. + + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state. + + @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be written. + The firmware device may have been partially erased. + + @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the variable argument list do + not exist in the firmware volume. + + **/ +EFI_STATUS +EFIAPI +FvbEraseBlocks ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, + ... +) +{ + EFI_STATUS Status; + VA_LIST Args; + UINTN BlockAddress; // Physical address of Lba to erase + EFI_LBA StartingLba; // Lba from which we start erasing + UINTN NumOfLba; // Number of Lba blocks to erase + FLASH_INSTANCE* Instance; + + Instance = INSTANCE_FROM_FVB_THIS(This); + + Status = EFI_SUCCESS; + + // Detect WriteDisabled state + if (Instance->Media.ReadOnly == TRUE) + { + // Firmware volume is in WriteDisabled state + return EFI_ACCESS_DENIED; + } + + // Before erasing, check the entire list of parameters to ensure all specified blocks are valid + VA_START (Args, This); + do + { + // Get the Lba from which we start erasing + StartingLba = VA_ARG (Args, EFI_LBA); + + // Have we reached the end of the list? + if (StartingLba == EFI_LBA_LIST_TERMINATOR) + { + //Exit the while loop + break; + } + + // How many Lba blocks are we requested to erase? + NumOfLba = VA_ARG (Args, UINT32); + + // All blocks must be within range + if ((NumOfLba == 0) || ((Instance->StartLba + StartingLba + NumOfLba - 1) > Instance->Media.LastBlock)) + { + VA_END (Args); + Status = EFI_INVALID_PARAMETER; + goto EXIT; + } + } + while (TRUE); + VA_END (Args); + + // + // To get here, all must be ok, so start erasing + // + VA_START (Args, This); + do + { + // Get the Lba from which we start erasing + StartingLba = VA_ARG (Args, EFI_LBA); + + // Have we reached the end of the list? + if (StartingLba == EFI_LBA_LIST_TERMINATOR) + { + // Exit the while loop + break; + } + + // How many Lba blocks are we requested to erase? + NumOfLba = VA_ARG (Args, UINT32); + + // Go through each one and erase it + while (NumOfLba > 0) + { + + // Get the physical address of Lba to erase + BlockAddress = GET_BLOCK_ADDRESS ( + Instance->RegionBaseAddress, + Instance->StartLba + StartingLba, + Instance->Media.BlockSize + ); + + // Erase it + + Status = FlashUnlockAndEraseSingleBlock (Instance, BlockAddress); + if (EFI_ERROR(Status)) + { + VA_END (Args); + Status = EFI_DEVICE_ERROR; + goto EXIT; + } + + // Move to the next Lba + StartingLba++; + NumOfLba--; + } + } + while (TRUE); + VA_END (Args); + +EXIT: + return Status; +} + +EFI_STATUS +EFIAPI +FvbInitialize ( + IN FLASH_INSTANCE* Instance +) +{ + EFI_STATUS Status; + UINT32 FvbNumLba; + + Instance->Initialized = TRUE; + mFlashNvStorageVariableBase = FixedPcdGet32 (PcdFlashNvStorageVariableBase); + + // Set the index of the first LBA for the FVB + Instance->StartLba = (PcdGet32 (PcdFlashNvStorageVariableBase) - Instance->RegionBaseAddress) / Instance->Media.BlockSize; + + // Determine if there is a valid header at the beginning of the Flash + Status = ValidateFvHeader (Instance); + if (EFI_ERROR(Status)) + { + // There is no valid header, so time to install one. + // Erase all the Flash that is reserved for variable storage + FvbNumLba = (PcdGet32(PcdFlashNvStorageVariableSize) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) + (UINT32)PcdGet32(PcdFlashNvStorageFtwSpareSize)) / Instance->Media.BlockSize; + Status = FvbEraseBlocks (&Instance->FvbProtocol, (EFI_LBA)0, FvbNumLba, EFI_LBA_LIST_TERMINATOR); + if (EFI_ERROR(Status)) + { + return Status; + } + + // Install all appropriate headers + Status = InitializeFvAndVariableStoreHeaders (Instance); + if (EFI_ERROR(Status)) + { + return Status; + } + } + return Status; +} + + +EFI_STATUS +FlashPlatformGetDevices ( + OUT FLASH_DESCRIPTION** FlashDevices, + OUT UINT32* Count +) +{ + if ((FlashDevices == NULL) || (Count == NULL)) + { + return EFI_INVALID_PARAMETER; + } + + *FlashDevices = mFlashDevices; + *Count = FLASH_DEVICE_COUNT; + + return EFI_SUCCESS; +} + + +EFI_STATUS +FlashCreateInstance ( + IN UINTN FlashDeviceBase, + IN UINTN FlashRegionBase, + IN UINTN FlashSize, + IN UINT32 MediaId, + IN UINT32 BlockSize, + IN BOOLEAN SupportFvb, + IN CONST GUID* FlashGuid, + OUT FLASH_INSTANCE** FlashInstance +) +{ + EFI_STATUS Status; + FLASH_INSTANCE* Instance; + + if (FlashInstance == NULL) + { + return EFI_INVALID_PARAMETER; + } + + Instance = AllocateRuntimeCopyPool (sizeof(FLASH_INSTANCE), &mFlashInstanceTemplate); + if (Instance == NULL) + { + return EFI_INVALID_PARAMETER; + } + + Instance->DeviceBaseAddress = FlashDeviceBase; + Instance->RegionBaseAddress = FlashRegionBase; + Instance->Size = FlashSize; + + Instance->BlockIoProtocol.Media = &Instance->Media; + Instance->BlockIoProtocol.Reset = FvbReset; + Instance->Media.MediaId = MediaId; + Instance->Media.BlockSize = BlockSize; + Instance->Media.LastBlock = (FlashSize / BlockSize) - 1; + + CopyGuid (&Instance->DevicePath.Vendor.Guid, FlashGuid); + + if (SupportFvb) + { + Instance->SupportFvb = TRUE; + Instance->Initialize = FvbInitialize; + + Status = gBS->InstallMultipleProtocolInterfaces ( + &Instance->Handle, + &gEfiDevicePathProtocolGuid, &Instance->DevicePath, + &gEfiBlockIoProtocolGuid, &Instance->BlockIoProtocol, + &gEfiFirmwareVolumeBlockProtocolGuid, &Instance->FvbProtocol, + NULL + ); + + if (EFI_ERROR(Status)) + { + FreePool(Instance); + return Status; + } + } + else + { + Instance->Initialized = TRUE; + + Status = gBS->InstallMultipleProtocolInterfaces ( + &Instance->Handle, + &gEfiDevicePathProtocolGuid, &Instance->DevicePath, + &gEfiBlockIoProtocolGuid, &Instance->BlockIoProtocol, + NULL + ); + if (EFI_ERROR(Status)) + { + FreePool(Instance); + return Status; + } + } + + *FlashInstance = Instance; + return Status; +} + +EFI_STATUS +FlashUnlockSingleBlockIfNecessary ( + IN FLASH_INSTANCE* Instance, + IN UINTN BlockAddress +) +{ + return EFI_SUCCESS; +} + + +EFI_STATUS +FlashEraseSingleBlock ( + IN FLASH_INSTANCE* Instance, + IN UINTN BlockAddress +) +{ + EFI_STATUS Status; + UINTN EraseAddress; + + Status = EFI_SUCCESS; + EraseAddress = BlockAddress - Instance->DeviceBaseAddress; + + Status = mFlash->Erase(mFlash, (UINT32)EraseAddress, Instance->Media.BlockSize); + if (EFI_SUCCESS != Status) + { + DEBUG((EFI_D_ERROR, "%s - %d Status=%r\n", __FILE__, __LINE__, Status)); + return Status; + } + + return EFI_SUCCESS; +} + +/** + * The following function presumes that the block has already been unlocked. + **/ +EFI_STATUS +FlashUnlockAndEraseSingleBlock ( + IN FLASH_INSTANCE* Instance, + IN UINTN BlockAddress +) +{ + EFI_STATUS Status; + UINTN Index; + + Index = 0; + // The block erase might fail a first time (SW bug ?). Retry it ... + do + { + // Unlock the block if we have to + Status = FlashUnlockSingleBlockIfNecessary (Instance, BlockAddress); + if (!EFI_ERROR(Status)) + { + Status = FlashEraseSingleBlock (Instance, BlockAddress); + } + Index++; + } + while ((Index < FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED)); + + if (Index == FLASH_ERASE_RETRY) + { + DEBUG((EFI_D_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n", BlockAddress, Index)); + } + + return Status; +} + +EFI_STATUS +FlashWriteBlocks ( + IN FLASH_INSTANCE* Instance, + IN EFI_LBA Lba, + IN UINTN BufferSizeInBytes, + IN VOID* Buffer +) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINTN BlockAddress; + UINT32 NumBlocks; + UINTN WriteAddress; + + // The buffer must be valid + if (Buffer == NULL) + { + return EFI_INVALID_PARAMETER; + } + + if (Instance->Media.ReadOnly == TRUE) + { + return EFI_WRITE_PROTECTED; + } + + // We must have some bytes to read + if (BufferSizeInBytes == 0) + { + return EFI_BAD_BUFFER_SIZE; + } + + // The size of the buffer must be a multiple of the block size + if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) + { + return EFI_BAD_BUFFER_SIZE; + } + + // All blocks must be within the device + NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize ; + if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL]ERROR - Write will exceed last block.\n", __FUNCTION__, __LINE__ )); + return EFI_INVALID_PARAMETER; + } + + BlockAddress = GET_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, Instance->Media.BlockSize); + + WriteAddress = BlockAddress - Instance->DeviceBaseAddress; + + Status = mFlash->Write(mFlash, (UINT32)WriteAddress, (UINT8*)Buffer, BufferSizeInBytes); + if (EFI_SUCCESS != Status) + { + DEBUG((EFI_D_ERROR, "%s - %d Status=%r\n", __FILE__, __LINE__, Status)); + return Status; + } + + return Status; +} + +EFI_STATUS +FlashReadBlocks ( + IN FLASH_INSTANCE* Instance, + IN EFI_LBA Lba, + IN UINTN BufferSizeInBytes, + OUT VOID* Buffer +) +{ + UINT32 NumBlocks; + UINTN StartAddress; + UINTN ReadAddress; + EFI_STATUS Status; + + // The buffer must be valid + if (Buffer == NULL) + { + return EFI_INVALID_PARAMETER; + } + + // We must have some bytes to read + if (BufferSizeInBytes == 0) + { + return EFI_BAD_BUFFER_SIZE; + } + + // The size of the buffer must be a multiple of the block size + if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) + { + return EFI_BAD_BUFFER_SIZE; + } + + // All blocks must be within the device + NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize ; + if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) + { + DEBUG((EFI_D_ERROR, "FlashReadBlocks: ERROR - Read will exceed last block\n")); + return EFI_INVALID_PARAMETER; + } + + // Get the address to start reading from + StartAddress = GET_BLOCK_ADDRESS (Instance->RegionBaseAddress, + Lba, + Instance->Media.BlockSize + ); + + + ReadAddress = StartAddress - Instance->DeviceBaseAddress; + + Status = mFlash->Read(mFlash, (UINT32)ReadAddress, Buffer, BufferSizeInBytes); + if (EFI_SUCCESS != Status) + { + DEBUG((EFI_D_ERROR, "%s - %d Status=%r\n", __FILE__, __LINE__, Status)); + return Status; + } + + return EFI_SUCCESS; +} + +VOID +EFIAPI +FlashFvbVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EfiConvertPointer (0x0, (VOID**)&mFlash); + EfiConvertPointer (0x0, (VOID**)&mFlashNvStorageVariableBase); + return; +} + +EFI_STATUS +EFIAPI +FlashFvbInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE* SystemTable +) +{ + EFI_STATUS Status; + UINT32 Index; + FLASH_DESCRIPTION* FlashDevices; + UINT32 FlashDeviceCount; + BOOLEAN ContainVariableStorage; + + + Status = FlashPlatformGetDevices (&FlashDevices, &FlashDeviceCount); + if (EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] Fail to get Flash devices\n", __FUNCTION__, __LINE__)); + return Status; + } + + mFlashInstances = AllocatePool ((UINT32)(sizeof(FLASH_INSTANCE*) * FlashDeviceCount)); + + Status = gBS->LocateProtocol (&gHisiSpiFlashProtocolGuid, NULL, (VOID*) &mFlash); + if (EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] Status=%r\n", __FUNCTION__, __LINE__, Status)); + return Status; + } + + for (Index = 0; Index < FlashDeviceCount; Index++) + { + // Check if this Flash device contain the variable storage region + ContainVariableStorage = + (FlashDevices[Index].RegionBaseAddress <= (UINT32)PcdGet32 (PcdFlashNvStorageVariableBase)) && + ((UINT32)(PcdGet32 (PcdFlashNvStorageVariableBase) + PcdGet32 (PcdFlashNvStorageVariableSize)) <= FlashDevices[Index].RegionBaseAddress + FlashDevices[Index].Size); + + Status = FlashCreateInstance ( + FlashDevices[Index].DeviceBaseAddress, + FlashDevices[Index].RegionBaseAddress, + FlashDevices[Index].Size, + Index, + FlashDevices[Index].BlockSize, + ContainVariableStorage, + &FlashDevices[Index].Guid, + &mFlashInstances[Index] + ); + if (EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] Fail to create instance for Flash[%d]\n", __FUNCTION__, __LINE__, Index)); + } + } + // + // Register for the virtual address change event + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + FlashFvbVirtualNotifyEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mFlashFvbVirtualAddrChangeEvent + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.h b/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.h new file mode 100644 index 0000000000..76385b6b65 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.h @@ -0,0 +1,228 @@ +/** @file +* +* Copyright (c) 2011-2015, ARM Limited. All rights reserved. +* Copyright (c) 2015, Hisilicon Limited. All rights reserved. +* Copyright (c) 2015, Linaro Limited. 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. +* +**/ + + +#ifndef __FLASH_FVB_DXE_H__ +#define __FLASH_FVB_DXE_H__ + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + + +#define FLASH_ERASE_RETRY 10 +#define FLASH_DEVICE_COUNT 1 + +// Device access macros +// These are necessary because we use 2 x 16bit parts to make up 32bit data +typedef struct +{ + UINTN DeviceBaseAddress; // Start address of the Device Base Address (DBA) + UINTN RegionBaseAddress; // Start address of one single region + UINTN Size; + UINTN BlockSize; + EFI_GUID Guid; +} FLASH_DESCRIPTION; + +#define GET_BLOCK_ADDRESS(BaseAddr,Lba,LbaSize)( BaseAddr + (UINTN)((Lba) * LbaSize) ) + +#define FLASH_SIGNATURE SIGNATURE_32('s', 'p', 'i', '0') +#define INSTANCE_FROM_FVB_THIS(a) CR(a, FLASH_INSTANCE, FvbProtocol, FLASH_SIGNATURE) +#define INSTANCE_FROM_BLKIO_THIS(a) CR(a, FLASH_INSTANCE, BlockIoProtocol, FLASH_SIGNATURE) + +typedef struct _FLASH_INSTANCE FLASH_INSTANCE; + +typedef EFI_STATUS (*FLASH_INITIALIZE) (FLASH_INSTANCE* Instance); + +typedef struct +{ + VENDOR_DEVICE_PATH Vendor; + EFI_DEVICE_PATH_PROTOCOL End; +} FLASH_DEVICE_PATH; + +struct _FLASH_INSTANCE +{ + UINT32 Signature; + EFI_HANDLE Handle; + + BOOLEAN Initialized; + FLASH_INITIALIZE Initialize; + + UINTN DeviceBaseAddress; + UINTN RegionBaseAddress; + UINTN Size; + EFI_LBA StartLba; + + EFI_BLOCK_IO_PROTOCOL BlockIoProtocol; + EFI_BLOCK_IO_MEDIA Media; + + BOOLEAN SupportFvb; + EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol; + + FLASH_DEVICE_PATH DevicePath; +}; + + +// +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks +// +EFI_STATUS +EFIAPI +FlashBlockIoReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL* This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSizeInBytes, + OUT VOID* Buffer +); + +// +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks +// +EFI_STATUS +EFIAPI +FlashBlockIoWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL* This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSizeInBytes, + IN VOID* Buffer +); + +// +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks +// +EFI_STATUS +EFIAPI +FlashBlockIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL* This +); + + +// +// FvbHw.c +// + +EFI_STATUS +EFIAPI +FvbInitialize ( + IN FLASH_INSTANCE* Instance +); + +EFI_STATUS +EFIAPI +FvbGetAttributes( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, + OUT EFI_FVB_ATTRIBUTES_2* Attributes +); + +EFI_STATUS +EFIAPI +FvbSetAttributes( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, + IN OUT EFI_FVB_ATTRIBUTES_2* Attributes +); + +EFI_STATUS +EFIAPI +FvbGetPhysicalAddress( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, + OUT EFI_PHYSICAL_ADDRESS* Address +); + +EFI_STATUS +EFIAPI +FvbGetBlockSize( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, + IN EFI_LBA Lba, + OUT UINTN* BlockSize, + OUT UINTN* NumberOfBlocks +); + +EFI_STATUS +EFIAPI +FvbRead( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN* NumBytes, + IN OUT UINT8* Buffer +); + +EFI_STATUS +EFIAPI +FvbWrite( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN* NumBytes, + IN UINT8* Buffer +); + +EFI_STATUS +EFIAPI +FvbEraseBlocks( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, + ... +); + +// +// FlashFvbDxe.c +// + +EFI_STATUS +FlashUnlockAndEraseSingleBlock ( + IN FLASH_INSTANCE* Instance, + IN UINTN BlockAddress +); + +EFI_STATUS +FlashWriteBlocks ( + IN FLASH_INSTANCE* Instance, + IN EFI_LBA Lba, + IN UINTN BufferSizeInBytes, + IN VOID* Buffer +); + +EFI_STATUS +FlashReadBlocks ( + IN FLASH_INSTANCE* Instance, + IN EFI_LBA Lba, + IN UINTN BufferSizeInBytes, + OUT VOID* Buffer +); + +#endif diff --git a/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.inf b/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.inf new file mode 100644 index 0000000000..09ec7ce08b --- /dev/null +++ b/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.inf @@ -0,0 +1,69 @@ +#/** @file +# +# Copyright (c) 2011-2015, ARM Limited. All rights reserved. +# Copyright (c) 2015, Hisilicon Limited. All rights reserved. +# Copyright (c) 2015, Linaro Limited. 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. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FlashFvbDxe + FILE_GUID = 93E34C7E-B50E-11DF-9223-2443DFD72085 + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = FlashFvbInitialize + +[Sources.common] + FlashFvbDxe.c + FlashBlockIoDxe.c + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + IoLib + BaseLib + DebugLib + HobLib + UefiLib + UefiDriverEntryPoint + UefiBootServicesTableLib + UefiRuntimeLib + +[Guids] + gEfiSystemNvDataFvGuid + gEfiVariableGuid + +[Protocols] + gEfiBlockIoProtocolGuid + gEfiDevicePathProtocolGuid + gEfiFirmwareVolumeBlockProtocolGuid + gHisiSpiFlashProtocolGuid + +[Pcd.common] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + + gArmPlatformTokenSpaceGuid.PcdNorFlashCheckBlockLocked + +[Depex] + gHisiSpiFlashProtocolGuid + +[BuildOptions] diff --git a/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatform.c b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatform.c new file mode 100644 index 0000000000..c8b56e1bd1 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatform.c @@ -0,0 +1,269 @@ +/** @file + Sample ACPI Platform Driver + + Copyright (c) 2008 - 2011, 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. + +**/ + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include "UpdateAcpiTable.h" + +/** + Locate the first instance of a protocol. If the protocol requested is an + FV protocol, then it will return the first FV that contains the ACPI table + storage file. + + @param Instance Return pointer to the first instance of the protocol + + @return EFI_SUCCESS The function completed successfully. + @return EFI_NOT_FOUND The protocol could not be located. + @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol. + +**/ +EFI_STATUS +LocateFvInstanceWithTables ( + OUT EFI_FIRMWARE_VOLUME2_PROTOCOL **Instance + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN NumberOfHandles; + EFI_FV_FILETYPE FileType; + UINT32 FvStatus; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINTN Size; + UINTN Index; + EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance; + + FvStatus = 0; + + // + // Locate protocol. + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &NumberOfHandles, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + // + // Defined errors at this time are not found and out of resources. + // + return Status; + } + + + + // + // Looking for FV with ACPI storage file + // + + for (Index = 0; Index < NumberOfHandles; Index++) { + // + // Get the protocol on this handle + // This should not fail because of LocateHandleBuffer + // + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID**) &FvInstance + ); + ASSERT_EFI_ERROR (Status); + + // + // See if it has the ACPI storage file + // + Status = FvInstance->ReadFile ( + FvInstance, + (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile), + NULL, + &Size, + &FileType, + &Attributes, + &FvStatus + ); + + // + // If we found it, then we are done + // + if (Status == EFI_SUCCESS) { + *Instance = FvInstance; + break; + } + } + + // + // Our exit status is determined by the success of the previous operations + // If the protocol was found, Instance already points to it. + // + + // + // Free any allocated buffers + // + gBS->FreePool (HandleBuffer); + + return Status; +} + + +/** + This function calculates and updates an UINT8 checksum. + + @param Buffer Pointer to buffer to checksum + @param Size Number of bytes to checksum + +**/ +VOID +AcpiPlatformChecksum ( + IN UINT8 *Buffer, + IN UINTN Size + ) +{ + UINTN ChecksumOffset; + + ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum); + + // + // Set checksum to 0 first + // + Buffer[ChecksumOffset] = 0; + + // + // Update checksum value + // + Buffer[ChecksumOffset] = CalculateCheckSum8(Buffer, Size); +} + + +/** + Entrypoint of Acpi Platform driver. + + @param ImageHandle + @param SystemTable + + @return EFI_SUCCESS + @return EFI_LOAD_ERROR + @return EFI_OUT_OF_RESOURCES + +**/ +EFI_STATUS +EFIAPI +AcpiPlatformEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_ACPI_TABLE_PROTOCOL *AcpiTable; + EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol; + INTN Instance; + EFI_ACPI_COMMON_HEADER *CurrentTable; + UINTN TableHandle; + UINT32 FvStatus; + UINTN TableSize; + UINTN Size; + EFI_STATUS TableStatus; + EFI_ACPI_DESCRIPTION_HEADER *TableHeader; + + Instance = 0; + CurrentTable = NULL; + TableHandle = 0; + + // + // Find the AcpiTable protocol + // + Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID**)&AcpiTable); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + + // + // Locate the firmware volume protocol + // + Status = LocateFvInstanceWithTables (&FwVol); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Read tables from the storage file. + // + while (Status == EFI_SUCCESS) { + + Status = FwVol->ReadSection ( + FwVol, + (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile), + EFI_SECTION_RAW, + Instance, + (VOID**) &CurrentTable, + &Size, + &FvStatus + ); + if (!EFI_ERROR(Status)) { + // + // Add the table + // + TableHeader = (EFI_ACPI_DESCRIPTION_HEADER*) (CurrentTable); + //Update specfic Acpi Table + //If the Table is updated failed, doesn't install it, + //go to find next section. + TableStatus = UpdateAcpiTable(TableHeader); + if (TableStatus == EFI_SUCCESS) { + TableHandle = 0; + + TableSize = ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length; + ASSERT (Size >= TableSize); + + // + // Checksum ACPI table + // + AcpiPlatformChecksum ((UINT8*)CurrentTable, TableSize); + + // + // Install ACPI table + // + Status = AcpiTable->InstallAcpiTable ( + AcpiTable, + CurrentTable, + TableSize, + &TableHandle + ); + } + // + // Free memory allocated by ReadSection + // + gBS->FreePool (CurrentTable); + + if (EFI_ERROR(Status)) { + return EFI_ABORTED; + } + + // + // Increment the instance + // + Instance++; + CurrentTable = NULL; + } + } + + return EFI_SUCCESS; +} + diff --git a/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatform.uni b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatform.uni new file mode 100644 index 0000000000..1275549bd0 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatform.uni @@ -0,0 +1,22 @@ +// /** @file +// Sample ACPI Platform Driver +// +// Sample ACPI Platform Driver +// +// Copyright (c) 2008 - 2014, 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. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Sample ACPI Platform Driver" + +#string STR_MODULE_DESCRIPTION #language en-US "Sample ACPI Platform Driver" + diff --git a/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatformDxe.inf b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatformDxe.inf new file mode 100644 index 0000000000..e268a56bbd --- /dev/null +++ b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatformDxe.inf @@ -0,0 +1,62 @@ +## @file +# Sample ACPI Platform Driver +# +# Copyright (c) 2008 - 2014, 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = AcpiPlatform + MODULE_UNI_FILE = AcpiPlatform.uni + FILE_GUID = cb933912-df8f-4305-b1f9-7b44fa11395c + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = AcpiPlatformEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + AcpiPlatform.c + UpdateAcpiTable.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + UefiLib + DxeServicesLib + PcdLib + BaseMemoryLib + DebugLib + HobLib + UefiBootServicesTableLib + UefiDriverEntryPoint + +[Protocols] + gEfiAcpiTableProtocolGuid ## CONSUMES + +[Guids] + gHisiEfiMemoryMapGuid + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile ## CONSUMES + +[Depex] + gEfiAcpiTableProtocolGuid + +[UserExtensions.TianoCore."ExtraFiles"] + AcpiPlatformExtra.uni diff --git a/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatformExtra.uni b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatformExtra.uni new file mode 100644 index 0000000000..4c21968f7a --- /dev/null +++ b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatformExtra.uni @@ -0,0 +1,20 @@ +// /** @file +// AcpiPlatform Localized Strings and Content +// +// Copyright (c) 2013 - 2014, 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. +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"ACPI Platform Sample DXE Driver" + + diff --git a/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/UpdateAcpiTable.c b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/UpdateAcpiTable.c new file mode 100644 index 0000000000..7d06fccc2b --- /dev/null +++ b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/UpdateAcpiTable.c @@ -0,0 +1,137 @@ +/** @file + Copyright (c) 2016, Hisilicon Limited. 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. +**/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CORE_NUM_PER_SOCKET 32 +#define NODE_IN_SOCKET 2 +#define CORECOUNT(X) ((X) * CORE_NUM_PER_SOCKET) + +STATIC +VOID +RemoveUnusedMemoryNode ( + IN OUT EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *Table, + IN UINTN MemoryNodeNum +) +{ + UINTN CurrPtr, NewPtr; + + if (MemoryNodeNum >= EFI_ACPI_MEMORY_AFFINITY_STRUCTURE_COUNT) { + return; + } + + CurrPtr = (UINTN) &(Table->Memory[EFI_ACPI_MEMORY_AFFINITY_STRUCTURE_COUNT]); + NewPtr = (UINTN) &(Table->Memory[MemoryNodeNum]); + + CopyMem ((VOID *)NewPtr, (VOID *)CurrPtr, (UINTN)Table + Table->Header.Header.Length - CurrPtr); + + Table->Header.Header.Length -= CurrPtr - NewPtr; + + return; +} + +STATIC +EFI_STATUS +UpdateSrat ( + IN OUT EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *Table + ) +{ + UINT8 Skt = 0; + UINTN Index = 0; + VOID *HobList; + GBL_DATA *Gbl_Data; + UINTN Base; + UINTN Size; + UINT8 NodeId; + UINT32 ScclInterleaveEn; + UINTN MemoryNode = 0; + + DEBUG((DEBUG_INFO, "SRAT: Updating SRAT memory information.\n")); + + HobList = GetHobList(); + if (HobList == NULL) { + return EFI_UNSUPPORTED; + } + Gbl_Data = (GBL_DATA*)GetNextGuidHob(&gHisiEfiMemoryMapGuid, HobList); + if (Gbl_Data == NULL) { + DEBUG((DEBUG_ERROR, "Get next Guid HOb fail.\n")); + return EFI_NOT_FOUND; + } + Gbl_Data = GET_GUID_HOB_DATA(Gbl_Data); + for(Skt = 0; Skt < MAX_SOCKET; Skt++) { + for(Index = 0; Index < MAX_NUM_PER_TYPE; Index++) { + NodeId = Gbl_Data->NumaInfo[Skt][Index].NodeId; + Base = Gbl_Data->NumaInfo[Skt][Index].Base; + Size = Gbl_Data->NumaInfo[Skt][Index].Length; + DEBUG((DEBUG_INFO, "Skt %d Index %d: NodeId = %d, Base = 0x%lx, Size = 0x%lx\n", Skt, Index, NodeId, Base, Size)); + if (Size > 0) { + Table->Memory[MemoryNode].ProximityDomain = NodeId; + Table->Memory[MemoryNode].AddressBaseLow = Base; + Table->Memory[MemoryNode].AddressBaseHigh = Base >> 32; + Table->Memory[MemoryNode].LengthLow = Size; + Table->Memory[MemoryNode].LengthHigh = Size >> 32; + MemoryNode = MemoryNode + 1; + } + } + ScclInterleaveEn = Gbl_Data->NumaInfo[Skt][0].ScclInterleaveEn; + DEBUG((DEBUG_INFO, "ScclInterleaveEn = %d\n", ScclInterleaveEn)); + //update gicc structure + if (ScclInterleaveEn != 0) { + DEBUG((DEBUG_INFO, "SRAT: Updating SRAT Gicc information.\n")); + for (Index = CORECOUNT (Skt); Index < CORECOUNT (Skt + 1); Index++) { + Table->Gicc[Index].ProximityDomain = Skt * NODE_IN_SOCKET; + } + } + } + + //remove invalid memory node + RemoveUnusedMemoryNode (Table, MemoryNode); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +UpdateSlit ( + IN OUT EFI_ACPI_DESCRIPTION_HEADER *Table + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +UpdateAcpiTable ( + IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader +) +{ + EFI_STATUS Status = EFI_SUCCESS; + + switch (TableHeader->Signature) { + + case EFI_ACPI_6_0_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE: + Status = UpdateSrat ((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) TableHeader); + break; + + case EFI_ACPI_6_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE: + Status = UpdateSlit (TableHeader); + break; + } + return Status; +} diff --git a/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/UpdateAcpiTable.h b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/UpdateAcpiTable.h new file mode 100644 index 0000000000..45b3729b6a --- /dev/null +++ b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/UpdateAcpiTable.h @@ -0,0 +1,16 @@ +/** @file + Copyright (c) 2016, Hisilicon Limited. 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. +**/ + +EFI_STATUS +UpdateAcpiTable ( + IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader +); + diff --git a/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashConfig.c b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashConfig.c new file mode 100644 index 0000000000..ab3b70caf2 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashConfig.c @@ -0,0 +1,162 @@ +/** @file +* +* Copyright (c) 2015, Hisilicon Limited. All rights reserved. +* Copyright (c) 2015, Linaro Limited. 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. +* +**/ + + +#include "NorFlashHw.h" + + +#define COMMAND_TYPE1 0x1 +#define COMMAND_TYPE2 0x2 +#define COMMAND_TYPE3 0x4 +#define COMMAND_TYPE4 0x8 +#define COMMAND_TYPE5 0x10 + + +NOR_FLASH_INFO_TABLE gFlashInfo[]= +{ + + {//S29GL512m + 0x00010001, + 0x227E227E, + 0x22232223, + 0x22012201, + 1, + 0x20000000, + 0x20000, + 0x0010, + COMMAND_TYPE1 + }, + {//S29GL1g + 0x00010001, + 0x227E227E, + 0x22282228, + 0x22012201, + 1, + 0x40000000, + 0x20000, + 0x0020, + COMMAND_TYPE1 + }, + {//M29ew512m + 0x00890089, + 0x227E227E, + 0x22232223, + 0x22012201, + 1, + 0x20000000, + 0x20000, + 0x0010, + COMMAND_TYPE1 + }, + {//M29EW2g + 0x00890089, + 0x227E227E, + 0x22482248, + 0x22012201, + 1, + 0x80000000, + 0x20000, + 0x0020, + COMMAND_TYPE1 + }, + { + 0x00890089, + 0x227E227E, + 0x22282228, + 0x22012201, + 1, + 0x10000000, + 0x20000, + 0x0020, + COMMAND_TYPE1 + }, + { + 0x00890089, + 0x227E227E, + 0x22282228, + 0x22012201, + 2, + 0x10000000, + 0x20000, + 0x0020, + COMMAND_TYPE1 + } +}; + + + +FLASH_COMMAND_RESET gFlashCommandReset[]= +{ + { + COMMAND_TYPE1, + (0x00F000F0) + } + +}; + + +FLASH_COMMAND_ID gFlashCommandId[]= +{ + { + COMMAND_TYPE1, + (0x0555), + (0x00AA00AA), + (0x02AA), + (0x00550055), + (0x0555), + (0x00900090), + (0x0000), + + (0x0001), + (0x000E), + (0x000F) + } +}; + + +FLASH_COMMAND_WRITE gFlashCommandWrite[]= +{ + { + COMMAND_TYPE1, + (0x0555), + (0x00AA00AA), + (0x02AA), + (0x00550055), + (0x00250025), + (0x00290029) + } + +}; + + +FLASH_COMMAND_ERASE gFlashCommandErase[]= +{ + { + COMMAND_TYPE1, + (0x0555), + (0x00AA00AA), + (0x02AA), + (0x00550055), + (0x0555), + (0x00800080), + (0x0555), + (0x00AA00AA), + (0x02AA), + (0x00550055), + (0x00300030) + } + +}; + diff --git a/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.c b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.c new file mode 100644 index 0000000000..8b8a5d7a3f --- /dev/null +++ b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.c @@ -0,0 +1,594 @@ +/** @file +* +* Copyright (c) 2015, Hisilicon Limited. All rights reserved. +* Copyright (c) 2015, Linaro Limited. 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. +* +**/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "NorFlashHw.h" + + +EFI_STATUS Erase( + IN UNI_NOR_FLASH_PROTOCOL *This, + IN UINT32 Offset, + IN UINT32 Length + ); + +EFI_STATUS Write( + IN UNI_NOR_FLASH_PROTOCOL *This, + IN UINT32 Offset, + IN UINT8 *Buffer, + UINT32 ulLength + ); + +EFI_STATUS Read( + IN UNI_NOR_FLASH_PROTOCOL *This, + IN UINT32 Offset, + IN OUT UINT8 *Buffer, + IN UINT32 ulLen + ); + +UNI_NOR_FLASH_PROTOCOL gUniNorFlash = { + Erase, + Write, + Read +}; + + +EFI_STATUS +EFIAPI Read( + IN UNI_NOR_FLASH_PROTOCOL *This, + IN UINT32 Offset, + IN OUT UINT8 *Buffer, + IN UINT32 ulLen + ) +{ + UINT32 index; + UINT64 ullAddr; + UINT32 ullCnt = 0; + UINT32 *puiBuffer32 = NULL; + UINT32 *puiDst32 = NULL; + UINT8 *pucBuffer8 = NULL; + UINT8 *pucDst8 = NULL; + + if (Offset + ulLen > (gFlashInfo[gIndex.InfIndex].SingleChipSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Exceed the flash scope!\n", __FUNCTION__,__LINE__)); + return EFI_INVALID_PARAMETER; + } + if (0 == ulLen) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Length is Zero!\n", __FUNCTION__,__LINE__)); + return EFI_INVALID_PARAMETER; + } + if (NULL == Buffer) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Buffer is NULL!\n", __FUNCTION__,__LINE__)); + return EFI_BAD_BUFFER_SIZE; + } + + + ullAddr = gIndex.Base + Offset; + + pucBuffer8 = (UINT8 *)Buffer; + pucDst8 = (UINT8 *)((UINTN)ullAddr); + + + if (ulLen < FOUR_BYTE_UNIT) + { + for(index = 0; index< ulLen; index++) + { + *pucBuffer8++ = *pucDst8++; + } + } + else + { + + ullCnt = Offset % FOUR_BYTE_UNIT; + ullCnt = FOUR_BYTE_UNIT - ullCnt; + + for(index = 0; index < ullCnt; index++) + { + *pucBuffer8++ = *pucDst8++; + } + + ulLen -= ullCnt; + + puiBuffer32 = (UINT32 *)pucBuffer8; + puiDst32 = (UINT32 *)pucDst8; + ullCnt = ulLen / FOUR_BYTE_UNIT; + + for(index = 0; index < ullCnt; index++) + { + *puiBuffer32++ = *puiDst32++; + } + + ullCnt = ulLen % FOUR_BYTE_UNIT; + pucBuffer8 = (UINT8 *)puiBuffer32; + pucDst8 = (UINT8 *)puiDst32; + + for(index = 0; index < ullCnt; index++) + { + *pucBuffer8++ = *pucDst8++; + } + } + + return EFI_SUCCESS; +} + + + +static EFI_STATUS WriteAfterErase_Fill( + IN const UINT32 Offset, + IN const UINT8 *Buffer, + IN const UINT32 Length + ) +{ + EFI_STATUS Status; + UINT32 Loop; + UINT32 DataOffset; + UINT32 NewOffset; + UINT8 *NewDataUnit; + + UINT32 FlashUnitLength; + + FlashUnitLength = gFlashInfo[gIndex.InfIndex].BufferProgramSize << gFlashInfo[gIndex.InfIndex].ParallelNum; + + if (0 == Length) + { + return EFI_SUCCESS; + } + if ((Offset % FlashUnitLength + Length) > FlashUnitLength) + { + DEBUG ((EFI_D_INFO, "[%a]:[%dL]:Exceed the Flash Size!\n", __FUNCTION__,__LINE__)); + return EFI_UNSUPPORTED; + } + + + Status = gBS->AllocatePool(EfiBootServicesData, FlashUnitLength, (VOID *)&NewDataUnit); + if (EFI_ERROR(Status)) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Allocate Pool failed, %r!\n", __FUNCTION__,__LINE__, Status)); + return Status; + } + + + NewOffset = Offset - (Offset % FlashUnitLength); + + gBS->CopyMem((VOID *)NewDataUnit, (VOID *)(UINTN)(gIndex.Base + NewOffset), FlashUnitLength); + + DataOffset = Offset % FlashUnitLength; + for (Loop = 0; Loop < Length; Loop ++) + { + NewDataUnit[(UINT32)(DataOffset + Loop)] = Buffer[Loop]; + } + + Status = BufferWrite(NewOffset, (void *)NewDataUnit, FlashUnitLength); + if (EFI_ERROR(Status)) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:BufferWrite %r!\n", __FUNCTION__,__LINE__, Status)); + return Status; + } + + (void)gBS->FreePool((VOID *)NewDataUnit); + return Status; +} + + +static EFI_STATUS WriteAfterErase_Final( + IN UINT32 Offset, + IN UINT8 *Buffer, + IN UINT32 Length + ) +{ + EFI_STATUS Status; + UINT32 Loop; + UINT32 FlashUnitLength; + + FlashUnitLength = gFlashInfo[gIndex.InfIndex].BufferProgramSize << gFlashInfo[gIndex.InfIndex].ParallelNum; + + if (0 == Length) + { + return EFI_SUCCESS; + } + + if (0 != (Offset % FlashUnitLength)) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: Offset must be a multiple of 0x%x!\n", __FUNCTION__,__LINE__,FlashUnitLength)); + return EFI_UNSUPPORTED; + } + + + Loop = Length / FlashUnitLength; + while (Loop --) + { + Status = BufferWrite(Offset, (void *)Buffer, FlashUnitLength); + if (EFI_ERROR(Status)) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:BufferWrite Failed: %r!\n", __FUNCTION__,__LINE__, Status)); + return EFI_DEVICE_ERROR; + } + Offset += FlashUnitLength; + Buffer += FlashUnitLength; + } + + + Length = Length % FlashUnitLength; + if (Length) + { + Status = WriteAfterErase_Fill(Offset, Buffer, Length); + if (EFI_ERROR(Status)) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:WriteAfterErase_Fill failed,%r!\n", __FUNCTION__,__LINE__, Status)); + return Status; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +WriteAfterErase( + UINT32 TempBase, + UINT32 Offset, + UINT8 *Buffer, + UINT32 Length + ) +{ + EFI_STATUS Status; + UINT32 FlashUnitLength; + + FlashUnitLength = gFlashInfo[gIndex.InfIndex].BufferProgramSize << gFlashInfo[gIndex.InfIndex].ParallelNum; + + if (0 == Length) + { + return EFI_SUCCESS; + } + + + if (Offset % FlashUnitLength) + { + UINT32 TempLength; + + + TempLength = FlashUnitLength - (Offset % FlashUnitLength); + if (TempLength > Length) + { + TempLength = Length; + } + Status = WriteAfterErase_Fill(Offset, Buffer, TempLength); + if (EFI_ERROR(Status)) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: %r!\n", __FUNCTION__,__LINE__, Status)); + return Status; + } + + Offset += TempLength; + Length -= TempLength; + Buffer += TempLength; + + //Desc:if Offset >= gOneFlashSize,modify base + if (0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize)) + { + TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize; + gIndex.Base = TempBase; + Offset = 0; + } + } + + + Status = WriteAfterErase_Final(Offset, Buffer, Length); + if (EFI_ERROR(Status)) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: %r!\n", __FUNCTION__,__LINE__, Status)); + return Status; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +FlashSectorErase( + UINT32 TempBase, + UINT32 Offset, + UINT32 Length + ) +{ + EFI_STATUS Status; + UINT32 SectorOffset; + UINT8 *StaticBuffer; + UINT8 *Buffer; + UINT32 TempOffset; + UINT32 TempLength; + UINT32 LeftLength; + + + if (0 == Length) + { + return EFI_SUCCESS; + } + + LeftLength = gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)); + if (LeftLength < Length) + { + return EFI_UNSUPPORTED; + } + + + SectorOffset = Offset - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)); + + Status = gBS->AllocatePool(EfiBootServicesData, gFlashInfo[gIndex.InfIndex].BlockSize * (UINTN)gFlashInfo[gIndex.InfIndex].ParallelNum, (VOID *)&StaticBuffer); + if (EFI_ERROR(Status)) + { + return Status; + } + + Buffer = StaticBuffer; + + gBS->CopyMem((VOID *)Buffer, (VOID *)(UINTN)(TempBase + SectorOffset), + (gFlashInfo[gIndex.InfIndex].BlockSize * (UINTN)gFlashInfo[gIndex.InfIndex].ParallelNum)); + + + Status = SectorErase(TempBase, SectorOffset); + if (EFI_ERROR(Status)) + { + goto DO; + } + + + TempOffset = SectorOffset; + TempLength = Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum); + + Status = WriteAfterErase(TempBase, TempOffset, Buffer, TempLength); + if (EFI_ERROR(Status)) + { + goto DO; + } + + + Buffer = Buffer + TempLength + Length; + TempOffset = Offset + Length; + TempLength = SectorOffset + (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum) - TempOffset; + + Status = WriteAfterErase(TempBase, TempOffset, Buffer, TempLength); + if (EFI_ERROR(Status)) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: %r!\n", __FUNCTION__,__LINE__,Status)); + goto DO; + } + + (void)gBS->FreePool((VOID *)StaticBuffer); + return EFI_SUCCESS; + +DO: + (void)gBS->FreePool((VOID *)StaticBuffer); + return Status; +} + + +EFI_STATUS +EFIAPI Erase( + IN UNI_NOR_FLASH_PROTOCOL *This, + IN UINT32 Offset, + IN UINT32 Length + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINT32 Sectors; + UINT32 TempLength; + UINT32 TempBase; + UINT32 Loop; + + + if (Offset + Length > (gFlashInfo[gIndex.InfIndex].SingleChipSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Exceed the Flash Size!\n", __FUNCTION__,__LINE__)); + return EFI_ABORTED; + } + if (0 == Length) + { + return EFI_SUCCESS; + } + + + Sectors = ((Offset + Length - 1) / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) - (Offset / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) + 1; + TempBase = gIndex.Base; + + //if Offset >= gOneFlashSize,modify base + if(0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize)) + { + TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize * (Offset/gFlashInfo[gIndex.InfIndex].SingleChipSize); + Offset = Offset - (Offset & gFlashInfo[gIndex.InfIndex].SingleChipSize); + } + + for (Loop = 0; Loop <= Sectors; Loop ++) + { + + TempLength = gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)); + + + if (TempLength > Length) + { + TempLength = Length; + } + + Status = FlashSectorErase(TempBase, Offset, TempLength); + if (EFI_ERROR(Status)) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: FlashErase One Sector Error, Status = %r!\n", __FUNCTION__,__LINE__,Status)); + return Status; + } + + Offset += TempLength; + + //if Offset >= gOneFlashSize,modify base + if (0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize)) + { + TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize; + Offset = 0; + } + Length -= TempLength; + } + + return Status; +} + + +EFI_STATUS +EFIAPI Write( + IN UNI_NOR_FLASH_PROTOCOL *This, + IN UINT32 Offset, + IN UINT8 *Buffer, + UINT32 ulLength + ) +{ + EFI_STATUS Status; + UINT32 TempLength; + UINT32 TempBase; + UINT32 Loop; + UINT32 Sectors; + + if((Offset + ulLength) > (gFlashInfo[gIndex.InfIndex].SingleChipSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Exceed the Flash Size!\n", __FUNCTION__,__LINE__)); + return EFI_INVALID_PARAMETER; + } + if (0 == ulLength) + { + return EFI_SUCCESS; + } + + + Sectors = ((Offset + ulLength - 1) / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) - (Offset / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) + 1; + TempBase = gIndex.Base; + + //if Offset >= gOneFlashSize,modify base + if(0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize)) + { + TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize * (Offset/gFlashInfo[gIndex.InfIndex].SingleChipSize); + Offset = Offset - (Offset & gFlashInfo[gIndex.InfIndex].SingleChipSize); + } + + for (Loop = 0; Loop <= Sectors; Loop ++) + { + + TempLength = gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)); + + + if (TempLength > ulLength) + { + TempLength = ulLength; + } + + + if (TRUE == IsNeedToWrite(TempBase, Offset, Buffer, TempLength)) + { + Status = FlashSectorErase(TempBase, Offset, TempLength); + if (EFI_ERROR(Status)) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:FlashErase One Sector Error, Status = %r!\n", __FUNCTION__,__LINE__,Status)); + return Status; + } + + + Status = WriteAfterErase(TempBase, Offset, Buffer, TempLength); + if (EFI_ERROR(Status)) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:WriteAfterErase Status = %r!\n", __FUNCTION__,__LINE__,Status)); + return Status; + } + } + + Offset += TempLength; + Buffer += TempLength; + + //if Offset >= gOneFlashSize,modify base + if (0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize)) + { + TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize; + Offset = 0; + } + ulLength -= TempLength; + } + + return EFI_SUCCESS; +} + + +VOID SetFlashAttributeToUncache(VOID) +{ + EFI_CPU_ARCH_PROTOCOL *gCpu = NULL; + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpu); + if (EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "LocateProtocol gEfiCpuArchProtocolGuid Status = %r !\n", Status)); + } + + Status = gCpu->SetMemoryAttributes( + gCpu, + PcdGet64(PcdNORFlashBase), + PcdGet32(PcdNORFlashCachableSize), + EFI_MEMORY_UC + ); + + if (EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "gCpu->SetMemoryAttributes Status = %r !\n", Status)); + } + +} + +EFI_STATUS +EFIAPI InitializeFlash ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable) +{ + EFI_STATUS Status; + + + gIndex.Base = (UINT32)PcdGet64(PcdNORFlashBase); + + SetFlashAttributeToUncache(); + Status = FlashInit(gIndex.Base); + if (EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "Init Flash Error !\n")); + return Status; + } + else + { + DEBUG((EFI_D_ERROR, "Init Flash OK!\n")); + } + + Status = gBS->InstallProtocolInterface ( + &ImageHandle, + &gUniNorFlashProtocolGuid, + EFI_NATIVE_INTERFACE, + &gUniNorFlash); + if(EFI_SUCCESS != Status) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Install Protocol Interface %r!\n", __FUNCTION__,__LINE__,Status)); + } + + return Status; +} diff --git a/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.inf b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.inf new file mode 100644 index 0000000000..254e27eeac --- /dev/null +++ b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.inf @@ -0,0 +1,64 @@ +#/** @file +# +# Copyright (c) 2015, Hisilicon Limited. All rights reserved. +# Copyright (c) 2015, Linaro Limited. 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. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = NorFlashDxe + FILE_GUID = E29977F9-20A4-4551-B0EC-BCE246592E73 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = InitializeFlash + +[Sources.common] + NorFlashDxe.c + NorFlashHw.c + NorFlashConfig.c + +[Packages] + ArmPlatformPkg/ArmPlatformPkg.dec + MdePkg/MdePkg.dec + ArmPkg/ArmPkg.dec + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + UefiDriverEntryPoint + DebugLib + BaseLib + DebugLib + IoLib + SerialPortLib + ArmLib + CacheMaintenanceLib + UefiLib + PrintLib + PcdLib + + DxeServicesTableLib +[Guids] + +[Protocols] + gUniNorFlashProtocolGuid + gEfiCpuArchProtocolGuid + +[Pcd] + gHisiTokenSpaceGuid.PcdNORFlashBase + gHisiTokenSpaceGuid.PcdNORFlashCachableSize + + +[Depex] + TRUE + diff --git a/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.c b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.c new file mode 100644 index 0000000000..3aeaeb9091 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.c @@ -0,0 +1,628 @@ +/** @file +* +* Copyright (c) 2015, Hisilicon Limited. All rights reserved. +* Copyright (c) 2015, Linaro Limited. 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. +* +**/ + +#include +#include +#include +#include +#include "NorFlashHw.h" + + +BOOLEAN gFlashBusy = FALSE; +FLASH_INDEX gIndex = { + 0, + 0, + 0, + 0, + 0, + 0 +}; + + +UINT32 PortReadData ( + UINT32 Index, + UINT32 FlashAddr + ) +{ + + switch (gFlashInfo[Index].ParallelNum) + { + case 2: + return MmioRead32 (FlashAddr); + case 1: + return MmioRead16 (FlashAddr); + + default: + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:illegal PortWidth!\n", __FUNCTION__,__LINE__)); + return 0xffffffff; + } +} + +EFI_STATUS +PortWriteData ( + UINT32 Index, + UINT32 FlashAddr, + UINT32 InputData + ) +{ + + switch (gFlashInfo[Index].ParallelNum) + { + case 2: + MmioWrite32 (FlashAddr, InputData); + break; + case 1: + MmioWrite16 (FlashAddr, InputData); + break; + default: + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:illegal PortWidth!\n", __FUNCTION__,__LINE__)); + return EFI_DEVICE_ERROR; + } + return EFI_SUCCESS; +} + +UINT32 PortAdjustData( + UINT32 Index, + UINT32 ulInputData + ) +{ + + switch (gFlashInfo[Index].ParallelNum) + { + case 2: + return ulInputData; + case 1: + return (0x0000ffff & ulInputData ); + default: + DEBUG((EFI_D_ERROR,"[FLASH_S29GL256N_PortAdjustData]: Error--illegal g_ulFlashS29Gl256NPortWidth!\n\r")); + return 0xffffffff; + } +} + + +EFI_STATUS GetCommandIndex( + UINT32 Index + ) +{ + UINT32 CommandCount = 0; + UINT32 i; + UINT8 Flag = 1; + + CommandCount = sizeof(gFlashCommandReset) / sizeof(FLASH_COMMAND_RESET); + for(i = 0;i < CommandCount; i ++ ) + { + if(gFlashInfo[Index].CommandType & gFlashCommandReset[i].CommandType) + { + Flag = 0; + gIndex.ReIndex = i; + break; + } + } + + if(Flag) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Can not Get Reset Command!\n", __FUNCTION__,__LINE__)); + return EFI_DEVICE_ERROR; + } + + CommandCount = sizeof(gFlashCommandId) / sizeof(FLASH_COMMAND_ID); + for(Flag = 1,i = 0;i < CommandCount; i ++ ) + { + if(gFlashInfo[Index].CommandType & gFlashCommandId[i].CommandType) + { + Flag = 0; + gIndex.IdIndex = i; + break; + } + } + + if(Flag) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Can not Get ID Command!\n", __FUNCTION__,__LINE__)); + return EFI_DEVICE_ERROR; + } + + CommandCount = sizeof(gFlashCommandWrite) / sizeof(FLASH_COMMAND_WRITE); + for(Flag = 1, i = 0;i < CommandCount; i ++ ) + { + if(gFlashInfo[Index].CommandType & gFlashCommandWrite[i].CommandType) + { + Flag = 0; + gIndex.WIndex = i; + break; + } + } + + if(Flag) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Can not Get Write Command!\n", __FUNCTION__,__LINE__)); + return EFI_DEVICE_ERROR; + } + + CommandCount = sizeof(gFlashCommandErase) / sizeof(FLASH_COMMAND_ERASE); + for(Flag = 1, i = 0;i < CommandCount; i ++ ) + { + if(gFlashInfo[Index].CommandType & gFlashCommandErase[i].CommandType) + { + Flag = 0; + gIndex.WIndex = i; + break; + } + } + + if(Flag) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Can not Get Erase Command!\n", __FUNCTION__,__LINE__)); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + + +VOID FlashReset(UINT32 Base) +{ + (VOID)PortWriteData(gIndex.InfIndex, Base, gFlashCommandReset[gIndex.ReIndex].ResetData); + (void)gBS->Stall(20000); +} + + +void GetManufacturerID(UINT32 Index, UINT32 Base, UINT8 *pbyData) +{ + + UINT32 dwAddr; + + FlashReset(Base); + + dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep1 << gFlashInfo[Index].ParallelNum); + (VOID)PortWriteData(Index, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep1); + + dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep2 << gFlashInfo[Index].ParallelNum); + (VOID)PortWriteData(Index, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep2); + + dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep3 << gFlashInfo[Index].ParallelNum); + (VOID)PortWriteData(Index, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep3); + + *pbyData = (UINT8)PortReadData(Index, Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddress << gFlashInfo[Index].ParallelNum)); + + FlashReset(Base); //must reset to return to the read mode +} + + +EFI_STATUS FlashInit(UINT32 Base) +{ + UINT32 FlashCount = 0; + UINT32 i = 0; + EFI_STATUS Status; + UINT8 Flag = 1; + UINT32 TempData = 0; + UINT32 TempDev1 = 0; + UINT32 TempDev2 = 0; + UINT32 TempDev3 = 0; + UINT32 dwAddr; + + FlashCount = sizeof(gFlashInfo) / sizeof(NOR_FLASH_INFO_TABLE); + for(;i < FlashCount; i ++ ) + { + + Status = GetCommandIndex(i); + if (EFI_ERROR(Status)) + { + DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Get Command Index %r!\n", __FUNCTION__,__LINE__, Status)); + return Status; + } + + FlashReset(Base); + + dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep1 << gFlashInfo[i].ParallelNum); + (VOID)PortWriteData(i, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep1); + + dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep2 << gFlashInfo[i].ParallelNum); + (VOID)PortWriteData(i, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep2); + + dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep3 << gFlashInfo[i].ParallelNum); + (VOID)PortWriteData(i, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep3); + //Get manufacture ID + TempData = PortReadData(i, Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddress << gFlashInfo[i].ParallelNum)); + + //Get Device Id + TempDev1 = PortReadData(i, Base + (gFlashCommandId[gIndex.IdIndex].DeviceIDAddress1 << gFlashInfo[i].ParallelNum)); + TempDev2 = PortReadData(i, Base + (gFlashCommandId[gIndex.IdIndex].DeviceIDAddress2 << gFlashInfo[i].ParallelNum)); + TempDev3 = PortReadData(i, Base + (gFlashCommandId[gIndex.IdIndex].DeviceIDAddress3 << gFlashInfo[i].ParallelNum)); + DEBUG ((EFI_D_ERROR, "[cdtest]manufactor ID 0x%x!\n",TempData)); + DEBUG ((EFI_D_ERROR, "[cdtest]Device ID 1 0x%x!\n",TempDev1)); + DEBUG ((EFI_D_ERROR, "[cdtest]Device ID 2 0x%x!\n",TempDev2)); + DEBUG ((EFI_D_ERROR, "[cdtest]Device ID 3 0x%x!\n",TempDev3)); + + FlashReset(Base); + + + if((0xffffffff != TempData) + && (PortAdjustData(i, gFlashInfo[i].ManufacturerID) == TempData)) + { + if((0xffffffff != TempDev1) + && (PortAdjustData(i, gFlashInfo[i].DeviceID1) == TempDev1)) + { + if((0xffffffff != TempDev2) + && (PortAdjustData(i, gFlashInfo[i].DeviceID2) == TempDev2)) + { + if((0xffffffff != TempDev3) + && (PortAdjustData(i, gFlashInfo[i].DeviceID3) == TempDev3)) + { + Flag = 0; + gIndex.InfIndex = i; + break; + } + } + } + } + } + + if(Flag) + { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + + +static BOOLEAN width8IsAll( + const UINT64 Base, + const UINT64 Offset, + const UINT64 Length, + const UINT8 Value +) +{ + UINT64 NewAddr = Base + Offset; + UINT64 NewLength = Length; + while (NewLength --) + { + if (*(UINT8 *)(UINTN)NewAddr == Value) + { + NewAddr ++; + continue; + } + else + { + return FALSE; + } + } + return TRUE; +} + + + +EFI_STATUS BufferWriteCommand(UINTN Base, UINTN Offset, void *pData) +{ + UINT32 dwCommAddr; + UINT32 *pdwData; + UINT16 *pwData; + UINT32 dwLoop; + UINT32 ulWriteWordCount; + UINT32 dwAddr; + + if(gFlashBusy) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL]:Flash is busy!\n", __FUNCTION__,__LINE__)); + return EFI_NOT_READY; + } + gFlashBusy = TRUE; + + if(2 == gFlashInfo[gIndex.InfIndex].ParallelNum) + { + pdwData = (UINT32 *)pData; + + dwAddr = (UINT32)Base + (gFlashCommandWrite[gIndex.WIndex].BufferProgramAddressStep1 << gFlashInfo[gIndex.InfIndex].ParallelNum); + (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep1); + + dwAddr = (UINT32)Base + (gFlashCommandWrite[gIndex.WIndex].BufferProgramAddressStep2 << gFlashInfo[gIndex.InfIndex].ParallelNum); + (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep2); + + //dwAddr = Base + (Offset << gFlashInfo[gIndex.InfIndex].ParallelNum); + dwAddr = (UINT32)Base + Offset; + (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep3); + + + ulWriteWordCount = ((gFlashInfo[gIndex.InfIndex].BufferProgramSize - 1) << 16) | (gFlashInfo[gIndex.InfIndex].BufferProgramSize - 1); + (VOID)PortWriteData(gIndex.InfIndex, dwAddr, ulWriteWordCount); + + + for (dwLoop = 0; dwLoop < gFlashInfo[gIndex.InfIndex].BufferProgramSize; dwLoop ++) + { + dwCommAddr = (UINT32)Base + (UINT32)Offset + (dwLoop << gFlashInfo[gIndex.InfIndex].ParallelNum); + MmioWrite32 (dwCommAddr, *pdwData); + pdwData ++; + } + + dwAddr = (UINT32)Base + (UINT32)Offset + ((gFlashInfo[gIndex.InfIndex].BufferProgramSize - 1) << gFlashInfo[gIndex.InfIndex].ParallelNum); + (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramtoFlash); + + + + } + else + { + pwData = (UINT16 *)pData; + + dwAddr = (UINT32)Base + (gFlashCommandWrite[gIndex.WIndex].BufferProgramAddressStep1 << gFlashInfo[gIndex.InfIndex].ParallelNum); + (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep1); + + dwAddr = (UINT32)Base + (gFlashCommandWrite[gIndex.WIndex].BufferProgramAddressStep2 << gFlashInfo[gIndex.InfIndex].ParallelNum); + (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep2); + + //dwAddr = Base + (Offset << gFlashInfo[gIndex.InfIndex].ParallelNum); + dwAddr = (UINT32)Base + Offset; + (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep3); + + + ulWriteWordCount = gFlashInfo[gIndex.InfIndex].BufferProgramSize - 1; + (VOID)PortWriteData(gIndex.InfIndex, dwAddr, ulWriteWordCount); + + + for (dwLoop = 0; dwLoop < gFlashInfo[gIndex.InfIndex].BufferProgramSize; dwLoop ++) + { + dwCommAddr = (UINT32)Base + (UINT32)Offset + (dwLoop << gFlashInfo[gIndex.InfIndex].ParallelNum); + MmioWrite16 (dwCommAddr, *pwData); + pwData ++; + } + + dwAddr = (UINT32)Base + (UINT32)Offset + ((gFlashInfo[gIndex.InfIndex].BufferProgramSize - 1) << gFlashInfo[gIndex.InfIndex].ParallelNum); + (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramtoFlash); + + } + + (void)gBS->Stall(200); + + gFlashBusy = FALSE; + return EFI_SUCCESS; + +} + + +EFI_STATUS SectorEraseCommand(UINTN Base, UINTN Offset) +{ + UINT32 dwAddr; + + if(gFlashBusy) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL]:Flash is busy!\n", __FUNCTION__,__LINE__)); + return EFI_NOT_READY; + } + + gFlashBusy = TRUE; + + dwAddr = (UINT32)Base + (gFlashCommandErase[gIndex.EIndex].SectorEraseAddressStep1 << gFlashInfo[gIndex.InfIndex].ParallelNum); + (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep1); + + dwAddr = (UINT32)Base + (gFlashCommandErase[gIndex.EIndex].SectorEraseAddressStep2 << gFlashInfo[gIndex.InfIndex].ParallelNum); + (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep2); + + dwAddr = (UINT32)Base + (gFlashCommandErase[gIndex.EIndex].SectorEraseAddressStep3 << gFlashInfo[gIndex.InfIndex].ParallelNum); + (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep3); + + dwAddr = (UINT32)Base + (gFlashCommandErase[gIndex.EIndex].SectorEraseAddressStep4 << gFlashInfo[gIndex.InfIndex].ParallelNum); + (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep4); + + dwAddr = (UINT32)Base + (gFlashCommandErase[gIndex.EIndex].SectorEraseAddressStep5 << gFlashInfo[gIndex.InfIndex].ParallelNum); + (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep5); + + dwAddr = (UINT32)Base + Offset; + (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep6); + + (void)gBS->Stall(500000); + + gFlashBusy = FALSE; + return EFI_SUCCESS; +} + + +EFI_STATUS CompleteCheck(UINT32 Base, UINT32 Offset, void *pData, UINT32 Length) +{ + UINT32 dwTestAddr; + UINT32 dwTestData; + UINT32 dwTemp = 0; + UINT32 dwTemp1 = 0; + UINT32 i; + UINT32 dwTimeOut = 3000000; + + if(gFlashBusy) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL]:Flash is busy!\n", __FUNCTION__,__LINE__)); + return EFI_NOT_READY; + } + gFlashBusy = TRUE; + + if(2 == gFlashInfo[gIndex.InfIndex].ParallelNum) + { + dwTestAddr = Base + Offset + Length - sizeof(UINT32); + dwTestData = *((UINT32 *)((UINT8 *)pData + Length - sizeof(UINT32))); + + while(dwTimeOut--) + { + dwTemp1 = MmioRead32 (dwTestAddr); + if (dwTestData == dwTemp1) + { + dwTemp = MmioRead32 (dwTestAddr); + dwTemp1 = MmioRead32 (dwTestAddr); + if ((dwTemp == dwTemp1) && (dwTestData == dwTemp1)) + { + gFlashBusy = FALSE; + return EFI_SUCCESS; + } + } + + (void)gBS->Stall(1); + } + + if((UINT16)(dwTemp1 >> 16) != (UINT16)(dwTestData >> 16)) + { + DEBUG((EFI_D_ERROR, "CompleteCheck ERROR: chip1 address %x, buffer %x, flash %x!\n", Offset, dwTestData, dwTemp1)); + } + if((UINT16)(dwTemp1) != (UINT16)(dwTestData)) + { + DEBUG((EFI_D_ERROR, "CompleteCheck ERROR: chip2 address %x, buffer %x, flash %x!\n", Offset, dwTestData, dwTemp1)); + } + } + else + { + dwTestAddr = Base + Offset + Length - sizeof(UINT16); + dwTestData = *((UINT16 *)((UINT8 *)pData + Length - sizeof(UINT16))); + + while(dwTimeOut--) + { + dwTemp1 = MmioRead16 (dwTestAddr); + if (dwTestData == dwTemp1) + { + dwTemp = MmioRead16 (dwTestAddr); + dwTemp1 = MmioRead16 (dwTestAddr); + if ((dwTemp == dwTemp1) && (dwTestData == dwTemp1)) + { + gFlashBusy = FALSE; + return EFI_SUCCESS; + } + } + + (void)gBS->Stall(1); + } + } + + for(i = 0; i < 5; i ++) + { + DEBUG((EFI_D_ERROR, "CompleteCheck ERROR: flash %x\n",PortReadData(gIndex.InfIndex, dwTestAddr))); + } + + FlashReset(Base); + + gFlashBusy = FALSE; + DEBUG((EFI_D_ERROR, "CompleteCheck ERROR: timeout address %x, buffer %x, flash %x\n", Offset, dwTestData, dwTemp1)); + return EFI_TIMEOUT; +} + +EFI_STATUS IsNeedToWrite( + IN UINT32 Base, + IN UINT32 Offset, + IN UINT8 *Buffer, + IN UINT32 Length + ) +{ + UINTN NewAddr = Base + Offset; + UINT8 FlashData = 0; + UINT8 BufferData = 0; + + for(; Length > 0; Length --) + { + BufferData = *Buffer; + //lint -epn -e511 + FlashData = *(UINT8 *)NewAddr; + if (BufferData != FlashData) + { + return TRUE; + } + NewAddr ++; + Buffer ++; + } + + return FALSE; +} + + +EFI_STATUS BufferWrite(UINT32 Offset, void *pData, UINT32 Length) +{ + EFI_STATUS Status; + UINT32 dwLoop; + UINT32 Retry = 3; + + if (FALSE == IsNeedToWrite(gIndex.Base, Offset, (UINT8 *)pData, Length)) + { + return EFI_SUCCESS; + } + + do + { + (void)BufferWriteCommand(gIndex.Base, Offset, pData); + Status = CompleteCheck(gIndex.Base, Offset, pData, Length); + + + if (EFI_SUCCESS == Status) + { + for (dwLoop = 0; dwLoop < Length; dwLoop ++) + { + if (*(UINT8 *)(UINTN)(gIndex.Base + Offset + dwLoop) != *((UINT8 *)pData + dwLoop)) + { + DEBUG((EFI_D_ERROR, "Flash_WriteUnit ERROR: address %x, buffer %x, flash %x\n", Offset, *((UINT8 *)pData + dwLoop), *(UINT8 *)(UINTN)(gIndex.Base + Offset + dwLoop))); + Status = EFI_ABORTED; + continue; + } + } + } + else + { + DEBUG((EFI_D_ERROR, "Flash_WriteUnit ERROR: complete check failed, %r\n", Status)); + continue; + } + } while ((Retry--) && EFI_ERROR(Status)); + + return Status; +} + + +EFI_STATUS SectorErase(UINT32 Base, UINT32 Offset) +{ + UINT8 gTemp[FLASH_MAX_UNIT]; + UINT64 dwLoop = FLASH_MAX_UNIT - 1; + UINT32 Retry = 3; + EFI_STATUS Status; + + do + { + gTemp[dwLoop] = 0xFF; + }while (dwLoop --); + + do + { + (void)SectorEraseCommand(Base, Offset); + Status = CompleteCheck(Base, Offset, (void *)gTemp, FLASH_MAX_UNIT); + + + if (EFI_SUCCESS == Status) + { + + if (width8IsAll(Base,Offset - (Offset % gFlashInfo[gIndex.InfIndex].BlockSize), gFlashInfo[gIndex.InfIndex].BlockSize, 0xFF)) + { + return EFI_SUCCESS; + } + else + { + DEBUG((EFI_D_ERROR, "Flash_SectorErase ERROR: not all address equal 0xFF\n")); + + Status = EFI_ABORTED; + continue; + } + } + else + { + DEBUG((EFI_D_ERROR, "Flash_SectorErase ERROR: complete check failed, %r\n", Status)); + continue; + } + }while ((Retry--) && EFI_ERROR(Status)); + + if(Retry) + { + //do nothing for pclint + } + + return Status; +} diff --git a/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.h b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.h new file mode 100644 index 0000000000..36c0c9ec23 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.h @@ -0,0 +1,116 @@ +/** @file +* +* Copyright (c) 2015, Hisilicon Limited. All rights reserved. +* Copyright (c) 2015, Linaro Limited. 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. +* +**/ + +#ifndef _NOR_FLASH_HW_H_ +#define _NOR_FLASH_HW_H_ + +#include + + +#define FOUR_BYTE_UNIT 4 +#define FLASH_MAX_UNIT 4 + +#define FLASH_DEVICE_NUM 0x10 + + + +typedef struct { + UINT32 ManufacturerID; + UINT32 DeviceID1; + UINT32 DeviceID2; + UINT32 DeviceID3; + UINT8 ParallelNum; + UINT32 SingleChipSize; + UINT32 BlockSize; + UINT32 BufferProgramSize; + UINT32 CommandType; +}NOR_FLASH_INFO_TABLE; + +/*Define Command Address And Data*/ +/*reset*/ +typedef struct { + UINT32 CommandType; + UINT32 ResetData; +}FLASH_COMMAND_RESET; + +/*manufacture ID & Device ID*/ +typedef struct { + UINT32 CommandType; + UINT32 ManuIDAddressStep1; + UINT32 ManuIDDataStep1; + UINT32 ManuIDAddressStep2; + UINT32 ManuIDDataStep2; + UINT32 ManuIDAddressStep3; + UINT32 ManuIDDataStep3; + UINT32 ManuIDAddress; + + UINT32 DeviceIDAddress1; + UINT32 DeviceIDAddress2; + UINT32 DeviceIDAddress3; +}FLASH_COMMAND_ID; + +/*Write Buffer*/ +typedef struct { + UINT32 CommandType; + UINT32 BufferProgramAddressStep1; + UINT32 BufferProgramDataStep1; + UINT32 BufferProgramAddressStep2; + UINT32 BufferProgramDataStep2; + UINT32 BufferProgramDataStep3; + UINT32 BufferProgramtoFlash; +}FLASH_COMMAND_WRITE; + +/*erase*/ +typedef struct { + UINT32 CommandType; + UINT32 SectorEraseAddressStep1; + UINT32 SectorEraseDataStep1; + UINT32 SectorEraseAddressStep2; + UINT32 SectorEraseDataStep2; + UINT32 SectorEraseAddressStep3; + UINT32 SectorEraseDataStep3; + UINT32 SectorEraseAddressStep4; + UINT32 SectorEraseDataStep4; + UINT32 SectorEraseAddressStep5; + UINT32 SectorEraseDataStep5; + UINT32 SectorEraseDataStep6; +}FLASH_COMMAND_ERASE; + + +typedef struct { + UINT32 Base; + UINT32 InfIndex; + UINT32 ReIndex; + UINT32 IdIndex; + UINT32 WIndex; + UINT32 EIndex; +}FLASH_INDEX; + + +extern EFI_STATUS FlashInit(UINT32 Base); +extern EFI_STATUS SectorErase(UINT32 Base, UINT32 Offset); +extern EFI_STATUS BufferWrite(UINT32 Offset, void *pData, UINT32 Length); +extern EFI_STATUS IsNeedToWrite(UINT32 Base, UINT32 Offset, UINT8 *Buffer, UINT32 Length); + + +extern NOR_FLASH_INFO_TABLE gFlashInfo[FLASH_DEVICE_NUM]; +extern FLASH_COMMAND_RESET gFlashCommandReset[FLASH_DEVICE_NUM]; +extern FLASH_COMMAND_ID gFlashCommandId[FLASH_DEVICE_NUM]; +extern FLASH_COMMAND_WRITE gFlashCommandWrite[FLASH_DEVICE_NUM]; +extern FLASH_COMMAND_ERASE gFlashCommandErase[FLASH_DEVICE_NUM]; +extern FLASH_INDEX gIndex; + + +#endif diff --git a/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridge.c b/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridge.c new file mode 100644 index 0000000000..a970da65df --- /dev/null +++ b/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridge.c @@ -0,0 +1,1651 @@ +/** + * Copyright (c) 2014, AppliedMicro Corp. All rights reserved. + * Copyright (c) 2016, Hisilicon Limited. All rights reserved. + * Copyright (c) 2016, Linaro Limited. 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. + * + **/ + +#include +#include +#include +#include +#include +#include + +#include "PciHostBridge.h" + +UINTN RootBridgeNumber[PCIE_MAX_HOSTBRIDGE] = { PCIE_MAX_ROOTBRIDGE,PCIE_MAX_ROOTBRIDGE }; + +UINT64 RootBridgeAttribute[PCIE_MAX_HOSTBRIDGE][PCIE_MAX_ROOTBRIDGE] = { + { //Host Bridge0 + EFI_PCI_HOST_BRIDGE_MEM64_DECODE, + EFI_PCI_HOST_BRIDGE_MEM64_DECODE, + EFI_PCI_HOST_BRIDGE_MEM64_DECODE, + EFI_PCI_HOST_BRIDGE_MEM64_DECODE, + EFI_PCI_HOST_BRIDGE_MEM64_DECODE, + EFI_PCI_HOST_BRIDGE_MEM64_DECODE, + EFI_PCI_HOST_BRIDGE_MEM64_DECODE, + EFI_PCI_HOST_BRIDGE_MEM64_DECODE, + }, + { //Host Bridge1 + EFI_PCI_HOST_BRIDGE_MEM64_DECODE, + EFI_PCI_HOST_BRIDGE_MEM64_DECODE, + EFI_PCI_HOST_BRIDGE_MEM64_DECODE, + EFI_PCI_HOST_BRIDGE_MEM64_DECODE, + EFI_PCI_HOST_BRIDGE_MEM64_DECODE, + EFI_PCI_HOST_BRIDGE_MEM64_DECODE, + EFI_PCI_HOST_BRIDGE_MEM64_DECODE, + EFI_PCI_HOST_BRIDGE_MEM64_DECODE, + } + }; + +EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[PCIE_MAX_HOSTBRIDGE][PCIE_MAX_ROOTBRIDGE] = { + { //Host Bridge0 + /* Port 0 */ + { + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID(0x0A03), + 0 + }, + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } + }, + /* Port 1 */ + { + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID(0x0A04), + 0 + }, + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } + }, + /* Port 2 */ + { + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID(0x0A05), + 0 + }, + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } + }, + /* Port 3 */ + { + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID(0x0A06), + 0 + }, + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } + }, + /* Port 4 */ + { + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID(0x0A07), + 0 + }, + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } + }, + /* Port 5 */ + { + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID(0x0A08), + 0 + }, + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } + }, + /* Port 6 */ + { + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID(0x0A09), + 0 + }, + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } + }, + /* Port 7 */ + { + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID(0x0A0A), + 0 + }, + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } + } +}, +{ // Host Bridge1 + /* Port 0 */ + { + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID(0x0A0B), + 0 + }, + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } + }, + /* Port 1 */ + { + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID(0x0A0C), + 0 + }, + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } + }, + /* Port 2 */ + { + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID(0x0A0D), + 0 + }, + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } + }, + /* Port 3 */ + { + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID(0x0A0E), + 0 + }, + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } + }, + /* Port 4 */ + { + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID(0x0A0F), + 0 + }, + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } + }, + /* Port 5 */ + { + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID(0x0A10), + 0 + }, + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } + }, + /* Port 6 */ + { + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID(0x0A11), + 0 + }, + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } + }, + /* Port 7 */ + { + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID(0x0A12), + 0 + }, + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } + } + } +}; + +EFI_HANDLE mDriverImageHandle; + +PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = { + PCI_HOST_BRIDGE_SIGNATURE, // Signature + NULL, // HostBridgeHandle + 0, // RootBridgeNumber + {NULL, NULL}, // Head + FALSE, // ResourceSubiteed + TRUE, // CanRestarted + { + NotifyPhase, + GetNextRootBridge, + GetAttributes, + StartBusEnumeration, + SetBusNumbers, + SubmitResources, + GetProposedResources, + PreprocessController + } +}; + +/** + Entry point of this driver + + @param ImageHandle Handle of driver image + @param SystemTable Point to EFI_SYSTEM_TABLE + + @retval EFI_OUT_OF_RESOURCES Can not allocate memory resource + @retval EFI_DEVICE_ERROR Can not install the protocol instance + @retval EFI_SUCCESS Success to initialize the Pci host bridge. +**/ +EFI_STATUS +EFIAPI +InitializePciHostBridge ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINTN Loop1; + UINTN Loop2; + PCI_HOST_BRIDGE_INSTANCE *HostBridge = NULL; + PCI_ROOT_BRIDGE_INSTANCE *PrivateData; + UINT32 PcieRootBridgeMask; + + if (!OemIsMpBoot()) + { + PcieRootBridgeMask = PcdGet32(PcdPcieRootBridgeMask); + } + else + { + PcieRootBridgeMask = PcdGet32(PcdPcieRootBridgeMask2P); + } + + mDriverImageHandle = ImageHandle; + // + // Create Host Bridge Device Handle + // + //Each Host Bridge have 8 Root Bridges max, every bits of 0xFF(8 bit) stands for the according PCIe Port + //is enable or not + for (Loop1 = 0; Loop1 < PCIE_MAX_HOSTBRIDGE; Loop1++) { + if (((PcieRootBridgeMask >> (PCIE_MAX_ROOTBRIDGE * Loop1)) & 0xFF ) == 0) { + continue; + } + + + HostBridge = AllocateCopyPool (sizeof(PCI_HOST_BRIDGE_INSTANCE), &mPciHostBridgeInstanceTemplate); + if (HostBridge == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + HostBridge->RootBridgeNumber = RootBridgeNumber[Loop1]; + InitializeListHead (&HostBridge->Head); + + Status = gBS->InstallMultipleProtocolInterfaces ( + &HostBridge->HostBridgeHandle, + &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc, + NULL + ); + if (EFI_ERROR (Status)) { + FreePool (HostBridge); + return EFI_DEVICE_ERROR; + } + + // + // Create Root Bridge Device Handle in this Host Bridge + // + for (Loop2 = 0; Loop2 < HostBridge->RootBridgeNumber; Loop2++) { + if (!(((PcieRootBridgeMask >> (PCIE_MAX_ROOTBRIDGE * Loop1)) >> Loop2 ) & 0x01)) { + continue; + } + + PrivateData = AllocateZeroPool (sizeof(PCI_ROOT_BRIDGE_INSTANCE)); + if (PrivateData == NULL) { + FreePool (HostBridge); + return EFI_OUT_OF_RESOURCES; + } + PrivateData->Port = Loop2; + PrivateData->SocType = PcdGet32(Pcdsoctype); + PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE; + PrivateData->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[Loop1][Loop2]; + + (VOID)RootBridgeConstructor ( + &PrivateData->Io, + HostBridge->HostBridgeHandle, + RootBridgeAttribute[Loop1][Loop2], + &mResAppeture[Loop1][Loop2], + Loop1 + ); + + Status = gBS->InstallMultipleProtocolInterfaces( + &PrivateData->Handle, + &gEfiDevicePathProtocolGuid, PrivateData->DevicePath, + &gEfiPciRootBridgeIoProtocolGuid, &PrivateData->Io, + NULL + ); + if (EFI_ERROR (Status)) { + (VOID)gBS->UninstallMultipleProtocolInterfaces ( + HostBridge->HostBridgeHandle, + &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc, + NULL + ); + FreePool(PrivateData); + FreePool (HostBridge); + return EFI_DEVICE_ERROR; + } + // PCI Memory Space + Status = gDS->AddMemorySpace ( + EfiGcdMemoryTypeMemoryMappedIo, + mResAppeture[Loop1][Loop2] .MemBase, + mResAppeture[Loop1][Loop2] .MemLimit -mResAppeture[Loop1][Loop2] .MemBase + 1, + 0 + ); + if (EFI_ERROR (Status)) { + DEBUG((EFI_D_ERROR,"PCIE AddMemorySpace Error\n")); + } + InsertTailList (&HostBridge->Head, &PrivateData->Link); + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +NotifyAllocateMemResources( + IN PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance, + IN PCI_RESOURCE_TYPE Index, + IN OUT UINT64 *AllocatedLenMem +) +{ + EFI_PHYSICAL_ADDRESS BaseAddress; + EFI_STATUS ReturnStatus; + UINT64 AddrLen; + UINTN BitsOfAlignment; + + AddrLen = RootBridgeInstance->ResAllocNode[Index].Length; + PCIE_DEBUG("Addrlen:%llx\n", AddrLen); + // Get the number of '1' in Alignment. + BitsOfAlignment = (UINTN) (HighBitSet64 (RootBridgeInstance->ResAllocNode[Index].Alignment) + 1); + + BaseAddress = (RootBridgeInstance->MemBase + *AllocatedLenMem + + RootBridgeInstance->ResAllocNode[Index].Alignment) + & ~(RootBridgeInstance->ResAllocNode[Index].Alignment); + if ((BaseAddress + AddrLen - 1) > RootBridgeInstance->MemLimit) { + ReturnStatus = EFI_OUT_OF_RESOURCES; + RootBridgeInstance->ResAllocNode[Index].Length = 0; + return ReturnStatus; + } + + PCIE_DEBUG("(P)Mem32/64 request memory at:%llx\n", BaseAddress); + ReturnStatus = gDS->AllocateMemorySpace ( + EfiGcdAllocateAddress, + EfiGcdMemoryTypeMemoryMappedIo, + BitsOfAlignment, + AddrLen, + &BaseAddress, + mDriverImageHandle, + NULL + ); + + if (!EFI_ERROR (ReturnStatus)) { + // We were able to allocate the PCI memory + RootBridgeInstance->ResAllocNode[Index].Base = (UINTN)BaseAddress; + RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated; + *AllocatedLenMem += AddrLen; + PCIE_DEBUG("(P)Mem32/64 resource allocated:%llx\n", BaseAddress); + + } else { + // Not able to allocate enough PCI memory + if (ReturnStatus != EFI_OUT_OF_RESOURCES) { + RootBridgeInstance->ResAllocNode[Index].Length = 0; + } + } + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +NotifyAllocateResources( + IN PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance +) +{ + EFI_STATUS ReturnStatus; + LIST_ENTRY *List; + PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; + PCI_RESOURCE_TYPE Index; + + ReturnStatus = EFI_SUCCESS; + List = HostBridgeInstance->Head.ForwardLink; + + while (List != &HostBridgeInstance->Head) { + RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); + + UINT64 AllocatedLenMem = 0; + for (Index = TypeIo; Index < TypeBus; Index++) { + if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) { + if(Index == TypeIo) { + PCIE_DEBUG("NOT SUPPOER IO RESOURCES ON THIS PLATFORM\n"); + } else if ((Index >= TypeMem32) && (Index <= TypePMem64)) { + ReturnStatus = NotifyAllocateMemResources(RootBridgeInstance,Index,&AllocatedLenMem); + } else { + ASSERT (FALSE); + } + } + } + + List = List->ForwardLink; + } + + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +NotifyFreeResources( + IN PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance +) +{ + EFI_STATUS ReturnStatus; + LIST_ENTRY *List; + PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; + PCI_RESOURCE_TYPE Index; + UINT64 AddrLen; + EFI_PHYSICAL_ADDRESS BaseAddress; + + ReturnStatus = EFI_SUCCESS; + List = HostBridgeInstance->Head.ForwardLink; + while (List != &HostBridgeInstance->Head) { + RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); + for (Index = TypeIo; Index < TypeBus; Index++) { + if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) { + AddrLen = RootBridgeInstance->ResAllocNode[Index].Length; + BaseAddress = RootBridgeInstance->ResAllocNode[Index].Base; + + if(Index <= TypePMem64){ + ReturnStatus = gDS->FreeMemorySpace (BaseAddress, AddrLen); + }else{ + ASSERT (FALSE); + } + + RootBridgeInstance->ResAllocNode[Index].Type = Index; + RootBridgeInstance->ResAllocNode[Index].Base = 0; + RootBridgeInstance->ResAllocNode[Index].Length = 0; + RootBridgeInstance->ResAllocNode[Index].Status = ResNone; + } + } + + List = List->ForwardLink; + } + + HostBridgeInstance->ResourceSubmited = FALSE; + HostBridgeInstance->CanRestarted = TRUE; + return ReturnStatus; + +} + +VOID +EFIAPI +NotifyBeginEnumeration( + IN PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance +) +{ + LIST_ENTRY *List; + PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; + PCI_RESOURCE_TYPE Index; + + // + // Reset the Each Root Bridge + // + List = HostBridgeInstance->Head.ForwardLink; + + while (List != &HostBridgeInstance->Head) { + RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); + for (Index = TypeIo; Index < TypeMax; Index++) { + RootBridgeInstance->ResAllocNode[Index].Type = Index; + RootBridgeInstance->ResAllocNode[Index].Base = 0; + RootBridgeInstance->ResAllocNode[Index].Length = 0; + RootBridgeInstance->ResAllocNode[Index].Status = ResNone; + } + + List = List->ForwardLink; + } + + HostBridgeInstance->ResourceSubmited = FALSE; + HostBridgeInstance->CanRestarted = TRUE; +} + +/** + These are the notifications from the PCI bus driver that it is about to enter a certain + phase of the PCI enumeration process. + + This member function can be used to notify the host bridge driver to perform specific actions, + including any chipset-specific initialization, so that the chipset is ready to enter the next phase. + Eight notification points are defined at this time. See belows: + EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data + structures. The PCI enumerator should issue this notification + before starting a fresh enumeration process. Enumeration cannot + be restarted after sending any other notification such as + EfiPciHostBridgeBeginBusAllocation. + EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is + required here. This notification can be used to perform any + chipset-specific programming. + EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No + specific action is required here. This notification can be used to + perform any chipset-specific programming. + EfiPciHostBridgeBeginResourceAllocation + The resource allocation phase is about to begin. No specific + action is required here. This notification can be used to perform + any chipset-specific programming. + EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI + root bridges. These resource settings are returned on the next call to + GetProposedResources(). Before calling NotifyPhase() with a Phase of + EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible + for gathering I/O and memory requests for + all the PCI root bridges and submitting these requests using + SubmitResources(). This function pads the resource amount + to suit the root bridge hardware, takes care of dependencies between + the PCI root bridges, and calls the Global Coherency Domain (GCD) + with the allocation request. In the case of padding, the allocated range + could be bigger than what was requested. + EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated + resources (proposed resources) for all the PCI root bridges. After the + hardware is programmed, reassigning resources will not be supported. + The bus settings are not affected. + EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI + root bridges and resets the I/O and memory apertures to their initial + state. The bus settings are not affected. If the request to allocate + resources fails, the PCI enumerator can use this notification to + deallocate previous resources, adjust the requests, and retry + allocation. + EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is + required here. This notification can be used to perform any chipsetspecific + programming. + + @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL + @param[in] Phase The phase during enumeration + + @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error + is valid for a Phase of EfiPciHostBridgeAllocateResources if + SubmitResources() has not been called for one or more + PCI root bridges before this call + @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid + for a Phase of EfiPciHostBridgeSetResources. + @retval EFI_INVALID_PARAMETER Invalid phase parameter + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the + previously submitted resource requests cannot be fulfilled or + were only partially fulfilled. + @retval EFI_SUCCESS The notification was accepted without any errors. + +**/ +EFI_STATUS +EFIAPI +NotifyPhase( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase + ) +{ + PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; + EFI_STATUS ReturnStatus; + + HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); + ReturnStatus = EFI_SUCCESS; + + switch (Phase) { + + case EfiPciHostBridgeBeginEnumeration: + PCIE_DEBUG("Case EfiPciHostBridgeBeginEnumeration\n"); + if (HostBridgeInstance->CanRestarted) { + NotifyBeginEnumeration(HostBridgeInstance); + } else { + // + // Can not restart + // + return EFI_NOT_READY; + } + break; + + case EfiPciHostBridgeEndEnumeration: + PCIE_DEBUG("Case EfiPciHostBridgeEndEnumeration\n"); + break; + + case EfiPciHostBridgeBeginBusAllocation: + PCIE_DEBUG("Case EfiPciHostBridgeBeginBusAllocation\n"); + // + // No specific action is required here, can perform any chipset specific programing + // + + HostBridgeInstance->CanRestarted = FALSE; + break; + + case EfiPciHostBridgeEndBusAllocation: + PCIE_DEBUG("Case EfiPciHostBridgeEndBusAllocation\n"); + // + // No specific action is required here, can perform any chipset specific programing + // + break; + + case EfiPciHostBridgeBeginResourceAllocation: + PCIE_DEBUG("Case EfiPciHostBridgeBeginResourceAllocation\n"); + // + // No specific action is required here, can perform any chipset specific programing + // + break; + + case EfiPciHostBridgeAllocateResources: + PCIE_DEBUG("Case EfiPciHostBridgeAllocateResources\n"); + + if (HostBridgeInstance->ResourceSubmited) { + // + // Take care of the resource dependencies between the root bridges + // + ReturnStatus = NotifyAllocateResources(HostBridgeInstance); + } else { + return EFI_NOT_READY; + } + //break; + + case EfiPciHostBridgeSetResources: + PCIE_DEBUG("Case EfiPciHostBridgeSetResources\n"); + break; + + case EfiPciHostBridgeFreeResources: + PCIE_DEBUG("Case EfiPciHostBridgeFreeResources\n"); + + ReturnStatus = NotifyFreeResources(HostBridgeInstance); + break; + + case EfiPciHostBridgeEndResourceAllocation: + PCIE_DEBUG("Case EfiPciHostBridgeEndResourceAllocation\n"); + HostBridgeInstance->CanRestarted = FALSE; + break; + + default: + return EFI_INVALID_PARAMETER; + } + + return ReturnStatus; +} + +/** + Return the device handle of the next PCI root bridge that is associated with this Host Bridge. + + This function is called multiple times to retrieve the device handles of all the PCI root bridges that + are associated with this PCI host bridge. Each PCI host bridge is associated with one or more PCI + root bridges. On each call, the handle that was returned by the previous call is passed into the + interface, and on output the interface returns the device handle of the next PCI root bridge. The + caller can use the handle to obtain the instance of the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL + for that root bridge. When there are no more PCI root bridges to report, the interface returns + EFI_NOT_FOUND. A PCI enumerator must enumerate the PCI root bridges in the order that they + are returned by this function. + For D945 implementation, there is only one root bridge in PCI host bridge. + + @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL + @param[in, out] RootBridgeHandle Returns the device handle of the next PCI root bridge. + + @retval EFI_SUCCESS If parameter RootBridgeHandle = NULL, then return the first Rootbridge handle of the + specific Host bridge and return EFI_SUCCESS. + @retval EFI_NOT_FOUND Can not find the any more root bridge in specific host bridge. + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not an EFI_HANDLE that was + returned on a previous call to GetNextRootBridge(). +**/ +EFI_STATUS +EFIAPI +GetNextRootBridge( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN OUT EFI_HANDLE *RootBridgeHandle + ) +{ + BOOLEAN NoRootBridge; + LIST_ENTRY *List; + PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; + PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; + + NoRootBridge = TRUE; + HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); + List = HostBridgeInstance->Head.ForwardLink; + + + while (List != &HostBridgeInstance->Head) { + NoRootBridge = FALSE; + RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); + if (*RootBridgeHandle == NULL) { + // + // Return the first Root Bridge Handle of the Host Bridge + // + *RootBridgeHandle = RootBridgeInstance->Handle; + return EFI_SUCCESS; + } else { + if (*RootBridgeHandle == RootBridgeInstance->Handle) { + // + // Get next if have + // + List = List->ForwardLink; + if (List!=&HostBridgeInstance->Head) { + RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); + *RootBridgeHandle = RootBridgeInstance->Handle; + return EFI_SUCCESS; + } else { + return EFI_NOT_FOUND; + } + } + } + + List = List->ForwardLink; + } //end while + + if (NoRootBridge) { + return EFI_NOT_FOUND; + } else { + return EFI_INVALID_PARAMETER; + } +} + +/** + Returns the allocation attributes of a PCI root bridge. + + The function returns the allocation attributes of a specific PCI root bridge. The attributes can vary + from one PCI root bridge to another. These attributes are different from the decode-related + attributes that are returned by the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The + RootBridgeHandle parameter is used to specify the instance of the PCI root bridge. The device + handles of all the root bridges that are associated with this host bridge must be obtained by calling + GetNextRootBridge(). The attributes are static in the sense that they do not change during or + after the enumeration process. The hardware may provide mechanisms to change the attributes on + the fly, but such changes must be completed before EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is + installed. The permitted values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in + "Related Definitions" below. The caller uses these attributes to combine multiple resource requests. + For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI bus enumerator needs to + include requests for the prefetchable memory in the nonprefetchable memory pool and not request any + prefetchable memory. + Attribute Description + ------------------------------------ ---------------------------------------------------------------------- + EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM If this bit is set, then the PCI root bridge does not support separate + windows for nonprefetchable and prefetchable memory. A PCI bus + driver needs to include requests for prefetchable memory in the + nonprefetchable memory pool. + + EFI_PCI_HOST_BRIDGE_MEM64_DECODE If this bit is set, then the PCI root bridge supports 64-bit memory + windows. If this bit is not set, the PCI bus driver needs to include + requests for a 64-bit memory address in the corresponding 32-bit + memory pool. + + @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL + @param[in] RootBridgeHandle The device handle of the PCI root bridge in which the caller is interested. Type + EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification. + @param[out] Attributes The pointer to attribte of root bridge, it is output parameter + + @retval EFI_INVALID_PARAMETER Attribute pointer is NULL + @retval EFI_INVALID_PARAMETER RootBridgehandle is invalid. + @retval EFI_SUCCESS Success to get attribute of interested root bridge. + +**/ +EFI_STATUS +EFIAPI +GetAttributes( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + OUT UINT64 *Attributes + ) +{ + LIST_ENTRY *List; + PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; + PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; + + if (Attributes == NULL) { + return EFI_INVALID_PARAMETER; + } + + HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); + List = HostBridgeInstance->Head.ForwardLink; + + while (List != &HostBridgeInstance->Head) { + RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); + if (RootBridgeHandle == RootBridgeInstance->Handle) { + *Attributes = RootBridgeInstance->RootBridgeAttrib; + return EFI_SUCCESS; + } + + List = List->ForwardLink; + } + + // + // RootBridgeHandle is not an EFI_HANDLE + // that was returned on a previous call to GetNextRootBridge() + // + return EFI_INVALID_PARAMETER; +} + +/** + Sets up the specified PCI root bridge for the bus enumeration process. + + This member function sets up the root bridge for bus enumeration and returns the PCI bus range + over which the search should be performed in ACPI 2.0 resource descriptor format. + + @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance. + @param[in] RootBridgeHandle The PCI Root Bridge to be set up. + @param[out] Configuration Pointer to the pointer to the PCI bus resource descriptor. + + @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle + @retval EFI_OUT_OF_RESOURCES Fail to allocate ACPI resource descriptor tag. + @retval EFI_SUCCESS Sucess to allocate ACPI resource descriptor. + +**/ +EFI_STATUS +EFIAPI +StartBusEnumeration( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + OUT VOID **Configuration + ) +{ + LIST_ENTRY *List; + PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; + PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; + VOID *Buffer; + UINT8 *Temp; + UINT64 BusStart; + UINT64 BusEnd; + + HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); + List = HostBridgeInstance->Head.ForwardLink; + + while (List != &HostBridgeInstance->Head) { + RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); + if (RootBridgeHandle == RootBridgeInstance->Handle) { + // + // Set up the Root Bridge for Bus Enumeration + // + BusStart = RootBridgeInstance->BusBase; + BusEnd = RootBridgeInstance->BusLimit; + // + // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR + // + + Buffer = AllocatePool (sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof(EFI_ACPI_END_TAG_DESCRIPTOR)); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Temp = (UINT8 *)Buffer; + + ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Desc = 0x8A; + ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Len = 0x2B; + ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->ResType = 2; + ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->GenFlag = 0; + ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->SpecificFlag = 0; + ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrSpaceGranularity = 0; + ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMin = BusStart; + ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMax = 0; + ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrTranslationOffset = 0; + ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrLen = BusEnd - BusStart + 1; + + Temp = Temp + sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); + ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79; + ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0; + + *Configuration = Buffer; + return EFI_SUCCESS; + } + List = List->ForwardLink; + } + + return EFI_INVALID_PARAMETER; +} + +/** + Programs the PCI root bridge hardware so that it decodes the specified PCI bus range. + + This member function programs the specified PCI root bridge to decode the bus range that is + specified by the input parameter Configuration. + The bus range information is specified in terms of the ACPI 2.0 resource descriptor format. + + @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance + @param[in] RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed + @param[in] Configuration The pointer to the PCI bus resource descriptor + + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor. + @retval EFI_INVALID_PARAMETER Configuration does not include a valid ACPI 2.0 bus resource descriptor. + @retval EFI_INVALID_PARAMETER Configuration includes valid ACPI 2.0 resource descriptors other than + bus descriptors. + @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid ACPI resource descriptors. + @retval EFI_INVALID_PARAMETER "Address Range Minimum" is invalid for this root bridge. + @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this root bridge. + @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. + @retval EFI_SUCCESS The bus range for the PCI root bridge was programmed. + +**/ +EFI_STATUS +EFIAPI +SetBusNumbers( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + IN VOID *Configuration + ) +{ + LIST_ENTRY *List; + PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; + PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; + UINT8 *Ptr; + UINTN BusStart; + UINTN BusEnd; + UINTN BusLen; + + if (Configuration == NULL) { + return EFI_INVALID_PARAMETER; + } + + Ptr = Configuration; + + // + // Check the Configuration is valid + // + if(*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) { + return EFI_INVALID_PARAMETER; + } + + if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != 2) { + return EFI_INVALID_PARAMETER; + } + + Ptr += sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); + if (*Ptr != ACPI_END_TAG_DESCRIPTOR) { + return EFI_INVALID_PARAMETER; + } + + HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); + List = HostBridgeInstance->Head.ForwardLink; + + Ptr = Configuration; + + while (List != &HostBridgeInstance->Head) { + RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); + if (RootBridgeHandle == RootBridgeInstance->Handle) { + BusStart = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin; + BusLen = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen; + BusEnd = BusStart + BusLen - 1; + + if (BusStart > BusEnd) { + return EFI_INVALID_PARAMETER; + } + + if ((BusStart < RootBridgeInstance->BusBase) || (BusEnd > RootBridgeInstance->BusLimit)) { + return EFI_INVALID_PARAMETER; + } + + // + // Update the Bus Range + // + RootBridgeInstance->ResAllocNode[TypeBus].Base = BusStart; + RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen; + RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated; + + // + // Program the Root Bridge Hardware + // + + return EFI_SUCCESS; + } + + List = List->ForwardLink; + } + + return EFI_INVALID_PARAMETER; +} + +VOID +EFIAPI +SubmitGetResourceType( + IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr, + OUT UINT64* Index +) +{ + switch (Ptr->ResType) { + case 0: + if (Ptr->AddrSpaceGranularity == 32) { + if (Ptr->SpecificFlag == 0x06) + *Index = TypePMem32; + else + *Index = TypeMem32; + } + + if (Ptr->AddrSpaceGranularity == 64) { + if (Ptr->SpecificFlag == 0x06) + *Index = TypePMem64; + else + *Index = TypeMem64; + } + break; + + case 1: + *Index = TypeIo; + break; + + default: + break; + }; + +} + +/** + Submits the I/O and memory resource requirements for the specified PCI root bridge. + + This function is used to submit all the I/O and memory resources that are required by the specified + PCI root bridge. The input parameter Configuration is used to specify the following: + - The various types of resources that are required + - The associated lengths in terms of ACPI 2.0 resource descriptor format + + @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance. + @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory resource requirements are being submitted. + @param[in] Configuration The pointer to the PCI I/O and PCI memory resource descriptor. + + @retval EFI_SUCCESS The I/O and memory resource requests for a PCI root bridge were accepted. + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor. + @retval EFI_INVALID_PARAMETER Configuration includes requests for one or more resource types that are + not supported by this PCI root bridge. This error will happen if the caller + did not combine resources according to Attributes that were returned by + GetAllocAttributes(). + @retval EFI_INVALID_PARAMETER Address Range Maximum" is invalid. + @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI root bridge. + @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for this PCI root bridge. + +**/ +EFI_STATUS +EFIAPI +SubmitResources( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + IN VOID *Configuration + ) +{ + LIST_ENTRY *List; + PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; + PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; + UINT8 *Temp; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr; + UINT64 AddrLen; + UINT64 Alignment; + UINTN Index; + + PCIE_DEBUG("In SubmitResources\n"); + // + // Check the input parameter: Configuration + // + if (Configuration == NULL) + return EFI_INVALID_PARAMETER; + + HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); + List = HostBridgeInstance->Head.ForwardLink; + + Temp = (UINT8 *)Configuration; + while ( *Temp == 0x8A) + Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ; + + if (*Temp != 0x79) + return EFI_INVALID_PARAMETER; + + Temp = (UINT8 *)Configuration; + while (List != &HostBridgeInstance->Head) { + RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); + if (RootBridgeHandle == RootBridgeInstance->Handle) { + while ( *Temp == 0x8A) { + Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ; + PCIE_DEBUG("Ptr->ResType:%d\n", Ptr->ResType); + PCIE_DEBUG("Ptr->Addrlen:%llx\n", Ptr->AddrLen); + PCIE_DEBUG("Ptr->AddrRangeMax:%llx\n", Ptr->AddrRangeMax); + PCIE_DEBUG("Ptr->AddrRangeMin:%llx\n", Ptr->AddrRangeMin); + PCIE_DEBUG("Ptr->SpecificFlag:%llx\n", Ptr->SpecificFlag); + PCIE_DEBUG("Ptr->AddrSpaceGranularity:%d\n", Ptr->AddrSpaceGranularity); + PCIE_DEBUG("RootBridgeInstance->RootBridgeAttrib:%llx\n", RootBridgeInstance->RootBridgeAttrib); + // + // Check address range alignment + // + if (Ptr->AddrRangeMax != (GetPowerOfTwo64 (Ptr->AddrRangeMax + 1) - 1)) { + return EFI_INVALID_PARAMETER; + } + Index = 0; + SubmitGetResourceType(Ptr,&Index); + AddrLen = (UINTN) Ptr->AddrLen; + Alignment = (UINTN) Ptr->AddrRangeMax; + RootBridgeInstance->ResAllocNode[Index].Length = AddrLen; + RootBridgeInstance->ResAllocNode[Index].Alignment = Alignment; + RootBridgeInstance->ResAllocNode[Index].Status = ResRequested; + HostBridgeInstance->ResourceSubmited = TRUE; + + Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ; + } + + return EFI_SUCCESS; + } + + List = List->ForwardLink; + } + return EFI_INVALID_PARAMETER; +} + +/** + Returns the proposed resource settings for the specified PCI root bridge. + + This member function returns the proposed resource settings for the specified PCI root bridge. The + proposed resource settings are prepared when NotifyPhase() is called with a Phase of + EfiPciHostBridgeAllocateResources. The output parameter Configuration + specifies the following: + - The various types of resources, excluding bus resources, that are allocated + - The associated lengths in terms of ACPI 2.0 resource descriptor format + + @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance. + @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification. + @param[out] Configuration The pointer to the pointer to the PCI I/O and memory resource descriptor. + + @retval EFI_SUCCESS The requested parameters were returned. + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. + @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +SetResource( + PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance, + VOID *Buffer + +) +{ + UINTN Index; + UINT8 *Temp; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr; + UINT64 ResStatus; + + Temp = Buffer; + + for (Index = 0; Index < TypeBus; Index ++) + { + if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) { + Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ; + ResStatus = RootBridgeInstance->ResAllocNode[Index].Status; + + switch (Index) { + + case TypeIo: + // + // Io + // + Ptr->Desc = 0x8A; + Ptr->Len = 0x2B; + Ptr->ResType = 1; + Ptr->GenFlag = 0; + Ptr->SpecificFlag = 0; + /* This is PCIE Device Bus which start address is the low 32bit of mem base*/ + Ptr->AddrRangeMin = (RootBridgeInstance->ResAllocNode[Index].Base - RootBridgeInstance->MemBase) + + (RootBridgeInstance->MemBase & 0xFFFFFFFF); + Ptr->AddrRangeMax = 0; + Ptr->AddrTranslationOffset = \ + (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS; + Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length; + break; + + case TypeMem32: + // + // Memory 32 + // + Ptr->Desc = 0x8A; + Ptr->Len = 0x2B; + Ptr->ResType = 0; + Ptr->GenFlag = 0; + Ptr->SpecificFlag = 0; + Ptr->AddrSpaceGranularity = 32; + /* This is PCIE Device Bus which start address is the low 32bit of mem base*/ + Ptr->AddrRangeMin = (RootBridgeInstance->ResAllocNode[Index].Base - RootBridgeInstance->MemBase) + + (RootBridgeInstance->MemBase & 0xFFFFFFFF); + Ptr->AddrRangeMax = 0; + Ptr->AddrTranslationOffset = \ + (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS; + Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length; + break; + + case TypePMem32: + // + // Prefetch memory 32 + // + Ptr->Desc = 0x8A; + Ptr->Len = 0x2B; + Ptr->ResType = 0; + Ptr->GenFlag = 0; + Ptr->SpecificFlag = 6; + Ptr->AddrSpaceGranularity = 32; + /* This is PCIE Device Bus which start address is the low 32bit of mem base*/ + Ptr->AddrRangeMin = (RootBridgeInstance->ResAllocNode[Index].Base - RootBridgeInstance->MemBase) + + (RootBridgeInstance->MemBase & 0xFFFFFFFF); + Ptr->AddrRangeMax = 0; + Ptr->AddrTranslationOffset = \ + (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS; + Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length; + break; + + case TypeMem64: + // + // Memory 64 + // + Ptr->Desc = 0x8A; + Ptr->Len = 0x2B; + Ptr->ResType = 0; + Ptr->GenFlag = 0; + Ptr->SpecificFlag = 0; + Ptr->AddrSpaceGranularity = 64; + /* This is PCIE Device Bus which start address is the low 32bit of mem base*/ + Ptr->AddrRangeMin = (RootBridgeInstance->ResAllocNode[Index].Base - RootBridgeInstance->MemBase) + + (RootBridgeInstance->MemBase & 0xFFFFFFFFFFFFFFFF); + Ptr->AddrRangeMax = 0; + Ptr->AddrTranslationOffset = \ + (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS; + Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length; + break; + + case TypePMem64: + // + // Prefetch memory 64 + // + Ptr->Desc = 0x8A; + Ptr->Len = 0x2B; + Ptr->ResType = 0; + Ptr->GenFlag = 0; + Ptr->SpecificFlag = 6; + Ptr->AddrSpaceGranularity = 64; + /* This is PCIE Device Bus which start address is the low 32bit of mem base*/ + Ptr->AddrRangeMin = (RootBridgeInstance->ResAllocNode[Index].Base - RootBridgeInstance->MemBase) + + (RootBridgeInstance->MemBase & 0xFFFFFFFFFFFFFFFF); + Ptr->AddrRangeMax = 0; + Ptr->AddrTranslationOffset = \ + (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS; + Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length; + break; + }; + PCIE_DEBUG("Ptr->ResType:%d\n", Ptr->ResType); + PCIE_DEBUG("Ptr->Addrlen:%llx\n", Ptr->AddrLen); + PCIE_DEBUG("Ptr->AddrRangeMax:%llx\n", Ptr->AddrRangeMax); + PCIE_DEBUG("Ptr->AddrRangeMin:%llx\n", Ptr->AddrRangeMin); + PCIE_DEBUG("Ptr->SpecificFlag:%llx\n", Ptr->SpecificFlag); + PCIE_DEBUG("Ptr->AddrTranslationOffset:%d\n", Ptr->AddrTranslationOffset); + PCIE_DEBUG("Ptr->AddrSpaceGranularity:%d\n", Ptr->AddrSpaceGranularity); + + Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); + } + } + ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79; + ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0; + + return EFI_SUCCESS; +} +/** + Returns the proposed resource settings for the specified PCI root bridge. + + This member function returns the proposed resource settings for the specified PCI root bridge. The + proposed resource settings are prepared when NotifyPhase() is called with a Phase of + EfiPciHostBridgeAllocateResources. The output parameter Configuration + specifies the following: + - The various types of resources, excluding bus resources, that are allocated + - The associated lengths in terms of ACPI 2.0 resource descriptor format + + @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance. + @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification. + @param[out] Configuration The pointer to the pointer to the PCI I/O and memory resource descriptor. + + @retval EFI_SUCCESS The requested parameters were returned. + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. + @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +GetProposedResources( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + OUT VOID **Configuration + ) +{ + LIST_ENTRY *List; + PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; + PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; + UINTN Index; + UINTN Number; + VOID *Buffer; + + Buffer = NULL; + Number = 0; + + PCIE_DEBUG("In GetProposedResources\n"); + // + // Get the Host Bridge Instance from the resource allocation protocol + // + HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); + List = HostBridgeInstance->Head.ForwardLink; + + // + // Enumerate the root bridges in this host bridge + // + while (List != &HostBridgeInstance->Head) { + RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); + if (RootBridgeHandle == RootBridgeInstance->Handle) { + for (Index = 0; Index < TypeBus; Index ++) { + if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) { + Number ++; + } + } + + Buffer = AllocateZeroPool (Number * sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof(EFI_ACPI_END_TAG_DESCRIPTOR)); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + (VOID)SetResource(RootBridgeInstance,Buffer); + + *Configuration = Buffer; + + return EFI_SUCCESS; + } + + List = List->ForwardLink; + } + + return EFI_INVALID_PARAMETER; +} + +/** + Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various + stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual + PCI controllers before enumeration. + + This function is called during the PCI enumeration process. No specific action is expected from this + member function. It allows the host bridge driver to preinitialize individual PCI controllers before + enumeration. + + @param This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance. + @param RootBridgeHandle The associated PCI root bridge handle. Type EFI_HANDLE is defined in + InstallProtocolInterface() in the UEFI 2.0 Specification. + @param PciAddress The address of the PCI device on the PCI bus. This address can be passed to the + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to access the PCI + configuration space of the device. See Table 12-1 in the UEFI 2.0 Specification for + the definition of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS. + @param Phase The phase of the PCI device enumeration. + + @retval EFI_SUCCESS The requested parameters were returned. + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. + @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in + EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE. + @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should + not enumerate this device, including its child devices if it is a PCI-to-PCI + bridge. + +**/ +EFI_STATUS +EFIAPI +PreprocessController ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress, + IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase + ) +{ + PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; + PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; + LIST_ENTRY *List; + + HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); + List = HostBridgeInstance->Head.ForwardLink; + + // + // Enumerate the root bridges in this host bridge + // + while (List != &HostBridgeInstance->Head) { + RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); + if (RootBridgeHandle == RootBridgeInstance->Handle) { + break; + } + List = List->ForwardLink; + } + if (List == &HostBridgeInstance->Head) { + return EFI_INVALID_PARAMETER; + } + + if ((UINT32)Phase > EfiPciBeforeResourceCollection) { + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} diff --git a/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridge.h b/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridge.h new file mode 100644 index 0000000000..cddda6b642 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridge.h @@ -0,0 +1,521 @@ +/** + * Copyright (c) 2014, AppliedMicro Corp. All rights reserved. + * Copyright (c) 2016, Hisilicon Limited. All rights reserved. + * Copyright (c) 2016, Linaro Limited. 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. + * + **/ + +#ifndef _PCI_HOST_BRIDGE_H_ +#define _PCI_HOST_BRIDGE_H_ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Enable below statments to enable PCIE debug +//#define PCIE_DEBUG_ENABLE +//#define PCIE_VDEBUG_ENABLE +//#define PCIE_CDEBUG_ENABLE + +#ifdef PCIE_CDEBUG_ENABLE +# define PCIE_CSR_DEBUG(arg...) DEBUG((EFI_D_VERBOSE,## arg)) +#else +# define PCIE_CSR_DEBUG(arg...) +#endif + +#ifdef PCIE_VDEBUG_ENABLE +# define PCIE_VDEBUG(arg...) DEBUG((EFI_D_VERBOSE,## arg)) +#else +# define PCIE_VDEBUG(arg...) +#endif + +#ifdef PCIE_DEBUG_ENABLE +# define PCIE_DEBUG(arg...) DEBUG((EFI_D_VERBOSE,## arg)) +#else +# define PCIE_DEBUG(arg...) +#endif +#define PCIE_WARN(arg...) DEBUG((EFI_D_WARN,## arg)) +#define PCIE_ERR(arg...) DEBUG((EFI_D_ERROR,## arg)) +#define PCIE_INFO(arg...) DEBUG((EFI_D_INFO,## arg)) + +#define MAX_PCI_DEVICE_NUMBER 31 +#define MAX_PCI_FUNCTION_NUMBER 7 +#define MAX_PCI_REG_ADDRESS 0xFFFF + +typedef enum { + IoOperation, + MemOperation, + PciOperation +} OPERATION_TYPE; + +#define PCI_HOST_BRIDGE_SIGNATURE SIGNATURE_32('e', 'h', 's', 't') +typedef struct { + UINTN Signature; + EFI_HANDLE HostBridgeHandle; + UINTN RootBridgeNumber; + LIST_ENTRY Head; + BOOLEAN ResourceSubmited; + BOOLEAN CanRestarted; + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL ResAlloc; +} PCI_HOST_BRIDGE_INSTANCE; + +#define INSTANCE_FROM_RESOURCE_ALLOCATION_THIS(a) \ + CR(a, PCI_HOST_BRIDGE_INSTANCE, ResAlloc, PCI_HOST_BRIDGE_SIGNATURE) + +// +// HostBridge Resource Allocation interface +// + +/** + These are the notifications from the PCI bus driver that it is about to enter a certain + phase of the PCI enumeration process. + + This member function can be used to notify the host bridge driver to perform specific actions, + including any chipset-specific initialization, so that the chipset is ready to enter the next phase. + Eight notification points are defined at this time. See belows: + EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data + structures. The PCI enumerator should issue this notification + before starting a fresh enumeration process. Enumeration cannot + be restarted after sending any other notification such as + EfiPciHostBridgeBeginBusAllocation. + EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is + required here. This notification can be used to perform any + chipset-specific programming. + EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No + specific action is required here. This notification can be used to + perform any chipset-specific programming. + EfiPciHostBridgeBeginResourceAllocation + The resource allocation phase is about to begin. No specific + action is required here. This notification can be used to perform + any chipset-specific programming. + EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI + root bridges. These resource settings are returned on the next call to + GetProposedResources(). Before calling NotifyPhase() with a Phase of + EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible + for gathering I/O and memory requests for + all the PCI root bridges and submitting these requests using + SubmitResources(). This function pads the resource amount + to suit the root bridge hardware, takes care of dependencies between + the PCI root bridges, and calls the Global Coherency Domain (GCD) + with the allocation request. In the case of padding, the allocated range + could be bigger than what was requested. + EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated + resources (proposed resources) for all the PCI root bridges. After the + hardware is programmed, reassigning resources will not be supported. + The bus settings are not affected. + EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI + root bridges and resets the I/O and memory apertures to their initial + state. The bus settings are not affected. If the request to allocate + resources fails, the PCI enumerator can use this notification to + deallocate previous resources, adjust the requests, and retry + allocation. + EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is + required here. This notification can be used to perform any chipsetspecific + programming. + + @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL + @param[in] Phase The phase during enumeration + + @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error + is valid for a Phase of EfiPciHostBridgeAllocateResources if + SubmitResources() has not been called for one or more + PCI root bridges before this call + @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid + for a Phase of EfiPciHostBridgeSetResources. + @retval EFI_INVALID_PARAMETER Invalid phase parameter + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the + previously submitted resource requests cannot be fulfilled or + were only partially fulfilled. + @retval EFI_SUCCESS The notification was accepted without any errors. + +**/ +EFI_STATUS +EFIAPI +NotifyPhase( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase + ); + +/** + Return the device handle of the next PCI root bridge that is associated with this Host Bridge. + + This function is called multiple times to retrieve the device handles of all the PCI root bridges that + are associated with this PCI host bridge. Each PCI host bridge is associated with one or more PCI + root bridges. On each call, the handle that was returned by the previous call is passed into the + interface, and on output the interface returns the device handle of the next PCI root bridge. The + caller can use the handle to obtain the instance of the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL + for that root bridge. When there are no more PCI root bridges to report, the interface returns + EFI_NOT_FOUND. A PCI enumerator must enumerate the PCI root bridges in the order that they + are returned by this function. + For D945 implementation, there is only one root bridge in PCI host bridge. + + @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL + @param[in, out] RootBridgeHandle Returns the device handle of the next PCI root bridge. + + @retval EFI_SUCCESS If parameter RootBridgeHandle = NULL, then return the first Rootbridge handle of the + specific Host bridge and return EFI_SUCCESS. + @retval EFI_NOT_FOUND Can not find the any more root bridge in specific host bridge. + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not an EFI_HANDLE that was + returned on a previous call to GetNextRootBridge(). +**/ +EFI_STATUS +EFIAPI +GetNextRootBridge( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN OUT EFI_HANDLE *RootBridgeHandle + ); + +/** + Returns the allocation attributes of a PCI root bridge. + + The function returns the allocation attributes of a specific PCI root bridge. The attributes can vary + from one PCI root bridge to another. These attributes are different from the decode-related + attributes that are returned by the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The + RootBridgeHandle parameter is used to specify the instance of the PCI root bridge. The device + handles of all the root bridges that are associated with this host bridge must be obtained by calling + GetNextRootBridge(). The attributes are static in the sense that they do not change during or + after the enumeration process. The hardware may provide mechanisms to change the attributes on + the fly, but such changes must be completed before EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is + installed. The permitted values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in + "Related Definitions" below. The caller uses these attributes to combine multiple resource requests. + For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI bus enumerator needs to + include requests for the prefetchable memory in the nonprefetchable memory pool and not request any + prefetchable memory. + Attribute Description + ------------------------------------ ---------------------------------------------------------------------- + EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM If this bit is set, then the PCI root bridge does not support separate + windows for nonprefetchable and prefetchable memory. A PCI bus + driver needs to include requests for prefetchable memory in the + nonprefetchable memory pool. + + EFI_PCI_HOST_BRIDGE_MEM64_DECODE If this bit is set, then the PCI root bridge supports 64-bit memory + windows. If this bit is not set, the PCI bus driver needs to include + requests for a 64-bit memory address in the corresponding 32-bit + memory pool. + + @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL + @param[in] RootBridgeHandle The device handle of the PCI root bridge in which the caller is interested. Type + EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification. + @param[out] Attributes The pointer to attribte of root bridge, it is output parameter + + @retval EFI_INVALID_PARAMETER Attribute pointer is NULL + @retval EFI_INVALID_PARAMETER RootBridgehandle is invalid. + @retval EFI_SUCCESS Success to get attribute of interested root bridge. + +**/ +EFI_STATUS +EFIAPI +GetAttributes( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + OUT UINT64 *Attributes + ); + +/** + Sets up the specified PCI root bridge for the bus enumeration process. + + This member function sets up the root bridge for bus enumeration and returns the PCI bus range + over which the search should be performed in ACPI 2.0 resource descriptor format. + + @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance. + @param[in] RootBridgeHandle The PCI Root Bridge to be set up. + @param[out] Configuration Pointer to the pointer to the PCI bus resource descriptor. + + @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle + @retval EFI_OUT_OF_RESOURCES Fail to allocate ACPI resource descriptor tag. + @retval EFI_SUCCESS Sucess to allocate ACPI resource descriptor. + +**/ +EFI_STATUS +EFIAPI +StartBusEnumeration( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + OUT VOID **Configuration + ); + +/** + Programs the PCI root bridge hardware so that it decodes the specified PCI bus range. + + This member function programs the specified PCI root bridge to decode the bus range that is + specified by the input parameter Configuration. + The bus range information is specified in terms of the ACPI 2.0 resource descriptor format. + + @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance + @param[in] RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed + @param[in] Configuration The pointer to the PCI bus resource descriptor + + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor. + @retval EFI_INVALID_PARAMETER Configuration does not include a valid ACPI 2.0 bus resource descriptor. + @retval EFI_INVALID_PARAMETER Configuration includes valid ACPI 2.0 resource descriptors other than + bus descriptors. + @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid ACPI resource descriptors. + @retval EFI_INVALID_PARAMETER "Address Range Minimum" is invalid for this root bridge. + @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this root bridge. + @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. + @retval EFI_SUCCESS The bus range for the PCI root bridge was programmed. + +**/ +EFI_STATUS +EFIAPI +SetBusNumbers( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + IN VOID *Configuration + ); + +/** + Submits the I/O and memory resource requirements for the specified PCI root bridge. + + This function is used to submit all the I/O and memory resources that are required by the specified + PCI root bridge. The input parameter Configuration is used to specify the following: + - The various types of resources that are required + - The associated lengths in terms of ACPI 2.0 resource descriptor format + + @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance. + @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory resource requirements are being submitted. + @param[in] Configuration The pointer to the PCI I/O and PCI memory resource descriptor. + + @retval EFI_SUCCESS The I/O and memory resource requests for a PCI root bridge were accepted. + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor. + @retval EFI_INVALID_PARAMETER Configuration includes requests for one or more resource types that are + not supported by this PCI root bridge. This error will happen if the caller + did not combine resources according to Attributes that were returned by + GetAllocAttributes(). + @retval EFI_INVALID_PARAMETER Address Range Maximum" is invalid. + @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI root bridge. + @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for this PCI root bridge. + +**/ +EFI_STATUS +EFIAPI +SubmitResources( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + IN VOID *Configuration + ); + +/** + Returns the proposed resource settings for the specified PCI root bridge. + + This member function returns the proposed resource settings for the specified PCI root bridge. The + proposed resource settings are prepared when NotifyPhase() is called with a Phase of + EfiPciHostBridgeAllocateResources. The output parameter Configuration + specifies the following: + - The various types of resources, excluding bus resources, that are allocated + - The associated lengths in terms of ACPI 2.0 resource descriptor format + + @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance. + @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification. + @param[out] Configuration The pointer to the pointer to the PCI I/O and memory resource descriptor. + + @retval EFI_SUCCESS The requested parameters were returned. + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. + @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +GetProposedResources( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + OUT VOID **Configuration + ); + +/** + Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various + stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual + PCI controllers before enumeration. + + This function is called during the PCI enumeration process. No specific action is expected from this + member function. It allows the host bridge driver to preinitialize individual PCI controllers before + enumeration. + + @param This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance. + @param RootBridgeHandle The associated PCI root bridge handle. Type EFI_HANDLE is defined in + InstallProtocolInterface() in the UEFI 2.0 Specification. + @param PciAddress The address of the PCI device on the PCI bus. This address can be passed to the + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to access the PCI + configuration space of the device. See Table 12-1 in the UEFI 2.0 Specification for + the definition of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS. + @param Phase The phase of the PCI device enumeration. + + @retval EFI_SUCCESS The requested parameters were returned. + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. + @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in + EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE. + @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should + not enumerate this device, including its child devices if it is a PCI-to-PCI + bridge. + +**/ +EFI_STATUS +EFIAPI +PreprocessController ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress, + IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase + ); + + +// +// Define resource status constant +// +#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFFULL +#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFEULL + + +// +// Driver Instance Data Prototypes +// + +typedef struct { + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation; + UINTN NumberOfBytes; + UINTN NumberOfPages; + EFI_PHYSICAL_ADDRESS HostAddress; + EFI_PHYSICAL_ADDRESS MappedHostAddress; +} MAP_INFO; + +typedef struct { + ACPI_HID_DEVICE_PATH AcpiDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH; + +typedef enum { + TypeIo = 0, + TypeMem32, + TypePMem32, + TypeMem64, + TypePMem64, + TypeBus, + TypeMax +} PCI_RESOURCE_TYPE; + +typedef enum { + ResNone = 0, + ResSubmitted, + ResRequested, + ResAllocated, + ResStatusMax +} RES_STATUS; + +typedef struct { + PCI_RESOURCE_TYPE Type; + UINT64 Base; + UINT64 Length; + UINT64 Alignment; + RES_STATUS Status; +} PCI_RES_NODE; + +#define PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32('e', '2', 'p', 'b') + +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + EFI_HANDLE Handle; + UINT64 RootBridgeAttrib; + UINT64 Attributes; + UINT64 Supports; + + // + // Specific for this memory controller: Bus, I/O, Mem + // + PCI_RES_NODE ResAllocNode[6]; + + // + // Addressing for Memory and I/O and Bus arrange + // + UINT64 BusBase; + UINT64 MemBase; + UINT64 IoBase; + UINT64 BusLimit; + UINT64 MemLimit; + UINT64 IoLimit; + UINT64 RbPciBar; + UINT64 Ecam; + + UINTN PciAddress; + UINTN PciData; + UINTN Port; + UINT32 SocType; + UINT64 CpuMemRegionBase; + UINT64 CpuIoRegionBase; + UINT64 PciRegionBase; + UINT64 PciRegionLimit; + + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io; + +} PCI_ROOT_BRIDGE_INSTANCE; + + +// +// Driver Instance Data Macros +// +#define DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) \ + CR(a, PCI_ROOT_BRIDGE_INSTANCE, Io, PCI_ROOT_BRIDGE_SIGNATURE) + + +#define DRIVER_INSTANCE_FROM_LIST_ENTRY(a) \ + CR(a, PCI_ROOT_BRIDGE_INSTANCE, Link, PCI_ROOT_BRIDGE_SIGNATURE) + +/** + + Construct the Pci Root Bridge Io protocol + + @param Protocol Point to protocol instance + @param HostBridgeHandle Handle of host bridge + @param Attri Attribute of host bridge + @param ResAppeture ResourceAppeture for host bridge + + @retval EFI_SUCCESS Success to initialize the Pci Root Bridge. + +**/ +EFI_STATUS +RootBridgeConstructor ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol, + IN EFI_HANDLE HostBridgeHandle, + IN UINT64 Attri, + IN PCI_ROOT_BRIDGE_RESOURCE_APPETURE *ResAppeture, + IN UINT32 Seg + ); + +#endif diff --git a/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.inf b/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.inf new file mode 100644 index 0000000000..7f5e1751ec --- /dev/null +++ b/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.inf @@ -0,0 +1,74 @@ +## @file +# +# Component description file PCI Host Bridge driver. +# Copyright (c) 2014, AppliedMicro Corp. All rights reserved. +# Copyright (c) 2016, Hisilicon Limited. All rights reserved. +# Copyright (c) 2016, Linaro Limited. 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. +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PciHostBridge + FILE_GUID = B0E61270-263F-11E3-8224-0800200C9A66 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = InitializePciHostBridge + +[Packages] + MdePkg/MdePkg.dec + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + MemoryAllocationLib + DxeServicesTableLib + CacheMaintenanceLib + DmaLib + BaseMemoryLib + BaseLib + DebugLib + TimerLib + ArmLib + DevicePathLib + PcdLib + OemMiscLib + +[Sources] + PciHostBridge.c + PciRootBridgeIo.c + PciHostBridge.h + +[Protocols] + gEfiPciHostBridgeResourceAllocationProtocolGuid + gEfiPciRootBridgeIoProtocolGuid + gEfiMetronomeArchProtocolGuid + gEfiDevicePathProtocolGuid + gEmbeddedGpioProtocolGuid + +[depex] + gEfiMetronomeArchProtocolGuid + +[FeaturePcd] + +[Pcd] + +[FixedPcd] + gHisiTokenSpaceGuid.PcdPcieRootBridgeMask + gHisiTokenSpaceGuid.PcdPcieRootBridgeMask2P + gHisiTokenSpaceGuid.Pcdsoctype + +[Guids] + gEfiEventExitBootServicesGuid ## PRODUCES ## Event diff --git a/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciRootBridgeIo.c b/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciRootBridgeIo.c new file mode 100644 index 0000000000..03edcf1e17 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciRootBridgeIo.c @@ -0,0 +1,2313 @@ +/** + * Copyright (c) 2014, AppliedMicro Corp. All rights reserved. + * Copyright (c) 2016, Hisilicon Limited. All rights reserved. + * Copyright (c) 2016, Linaro Limited. 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. + * + **/ + +#include "PciHostBridge.h" +#include +#include +#include +#include + + +typedef struct { + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR SpaceDesp[TypeMax]; + EFI_ACPI_END_TAG_DESCRIPTOR EndDesp; +} RESOURCE_CONFIGURATION; + +RESOURCE_CONFIGURATION Configuration = { + {{0x8A, 0x2B, 1, 0, 0, 0, 0, 0, 0, 0}, + {0x8A, 0x2B, 0, 0, 0, 32, 0, 0, 0, 0}, + {0x8A, 0x2B, 0, 0, 6, 32, 0, 0, 0, 0}, + {0x8A, 0x2B, 0, 0, 0, 64, 0, 0, 0, 0}, + {0x8A, 0x2B, 0, 0, 6, 64, 0, 0, 0, 0}, + {0x8A, 0x2B, 2, 0, 0, 0, 0, 0, 0, 0}}, + {0x79, 0} +}; + +// +// Protocol Member Function Prototypes +// + +/** + Polls an address in memory mapped I/O space until an exit condition is met, or + a timeout occurs. + + This function provides a standard way to poll a PCI memory location. A PCI memory read + operation is performed at the PCI memory address specified by Address for the width specified + by Width. The result of this PCI memory read operation is stored in Result. This PCI memory + read operation is repeated until either a timeout of Delay 100 ns units has expired, or (Result & + Mask) is equal to Value. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Width Signifies the width of the memory operations. + @param[in] Address The base address of the memory operations. The caller is + responsible for aligning Address if required. + @param[in] Mask Mask used for the polling criteria. Bytes above Width in Mask + are ignored. The bits in the bytes below Width which are zero in + Mask are ignored when polling the memory address. + @param[in] Value The comparison value used for the polling exit criteria. + @param[in] Delay The number of 100 ns units to poll. Note that timer available may + be of poorer granularity. + @param[out] Result Pointer to the last value read from the memory location. + + @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria. + @retval EFI_INVALID_PARAMETER Width is invalid. + @retval EFI_INVALID_PARAMETER Result is NULL. + @retval EFI_TIMEOUT Delay expired before a match occurred. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoPollMem ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ); + +/** + Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is + satisfied or after a defined duration. + + This function provides a standard way to poll a PCI I/O location. A PCI I/O read operation is + performed at the PCI I/O address specified by Address for the width specified by Width. + The result of this PCI I/O read operation is stored in Result. This PCI I/O read operation is + repeated until either a timeout of Delay 100 ns units has expired, or (Result & Mask) is equal + to Value. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Width Signifies the width of the I/O operations. + @param[in] Address The base address of the I/O operations. The caller is responsible + for aligning Address if required. + @param[in] Mask Mask used for the polling criteria. Bytes above Width in Mask + are ignored. The bits in the bytes below Width which are zero in + Mask are ignored when polling the I/O address. + @param[in] Value The comparison value used for the polling exit criteria. + @param[in] Delay The number of 100 ns units to poll. Note that timer available may + be of poorer granularity. + @param[out] Result Pointer to the last value read from the memory location. + + @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria. + @retval EFI_INVALID_PARAMETER Width is invalid. + @retval EFI_INVALID_PARAMETER Result is NULL. + @retval EFI_TIMEOUT Delay expired before a match occurred. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoPollIo ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ); + +/** + Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space. + + The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller + registers in the PCI root bridge memory space. + The memory operations are carried out exactly as requested. The caller is responsible for satisfying + any alignment and memory width restrictions that a PCI Root Bridge on a platform might require. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Width Signifies the width of the memory operation. + @param[in] Address The base address of the memory operation. The caller is + responsible for aligning the Address if required. + @param[in] Count The number of memory operations to perform. Bytes moved is + Width size * Count, starting at Address. + @param[out] Buffer For read operations, the destination buffer to store the results. For + write operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. + @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoMemRead ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ); + +/** + Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space. + + The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller + registers in the PCI root bridge memory space. + The memory operations are carried out exactly as requested. The caller is responsible for satisfying + any alignment and memory width restrictions that a PCI Root Bridge on a platform might require. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Width Signifies the width of the memory operation. + @param[in] Address The base address of the memory operation. The caller is + responsible for aligning the Address if required. + @param[in] Count The number of memory operations to perform. Bytes moved is + Width size * Count, starting at Address. + @param[in] Buffer For read operations, the destination buffer to store the results. For + write operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. + @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +RootBridgeIoMemWrite ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Width Signifies the width of the memory operations. + @param[in] UserAddress The base address of the I/O operation. The caller is responsible for + aligning the Address if required. + @param[in] Count The number of I/O operations to perform. Bytes moved is Width + size * Count, starting at Address. + @param[out] UserBuffer For read operations, the destination buffer to store the results. For + write operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. + @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoIoRead ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 UserAddress, + IN UINTN Count, + OUT VOID *UserBuffer + ); + +/** + Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Width Signifies the width of the memory operations. + @param[in] UserAddress The base address of the I/O operation. The caller is responsible for + aligning the Address if required. + @param[in] Count The number of I/O operations to perform. Bytes moved is Width + size * Count, starting at Address. + @param[in] UserBuffer For read operations, the destination buffer to store the results. For + write operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. + @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoIoWrite ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 UserAddress, + IN UINTN Count, + IN VOID *UserBuffer + ); + +/** + Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI + root bridge memory space. + + The CopyMem() function enables a PCI driver to copy one region of PCI root bridge memory + space to another region of PCI root bridge memory space. This is especially useful for video scroll + operation on a memory mapped video buffer. + The memory operations are carried out exactly as requested. The caller is responsible for satisfying + any alignment and memory width restrictions that a PCI root bridge on a platform might require. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance. + @param[in] Width Signifies the width of the memory operations. + @param[in] DestAddress The destination address of the memory operation. The caller is + responsible for aligning the DestAddress if required. + @param[in] SrcAddress The source address of the memory operation. The caller is + responsible for aligning the SrcAddress if required. + @param[in] Count The number of memory operations to perform. Bytes moved is + Width size * Count, starting at DestAddress and SrcAddress. + + @retval EFI_SUCCESS The data was copied from one memory region to another memory region. + @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoCopyMem ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 DestAddress, + IN UINT64 SrcAddress, + IN UINTN Count + ); + +/** + Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space. + + The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration + registers for a PCI controller. + The PCI Configuration operations are carried out exactly as requested. The caller is responsible for + any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might + require. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Width Signifies the width of the memory operations. + @param[in] Address The address within the PCI configuration space for the PCI controller. + @param[in] Count The number of PCI configuration operations to perform. Bytes + moved is Width size * Count, starting at Address. + @param[out] Buffer For read operations, the destination buffer to store the results. For + write operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. + @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoPciRead ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ); + +/** + Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space. + + The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration + registers for a PCI controller. + The PCI Configuration operations are carried out exactly as requested. The caller is responsible for + any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might + require. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Width Signifies the width of the memory operations. + @param[in] Address The address within the PCI configuration space for the PCI controller. + @param[in] Count The number of PCI configuration operations to perform. Bytes + moved is Width size * Count, starting at Address. + @param[in] Buffer For read operations, the destination buffer to store the results. For + write operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. + @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoPciWrite ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Provides the PCI controller-specific addresses required to access system memory from a + DMA bus master. + + The Map() function provides the PCI controller specific addresses needed to access system + memory. This function is used to map system memory for PCI bus master DMA accesses. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Operation Indicates if the bus master is going to read or write to system memory. + @param[in] HostAddress The system memory address to map to the PCI controller. + @param[in, out] NumberOfBytes On input the number of bytes to map. On output the number of bytes that were mapped. + @param[out] DeviceAddress The resulting map address for the bus master PCI controller to use + to access the system memory's HostAddress. + @param[out] Mapping The value to pass to Unmap() when the bus master DMA operation is complete. + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_INVALID_PARAMETER Operation is invalid. + @retval EFI_INVALID_PARAMETER HostAddress is NULL. + @retval EFI_INVALID_PARAMETER NumberOfBytes is NULL. + @retval EFI_INVALID_PARAMETER DeviceAddress is NULL. + @retval EFI_INVALID_PARAMETER Mapping is NULL. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoMap ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Completes the Map() operation and releases any corresponding resources. + + The Unmap() function completes the Map() operation and releases any corresponding resources. + If the operation was an EfiPciOperationBusMasterWrite or + EfiPciOperationBusMasterWrite64, the data is committed to the target system memory. + Any resources used for the mapping are freed. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Mapping The mapping value returned from Map(). + + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map(). + @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoUnmap ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN VOID *Mapping + ); + +/** + Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or + EfiPciOperationBusMasterCommonBuffer64 mapping. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Type This parameter is not used and must be ignored. + @param MemoryType The type of memory to allocate, EfiBootServicesData or EfiRuntimeServicesData. + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system memory address of the allocated range. + @param Attributes The requested bit mask of attributes for the allocated range. Only + the attributes EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_ATTRIBUTE_MEMORY_CACHED, + and EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this function. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_INVALID_PARAMETER MemoryType is invalid. + @retval EFI_INVALID_PARAMETER HostAddress is NULL. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are + MEMORY_WRITE_COMBINE, MEMORY_CACHED, and DUAL_ADDRESS_CYCLE. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoAllocateBuffer ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ); + +/** + Frees memory that was allocated with AllocateBuffer(). + + The FreeBuffer() function frees memory that was allocated with AllocateBuffer(). + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allocated range. + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages + was not allocated with AllocateBuffer(). + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoFreeBuffer ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN UINTN Pages, + OUT VOID *HostAddress + ); + +/** + Flushes all PCI posted write transactions from a PCI host bridge to system memory. + + The Flush() function flushes any PCI posted write transactions from a PCI host bridge to system + memory. Posted write transactions are generated by PCI bus masters when they perform write + transactions to target addresses in system memory. + This function does not flush posted write transactions from any PCI bridges. A PCI controller + specific action must be taken to guarantee that the posted write transactions have been flushed from + the PCI controller and from all the PCI bridges into the PCI host bridge. This is typically done with + a PCI read transaction from the PCI controller prior to calling Flush(). + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + + @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host + bridge to system memory. + @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI + host bridge due to a hardware error. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoFlush ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This + ); + +/** + Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the + attributes that a PCI root bridge is currently using. + + The GetAttributes() function returns the mask of attributes that this PCI root bridge supports + and the mask of attributes that the PCI root bridge is currently using. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Supported A pointer to the mask of attributes that this PCI root bridge + supports setting with SetAttributes(). + @param Attributes A pointer to the mask of attributes that this PCI root bridge is + currently using. + + @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI root + bridge supports is returned in Supports. If Attributes is + not NULL, then the attributes that the PCI root bridge is currently + using is returned in Attributes. + @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoGetAttributes ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + OUT UINT64 *Supported, + OUT UINT64 *Attributes + ); + +/** + Sets attributes for a resource range on a PCI root bridge. + + The SetAttributes() function sets the attributes specified in Attributes for the PCI root + bridge on the resource range specified by ResourceBase and ResourceLength. Since the + granularity of setting these attributes may vary from resource type to resource type, and from + platform to platform, the actual resource range and the one passed in by the caller may differ. As a + result, this function may set the attributes specified by Attributes on a larger resource range + than the caller requested. The actual range is returned in ResourceBase and + ResourceLength. The caller is responsible for verifying that the actual range for which the + attributes were set is acceptable. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Attributes The mask of attributes to set. If the attribute bit + MEMORY_WRITE_COMBINE, MEMORY_CACHED, or + MEMORY_DISABLE is set, then the resource range is specified by + ResourceBase and ResourceLength. If + MEMORY_WRITE_COMBINE, MEMORY_CACHED, and + MEMORY_DISABLE are not set, then ResourceBase and + ResourceLength are ignored, and may be NULL. + @param[in, out] ResourceBase A pointer to the base address of the resource range to be modified + by the attributes specified by Attributes. + @param[in, out] ResourceLength A pointer to the length of the resource range to be modified by the + attributes specified by Attributes. + + @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in Resources. + @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved. + @retval EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoSetAttributes ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN UINT64 Attributes, + IN OUT UINT64 *ResourceBase, + IN OUT UINT64 *ResourceLength + ); + +/** + Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0 + resource descriptors. + + There are only two resource descriptor types from the ACPI Specification that may be used to + describe the current resources allocated to a PCI root bridge. These are the QWORD Address + Space Descriptor (ACPI 2.0 Section 6.4.3.5.1), and the End Tag (ACPI 2.0 Section 6.4.2.8). The + QWORD Address Space Descriptor can describe memory, I/O, and bus number ranges for dynamic + or fixed resources. The configuration of a PCI root bridge is described with one or more QWORD + Address Space Descriptors followed by an End Tag. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[out] Resources A pointer to the ACPI 2.0 resource descriptors that describe the + current configuration of this PCI root bridge. The storage for the + ACPI 2.0 resource descriptors is allocated by this function. The + caller must treat the return buffer as read-only data, and the buffer + must not be freed by the caller. + + @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in Resources. + @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved. + @retval EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoConfiguration ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + OUT VOID **Resources + ); + +// +// Memory Controller Pci Root Bridge Io Module Variables +// +EFI_METRONOME_ARCH_PROTOCOL *mMetronome; + +// +// Lookup table for increment values based on transfer widths +// +UINT8 mInStride[] = { + 1, // EfiPciWidthUint8 + 2, // EfiPciWidthUint16 + 4, // EfiPciWidthUint32 + 8, // EfiPciWidthUint64 + 0, // EfiPciWidthFifoUint8 + 0, // EfiPciWidthFifoUint16 + 0, // EfiPciWidthFifoUint32 + 0, // EfiPciWidthFifoUint64 + 1, // EfiPciWidthFillUint8 + 2, // EfiPciWidthFillUint16 + 4, // EfiPciWidthFillUint32 + 8 // EfiPciWidthFillUint64 +}; + +// +// Lookup table for increment values based on transfer widths +// +UINT8 mOutStride[] = { + 1, // EfiPciWidthUint8 + 2, // EfiPciWidthUint16 + 4, // EfiPciWidthUint32 + 8, // EfiPciWidthUint64 + 1, // EfiPciWidthFifoUint8 + 2, // EfiPciWidthFifoUint16 + 4, // EfiPciWidthFifoUint32 + 8, // EfiPciWidthFifoUint64 + 0, // EfiPciWidthFillUint8 + 0, // EfiPciWidthFillUint16 + 0, // EfiPciWidthFillUint32 + 0 // EfiPciWidthFillUint64 +}; + + +UINT64 GetPcieCfgAddress ( + UINT64 Ecam, + UINTN Bus, + UINTN Device, + UINTN Function, + UINTN Reg + ) +{ + return Ecam + PCI_EXPRESS_LIB_ADDRESS (Bus, Device, Function, Reg); +} + + +void SetAtuConfig0RW ( + PCI_ROOT_BRIDGE_INSTANCE *Private, + UINT32 Index + ) +{ + UINTN RbPciBase = Private->RbPciBar; + UINT64 MemLimit = GetPcieCfgAddress (Private->Ecam, Private->BusBase + 1, 1, 0, 0) - 1; + + + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_VIEW_POINT, Index); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LOW, (UINT32)(Private->Ecam)); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_HIGH, (UINT32)((UINT64)(Private->Ecam) >> 32)); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LIMIT, (UINT32) MemLimit); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_LOW, 0); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_HIGH, 0); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL1, IATU_CTRL1_TYPE_CONFIG0); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL2, IATU_SHIIF_MODE); + + { + UINTN i; + for (i=0; i<0x20; i+=4) { + DEBUG ((EFI_D_ERROR, "[%a:%d] - Base=%p value=%x\n", __FUNCTION__, __LINE__, RbPciBase + 0x900 + i, MmioRead32(RbPciBase + 0x900 + i))); + } + } +} + +void SetAtuConfig1RW ( + PCI_ROOT_BRIDGE_INSTANCE *Private, + UINT32 Index + ) +{ + UINTN RbPciBase = Private->RbPciBar; + UINT64 MemLimit = GetPcieCfgAddress (Private->Ecam, Private->BusLimit + 1, 0, 0, 0) - 1; + + + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_VIEW_POINT, Index); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL1, IATU_CTRL1_TYPE_CONFIG1); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LOW, (UINT32)(Private->Ecam)); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_HIGH, (UINT32)((UINT64)(Private->Ecam) >> 32)); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LIMIT, (UINT32) MemLimit); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_LOW, 0); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_HIGH, 0); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL2, IATU_SHIIF_MODE); + + { + UINTN i; + for (i=0; i<0x20; i+=4) { + DEBUG ((EFI_D_ERROR, "[%a:%d] - Base=%p value=%x\n", __FUNCTION__, __LINE__, RbPciBase + 0x900 + i, MmioRead32(RbPciBase + 0x900 + i))); + } + } +} + +void SetAtuIoRW(UINT64 RbPciBase,UINT64 IoBase,UINT64 CpuIoRegionLimit, UINT64 CpuIoRegionBase, UINT32 Index) +{ + + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_VIEW_POINT, Index); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL1, IATU_CTRL1_TYPE_IO); + + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LOW, (UINT32)(CpuIoRegionBase)); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_HIGH, (UINT32)((UINT64)CpuIoRegionBase >> 32)); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LIMIT, (UINT32)(CpuIoRegionLimit)); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_LOW, (UINT32)(IoBase)); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_HIGH, (UINT32)((UINT64)(IoBase) >> 32)); + + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL2, IATU_NORMAL_MODE); + + { + UINTN i; + for (i=0; i<0x20; i+=4) { + DEBUG ((EFI_D_ERROR, "[%a:%d] - Base=%p value=%x\n", __FUNCTION__, __LINE__, RbPciBase + 0x900 + i, MmioRead32(RbPciBase + 0x900 + i))); + } + } +} + +void SetAtuMemRW(UINT64 RbPciBase,UINT64 MemBase,UINT64 CpuMemRegionLimit, UINT64 CpuMemRegionBase, UINT32 Index) +{ + + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_VIEW_POINT, Index); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL1, IATU_CTRL1_TYPE_MEM); + + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LOW, (UINT32)(CpuMemRegionBase)); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_HIGH, (UINT32)((UINT64)(CpuMemRegionBase) >> 32)); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LIMIT, (UINT32)(CpuMemRegionLimit)); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_LOW, (UINT32)(MemBase)); + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_HIGH, (UINT32)((UINT64)(MemBase) >> 32)); + + MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL2, IATU_NORMAL_MODE); + + { + UINTN i; + for (i=0; i<0x20; i+=4) { + DEBUG ((EFI_D_ERROR, "[%a:%d] - Base=%p value=%x\n", __FUNCTION__, __LINE__, RbPciBase + 0x900 + i, MmioRead32(RbPciBase + 0x900 + i))); + } + } +} + +VOID InitAtu (PCI_ROOT_BRIDGE_INSTANCE *Private) +{ + SetAtuMemRW (Private->RbPciBar, Private->PciRegionBase, Private->PciRegionLimit, Private->CpuMemRegionBase, 0); + SetAtuConfig0RW (Private, 1); + SetAtuConfig1RW (Private, 2); + SetAtuIoRW (Private->RbPciBar, Private->IoBase, Private->IoLimit, Private->CpuIoRegionBase, 3); +} + + +BOOLEAN PcieIsLinkUp (UINT32 SocType, UINTN RbPciBar, UINTN Port) +{ + UINT32 Value = 0; + + if (0x1610 == SocType) + { + Value = MmioRead32(RbPciBar + 0x131C); + if ((Value & 0x3F) == 0x11) + { + return TRUE; + } + return FALSE; + } + else + { + Value = MmioRead32 (0xb0000000 + 0x6818 + 0x100 * Port); + if ((Value & 0x3F) == 0x11) + { + return TRUE; + } + return FALSE; + } +} + +/** + + Construct the Pci Root Bridge Io protocol + + @param Protocol Point to protocol instance + @param HostBridgeHandle Handle of host bridge + @param Attri Attribute of host bridge + @param ResAppeture ResourceAppeture for host bridge + + @retval EFI_SUCCESS Success to initialize the Pci Root Bridge. + +**/ +EFI_STATUS +RootBridgeConstructor ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol, + IN EFI_HANDLE HostBridgeHandle, + IN UINT64 Attri, + IN PCI_ROOT_BRIDGE_RESOURCE_APPETURE *ResAppeture, + IN UINT32 Seg + ) +{ + EFI_STATUS Status; + PCI_ROOT_BRIDGE_INSTANCE *PrivateData; + PCI_RESOURCE_TYPE Index; + + PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol); + + // + // The host to pci bridge, the host memory and io addresses are + // direct mapped to pci addresses, so no need translate, set bases to 0. + // + PrivateData->MemBase = ResAppeture->MemBase; + PrivateData->IoBase = ResAppeture->IoBase; + PrivateData->RbPciBar = ResAppeture->RbPciBar; + PrivateData->MemLimit = ResAppeture->MemLimit; + PrivateData->IoLimit = ResAppeture->IoLimit; + PrivateData->Ecam = ResAppeture->Ecam; + PrivateData->CpuMemRegionBase = ResAppeture->CpuMemRegionBase; + PrivateData->CpuIoRegionBase = ResAppeture->CpuIoRegionBase; + PrivateData->PciRegionBase = ResAppeture->PciRegionBase; + PrivateData->PciRegionLimit = ResAppeture->PciRegionLimit; + + // + // Bus Appeture for this Root Bridge (Possible Range) + // + PrivateData->BusBase = ResAppeture->BusBase; + PrivateData->BusLimit = ResAppeture->BusLimit; + + // + // Specific for this chipset + // + for (Index = TypeIo; Index < TypeMax; Index++) { + PrivateData->ResAllocNode[Index].Type = Index; + PrivateData->ResAllocNode[Index].Base = 0; + PrivateData->ResAllocNode[Index].Length = 0; + PrivateData->ResAllocNode[Index].Status = ResNone; + } + + PrivateData->RootBridgeAttrib = Attri; + + PrivateData->Supports = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO | \ + EFI_PCI_ATTRIBUTE_ISA_IO_16 | EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO | \ + EFI_PCI_ATTRIBUTE_VGA_MEMORY | \ + EFI_PCI_ATTRIBUTE_VGA_IO_16 | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 | \ + EFI_PCI_ATTRIBUTE_VALID_FOR_ALLOCATE_BUFFER; + PrivateData->Attributes = PrivateData->Supports; + + Protocol->ParentHandle = HostBridgeHandle; + + Protocol->PollMem = RootBridgeIoPollMem; + Protocol->PollIo = RootBridgeIoPollIo; + + Protocol->Mem.Read = RootBridgeIoMemRead; + Protocol->Mem.Write = RootBridgeIoMemWrite; + + Protocol->Io.Read = RootBridgeIoIoRead; + Protocol->Io.Write = RootBridgeIoIoWrite; + + Protocol->CopyMem = RootBridgeIoCopyMem; + + Protocol->Pci.Read = RootBridgeIoPciRead; + Protocol->Pci.Write = RootBridgeIoPciWrite; + + Protocol->Map = RootBridgeIoMap; + Protocol->Unmap = RootBridgeIoUnmap; + + Protocol->AllocateBuffer = RootBridgeIoAllocateBuffer; + Protocol->FreeBuffer = RootBridgeIoFreeBuffer; + + Protocol->Flush = RootBridgeIoFlush; + + Protocol->GetAttributes = RootBridgeIoGetAttributes; + Protocol->SetAttributes = RootBridgeIoSetAttributes; + + Protocol->Configuration = RootBridgeIoConfiguration; + + Protocol->SegmentNumber = Seg; + + InitAtu (PrivateData); + + Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **)&mMetronome); + if (EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR,"LocateProtocol MetronomeArchProtocol Error\n")); + } + + return EFI_SUCCESS; +} + +/** + Check parameters for IO,MMIO,PCI read/write services of PCI Root Bridge IO. + + The I/O operations are carried out exactly as requested. The caller is responsible + for satisfying any alignment and I/O width restrictions that a PI System on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will + be handled by the driver. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] OperationType I/O operation type: IO/MMIO/PCI. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number of + bytes moved is Width size * Count, starting at Address. + @param[in] Buffer For read operations, the destination buffer to store the results. + For write operations, the source buffer from which to write data. + + @retval EFI_SUCCESS The parameters for this request pass the checks. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. + @retval EFI_UNSUPPORTED The address range specified by Address, Width, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +RootBridgeIoCheckParameter ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN OPERATION_TYPE OperationType, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + PCI_ROOT_BRIDGE_INSTANCE *PrivateData; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *PciRbAddr; + UINT64 MaxCount; + UINT64 Base; + UINT64 Limit; + + // + // Check to see if Buffer is NULL + // + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check to see if Width is in the valid range + // + if ((UINT32)Width >= EfiPciWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + // + // For FIFO type, the target address won't increase during the access, + // so treat Count as 1 + // + if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) { + Count = 1; + } + + // + // Check to see if Width is in the valid range for I/O Port operations + // + Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03); + if ((OperationType != MemOperation) && (Width == EfiPciWidthUint64)) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + // + // Check to see if Address is aligned + // + if ((Address & (UINT64)(mInStride[Width] - 1)) != 0) { + return EFI_UNSUPPORTED; + } + + PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This); + + // + // Check to see if any address associated with this transfer exceeds the maximum + // allowed address. The maximum address implied by the parameters passed in is + // Address + Size * Count. If the following condition is met, then the transfer + // is not supported. + // + // Address + Size * Count > Limit + 1 + // + // Since Limit can be the maximum integer value supported by the CPU and Count + // can also be the maximum integer value supported by the CPU, this range + // check must be adjusted to avoid all oveflow conditions. + // + // The following form of the range check is equivalent but assumes that + // Limit is of the form (2^n - 1). + // + if (OperationType == IoOperation) { + Base = PrivateData->IoBase; + Limit = PrivateData->IoLimit; + } else if (OperationType == MemOperation) { + Base = PrivateData->MemBase; + Limit = PrivateData->MemLimit; + } else { + PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &Address; + if (PciRbAddr->Bus < PrivateData->BusBase || PciRbAddr->Bus > PrivateData->BusLimit) { + return EFI_INVALID_PARAMETER; + } + + /* The root complex has only one device / function */ + if (PciRbAddr->Bus == PrivateData->BusBase && PciRbAddr->Device != 0) { + return EFI_INVALID_PARAMETER; + } + + /* The other side of the RC has only one device as well */ + if (PciRbAddr->Bus == (PrivateData->BusBase + 1 ) && PciRbAddr->Device != 0) { + return EFI_INVALID_PARAMETER; + } + + if (PciRbAddr->Device > MAX_PCI_DEVICE_NUMBER || PciRbAddr->Function > MAX_PCI_FUNCTION_NUMBER) { + return EFI_INVALID_PARAMETER; + } + + if (PciRbAddr->ExtendedRegister != 0) { + Address = PciRbAddr->ExtendedRegister; + } else { + Address = PciRbAddr->Register; + } + Base = 0; + Limit = MAX_PCI_REG_ADDRESS; + } + + if (Address < Base) { + return EFI_INVALID_PARAMETER; + } + + if (Count == 0) { + if (Address > Limit) { + return EFI_UNSUPPORTED; + } + } else { + MaxCount = RShiftU64 (Limit, Width); + if (MaxCount < (Count - 1)) { + return EFI_UNSUPPORTED; + } + if (Address > LShiftU64 (MaxCount - Count + 1, Width)) { + return EFI_UNSUPPORTED; + } + } + + return EFI_SUCCESS; +} + +/** + Internal help function for read and write memory space. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Write Switch value for Read or Write. + @param[in] Width Signifies the width of the memory operations. + @param[in] UserAddress The address within the PCI configuration space for the PCI controller. + @param[in] Count The number of PCI configuration operations to perform. Bytes + moved is Width size * Count, starting at Address. + @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For + write operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. + @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +RootBridgeIoMemRW ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN BOOLEAN Write, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT8 InStride; + UINT8 OutStride; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OperationWidth; + UINT8 *Uint8Buffer; + PCI_ROOT_BRIDGE_INSTANCE *PrivateData; + + PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This); + /* Address is bus resource */ + Address -= PrivateData->PciRegionBase; + Address += PrivateData->CpuMemRegionBase; + + PCIE_DEBUG("RootBridgeIoMemRW Address:0x%llx\n", Address); + PCIE_DEBUG("RootBridgeIoMemRW Count:0x%llx\n", Count); + PCIE_DEBUG("RootBridgeIoMemRW Write:0x%llx\n", Write); + PCIE_DEBUG("RootBridgeIoMemRW Width:0x%llx\n", Width); + + Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address, Count, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + InStride = mInStride[Width]; + OutStride = mOutStride[Width]; + OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03); + for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { + if (Write) { + switch (OperationWidth) { + case EfiPciWidthUint8: + MmioWrite8 ((UINTN)Address, *Uint8Buffer); + break; + case EfiPciWidthUint16: + MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); + break; + case EfiPciWidthUint32: + MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); + break; + case EfiPciWidthUint64: + MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer)); + break; + default: + // + // The RootBridgeIoCheckParameter call above will ensure that this + // path is not taken. + // + ASSERT (FALSE); + break; + } + } else { + switch (OperationWidth) { + case EfiPciWidthUint8: + *Uint8Buffer = MmioRead8 ((UINTN)Address); + break; + case EfiPciWidthUint16: + *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address); + break; + case EfiPciWidthUint32: + *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address); + break; + case EfiPciWidthUint64: + *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address); + break; + default: + // + // The RootBridgeIoCheckParameter call above will ensure that this + // path is not taken. + // + ASSERT (FALSE); + break; + } + } + } + return EFI_SUCCESS; +} + +/** + Internal help function for read and write IO space. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Write Switch value for Read or Write. + @param[in] Width Signifies the width of the memory operations. + @param[in] UserAddress The address within the PCI configuration space for the PCI controller. + @param[in] Count The number of PCI configuration operations to perform. Bytes + moved is Width size * Count, starting at Address. + @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For + write operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. + @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +RootBridgeIoIoRW ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN BOOLEAN Write, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT8 InStride; + UINT8 OutStride; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OperationWidth; + UINT8 *Uint8Buffer; + PCI_ROOT_BRIDGE_INSTANCE *PrivateData; + + PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This); + /* Address is bus resource */ + Address -= PrivateData->IoBase; + Address += PrivateData->CpuIoRegionBase; + + Status = RootBridgeIoCheckParameter (This, IoOperation, Width, Address, Count, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + InStride = mInStride[Width]; + OutStride = mOutStride[Width]; + OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03); + + for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { + if (Write) { + switch (OperationWidth) { + case EfiPciWidthUint8: + MmioWrite8 ((UINTN)Address, *Uint8Buffer); + break; + case EfiPciWidthUint16: + MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); + break; + case EfiPciWidthUint32: + MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); + break; + case EfiPciWidthUint64: + MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer)); + break; + default: + // + // The RootBridgeIoCheckParameter call above will ensure that this + // path is not taken. + // + ASSERT (FALSE); + break; + } + } else { + switch (OperationWidth) { + case EfiPciWidthUint8: + *Uint8Buffer = MmioRead8 ((UINTN)Address); + break; + case EfiPciWidthUint16: + *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address); + break; + case EfiPciWidthUint32: + *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address); + break; + case EfiPciWidthUint64: + *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address); + break; + default: + // + // The RootBridgeIoCheckParameter call above will ensure that this + // path is not taken. + // + ASSERT (FALSE); + break; + } + } + } + return EFI_SUCCESS; +} + + +/** + Polls an address in memory mapped I/O space until an exit condition is met, or + a timeout occurs. + + This function provides a standard way to poll a PCI memory location. A PCI memory read + operation is performed at the PCI memory address specified by Address for the width specified + by Width. The result of this PCI memory read operation is stored in Result. This PCI memory + read operation is repeated until either a timeout of Delay 100 ns units has expired, or (Result & + Mask) is equal to Value. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Width Signifies the width of the memory operations. + @param[in] Address The base address of the memory operations. The caller is + responsible for aligning Address if required. + @param[in] Mask Mask used for the polling criteria. Bytes above Width in Mask + are ignored. The bits in the bytes below Width which are zero in + Mask are ignored when polling the memory address. + @param[in] Value The comparison value used for the polling exit criteria. + @param[in] Delay The number of 100 ns units to poll. Note that timer available may + be of poorer granularity. + @param[out] Result Pointer to the last value read from the memory location. + + @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria. + @retval EFI_INVALID_PARAMETER Width is invalid. + @retval EFI_INVALID_PARAMETER Result is NULL. + @retval EFI_TIMEOUT Delay expired before a match occurred. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoPollMem ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ) +{ + EFI_STATUS Status; + UINT64 NumberOfTicks; + UINT32 Remainder; + + if (Result == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // No matter what, always do a single poll. + // + Status = This->Mem.Read (This, Width, Address, 1, Result); + if (EFI_ERROR (Status)) { + return Status; + } + if ((*Result & Mask) == Value) { + return EFI_SUCCESS; + } + + if (Delay == 0) { + return EFI_TIMEOUT; + + } else { + + // + // Determine the proper # of metronome ticks to wait for polling the + // location. The nuber of ticks is Roundup (Delay / mMetronome->TickPeriod)+1 + // The "+1" to account for the possibility of the first tick being short + // because we started in the middle of a tick. + // + // BugBug: overriding mMetronome->TickPeriod with UINT32 until Metronome + // protocol definition is updated. + // + NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) mMetronome->TickPeriod, &Remainder); + if (Remainder != 0) { + NumberOfTicks += 1; + } + NumberOfTicks += 1; + + while (NumberOfTicks != 0) { + + mMetronome->WaitForTick (mMetronome, 1); + + Status = This->Mem.Read (This, Width, Address, 1, Result); + if (EFI_ERROR (Status)) { + return Status; + } + + if ((*Result & Mask) == Value) { + return EFI_SUCCESS; + } + + NumberOfTicks -= 1; + } + } + return EFI_TIMEOUT; +} + +/** + Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is + satisfied or after a defined duration. + + This function provides a standard way to poll a PCI I/O location. A PCI I/O read operation is + performed at the PCI I/O address specified by Address for the width specified by Width. + The result of this PCI I/O read operation is stored in Result. This PCI I/O read operation is + repeated until either a timeout of Delay 100 ns units has expired, or (Result & Mask) is equal + to Value. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Width Signifies the width of the I/O operations. + @param[in] Address The base address of the I/O operations. The caller is responsible + for aligning Address if required. + @param[in] Mask Mask used for the polling criteria. Bytes above Width in Mask + are ignored. The bits in the bytes below Width which are zero in + Mask are ignored when polling the I/O address. + @param[in] Value The comparison value used for the polling exit criteria. + @param[in] Delay The number of 100 ns units to poll. Note that timer available may + be of poorer granularity. + @param[out] Result Pointer to the last value read from the memory location. + + @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria. + @retval EFI_INVALID_PARAMETER Width is invalid. + @retval EFI_INVALID_PARAMETER Result is NULL. + @retval EFI_TIMEOUT Delay expired before a match occurred. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoPollIo ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ) +{ + EFI_STATUS Status; + UINT64 NumberOfTicks; + UINT32 Remainder; + + // + // No matter what, always do a single poll. + // + + if (Result == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = This->Io.Read (This, Width, Address, 1, Result); + if (EFI_ERROR (Status)) { + return Status; + } + if ((*Result & Mask) == Value) { + return EFI_SUCCESS; + } + + if (Delay == 0) { + return EFI_SUCCESS; + + } else { + + // + // Determine the proper # of metronome ticks to wait for polling the + // location. The number of ticks is Roundup (Delay / mMetronome->TickPeriod)+1 + // The "+1" to account for the possibility of the first tick being short + // because we started in the middle of a tick. + // + NumberOfTicks = DivU64x32Remainder (Delay, (UINT32)mMetronome->TickPeriod, &Remainder); + if (Remainder != 0) { + NumberOfTicks += 1; + } + NumberOfTicks += 1; + + while (NumberOfTicks != 0) { + + mMetronome->WaitForTick (mMetronome, 1); + + Status = This->Io.Read (This, Width, Address, 1, Result); + if (EFI_ERROR (Status)) { + return Status; + } + + if ((*Result & Mask) == Value) { + return EFI_SUCCESS; + } + + NumberOfTicks -= 1; + } + } + return EFI_TIMEOUT; +} + +/** + Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space. + + The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller + registers in the PCI root bridge memory space. + The memory operations are carried out exactly as requested. The caller is responsible for satisfying + any alignment and memory width restrictions that a PCI Root Bridge on a platform might require. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Width Signifies the width of the memory operation. + @param[in] Address The base address of the memory operation. The caller is + responsible for aligning the Address if required. + @param[in] Count The number of memory operations to perform. Bytes moved is + Width size * Count, starting at Address. + @param[out] Buffer For read operations, the destination buffer to store the results. For + write operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. + @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoMemRead ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + return RootBridgeIoMemRW (This, FALSE, Width, Address, Count, Buffer); +} + +/** + Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space. + + The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller + registers in the PCI root bridge memory space. + The memory operations are carried out exactly as requested. The caller is responsible for satisfying + any alignment and memory width restrictions that a PCI Root Bridge on a platform might require. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Width Signifies the width of the memory operation. + @param[in] Address The base address of the memory operation. The caller is + responsible for aligning the Address if required. + @param[in] Count The number of memory operations to perform. Bytes moved is + Width size * Count, starting at Address. + @param[in] Buffer For read operations, the destination buffer to store the results. For + write operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. + @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +RootBridgeIoMemWrite ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + return RootBridgeIoMemRW (This, TRUE, Width, Address, Count, Buffer); +} + +/** + Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Width Signifies the width of the memory operations. + @param[in] Address The base address of the I/O operation. The caller is responsible for + aligning the Address if required. + @param[in] Count The number of I/O operations to perform. Bytes moved is Width + size * Count, starting at Address. + @param[out] Buffer For read operations, the destination buffer to store the results. For + write operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. + @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoIoRead ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + return RootBridgeIoIoRW (This, FALSE, Width, Address, Count, Buffer); +} + +/** + Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Width Signifies the width of the memory operations. + @param[in] Address The base address of the I/O operation. The caller is responsible for + aligning the Address if required. + @param[in] Count The number of I/O operations to perform. Bytes moved is Width + size * Count, starting at Address. + @param[in] Buffer For read operations, the destination buffer to store the results. For + write operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. + @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoIoWrite ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + return RootBridgeIoIoRW (This, TRUE, Width, Address, Count, Buffer); +} + +/** + Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI + root bridge memory space. + + The CopyMem() function enables a PCI driver to copy one region of PCI root bridge memory + space to another region of PCI root bridge memory space. This is especially useful for video scroll + operation on a memory mapped video buffer. + The memory operations are carried out exactly as requested. The caller is responsible for satisfying + any alignment and memory width restrictions that a PCI root bridge on a platform might require. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance. + @param[in] Width Signifies the width of the memory operations. + @param[in] DestAddress The destination address of the memory operation. The caller is + responsible for aligning the DestAddress if required. + @param[in] SrcAddress The source address of the memory operation. The caller is + responsible for aligning the SrcAddress if required. + @param[in] Count The number of memory operations to perform. Bytes moved is + Width size * Count, starting at DestAddress and SrcAddress. + + @retval EFI_SUCCESS The data was copied from one memory region to another memory region. + @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoCopyMem ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 DestAddress, + IN UINT64 SrcAddress, + IN UINTN Count + ) +{ + EFI_STATUS Status; + BOOLEAN Direction; + UINTN Stride; + UINTN Index; + UINT64 Result; + + if ((UINT32)Width > EfiPciWidthUint64) { + return EFI_INVALID_PARAMETER; + } + + if (DestAddress == SrcAddress) { + return EFI_SUCCESS; + } + + Stride = (UINTN)((UINTN)1 << Width); + + Direction = TRUE; + if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) { + Direction = FALSE; + SrcAddress = SrcAddress + (Count-1) * Stride; + DestAddress = DestAddress + (Count-1) * Stride; + } + + for (Index = 0;Index < Count;Index++) { + Status = RootBridgeIoMemRead ( + This, + Width, + SrcAddress, + 1, + &Result + ); + if (EFI_ERROR (Status)) { + return Status; + } + Status = RootBridgeIoMemWrite ( + This, + Width, + DestAddress, + 1, + &Result + ); + if (EFI_ERROR (Status)) { + return Status; + } + if (Direction) { + SrcAddress += Stride; + DestAddress += Stride; + } else { + SrcAddress -= Stride; + DestAddress -= Stride; + } + } + return EFI_SUCCESS; +} + +/** + Reads memory-mapped registers. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number of + bytes moved is Width size * Count, starting at Address. + @param[out] Buffer For read operations, the destination buffer to store the results. + For write operations, the source buffer from which to write data. + + @retval EFI_SUCCESS The data was read from or written to the PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. + @retval EFI_UNSUPPORTED The address range specified by Address, Width, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +CpuMemoryServiceRead ( + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + + UINT8 InStride; + UINT8 OutStride; + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; + UINT8 *Uint8Buffer; + UINT32 Uint32Buffer = 0; + + // + // Select loop based on the width of the transfer + // + InStride = mInStride[Width]; + OutStride = mOutStride[Width]; + OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); + for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { + if (OperationWidth == EfiCpuIoWidthUint8) { + Uint32Buffer = MmioRead32((UINTN)(Address & (~0x3))); + Uint32Buffer &= (0xFF << ((Address & 0x3) * 8)); + *((UINT8*)Uint8Buffer) = (UINT8)(Uint32Buffer >> (((Address & 0x3) * 8))); + } else if (OperationWidth == EfiCpuIoWidthUint16) { + if (((Address & 0x3) == 1) || ((Address & 0x3) == 3)) { + return EFI_INVALID_PARAMETER; + } + Uint32Buffer = MmioRead32((UINTN)(Address & (~0x3))); + Uint32Buffer &= (0xFFFF << ((Address & 0x3) * 8)); + *(UINT16 *)Uint8Buffer = (UINT16)(Uint32Buffer >> (((Address & 0x3) * 8))); + } else if (OperationWidth == EfiCpuIoWidthUint32) { + *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address); + } else if (OperationWidth == EfiCpuIoWidthUint64) { + *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address); + } + } + return EFI_SUCCESS; +} + +/** + Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space. + + The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration + registers for a PCI controller. + The PCI Configuration operations are carried out exactly as requested. The caller is responsible for + any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might + require. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Width Signifies the width of the memory operations. + @param[in] Address The address within the PCI configuration space for the PCI controller. + @param[in] Count The number of PCI configuration operations to perform. Bytes + moved is Width size * Count, starting at Address. + @param[out] Buffer For read operations, the destination buffer to store the results. For + write operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. + @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoPciRead ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 EfiAddress, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + UINT32 Offset; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *EfiPciAddress; + UINT64 Address; + PCI_ROOT_BRIDGE_INSTANCE *PrivateData; + + EfiPciAddress = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&EfiAddress; + PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Width >= EfiPciWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + if (EfiPciAddress->ExtendedRegister) { + Offset = EfiPciAddress->ExtendedRegister; + } else { + Offset = EfiPciAddress->Register; + } + + PCIE_DEBUG ("[%a:%d] - bus %x dev %x func %x Off %x\n", __FUNCTION__, __LINE__, + EfiPciAddress->Bus, + EfiPciAddress->Device, + EfiPciAddress->Function, + Offset + ); + if (EfiPciAddress->Bus < PrivateData->BusBase || EfiPciAddress->Bus > PrivateData->BusLimit) { + PCIE_DEBUG ("[%a:%d] - Bus number out of range %d\n", __FUNCTION__, __LINE__, EfiPciAddress->Bus); + SetMem (Buffer, mOutStride[Width] * Count, 0xFF); + return EFI_INVALID_PARAMETER; + } + + // The UEFI PCI enumerator scans for devices at all possible addresses, + // and ignores some PCI rules - this results in some hardware being + // detected multiple times. We work around this by faking absent + // devices + if(EfiPciAddress->Bus == PrivateData->BusBase) + { + if((EfiPciAddress->Device != 0x0) || (EfiPciAddress->Function != 0)) { + SetMem (Buffer, mOutStride[Width] * Count, 0xFF); + return EFI_UNSUPPORTED; + } + } + + if (EfiPciAddress->Bus == PrivateData->BusBase){ + Address = PrivateData->RbPciBar + Offset; + } + else if(EfiPciAddress->Bus == PrivateData->BusBase + 1) + { + if (!PcieIsLinkUp(PrivateData->SocType,PrivateData->RbPciBar, PrivateData->Port)) + { + SetMem (Buffer, mOutStride[Width] * Count, 0xFF); + return EFI_NOT_READY; + } + Address = GetPcieCfgAddress ( + PrivateData->Ecam, + EfiPciAddress->Bus, + EfiPciAddress->Device, + EfiPciAddress->Function, + Offset + ); + } + else + { + Address = GetPcieCfgAddress ( + PrivateData->Ecam, + EfiPciAddress->Bus, + EfiPciAddress->Device, + EfiPciAddress->Function, + Offset + ); + } + + (VOID)CpuMemoryServiceRead((EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer); + PCIE_DEBUG ("[%a:%d] - %x\n", __FUNCTION__, __LINE__, *(UINT32 *)Buffer); + + return EFI_SUCCESS; +} + +/** + Writes memory-mapped registers. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number of + bytes moved is Width size * Count, starting at Address. + @param[in] Buffer For read operations, the destination buffer to store the results. + For write operations, the source buffer from which to write data. + + @retval EFI_SUCCESS The data was read from or written to the PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. + @retval EFI_UNSUPPORTED The address range specified by Address, Width, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +CpuMemoryServiceWrite ( + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + UINT8 InStride; + UINT8 OutStride; + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; + UINT8 *Uint8Buffer; + UINT32 Uint32Buffer; + + // + // Select loop based on the width of the transfer + // + InStride = mInStride[Width]; + OutStride = mOutStride[Width]; + OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); + for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { + if (OperationWidth == EfiCpuIoWidthUint8) { + Uint32Buffer = MmioRead32 ((UINTN)(Address & (~0x03))); + Uint32Buffer &= ~(UINT32)(0xFF << ((Address & 0x3) * 8)); + Uint32Buffer |= (UINT32)(*(UINT8 *)Uint8Buffer) << ((Address & 0x3) * 8); + MmioWrite32 ((UINTN)(Address & (~0x03)), Uint32Buffer); + } else if (OperationWidth == EfiCpuIoWidthUint16) { + if (((Address & 0x3) == 1) || ((Address & 0x3) == 3)) { + return EFI_INVALID_PARAMETER; + } + Uint32Buffer = MmioRead32 ((UINTN)(Address & (~0x03))); + Uint32Buffer &= ~(UINT32)(0xFFFF << ((Address & 0x3) * 8)); + Uint32Buffer |= (UINT32)(*(UINT16 *)Uint8Buffer) << ((Address & 0x3) * 8); + MmioWrite32 ((UINTN)(Address & (~0x03)), Uint32Buffer); + } else if (OperationWidth == EfiCpuIoWidthUint32) { + MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); + } else if (OperationWidth == EfiCpuIoWidthUint64) { + MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer)); + } + } + return EFI_SUCCESS; +} + +/** + Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space. + + The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration + registers for a PCI controller. + The PCI Configuration operations are carried out exactly as requested. The caller is responsible for + any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might + require. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Width Signifies the width of the memory operations. + @param[in] Address The address within the PCI configuration space for the PCI controller. + @param[in] Count The number of PCI configuration operations to perform. Bytes + moved is Width size * Count, starting at Address. + @param[in] Buffer For read operations, the destination buffer to store the results. For + write operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. + @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoPciWrite ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 EfiAddress, + IN UINTN Count, + IN VOID *Buffer + ) +{ + UINT32 Offset; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *EfiPciAddress; + UINT64 Address; + PCI_ROOT_BRIDGE_INSTANCE *PrivateData; + + EfiPciAddress = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&EfiAddress; + PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Width >= EfiPciWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + if (EfiPciAddress->ExtendedRegister) + Offset = EfiPciAddress->ExtendedRegister; + else + Offset = EfiPciAddress->Register; + + PCIE_DEBUG ("[%a:%d] - bus %x dev %x func %x Off %x\n", __FUNCTION__, __LINE__, + EfiPciAddress->Bus, + EfiPciAddress->Device, + EfiPciAddress->Function, + Offset + ); + if (((EfiPciAddress->Bus == PrivateData->BusBase) && (EfiPciAddress->Device == 0x00) && (EfiPciAddress->Function == 0))){ + Address = PrivateData->RbPciBar + Offset; + if ((Offset == 0x14) || (Offset == 0x10)) { + return EFI_SUCCESS; + } + } + else if (EfiPciAddress->Bus == PrivateData->BusBase + 1) + { + if (!PcieIsLinkUp(PrivateData->SocType,PrivateData->RbPciBar, PrivateData->Port)) { + return EFI_NOT_READY; + } + Address = GetPcieCfgAddress ( + PrivateData->Ecam, + EfiPciAddress->Bus, + EfiPciAddress->Device, + EfiPciAddress->Function, + Offset + ); + } + else + { + Address = GetPcieCfgAddress ( + PrivateData->Ecam, + EfiPciAddress->Bus, + EfiPciAddress->Device, + EfiPciAddress->Function, + Offset + ); + } + + (VOID)CpuMemoryServiceWrite ((EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer); + PCIE_DEBUG ("[%a:%d] - 0x%08x\n", __FUNCTION__, __LINE__, *(UINT32 *)Buffer); + return EFI_SUCCESS; +} + +/** + Provides the PCI controller-specific addresses required to access system memory from a + DMA bus master. + + The Map() function provides the PCI controller specific addresses needed to access system + memory. This function is used to map system memory for PCI bus master DMA accesses. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Operation Indicates if the bus master is going to read or write to system memory. + @param[in] HostAddress The system memory address to map to the PCI controller. + @param[in, out] NumberOfBytes On input the number of bytes to map. On output the number of bytes that were mapped. + @param[out] DeviceAddress The resulting map address for the bus master PCI controller to use + to access the system memory's HostAddress. + @param[out] Mapping The value to pass to Unmap() when the bus master DMA operation is complete. + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_INVALID_PARAMETER Operation is invalid. + @retval EFI_INVALID_PARAMETER HostAddress is NULL. + @retval EFI_INVALID_PARAMETER NumberOfBytes is NULL. + @retval EFI_INVALID_PARAMETER DeviceAddress is NULL. + @retval EFI_INVALID_PARAMETER Mapping is NULL. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoMap ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + DMA_MAP_OPERATION DmaOperation; + + if (Operation == EfiPciOperationBusMasterRead) { + DmaOperation = MapOperationBusMasterRead; + } else if (Operation == EfiPciOperationBusMasterWrite) { + DmaOperation = MapOperationBusMasterWrite; + } else if (Operation == EfiPciOperationBusMasterCommonBuffer) { + DmaOperation = MapOperationBusMasterCommonBuffer; + } else if (Operation == EfiPciOperationBusMasterRead64) { + DmaOperation = MapOperationBusMasterRead; + } else if (Operation == EfiPciOperationBusMasterWrite64) { + DmaOperation = MapOperationBusMasterWrite; + } else if (Operation == EfiPciOperationBusMasterCommonBuffer64) { + DmaOperation = MapOperationBusMasterCommonBuffer; + } else { + return EFI_INVALID_PARAMETER; + } + (VOID)DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping); + return EFI_SUCCESS; +} + +/** + Completes the Map() operation and releases any corresponding resources. + + The Unmap() function completes the Map() operation and releases any corresponding resources. + If the operation was an EfiPciOperationBusMasterWrite or + EfiPciOperationBusMasterWrite64, the data is committed to the target system memory. + Any resources used for the mapping are freed. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Mapping The mapping value returned from Map(). + + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map(). + @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoUnmap ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN VOID *Mapping + ) +{ + return DmaUnmap (Mapping); +} + +/** + Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or + EfiPciOperationBusMasterCommonBuffer64 mapping. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Type This parameter is not used and must be ignored. + @param MemoryType The type of memory to allocate, EfiBootServicesData or EfiRuntimeServicesData. + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system memory address of the allocated range. + @param Attributes The requested bit mask of attributes for the allocated range. Only + the attributes EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_ATTRIBUTE_MEMORY_CACHED, + and EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this function. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_INVALID_PARAMETER MemoryType is invalid. + @retval EFI_INVALID_PARAMETER HostAddress is NULL. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are + MEMORY_WRITE_COMBINE, MEMORY_CACHED, and DUAL_ADDRESS_CYCLE. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoAllocateBuffer ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ) +{ + if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) { + return EFI_UNSUPPORTED; + } + + return DmaAllocateBuffer (MemoryType, Pages, HostAddress); + +} + +/** + Frees memory that was allocated with AllocateBuffer(). + + The FreeBuffer() function frees memory that was allocated with AllocateBuffer(). + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allocated range. + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages + was not allocated with AllocateBuffer(). + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoFreeBuffer ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN UINTN Pages, + OUT VOID *HostAddress + ) +{ + return DmaFreeBuffer (Pages, HostAddress); +} + +/** + Flushes all PCI posted write transactions from a PCI host bridge to system memory. + + The Flush() function flushes any PCI posted write transactions from a PCI host bridge to system + memory. Posted write transactions are generated by PCI bus masters when they perform write + transactions to target addresses in system memory. + This function does not flush posted write transactions from any PCI bridges. A PCI controller + specific action must be taken to guarantee that the posted write transactions have been flushed from + the PCI controller and from all the PCI bridges into the PCI host bridge. This is typically done with + a PCI read transaction from the PCI controller prior to calling Flush(). + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + + @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host + bridge to system memory. + @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI + host bridge due to a hardware error. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoFlush ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This + ) +{ + // + // not supported yet + // + return EFI_SUCCESS; +} + +/** + Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the + attributes that a PCI root bridge is currently using. + + The GetAttributes() function returns the mask of attributes that this PCI root bridge supports + and the mask of attributes that the PCI root bridge is currently using. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Supported A pointer to the mask of attributes that this PCI root bridge + supports setting with SetAttributes(). + @param Attributes A pointer to the mask of attributes that this PCI root bridge is + currently using. + + @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI root + bridge supports is returned in Supports. If Attributes is + not NULL, then the attributes that the PCI root bridge is currently + using is returned in Attributes. + @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL. + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoGetAttributes ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + OUT UINT64 *Supported, + OUT UINT64 *Attributes + ) +{ + PCI_ROOT_BRIDGE_INSTANCE *PrivateData; + + PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); + + if (Attributes == NULL && Supported == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Set the return value for Supported and Attributes + // + if (Supported != NULL) { + *Supported = PrivateData->Supports; + } + + if (Attributes != NULL) { + *Attributes = PrivateData->Attributes; + } + + return EFI_SUCCESS; +} + +/** + Sets attributes for a resource range on a PCI root bridge. + + The SetAttributes() function sets the attributes specified in Attributes for the PCI root + bridge on the resource range specified by ResourceBase and ResourceLength. Since the + granularity of setting these attributes may vary from resource type to resource type, and from + platform to platform, the actual resource range and the one passed in by the caller may differ. As a + result, this function may set the attributes specified by Attributes on a larger resource range + than the caller requested. The actual range is returned in ResourceBase and + ResourceLength. The caller is responsible for verifying that the actual range for which the + attributes were set is acceptable. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[in] Attributes The mask of attributes to set. If the attribute bit + MEMORY_WRITE_COMBINE, MEMORY_CACHED, or + MEMORY_DISABLE is set, then the resource range is specified by + ResourceBase and ResourceLength. If + MEMORY_WRITE_COMBINE, MEMORY_CACHED, and + MEMORY_DISABLE are not set, then ResourceBase and + ResourceLength are ignored, and may be NULL. + @param[in, out] ResourceBase A pointer to the base address of the resource range to be modified + by the attributes specified by Attributes. + @param[in, out] ResourceLength A pointer to the length of the resource range to be modified by the + attributes specified by Attributes. + + @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in Resources. + @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved. + @retval EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoSetAttributes ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN UINT64 Attributes, + IN OUT UINT64 *ResourceBase, + IN OUT UINT64 *ResourceLength + ) +{ + PCI_ROOT_BRIDGE_INSTANCE *PrivateData; + + PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); + + if (Attributes != 0) { + if ((Attributes & (~(PrivateData->Supports))) != 0) { + return EFI_UNSUPPORTED; + } + } + + // + // This is a generic driver for a PC-AT class system. It does not have any + // chipset specific knowlegde, so none of the attributes can be set or + // cleared. Any attempt to set attribute that are already set will succeed, + // and any attempt to set an attribute that is not supported will fail. + // + if (Attributes & (~PrivateData->Attributes)) { + /* FIXME: */ + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0 + resource descriptors. + + There are only two resource descriptor types from the ACPI Specification that may be used to + describe the current resources allocated to a PCI root bridge. These are the QWORD Address + Space Descriptor (ACPI 2.0 Section 6.4.3.5.1), and the End Tag (ACPI 2.0 Section 6.4.2.8). The + QWORD Address Space Descriptor can describe memory, I/O, and bus number ranges for dynamic + or fixed resources. The configuration of a PCI root bridge is described with one or more QWORD + Address Space Descriptors followed by an End Tag. + + @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param[out] Resources A pointer to the ACPI 2.0 resource descriptors that describe the + current configuration of this PCI root bridge. The storage for the + ACPI 2.0 resource descriptors is allocated by this function. The + caller must treat the return buffer as read-only data, and the buffer + must not be freed by the caller. + + @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in Resources. + @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved. + @retval EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL + +**/ +EFI_STATUS +EFIAPI +RootBridgeIoConfiguration ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + OUT VOID **Resources + ) +{ + PCI_ROOT_BRIDGE_INSTANCE *PrivateData; + UINTN Index; + + PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This); + for (Index = 0; Index < TypeMax; Index++) { + if (PrivateData->ResAllocNode[Index].Status == ResAllocated) { + Configuration.SpaceDesp[Index].AddrRangeMin = PrivateData->ResAllocNode[Index].Base; + Configuration.SpaceDesp[Index].AddrRangeMax = PrivateData->ResAllocNode[Index].Base + PrivateData->ResAllocNode[Index].Length - 1; + Configuration.SpaceDesp[Index].AddrLen = PrivateData->ResAllocNode[Index].Length; + } + } + + *Resources = &Configuration; + return EFI_SUCCESS; +} + diff --git a/Silicon/Hisilicon/Drivers/SasV1Dxe/SasV1Dxe.c b/Silicon/Hisilicon/Drivers/SasV1Dxe/SasV1Dxe.c new file mode 100644 index 0000000000..18085c43c5 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/SasV1Dxe/SasV1Dxe.c @@ -0,0 +1,1049 @@ +/** @file + + Copyright (c) 2016 Linaro Ltd. + Copyright (c) 2016 Hisilicon Limited. + + 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. + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define READ_REG32(Base, Offset) MmioRead32 ((Base) + (Offset)) +#define WRITE_REG32(Base, Offset, Val) MmioWrite32 ((Base) + (Offset), (Val)) + +#define PHY_READ_REG32(Base, Offset, phy) MmioRead32 ((Base) + (Offset) + 0x400 * (phy)) +#define PHY_WRITE_REG32(Base, Offset, phy, Val) MmioWrite32 ((Base) + (Offset) + 0x400 * (phy), (Val)) + +#define DLVRY_QUEUE_ENABLE 0x0 +#define IOST_BASE_ADDR_LO 0x8 +#define IOST_BASE_ADDR_HI 0xc +#define ITCT_BASE_ADDR_LO 0x10 +#define ITCT_BASE_ADDR_HI 0x14 +#define BROKEN_MSG_ADDR_LO 0x18 +#define BROKEN_MSG_ADDR_HI 0x1c +#define PHY_CONTEXT 0x20 +#define PHY_PORT_NUM_MA 0x28 +#define HGC_TRANS_TASK_CNT_LIMIT 0x38 +#define AXI_AHB_CLK_CFG 0x3c +#define HGC_SAS_TXFAIL_RETRY_CTRL 0x84 +#define HGC_GET_ITV_TIME 0x90 +#define DEVICE_MSG_WORK_MODE 0x94 +#define I_T_NEXUS_LOSS_TIME 0xa0 +#define BUS_INACTIVE_LIMIT_TIME 0xa8 +#define REJECT_TO_OPEN_LIMIT_TIME 0xac +#define CFG_AGING_TIME 0xbc +#define HGC_DFX_CFG2 0xc0 +#define FIS_LIST_BADDR_L 0xc4 +#define CFG_1US_TIMER_TRSH 0xcc +#define CFG_SAS_CONFIG 0xd4 +#define INT_COAL_EN 0x1bc +#define OQ_INT_COAL_TIME 0x1c0 +#define OQ_INT_COAL_CNT 0x1c4 +#define ENT_INT_COAL_TIME 0x1c8 +#define ENT_INT_COAL_CNT 0x1cc +#define OQ_INT_SRC 0x1d0 +#define OQ_INT_SRC_MSK 0x1d4 +#define ENT_INT_SRC1 0x1d8 +#define ENT_INT_SRC2 0x1dc +#define ENT_INT_SRC_MSK1 0x1e0 +#define ENT_INT_SRC_MSK2 0x1e4 +#define SAS_ECC_INTR_MSK 0x1ec +#define HGC_ERR_STAT_EN 0x238 +#define DLVRY_Q_0_BASE_ADDR_LO 0x260 +#define DLVRY_Q_0_BASE_ADDR_HI 0x264 +#define DLVRY_Q_0_DEPTH 0x268 +#define DLVRY_Q_0_WR_PTR 0x26c +#define DLVRY_Q_0_RD_PTR 0x270 +#define COMPL_Q_0_BASE_ADDR_LO 0x4e0 +#define COMPL_Q_0_BASE_ADDR_HI 0x4e4 +#define COMPL_Q_0_DEPTH 0x4e8 +#define COMPL_Q_0_WR_PTR 0x4ec +#define COMPL_Q_0_RD_PTR 0x4f0 +#define AXI_CFG 0x5100 + +#define PORT_BASE 0x800 +#define PHY_CFG (PORT_BASE + 0x0) +#define PHY_CFG_ENA_OFF 0 +#define PHY_CFG_ENA_MSK (0x1 << PHY_CFG_ENA_OFF) +#define PHY_CFG_DC_OPT_OFF 2 +#define PHY_CFG_DC_OPT_MSK (0x1 << PHY_CFG_DC_OPT_OFF) +#define PROG_PHY_LINK_RATE (PORT_BASE + 0xc) +#define PHY_CTRL (PORT_BASE + 0x14) +#define PHY_CTRL_RESET BIT0 +#define PHY_RATE_NEGO (PORT_BASE + 0x30) +#define PHY_PCN (PORT_BASE + 0x44) +#define SL_TOUT_CFG (PORT_BASE + 0x8c) +#define SL_CONTROL (PORT_BASE + 0x94) +#define SL_CONTROL_NOTIFY_EN BIT0 +#define TX_ID_DWORD0 (PORT_BASE + 0x9c) +#define TX_ID_DWORD1 (PORT_BASE + 0xa0) +#define TX_ID_DWORD2 (PORT_BASE + 0xa4) +#define TX_ID_DWORD3 (PORT_BASE + 0xa8) +#define TX_ID_DWORD4 (PORT_BASE + 0xaC) +#define TX_ID_DWORD5 (PORT_BASE + 0xb0) +#define TX_ID_DWORD6 (PORT_BASE + 0xb4) +#define RX_IDAF_DWORD3 (PORT_BASE + 0xd0) +#define RX_IDAF_DWORD4 (PORT_BASE + 0xd4) +#define RXOP_CHECK_CFG_H (PORT_BASE + 0xfc) +#define DONE_RECEIVED_TIME (PORT_BASE + 0x12c) +#define CON_CFG_DRIVER (PORT_BASE + 0x130) +#define PHY_CONFIG2 (PORT_BASE + 0x1a8) +#define PHY_CONFIG2_FORCE_TXDEEMPH_OFF 3 +#define PHY_CONFIG2_FORCE_TXDEEMPH_MSK (0x1 << PHY_CONFIG2_FORCE_TXDEEMPH_OFF) +#define CHL_INT_COAL_EN (PORT_BASE + 0x1d0) +#define CHL_INT0 (PORT_BASE + 0x1b0) +#define CHL_INT0_PHYCTRL_NOTRDY BIT0 +#define CHL_INT1 (PORT_BASE + 0x1b4) +#define CHL_INT2 (PORT_BASE + 0x1b8) +#define CHL_INT2_SL_PHY_ENA BIT6 +#define CHL_INT0_MSK (PORT_BASE + 0x1bc) +#define CHL_INT0_MSK_PHYCTRL_NOTRDY BIT0 +#define CHL_INT1_MSK (PORT_BASE + 0x1c0) +#define CHL_INT2_MSK (PORT_BASE + 0x1c4) +#define DMA_TX_STATUS (PORT_BASE + 0x2d0) +#define DMA_TX_STATUS_BUSY BIT0 +#define DMA_RX_STATUS (PORT_BASE + 0x2e8) +#define DMA_RX_STATUS_BUSY BIT0 + +#define QUEUE_CNT 32 +#define QUEUE_SLOTS 256 +#define SLOT_ENTRIES 8192 +#define PHY_CNT 8 +#define MAX_ITCT_ENTRIES 1 + +// Completion header +#define CMPLT_HDR_IPTT_OFF 0 +#define CMPLT_HDR_IPTT_MSK (0xffff << CMPLT_HDR_IPTT_OFF) + +#define BIT(x) (1 << x) + +// HW dma structures +// Delivery queue header +// dw0 +#define CMD_HDR_RESP_REPORT_OFF 5 +#define CMD_HDR_RESP_REPORT_MSK 0x20 +#define CMD_HDR_TLR_CTRL_OFF 6 +#define CMD_HDR_TLR_CTRL_MSK 0xc0 +#define CMD_HDR_PORT_OFF 17 +#define CMD_HDR_PORT_MSK 0xe0000 +#define CMD_HDR_PRIORITY_OFF 27 +#define CMD_HDR_PRIORITY_MSK 0x8000000 +#define CMD_HDR_MODE_OFF 28 +#define CMD_HDR_MODE_MSK 0x10000000 +#define CMD_HDR_CMD_OFF 29 +#define CMD_HDR_CMD_MSK 0xe0000000 +// dw1 +#define CMD_HDR_VERIFY_DTL_OFF 10 +#define CMD_HDR_VERIFY_DTL_MSK 0x400 +#define CMD_HDR_SSP_FRAME_TYPE_OFF 13 +#define CMD_HDR_SSP_FRAME_TYPE_MSK 0xe000 +#define CMD_HDR_DEVICE_ID_OFF 16 +#define CMD_HDR_DEVICE_ID_MSK 0xffff0000 +// dw2 +#define CMD_HDR_CFL_OFF 0 +#define CMD_HDR_CFL_MSK 0x1ff +#define CMD_HDR_MRFL_OFF 15 +#define CMD_HDR_MRFL_MSK 0xff8000 +#define CMD_HDR_FIRST_BURST_OFF 25 +#define CMD_HDR_FIRST_BURST_MSK 0x2000000 +// dw3 +#define CMD_HDR_IPTT_OFF 0 +#define CMD_HDR_IPTT_MSK 0xffff +// dw6 +#define CMD_HDR_DATA_SGL_LEN_OFF 16 +#define CMD_HDR_DATA_SGL_LEN_MSK 0xffff0000 + +// Completion header +#define CMPLT_HDR_IPTT_OFF 0 +#define CMPLT_HDR_IPTT_MSK (0xffff << CMPLT_HDR_IPTT_OFF) +#define CMPLT_HDR_CMD_CMPLT_MSK BIT17 +#define CMPLT_HDR_ERR_RCRD_XFRD_MSK BIT18 +#define CMPLT_HDR_RSPNS_XFRD_MSK BIT19 +#define CMPLT_HDR_IO_CFG_ERR_MSK BIT27 + +#define SENSE_DATA_PRES 26 + +#define SGE_LIMIT 0x10000 +#define upper_32_bits(n) ((UINT32)(((n) >> 16) >> 16)) +#define lower_32_bits(n) ((UINT32)(n)) +#define MAX_TARGET_ID 4 + +// Generic HW DMA host memory structures +struct hisi_sas_cmd_hdr { + UINT32 dw0; + UINT32 dw1; + UINT32 dw2; + UINT32 transfer_tags; + UINT32 data_transfer_len; + UINT32 first_burst_num; + UINT32 sg_len; + UINT32 dw7; + UINT64 cmd_table_addr; + UINT64 sts_buffer_addr; + UINT64 prd_table_addr; + UINT64 dif_prd_table_addr; +}; + +struct hisi_sas_complete_hdr { + UINT32 data; +}; + +struct hisi_sas_iost { + UINT64 qw0; + UINT64 qw1; + UINT64 qw2; + UINT64 qw3; +}; + +struct hisi_sas_itct { + UINT64 qw0; + UINT64 sas_addr; + UINT64 qw2; + UINT64 qw3; + UINT64 qw4; + UINT64 qw_sata_ncq0_3; + UINT64 qw_sata_ncq7_4; + UINT64 qw_sata_ncq11_8; + UINT64 qw_sata_ncq15_12; + UINT64 qw_sata_ncq19_16; + UINT64 qw_sata_ncq23_20; + UINT64 qw_sata_ncq27_24; + UINT64 qw_sata_ncq31_28; + UINT64 qw_non_ncq_iptt; + UINT64 qw_rsvd0; + UINT64 qw_rsvd1; +}; + +struct hisi_sas_breakpoint { + UINT8 data[128]; +}; + +struct hisi_sas_sge { + UINT64 addr; + UINT32 page_ctrl_0; + UINT32 page_ctrl_1; + UINT32 data_len; + UINT32 data_off; +}; + +struct hisi_sas_sge_page { + struct hisi_sas_sge sg[512]; +}; + +struct hisi_sas_cmd { + UINT8 cmd[128]; +}; + +struct hisi_sas_sts { +UINT32 status[260]; +}; + +struct hisi_sas_slot { + BOOLEAN used; +}; + +struct hisi_hba { + struct hisi_sas_cmd_hdr *cmd_hdr[QUEUE_CNT]; + struct hisi_sas_complete_hdr *complete_hdr[QUEUE_CNT]; + struct hisi_sas_sge_page *sge[QUEUE_CNT]; + struct hisi_sas_sts *status_buf[QUEUE_CNT]; + struct hisi_sas_cmd *command_table[QUEUE_CNT]; + struct hisi_sas_iost *iost; + struct hisi_sas_itct *itct; + struct hisi_sas_breakpoint *breakpoint; + struct hisi_sas_slot *slots; + UINT32 base; + int queue; + int port_id; + UINT32 LatestTargetId; + UINT64 LatestLun; +}; + +#pragma pack (1) +typedef struct { + VENDOR_DEVICE_PATH Vendor; + UINT64 PhysBase; + EFI_DEVICE_PATH_PROTOCOL End; +} SAS_V1_TRANSPORT_DEVICE_PATH; +#pragma pack () + +typedef struct { + UINT32 Signature; + EFI_EXT_SCSI_PASS_THRU_MODE ExtScsiPassThruMode; + EFI_EXT_SCSI_PASS_THRU_PROTOCOL ExtScsiPassThru; + SAS_V1_TRANSPORT_DEVICE_PATH *DevicePath; + struct hisi_hba *hba; + EFI_EVENT TimerEvent; +} SAS_V1_INFO; + +#define SAS_DEVICE_SIGNATURE SIGNATURE_32 ('S','A','S','0') +#define SAS_FROM_PASS_THRU(a) CR (a, SAS_V1_INFO, ExtScsiPassThru, SAS_DEVICE_SIGNATURE) + +STATIC EFI_STATUS prepare_cmd ( + struct hisi_hba *hba, + EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet + ) +{ + struct hisi_sas_slot *slot; + struct hisi_sas_cmd_hdr *hdr; + struct hisi_sas_sge_page *sge; + struct hisi_sas_sts *sts; + struct hisi_sas_cmd *cmd; + EFI_SCSI_SENSE_DATA *SensePtr = Packet->SenseData; + VOID *Buffer = NULL; + UINTN BufferSize = 0; + int queue = hba->queue; + UINT32 r, w = 0, slot_idx = 0; + UINT32 base = hba->base; + UINT8 *p; + EFI_PHYSICAL_ADDRESS BufferAddress; + EFI_STATUS Status = EFI_SUCCESS; + VOID *BufferMap = NULL; + DMA_MAP_OPERATION DmaOperation = MapOperationBusMasterCommonBuffer; + + while (1) { + w = READ_REG32(base, DLVRY_Q_0_WR_PTR + (queue * 0x14)); + r = READ_REG32(base, DLVRY_Q_0_RD_PTR + (queue * 0x14)); + slot_idx = queue * QUEUE_SLOTS + w; + slot = &hba->slots[slot_idx]; + if (slot->used || (r == (w+1) % QUEUE_SLOTS)) { + queue = (queue + 1) % QUEUE_CNT; + if (queue == hba->queue) { + DEBUG ((EFI_D_ERROR, "could not find free slot\n")); + return EFI_NOT_READY; + } + continue; + } + break; + } + + hdr = &hba->cmd_hdr[queue][w]; + cmd = &hba->command_table[queue][w]; + sts = &hba->status_buf[queue][w]; + sge = &hba->sge[queue][w]; + + ZeroMem (cmd, sizeof (struct hisi_sas_cmd)); + ZeroMem (sts, sizeof (struct hisi_sas_sts)); + if (SensePtr) + ZeroMem (SensePtr, sizeof (EFI_SCSI_SENSE_DATA)); + + slot->used = TRUE; + hba->queue = (queue + 1) % QUEUE_CNT; + + // Only consider ssp + hdr->dw0 = (1 << CMD_HDR_RESP_REPORT_OFF) | + (0x2 << CMD_HDR_TLR_CTRL_OFF) | + (hba->port_id << CMD_HDR_PORT_OFF) | + (1 << CMD_HDR_MODE_OFF) | + (1 << CMD_HDR_CMD_OFF); + hdr->dw1 = 1 << CMD_HDR_VERIFY_DTL_OFF; + hdr->dw1 |= 0 << CMD_HDR_DEVICE_ID_OFF; + hdr->dw2 = 0x83000d; + hdr->transfer_tags = slot_idx << CMD_HDR_IPTT_OFF; + + if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) { + Buffer = Packet->InDataBuffer; + BufferSize = Packet->InTransferLength; + if (Buffer) { + hdr->dw1 |= 1 << CMD_HDR_SSP_FRAME_TYPE_OFF; + DmaOperation = MapOperationBusMasterWrite; + } + } else if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE) { + Buffer = Packet->OutDataBuffer; + BufferSize = Packet->OutTransferLength; + if (Buffer) { + DmaOperation = MapOperationBusMasterRead; + hdr->dw1 |= 2 << CMD_HDR_SSP_FRAME_TYPE_OFF; + } + } else { + hdr->dw1 |= 0 << CMD_HDR_SSP_FRAME_TYPE_OFF; + } + + hdr->data_transfer_len = BufferSize; + hdr->cmd_table_addr = (UINT64)cmd; + hdr->sts_buffer_addr = (UINT64)sts; + + CopyMem (&cmd->cmd[36], Packet->Cdb, Packet->CdbLength); + + if (Buffer != NULL) { + struct hisi_sas_sge *sg; + UINT32 remain, len, pos = 0, i = 0; + + Status = DmaMap (DmaOperation, Buffer, &BufferSize, &BufferAddress, &BufferMap); + if (EFI_ERROR (Status)) { + return Status; + } + remain = len = BufferSize; + + while (remain) { + if (len > SGE_LIMIT) + len = SGE_LIMIT; + sg = &sge->sg[i]; + sg->addr = (UINT64)(BufferAddress + pos); + sg->page_ctrl_0 = sg->page_ctrl_1 = 0; + sg->data_len = len; + sg->data_off = 0; + remain -= len; + pos += len; + len = remain; + i++; + } + + hdr->prd_table_addr = (UINT64)sge; + hdr->sg_len = i << CMD_HDR_DATA_SGL_LEN_OFF; + } + + // Ensure descriptor effective before start dma + MemoryFence(); + + // Start dma + WRITE_REG32(base, DLVRY_Q_0_WR_PTR + queue * 0x14, ++w % QUEUE_SLOTS); + + // Wait for dma complete + while (slot->used) { + if (READ_REG32(base, OQ_INT_SRC) & BIT(queue)) { + struct hisi_sas_complete_hdr *complete_hdr; + UINT32 data, rd; + rd = READ_REG32(base, COMPL_Q_0_RD_PTR + (0x14 * queue)); + + complete_hdr = &hba->complete_hdr[queue][rd]; + data = complete_hdr->data; + + // Check whether dma transfer error + if ((data & CMPLT_HDR_ERR_RCRD_XFRD_MSK) && + !(data & CMPLT_HDR_RSPNS_XFRD_MSK)) { + DEBUG ((EFI_D_VERBOSE, "sas retry data=0x%x\n", data)); + DEBUG ((EFI_D_VERBOSE, "sts[0]=0x%x\n", sts->status[0])); + DEBUG ((EFI_D_VERBOSE, "sts[1]=0x%x\n", sts->status[1])); + DEBUG ((EFI_D_VERBOSE, "sts[2]=0x%x\n", sts->status[2])); + Status = EFI_NOT_READY; + // wait 1 second and retry, some disk need long time to be ready + // and ScsiDisk treat retry over 3 times as error + MicroSecondDelay(1000000); + } + // Update read point + WRITE_REG32(base, COMPL_Q_0_RD_PTR + (0x14 * queue), w); + // Clear int + WRITE_REG32(base, OQ_INT_SRC, BIT(queue)); + slot->used = FALSE; + break; + } + // Wait for status change in polling + NanoSecondDelay (100); + } + + if (BufferMap) + DmaUnmap (BufferMap); + + p = (UINT8 *)&sts->status[0]; + if (p[SENSE_DATA_PRES]) { + // Disk not ready normal return for ScsiDiskTestUnitReady do next try + SensePtr->Sense_Key = EFI_SCSI_SK_NOT_READY; + SensePtr->Addnl_Sense_Code = EFI_SCSI_ASC_NOT_READY; + SensePtr->Addnl_Sense_Code_Qualifier = EFI_SCSI_ASCQ_IN_PROGRESS; + // wait 1 second for disk spin up, refer drivers/scsi/sd.c + MicroSecondDelay(1000000); + } + return Status; +} + +STATIC VOID hisi_sas_v1_init(struct hisi_hba *hba, PLATFORM_SAS_PROTOCOL *plat) +{ + int i, j; + UINT32 val, base = hba->base; + + // Reset + for (i = 0; i < PHY_CNT; i++) { + UINT32 phy_ctrl = PHY_READ_REG32(base, PHY_CTRL, i); + + phy_ctrl |= PHY_CTRL_RESET; + PHY_WRITE_REG32(base, PHY_CTRL, i, phy_ctrl); + } + // spec says safe to wait 50us after reset + MicroSecondDelay(50); + + // Ensure DMA tx & rx idle + for (i = 0; i < PHY_CNT; i++) { + UINT32 dma_tx_status, dma_rx_status; + + for (j = 0; j < 100; j++) { + dma_tx_status = PHY_READ_REG32(base, DMA_TX_STATUS, i); + dma_rx_status = PHY_READ_REG32(base, DMA_RX_STATUS, i); + + if (!(dma_tx_status & DMA_TX_STATUS_BUSY) && + !(dma_rx_status & DMA_RX_STATUS_BUSY)) + break; + + // Wait for status change in polling + NanoSecondDelay (100); + } + } + + // Ensure axi bus idle + for (j = 0; j < 100; j++) { + UINT32 axi_status = READ_REG32(base, AXI_CFG); + if (axi_status == 0) + break; + + // Wait for status change in polling + NanoSecondDelay (100); + } + + plat->Init(plat); + + WRITE_REG32(base, DLVRY_QUEUE_ENABLE, 0xffffffff); + WRITE_REG32(base, HGC_TRANS_TASK_CNT_LIMIT, 0x11); + WRITE_REG32(base, DEVICE_MSG_WORK_MODE, 0x1); + WRITE_REG32(base, HGC_SAS_TXFAIL_RETRY_CTRL, 0x1ff); + WRITE_REG32(base, HGC_ERR_STAT_EN, 0x401); + WRITE_REG32(base, CFG_1US_TIMER_TRSH, 0x64); + WRITE_REG32(base, HGC_GET_ITV_TIME, 0x1); + WRITE_REG32(base, I_T_NEXUS_LOSS_TIME, 0x64); + WRITE_REG32(base, BUS_INACTIVE_LIMIT_TIME, 0x2710); + WRITE_REG32(base, REJECT_TO_OPEN_LIMIT_TIME, 0x1); + WRITE_REG32(base, CFG_AGING_TIME, 0x7a12); + WRITE_REG32(base, HGC_DFX_CFG2, 0x9c40); + WRITE_REG32(base, FIS_LIST_BADDR_L, 0x2); + WRITE_REG32(base, INT_COAL_EN, 0xc); + WRITE_REG32(base, OQ_INT_COAL_TIME, 0x186a0); + WRITE_REG32(base, OQ_INT_COAL_CNT, 1); + WRITE_REG32(base, ENT_INT_COAL_TIME, 0x1); + WRITE_REG32(base, ENT_INT_COAL_CNT, 0x1); + WRITE_REG32(base, OQ_INT_SRC, 0xffffffff); + WRITE_REG32(base, ENT_INT_SRC1, 0xffffffff); + WRITE_REG32(base, ENT_INT_SRC_MSK1, 0); + WRITE_REG32(base, ENT_INT_SRC2, 0xffffffff); + WRITE_REG32(base, ENT_INT_SRC_MSK2, 0); + WRITE_REG32(base, SAS_ECC_INTR_MSK, 0); + WRITE_REG32(base, AXI_AHB_CLK_CFG, 0x2); + WRITE_REG32(base, CFG_SAS_CONFIG, 0x22000000); + + for (i = 0; i < PHY_CNT; i++) { + PHY_WRITE_REG32(base, PROG_PHY_LINK_RATE, i, 0x88a); + PHY_WRITE_REG32(base, PHY_CONFIG2, i, 0x7c080); + PHY_WRITE_REG32(base, PHY_RATE_NEGO, i, 0x415ee00); + PHY_WRITE_REG32(base, PHY_PCN, i, 0x80a80000); + PHY_WRITE_REG32(base, SL_TOUT_CFG, i, 0x7d7d7d7d); + PHY_WRITE_REG32(base, DONE_RECEIVED_TIME, i, 0x0); + PHY_WRITE_REG32(base, RXOP_CHECK_CFG_H, i, 0x1000); + PHY_WRITE_REG32(base, DONE_RECEIVED_TIME, i, 0); + PHY_WRITE_REG32(base, CON_CFG_DRIVER, i, 0x13f0a); + PHY_WRITE_REG32(base, CHL_INT_COAL_EN, i, 3); + PHY_WRITE_REG32(base, DONE_RECEIVED_TIME, i, 8); + } + + for (i = 0; i < QUEUE_CNT; i++) { + WRITE_REG32(base, DLVRY_Q_0_BASE_ADDR_HI + (i * 0x14), upper_32_bits((UINT64)(hba->cmd_hdr[i]))); + WRITE_REG32(base, DLVRY_Q_0_BASE_ADDR_LO + (i * 0x14), lower_32_bits((UINT64)(hba->cmd_hdr[i]))); + WRITE_REG32(base, DLVRY_Q_0_DEPTH + (i * 0x14), QUEUE_SLOTS); + + WRITE_REG32(base, COMPL_Q_0_BASE_ADDR_HI + (i * 0x14), upper_32_bits((UINT64)(hba->complete_hdr[i]))); + WRITE_REG32(base, COMPL_Q_0_BASE_ADDR_LO + (i * 0x14), lower_32_bits((UINT64)(hba->complete_hdr[i]))); + WRITE_REG32(base, COMPL_Q_0_DEPTH + (i * 0x14), QUEUE_SLOTS); + } + + WRITE_REG32(base, ITCT_BASE_ADDR_LO, lower_32_bits((UINT64)(hba->itct))); + WRITE_REG32(base, ITCT_BASE_ADDR_HI, upper_32_bits((UINT64)(hba->itct))); + + WRITE_REG32(base, IOST_BASE_ADDR_LO, lower_32_bits((UINT64)(hba->iost))); + WRITE_REG32(base, IOST_BASE_ADDR_HI, upper_32_bits((UINT64)(hba->iost))); + + WRITE_REG32(base, BROKEN_MSG_ADDR_LO, lower_32_bits((UINT64)(hba->breakpoint))); + WRITE_REG32(base, BROKEN_MSG_ADDR_HI, upper_32_bits((UINT64)(hba->breakpoint))); + + for (i = 0; i < PHY_CNT; i++) { + // Clear interrupt status + val = PHY_READ_REG32(base, CHL_INT0, i); + PHY_WRITE_REG32(base, CHL_INT0, i, val); + val = PHY_READ_REG32(base, CHL_INT1, i); + PHY_WRITE_REG32(base, CHL_INT1, i, val); + val = PHY_READ_REG32(base, CHL_INT2, i); + PHY_WRITE_REG32(base, CHL_INT2, i, val); + + // Bypass chip bug mask abnormal intr + PHY_WRITE_REG32(base, CHL_INT0_MSK, i, 0x3fffff & ~CHL_INT0_MSK_PHYCTRL_NOTRDY); + } + + // Init phy + for (i = 0; i < PHY_CNT; i++) { + PHY_WRITE_REG32(base, TX_ID_DWORD0, i, 0x10010e00); + PHY_WRITE_REG32(base, TX_ID_DWORD1, i, 0x16); + PHY_WRITE_REG32(base, TX_ID_DWORD2, i, 0x20880150); + PHY_WRITE_REG32(base, TX_ID_DWORD3, i, 0x16); + PHY_WRITE_REG32(base, TX_ID_DWORD4, i, 0x20880150); + PHY_WRITE_REG32(base, TX_ID_DWORD5, i, 0x0); + + val = PHY_READ_REG32(base, PHY_CFG, i); + val &= ~PHY_CFG_DC_OPT_MSK; + val |= 1 << PHY_CFG_DC_OPT_OFF; + PHY_WRITE_REG32(base, PHY_CFG, i, val); + + val = PHY_READ_REG32(base, PHY_CONFIG2, i); + val &= ~PHY_CONFIG2_FORCE_TXDEEMPH_MSK; + PHY_WRITE_REG32(base, PHY_CONFIG2, i, val); + + val = PHY_READ_REG32(base, PHY_CFG, i); + val |= PHY_CFG_ENA_MSK; + PHY_WRITE_REG32(base, PHY_CFG, i, val); + } +} + +STATIC VOID sas_init(SAS_V1_INFO *SasV1Info, PLATFORM_SAS_PROTOCOL *plat) +{ + struct hisi_hba *hba = SasV1Info->hba; + int i, s; + + for (i = 0; i < QUEUE_CNT; i++) { + s = sizeof(struct hisi_sas_cmd_hdr) * QUEUE_SLOTS; + DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->cmd_hdr[i]); + ASSERT (hba->cmd_hdr[i] != NULL); + ZeroMem (hba->cmd_hdr[i], s); + + s = sizeof(struct hisi_sas_complete_hdr) * QUEUE_SLOTS; + DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->complete_hdr[i]); + ASSERT (hba->complete_hdr[i] != NULL); + ZeroMem (hba->complete_hdr[i], s); + + s = sizeof(struct hisi_sas_sts) * QUEUE_SLOTS; + DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->status_buf[i]); + ASSERT (hba->status_buf[i] != NULL); + ZeroMem (hba->status_buf[i], s); + + s = sizeof(struct hisi_sas_cmd) * QUEUE_SLOTS; + DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->command_table[i]); + ASSERT (hba->command_table[i] != NULL); + ZeroMem (hba->command_table[i], s); + + s = sizeof(struct hisi_sas_sge_page) * QUEUE_SLOTS; + DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->sge[i]); + ASSERT (hba->sge[i] != NULL); + ZeroMem (hba->sge[i], s); + } + + s = SLOT_ENTRIES * sizeof(struct hisi_sas_iost); + DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->iost); + ASSERT (hba->iost != NULL); + ZeroMem (hba->iost, s); + + s = SLOT_ENTRIES * sizeof(struct hisi_sas_breakpoint); + DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->breakpoint); + ASSERT (hba->breakpoint != NULL); + ZeroMem (hba->breakpoint, s); + + s = MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct); + DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->itct); + ASSERT (hba->itct != NULL); + ZeroMem (hba->itct, s); + + hba->slots = AllocateZeroPool (SLOT_ENTRIES * sizeof(struct hisi_sas_slot)); + ASSERT (hba->slots != NULL); + + hisi_sas_v1_init(hba, plat); +} + +STATIC +EFI_STATUS +EFIAPI +SasV1ExtScsiPassThruFunction ( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT8 *Target, + IN UINT64 Lun, + IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet, + IN EFI_EVENT Event OPTIONAL + ) +{ + SAS_V1_INFO *SasV1Info = SAS_FROM_PASS_THRU(This); + struct hisi_hba *hba = SasV1Info->hba; + + return prepare_cmd(hba, Packet); +} + +STATIC +EFI_STATUS +EFIAPI +SasV1ExtScsiPassThruGetNextTargetLun ( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, + IN OUT UINT8 **Target, + IN OUT UINT64 *Lun + ) +{ + SAS_V1_INFO *SasV1Info = SAS_FROM_PASS_THRU(This); + struct hisi_hba *hba = SasV1Info->hba; + UINT8 ScsiId[TARGET_MAX_BYTES]; + UINT8 TargetId; + + if (*Target == NULL || Lun == NULL) { + return EFI_INVALID_PARAMETER; + } + + SetMem (ScsiId, TARGET_MAX_BYTES, 0xFF); + + TargetId = (*Target)[0]; + + if (TargetId == MAX_TARGET_ID) { + return EFI_NOT_FOUND; + } + + if (CompareMem(*Target, ScsiId, TARGET_MAX_BYTES) == 0) { + SetMem (*Target, TARGET_MAX_BYTES,0); + } else { + (*Target)[0] = (UINT8) (hba->LatestTargetId + 1); + } + + *Lun = 0; + + // + // Update the LatestTargetId. + // + hba->LatestTargetId = (*Target)[0]; + hba->LatestLun = *Lun; + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +SasV1ExtScsiPassThruBuildDevicePath ( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT8 *Target, + IN UINT64 Lun, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +{ + SAS_V1_INFO *SasV1Info = SAS_FROM_PASS_THRU(This); + + *DevicePath = DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL *)(SasV1Info->DevicePath)); + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +SasV1ExtScsiPassThruGetTargetLun ( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT UINT8 **Target, + OUT UINT64 *Lun + ) +{ + return EFI_UNSUPPORTED; +} + +STATIC +EFI_STATUS +EFIAPI +SasV1ExtScsiPassThruResetChannel ( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This + ) +{ + + return EFI_UNSUPPORTED; +} + +STATIC +EFI_STATUS +EFIAPI +SasV1ExtScsiPassThruResetTarget ( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT8 *Target, + IN UINT64 Lun + ) +{ + + return EFI_UNSUPPORTED; +} + +STATIC +EFI_STATUS +EFIAPI +SasV1ExtScsiPassThruGetNextTarget ( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, + IN OUT UINT8 **Target + ) +{ + + return EFI_UNSUPPORTED; +} + +STATIC EFI_EXT_SCSI_PASS_THRU_PROTOCOL SasV1ExtScsiPassThruProtocolTemplate = { + NULL, + SasV1ExtScsiPassThruFunction, + SasV1ExtScsiPassThruGetNextTargetLun, + SasV1ExtScsiPassThruBuildDevicePath, + SasV1ExtScsiPassThruGetTargetLun, + SasV1ExtScsiPassThruResetChannel, + SasV1ExtScsiPassThruResetTarget, + SasV1ExtScsiPassThruGetNextTarget +}; + +EFI_STATUS +EFIAPI +SasDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + PLATFORM_SAS_PROTOCOL *plat; + EFI_STATUS Status; + + Status = gBS->OpenProtocol ( + Controller, + &gPlatformSasProtocolGuid, + (VOID **) &plat, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Close the Sas Host used to perform the supported test + // + gBS->CloseProtocol ( + Controller, + &gPlatformSasProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +SasDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + PLATFORM_SAS_PROTOCOL *plat; + SAS_V1_INFO *SasV1Info = NULL; + SAS_V1_TRANSPORT_DEVICE_PATH *DevicePath; + UINT32 val, base; + int i, phy_id = 0; + struct hisi_sas_itct *itct; + struct hisi_hba *hba; + + Status = gBS->OpenProtocol ( + Controller, + &gPlatformSasProtocolGuid, + (VOID **) &plat, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + return Status; + } + + SasV1Info = AllocateZeroPool (sizeof (SAS_V1_INFO)); + ASSERT (SasV1Info); + SasV1Info->Signature = SAS_DEVICE_SIGNATURE; + + SasV1Info->hba = AllocateZeroPool (sizeof(struct hisi_hba)); + ASSERT (SasV1Info->hba); + hba = SasV1Info->hba; + base = hba->base = plat->BaseAddr; + + sas_init(SasV1Info, plat); + + // Wait for sas controller phyup happen + MicroSecondDelay(100000); + + for (i = 0; i < PHY_CNT; i++) { + val = PHY_READ_REG32(base, CHL_INT2, i); + + if (val & CHL_INT2_SL_PHY_ENA) { + phy_id = i; + } + } + + itct = &hba->itct[0]; //device_id = 0 + + hba->port_id = (READ_REG32(base, PHY_PORT_NUM_MA) >> (4 * phy_id)) & 0xf; + // Setup itct + itct->qw0 = 0x355; + itct->sas_addr = PHY_READ_REG32(base, RX_IDAF_DWORD3, phy_id); + itct->sas_addr = itct->sas_addr << 32 | PHY_READ_REG32(base, RX_IDAF_DWORD4, phy_id); + itct->qw2 = 0; + + // Clear phyup + PHY_WRITE_REG32(base, CHL_INT2, phy_id, CHL_INT2_SL_PHY_ENA); + val = PHY_READ_REG32(base, CHL_INT0, phy_id); + val &= ~CHL_INT0_PHYCTRL_NOTRDY; + PHY_WRITE_REG32(base, CHL_INT0, phy_id, val); + PHY_WRITE_REG32(base, CHL_INT0_MSK, phy_id, 0x3ce3ee); + + // Need notify + val = PHY_READ_REG32(base, SL_CONTROL, phy_id); + val |= SL_CONTROL_NOTIFY_EN; + PHY_WRITE_REG32(base, SL_CONTROL, phy_id, val); + // wait 100ms required for notify takes effect, refer drivers/scsi/hisi_sas/hisi_sas_v1_hw.c + MicroSecondDelay(100000); + val = PHY_READ_REG32(base, SL_CONTROL, phy_id); + val &= ~SL_CONTROL_NOTIFY_EN; + PHY_WRITE_REG32(base, SL_CONTROL, phy_id, val); + + CopyMem (&SasV1Info->ExtScsiPassThru, &SasV1ExtScsiPassThruProtocolTemplate, sizeof (EFI_EXT_SCSI_PASS_THRU_PROTOCOL)); + SasV1Info->ExtScsiPassThruMode.AdapterId = 2; + SasV1Info->ExtScsiPassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL; + SasV1Info->ExtScsiPassThruMode.IoAlign = 64; //cache line align + SasV1Info->ExtScsiPassThru.Mode = &SasV1Info->ExtScsiPassThruMode; + + DevicePath = (SAS_V1_TRANSPORT_DEVICE_PATH *)CreateDeviceNode ( + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + sizeof (SAS_V1_TRANSPORT_DEVICE_PATH)); + ASSERT (DevicePath != NULL); + SasV1Info->DevicePath = DevicePath; + + CopyMem (&DevicePath->Vendor.Guid, &gPlatformSasProtocolGuid, sizeof (EFI_GUID)); + DevicePath->PhysBase = base; + SetDevicePathNodeLength (&DevicePath->Vendor, + sizeof (*DevicePath) - sizeof (DevicePath->End)); + SetDevicePathEndNode (&DevicePath->End); + + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiDevicePathProtocolGuid, DevicePath, + &gEfiExtScsiPassThruProtocolGuid, &SasV1Info->ExtScsiPassThru, + NULL); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +SasDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + SAS_V1_INFO *SasV1Info; + EFI_STATUS Status; + EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtScsi; + int i, s; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiExtScsiPassThruProtocolGuid, + (VOID **) &ExtScsi, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + SasV1Info = SAS_FROM_PASS_THRU(ExtScsi); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiDevicePathProtocolGuid, + SasV1Info->DevicePath, + &gEfiExtScsiPassThruProtocolGuid, + &SasV1Info->ExtScsiPassThru, + NULL); + if (!EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gPlatformSasProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->CloseEvent (SasV1Info->TimerEvent); + + for (i = 0; i < QUEUE_CNT; i++) { + s = sizeof(struct hisi_sas_cmd_hdr) * QUEUE_SLOTS; + DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->cmd_hdr[i]); + s = sizeof(struct hisi_sas_complete_hdr) * QUEUE_SLOTS; + DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->complete_hdr[i]); + s = sizeof(struct hisi_sas_sts) * QUEUE_SLOTS; + DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->status_buf[i]); + s = sizeof(struct hisi_sas_cmd) * QUEUE_SLOTS; + DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->command_table[i]); + s = sizeof(struct hisi_sas_sge_page) * QUEUE_SLOTS; + DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->sge[i]); + } + + s = SLOT_ENTRIES * sizeof(struct hisi_sas_iost); + DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->iost); + s = SLOT_ENTRIES * sizeof(struct hisi_sas_breakpoint); + DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->breakpoint); + s = MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct); + DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->itct); + + FreePool (SasV1Info->hba->slots); + FreePool (SasV1Info->hba); + FreePool (SasV1Info); + return EFI_SUCCESS; + } + return Status; +} + +EFI_DRIVER_BINDING_PROTOCOL gSasDriverBinding = { + SasDriverBindingSupported, + SasDriverBindingStart, + SasDriverBindingStop, + 0xa, + NULL, + NULL +}; + +EFI_STATUS +SasV1Initialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gSasDriverBinding, + ImageHandle, + NULL, + NULL + ); +} diff --git a/Silicon/Hisilicon/Drivers/SasV1Dxe/SasV1Dxe.inf b/Silicon/Hisilicon/Drivers/SasV1Dxe/SasV1Dxe.inf new file mode 100644 index 0000000000..7e65cc819c --- /dev/null +++ b/Silicon/Hisilicon/Drivers/SasV1Dxe/SasV1Dxe.inf @@ -0,0 +1,46 @@ +#/** @file +# +# Copyright (c) 2016 Linaro Ltd. +# Copyright (c) 2016 Hisilicon Limited. +# 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. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SasV1Dxe + FILE_GUID = 2b235921-8405-4219-a461-972a3a60969c + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = SasV1Initialize + + +[Sources.common] + SasV1Dxe.c + +[Packages] + ArmPkg/ArmPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + DmaLib + IoLib + MemoryAllocationLib + PcdLib + TimerLib + UefiDriverEntryPoint + UefiLib + UncachedMemoryAllocationLib + +[Protocols] + gEfiExtScsiPassThruProtocolGuid + gPlatformSasProtocolGuid diff --git a/Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.c b/Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.c new file mode 100644 index 0000000000..8d8dacd3e0 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.c @@ -0,0 +1,205 @@ +/** @file +* +* Copyright (c) 2015, Hisilicon Limited. All rights reserved. +* Copyright (c) 2015, Linaro Limited. 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. +* +**/ + +#include "AddSmbiosType9.h" + +extern SMBIOS_TABLE_TYPE9 gPcieSlotInfo[]; +extern UINT8 OemGetPcieSlotNumber (); + +REPORT_PCIEDIDVID2BMC PcieDeviceToReport_2P[PCIEDEVICE_REPORT_MAX] = { + {67,0,0,0}, + {225,0,0,3}, + {0xFFFF,0xFFFF,0xFFFF,0xFFFF}, + {0xFFFF,0xFFFF,0xFFFF,0xFFFF} +}; +VOID +EFIAPI +UpdateSmbiosType9Info( + IN OUT SMBIOS_TABLE_TYPE9 *Type9Record +) +{ + EFI_STATUS Status; + UINTN HandleIndex; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + EFI_PCI_IO_PROTOCOL *PciIo; + UINTN SegmentNumber; + UINTN BusNumber; + UINTN DeviceNumber; + UINTN FunctionNumber; + UINTN Index; + REPORT_PCIEDIDVID2BMC ReportPcieDidVid[PCIEDEVICE_REPORT_MAX]; + if(OemIsMpBoot()){ + (VOID)CopyMem((VOID *)ReportPcieDidVid,(VOID *)PcieDeviceToReport_2P,sizeof(PcieDeviceToReport_2P)); + } else { + (VOID)CopyMem((VOID *)ReportPcieDidVid,(VOID *)PcieDeviceToReport,sizeof(PcieDeviceToReport)); + } + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if(EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, " Locate gEfiPciIoProtocol Failed.\n")); + gBS->FreePool ((VOID *)HandleBuffer); + return; + } + for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) { + Status = gBS->HandleProtocol ( + HandleBuffer[HandleIndex], + &gEfiPciIoProtocolGuid, + (VOID **)&PciIo + ); + if (EFI_ERROR (Status)) { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] Status : %r\n", __FUNCTION__, __LINE__, Status)); + continue; + } + (VOID)PciIo->GetLocation(PciIo, &SegmentNumber, &BusNumber, &DeviceNumber, &FunctionNumber); + for(Index = 0; Index < sizeof(ReportPcieDidVid) / sizeof(REPORT_PCIEDIDVID2BMC); Index++){ + if (Type9Record->SlotID == ReportPcieDidVid[Index].Slot + 1) { + if((BusNumber == ReportPcieDidVid[Index].Bus) && (DeviceNumber == ReportPcieDidVid[Index].Device)) { + DEBUG((EFI_D_ERROR,"PCIe device plot in slot Seg %d bdf %d %d %d\r\n",SegmentNumber,BusNumber,DeviceNumber,FunctionNumber)); + Type9Record->SegmentGroupNum = SegmentNumber; + Type9Record->BusNum = BusNumber; + Type9Record->DevFuncNum = (DeviceNumber << 3) | FunctionNumber; + Type9Record->CurrentUsage = SlotUsageInUse; + break; + } + } + } + } + gBS->FreePool ((VOID *)HandleBuffer); + return; +} +EFI_STATUS +EFIAPI +AddSmbiosType9Entry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_SMBIOS_TYPE SmbiosType; + EFI_SMBIOS_HANDLE SmbiosHandle; + EFI_SMBIOS_PROTOCOL *Smbios; + EFI_SMBIOS_TABLE_HEADER *Record; + SMBIOS_TABLE_TYPE9 *Type9Record; + SMBIOS_TABLE_TYPE9 *SmbiosRecord = NULL; + CHAR8 *OptionalStrStart; + + UINT8 SmbiosAddType9Number; + UINT8 Index; + + CHAR16 *SlotDesignation = NULL; + UINTN SlotDesignationStrLen; + + Status = gBS->LocateProtocol ( + &gEfiSmbiosProtocolGuid, + NULL, + (VOID **) &Smbios + ); + if (EFI_ERROR (Status)) { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] LocateProtocol Failed. Status : %r\n", __FUNCTION__, __LINE__, Status)); + return Status; + } + + do { + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + SmbiosType = EFI_SMBIOS_TYPE_SYSTEM_SLOTS; + Status = Smbios->GetNext (Smbios, &SmbiosHandle, &SmbiosType, &Record, NULL); + if (!EFI_ERROR(Status)) { + Status = Smbios->Remove (Smbios, SmbiosHandle); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] Remove System Slot Failed. Status : %r\n", __FUNCTION__, __LINE__, Status)); + break; + } + } + } while (SmbiosHandle != SMBIOS_HANDLE_PI_RESERVED); + + SmbiosAddType9Number = OemGetPcieSlotNumber(); + + for (Index = 0; Index < SmbiosAddType9Number; Index++) + { + if (gPcieSlotInfo[Index].Hdr.Type != EFI_SMBIOS_TYPE_SYSTEM_SLOTS) + { + continue; + } + + Type9Record = &gPcieSlotInfo[Index]; + + UpdateSmbiosType9Info (Type9Record); + SlotDesignation = AllocateZeroPool ((sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH); + if (NULL == SlotDesignation) + { + Status = EFI_OUT_OF_RESOURCES; + DEBUG((EFI_D_ERROR, "[%a]:[%dL] AllocateZeroPool Failed. Status : %r\n", __FUNCTION__, __LINE__, Status)); + + goto Exit; + } + + SlotDesignationStrLen = UnicodeSPrint (SlotDesignation, SMBIOS_STRING_MAX_LENGTH - 1, L"PCIE Slot%d", Type9Record->SlotID); + + // + // Two zeros following the last string. + // + SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE9) + SlotDesignationStrLen + 1 + 1); + if(NULL == SmbiosRecord) + { + Status = EFI_OUT_OF_RESOURCES; + DEBUG((EFI_D_ERROR, "[%a]:[%dL] AllocateZeroPool Failed. Status : %r\n", __FUNCTION__, __LINE__, Status)); + + goto Exit; + } + + (VOID)CopyMem(SmbiosRecord, Type9Record, sizeof (SMBIOS_TABLE_TYPE9)); + + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE9); + + OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1); + UnicodeStrToAsciiStr(SlotDesignation, OptionalStrStart); + + // + // Now we have got the full smbios record, call smbios protocol to add this record. + // + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + Status = Smbios->Add (Smbios, NULL, &SmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *)SmbiosRecord); + if(EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type09 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status)); + goto Exit; + } + + FreePool(SmbiosRecord); + FreePool(SlotDesignation); + } + + return EFI_SUCCESS; + +Exit: + if(SmbiosRecord != NULL) + { + FreePool(SmbiosRecord); + } + + if(SlotDesignation != NULL) + { + FreePool(SlotDesignation); + } + + return Status; +} + diff --git a/Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.h b/Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.h new file mode 100644 index 0000000000..5766152399 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.h @@ -0,0 +1,36 @@ +/** @file +* +* Copyright (c) 2015, Hisilicon Limited. All rights reserved. +* Copyright (c) 2015, Linaro Limited. 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. +* +**/ + + +#ifndef _ADD_SMBIOS_TYPE9_H_ +#define _ADD_SMBIOS_TYPE9_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.inf b/Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.inf new file mode 100644 index 0000000000..4db7b498bd --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.inf @@ -0,0 +1,50 @@ +#/** @file +# +# Copyright (c) 2015, Hisilicon Limited. All rights reserved. +# Copyright (c) 2015, Linaro Limited. 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. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = AddSmbiosType9 + FILE_GUID = 7AE6F104-66DF-48EF-B5A3-5050BF4908F0 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = AddSmbiosType9Entry + +[Sources] + AddSmbiosType9.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + BaseMemoryLib + MemoryAllocationLib + DebugLib + UefiLib + UefiDriverEntryPoint + OemMiscLib + +[Protocols] + gEfiSmbiosProtocolGuid + gEfiPciIoProtocolGuid + +[Guids] + +[Pcd] + +[Depex] + gEfiSmbiosProtocolGuid AND + gEfiPciIoProtocolGuid diff --git a/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClass.c b/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClass.c new file mode 100644 index 0000000000..da714c9e22 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClass.c @@ -0,0 +1,762 @@ +/** @file +* +* Copyright (c) 2015, Hisilicon Limited. All rights reserved. +* Copyright (c) 2015, Linaro Limited. 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. +* +**/ + + +#include "MemorySubClass.h" + +EFI_SMBIOS_PROTOCOL *mSmbios = NULL; +EFI_HII_HANDLE mHiiHandle; + +UINT8 mMaxSkt; +UINT8 mMaxCh; + +VOID +SmbiosGetManufacturer ( + IN UINT8 MfgIdLSB, + IN UINT8 MfgIdMSB, + OUT CHAR16 *Manufacturer +) +{ + UINT32 Index = 0; + + (VOID)StrCpyS(Manufacturer, SMBIOS_STRING_MAX_LENGTH - 1, L"Unknown"); + while (JEP106[Index].MfgIdLSB != 0xFF && JEP106[Index].MfgIdMSB != 0xFF ) + { + if (JEP106[Index].MfgIdLSB == MfgIdLSB && JEP106[Index].MfgIdMSB == MfgIdMSB) + { + (VOID)StrCpyS (Manufacturer, SMBIOS_STRING_MAX_LENGTH - 1, JEP106[Index].Name); + break; + } + Index++; + } +} + +VOID +SmbiosGetPartNumber ( + IN pGBL_DATA pGblData, + IN UINT8 Skt, + IN UINT8 Ch, + IN UINT8 Dimm, + OUT CHAR16 *PartNumber + ) +{ + CHAR16 StringBuffer2[SMBIOS_STRING_MAX_LENGTH]; + UINT32 Index2; + + (VOID)StrCpyS(PartNumber, SMBIOS_STRING_MAX_LENGTH - 1, L""); + if (pGblData->Channel[Skt][Ch].Dimm[Dimm].DramType == SPD_TYPE_DDR3) + { + for (Index2 = 0; Index2 < SPD_MODULE_PART; Index2++) + { + UnicodeSPrint (StringBuffer2, SMBIOS_STRING_MAX_LENGTH - 1, L"%c", pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdModPart[Index2]); + (VOID)StrCatS(PartNumber, SMBIOS_STRING_MAX_LENGTH - 1, StringBuffer2); + } + } + else + { + for (Index2 = 0; Index2 < SPD_MODULE_PART_DDR4; Index2++) + { + UnicodeSPrint (StringBuffer2, SMBIOS_STRING_MAX_LENGTH - 1, L"%c", pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdModPartDDR4[Index2]); + (VOID)StrCatS(PartNumber, SMBIOS_STRING_MAX_LENGTH - 1, StringBuffer2); + } + } + + return; +} + +VOID +SmbiosGetSerialNumber ( + IN pGBL_DATA pGblData, + IN UINT8 Skt, + IN UINT8 Ch, + IN UINT8 Dimm, + OUT CHAR16 *SerialNumber + ) +{ + UINT32 Temp; + + Temp = SwapBytes32 (pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdSerialNum); + + UnicodeSPrint(SerialNumber, SMBIOS_STRING_MAX_LENGTH, L"0x%08x", Temp); + + return; +} + +BOOLEAN +IsDimmPresent ( + IN pGBL_DATA pGblData, + IN UINT8 Skt, + IN UINT8 Ch, + IN UINT8 Dimm +) +{ + if (pGblData->Channel[Skt][Ch].Status == FALSE || + pGblData->Channel[Skt][Ch].Dimm[Dimm].Status == FALSE) + { + return FALSE; + } + else + { + return TRUE; + } +} + +UINT8 +SmbiosGetMemoryType ( + IN pGBL_DATA pGblData, + IN UINT8 Skt, + IN UINT8 Ch, + IN UINT8 Dimm +) +{ + UINT8 MemoryType; + + if(!IsDimmPresent(pGblData, Skt, Ch, Dimm)) + { + return MemoryTypeUnknown; + } + + if (pGblData->Channel[Skt][Ch].Dimm[Dimm].DramType == SPD_TYPE_DDR3) + { + MemoryType = MemoryTypeDdr3; + } + else if (pGblData->Channel[Skt][Ch].Dimm[Dimm].DramType == SPD_TYPE_DDR4) + { + MemoryType = MemoryTypeDdr4; + } + else + { + MemoryType = MemoryTypeUnknown; + } + + return MemoryType; +} + +VOID +SmbiosGetTypeDetail ( + IN pGBL_DATA pGblData, + IN UINT8 Skt, + IN UINT8 Ch, + IN UINT8 Dimm, + IN OUT MEMORY_DEVICE_TYPE_DETAIL *TypeDetail +) +{ + if (NULL == TypeDetail) + { + return; + } + + if(!IsDimmPresent(pGblData, Skt, Ch, Dimm)) + { + TypeDetail->Unknown = 1; + return; + } + + switch (pGblData->Channel[Skt][Ch].Dimm[Dimm].ModuleType) + { + case SPD_UDIMM: + TypeDetail->Unbuffered = 1; + break; + + case SPD_LRDIMM: + TypeDetail->LrDimm = 1; + break; + + case SPD_RDIMM: + TypeDetail->Registered = 1; + break; + + default: + TypeDetail->Unknown = 1; + break; + } +} + +VOID +SmbiosGetDimmVoltageInfo ( + IN pGBL_DATA pGblData, + IN UINT8 Skt, + IN UINT8 Ch, + IN UINT8 Dimm, + IN OUT SMBIOS_TABLE_TYPE17 *Type17Record + +) +{ + if(!IsDimmPresent(pGblData, Skt, Ch, Dimm)) + { + return; + } + + if (pGblData->Channel[Skt][Ch].Dimm[Dimm].DramType == SPD_TYPE_DDR3) + { + Type17Record->MinimumVoltage = 1250; + Type17Record->MaximumVoltage = 1500; + + switch (pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdVdd) + { + case SPD_VDD_150: + Type17Record->ConfiguredVoltage = 1500; + break; + + case SPD_VDD_135: + Type17Record->ConfiguredVoltage = 1350; + break; + + case SPD_VDD_125: + Type17Record->ConfiguredVoltage = 1250; + break; + + default: + break; + } + } + else if (pGblData->Channel[Skt][Ch].Dimm[Dimm].DramType == SPD_TYPE_DDR4) + { + Type17Record->MinimumVoltage = 1200; + Type17Record->MaximumVoltage = 2000; + switch (pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdVdd) + { + case SPD_VDD_120: + Type17Record->ConfiguredVoltage = 1200; + break; + + default: + break; + } + } +} + +VOID +SmbiosGetMemoryDevicesNumber ( + IN OUT UINT16 *NumberOfDevices +) +{ + UINT8 Skt, Ch, Dimm; + + for(Skt = 0; Skt < mMaxSkt; Skt++) + { + for(Ch = 0; Ch < mMaxCh; Ch++) + { + for(Dimm = 0; Dimm < OemGetDimmSlot(Skt, Ch); Dimm++) + { + (*NumberOfDevices)++; + } + } + } +} + +UINT8 +SmbiosGetPartitionWidth ( +) +{ + + UINT8 Skt, Ch, Dimm; + UINT8 PartitionWidth = 0; + + for(Skt = 0; Skt < mMaxSkt; Skt++) + { + for(Ch = 0; Ch < mMaxCh; Ch++) + { + for(Dimm = 0; Dimm < OemGetDimmSlot(Skt, Ch); Dimm++) + { + PartitionWidth++; + } + } + } + + return PartitionWidth; +} + +EFI_STATUS +SmbiosAddType16Table ( + IN pGBL_DATA pGblData, + OUT EFI_SMBIOS_HANDLE *MemArraySmbiosHandle + ) +{ + EFI_STATUS Status; + UINT64 MemoryCapacity; + SMBIOS_TABLE_TYPE16 *Type16Record; + + UINT16 NumberOfMemoryDevices = 0; + + SmbiosGetMemoryDevicesNumber (&NumberOfMemoryDevices); + + MemoryCapacity = (UINT64) LShiftU64 (NumberOfMemoryDevices * MAX_DIMM_SIZE, 20); // GB to KB. + + // + // Type 16 SMBIOS Record + // + Type16Record = AllocateZeroPool(sizeof(SMBIOS_TABLE_TYPE16) + 1 + 1); + if (NULL == Type16Record) + { + return EFI_OUT_OF_RESOURCES; + } + + Type16Record->Hdr.Type = EFI_SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY; + Type16Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE16); + Type16Record->Hdr.Handle = 0x0; + Type16Record->Location = MemoryArrayLocationSystemBoard; + Type16Record->Use = MemoryArrayUseSystemMemory; + Type16Record->MemoryErrorInformationHandle = 0xFFFE; + Type16Record->NumberOfMemoryDevices = NumberOfMemoryDevices; + + if(pGblData->EccEn) + { + Type16Record->MemoryErrorCorrection = MemoryErrorCorrectionSingleBitEcc; + } + else + { + Type16Record->MemoryErrorCorrection = MemoryErrorCorrectionNone; + } + + if (MemoryCapacity >= 0x80000000) + { + Type16Record->MaximumCapacity = 0x80000000; // in KB; + Type16Record->ExtendedMaximumCapacity = MemoryCapacity << 10; // Extended Max capacity should be stored in bytes. + } + else + { + Type16Record->MaximumCapacity = (UINT32)MemoryCapacity; // Max capacity should be stored in kilo bytes. + Type16Record->ExtendedMaximumCapacity = 0; + } + + *MemArraySmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + Status = mSmbios->Add (mSmbios, NULL, MemArraySmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *)Type16Record); + if(EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type16 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status)); + } + + FreePool(Type16Record); + return Status; +} + +EFI_STATUS +SmbiosAddType19Table ( + IN pGBL_DATA pGblData, + IN EFI_SMBIOS_HANDLE MemArraySmbiosHandle + ) +{ + EFI_STATUS Status; + UINT32 MemInfoTotalMem; + UINT64 TotalMemorySize; + EFI_SMBIOS_HANDLE MemArrayMappedAddrSmbiosHandle; + SMBIOS_TABLE_TYPE19 *Type19Record; + + MemInfoTotalMem = pGblData->MemSize; // In MB + + if (MemInfoTotalMem == 0) + { + return EFI_NOT_FOUND; + } + + TotalMemorySize = (UINT64) LShiftU64 (MemInfoTotalMem, 10); // MB to KB. + + // + // Type 19 SMBIOS Record + // + Type19Record = AllocateZeroPool(sizeof(SMBIOS_TABLE_TYPE19) + 1 + 1); + if (NULL == Type19Record) + { + return EFI_OUT_OF_RESOURCES; + } + + Type19Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS; + Type19Record->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE19); + Type19Record->Hdr.Handle = 0x0; + Type19Record->StartingAddress = 0x0; + Type19Record->EndingAddress = (UINT32) (TotalMemorySize - 1); // in KB; + Type19Record->MemoryArrayHandle = MemArraySmbiosHandle; + Type19Record->PartitionWidth = SmbiosGetPartitionWidth (); + Type19Record->ExtendedStartingAddress = 0x0; + Type19Record->ExtendedEndingAddress = 0x0; + + MemArrayMappedAddrSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + Status = mSmbios->Add (mSmbios, NULL, &MemArrayMappedAddrSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *)Type19Record); + if(EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type19 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status)); + } + + FreePool(Type19Record); + return Status; +} + + +EFI_STATUS +SmbiosAddType17Table ( + IN pGBL_DATA pGblData, + IN UINT8 Skt, + IN UINT8 Ch, + IN UINT8 Dimm, + IN EFI_SMBIOS_HANDLE MemArraySmbiosHandle + ) +{ + EFI_STATUS Status; + SMBIOS_TABLE_TYPE17 *Type17Record; + EFI_SMBIOS_HANDLE MemDevSmbiosHandle; + UINTN TableSize; + + UINTN StringBufferSize; + EFI_STRING StringBuffer; + UINT16 MemInfoMemFreq; + UINT16 MemoryTotalWidth; + UINT16 MemoryDataWidth; + UINT16 MemoryDeviceSize; + UINT16 MemorySpeed; + UINT8 Attributes; + UINT32 MemoryDeviceExtendSize; + UINT16 CfgMemorySpeed; + + CHAR8 *OptionalStrStart; + UINTN DeviceLocatorStrLen; + UINTN BankLocatorStrLen; + UINTN ManufactureStrLen; + UINTN SerialNumberStrLen; + UINTN AssertTagStrLen; + UINTN PartNumberStrLen; + EFI_STRING DeviceLocatorStr; + EFI_STRING BankLocatorStr; + EFI_STRING ManufactureStr; + EFI_STRING SerialNumberStr; + EFI_STRING AssertTagStr; + EFI_STRING PartNumberStr; + EFI_STRING_ID DeviceLocator; + + Type17Record = NULL; + DeviceLocatorStr = NULL; + BankLocatorStr = NULL; + ManufactureStr = NULL; + SerialNumberStr = NULL; + AssertTagStr = NULL; + PartNumberStr = NULL; + + MemoryTotalWidth = 0; + MemoryDataWidth = 0; + MemoryDeviceSize = 0; + MemoryDeviceExtendSize = 0; + MemorySpeed = 0; + Attributes = 0; + CfgMemorySpeed = 0; + + // + // Allocate Buffers + // + StringBufferSize = (sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH; + StringBuffer = AllocateZeroPool (StringBufferSize); + if(NULL == StringBuffer) + { + return EFI_OUT_OF_RESOURCES; + } + + + // + // Manufacture + // + ManufactureStr = AllocateZeroPool (StringBufferSize); + if(NULL == ManufactureStr) + { + Status = EFI_OUT_OF_RESOURCES; + goto FREE_STR_BUF; + } + UnicodeSPrint(ManufactureStr, SMBIOS_STRING_MAX_LENGTH - 1, L"NO DIMM"); + + // + // SerialNumber + // + SerialNumberStr = AllocateZeroPool (StringBufferSize); + if(NULL == SerialNumberStr) + { + Status = EFI_OUT_OF_RESOURCES; + goto FREE_STR_MAN; + } + UnicodeSPrint(SerialNumberStr, SMBIOS_STRING_MAX_LENGTH - 1, L"NO DIMM"); + + // + // AssetTag + // + AssertTagStr = AllocateZeroPool (StringBufferSize); + if(NULL == AssertTagStr) + { + Status = EFI_OUT_OF_RESOURCES; + goto FREE_STR_SN; + } + UnicodeSPrint(AssertTagStr, SMBIOS_STRING_MAX_LENGTH - 1, L"NO DIMM"); + + // + // PartNumber + // + PartNumberStr = AllocateZeroPool (StringBufferSize); + if(NULL == PartNumberStr) + { + Status = EFI_OUT_OF_RESOURCES; + goto FREE_STR_AST; + } + UnicodeSPrint(PartNumberStr, SMBIOS_STRING_MAX_LENGTH - 1, L"NO DIMM"); + + + if(IsDimmPresent(pGblData, Skt, Ch, Dimm)) + { + MemoryDataWidth = pGblData->Channel[Skt][Ch].Dimm[Dimm].PrimaryBusWidth; + MemoryTotalWidth = MemoryDataWidth + pGblData->Channel[Skt][Ch].Dimm[Dimm].ExtensionBusWidth; + + MemoryDeviceSize = pGblData->Channel[Skt][Ch].Dimm[Dimm].DimmSize; //in MB + MemoryDeviceExtendSize = 0; + + if (MemoryDeviceSize >= 0x7fff) + { + MemoryDeviceExtendSize = MemoryDeviceSize; // in MB + MemoryDeviceSize = 0x7fff; // max value + } + + MemInfoMemFreq = pGblData->Freq; + MemorySpeed = pGblData->Channel[Skt][Ch].Dimm[Dimm].DimmSpeed; + Attributes = pGblData->Channel[Skt][Ch].Dimm[Dimm].RankNum; + CfgMemorySpeed = MemInfoMemFreq; + + // + // Manufacturer + // + SmbiosGetManufacturer (pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdMMfgId & 0xFF, + pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdMMfgId >> 8, + ManufactureStr + ); + + // + // SerialNumber + // + SmbiosGetSerialNumber(pGblData, Skt, Ch, Dimm, SerialNumberStr); + + // + // AssetTag + // + UnicodeSPrint(AssertTagStr, SMBIOS_STRING_MAX_LENGTH - 1, L"Unknown"); + + // + // PartNumber + // + SmbiosGetPartNumber(pGblData, Skt, Ch, Dimm, PartNumberStr); + } + + // + // DeviceLocator + // + DeviceLocatorStr = AllocateZeroPool ((sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH); + if(NULL == DeviceLocatorStr) + { + Status = EFI_OUT_OF_RESOURCES; + goto FREE_STR_PN; + } + DeviceLocator = gDimmToDevLocator[Skt][Ch][Dimm]; + if (DeviceLocator != 0xFFFF) + { + UnicodeSPrint(DeviceLocatorStr, SMBIOS_STRING_MAX_LENGTH, L"DIMM%x%x%x ", Skt, Ch, Dimm); + StringBuffer = HiiGetPackageString (&gEfiCallerIdGuid, DeviceLocator, NULL); + (VOID)StrCatS(DeviceLocatorStr, SMBIOS_STRING_MAX_LENGTH, StringBuffer); + } + else + { + UnicodeSPrint(DeviceLocatorStr, SMBIOS_STRING_MAX_LENGTH, L"DIMM%x%x%x", Skt, Ch, Dimm); + } + DeviceLocatorStrLen = StrLen (DeviceLocatorStr); + + // + // BankLocator + // + BankLocatorStr = AllocateZeroPool ((sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH); + if(NULL == BankLocatorStr) + { + Status = EFI_OUT_OF_RESOURCES; + goto FREE_STR_DEV; + } + UnicodeSPrint(BankLocatorStr, SMBIOS_STRING_MAX_LENGTH, L"SOCKET %x CHANNEL %x DIMM %x", Skt, Ch, Dimm); + BankLocatorStrLen = StrLen (BankLocatorStr); + + ManufactureStrLen = StrLen (ManufactureStr); + SerialNumberStrLen = StrLen (SerialNumberStr); + AssertTagStrLen = StrLen (AssertTagStr); + PartNumberStrLen = StrLen (PartNumberStr); + + // + // Report Type 17 SMBIOS Record + // + TableSize = sizeof(SMBIOS_TABLE_TYPE17) + DeviceLocatorStrLen + 1 + BankLocatorStrLen + 1 + ManufactureStrLen + 1 + SerialNumberStrLen + 1 + AssertTagStrLen + 1 + PartNumberStrLen + 1 + 1; + Type17Record = AllocateZeroPool (TableSize); + if(NULL == Type17Record) + { + Status = EFI_OUT_OF_RESOURCES; + goto FREE_BL; + } + + Type17Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_DEVICE; + Type17Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE17); + Type17Record->Hdr.Handle = 0; + Type17Record->MemoryArrayHandle = MemArraySmbiosHandle; + Type17Record->MemoryErrorInformationHandle = 0xFFFE; + Type17Record->TotalWidth = MemoryTotalWidth; + Type17Record->DataWidth = MemoryDataWidth; + Type17Record->Size = MemoryDeviceSize; // in MB + Type17Record->FormFactor = MemoryFormFactorDimm; + Type17Record->DeviceLocator = 1; + Type17Record->BankLocator = 2; + Type17Record->MemoryType = SmbiosGetMemoryType (pGblData, Skt, Ch, Dimm); + + Type17Record->TypeDetail.Synchronous = 1; + + SmbiosGetTypeDetail (pGblData, Skt, Ch, Dimm, &(Type17Record->TypeDetail)); + + Type17Record->Speed = MemorySpeed; // in MHZ + Type17Record->Manufacturer = 3; + Type17Record->SerialNumber = 4; + Type17Record->AssetTag = 5; + Type17Record->PartNumber = 6; + Type17Record->Attributes = Attributes; + Type17Record->ExtendedSize = MemoryDeviceExtendSize; + Type17Record->ConfiguredMemoryClockSpeed = CfgMemorySpeed; + // + // Add for smbios 2.8.0 + // + SmbiosGetDimmVoltageInfo (pGblData, Skt, Ch, Dimm, Type17Record); + + OptionalStrStart = (CHAR8 *) (Type17Record + 1); + UnicodeStrToAsciiStr (DeviceLocatorStr, OptionalStrStart); + UnicodeStrToAsciiStr (BankLocatorStr, OptionalStrStart + DeviceLocatorStrLen + 1); + UnicodeStrToAsciiStr (ManufactureStr, OptionalStrStart + DeviceLocatorStrLen + 1 + BankLocatorStrLen + 1); + UnicodeStrToAsciiStr (SerialNumberStr, OptionalStrStart + DeviceLocatorStrLen + 1 + BankLocatorStrLen + 1 + ManufactureStrLen + 1); + UnicodeStrToAsciiStr (AssertTagStr, OptionalStrStart + DeviceLocatorStrLen + 1 + BankLocatorStrLen + 1 + ManufactureStrLen + 1 + SerialNumberStrLen + 1); + UnicodeStrToAsciiStr (PartNumberStr, OptionalStrStart + DeviceLocatorStrLen + 1 + BankLocatorStrLen + 1 + ManufactureStrLen + 1 + SerialNumberStrLen + 1 + AssertTagStrLen + 1); + + MemDevSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + Status = mSmbios->Add (mSmbios, NULL, &MemDevSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) Type17Record); + if(EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type17 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status)); + } + + FreePool (Type17Record); + +FREE_BL: + FreePool (BankLocatorStr); + +FREE_STR_DEV: + FreePool (DeviceLocatorStr); + +FREE_STR_PN: + FreePool (PartNumberStr); + +FREE_STR_AST: + FreePool (AssertTagStr); + +FREE_STR_SN: + FreePool (SerialNumberStr); + +FREE_STR_MAN: + FreePool (ManufactureStr); + +FREE_STR_BUF: + FreePool (StringBuffer); + + return Status; +} + + +/** + Standard EFI driver point. This driver locates the MemoryConfigurationData Variable, + if it exists, add the related SMBIOS tables by PI SMBIOS protocol. + + @param ImageHandle Handle for the image of this driver + @param SystemTable Pointer to the EFI System Table + + @retval EFI_SUCCESS The data was successfully stored. + +**/ +EFI_STATUS +EFIAPI +MemorySubClassEntryPoint( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_SMBIOS_PROTOCOL *Smbios; + EFI_HOB_GUID_TYPE *GuidHob; + pGBL_DATA pGblData; + EFI_SMBIOS_HANDLE MemArraySmbiosHandle; + UINT8 Skt, Ch, Dimm; + + GuidHob = GetFirstGuidHob(&gHisiEfiMemoryMapGuid); + if(NULL == GuidHob) + { + DEBUG((EFI_D_ERROR, "Could not get MemoryMap Guid hob. %r\n")); + return EFI_NOT_FOUND; + } + pGblData = (pGBL_DATA) GET_GUID_HOB_DATA(GuidHob); + + // + // Locate dependent protocols + // + Status = gBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, (VOID**)&Smbios); + if (EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "Could not locate SMBIOS protocol. %r\n", Status)); + return Status; + } + mSmbios = Smbios; + + // + // Add our default strings to the HII database. They will be modified later. + // + mHiiHandle = OemGetPackages(); + if(NULL == mHiiHandle) + { + return EFI_OUT_OF_RESOURCES; + } + + mMaxSkt = OemGetSocketNumber(); + mMaxCh = OemGetDdrChannel(); + // Get DIMM slot number on Socket 0 Channel 0 + // TODO: Assume all channels have same slot number + + Status = SmbiosAddType16Table (pGblData, &MemArraySmbiosHandle); + if(EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "Smbios Add Type16 Table Failed. %r\n", Status)); + return Status; + } + + Status = SmbiosAddType19Table (pGblData, MemArraySmbiosHandle); + if(EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "Smbios Add Type19 Table Failed. %r\n", Status)); + return Status; + } + + for(Skt = 0; Skt < mMaxSkt; Skt++) + { + for(Ch = 0; Ch < mMaxCh; Ch++) + { + for(Dimm = 0; Dimm < OemGetDimmSlot(Skt, Ch); Dimm++) + { + Status = SmbiosAddType17Table (pGblData, Skt, Ch, Dimm, MemArraySmbiosHandle); + if(EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "Smbios Add Type17 Table Failed. %r\n", Status)); + } + } + } + } + + return Status; +} diff --git a/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClass.h b/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClass.h new file mode 100644 index 0000000000..c35ce39d61 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClass.h @@ -0,0 +1,79 @@ +/** @file +* +* Copyright (c) 2015, Hisilicon Limited. All rights reserved. +* Copyright (c) 2015, Linaro Limited. 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. +* +**/ + + +#ifndef _MEMORY_SUBCLASS_DRIVER_H +#define _MEMORY_SUBCLASS_DRIVER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +// +// This is the generated header file which includes whatever needs to be exported (strings + IFR) +// + +extern UINT8 MemorySubClassStrings[]; + +#define MAX_DIMM_SIZE 32 // In GB + +struct SPD_JEDEC_MANUFACTURER +{ + UINT8 MfgIdLSB; + UINT8 MfgIdMSB; + CHAR16 *Name; +}; + +struct SPD_JEDEC_MANUFACTURER JEP106[] = { + { 0, 0x10, L"NEC"}, + { 0, 0x2c, L"Micron"}, + { 0, 0x3d, L"Tektronix"}, + { 0, 0x97, L"TI"}, + { 0, 0xad, L"Hynix"}, + { 0, 0xb3, L"IDT"}, + { 0, 0xc1, L"Infineon"}, + { 0, 0xce, L"Samsung"}, + { 1, 0x94, L"Smart"}, + { 1, 0x98, L"Kingston"}, + { 2, 0xc8, L"Agilent"}, + { 2, 0xfe, L"Elpida"}, + { 3, 0x0b, L"Nanya"}, + { 4, 0x43, L"Ramaxel"}, + { 4, 0xb3, L"Inphi"}, + { 5, 0x51, L"Qimonda"}, + { 5, 0x57, L"AENEON"}, + { 0xFF, 0xFF, L""} +}; + + + +#endif diff --git a/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClassDxe.inf b/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClassDxe.inf new file mode 100644 index 0000000000..93a2bcac37 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClassDxe.inf @@ -0,0 +1,59 @@ +#/** @file +# +# Copyright (c) 2015, Hisilicon Limited. All rights reserved. +# Copyright (c) 2015, Linaro Limited. 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. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = MemorySubClass + FILE_GUID = 62194F1A-5A0D-4B33-9EF0-7D05C6CB923A + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = MemorySubClassEntryPoint + +[Sources] + MemorySubClassStrings.uni + MemorySubClass.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + HobLib + HiiLib + MemoryAllocationLib + BaseMemoryLib + BaseLib + DebugLib + PrintLib + PlatformSysCtrlLib + PcdLib + +[Protocols] + gEfiSmbiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED + +[Pcd] + +[Guids] + gHisiEfiMemoryMapGuid + +[Depex] + gEfiSmbiosProtocolGuid + + diff --git a/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClassStrings.uni b/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClassStrings.uni new file mode 100644 index 0000000000..edf8464e5c --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClassStrings.uni @@ -0,0 +1,30 @@ +// *++ +// +// Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+// Copyright (c) 2015, Hisilicon Limited. All rights reserved. +// Copyright (c) 2015, Linaro Limited. 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. +// +// --*/ + +/=# + +#langdef en-US "English" + +// +// Begin English Language Strings +// + +#string STR_MEMORY_SUBCLASS_UNKNOWN #language en-US "Unknown" + +// +// End English Language Strings +// + diff --git a/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c b/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c new file mode 100644 index 0000000000..61473e85b8 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c @@ -0,0 +1,728 @@ +/** @file +* +* Copyright (c) 2015, Hisilicon Limited. All rights reserved. +* Copyright (c) 2015, Linaro Limited. 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. +* +**/ + +#include "ProcessorSubClass.h" + +#include + +EFI_HII_HANDLE mHiiHandle; + +EFI_SMBIOS_PROTOCOL *mSmbios; + +SMBIOS_TABLE_TYPE7 mSmbiosCacheTable[] = { + //L1 Instruction Cache + { + { //Header + EFI_SMBIOS_TYPE_CACHE_INFORMATION, //Type + sizeof(SMBIOS_TABLE_TYPE7), //Length + 0 //Handle + }, + 1, //SocketDesignation + 0, //CacheConfiguration + 0, //MaximumCacheSize + 48, //InstalledSize + { //SupportedSRAMType + 0 + }, + { //CurrentSRAMType + 0 + }, + 0, //CacheSpeed + CacheErrorParity, //ErrorCorrectionType + CacheTypeInstruction, //SystemCacheType + CacheAssociativity8Way //Associativity + }, + + //L1 Data Cache + { + { //Header + EFI_SMBIOS_TYPE_CACHE_INFORMATION, //Type + sizeof(SMBIOS_TABLE_TYPE7), //Length + 0 //Handle + }, + 1, //SocketDesignation + 0, //CacheConfiguration + 0, //MaximumCacheSize + 32, //InstalledSize + { //SupportedSRAMType + 0 + }, + { //CurrentSRAMType + 0 + }, + 0, //CacheSpeed + CacheErrorSingleBit, //ErrorCorrectionType + CacheTypeData, //SystemCacheType + CacheAssociativity8Way //Associativity + }, + + //L2 Cache + { + { //Header + EFI_SMBIOS_TYPE_CACHE_INFORMATION, //Type + sizeof(SMBIOS_TABLE_TYPE7), //Length + 0 //Handle + }, + 1, //SocketDesignation + 0, //CacheConfiguration + 0, //MaximumCacheSize + 4096, //InstalledSize + { //SupportedSRAMType + 0 + }, + { //CurrentSRAMType + 0 + }, + 0, //CacheSpeed + CacheErrorSingleBit, //ErrorCorrectionType + CacheTypeUnified, //SystemCacheType + CacheAssociativity8Way //Associativity + }, + + //L3 Cache + { + { //Header + EFI_SMBIOS_TYPE_CACHE_INFORMATION, //Type + sizeof(SMBIOS_TABLE_TYPE7), //Length + 0 //Handle + }, + 1, //SocketDesignation + 0, //CacheConfiguration + 0, //MaximumCacheSize + 16384, //InstalledSize + { //SupportedSRAMType + 0 + }, + { //CurrentSRAMType + 0 + }, + 0, //CacheSpeed + CacheErrorSingleBit, //ErrorCorrectionType + CacheTypeUnified, //SystemCacheType + CacheAssociativity16Way //Associativity + } +}; + +SMBIOS_TABLE_TYPE4 mSmbiosProcessorTable[] = { + //CPU0 + { + { //Header + EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION, //Type + sizeof(SMBIOS_TABLE_TYPE4), //Length + 0 //Handle + }, + 1, //Socket + CentralProcessor, //ProcessorType + ProcessorFamilyOther, //ProcessorFamily + 2, //ProcessorManufacture + { //ProcessorId + { //Signature + 0 + }, + { //FeatureFlags + 0 + } + }, + 3, //ProcessorVersion + { //Voltage + 0 + }, + EXTERNAL_CLOCK, //ExternalClock + CPU_MAX_SPEED, //MaxSpeed + 0, //CurrentSpeed + 0, //Status + ProcessorUpgradeUnknown, //ProcessorUpgrade + 0xFFFF, //L1CacheHandle + 0xFFFF, //L2CacheHandle + 0xFFFF, //L3CacheHandle + 4, //SerialNumber + 5, //AssetTag + 6, //PartNumber + + 0, //CoreCount + 0, //EnabledCoreCount + 0, //ThreadCount + 0, //ProcessorCharacteristics + + ProcessorFamilyARM, //ProcessorFamily2 + + 0, //CoreCount2 + 0, //EnabledCoreCount2 + 0 //ThreadCount2 + }, + + //CPU1 + { + { //Header + EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION, //Type + sizeof(SMBIOS_TABLE_TYPE4), //Length + 0 //Handle + }, + 1, //Socket + CentralProcessor, //ProcessorType + ProcessorFamilyOther, //ProcessorFamily + 2, //ProcessorManufacture + { //ProcessorId + { //Signature + 0 + }, + { //FeatureFlags + 0 + } + }, + 3, //ProcessorVersion + { //Voltage + 0 + }, + EXTERNAL_CLOCK, //ExternalClock + CPU_MAX_SPEED, //MaxSpeed + 0, //CurrentSpeed + 0, //Status + ProcessorUpgradeUnknown, //ProcessorUpgrade + 0xFFFF, //L1CacheHandle + 0xFFFF, //L2CacheHandle + 0xFFFF, //L3CacheHandle + 4, //SerialNumber + 5, //AssetTag + 6, //PartNumber + + 0, //CoreCount + 0, //EnabledCoreCount + 0, //ThreadCount + 0, //ProcessorCharacteristics + + ProcessorFamilyARM, //ProcessorFamily2 + + 0, //CoreCount2 + 0, //EnabledCoreCount2 + 0 //ThreadCount2 + } +}; + + +UINT16 +GetCpuFrequency ( + IN UINT8 ProcessorNumber +) +{ + return (UINT16)(PlatformGetCpuFreq(ProcessorNumber)/1000/1000); +} + +UINTN +GetCacheSocketStr ( + IN UINT8 CacheLevel, + OUT CHAR16 *CacheSocketStr + ) +{ + UINTN CacheSocketStrLen; + + if(CacheLevel == CPU_CACHE_L1_Instruction) + { + CacheSocketStrLen = UnicodeSPrint (CacheSocketStr, SMBIOS_STRING_MAX_LENGTH - 1, L"L%x Instruction Cache", CacheLevel + 1); + } + else if(CacheLevel == CPU_CACHE_L1_Data) + { + CacheSocketStrLen = UnicodeSPrint (CacheSocketStr, SMBIOS_STRING_MAX_LENGTH - 1, L"L%x Data Cache", CacheLevel); + } + else + { + CacheSocketStrLen = UnicodeSPrint (CacheSocketStr, SMBIOS_STRING_MAX_LENGTH - 1, L"L%x Cache", CacheLevel); + } + + return CacheSocketStrLen; +} + +VOID +UpdateSmbiosCacheTable ( + IN UINT8 CacheLevel + ) +{ + UINT16 CoreCount; + UINT32 TotalSize; + UINT32 CacheSize; + UINT16 MaximumCacheSize; + UINT16 InstalledSize; + CACHE_CONFIGURATION CacheConfig; + CACHE_SRAM_TYPE_DATA CacheSramType = {0}; + + CoreCount = 16; // Default value is 16 Core + + // + // Set Cache Configuration + // + CacheConfig.Bits.Socketed = 0; // Not Socketed + CacheConfig.Bits.Reserved1 = 0; // + CacheConfig.Bits.Location = 0; // Internal + CacheConfig.Bits.Enable = 1; // Enabled + CacheConfig.Bits.Reserved2 = 0; + if(CacheLevel == CPU_CACHE_L1_Instruction || CacheLevel == CPU_CACHE_L1_Data) + { + CacheConfig.Bits.Level = 0; + CacheConfig.Bits.OperationalMode = 1; // Write Back + } + else + { + CacheConfig.Bits.Level = CacheLevel - 1; + CacheConfig.Bits.OperationalMode = 2; // Varies with Memory Address + } + + mSmbiosCacheTable[CacheLevel].CacheConfiguration = CacheConfig.Data; + + // + // Set Cache Size + // + CacheSize = mSmbiosCacheTable[CacheLevel].InstalledSize; + if (PACKAGE_16CORE != PlatformGetPackageType()) // 32 Core + { + CoreCount = CoreCount * 2; + + if (CacheLevel > 1) + { + CacheSize = CacheSize * 2; + } + } + + if(CacheLevel <= 1) + { + TotalSize = CacheSize * CoreCount; + } + else + { + TotalSize = CacheSize; + } + + if((TotalSize >> 15) == 0) // 1K granularity + { + MaximumCacheSize = (UINT16)TotalSize; + InstalledSize = (UINT16)TotalSize; + } + else // 64K granularity + { + MaximumCacheSize = (UINT16)(TotalSize >> 6); + InstalledSize = (UINT16)(TotalSize >> 6); + + // Set BIT15 to 1 + MaximumCacheSize |= BIT15; + InstalledSize |= BIT15; + } + + mSmbiosCacheTable[CacheLevel].MaximumCacheSize = MaximumCacheSize; + mSmbiosCacheTable[CacheLevel].InstalledSize = InstalledSize; + + // + // Set SRAM Type + // + CacheSramType.Synchronous = 1; + (VOID)CopyMem(&mSmbiosCacheTable[CacheLevel].SupportedSRAMType, &CacheSramType, sizeof(CACHE_SRAM_TYPE_DATA)); + (VOID)CopyMem(&mSmbiosCacheTable[CacheLevel].CurrentSRAMType, &CacheSramType, sizeof(CACHE_SRAM_TYPE_DATA)); +} + +/** + Add Type 7 SMBIOS Record for Cache Information. + + @param[in] ProcessorNumber Processor number of specified processor. + @param[out] L1CacheHandle Pointer to the handle of the L1 Cache SMBIOS record. + @param[out] L2CacheHandle Pointer to the handle of the L2 Cache SMBIOS record. + @param[out] L3CacheHandle Pointer to the handle of the L3 Cache SMBIOS record. + +**/ +EFI_STATUS +AddSmbiosCacheTypeTable ( + IN UINTN ProcessorNumber, + OUT EFI_SMBIOS_HANDLE *L1CacheHandle, + OUT EFI_SMBIOS_HANDLE *L2CacheHandle, + OUT EFI_SMBIOS_HANDLE *L3CacheHandle + ) +{ + EFI_STATUS Status; + SMBIOS_TABLE_TYPE7 *Type7Record; + EFI_SMBIOS_HANDLE SmbiosHandle; + UINTN TableSize; + UINT8 CacheLevel; + CHAR8 *OptionalStrStart; + EFI_STRING CacheSocketStr; + UINTN CacheSocketStrLen; + UINTN StringBufferSize; + + Status = EFI_SUCCESS; + + // + // Get Cache information + // + for(CacheLevel = 0; CacheLevel < MAX_CACHE_LEVEL; CacheLevel++) + { + Type7Record = NULL; + + if(mSmbiosCacheTable[CacheLevel].InstalledSize == 0) + { + continue; + } + + // + // Update Cache information + // + if (mSmbiosCacheTable[CacheLevel].MaximumCacheSize == 0) + { + UpdateSmbiosCacheTable (CacheLevel); + } + + StringBufferSize = sizeof(CHAR16) * SMBIOS_STRING_MAX_LENGTH; + CacheSocketStr = AllocateZeroPool(StringBufferSize); + if (CacheSocketStr == NULL) + { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + CacheSocketStrLen = GetCacheSocketStr (CacheLevel, CacheSocketStr); + + TableSize = sizeof(SMBIOS_TABLE_TYPE7) + CacheSocketStrLen + 1 + 1; + Type7Record = AllocateZeroPool (TableSize); + if (Type7Record == NULL) + { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + (VOID)CopyMem(Type7Record, &mSmbiosCacheTable[CacheLevel], sizeof (SMBIOS_TABLE_TYPE7)); + + OptionalStrStart = (CHAR8 *) (Type7Record + 1); + UnicodeStrToAsciiStr (CacheSocketStr, OptionalStrStart); + + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + Status = mSmbios->Add (mSmbios, NULL, &SmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *)Type7Record); + if (EFI_ERROR (Status)) + { + goto Exit; + } + + // Config L1/L2/L3 Cache Handle + switch(CacheLevel) + { + case CPU_CACHE_L1_Instruction: + case CPU_CACHE_L1_Data: + *L1CacheHandle = SmbiosHandle; + break; + case CPU_CACHE_L2: + *L2CacheHandle = SmbiosHandle; + break; + case CPU_CACHE_L3: + *L3CacheHandle = SmbiosHandle; + break; + default : + break; + } +Exit: + if(Type7Record != NULL) + { + FreePool (Type7Record); + } + if(CacheSocketStr != NULL) + { + FreePool (CacheSocketStr); + CacheSocketStr = NULL; + } + } + + return Status; +} + +/** + Add Type 4 SMBIOS Record for Processor Information. + + @param[in] ProcessorNumber Processor number of specified processor. + +**/ +EFI_STATUS +AddSmbiosProcessorTypeTable ( + IN UINTN ProcessorNumber + ) +{ + EFI_STATUS Status; + SMBIOS_TABLE_TYPE4 *Type4Record; + EFI_SMBIOS_HANDLE SmbiosHandle; + EFI_SMBIOS_HANDLE L1CacheHandle; + EFI_SMBIOS_HANDLE L2CacheHandle; + EFI_SMBIOS_HANDLE L3CacheHandle; + + CHAR8 *OptionalStrStart; + EFI_STRING_ID ProcessorManu; + EFI_STRING_ID ProcessorVersion; + EFI_STRING_ID SerialNumber; + EFI_STRING_ID AssetTag; + EFI_STRING_ID PartNumber; + EFI_STRING ProcessorSocketStr; + EFI_STRING ProcessorManuStr; + EFI_STRING ProcessorVersionStr; + EFI_STRING SerialNumberStr; + EFI_STRING AssetTagStr; + EFI_STRING PartNumberStr; + UINTN ProcessorSocketStrLen; + UINTN ProcessorManuStrLen; + UINTN ProcessorVersionStrLen; + UINTN SerialNumberStrLen; + UINTN AssetTagStrLen; + UINTN PartNumberStrLen; + UINTN StringBufferSize; + UINTN TotalSize; + + UINT8 Voltage; + UINT16 CoreCount; + UINT16 CoreEnabled; + UINT16 ThreadCount; + UINT16 CurrentSpeed; + PROCESSOR_STATUS_DATA ProcessorStatus = {{0}}; + PROCESSOR_CHARACTERISTICS_DATA ProcessorCharacteristics = {{0}}; + + CHAR16 *CpuVersion; + STRING_REF TokenToUpdate; + + UINT64 *ProcessorId; + Type4Record = NULL; + ProcessorManuStr = NULL; + ProcessorVersionStr = NULL; + SerialNumberStr = NULL; + AssetTagStr = NULL; + PartNumberStr = NULL; + + if(OemIsSocketPresent(ProcessorNumber)) //CPU is present + { + Voltage = BIT7 | 9; // 0.9V + + Status = AddSmbiosCacheTypeTable (ProcessorNumber, &L1CacheHandle, &L2CacheHandle, &L3CacheHandle); + if(EFI_ERROR(Status)) + { + return Status; + } + + CurrentSpeed = GetCpuFrequency(ProcessorNumber); + + CoreCount = PlatformGetCoreCount(); + CoreEnabled = CoreCount; + ThreadCount = CoreCount; + + CpuVersion = (CHAR16 *) PcdGetPtr (PcdCPUInfo); + if (StrLen(CpuVersion) > 0) + { + TokenToUpdate = STRING_TOKEN (STR_PROCESSOR_VERSION); + HiiSetString (mHiiHandle, TokenToUpdate, CpuVersion, NULL); + } + + ProcessorManu = STRING_TOKEN (STR_PROCESSOR_MANUFACTURE); + ProcessorVersion = STRING_TOKEN (STR_PROCESSOR_VERSION); + SerialNumber = STRING_TOKEN (STR_PROCESSOR_SERIAL_NUMBER); + AssetTag = STRING_TOKEN (STR_PROCESSOR_ASSET_TAG); + PartNumber = STRING_TOKEN (STR_PROCESSOR_PART_NUMBER); + + // Processor Status + ProcessorStatus.Bits.CpuStatus = 1; // CPU Enabled + ProcessorStatus.Bits.Reserved1 = 0; + ProcessorStatus.Bits.SocketPopulated = 1; // CPU Socket Populated + ProcessorStatus.Bits.Reserved2 = 0; + + // Processor Characteristics + ProcessorCharacteristics.Bits.Reserved = 0; + ProcessorCharacteristics.Bits.Capable64Bit = 1; // 64-bit Capable + ProcessorCharacteristics.Bits.Unknown = 0; + ProcessorCharacteristics.Bits.EnhancedVirtualization = 1; + ProcessorCharacteristics.Bits.HardwareThread = 0; + ProcessorCharacteristics.Bits.MultiCore = 1; + ProcessorCharacteristics.Bits.ExecuteProtection = 1; + ProcessorCharacteristics.Bits.PowerPerformanceControl = 1; + ProcessorCharacteristics.Bits.Reserved2 = 0; + } + else + { + Voltage = 0; + CurrentSpeed = 0; + CoreCount = 0; + CoreEnabled = 0; + ThreadCount = 0; + L1CacheHandle = 0xFFFF; + L2CacheHandle = 0xFFFF; + L3CacheHandle = 0xFFFF; + + ProcessorManu = STRING_TOKEN (STR_PROCESSOR_UNKNOWN); + ProcessorVersion = STRING_TOKEN (STR_PROCESSOR_UNKNOWN); + SerialNumber = STRING_TOKEN (STR_PROCESSOR_UNKNOWN); + AssetTag = STRING_TOKEN (STR_PROCESSOR_UNKNOWN); + PartNumber = STRING_TOKEN (STR_PROCESSOR_UNKNOWN); + } + + // Processor Socket Designation + StringBufferSize = sizeof(CHAR16) * SMBIOS_STRING_MAX_LENGTH; + ProcessorSocketStr = AllocateZeroPool(StringBufferSize); + if (ProcessorSocketStr == NULL) + { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + ProcessorSocketStrLen = UnicodeSPrint (ProcessorSocketStr, StringBufferSize, L"CPU%02d", ProcessorNumber + 1); + + // Processor Manufacture + ProcessorManuStr = HiiGetPackageString (&gEfiCallerIdGuid, ProcessorManu, NULL); + ProcessorManuStrLen = StrLen (ProcessorManuStr); + + // Processor Version + ProcessorVersionStr = HiiGetPackageString (&gEfiCallerIdGuid, ProcessorVersion, NULL); + ProcessorVersionStrLen = StrLen (ProcessorVersionStr); + + // Serial Number + SerialNumberStr = HiiGetPackageString (&gEfiCallerIdGuid, SerialNumber, NULL); + SerialNumberStrLen = StrLen (SerialNumberStr); + + // Asset Tag + AssetTagStr = HiiGetPackageString (&gEfiCallerIdGuid, AssetTag, NULL); + AssetTagStrLen = StrLen (AssetTagStr); + + // Part Number + PartNumberStr = HiiGetPackageString (&gEfiCallerIdGuid, PartNumber, NULL); + PartNumberStrLen = StrLen (PartNumberStr); + + TotalSize = sizeof (SMBIOS_TABLE_TYPE4) + ProcessorSocketStrLen + 1 + ProcessorManuStrLen + 1 + ProcessorVersionStrLen + 1 + SerialNumberStrLen + 1 + AssetTagStrLen + 1 + PartNumberStrLen + 1 + 1; + Type4Record = AllocateZeroPool (TotalSize); + if (Type4Record == NULL) + { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + (VOID)CopyMem(Type4Record, &mSmbiosProcessorTable[ProcessorNumber], sizeof (SMBIOS_TABLE_TYPE4)); + + *(UINT8 *) &Type4Record->Voltage = Voltage; + Type4Record->CurrentSpeed = CurrentSpeed; + Type4Record->Status = ProcessorStatus.Data; + Type4Record->L1CacheHandle = L1CacheHandle; + Type4Record->L2CacheHandle = L2CacheHandle; + Type4Record->L3CacheHandle = L3CacheHandle; + Type4Record->CoreCount = CoreCount; + Type4Record->EnabledCoreCount = CoreEnabled; + Type4Record->ThreadCount = ThreadCount; + Type4Record->ProcessorCharacteristics = ProcessorCharacteristics.Data; + + Type4Record->ExternalClock = (UINT16)(ArmReadCntFrq() / 1000 / 1000); + ProcessorId = (UINT64 *)&(Type4Record->ProcessorId); + *ProcessorId = ArmReadMidr(); + + OptionalStrStart = (CHAR8 *) (Type4Record + 1); + UnicodeStrToAsciiStr (ProcessorSocketStr, OptionalStrStart); + UnicodeStrToAsciiStr (ProcessorManuStr, OptionalStrStart + ProcessorSocketStrLen + 1); + UnicodeStrToAsciiStr (ProcessorVersionStr, OptionalStrStart + ProcessorSocketStrLen + 1 + ProcessorManuStrLen + 1); + UnicodeStrToAsciiStr (SerialNumberStr, OptionalStrStart + ProcessorSocketStrLen + 1 + ProcessorManuStrLen + 1 + ProcessorVersionStrLen + 1); + UnicodeStrToAsciiStr (AssetTagStr, OptionalStrStart + ProcessorSocketStrLen + 1 + ProcessorManuStrLen + 1 + ProcessorVersionStrLen + 1 + SerialNumberStrLen + 1); + UnicodeStrToAsciiStr (PartNumberStr, OptionalStrStart + ProcessorSocketStrLen + 1 + ProcessorManuStrLen + 1 + ProcessorVersionStrLen + 1 + SerialNumberStrLen + 1 + AssetTagStrLen + 1); + + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + Status = mSmbios->Add (mSmbios, NULL, &SmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *)Type4Record); + if (EFI_ERROR (Status)) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type04 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status)); + } + FreePool (Type4Record); + +Exit: + if(ProcessorSocketStr != NULL) + { + FreePool (ProcessorSocketStr); + } + if(ProcessorManuStr != NULL) + { + FreePool (ProcessorManuStr); + } + if(ProcessorVersionStr != NULL) + { + FreePool (ProcessorVersionStr); + } + if(SerialNumberStr != NULL) + { + FreePool (SerialNumberStr); + } + if(AssetTagStr != NULL) + { + FreePool (AssetTagStr); + } + if(PartNumberStr != NULL) + { + FreePool (PartNumberStr); + } + + return Status; +} + +/** + Standard EFI driver point. This driver locates the ProcessorConfigurationData Variable, + if it exists, add the related SMBIOS tables by PI SMBIOS protocol. + + @param ImageHandle Handle for the image of this driver + @param SystemTable Pointer to the EFI System Table + + @retval EFI_SUCCESS The data was successfully stored. + +**/ +EFI_STATUS +EFIAPI +ProcessorSubClassEntryPoint( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINT32 SocketIndex; + + // + // Locate dependent protocols + // + Status = gBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, (VOID**)&mSmbios); + if (EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "Could not locate SMBIOS protocol. %r\n", Status)); + return Status; + } + + // + // Add our default strings to the HII database. They will be modified later. + // + mHiiHandle = HiiAddPackages ( + &gEfiCallerIdGuid, + NULL, + ProcessorSubClassStrings, + NULL, + NULL + ); + if (mHiiHandle == NULL) + { + return EFI_OUT_OF_RESOURCES; + } + + // + // Add SMBIOS tables for populated sockets. + // + for (SocketIndex = 0; SocketIndex < MAX_SOCKET; SocketIndex++) + { + if((SocketIndex == 1) && !OemIsMpBoot()) + { + break; + } + Status = AddSmbiosProcessorTypeTable (SocketIndex); + if(EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "Add Processor Type Table Failed! %r.\n", Status)); + return Status; + } + } + + return Status; +} diff --git a/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClass.h b/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClass.h new file mode 100644 index 0000000000..6ddc6cf590 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClass.h @@ -0,0 +1,108 @@ +/** @file +* +* Copyright (c) 2015, Hisilicon Limited. All rights reserved. +* Copyright (c) 2015, Linaro Limited. 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. +* +**/ + +#ifndef _PROCESSOR_SUBCLASS_DRIVER_H +#define _PROCESSOR_SUBCLASS_DRIVER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// This is the generated header file which includes whatever needs to be exported (strings + IFR) +// + +extern UINT8 ProcessorSubClassStrings[]; + +#define CPU_CACHE_L1_Instruction 0 +#define CPU_CACHE_L1_Data 1 +#define CPU_CACHE_L2 2 +#define CPU_CACHE_L3 3 +#define MAX_CACHE_LEVEL 4 + +#define EXTERNAL_CLOCK 50 //50 MHz +#define CPU_MAX_SPEED 2100 //2.1G + +// +// Cache Info +// +typedef struct { + UINT16 InstalledSize; //In KB + CACHE_TYPE_DATA SystemCacheType; + CACHE_ASSOCIATIVITY_DATA Associativity; +} CACHE_INFO; + +// +// Cache Configuration +// +typedef union { + struct { + UINT16 Level :3; + UINT16 Socketed :1; + UINT16 Reserved1 :1; + UINT16 Location :2; + UINT16 Enable :1; + UINT16 OperationalMode :2; + UINT16 Reserved2 :6; + } Bits; + UINT16 Data; +}CACHE_CONFIGURATION; + +// +// Processor Status +// +typedef union { + struct { + UINT8 CpuStatus :3; // Indicates the status of the processor. + UINT8 Reserved1 :3; // Reserved for future use. Should be set to zero. + UINT8 SocketPopulated :1; // Indicates if the processor socket is populated or not. + UINT8 Reserved2 :1; // Reserved for future use. Should be set to zero. + } Bits; + UINT8 Data; +}PROCESSOR_STATUS_DATA; + +// +// Processor Characteristics +// +typedef union { + struct { + UINT16 Reserved :1; + UINT16 Unknown :1; + UINT16 Capable64Bit :1; + UINT16 MultiCore :1; + UINT16 HardwareThread :1; + UINT16 ExecuteProtection :1; + UINT16 EnhancedVirtualization :1; + UINT16 PowerPerformanceControl :1; + UINT16 Reserved2 :8; + } Bits; + UINT16 Data; +} PROCESSOR_CHARACTERISTICS_DATA; + +#endif diff --git a/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf b/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf new file mode 100644 index 0000000000..2275586ff3 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf @@ -0,0 +1,64 @@ +#/** @file +# +# Copyright (c) 2015, Hisilicon Limited. All rights reserved. +# Copyright (c) 2015, Linaro Limited. 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. +# +#**/ + + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ProcessorSubClass + FILE_GUID = 9B25B1EA-0FD4-455D-A450-AD640C8A9C1B + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = ProcessorSubClassEntryPoint + +[Sources] + ProcessorSubClassStrings.uni + ProcessorSubClass.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + IoLib + HiiLib + MemoryAllocationLib + BaseMemoryLib + BaseLib + DebugLib + PrintLib + PcdLib + + PlatformSysCtrlLib + OemMiscLib + +[Protocols] + gEfiSmbiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED + +[Pcd] + gHisiTokenSpaceGuid.PcdCPUInfo + gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz + +[Guids] + + +[Depex] + gEfiSmbiosProtocolGuid + + diff --git a/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni b/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni new file mode 100644 index 0000000000..d2928faf93 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni @@ -0,0 +1,32 @@ +///// @file +// +// Copyright (c) 2015, Hisilicon Limited. All rights reserved. +// Copyright (c) 2015, Linaro Limited. 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. +// +///// + +/=# + +#langdef en-US "English" + +// +// Processor Information +// +#string STR_PROCESSOR_SOCKET_DESIGNATION #language en-US "Hisilicon PhosphorV660 Processor" +#string STR_PROCESSOR_MANUFACTURE #language en-US "Hisilicon" +#string STR_PROCESSOR_VERSION #language en-US "Hi1610ES" +#string STR_PROCESSOR_SERIAL_NUMBER #language en-US "To be filled by O.E.M." +#string STR_PROCESSOR_ASSET_TAG #language en-US "To be filled by O.E.M." +#string STR_PROCESSOR_PART_NUMBER #language en-US "To be filled by O.E.M." +#string STR_PROCESSOR_UNKNOWN #language en-US "Unknown" + + + diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMisc.h b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMisc.h new file mode 100644 index 0000000000..66f9db9665 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMisc.h @@ -0,0 +1,226 @@ +/**@file + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+Copyright (c) 2015, Linaro Limited. 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: + + SmbiosMisc.h + +Abstract: + + Header file for the SmbiosMisc Driver. + +Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ +**/ + +#ifndef _SMBIOS_MISC_DRIVER_H +#define _SMBIOS_MISC_DRIVER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// +// Data table entry update function. +// +typedef EFI_STATUS (EFIAPI EFI_MISC_SMBIOS_DATA_FUNCTION) ( + IN VOID *RecordData, + IN EFI_SMBIOS_PROTOCOL *Smbios + ); + + +// +// Data table entry definition. +// +typedef struct { + // + // intermediat input data for SMBIOS record + // + VOID *RecordData; + EFI_MISC_SMBIOS_DATA_FUNCTION *Function; +} EFI_MISC_SMBIOS_DATA_TABLE; + + +// +// Data Table extern definitions. +// +#define MISC_SMBIOS_TABLE_EXTERNS(NAME1, NAME2, NAME3) \ +extern NAME1 NAME2 ## Data; \ +extern EFI_MISC_SMBIOS_DATA_FUNCTION NAME3 ## Function; + + +// +// Data Table entries +// + +#define MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(NAME1, NAME2) \ +{ \ + & NAME1 ## Data, \ + NAME2 ## Function \ +} + + +// +// Global definition macros. +// +#define MISC_SMBIOS_TABLE_DATA(NAME1, NAME2) \ + NAME1 NAME2 ## Data + +#define MISC_SMBIOS_TABLE_FUNCTION(NAME2) \ + EFI_STATUS EFIAPI NAME2 ## Function( \ + IN VOID *RecordData, \ + IN EFI_SMBIOS_PROTOCOL *Smbios \ + ) + +// +// Data Table Array Entries +// +extern EFI_HII_HANDLE mHiiHandle; + +typedef struct _EFI_TYPE11_OEM_STRING{ + UINT8 Offset; + EFI_STRING_ID RefOemDefineString; +} EFI_TYPE11_OEM_STRING; + +typedef struct _EFI_TYPE12_SYSTEM_CONFIGURATION_OPTIONS_STRING{ + UINT8 Offset; + EFI_STRING_ID RefType12SystemConfigurationOptionsString; +} EFI_TYPE12_SYSTEM_CONFIGURATION_OPTIONS_STRING; + +typedef struct _EFI_TYPE13_BIOS_LANGUAGE_INFORMATION_STRING{ + UINT8 *LanguageSignature; + EFI_STRING_ID InstallableLanguageLongString; + EFI_STRING_ID InstallableLanguageAbbreviateString; +} EFI_TYPE13_BIOS_LANGUAGE_INFORMATION_STRING; + +typedef struct _EFI_TYPE40_ADDITIONAL_INFORMATION_ENTRY{ + UINT8 RefType; + UINT8 RefOffset; + EFI_STRING_ID RefString; + UINT8 Value; +} EFI_TYPE40_ADDITIONAL_INFORMATION_ENTRY; + +typedef enum { + STRING, + DATA, +} OEM_DEFINE_TYPE; + +typedef struct { + OEM_DEFINE_TYPE Type; + UINTN Token; + UINTN DataSize; +} OEM_DEFINE_INFO_STRING; + +typedef struct { + OEM_DEFINE_TYPE Type; + UINTN DataAddress; + UINTN DataSize; +} OEM_DEFINE_INFO_DATA; + +typedef union { + OEM_DEFINE_INFO_STRING DefineString; + OEM_DEFINE_INFO_DATA DefineData; +} EFI_OEM_DEFINE_ARRAY; + +typedef struct _DMI_STRING_STRUCTURE { + UINT8 Type; + UINT8 Offset; + UINT8 Valid; + UINT16 Length; + UINT8 String[1]; // Variable length field +} DMI_STRING_STRUCTURE; + +typedef struct { + UINT8 Type; // The SMBIOS structure type + UINT8 FixedOffset; // The offset of the string reference + // within the structure's fixed data. +} DMI_UPDATABLE_STRING; + +EFI_STATUS +FindString ( + IN UINT8 Type, + IN UINT8 Offset, + IN EFI_STRING_ID TokenToUpdate +); + +EFI_STATUS +FindUuid ( + EFI_GUID *Uuid +); + +EFI_STATUS +StringToBiosVeriosn ( + IN EFI_STRING_ID BiosVersionToken, + OUT UINT8 *MajorVersion, + OUT UINT8 *MinorVersion +); + + +/** + Logs SMBIOS record. + + @param [in] Buffer Pointer to the data buffer. + @param [in] SmbiosHandle Pointer for retrieve handle. + +**/ +EFI_STATUS +LogSmbiosData ( + IN UINT8 *Buffer, + IN OUT EFI_SMBIOS_HANDLE *SmbiosHandle + ); + +/** + Get Link Type Handle. + + @param [in] SmbiosType Get this Type from SMBIOS table + @param [out] HandleArray Pointer to Hadndler array with has been free by caller + @param [out] HandleCount Pointer to Hadndler Counter + +**/ +VOID +GetLinkTypeHandle( + IN UINT8 SmbiosType, + OUT UINT16 **HandleArray, + OUT UINTN *HandleCount + ); + +typedef enum { + ProductNameType01, + SerialNumType01, + UuidType01, + SystemManufacturerType01, + AssertTagType02, + SrNumType02, + BoardManufacturerType02, + AssetTagType03, + SrNumType03, + VersionType03, + ChassisTypeType03 , + ManufacturerType03, +} GET_INFO_BMC_OFFSET; + +VOID UpdateSmbiosInfo (IN EFI_HII_HANDLE mHiiHandle, IN EFI_STRING_ID TokenToUpdate, IN UINT8 Offset); +EFI_STATUS GetUuidType1 (IN OUT EFI_GUID *Uuid); +EFI_STATUS IpmiGetChassisType (IN OUT UINT8 *Type); +#endif diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscDataTable.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscDataTable.c new file mode 100644 index 0000000000..8e00865712 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscDataTable.c @@ -0,0 +1,58 @@ +/**@file + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+Copyright (c) 2015, Linaro Limited. 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: + + SmbiosMiscDataTable.c + +Abstract: + + This file provide OEM to config SMBIOS Misc Type. + +Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ +**/ + +#include "SmbiosMisc.h" + + MISC_SMBIOS_TABLE_EXTERNS(SMBIOS_TABLE_TYPE0, MiscBiosVendor, MiscBiosVendor) + MISC_SMBIOS_TABLE_EXTERNS(SMBIOS_TABLE_TYPE1, MiscSystemManufacturer, MiscSystemManufacturer) + MISC_SMBIOS_TABLE_EXTERNS(SMBIOS_TABLE_TYPE3, MiscChassisManufacturer, MiscChassisManufacturer) + MISC_SMBIOS_TABLE_EXTERNS(SMBIOS_TABLE_TYPE2, MiscBaseBoardManufacturer, MiscBaseBoardManufacturer) + MISC_SMBIOS_TABLE_EXTERNS(SMBIOS_TABLE_TYPE13, MiscNumberOfInstallableLanguages, MiscNumberOfInstallableLanguages) + MISC_SMBIOS_TABLE_EXTERNS(SMBIOS_TABLE_TYPE32, MiscBootInformation, MiscBootInformation) + MISC_SMBIOS_TABLE_EXTERNS(SMBIOS_TABLE_TYPE38, MiscIpmiDeviceInformation, MiscIpmiDeviceInformation) + + +EFI_MISC_SMBIOS_DATA_TABLE mSmbiosMiscDataTable[] = { + // Type0 + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscBiosVendor, MiscBiosVendor), + // Type1 + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemManufacturer, MiscSystemManufacturer), + // Type3 + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscChassisManufacturer, MiscChassisManufacturer), + // Type2 + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscBaseBoardManufacturer, MiscBaseBoardManufacturer), + // Type13 + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscNumberOfInstallableLanguages, MiscNumberOfInstallableLanguages), + // Type32 + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscBootInformation, MiscBootInformation), + // Type38 + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscIpmiDeviceInformation, MiscIpmiDeviceInformation), +}; + + +// +// Number of Data Table entries. +// +UINTN mSmbiosMiscDataTableEntries = + (sizeof mSmbiosMiscDataTable) / sizeof(EFI_MISC_SMBIOS_DATA_TABLE); diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf new file mode 100644 index 0000000000..61cead7779 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf @@ -0,0 +1,108 @@ +## @file +# Component description file for SmbiosMisc instance. +# +# Parses the MiscSubclassDataTable and reports any generated data to the DataHub. +# All .uni file who tagged with "ToolCode="DUMMY"" in following file list is included by +# MiscSubclassDriver.uni file, the StrGather tool will expand MiscSubclassDriver.uni file +# and parse all .uni file. +# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+# Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+# Copyright (c) 2015, Linaro Limited. 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. +# +# +# Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ +## + + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmbiosMiscDxe + FILE_GUID = EF0C99B6-B1D3-4025-9405-BF6A560FE0E0 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = SmbiosMiscEntryPoint + +[Sources] + SmbiosMisc.h + SmbiosMiscDataTable.c + SmbiosMiscEntryPoint.c + SmbiosMiscLibString.uni + ./Type00/MiscBiosVendorData.c + ./Type00/MiscBiosVendorFunction.c + ./Type01/MiscSystemManufacturerData.c + ./Type01/MiscSystemManufacturerFunction.c + ./Type02/MiscBaseBoardManufacturerData.c + ./Type02/MiscBaseBoardManufacturerFunction.c + ./Type03/MiscChassisManufacturerData.c + ./Type03/MiscChassisManufacturerFunction.c + ./Type13/MiscNumberOfInstallableLanguagesData.c + ./Type13/MiscNumberOfInstallableLanguagesFunction.c + ./Type32/MiscBootInformationData.c + ./Type32/MiscBootInformationFunction.c + ./Type38/MiscIpmiDeviceInformationData.c + ./Type38/MiscIpmiDeviceInformationFunction.c + + ./Type09/MiscSystemSlotDesignationData.c + ./Type09/MiscSystemSlotDesignationFunction.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + PcdLib + HiiLib + MemoryAllocationLib + DevicePathLib + BaseMemoryLib + BaseLib + DebugLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiDriverEntryPoint + UefiLib + HobLib + + IpmiCmdLib + + SerdesLib + +[Protocols] + gEfiSmbiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED + +[Pcd] + gArmTokenSpaceGuid.PcdFdSize + gHisiTokenSpaceGuid.PcdFirmwareVendor + gHisiTokenSpaceGuid.PcdBiosVersionString + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareReleaseDateString + + gHisiTokenSpaceGuid.PcdSystemProductName + gHisiTokenSpaceGuid.PcdSystemVersion + gHisiTokenSpaceGuid.PcdBaseBoardProductName + gHisiTokenSpaceGuid.PcdBaseBoardVersion + gArmTokenSpaceGuid.PcdFdBaseAddress + + gHisiTokenSpaceGuid.PcdBiosVersionForBmc + + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang + +[Guids] + gEfiGenericVariableGuid + gVersionInfoHobGuid + +[Depex] + gEfiSmbiosProtocolGuid + + diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscEntryPoint.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscEntryPoint.c new file mode 100644 index 0000000000..051410b527 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscEntryPoint.c @@ -0,0 +1,194 @@ +/**@file + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+Copyright (c) 2015, Linaro Limited. 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: + + SmbiosMiscEntryPoint.c + +Abstract: + + This driver parses the mSmbiosMiscDataTable structure and reports + any generated data using SMBIOS protocol. + +Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ +**/ + +#include "SmbiosMisc.h" + +#define MAX_HANDLE_COUNT 0x10 + +EFI_HANDLE mImageHandle; +EFI_HII_HANDLE mHiiHandle; +EFI_SMBIOS_PROTOCOL *mSmbios = NULL; + +// +// Data Table Array +// +extern EFI_MISC_SMBIOS_DATA_TABLE mSmbiosMiscDataTable[]; +// +// Data Table Array Entries +// +extern UINTN mSmbiosMiscDataTableEntries; + +extern UINT8 SmbiosMiscDxeStrings[]; + + + +/** + Standard EFI driver point. This driver parses the mSmbiosMiscDataTable + structure and reports any generated data using SMBIOS protocol. + + @param ImageHandle Handle for the image of this driver + @param SystemTable Pointer to the EFI System Table + + @retval EFI_SUCCESS The data was successfully stored. + +**/ +EFI_STATUS +EFIAPI +SmbiosMiscEntryPoint( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + UINTN Index; + EFI_STATUS EfiStatus; + EFI_SMBIOS_PROTOCOL *Smbios; + + mImageHandle = ImageHandle; + + EfiStatus = gBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, (VOID**)&Smbios); + if (EFI_ERROR(EfiStatus)) + { + DEBUG((EFI_D_ERROR, "Could not locate SMBIOS protocol. %r\n", EfiStatus)); + return EfiStatus; + } + + mSmbios = Smbios; + + mHiiHandle = HiiAddPackages ( + &gEfiCallerIdGuid, + mImageHandle, + SmbiosMiscDxeStrings, + NULL + ); + if(mHiiHandle == NULL) + { + return EFI_OUT_OF_RESOURCES; + } + + for (Index = 0; Index < mSmbiosMiscDataTableEntries; ++Index) + { + // + // If the entry have a function pointer, just log the data. + // + if (mSmbiosMiscDataTable[Index].Function != NULL) + { + EfiStatus = (*mSmbiosMiscDataTable[Index].Function)( + mSmbiosMiscDataTable[Index].RecordData, + Smbios + ); + + if (EFI_ERROR(EfiStatus)) + { + DEBUG((EFI_D_ERROR, "Misc smbios store error. Index=%d, ReturnStatus=%r\n", Index, EfiStatus)); + return EfiStatus; + } + } + } + + return EfiStatus; +} + + +/** + Logs SMBIOS record. + + @param Buffer The data for the fixed portion of the SMBIOS record. The format of the record is + determined by EFI_SMBIOS_TABLE_HEADER.Type. The size of the formatted area is defined + by EFI_SMBIOS_TABLE_HEADER.Length and either followed by a double-null (0x0000) or + a set of null terminated strings and a null. + @param SmbiosHandle A unique handle will be assigned to the SMBIOS record. + + @retval EFI_SUCCESS Record was added. + @retval EFI_OUT_OF_RESOURCES Record was not added due to lack of system resources. + +**/ +EFI_STATUS +LogSmbiosData ( + IN UINT8 *Buffer, + IN OUT EFI_SMBIOS_HANDLE *SmbiosHandle + ) +{ + EFI_STATUS Status; + + *SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + + Status = mSmbios->Add ( + mSmbios, + NULL, + SmbiosHandle, + (EFI_SMBIOS_TABLE_HEADER *)Buffer + ); + + return Status; +} + + +VOID +GetLinkTypeHandle( + IN UINT8 SmbiosType, + OUT UINT16 **HandleArray, + OUT UINTN *HandleCount + ) +{ + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + EFI_SMBIOS_TABLE_HEADER *LinkTypeData = NULL; + + if(mSmbios == NULL) + return ; + + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + + *HandleArray = AllocateZeroPool(sizeof(UINT16) * MAX_HANDLE_COUNT); + if (*HandleArray == NULL) + { + DEBUG ((EFI_D_INFO, "HandleArray allocate memory resource failed.\n")); + return; + } + + *HandleCount = 0; + + while(1) + { + Status = mSmbios->GetNext( + mSmbios, + &SmbiosHandle, + &SmbiosType, + &LinkTypeData, + NULL + ); + + if(!EFI_ERROR(Status)) + { + (*HandleArray)[*HandleCount] = LinkTypeData->Handle; + (*HandleCount)++; + } + else + { + break; + } + } +} + diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscLibString.uni b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscLibString.uni new file mode 100644 index 0000000000..2e434e323a --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscLibString.uni @@ -0,0 +1,28 @@ +// *++ +// +// Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+// Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+// Copyright (c) 2015, Linaro Limited. 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. +// +// Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ +// --*/ + + +/=# + +#langdef en-US "English" + +#include "./Type00/MiscBiosVendor.uni" +#include "./Type01/MiscSystemManufacturer.uni" +#include "./Type02/MiscBaseBoardManufacturer.uni" +#include "./Type03/MiscChassisManufacturer.uni" +#include "./Type13/MiscNumberOfInstallableLanguages.uni" +#include "./Type09/MiscSystemSlotDesignation.uni" diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendor.uni b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendor.uni new file mode 100644 index 0000000000..215952a560 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendor.uni @@ -0,0 +1,25 @@ +// *++ +// +// Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+// Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+// Copyright (c) 2015, Linaro Limited. 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. +// +// Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ +// --*/ + +/=# + +//#string STR_MISC_BIOS_VENDOR #language en-US "Bios Vendor" +#string STR_MISC_BIOS_VERSION #language en-US "Bios Version" +//#string STR_MISC_BIOS_RELEASE_DATE #language en-US "Bios Release Date" + +#string STR_MISC_BIOS_VENDOR #language en-US "Huawei Technologies Co., Ltd." +#string STR_MISC_BIOS_RELEASE_DATE #language en-US "01/01/1900" diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorData.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorData.c new file mode 100644 index 0000000000..b822768b44 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorData.c @@ -0,0 +1,105 @@ +/*++ + +Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+Copyright (c) 2015, Linaro Limited. 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: + + MiscBiosVendorData.c + +Abstract: + + This file provide OEM to define Smbios Type0 Data + +Based on the files under Nt32Pkg/MiscSubClassPlatformDxe/ + +**/ + + +#include "SmbiosMisc.h" + + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE0, MiscBiosVendor) = { + { //Hdr + EFI_SMBIOS_TYPE_BIOS_INFORMATION, // Type, + 0, // Length, + 0 // Handle + }, + 1, //Vendor + 2, //BiosVersion + 0xE000, //BiosSegment + 3, //BiosReleaseDate + 0, //BiosSize + { //BiosCharacteristics + 0, // Reserved :2 + 0, // Unknown :1 + 0, // BiosCharacteristicsNotSupported :1 + 0, // IsaIsSupported :1 + 0, // McaIsSupported :1 + 0, // EisaIsSupported :1 + 1, // PciIsSupported :1 + 0, // PcmciaIsSupported :1 + 0, // PlugAndPlayIsSupported :1 + 0, // ApmIsSupported :1 + 1, // BiosIsUpgradable :1 + 1, // BiosShadowingAllowed :1 + 0, // VlVesaIsSupported :1 + 0, // EscdSupportIsAvailable :1 + 1, // BootFromCdIsSupported :1 + 1, // SelectableBootIsSupported :1 + 0, // RomBiosIsSocketed :1 + 0, // BootFromPcmciaIsSupported :1 + 1, // EDDSpecificationIsSupported :1 + 1, // JapaneseNecFloppyIsSupported :1 + 1, // JapaneseToshibaFloppyIsSupported :1 + 1, // Floppy525_360IsSupported :1 + 1, // Floppy525_12IsSupported :1 + 1, // Floppy35_720IsSupported :1 + 1, // Floppy35_288IsSupported :1 + 0, // PrintScreenIsSupported :1 + 1, // Keyboard8042IsSupported :1 + 0, // SerialIsSupported :1 + 0, // PrinterIsSupported :1 + 1, // CgaMonoIsSupported :1 + 0, // NecPc98 :1 + 0 // ReservedForVendor :32 + }, + + { + 0x03, //BIOSCharacteristicsExtensionBytes[0] + // { //BiosReserved + // 1, // AcpiIsSupported :1 + // 1, // UsbLegacyIsSupported :1 + // 0, // AgpIsSupported :1 + // 0, // I20BootIsSupported :1 + // 0, // Ls120BootIsSupported :1 + // 0, // AtapiZipDriveBootIsSupported :1 + // 0, // Boot1394IsSupported :1 + // 0 // SmartBatteryIsSupported :1 + // }, + 0x0D //BIOSCharacteristicsExtensionBytes[1] + // { //SystemReserved + // 1, //BiosBootSpecIsSupported :1 + // 0, //FunctionKeyNetworkBootIsSupported :1 + // 1, //TargetContentDistributionEnabled :1 + // 1, //UefiSpecificationSupported :1 + // 0, //VirtualMachineSupported :1 + // 0 //ExtensionByte2Reserved :3 + // }, + }, + 0, //SystemBiosMajorRelease; + 0, //SystemBiosMinorRelease; + 0xFF, //EmbeddedControllerFirmwareMajorRelease; + 0xFF //EmbeddedControllerFirmwareMinorRelease; +}; diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c new file mode 100644 index 0000000000..9a42f04085 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c @@ -0,0 +1,258 @@ +/** @file + + Copyright (c) 2009, Intel Corporation. All rights reserved.
+ Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+ Copyright (c) 2015, Linaro Limited. 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: + + MiscBiosVendorData.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + +Based on the files under Nt32Pkg/MiscSubClassPlatformDxe/ + +--*/ + +// +#include "SmbiosMisc.h" +#include +#include + + +/** + Field Filling Function. Transform an EFI_EXP_BASE2_DATA to a byte, with '64k' + as the unit. + + @param Value Pointer to Base2_Data + + @retval + +**/ +UINT8 +Base2ToByteWith64KUnit ( + IN UINTN Value + ) +{ + UINT8 Size; + + Size = Value / SIZE_64KB + (Value % SIZE_64KB + SIZE_64KB - 1) / SIZE_64KB; + + return Size; +} + + +/** + +**/ +VOID * +GetBiosReleaseDate ( + ) +{ + CHAR16 *ReleaseDate = NULL; + VERSION_INFO *Version; + VOID *Hob; + + ReleaseDate = AllocateZeroPool ((sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH); + if(NULL == ReleaseDate) + { + return NULL; + } + + Hob = GetFirstGuidHob (&gVersionInfoHobGuid); + if (Hob == NULL) { + DEBUG ((EFI_D_ERROR, "[%a:%d] Version info HOB not found!\n", __FUNCTION__, __LINE__)); + return NULL; + } + + Version = GET_GUID_HOB_DATA (Hob); + (VOID)UnicodeSPrintAsciiFormat( ReleaseDate, + (sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH, + "%02d/%02d/%4d", + Version->BuildTime.Month, + Version->BuildTime.Day, + Version->BuildTime.Year + ); + + return ReleaseDate; +} + +VOID * +GetBiosVersion ( + ) +{ + VERSION_INFO *Version; + VOID *Hob; + + Hob = GetFirstGuidHob (&gVersionInfoHobGuid); + if (Hob == NULL) { + DEBUG ((EFI_D_ERROR, "[%a:%d] Version info HOB not found!\n", __FUNCTION__, __LINE__)); + return NULL; + } + Version = GET_GUID_HOB_DATA (Hob); + return Version->String; +} + + +/** + This function makes boot time changes to the contents of the + MiscBiosVendor (Type 0). + + @param RecordData Pointer to copy of RecordData from the Data Table. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_UNSUPPORTED Unexpected RecordType value. + @retval EFI_INVALID_PARAMETER Invalid parameter was found. + +**/ +MISC_SMBIOS_TABLE_FUNCTION(MiscBiosVendor) +{ + CHAR8 *OptionalStrStart; + UINTN VendorStrLen; + UINTN VerStrLen; + UINTN DateStrLen; + UINTN BiosPhysicalSizeHexValue; + CHAR16 *Vendor; + CHAR16 *Version; + CHAR16 *ReleaseDate; + CHAR16 *Char16String; + EFI_STATUS Status; + STRING_REF TokenToUpdate; + STRING_REF TokenToGet; + SMBIOS_TABLE_TYPE0 *SmbiosRecord; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE0 *InputData; + + // + // First check for invalid parameters. + // + if (RecordData == NULL) + { + return EFI_INVALID_PARAMETER; + } + + InputData = (SMBIOS_TABLE_TYPE0 *)RecordData; + + Vendor = (CHAR16 *) PcdGetPtr (PcdFirmwareVendor); + if (StrLen(Vendor) > 0) + { + TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_VENDOR); + HiiSetString (mHiiHandle, TokenToUpdate, Vendor, NULL); + } + + Version = GetBiosVersion(); + if (StrLen (Version) > 0) + { + TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_VERSION); + HiiSetString (mHiiHandle, TokenToUpdate, Version, NULL); + } + else + { + Version = (CHAR16 *) PcdGetPtr (PcdBiosVersionForBmc); + if (StrLen (Version) > 0) + { + TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_VERSION); + HiiSetString (mHiiHandle, TokenToUpdate, Version, NULL); + } + else + { + Version = (CHAR16 *) PcdGetPtr (PcdBiosVersionString); + if (StrLen (Version) > 0) + { + TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_VERSION); + HiiSetString (mHiiHandle, TokenToUpdate, Version, NULL); + } + } + } + + Char16String = GetBiosReleaseDate (); + if (StrLen(Char16String) > 0) + { + TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_RELEASE_DATE); + HiiSetString (mHiiHandle, TokenToUpdate, Char16String, NULL); + } + + TokenToGet = STRING_TOKEN (STR_MISC_BIOS_VENDOR); + Vendor = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + VendorStrLen = StrLen(Vendor); + + + TokenToGet = STRING_TOKEN (STR_MISC_BIOS_VERSION); + Version = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + VerStrLen = StrLen(Version); + + + TokenToGet = STRING_TOKEN (STR_MISC_BIOS_RELEASE_DATE); + ReleaseDate = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + DateStrLen = StrLen(ReleaseDate); + + // + // Now update the BiosPhysicalSize + // + BiosPhysicalSizeHexValue = FixedPcdGet32 (PcdFdSize); + + // + // Two zeros following the last string. + // + SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE0) + VendorStrLen + 1 + VerStrLen + 1 + DateStrLen + 1 + 1); + if(NULL == SmbiosRecord) + { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + (VOID)CopyMem(SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE0)); + + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE0); + SmbiosRecord->BiosSegment = (UINT16)(FixedPcdGet32 (PcdFdBaseAddress) / 0x10000); + SmbiosRecord->BiosSize = Base2ToByteWith64KUnit(BiosPhysicalSizeHexValue) - 1; + + OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1); + UnicodeStrToAsciiStr(Vendor, OptionalStrStart); + UnicodeStrToAsciiStr(Version, OptionalStrStart + VendorStrLen + 1); + UnicodeStrToAsciiStr(ReleaseDate, OptionalStrStart + VendorStrLen + 1 + VerStrLen + 1); + // + // Now we have got the full smbios record, call smbios protocol to add this record. + // + Status = LogSmbiosData( (UINT8*)SmbiosRecord, &SmbiosHandle); + if(EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type00 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status)); + } + + FreePool(SmbiosRecord); + +Exit: + if(Vendor != NULL) + { + FreePool(Vendor); + } + + if(Version != NULL) + { + FreePool(Version); + } + + if(ReleaseDate != NULL) + { + FreePool(ReleaseDate); + } + + if(Char16String != NULL) + { + FreePool(Char16String); + } + + return Status; +} diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturer.uni b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturer.uni new file mode 100644 index 0000000000..1632f83880 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturer.uni @@ -0,0 +1,27 @@ +// *++ +// +// Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+// Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+// Copyright (c) 2015, Linaro Limited. 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. +// +// Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ +// --*/ + +/=# + +#string STR_MISC_SYSTEM_MANUFACTURER #language en-US "Huawei Technologies Co., Ltd." +//#string STR_MISC_SYSTEM_PRODUCT_NAME #language en-US "To be filled by O.E.M." +#string STR_MISC_SYSTEM_PRODUCT_NAME #language en-US "PANGEA" +//#string STR_MISC_SYSTEM_VERSION #language en-US "To be filled by O.E.M." +#string STR_MISC_SYSTEM_VERSION #language en-US "V200R002" +#string STR_MISC_SYSTEM_SERIAL_NUMBER #language en-US "To be filled by O.E.M." +#string STR_MISC_SYSTEM_SKU_NUMBER #language en-US "To be filled by O.E.M." +#string STR_MISC_SYSTEM_FAMILY #language en-US "To be filled by O.E.M." diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerData.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerData.c new file mode 100644 index 0000000000..37fc33b00a --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerData.c @@ -0,0 +1,52 @@ +/*++ + +Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+Copyright (c) 2015, Linaro Limited. 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: + + MiscSystemManufacturerData.c + +Abstract: + + This file provide OEM to define Smbios Type1 Data + +Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ + +**/ + +/* Modify list +DATA AUTHOR REASON +*/ + +#include "SmbiosMisc.h" + + +// +// Static (possibly build generated) System Manufacturer data. +// +MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE1, MiscSystemManufacturer) = { + { // Hdr + EFI_SMBIOS_TYPE_SYSTEM_INFORMATION, // Type, + 0, // Length, + 0 // Handle + }, + 1, // Manufacturer + 2, // ProductName + 3, // Version + 4, // SerialNumber + { // Uuid + 0x12345678, 0x1234, 0x5678, {0x90, 0xab, 0xcd, 0xde, 0xef, 0xaa, 0xbb, 0xcc} + }, + SystemWakeupTypePowerSwitch, // SystemWakeupType + 5, // SKUNumber, + 6 // Family +}; diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerFunction.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerFunction.c new file mode 100644 index 0000000000..fcefe2442c --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerFunction.c @@ -0,0 +1,195 @@ +/*++ + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+Copyright (c) 2015, Linaro Limited. 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: + + MiscSystemManufacturerFunction.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to smbios. + +Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ + +**/ + +#include "SmbiosMisc.h" + +/** + This function makes boot time changes to the contents of the + MiscSystemManufacturer (Type 1). + + @param RecordData Pointer to copy of RecordData from the Data Table. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_UNSUPPORTED Unexpected RecordType value. + @retval EFI_INVALID_PARAMETER Invalid parameter was found. + +**/ +MISC_SMBIOS_TABLE_FUNCTION(MiscSystemManufacturer) +{ + CHAR8 *OptionalStrStart; + UINTN ManuStrLen; + UINTN VerStrLen; + UINTN PdNameStrLen; + UINTN SerialNumStrLen; + UINTN SKUNumStrLen; + UINTN FamilyStrLen; + EFI_STRING Manufacturer; + EFI_STRING ProductName; + EFI_STRING Version; + EFI_STRING SerialNumber; + EFI_STRING SKUNumber; + EFI_STRING Family; + STRING_REF TokenToGet; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE1 *SmbiosRecord; + SMBIOS_TABLE_TYPE1 *InputData; + EFI_STATUS Status; + STRING_REF TokenToUpdate; + CHAR16 *Product; + CHAR16 *pVersion; + + EFI_GUID Uuid; + + // + // First check for invalid parameters. + // + if (RecordData == NULL) + { + return EFI_INVALID_PARAMETER; + } + + InputData = (SMBIOS_TABLE_TYPE1 *)RecordData; + + Product = (CHAR16 *) PcdGetPtr (PcdSystemProductName); + if (StrLen(Product) > 0) + { + TokenToUpdate = STRING_TOKEN (STR_MISC_SYSTEM_PRODUCT_NAME); + HiiSetString (mHiiHandle, TokenToUpdate, Product, NULL); + } + + pVersion = (CHAR16 *) PcdGetPtr (PcdSystemVersion); + if (StrLen(pVersion) > 0) + { + TokenToUpdate = STRING_TOKEN (STR_MISC_SYSTEM_VERSION); + HiiSetString (mHiiHandle, TokenToUpdate, pVersion, NULL); + } + UpdateSmbiosInfo(mHiiHandle, STRING_TOKEN (STR_MISC_SYSTEM_PRODUCT_NAME), ProductNameType01); + UpdateSmbiosInfo(mHiiHandle, STRING_TOKEN (STR_MISC_SYSTEM_SERIAL_NUMBER), SerialNumType01); + UpdateSmbiosInfo(mHiiHandle, STRING_TOKEN (STR_MISC_SYSTEM_MANUFACTURER), SystemManufacturerType01); + + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_MANUFACTURER); + Manufacturer = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + ManuStrLen = StrLen(Manufacturer); + + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_PRODUCT_NAME); + ProductName = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + PdNameStrLen = StrLen(ProductName); + + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_VERSION); + Version = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + VerStrLen = StrLen(Version); + + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_SERIAL_NUMBER); + SerialNumber = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + SerialNumStrLen = StrLen(SerialNumber); + + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_SKU_NUMBER); + SKUNumber = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + SKUNumStrLen = StrLen(SKUNumber); + + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_FAMILY); + Family = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + FamilyStrLen = StrLen(Family); + + // + // Two zeros following the last string. + // + SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE1) + ManuStrLen + 1 + + PdNameStrLen + 1 + + VerStrLen + 1 + + SerialNumStrLen + 1 + + SKUNumStrLen + 1 + + FamilyStrLen + 1 + 1); + + if (NULL == SmbiosRecord) + { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + (VOID)CopyMem(SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE1)); + + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE1); + + SmbiosRecord->Uuid = InputData->Uuid; + Status = GetUuidType1 (&Uuid); + if (!EFI_ERROR (Status)) + { + SmbiosRecord->Uuid = Uuid; + } + + OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1); + UnicodeStrToAsciiStr(Manufacturer, OptionalStrStart); + UnicodeStrToAsciiStr(ProductName, OptionalStrStart + ManuStrLen + 1); + UnicodeStrToAsciiStr(Version, OptionalStrStart + ManuStrLen + 1 + PdNameStrLen + 1); + UnicodeStrToAsciiStr(SerialNumber, OptionalStrStart + ManuStrLen + 1 + PdNameStrLen + 1 + VerStrLen + 1); + UnicodeStrToAsciiStr(SKUNumber, OptionalStrStart + ManuStrLen + 1 + PdNameStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1); + UnicodeStrToAsciiStr(Family, OptionalStrStart + ManuStrLen + 1 + PdNameStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1 + SKUNumStrLen + 1); + + // + // Now we have got the full smbios record, call smbios protocol to add this record. + // + Status = LogSmbiosData( (UINT8*)SmbiosRecord, &SmbiosHandle); + if(EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type01 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status)); + } + + FreePool(SmbiosRecord); + +Exit: + if(Manufacturer != NULL) + { + FreePool(Manufacturer); + } + + if(ProductName != NULL) + { + FreePool(ProductName); + } + + if(Version != NULL) + { + FreePool(Version); + } + + if(SerialNumber != NULL) + { + FreePool(SerialNumber); + } + + if(SKUNumber != NULL) + { + FreePool(SKUNumber); + } + + if(Family != NULL) + { + FreePool(Family); + } + + return Status; +} diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturer.uni b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturer.uni new file mode 100644 index 0000000000..11320c0fe7 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturer.uni @@ -0,0 +1,27 @@ +// *++ +// +// Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+// Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+// Copyright (c) 2015, Linaro Limited. 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. +// +// Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ +// --*/ + +/=# + +#string STR_MISC_BASE_BOARD_MANUFACTURER #language en-US "Huawei Technologies Co., Ltd." +//#string STR_MISC_BASE_BOARD_PRODUCT_NAME #language en-US "To Be Filled By O.E.M." +#string STR_MISC_BASE_BOARD_PRODUCT_NAME #language en-US "STL2SPCA" +//#string STR_MISC_BASE_BOARD_VERSION #language en-US "To Be Filled By O.E.M." +#string STR_MISC_BASE_BOARD_VERSION #language en-US "V200R002" +#string STR_MISC_BASE_BOARD_SERIAL_NUMBER #language en-US "To Be Filled By O.E.M." +#string STR_MISC_BASE_BOARD_ASSET_TAG #language en-US "To Be Filled By O.E.M." +#string STR_MISC_BASE_BOARD_CHASSIS_LOCATION #language en-US "To Be Filled By O.E.M." diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerData.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerData.c new file mode 100644 index 0000000000..20991b1ea1 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerData.c @@ -0,0 +1,56 @@ +/*++ + +Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+Copyright (c) 2015, Linaro Limited. 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: + + MiscBaseBoardManufacturerData.c + +Abstract: + + This file provide OEM to define Smbios Type2 Data + +Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ +**/ + +#include "SmbiosMisc.h" + +// +// Static (possibly build generated) Chassis Manufacturer data. +// +MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE2, MiscBaseBoardManufacturer) = { + { // Hdr + EFI_SMBIOS_TYPE_BASEBOARD_INFORMATION, // Type, + 0, // Length, + 0 // Handle + }, + 1, // BaseBoardManufacturer + 2, // BaseBoardProductName + 3, // BaseBoardVersion + 4, // BaseBoardSerialNumber + 5, // BaseBoardAssetTag + { // FeatureFlag + 1, // Motherboard :1 + 0, // RequiresDaughterCard :1 + 0, // Removable :1 + 1, // Replaceable :1 + 0, // HotSwappable :1 + 0 // Reserved :3 + }, + 6, // BaseBoardChassisLocation + 0, // ChassisHandle; + BaseBoardTypeMotherBoard, // BoardType; + 0, // NumberOfContainedObjectHandles; + { + 0 + } // ContainedObjectHandles[1]; +}; diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerFunction.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerFunction.c new file mode 100644 index 0000000000..a141f9e7d7 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerFunction.c @@ -0,0 +1,198 @@ +/** @file + + Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+ Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+ Copyright (c) 2015, Linaro Limited. 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: + + MiscBaseBoardManufacturerFunction.c + +Abstract: + + This driver parses the mSmbiosMiscDataTable structure and reports + any generated data using SMBIOS protocol. + +Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ +**/ + +#include "SmbiosMisc.h" + + +/** + This function makes basic board manufacturer to the contents of the + Misc Base Board Manufacturer (Type 2). + + @param RecordData Pointer to copy of RecordData from the Data Table. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_UNSUPPORTED Unexpected RecordType value. + @retval EFI_INVALID_PARAMETER Invalid parameter was found. + +**/ +MISC_SMBIOS_TABLE_FUNCTION(MiscBaseBoardManufacturer) +{ + CHAR8 *OptionalStrStart; + UINTN ManuStrLen; + UINTN ProductNameStrLen; + UINTN VerStrLen; + UINTN SerialNumStrLen; + UINTN AssetTagStrLen; + UINTN ChassisLocaStrLen; + UINTN HandleCount = 0; + UINT16 *HandleArray = NULL; + CHAR16 *BaseBoardManufacturer; + CHAR16 *BaseBoardProductName; + CHAR16 *Version; + EFI_STRING SerialNumber; + EFI_STRING AssetTag; + EFI_STRING ChassisLocation; + STRING_REF TokenToGet; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE2 *SmbiosRecord; + SMBIOS_TABLE_TYPE2 *InputData = NULL; + EFI_STATUS Status; + + STRING_REF TokenToUpdate; + //CHAR16 *ProductName; + //CHAR16 *pVersion; + //uniBIOS_y00216284_018_end 2015-1-13 09:08:22 + + // + // First check for invalid parameters. + // + if (RecordData == NULL) + { + return EFI_INVALID_PARAMETER; + } + + InputData = (SMBIOS_TABLE_TYPE2*)RecordData; + + BaseBoardProductName = (CHAR16 *) PcdGetPtr (PcdBaseBoardProductName); + if (StrLen(BaseBoardProductName) > 0) + { + TokenToUpdate = STRING_TOKEN (STR_MISC_BASE_BOARD_PRODUCT_NAME); + HiiSetString (mHiiHandle, TokenToUpdate, BaseBoardProductName, NULL); + } + + Version = (CHAR16 *) PcdGetPtr (PcdBaseBoardVersion); + if (StrLen(Version) > 0) + { + TokenToUpdate = STRING_TOKEN (STR_MISC_BASE_BOARD_VERSION); + HiiSetString (mHiiHandle, TokenToUpdate, Version, NULL); + } + + UpdateSmbiosInfo(mHiiHandle, STRING_TOKEN (STR_MISC_BASE_BOARD_ASSET_TAG), AssertTagType02); + UpdateSmbiosInfo(mHiiHandle, STRING_TOKEN (STR_MISC_BASE_BOARD_SERIAL_NUMBER), SrNumType02); + UpdateSmbiosInfo(mHiiHandle, STRING_TOKEN (STR_MISC_BASE_BOARD_MANUFACTURER), BoardManufacturerType02); + + TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_MANUFACTURER); + BaseBoardManufacturer = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + ManuStrLen = StrLen(BaseBoardManufacturer); + + TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_PRODUCT_NAME); + BaseBoardProductName = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + ProductNameStrLen = StrLen(BaseBoardProductName); + + TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_VERSION); + Version = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + VerStrLen = StrLen(Version); + + TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_SERIAL_NUMBER); + SerialNumber = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + SerialNumStrLen = StrLen(SerialNumber); + + TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_ASSET_TAG); + AssetTag = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + AssetTagStrLen = StrLen(AssetTag); + + TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_CHASSIS_LOCATION); + ChassisLocation = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + ChassisLocaStrLen = StrLen(ChassisLocation); + + // + // Two zeros following the last string. + // + SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE2) + ManuStrLen + 1 + + ProductNameStrLen + 1 + + VerStrLen + 1 + + SerialNumStrLen + 1 + + AssetTagStrLen + 1 + + ChassisLocaStrLen + 1 + 1); + if (NULL == SmbiosRecord) + { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + (VOID)CopyMem(SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE2)); + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE2); + + // + // Update Contained objects Handle + // + SmbiosRecord->NumberOfContainedObjectHandles = 0; + GetLinkTypeHandle(EFI_SMBIOS_TYPE_SYSTEM_ENCLOSURE, &HandleArray, &HandleCount); + if(HandleCount) + { + SmbiosRecord->ChassisHandle = HandleArray[0]; + } + + FreePool(HandleArray); + + OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1); + UnicodeStrToAsciiStr(BaseBoardManufacturer, OptionalStrStart); + UnicodeStrToAsciiStr(BaseBoardProductName, OptionalStrStart + ManuStrLen + 1); + UnicodeStrToAsciiStr(Version, OptionalStrStart + ManuStrLen + 1 + ProductNameStrLen + 1); + UnicodeStrToAsciiStr(SerialNumber, OptionalStrStart + ManuStrLen + 1 + ProductNameStrLen + 1 + VerStrLen + 1); + UnicodeStrToAsciiStr(AssetTag, OptionalStrStart + ManuStrLen + 1 + ProductNameStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1 ); + UnicodeStrToAsciiStr(ChassisLocation, OptionalStrStart + ManuStrLen + 1 + ProductNameStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1 + AssetTagStrLen + 1); + + Status = LogSmbiosData( (UINT8*)SmbiosRecord, &SmbiosHandle); + if(EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type02 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status)); + } + + FreePool(SmbiosRecord); + +Exit: + if(BaseBoardManufacturer != NULL) + { + FreePool(BaseBoardManufacturer); + } + + if(BaseBoardProductName != NULL) + { + FreePool(BaseBoardProductName); + } + + if(Version != NULL) + { + FreePool(Version); + } + + if(SerialNumber != NULL) + { + FreePool(SerialNumber); + } + + if(AssetTag != NULL) + { + FreePool(AssetTag); + } + + if(ChassisLocation != NULL) + { + FreePool(ChassisLocation); + } + + return Status; +} diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturer.uni b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturer.uni new file mode 100644 index 0000000000..543ef00c0d --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturer.uni @@ -0,0 +1,24 @@ +// *++ +// +// Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+// Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+// Copyright (c) 2015, Linaro Limited. 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. +// +// Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ +// --*/ + +/=# + +#string STR_MISC_CHASSIS_MANUFACTURER #language en-US "Huawei Technologies Co., Ltd." +#string STR_MISC_CHASSIS_VERSION #language en-US "To Be Filled By O.E.M." +#string STR_MISC_CHASSIS_SERIAL_NUMBER #language en-US "To Be Filled By O.E.M." +#string STR_MISC_CHASSIS_ASSET_TAG #language en-US "To Be Filled By O.E.M." +#string STR_MISC_CHASSIS_SKU_NUMBER #language en-US "To Be Filled By O.E.M." diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerData.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerData.c new file mode 100644 index 0000000000..6237fbe535 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerData.c @@ -0,0 +1,66 @@ +/*++ + +Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+Copyright (c) 2015, Linaro Limited. 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: + + MiscChassisManufacturerData.c + +Abstract: + + This file provide OEM to define Smbios Type3 Data + +Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ +**/ +/* Modify list +DATA AUTHOR REASON +*/ + +#include "SmbiosMisc.h" + + +// +// Static (possibly build generated) Chassis Manufacturer data. +// +MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE3, MiscChassisManufacturer) = { + { // Hdr + EFI_SMBIOS_TYPE_SYSTEM_ENCLOSURE , // Type, + 0, // Length, + 0 // Handle + }, + 1, // Manufactrurer + MiscChassisTypeMainServerChassis, // Type + 2, // Version + 3, // SerialNumber + 4, // AssetTag + ChassisStateSafe, // BootupState + ChassisStateSafe, // PowerSupplyState + ChassisStateSafe, // ThermalState + ChassisSecurityStatusNone, // SecurityState + { + 0, // OemDefined[0] + 0, // OemDefined[1] + 0, // OemDefined[2] + 0 // OemDefined[3] + }, + 2, // Height + 1, // NumberofPowerCords + 0, // ContainedElementCount + 0, // ContainedElementRecordLength + { // ContainedElements[0] + { + 0, // ContainedElementType + 0, // ContainedElementMinimum + 0 // ContainedElementMaximum + } + } +}; diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerFunction.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerFunction.c new file mode 100644 index 0000000000..4bb170117d --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerFunction.c @@ -0,0 +1,199 @@ +/** @file + +Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+Copyright (c) 2015, Linaro Limited. 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: + + MiscChassisManufacturerFunction.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to smbios. + +Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ +**/ +/* Modify list +DATA AUTHOR REASON +*/ + +#include "SmbiosMisc.h" + +UINT8 +GetChassisType ( +) +{ + EFI_STATUS Status; + UINT8 ChassisType; + Status = IpmiGetChassisType(&ChassisType); + if (EFI_ERROR(Status)) + { + return 0; + } + + return ChassisType; +} + +/** + This function makes boot time changes to the contents of the + MiscChassisManufacturer (Type 3). + + @param RecordData Pointer to copy of RecordData from the Data Table. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_UNSUPPORTED Unexpected RecordType value. + @retval EFI_INVALID_PARAMETER Invalid parameter was found. + +**/ +MISC_SMBIOS_TABLE_FUNCTION(MiscChassisManufacturer) +{ + CHAR8 *OptionalStrStart; + UINTN ManuStrLen; + UINTN VerStrLen; + UINTN AssertTagStrLen; + UINTN SerialNumStrLen; + UINTN ChaNumStrLen; + EFI_STRING Manufacturer; + EFI_STRING Version; + EFI_STRING SerialNumber; + EFI_STRING AssertTag; + EFI_STRING ChassisSkuNumber; + STRING_REF TokenToGet; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE3 *SmbiosRecord; + SMBIOS_TABLE_TYPE3 *InputData; + EFI_STATUS Status; + + UINT8 ContainedElementCount; + CONTAINED_ELEMENT ContainedElements = {0}; + UINT8 ExtendLength = 0; + + UINT8 ChassisType; + + // + // First check for invalid parameters. + // + if (RecordData == NULL) + { + return EFI_INVALID_PARAMETER; + } + + InputData = (SMBIOS_TABLE_TYPE3 *)RecordData; + + UpdateSmbiosInfo(mHiiHandle, STRING_TOKEN (STR_MISC_CHASSIS_ASSET_TAG), AssetTagType03); + UpdateSmbiosInfo(mHiiHandle, STRING_TOKEN (STR_MISC_CHASSIS_SERIAL_NUMBER), SrNumType03); + UpdateSmbiosInfo(mHiiHandle, STRING_TOKEN (STR_MISC_CHASSIS_VERSION), VersionType03); + UpdateSmbiosInfo(mHiiHandle, STRING_TOKEN (STR_MISC_CHASSIS_MANUFACTURER), ManufacturerType03); + + TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_MANUFACTURER); + Manufacturer = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + ManuStrLen = StrLen(Manufacturer); + + TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_VERSION); + Version = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + VerStrLen = StrLen(Version); + + TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_SERIAL_NUMBER); + SerialNumber = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + SerialNumStrLen = StrLen(SerialNumber); + + TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_ASSET_TAG); + AssertTag = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + AssertTagStrLen = StrLen(AssertTag); + + TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_SKU_NUMBER); + ChassisSkuNumber = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + ChaNumStrLen = StrLen(ChassisSkuNumber); + + ContainedElementCount = InputData->ContainedElementCount; + + if (ContainedElementCount > 1) + { + ExtendLength = (ContainedElementCount - 1) * sizeof (CONTAINED_ELEMENT); + } + + // + // Two zeros following the last string. + // + SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE3) + ExtendLength + 1 + + ManuStrLen + 1 + + VerStrLen + 1 + + SerialNumStrLen + 1 + + AssertTagStrLen + 1 + + ChaNumStrLen + 1 + 1); + if (NULL == SmbiosRecord) + { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + (VOID)CopyMem(SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE3)); + + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE3) + ExtendLength + 1; + + ChassisType = GetChassisType (); + if (ChassisType != 0) + { + SmbiosRecord->Type = ChassisType; + } + + //ContainedElements + (VOID)CopyMem(SmbiosRecord + 1, &ContainedElements, ExtendLength); + + //ChassisSkuNumber + *((UINT8 *)SmbiosRecord + sizeof (SMBIOS_TABLE_TYPE3) + ExtendLength) = 5; + + OptionalStrStart = (CHAR8 *)((UINT8 *)SmbiosRecord + sizeof (SMBIOS_TABLE_TYPE3) + ExtendLength + 1); + UnicodeStrToAsciiStr(Manufacturer, OptionalStrStart); + UnicodeStrToAsciiStr(Version, OptionalStrStart + ManuStrLen + 1); + UnicodeStrToAsciiStr(SerialNumber, OptionalStrStart + ManuStrLen + 1 + VerStrLen + 1); + UnicodeStrToAsciiStr(AssertTag, OptionalStrStart + ManuStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1); + UnicodeStrToAsciiStr(ChassisSkuNumber, OptionalStrStart + ManuStrLen + 1 + VerStrLen + 1 + SerialNumStrLen +1 + AssertTagStrLen + 1); + // + // Now we have got the full smbios record, call smbios protocol to add this record. + // + Status = LogSmbiosData( (UINT8*)SmbiosRecord, &SmbiosHandle); + if(EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type03 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status)); + } + + FreePool(SmbiosRecord); + +Exit: + if(Manufacturer != NULL) + { + FreePool(Manufacturer); + } + + if(Version != NULL) + { + FreePool(Version); + } + + if(SerialNumber != NULL) + { + FreePool(SerialNumber); + } + + if(AssertTag != NULL) + { + FreePool(AssertTag); + } + + if(ChassisSkuNumber != NULL) + { + FreePool(ChassisSkuNumber); + } + + return Status; +} diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignation.uni b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignation.uni new file mode 100644 index 0000000000..19968f22f3 Binary files /dev/null and b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignation.uni differ diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignationData.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignationData.c new file mode 100644 index 0000000000..f9b1f03abd --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignationData.c @@ -0,0 +1,162 @@ +/*++ + +Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+Copyright (c) 2016, Hisilicon Limited. All rights reserved.
+Copyright (c) 2016, Linaro Limited. 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: + + MiscSystemSlotDesignationData.c + +Abstract: + + This file provide OEM to define Smbios Type09 Data + +**/ + +#include "SmbiosMisc.h" + + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE9, MiscSystemSlotDesignationPcie0) = { + { // Hdr + EFI_SMBIOS_TYPE_SYSTEM_SLOTS, // Type, + 0, // Length, + 0 // Handle + }, + 1, // SlotDesignation + SlotTypePciExpressX8, // SlotType + SlotDataBusWidth8X, // SlotDataBusWidth + SlotUsageOther, // SlotUsage + SlotLengthOther, // SlotLength + 0x0000, // SlotId + { // SlotCharacteristics1 + 0, // CharacteristicsUnknown :1; + 0, // Provides50Volts :1; + 0, // Provides33Volts :1; + 0, // SharedSlot :1; + 0, // PcCard16Supported :1; + 0, // CardBusSupported :1; + 0, // ZoomVideoSupported :1; + 0 // ModemRingResumeSupported:1; + }, + { // SlotCharacteristics2 + 0, // PmeSignalSupported :1; + 0, // HotPlugDevicesSupported :1; + 0, // SmbusSignalSupported :1; + 0 // Reserved :5; + }, + 0x00, // SegmentGroupNum + 0x00, // BusNum + 0 // DevFuncNum +}; + +MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE9, MiscSystemSlotDesignationPcie1) = { + { // Hdr + EFI_SMBIOS_TYPE_SYSTEM_SLOTS, // Type, + 0, // Length, + 0 // Handle + }, + 1, // SlotDesignation + SlotTypePciExpressX8, // SlotType + SlotDataBusWidth8X, // SlotDataBusWidth + SlotUsageAvailable, // SlotUsage + SlotLengthOther, // SlotLength + 0x0001, // SlotId + { // SlotCharacteristics1 + 0, // CharacteristicsUnknown :1; + 0, // Provides50Volts :1; + 0, // Provides33Volts :1; + 0, // SharedSlot :1; + 0, // PcCard16Supported :1; + 0, // CardBusSupported :1; + 0, // ZoomVideoSupported :1; + 0 // ModemRingResumeSupported:1; + }, + { // SlotCharacteristics2 + 0, // PmeSignalSupported :1; + 0, // HotPlugDevicesSupported :1; + 0, // SmbusSignalSupported :1; + 0 // Reserved :5; + }, + 0x00, // SegmentGroupNum + 0x40, // BusNum + 0 // DevFuncNum +}; + +MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE9, MiscSystemSlotDesignationPcie2) = { + { // Hdr + EFI_SMBIOS_TYPE_SYSTEM_SLOTS, // Type, + 0, // Length, + 0 // Handle + }, + 1, // SlotDesignation + SlotTypePciExpressX8, // SlotType + SlotDataBusWidth8X, // SlotDataBusWidth + SlotUsageOther, // SlotUsage + SlotLengthOther, // SlotLength + 0x0002, // SlotId + { // SlotCharacteristics1 + 0, // CharacteristicsUnknown :1; + 0, // Provides50Volts :1; + 0, // Provides33Volts :1; + 0, // SharedSlot :1; + 0, // PcCard16Supported :1; + 0, // CardBusSupported :1; + 0, // ZoomVideoSupported :1; + 0 // ModemRingResumeSupported:1; + }, + { // SlotCharacteristics2 + 0, // PmeSignalSupported :1; + 0, // HotPlugDevicesSupported :1; + 0, // SmbusSignalSupported :1; + 0 // Reserved :5; + }, + 0x00, // SegmentGroupNum + 0x80, // BusNum + 0 // DevFuncNum +}; + +MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE9, MiscSystemSlotDesignationPcie3) = { + { // Hdr + EFI_SMBIOS_TYPE_SYSTEM_SLOTS, // Type, + 0, // Length, + 0 // Handle + }, + 1, // SlotDesignation + SlotTypePciExpressX4, // SlotType + SlotDataBusWidth4X, // SlotDataBusWidth + SlotUsageOther, // SlotUsage + SlotLengthOther, // SlotLength + 0x0003, // SlotId + { // SlotCharacteristics1 + 0, // CharacteristicsUnknown :1; + 0, // Provides50Volts :1; + 0, // Provides33Volts :1; + 0, // SharedSlot :1; + 0, // PcCard16Supported :1; + 0, // CardBusSupported :1; + 0, // ZoomVideoSupported :1; + 0 // ModemRingResumeSupported:1; + }, + { // SlotCharacteristics2 + 0, // PmeSignalSupported :1; + 0, // HotPlugDevicesSupported :1; + 0, // SmbusSignalSupported :1; + 0 // Reserved :5; + }, + 0x00, // SegmentGroupNum + 0xC0, // BusNum + 0 // DevFuncNum +}; + +/* eof - MiscSystemSlotsData.c */ diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignationFunction.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignationFunction.c new file mode 100644 index 0000000000..bc33639ac5 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignationFunction.c @@ -0,0 +1,201 @@ +/** @file + BIOS system slot designator information boot time changes. + SMBIOS type 9. + + Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+ Copyright (c) 2016, Hisilicon Limited. All rights reserved.
+ Copyright (c) 2016, Linaro Limited. 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. + +**/ + +#include "SmbiosMisc.h" + +#include + +extern SMBIOS_TABLE_TYPE9 MiscSystemSlotDesignationPcie0Data; +extern SMBIOS_TABLE_TYPE9 MiscSystemSlotDesignationPcie1Data; +extern SMBIOS_TABLE_TYPE9 MiscSystemSlotDesignationPcie2Data; +extern SMBIOS_TABLE_TYPE9 MiscSystemSlotDesignationPcie3Data; + +VOID +UpdateSlotDesignation ( + IN SMBIOS_TABLE_TYPE9 *InputData + ) +{ + STRING_REF TokenToUpdate; + CHAR16 *SlotDesignation; + UINTN DesignationStrLen; + + SlotDesignation = AllocateZeroPool ((sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH); + if (NULL == SlotDesignation) + { + return; + } + + if ((UINTN)InputData == (UINTN)&MiscSystemSlotDesignationPcie0Data) + { + UnicodeSPrint(SlotDesignation, SMBIOS_STRING_MAX_LENGTH - 1, L"PCIE0"); + } + else if ((UINTN)InputData == (UINTN)&MiscSystemSlotDesignationPcie1Data) + { + UnicodeSPrint(SlotDesignation, SMBIOS_STRING_MAX_LENGTH - 1, L"PCIE1"); + } + else if ((UINTN)InputData == (UINTN)&MiscSystemSlotDesignationPcie2Data) + { + UnicodeSPrint(SlotDesignation, SMBIOS_STRING_MAX_LENGTH - 1, L"PCIE2"); + } + else if ((UINTN)InputData == (UINTN)&MiscSystemSlotDesignationPcie3Data) + { + UnicodeSPrint(SlotDesignation, SMBIOS_STRING_MAX_LENGTH - 1, L"PCIE3"); + } + + DesignationStrLen = StrLen (SlotDesignation); + + if (DesignationStrLen > 0 ) + { + TokenToUpdate = STRING_TOKEN (STR_MISC_SYSTEM_SLOT_DESIGNATION); + HiiSetString (mHiiHandle, TokenToUpdate, SlotDesignation, NULL); + } + + FreePool (SlotDesignation); +} + +VOID +UpdateSlotUsage( + IN OUT SMBIOS_TABLE_TYPE9 *InputData + ) +{ + EFI_STATUS Status; + SERDES_PARAM SerdesParamA; + SERDES_PARAM SerdesParamB; + + Status = OemGetSerdesParam (&SerdesParamA, &SerdesParamB, 0); + if(EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] OemGetSerdesParam failed %r\n", __FUNCTION__, __LINE__, Status)); + return; + } + + // + // PCIE0 + // + if (((UINTN)InputData == (UINTN)&MiscSystemSlotDesignationPcie0Data) + && SerdesParamA.Hilink1Mode == EmHilink1Pcie0X8) { + InputData->CurrentUsage = SlotUsageAvailable; + } + + // + // PCIE1 + // + if ((UINTN)InputData == (UINTN)&MiscSystemSlotDesignationPcie1Data) + { + if (SerdesParamA.Hilink0Mode == EmHilink0Pcie1X4Pcie2X4) { + InputData->SlotDataBusWidth = SlotDataBusWidth4X; + } + } + + // + // PCIE2 + // + if ((UINTN)InputData == (UINTN)&MiscSystemSlotDesignationPcie2Data) + { + if (SerdesParamA.Hilink0Mode == EmHilink0Pcie1X4Pcie2X4) { + InputData->SlotDataBusWidth = SlotDataBusWidth4X; + InputData->CurrentUsage = SlotUsageAvailable; + } else if (SerdesParamA.Hilink2Mode == EmHilink2Pcie2X8) { + InputData->CurrentUsage = SlotUsageAvailable; + } + } + + // + // PCIE3 + // + if (((UINTN)InputData == (UINTN)&MiscSystemSlotDesignationPcie3Data) + && SerdesParamA.Hilink5Mode == EmHilink5Pcie3X4) { + InputData->CurrentUsage = SlotUsageAvailable; + } +} + +/** + This function makes boot time changes to the contents of the + MiscSystemSlotDesignator structure (Type 9). + + @param RecordData Pointer to copy of RecordData from the Data Table. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_UNSUPPORTED Unexpected RecordType value. + @retval EFI_INVALID_PARAMETER Invalid parameter was found. + +**/ +MISC_SMBIOS_TABLE_FUNCTION(MiscSystemSlotDesignation) +{ + CHAR8 *OptionalStrStart; + UINTN SlotDesignationStrLen; + EFI_STATUS Status; + EFI_STRING SlotDesignation; + STRING_REF TokenToGet; + SMBIOS_TABLE_TYPE9 *SmbiosRecord; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE9 *InputData = NULL; + + // + // First check for invalid parameters. + // + if (RecordData == NULL) + { + return EFI_INVALID_PARAMETER; + } + + InputData = (SMBIOS_TABLE_TYPE9 *)RecordData; + + UpdateSlotUsage (InputData); + + UpdateSlotDesignation (InputData); + + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_SLOT_DESIGNATION); + SlotDesignation = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL); + SlotDesignationStrLen = StrLen(SlotDesignation); + + // + // Two zeros following the last string. + // + SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE9) + SlotDesignationStrLen + 1 + 1); + if(NULL == SmbiosRecord) + { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + (VOID)CopyMem(SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE9)); + + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE9); + + OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1); + UnicodeStrToAsciiStr(SlotDesignation, OptionalStrStart); + // + // Now we have got the full smbios record, call smbios protocol to add this record. + // + + Status = LogSmbiosData( (UINT8*)SmbiosRecord, &SmbiosHandle); + if(EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type09 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status)); + } + + FreePool(SmbiosRecord); + +Exit: + if(SlotDesignation != NULL) + { + FreePool(SlotDesignation); + } + + return Status; +} diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguages.uni b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguages.uni new file mode 100644 index 0000000000..c9873ad890 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguages.uni @@ -0,0 +1,49 @@ +// *++ +// +// Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+// Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+// Copyright (c) 2015, Linaro Limited. 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. +// +// Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ +// --*/ + +/=# + +/=# +// +// Language String (Long Format) +// +#string STR_MISC_BIOS_LANGUAGES_ENG_LONG #language en-US "en|US|iso8859-1" +#string STR_MISC_BIOS_LANGUAGES_FRA_LONG #language en-US "fr|CA|iso8859-1" +#string STR_MISC_BIOS_LANGUAGES_CHN_LONG #language en-US "zh|TW|unicode" +#string STR_MISC_BIOS_LANGUAGES_JPN_LONG #language en-US "ja|JP|unicode" +#string STR_MISC_BIOS_LANGUAGES_ITA_LONG #language en-US "it|IT|iso8859-1" +#string STR_MISC_BIOS_LANGUAGES_SPA_LONG #language en-US "es|ES|iso8859-1" +#string STR_MISC_BIOS_LANGUAGES_GER_LONG #language en-US "de|DE|iso8859-1" +#string STR_MISC_BIOS_LANGUAGES_POR_LONG #language en-US "pt|PT|iso8859-1" + + +// +// Language String (Abbreviated Format) +// +#string STR_MISC_BIOS_LANGUAGES_ENG_ABBREVIATE #language en-US "enUS" +#string STR_MISC_BIOS_LANGUAGES_FRA_ABBREVIATE #language en-US "frCA" +#string STR_MISC_BIOS_LANGUAGES_CHN_ABBREVIATE #language en-US "zhTW" +#string STR_MISC_BIOS_LANGUAGES_JPN_ABBREVIATE #language en-US "jaJP" +#string STR_MISC_BIOS_LANGUAGES_ITA_ABBREVIATE #language en-US "itIT" +#string STR_MISC_BIOS_LANGUAGES_SPA_ABBREVIATE #language en-US "esES" +#string STR_MISC_BIOS_LANGUAGES_GER_ABBREVIATE #language en-US "deDE" +#string STR_MISC_BIOS_LANGUAGES_POR_ABBREVIATE #language en-US "ptPT" + +#string STR_MISC_BIOS_LANGUAGES_SIMPLECH_ABBREVIATE #language en-US "zhCN" +#string STR_MISC_BIOS_LANGUAGES_SIMPLECH_LONG #language en-US "zh|CN|unicode" + + diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesData.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesData.c new file mode 100644 index 0000000000..60f616085e --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesData.c @@ -0,0 +1,46 @@ +/**@file + +Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+Copyright (c) 2015, Linaro Limited. 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: + + MiscNumberOfInstallableLanguagesData.c + +Abstract: + + This file provide OEM to define Smbios Type13 Data + +Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ +**/ + +#include "SmbiosMisc.h" + +// +// Static (possibly build generated) Bios Vendor data. +// + +MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE13, MiscNumberOfInstallableLanguages) = +{ + { // Hdr + EFI_SMBIOS_TYPE_BIOS_LANGUAGE_INFORMATION, // Type, + 0, // Length, + 0 // Handle + }, + 0, // InstallableLanguages + 0, // Flags + { + 0 // Reserved[15] + }, + 1 // CurrentLanguage +}; + +/* eof - MiscNumberOfInstallableLanguagesData.c */ diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesFunction.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesFunction.c new file mode 100644 index 0000000000..1f8f3eaf58 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesFunction.c @@ -0,0 +1,163 @@ +/** @file + +Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+Copyright (c) 2015, Linaro Limited. 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. + +Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ +**/ + +/* Modify list +DATA AUTHOR REASON +*/ + +#include "SmbiosMisc.h" + +/** + Get next language from language code list (with separator ';'). + + @param LangCode Input: point to first language in the list. On + Otput: point to next language in the list, or + NULL if no more language in the list. + @param Lang The first language in the list. + +**/ +VOID +EFIAPI +GetNextLanguage ( + IN OUT CHAR8 **LangCode, + OUT CHAR8 *Lang + ) +{ + UINTN Index; + CHAR8 *StringPtr; + + if(NULL == LangCode || NULL == *LangCode || NULL == Lang) { + return; + } + + Index = 0; + StringPtr = *LangCode; + while (StringPtr[Index] != 0 && StringPtr[Index] != ';') { + Index++; + } + + (VOID)CopyMem(Lang, StringPtr, Index); + Lang[Index] = 0; + + if (StringPtr[Index] == ';') { + Index++; + } + *LangCode = StringPtr + Index; +} + +/** + This function returns the number of supported languages on HiiHandle. + + @param HiiHandle The HII package list handle. + + @retval The number of supported languages. + +**/ +UINT16 +EFIAPI +GetSupportedLanguageNumber ( + IN EFI_HII_HANDLE HiiHandle + ) +{ + CHAR8 *Lang; + CHAR8 *Languages; + CHAR8 *LanguageString; + UINT16 LangNumber; + + Languages = HiiGetSupportedLanguages (HiiHandle); + if (Languages == NULL) { + return 0; + } + + LangNumber = 0; + Lang = AllocatePool (AsciiStrSize (Languages)); + if (Lang != NULL) { + LanguageString = Languages; + while (*LanguageString != 0) { + GetNextLanguage (&LanguageString, Lang); + LangNumber++; + } + FreePool (Lang); + } + FreePool (Languages); + return LangNumber; +} + + +/** + This function makes boot time changes to the contents of the + MiscNumberOfInstallableLanguages (Type 13). + + @param RecordData Pointer to copy of RecordData from the Data Table. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_UNSUPPORTED Unexpected RecordType value. + @retval EFI_INVALID_PARAMETER Invalid parameter was found. + +**/ +MISC_SMBIOS_TABLE_FUNCTION(MiscNumberOfInstallableLanguages) +{ + UINTN LangStrLen; + CHAR8 CurrentLang[SMBIOS_STRING_MAX_LENGTH + 1]; + CHAR8 *OptionalStrStart; + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE13 *SmbiosRecord; + SMBIOS_TABLE_TYPE13 *InputData = NULL;; + + // + // First check for invalid parameters. + // + if (RecordData == NULL) { + return EFI_INVALID_PARAMETER; + } + + InputData = (SMBIOS_TABLE_TYPE13 *)RecordData; + + InputData->InstallableLanguages = GetSupportedLanguageNumber (mHiiHandle); + + // + // Try to check if current langcode matches with the langcodes in installed languages + // + ZeroMem(CurrentLang, SMBIOS_STRING_MAX_LENGTH - 1); + (VOID)AsciiStrCpyS(CurrentLang, SMBIOS_STRING_MAX_LENGTH - 1, "en|US|iso8859-1"); + LangStrLen = AsciiStrLen(CurrentLang); + + // + // Two zeros following the last string. + // + SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE13) + LangStrLen + 1 + 1); + if(NULL == SmbiosRecord) { + return EFI_OUT_OF_RESOURCES; + } + + (VOID)CopyMem(SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE13)); + + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE13); + + OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1); + (VOID)AsciiStrCpyS(OptionalStrStart, SMBIOS_STRING_MAX_LENGTH - 1, CurrentLang); + // + // Now we have got the full smbios record, call smbios protocol to add this record. + // + Status = LogSmbiosData((UINT8*)SmbiosRecord, &SmbiosHandle); + if(EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type13 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status)); + } + + FreePool(SmbiosRecord); + return Status; +} diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationData.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationData.c new file mode 100644 index 0000000000..9f04694548 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationData.c @@ -0,0 +1,48 @@ +/**@file + +Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+Copyright (c) 2015, Linaro Limited. 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: + + MiscBootInformationData.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + +Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ +**/ + +#include "SmbiosMisc.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE32, MiscBootInformation) = { + { // Hdr + EFI_SMBIOS_TYPE_SYSTEM_BOOT_INFORMATION, // Type, + 0, // Length, + 0 // Handle + }, + { // Reserved[6] + 0, + 0, + 0, + 0, + 0, + 0 + }, + BootInformationStatusNoError // BootInformationStatus +}; + +/* eof - MiscBootInformationData.c */ diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationFunction.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationFunction.c new file mode 100644 index 0000000000..7840445eb8 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationFunction.c @@ -0,0 +1,74 @@ +/** @file + boot information boot time changes. + SMBIOS type 32. + +Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+Copyright (c) 2015, Linaro Limited. 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. + +Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ +**/ +/* Modify list +DATA AUTHOR REASON +*/ + +#include "SmbiosMisc.h" + +/** + This function makes boot time changes to the contents of the + MiscBootInformation (Type 32). + + @param RecordData Pointer to copy of RecordData from the Data Table. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_UNSUPPORTED Unexpected RecordType value. + @retval EFI_INVALID_PARAMETER Invalid parameter was found. + +**/ + +MISC_SMBIOS_TABLE_FUNCTION(MiscBootInformation) +{ + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE32 *SmbiosRecord; + SMBIOS_TABLE_TYPE32 *InputData; + + // + // First check for invalid parameters. + // + if (RecordData == NULL) { + return EFI_INVALID_PARAMETER; + } + + InputData = (SMBIOS_TABLE_TYPE32 *)RecordData; + + // + // Two zeros following the last string. + // + SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE32) + 1 + 1); + if(NULL == SmbiosRecord) { + return EFI_OUT_OF_RESOURCES; + } + + (VOID)CopyMem(SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE32)); + + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE32); + + // + // Now we have got the full smbios record, call smbios protocol to add this record. + // + Status = LogSmbiosData( (UINT8*)SmbiosRecord, &SmbiosHandle); + if(EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type32 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status)); + } + + FreePool(SmbiosRecord); + return Status; +} diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type38/MiscIpmiDeviceInformationData.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type38/MiscIpmiDeviceInformationData.c new file mode 100644 index 0000000000..2dc99f1f9c --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type38/MiscIpmiDeviceInformationData.c @@ -0,0 +1,42 @@ +/*++ + +Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+Copyright (c) 2015, Linaro Limited. 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: + + MiscIpmiDeviceInformationData.c + +Abstract: + + This file provide OEM to define Smbios Type38 Data + +Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ +**/ + +#include "SmbiosMisc.h" + +MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE38, MiscIpmiDeviceInformation) = +{ + { // Header + EFI_SMBIOS_TYPE_IPMI_DEVICE_INFORMATION, // Type; + 0, // Length; + 0 // Handle; + }, + IPMIDeviceInfoInterfaceTypeUnknown, // InterfaceType + 0x00, // Ipmi Specification Revision + 0, // I2CSlaveAddress + 0xFF, // NvStorageDeviceAddress + 0x88, // BaseAddress + 0, // BaseAddressModifier/InterruptInfo + 0 // InterruptNumber +}; + diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type38/MiscIpmiDeviceInformationFunction.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type38/MiscIpmiDeviceInformationFunction.c new file mode 100644 index 0000000000..f198237e4d --- /dev/null +++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type38/MiscIpmiDeviceInformationFunction.c @@ -0,0 +1,87 @@ +/*++ + +Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+Copyright (c) 2015, Linaro Limited. 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: + + MiscIpmiDeviceInformationFunction.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to smbios. + +Based on files under Nt32Pkg/MiscSubClassPlatformDxe/ +**/ +/* Modify list +DATA AUTHOR REASON +*/ + +#include "SmbiosMisc.h" + +#include + +/** + This function makes the attributes of IPMI to the contents of the + MiscChassisManufacturer structure. + + @param RecordData Pointer to copy of RecordData from the Data Table. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_UNSUPPORTED Unexpected RecordType value. + @retval EFI_INVALID_PARAMETER Invalid parameter was found. + +**/ +MISC_SMBIOS_TABLE_FUNCTION(MiscIpmiDeviceInformation) +{ + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE38 *SmbiosRecord; + SMBIOS_TABLE_TYPE38 *InputData = NULL; + + IPMI_INTERFACE_PROTOCOL *Ipmi; + + // + // First check for invalid parameters. + // + if (RecordData == NULL) { + return EFI_INVALID_PARAMETER; + } + + InputData = (SMBIOS_TABLE_TYPE38*)RecordData; + + SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE38) + 1 + 1); + if(NULL == SmbiosRecord) { + return EFI_OUT_OF_RESOURCES; + } + + (VOID)CopyMem(SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE38)); + + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE38); + + Status = gBS->LocateProtocol (&gIpmiInterfaceProtocolGuid, NULL, (VOID **)&Ipmi); + if (!EFI_ERROR (Status)) { + SmbiosRecord->InterfaceType = Ipmi->GetIpmiInterfaceType (Ipmi); + SmbiosRecord->BaseAddress = (UINT64)Ipmi->GetIpmiBaseAddress (Ipmi) | Ipmi->GetIpmiBaseAddressType (Ipmi); + SmbiosRecord->IPMISpecificationRevision = Ipmi->GetIpmiVersion (Ipmi); + } + // + // Now we have got the full smbios record, call smbios protocol to add this record. + // + Status = LogSmbiosData((UINT8*)SmbiosRecord, &SmbiosHandle); + if(EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type38 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status)); + } + + FreePool(SmbiosRecord); + return Status; +} diff --git a/Silicon/Hisilicon/Drivers/UpdateFdtDxe/UpdateFdtDxe.c b/Silicon/Hisilicon/Drivers/UpdateFdtDxe/UpdateFdtDxe.c new file mode 100644 index 0000000000..699a820108 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/UpdateFdtDxe/UpdateFdtDxe.c @@ -0,0 +1,158 @@ +/** @file +* +* Copyright (c) 2015, Hisilicon Limited. All rights reserved. +* Copyright (c) 2015, Linaro Limited. 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. +* +**/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +STATIC +EFI_STATUS +InstallFdtIntoConfigurationTable ( + IN VOID* FdtBlob, + IN UINTN FdtSize + ) +{ + EFI_STATUS Status; + + // Check the FDT header is valid. We only make this check in DEBUG mode in case the FDT header change on + // production device and this ASSERT() becomes not valid. + if(!(fdt_check_header (FdtBlob) == 0)) + { + DEBUG ((EFI_D_ERROR,"can not find FdtBlob \n")); + return EFI_INVALID_PARAMETER; + } + + // Ensure the Size of the Device Tree is smaller than the size of the read file + if(!((UINTN)fdt_totalsize (FdtBlob) <= FdtSize)) + { + DEBUG ((EFI_D_ERROR,"FdtBlob <= FdtSize \n")); + return EFI_INVALID_PARAMETER; + } + + // Install the FDT into the Configuration Table + Status = gBS->InstallConfigurationTable (&gFdtTableGuid, FdtBlob); + + return Status; +} + +EFI_STATUS +SetNvramSpace (VOID) +{ + EFI_STATUS Status; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR desp = {0}; + + if (PcdGet64(PcdReservedNvramSize) == 0) { + return EFI_SUCCESS; + } + + Status = gDS->GetMemorySpaceDescriptor(PcdGet64(PcdReservedNvramBase),&desp); + if(EFI_ERROR(Status)){ + DEBUG ((EFI_D_ERROR,"get memory space error:--------- \n")); + return Status; + } + desp.Attributes |= EFI_MEMORY_RUNTIME | EFI_MEMORY_WB; + Status = gDS->SetMemorySpaceAttributes(PcdGet64(PcdReservedNvramBase),PcdGet64(PcdReservedNvramSize), desp.Attributes); + if(EFI_ERROR(Status)){ + DEBUG ((EFI_D_ERROR,"set memory space error:--------- \n")); + return Status; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI UpdateFdt ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable) +{ + INTN Error; + VOID* Fdt; + UINT32 Size; + UINTN NewFdtBlobSize; + UINTN NewFdtBlobBase; + EFI_STATUS Status = EFI_SUCCESS; + UINT32 Index = 0; + UINTN FDTConfigTable; + + (VOID) SetNvramSpace (); + + Fdt = (VOID*)(PcdGet64(FdtFileAddress)); + + + Error = fdt_check_header ((VOID*)(PcdGet64(FdtFileAddress))); + DEBUG ((EFI_D_ERROR,"fdtfileaddress:--------- 0x%lx\n",PcdGet64(FdtFileAddress))); + if (Error != 0) + { + DEBUG ((EFI_D_ERROR,"ERROR: Device Tree header not valid (%a)\n", fdt_strerror(Error))); + return EFI_INVALID_PARAMETER; + } + + Size = (UINTN)fdt_totalsize ((VOID*)(PcdGet64(FdtFileAddress))); + NewFdtBlobSize = Size + ADD_FILE_LENGTH; + + Status = gBS->AllocatePages (AllocateAnyPages, EfiRuntimeServicesData, EFI_SIZE_TO_PAGES(NewFdtBlobSize), &NewFdtBlobBase); + if (EFI_ERROR (Status)) + { + return EFI_OUT_OF_RESOURCES; + } + + (VOID) CopyMem((VOID*)NewFdtBlobBase, Fdt, Size); + + Status = EFIFdtUpdate(NewFdtBlobBase); + if (EFI_ERROR (Status)) + { + DEBUG((EFI_D_ERROR, "%a(%d):EFIFdtUpdate Fail!\n", __FUNCTION__,__LINE__)); + goto EXIT; + } + + + Status = InstallFdtIntoConfigurationTable ((VOID*)(UINTN)NewFdtBlobBase, NewFdtBlobSize); + DEBUG ((EFI_D_ERROR, "NewFdtBlobBase: 0x%lx NewFdtBlobSize:0x%lx\n",NewFdtBlobBase,NewFdtBlobSize)); + if (EFI_ERROR (Status)) + { + DEBUG ((EFI_D_ERROR, "installfdtconfiguration table fail():\n")); + goto EXIT; + } + + + for (Index = 0; Index < gST->NumberOfTableEntries; Index ++) + { + if (CompareGuid (&gFdtTableGuid, &(gST->ConfigurationTable[Index].VendorGuid))) + { + FDTConfigTable = (UINTN)gST->ConfigurationTable[Index].VendorTable; + DEBUG ((EFI_D_ERROR, "FDTConfigTable Address: 0x%lx\n",FDTConfigTable)); + break; + } + } + + return Status; + + EXIT: + + gBS->FreePages(NewFdtBlobBase,EFI_SIZE_TO_PAGES(NewFdtBlobSize)); + + return Status; + +} diff --git a/Silicon/Hisilicon/Drivers/UpdateFdtDxe/UpdateFdtDxe.inf b/Silicon/Hisilicon/Drivers/UpdateFdtDxe/UpdateFdtDxe.inf new file mode 100644 index 0000000000..ccdcae7acf --- /dev/null +++ b/Silicon/Hisilicon/Drivers/UpdateFdtDxe/UpdateFdtDxe.inf @@ -0,0 +1,62 @@ +#/** @file +# +# Copyright (c) 2015, Hisilicon Limited. All rights reserved. +# Copyright (c) 2015, Linaro Limited. 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. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UpdateFdtDxe + FILE_GUID = E29977F9-20A4-4551-B0EC-BCE246592E76 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = UpdateFdt + +[Sources.common] + UpdateFdtDxe.c + + +[Packages] + ArmPlatformPkg/ArmPlatformPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ArmPkg/ArmPkg.dec + OpenPlatformPkg/Chips/Hisilicon/HisiPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + MemoryAllocationLib + UefiDriverEntryPoint + DebugLib + BaseLib + FdtLib + PcdLib + FdtUpdateLib + DxeServicesTableLib + +[Guids] + gFdtTableGuid +[Protocols] + + gHisiBoardNicProtocolGuid + +[Pcd] + + gHisiTokenSpaceGuid.FdtFileAddress + gHisiTokenSpaceGuid.PcdReservedNvramSize + gHisiTokenSpaceGuid.PcdReservedNvramBase + + +[Depex] + gEfiGenericMemTestProtocolGuid diff --git a/Silicon/Hisilicon/Drivers/VersionInfoPeim/VersionInfoPeim.c b/Silicon/Hisilicon/Drivers/VersionInfoPeim/VersionInfoPeim.c new file mode 100644 index 0000000000..40e9137d78 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/VersionInfoPeim/VersionInfoPeim.c @@ -0,0 +1,108 @@ +/** @file +* +* Copyright (c) 2016, Hisilicon Limited. All rights reserved. +* Copyright (c) 2016, Linaro Limited. 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. +* +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct MonthDescription { + CONST CHAR8* MonthStr; + UINT32 MonthInt; +} gMonthDescription[] = { + { "Jan", 1 }, + { "Feb", 2 }, + { "Mar", 3 }, + { "Apr", 4 }, + { "May", 5 }, + { "Jun", 6 }, + { "Jul", 7 }, + { "Aug", 8 }, + { "Sep", 9 }, + { "Oct", 10 }, + { "Nov", 11 }, + { "Dec", 12 }, + { "???", 1 }, // Use 1 as default month +}; + +VOID GetReleaseTime (EFI_TIME *Time) +{ + CONST CHAR8 *ReleaseDate = __DATE__; + CONST CHAR8 *ReleaseTime = __TIME__; + UINTN i; + + for(i=0;i<12;i++) + { + if(0 == AsciiStrnCmp(ReleaseDate, gMonthDescription[i].MonthStr, 3)) + { + break; + } + } + Time->Month = gMonthDescription[i].MonthInt; + Time->Day = AsciiStrDecimalToUintn(ReleaseDate+4); + Time->Year = AsciiStrDecimalToUintn(ReleaseDate+7); + Time->Hour = AsciiStrDecimalToUintn(ReleaseTime); + Time->Minute = AsciiStrDecimalToUintn(ReleaseTime+3); + Time->Second = AsciiStrDecimalToUintn(ReleaseTime+6); + + return; +} + +EFI_STATUS +EFIAPI +VersionInfoEntry ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + CHAR8 Buffer[100]; + UINTN CharCount; + VERSION_INFO *VersionInfo; + EFI_TIME Time = {0}; + CONST CHAR16 *ReleaseString = + (CHAR16 *) FixedPcdGetPtr (PcdFirmwareVersionString); + + GetReleaseTime (&Time); + + CharCount = AsciiSPrint ( + Buffer, + sizeof (Buffer), + "\n\rBoot firmware (version %s built at %t)\n\r\n\r", + ReleaseString, + &Time + ); + SerialPortWrite ((UINT8 *) Buffer, CharCount); + + VersionInfo = BuildGuidHob (&gVersionInfoHobGuid, + sizeof (VERSION_INFO) - + sizeof (VersionInfo->String) + + StrSize (ReleaseString)); + if (VersionInfo == NULL) { + DEBUG ((EFI_D_ERROR, "[%a]:[%d] Build HOB failed!\n", __FILE__, __LINE__)); + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (&VersionInfo->BuildTime, &Time, sizeof (EFI_TIME)); + CopyMem (VersionInfo->String, ReleaseString, StrSize (ReleaseString)); + + return EFI_SUCCESS; +} diff --git a/Silicon/Hisilicon/Drivers/VersionInfoPeim/VersionInfoPeim.inf b/Silicon/Hisilicon/Drivers/VersionInfoPeim/VersionInfoPeim.inf new file mode 100644 index 0000000000..ac39411a77 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/VersionInfoPeim/VersionInfoPeim.inf @@ -0,0 +1,53 @@ +#/** @file +# +# Copyright (c) 2016, Hisilicon Limited. All rights reserved. +# Copyright (c) 2016, Linaro Limited. 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. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = VersionInfoPeim + FILE_GUID = F414EE11-EEE3-4edc-8C12-0E80E446A849 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = VersionInfoEntry + +[Sources.common] + VersionInfoPeim.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + PeimEntryPoint + PcdLib + DebugLib + HobLib + BaseLib + BaseMemoryLib + PrintLib + SerialPortLib + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString + +[Guids] + gVersionInfoHobGuid + +[Depex] + TRUE + +[BuildOptions] + diff --git a/Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.c b/Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.c new file mode 100644 index 0000000000..0cb1e8049a --- /dev/null +++ b/Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.c @@ -0,0 +1,682 @@ +/** @file +* +* Copyright (c) 2016, Hisilicon Limited. All rights reserved. +* Copyright (c) 2016, Linaro Limited. 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. +* +**/ + +#include "VirtualEhciPciIo.h" +#include + +UINT32 mUsbMemBase; +UINTN mSegmentNumber = 0; +// Use 0xFF for the virtual PCI devices +UINTN mBusNumber = 0xFF; +UINTN mDeviceNumber = 0; +UINTN mFunctionNumber = 0; + +typedef struct { + EFI_PHYSICAL_ADDRESS HostAddress; + EFI_PHYSICAL_ADDRESS DeviceAddress; + UINTN NumberOfBytes; + EFI_PCI_IO_PROTOCOL_OPERATION Operation; + BOOLEAN DoubleBuffer; +} MEM_MAP_INFO_INSTANCE; + + +EFI_CPU_ARCH_PROTOCOL *gCpu; + + +EHCI_PCI_CONFIG mEhciPciConfig = { + { + 0x00,//UINT16 VendorId; + 0x00,//UINT16 DeviceId; + 0x00,//UINT16 Command; + 0x0010,//UINT16 Status; + 0x00,//UINT8 RevisionID; + { + PCI_IF_EHCI,//UINT8 ClassCode[3]; + PCI_CLASS_SERIAL_USB, + PCI_CLASS_SERIAL + }, + 0x00,//UINT8 CacheLineSize; + 0x00,//UINT8 LatencyTimer; + 0x00,//UINT8 HeaderType; + 0x00//UINT8 BIST; + }, + { + { + 0x00,//UINT32 Bar[6]; + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 + }, + 0x00,//UINT32 CISPtr; + 0x00,//UINT16 SubsystemVendorID; + 0x00,//UINT16 SubsystemID; + 0x00,//UINT32 ExpansionRomBar; + 0x40,//UINT8 CapabilityPtr; + { + 0x00,//UINT8 Reserved1[3]; + 0x00, + 0x00 + }, + 0x00,//UINT32 Reserved2; + 0x00,//UINT8 InterruptLine; + 0x00,//UINT8 InterruptPin; + 0x00,//UINT8 MinGnt; + 0x00//UINT8 MaxLat; + }, + 0x0A,// UINT8 CapabilityID offset 0x40 + 0x00,// UINT8 NextItemPtr + 0x2000 //UINT16 DebugPort +}; + + + +EFI_STATUS +EhciPciIoPollMem ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EhciPciIoPollIo ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EhciPciIoMemRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + UINT32 i; + + if ((UINT32)Width >= EfiPciIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BarIndex != 0) { + return EFI_INVALID_PARAMETER; + } + + Width = Width & 0x03; + + // + // Loop for each iteration and move the data + // + switch (Width) { + case EfiPciWidthUint8: + for (i = 0; i < Count; i++){ + *((UINT8 *)Buffer + i)= MmioRead8(mUsbMemBase + Offset + i); + } + break; + case EfiPciWidthUint16: + for (i = 0; i < Count; i++){ + *((UINT16 *)Buffer + i)= MmioRead16(mUsbMemBase + Offset + i * 2); + } + break; + case EfiPciWidthUint32: + for (i = 0; i < Count; i++){ + *((UINT32 *)Buffer + i)= MmioRead32(mUsbMemBase + Offset + i * 4); + } + break; + case EfiPciWidthUint64: + for (i = 0; i < Count; i++){ + *((UINT64 *)Buffer + i)= MmioRead64(mUsbMemBase + Offset + i * 8); + } + break; + default: + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EhciPciIoMemWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + UINT32 i; + + if ((UINT32)Width >= EfiPciIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + Width = Width & 0x03; + + // + // Loop for each iteration and move the data + // + switch (Width) { + case EfiPciWidthUint8: + for (i = 0; i < Count; i++){ + MmioWrite8(mUsbMemBase + Offset + i, *((UINT8 *)Buffer + i)); + } + break; + case EfiPciWidthUint16: + for (i = 0; i < Count; i++){ + MmioWrite16(mUsbMemBase + Offset + i * 2, *((UINT16 *)Buffer + i)); + } + break; + case EfiPciWidthUint32: + for (i = 0; i < Count; i++){ + MmioWrite32(mUsbMemBase + Offset + i * 4, *((UINT32 *)Buffer + i)); + } + break; + case EfiPciWidthUint64: + for (i = 0; i < Count; i++){ + MmioWrite64(mUsbMemBase + Offset + i * 8, *((UINT64 *)Buffer + i)); + } + break; + default: + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; + +} + +EFI_STATUS +EhciPciIoIoRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EhciPciIoIoWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EhciPciIoPciRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + UINT32 i; + UINT8 *DataPtr; + + Width = Width & 0x03; + + if (Offset < sizeof (EHCI_PCI_CONFIG) / sizeof (UINT8)){ + + DataPtr = (UINT8 *)(&mEhciPciConfig) + Offset; + + switch (Width) { + case EfiPciWidthUint8: + for (i = 0; i < Count; i++){ + *((UINT8 *)Buffer + i)= *(DataPtr + i); + } + break; + case EfiPciWidthUint16: + for (i = 0; i < Count; i++){ + *((UINT16 *)Buffer + i)= *((UINT16 *)DataPtr + i); + } + break; + case EfiPciWidthUint32: + for (i = 0; i < Count; i++){ + *(UINT32 *)(Buffer + i)= *((UINT32 *)DataPtr + i); + } + break; + case EfiPciWidthUint64: + for (i = 0; i < Count; i++){ + *(UINT64 *)(Buffer + i)= *((UINT64 *)DataPtr + i); + } + break; + default: + return EFI_INVALID_PARAMETER; + } + + } else { + switch (Width) { + case EfiPciWidthUint8: + *(UINT8 *)Buffer = 0xFF; + break; + case EfiPciWidthUint16: + *(UINT16 *)Buffer = 0xFFFF; + break; + case EfiPciWidthUint32: + *(UINT32 *)Buffer = 0xFFFFFFFF; + break; + case EfiPciWidthUint64: + *(UINT64 *)Buffer = 0xFFFFFFFFFFFFFFFF; + break; + default: + return EFI_INVALID_PARAMETER; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EhciPciIoPciWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + + return EFI_SUCCESS; +} + +EFI_STATUS +EhciPciIoCopyMem ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 DestBarIndex, + IN UINT64 DestOffset, + IN UINT8 SrcBarIndex, + IN UINT64 SrcOffset, + IN UINTN Count + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EhciPciIoMap ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + MEM_MAP_INFO_INSTANCE *Map; + VOID *Buffer; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor; + + if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((UINT32)Operation >= EfiPciIoOperationMaximum) { + return EFI_INVALID_PARAMETER; + } + + *DeviceAddress = ConvertToPhysicalAddress (HostAddress); + + // Remember range so we can flush on the other side + Map = AllocatePool (sizeof (MEM_MAP_INFO_INSTANCE)); + if (Map == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + *Mapping = Map; + + if ((((UINTN)HostAddress & (EFI_PAGE_SIZE - 1)) != 0) || + ((*NumberOfBytes % EFI_PAGE_SIZE) != 0)) { + + // Get the cacheability of the region + Status = gDS->GetMemorySpaceDescriptor (*DeviceAddress, &GcdDescriptor); + if (EFI_ERROR(Status)) { + return Status; + } + + // If the mapped buffer is not an uncached buffer + if ( (GcdDescriptor.Attributes != EFI_MEMORY_WC) && + (GcdDescriptor.Attributes != EFI_MEMORY_UC) ) + { + // + // If the buffer does not fill entire cache lines we must double buffer into + // uncached memory. Device (PCI) address becomes uncached page. + // + Map->DoubleBuffer = TRUE; + Buffer = UncachedAllocatePages(EFI_SIZE_TO_PAGES (*NumberOfBytes)); + + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (Buffer, HostAddress, *NumberOfBytes); + *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer; + } else { + Map->DoubleBuffer = FALSE; + } + } else { + Map->DoubleBuffer = FALSE; + + // Flush the Data Cache (should not have any effect if the memory region is uncached) + gCpu->FlushDataCache (gCpu, *DeviceAddress, *NumberOfBytes, EfiCpuFlushTypeWriteBackInvalidate); + + Status = gDS->SetMemorySpaceAttributes (*DeviceAddress & ~(BASE_4KB - 1), ALIGN_VALUE (*NumberOfBytes, BASE_4KB), EFI_MEMORY_WC); + if (EFI_ERROR (Status)) { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] SetMemorySpaceAttributes Fail. %r\n", __FUNCTION__, __LINE__, Status)); + } + } + + Map->HostAddress = (UINTN)HostAddress; + Map->DeviceAddress = *DeviceAddress; + Map->NumberOfBytes = *NumberOfBytes; + Map->Operation = Operation; + + return EFI_SUCCESS; +} + +EFI_STATUS +EhciPciIoUnmap ( + IN EFI_PCI_IO_PROTOCOL *This, + IN VOID *Mapping + ) +{ + MEM_MAP_INFO_INSTANCE *Map; + + if (Mapping == NULL) { + return EFI_INVALID_PARAMETER; + } + + Map = (MEM_MAP_INFO_INSTANCE *)Mapping; + + if (Map->DoubleBuffer) { + if ((Map->Operation == EfiPciIoOperationBusMasterWrite) || (Map->Operation == EfiPciIoOperationBusMasterCommonBuffer)) { + CopyMem ((VOID *)(UINTN)Map->HostAddress, (VOID *)(UINTN)Map->DeviceAddress, Map->NumberOfBytes); + } + + if((VOID *)(UINTN)Map->DeviceAddress != NULL) { + UncachedFreePages ((VOID *)(UINTN)Map->DeviceAddress, EFI_SIZE_TO_PAGES (Map->NumberOfBytes)); + } + + + } else { + if (Map->Operation == EfiPciIoOperationBusMasterWrite) { + // + // Make sure we read buffer from uncached memory and not the cache + // + gCpu->FlushDataCache (gCpu, Map->HostAddress, Map->NumberOfBytes, EfiCpuFlushTypeInvalidate); + } + } + + FreePool (Map); + + return EFI_SUCCESS; +} + + + +EFI_STATUS +EhciPciIoAllocateBuffer ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ) +{ + UINT32 HcCapParams; + + if (Attributes & + (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | + EFI_PCI_ATTRIBUTE_MEMORY_CACHED ))) { + return EFI_UNSUPPORTED; + } + + if (HostAddress == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (MemoryType == EfiBootServicesData) { + HcCapParams = MmioRead32(mUsbMemBase + EHC_HCCPARAMS_OFFSET); + if ((BOOLEAN)(((HcCapParams) & (HCCP_64BIT)) == (HCCP_64BIT))){ + *HostAddress = UncachedAllocatePages(Pages); + } else { + // TODO: We need support allocating UC memory below 4GB strictly + *HostAddress = UncachedAllocatePages(Pages); + } + + }else{ + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +EhciPciIoFreeBuffer ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ) +{ + UncachedFreePages (HostAddress, Pages); + return EFI_SUCCESS; +} + +EFI_STATUS +EhciPciIoFlush ( + IN EFI_PCI_IO_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +EhciPciIoGetLocation ( + IN EFI_PCI_IO_PROTOCOL *This, + OUT UINTN *SegmentNumber, + OUT UINTN *BusNumber, + OUT UINTN *DeviceNumber, + OUT UINTN *FunctionNumber + ) +{ + + *SegmentNumber = mSegmentNumber; + *BusNumber = mBusNumber; + *DeviceNumber = mDeviceNumber; + *FunctionNumber = mFunctionNumber; + + return EFI_SUCCESS; +} + + +EFI_STATUS +EhciPciIoAttributes ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, + IN UINT64 Attributes, + OUT UINT64 *Result OPTIONAL + ) +{ + if (Result != NULL) { + *Result = 0; + } + return EFI_SUCCESS; +} + +EFI_STATUS +EhciPciIoGetBarAttributes ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINT8 BarIndex, + OUT UINT64 *Supports, OPTIONAL + OUT VOID **Resources OPTIONAL + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EhciPciIoSetBarAttributes ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINT64 Attributes, + IN UINT8 BarIndex, + IN OUT UINT64 *Offset, + IN OUT UINT64 *Length + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +// +// Pci Io Protocol Interface +// +EFI_PCI_IO_PROTOCOL mEhciPciIoInterface = { + EhciPciIoPollMem, + EhciPciIoPollIo, + { + EhciPciIoMemRead, + EhciPciIoMemWrite + }, + { + EhciPciIoIoRead, + EhciPciIoIoWrite + }, + { + EhciPciIoPciRead, + EhciPciIoPciWrite + }, + EhciPciIoCopyMem, + EhciPciIoMap, + EhciPciIoUnmap, + EhciPciIoAllocateBuffer, + EhciPciIoFreeBuffer, + EhciPciIoFlush, + EhciPciIoGetLocation, + EhciPciIoAttributes, + EhciPciIoGetBarAttributes, + EhciPciIoSetBarAttributes, + 0, + NULL +}; + + +EFI_STATUS +EFIAPI +EhciVirtualPciIoInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_DEV_PATH EndNode; + EFI_DEV_PATH Node; + EFI_DEVICE_PATH_PROTOCOL *DevicePath = NULL; + + mUsbMemBase = PlatformGetEhciBase (); + + DEBUG ((EFI_D_ERROR, "mUsbMemBase: 0x%x\n", mUsbMemBase)); + + // Get the Cpu protocol for later use + Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpu); + + // + // Install the pciio protocol, device path protocol + // + Handle = NULL; + + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiPciIoProtocolGuid, + &mEhciPciIoInterface, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + (void)ZeroMem (&Node, sizeof (Node)); + Node.DevPath.Type = HARDWARE_DEVICE_PATH; + Node.DevPath.SubType = HW_PCI_DP; + (void)SetDevicePathNodeLength (&Node.DevPath, sizeof (PCI_DEVICE_PATH)); + // Make USB controller device path different from built-in SATA controller + Node.Pci.Function = 1; + Node.Pci.Device = 0; + + SetDevicePathEndNode (&EndNode.DevPath); + + DevicePath = AppendDevicePathNode (&EndNode.DevPath, &Node.DevPath); + + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiDevicePathProtocolGuid, + EFI_NATIVE_INTERFACE, + DevicePath + ); + if(EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] InstallProtocolInterface fail. %r\n", __FUNCTION__, __LINE__, Status)); + } + + + return EFI_SUCCESS; +} diff --git a/Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.h b/Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.h new file mode 100644 index 0000000000..ae7a934a11 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.h @@ -0,0 +1,82 @@ +/** @file +* +* Copyright (c) 2016, Hisilicon Limited. All rights reserved. +* Copyright (c) 2016, Linaro Limited. 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. +* +**/ + +#ifndef _EHCI_PCIIO_H_ +#define _EHCI_PCIIO_H_ + +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#define PCI_CLASS_SERIAL 0x0C +#define PCI_CLASS_SERIAL_FIREWIRE 0x00 +#define PCI_CLASS_SERIAL_ACCESS_BUS 0x01 +#define PCI_CLASS_SERIAL_SSA 0x02 +#define PCI_CLASS_SERIAL_USB 0x03 +#define PCI_IF_EHCI 0x20 +#define PCI_CLASS_SERIAL_FIBRECHANNEL 0x04 +#define PCI_CLASS_SERIAL_SMB 0x05 + +// +// Capability register offset +// +#define EHC_CAPLENGTH_OFFSET 0 // Capability register length offset +#define EHC_HCSPARAMS_OFFSET 0x04 // Structural Parameters 04-07h +#define EHC_HCCPARAMS_OFFSET 0x08 // Capability parameters offset + +// +// Capability register bit definition +// +#define HCSP_NPORTS 0x0F // Number of root hub port +#define HCSP_PPC 0x10 // Port Power Control +#define HCCP_64BIT 0x01 // 64-bit addressing capability + + +typedef struct { + PCI_DEVICE_INDEPENDENT_REGION Hdr; + PCI_DEVICE_HEADER_TYPE_REGION Device; + UINT8 CapabilityID; + UINT8 NextItemPtr; + UINT16 DebugPort; +} EHCI_PCI_CONFIG; + + +#endif // _EHCI_PCIIO_H_ diff --git a/Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.inf b/Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.inf new file mode 100644 index 0000000000..4a5f5c30bc --- /dev/null +++ b/Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.inf @@ -0,0 +1,60 @@ +#/** @file +# +# Copyright (c) 2016, Hisilicon Limited. All rights reserved. +# Copyright (c) 2016, Linaro Limited. 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. +# +#**/ + + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = VirtualEhciPciIo + FILE_GUID = CCC39A9C-33EC-4e5a-924B-2C5CD4CEF6A4 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = EhciVirtualPciIoInitialize + + +[Sources] + VirtualEhciPciIo.h + VirtualEhciPciIo.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ArmPkg/ArmPkg.dec + Silicon/Hisilicon/HisiPkg.dec + +[FeaturePcd] + + +[LibraryClasses] + MemoryAllocationLib + BaseLib + UefiLib + UefiBootServicesTableLib + UefiDriverEntryPoint + BaseMemoryLib + DebugLib + PcdLib + IoLib + ReportStatusCodeLib + UncachedMemoryAllocationLib + ArmLib + DxeServicesTableLib + CacheMaintenanceLib + PlatformSysCtrlLib + +[Guids] + +[Protocols] + gEfiPciIoProtocolGuid ## TO_START -- cgit v1.2.3