summaryrefslogtreecommitdiff
path: root/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClass.c
diff options
context:
space:
mode:
Diffstat (limited to 'Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClass.c')
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClass.c762
1 files changed, 762 insertions, 0 deletions
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;
+}