summaryrefslogtreecommitdiff
path: root/ReferenceCode/Chipset/SystemAgent/SmbiosMemory
diff options
context:
space:
mode:
authorraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
committerraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
commitb7c51c9cf4864df6aabb99a1ae843becd577237c (patch)
treeeebe9b0d0ca03062955223097e57da84dd618b9a /ReferenceCode/Chipset/SystemAgent/SmbiosMemory
downloadzprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'ReferenceCode/Chipset/SystemAgent/SmbiosMemory')
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmBiosMemory.cif14
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmBiosMemory.inf98
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmBiosMemory.mak85
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmBiosMemory.sdl32
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmbiosMemory.c745
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmbiosMemory.dxs58
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmbiosMemory.h127
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmbiosMemoryStrings.unibin0 -> 4068 bytes
8 files changed, 1159 insertions, 0 deletions
diff --git a/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmBiosMemory.cif b/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmBiosMemory.cif
new file mode 100644
index 0000000..e3a1e70
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmBiosMemory.cif
@@ -0,0 +1,14 @@
+<component>
+ name = "SmBiosMemory"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Chipset\SystemAgent\SmbiosMemory\Dxe\"
+ RefName = "SmBiosMemory"
+[files]
+"SmBiosMemory.sdl"
+"SmBiosMemory.mak"
+"SmbiosMemory.c"
+"SmbiosMemory.h"
+"SmbiosMemory.dxs"
+"SmbiosMemoryStrings.uni"
+"SmBiosMemory.inf"
+<endComponent>
diff --git a/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmBiosMemory.inf b/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmBiosMemory.inf
new file mode 100644
index 0000000..3bacc7c
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmBiosMemory.inf
@@ -0,0 +1,98 @@
+## @file
+# Component description file for SmbiosMemory Driver module
+# {EDA39402-F375-4496-92D3-83B43CB8A76A}
+#
+#@copyright
+# Copyright (c) 1999 - 2013 Intel Corporation. All rights reserved
+# This software and associated documentation (if any) is furnished
+# under a license and may only be used or copied in accordance
+# with the terms of the license. Except as permitted by such
+# license, no part of this software or documentation may be
+# reproduced, stored in a retrieval system, or transmitted in any
+# form or by any means without the express written consent of
+# Intel Corporation.
+#
+# This file contains a 'Sample Driver' and is licensed as such
+# under the terms of your license agreement with Intel or your
+# vendor. This file may be modified by the user, subject to
+# the additional terms of the license agreement
+#
+##
+
+[defines]
+BASE_NAME = SmBiosMemory
+FILE_GUID = EDA39402-F375-4496-92D3-83B43CB8A76A
+COMPONENT_TYPE = BS_DRIVER
+
+[sources.common]
+ SmbiosMemory.h
+ SmbiosMemory.c
+ SmbiosMemoryStrings.uni
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGlueDxeDriverEntryPoint.c
+
+[includes.common]
+ .
+ $(DEST_DIR)
+ $(EFI_SOURCE)
+ $(EFI_SOURCE)/Include
+ $(EFI_SOURCE)/Include/IndustryStandard
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+ $(EDK_SOURCE)/Foundation/Library/Dxe/UefiEfiIfrSupportLib
+
+#
+# Typically the sample code referenced will be available in the code base already
+# So keep this include at the end to defer to the source base definition
+# and only use the sample code definition if source base does not include these files.
+#
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/SampleCode
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/SampleCode/Include
+
+[libraries.common]
+ EdkGuidLib
+ EfiCommonLib
+ EfiProtocolLib
+ UefiEfiIfrSupportLib
+ $(PROJECT_SA_FAMILY)ProtocolLib
+ EdkIIGlueBaseLib
+ EdkIIGlueBaseIoLibIntrinsic
+ EdkIIGlueDxeMemoryAllocationLib
+ EdkIIGlueDxeDebugLibReportStatusCode
+ EdkIIGlueDxeReportStatusCodeLib
+ EdkIIGlueUefiBootServicesTableLib
+ EdkIIGlueUefiRuntimeServicesTableLib
+ EdkIIGlueDxeServicesTableLib
+ EdkIIGlueHiiLib
+ EdkIIGlueBasePrintLib
+ EdkProtocolLib
+ EfiDriverLib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT = _ModuleEntryPoint
+ DPX_SOURCE = SmbiosMemory.dxs
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=SmbiosMemoryEntryPoint\
+ -D __EDKII_GLUE_BASE_LIB__ \
+ -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ -D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ -D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_HII_LIB__ \
+ -D __EDKII_GLUE_BASE_PRINT_LIB__
diff --git a/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmBiosMemory.mak b/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmBiosMemory.mak
new file mode 100644
index 0000000..33553e3
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmBiosMemory.mak
@@ -0,0 +1,85 @@
+#---------------------------------------------------------------------------
+# Create SmBiosMemory DXE driver
+#---------------------------------------------------------------------------
+EDK: SmBiosMemorySDB SmBiosMemory
+
+SmBiosMemory: $(BUILD_DIR)\SmBiosMemory.mak SmBiosMemoryBin
+
+$(BUILD_DIR)\SmBiosMemory.mak : $(SmBiosMemory_DIR)\$(@B).cif $(SmBiosMemory_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(SmBiosMemory_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+SmBiosMemory_OBJECTS = \
+ $(BUILD_DIR)\$(SmBiosMemory_DIR)\SmBiosMemory.obj \
+ $(BUILD_DIR)\SmBiosMemoryStrings.obj \
+
+SmBiosMemory_INCLUDES=\
+ $(EdkIIGlueLib_INCLUDES)\
+ $(EDK_INCLUDES)\
+ $(INTEL_MCH_INCLUDES)\
+ $(NB_INCLUDES)\
+ /I$(UefiEfiIfrSupportLib_DIR)\
+
+SmBiosMemory_DEFINES = $(MY_DEFINES)\
+ /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=SmbiosMemoryEntryPoint"\
+ /D __EDKII_GLUE_BASE_LIB__ \
+ /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ /D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \
+ /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_HII_LIB__
+
+SmBiosMemory_LIBS=\
+ $(EDKGUIDLIB)\
+ $(EFICOMMONLIB)\
+ $(EFIPROTOCOLLIB)\
+!IF $(EFI_SPECIFICATION_VERSION) >= 0x0002000A
+ $(UEFIEFIIFRSUPPORTLIB)\
+!ENDIF
+ $(INTEL_SA_PROTOCOL_LIB)\
+ $(EdkIIGlueBaseLib_LIB)\
+!IF "$(x64_BUILD)"=="1"
+ $(EdkIIGlueBaseLibX64_LIB)\
+!ELSE
+ $(EdkIIGlueBaseLibIA32_LIB)\
+!ENDIF
+ $(EdkIIGlueBaseIoLibIntrinsic_LIB)\
+ $(EdkIIGlueDxeMemoryAllocationLib_LIB)\
+ $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\
+ $(EdkIIGlueDxeReportStatusCodeLib_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+ $(EdkIIGlueDxeServicesTableLib_LIB)\
+ $(EdkIIGlueHiiLib_LIB)\
+ $(EFIDRIVERLIB)\
+ $(EdkIIGlueUefiRuntimeServicesTableLib_LIB)\
+ $(EdkIIGlueBasePrintLib_LIB) \
+ $(EDKPROTOCOLLIB)\
+
+SmBiosMemoryBin : $(SmBiosMemory_LIBS)
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\SmBiosMemory.mak all\
+ GUID=EDA39402-F375-4496-92D3-83B43CB8A76A\
+ "MY_INCLUDES=$(SmBiosMemory_INCLUDES)" \
+ "MY_DEFINES=$(SmBiosMemory_DEFINES)"\
+ ENTRY_POINT=_ModuleEntryPoint\
+ TYPE=BS_DRIVER\
+ EDKIIModule=DXEDRIVER\
+ "OBJECTS=$(SmBiosMemory_OBJECTS)"\
+ DEPEX1=$(SmBiosMemory_DIR)\SmBiosMemory.dxs\
+ DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX\
+ COMPRESS=1
+
+#---------------------------------------------------------------------------
+# Create SmBiosMemory Setup Screens
+#---------------------------------------------------------------------------
+SmBiosMemorySDB : $(BUILD_DIR)\SmBiosMemory.mak
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\SmBiosMemory.mak all\
+ TYPE=SDB NAME=SmBiosMemory
+ $(STRGATHER) -dump -lang $(SUPPORTED_LANGUAGES: = -lang )\
+ -db $(BUILD_DIR)\SmBiosMemory.sdb\
+ -oh $(BUILD_DIR)\SmBiosMemoryStrDefs.h\
+ -bn SmBiosMemoryStrings\
+ -oc $(BUILD_DIR)\SmBiosMemoryStrings.c
+ $(CC) $(CFLAGS) /Fo$(BUILD_DIR)\ $(BUILD_DIR)\SmBiosMemoryStrings.c \ No newline at end of file
diff --git a/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmBiosMemory.sdl b/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmBiosMemory.sdl
new file mode 100644
index 0000000..945477c
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmBiosMemory.sdl
@@ -0,0 +1,32 @@
+TOKEN
+ Name = "SMBIOS_MEMORY_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable SmBiosMemory support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "SmBiosMemory_DIR"
+End
+
+MODULE
+ Help = "Includes SmBiosMemory.mak to Project"
+ File = "SmBiosMemory.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\SmBiosMemory.ffs"
+ Parent = "FV_MAIN"
+ Help = "Add Intel SMBIOSMemory driver"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "SmBiosMemory"
+ InvokeOrder = ReplaceParent
+End
+
diff --git a/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmbiosMemory.c b/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmbiosMemory.c
new file mode 100644
index 0000000..910c58a
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmbiosMemory.c
@@ -0,0 +1,745 @@
+/** @file
+ This driver will determine memory configuration information from the chipset
+ and memory and create SMBIOS memory structures appropriately.
+
+@copyright
+ Copyright (c) 1999 - 2013 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#include "SmbiosMemory.h"
+EFI_DRIVER_ENTRY_POINT (SmbiosMemoryEntryPoint)
+
+extern UINT8 SmBiosMemoryStrings[];
+MEMORY_MODULE_MANUFACTURE_LIST MemoryModuleManufactureList[] = {
+ {
+ 0,
+ 0x2c,
+ L"Micron"
+ },
+ {
+ 0,
+ 0xad,
+ L"Hynix/Hyundai"
+ },
+ {
+ 0,
+ 0xce,
+ L"Samsung"
+ },
+ {
+ 1,
+ 0x4f,
+ L"Transcend"
+ },
+ {
+ 1,
+ 0x98,
+ L"Kingston"
+ },
+ {
+ 2,
+ 0xfe,
+ L"Elpida"
+ },
+ {
+ 0xff,
+ 0xff,
+ 0
+ }
+};
+
+///
+/// Even SPD Addresses only as we read Words
+///
+const UINT8
+ SpdAddress[] = { 2, 8, 116, 118, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144 };
+
+/**
+ This driver will determine memory configuration information from the chipset
+ and memory and report the memory configuration info to the DataHub.
+
+ @param[in] ImageHandle - Handle for the image of this driver
+ @param[in] SystemTable - Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS - if the data is successfully reported
+ @retval EFI_NOT_FOUND - if the HOB list could not be located.
+ @retval EFI_OUT_OF_RESOURCES - if not able to get resouces.
+**/
+EFI_STATUS
+SmbiosMemoryEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ BOOLEAN Populated;
+ CHAR16 StringBuffer2[64];
+ EFI_DATA_HUB_PROTOCOL *DataHub;
+ DDR_ROW_CONFIG RowConfArray[SA_MC_MAX_SOCKETS];
+ EFI_MEMORY_SUBCLASS_DRIVER_DATA MemorySubClassData;
+ EFI_SMBUS_DEVICE_ADDRESS SmbusSlaveAddress;
+ EFI_SMBUS_HC_PROTOCOL *SmbusController;
+ EFI_STATUS Status;
+ EFI_STRING StringBuffer;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT8 Index;
+ UINT8 *SmbusBuffer;
+ UINT16 ArrayInstance;
+ UINT64 DimmMemorySize;
+ UINT64 TotalMemorySize;
+ UINT8 Dimm;
+ UINTN SmbusBufferSize;
+ UINTN SmbusLength;
+ UINTN SmbusOffset;
+ UINTN StringBufferSize;
+ UINT8 IndexCounter;
+ UINTN IdListIndex;
+ MEM_INFO_PROTOCOL *MemInfoHob;
+ EFI_GUID MemInfoProtocolGuid = MEM_INFO_PROTOCOL_GUID;
+ UINT8 ChannelASlotMap;
+ UINT8 ChannelBSlotMap;
+ UINT8 BitIndex;
+ UINT16 MaxSockets;
+ UINT8 WidthCount=0; //AMI_OVERRIDE [EIP344598]
+ UINT8 ChannelASlotNum;
+ UINT8 ChannelBSlotNum;
+ BOOLEAN SlotPresent;
+ UINT16 MemoryTotalWidth;
+ UINT16 MemoryDataWidth;
+ UINT8 i;
+
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ EFI_HANDLE DriverHandle;
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+ EFI_HII_HANDLE StringPackHandle;
+#else
+ EFI_HII_PROTOCOL *Hii;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HII_PACKAGES *PackageList;
+#endif
+ STRING_REF DimmToDevLocator[] = {
+ STRING_TOKEN (STR_MEMORY_SUBCLASS_DEVICE_LOCATOR_0),
+ STRING_TOKEN (STR_MEMORY_SUBCLASS_DEVICE_LOCATOR_1),
+ STRING_TOKEN (STR_MEMORY_SUBCLASS_DEVICE_LOCATOR_2),
+ STRING_TOKEN (STR_MEMORY_SUBCLASS_DEVICE_LOCATOR_3)
+ };
+
+ STRING_REF DimmToBankLocator[] = {
+ STRING_TOKEN (STR_MEMORY_SUBCLASS_BANK_LOCATOR_0),
+ STRING_TOKEN (STR_MEMORY_SUBCLASS_BANK_LOCATOR_1),
+ STRING_TOKEN (STR_MEMORY_SUBCLASS_BANK_LOCATOR_2),
+ STRING_TOKEN (STR_MEMORY_SUBCLASS_BANK_LOCATOR_3)
+ };
+
+ EFI_GUID gEfiMemorySubClassDriverGuid = EFI_MEMORY_SUBCLASS_DRIVER_GUID;
+ DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy;
+
+ DxePlatformSaPolicy = NULL;
+
+ ///
+ /// Get the platform setup policy.
+ ///
+ Status = gBS->LocateProtocol (&gDxePlatformSaPolicyGuid, NULL, (VOID **) &DxePlatformSaPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ StringBufferSize = (sizeof (CHAR16)) * 100;
+ StringBuffer = AllocateZeroPool (StringBufferSize);
+ if (StringBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SmbusBuffer = NULL;
+ SmbusBufferSize = 0x100;
+ SmbusBuffer = AllocatePool (SmbusBufferSize);
+ if (SmbusBuffer == NULL) {
+ (gBS->FreePool) (StringBuffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, (VOID **) &DataHub);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol (&gEfiSmbusProtocolGuid, NULL, (VOID **) &SmbusController);
+ ASSERT_EFI_ERROR (Status);
+
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+
+ Status = gBS->LocateProtocol (
+ &gEfiHiiDatabaseProtocolGuid,
+ NULL,
+ (VOID **) &HiiDatabase
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// Create driver handle used by HII database
+ ///
+ Status = CreateHiiDriverHandle (&DriverHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// Publish our HII data
+ ///
+ PackageList = PreparePackageList (1, &gEfiMemorySubClassDriverGuid, SmBiosMemoryStrings);
+ if (PackageList == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = HiiDatabase->NewPackageList (
+ HiiDatabase,
+ PackageList,
+ DriverHandle,
+ &StringPackHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+#else
+ ///
+ /// There should only be one HII protocol
+ ///
+ Status = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, (VOID **) &Hii);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Add our default strings to the HII database. They will be modified later.
+ ///
+ PackageList = PreparePackages (1, &gEfiMemorySubClassDriverGuid, SmBiosMemoryStrings);
+ Status = Hii->NewPack (Hii, PackageList, &HiiHandle);
+
+#endif
+
+ (gBS->FreePool) (PackageList);
+
+ Status = gBS->LocateProtocol (&MemInfoProtocolGuid, NULL, (VOID **) &MemInfoHob);
+ ASSERT_EFI_ERROR (Status);
+ ///
+ /// Data for TYPE 16 SMBIOS Structure
+ ///
+ ///
+ /// Create physical array and associated data for all mainboard memory
+ ///
+ ArrayInstance = 1;
+ TotalMemorySize = 0;
+ MemorySubClassData.Header.Version = EFI_MEMORY_SUBCLASS_VERSION;
+ MemorySubClassData.Header.HeaderSize = sizeof (EFI_SUBCLASS_TYPE1_HEADER);
+ MemorySubClassData.Header.Instance = ArrayInstance;
+ MemorySubClassData.Header.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;
+ MemorySubClassData.Header.RecordType = EFI_MEMORY_ARRAY_LOCATION_RECORD_NUMBER;
+
+ MemorySubClassData.Record.ArrayLocationData.MemoryArrayLocation = EfiMemoryArrayLocationSystemBoard;
+ MemorySubClassData.Record.ArrayLocationData.MemoryArrayUse = EfiMemoryArrayUseSystemMemory;
+
+ ///
+ /// Detect ECC
+ ///
+ if (MemInfoHob->MemInfoData.EccSupport) {
+ MemorySubClassData.Record.ArrayLocationData.MemoryErrorCorrection = EfiMemoryErrorCorrectionSingleBitEcc;
+ } else {
+ MemorySubClassData.Record.ArrayLocationData.MemoryErrorCorrection = EfiMemoryErrorCorrectionNone;
+ }
+ ///
+ /// Get the Memory DIMM info from platform policy protocols
+ ///
+ ChannelASlotMap = DxePlatformSaPolicy->MemoryConfig->ChannelASlotMap;
+ ChannelBSlotMap = DxePlatformSaPolicy->MemoryConfig->ChannelBSlotMap;
+ ChannelASlotNum = 0;
+ ChannelBSlotNum = 0;
+ for (BitIndex = 0; BitIndex < 8; BitIndex++) {
+ if ((ChannelASlotMap >> BitIndex) & BIT0) {
+ ChannelASlotNum++;
+ }
+
+ if ((ChannelBSlotMap >> BitIndex) & BIT0) {
+ ChannelBSlotNum++;
+ }
+ }
+
+ MaxSockets = ChannelASlotNum + ChannelBSlotNum;
+ MemorySubClassData.Record.ArrayLocationData.MaximumMemoryCapacity = MAX_RANK_CAPACITY * SA_MC_MAX_SIDES * MaxSockets;
+ MemorySubClassData.Record.ArrayLocationData.NumberMemoryDevices = (UINT16) (MaxSockets);
+
+ ///
+ /// Report top level physical array to datahub
+ /// This will translate into a Type 16 SMBIOS Record
+ ///
+ Status = DataHub->LogData (
+ DataHub,
+ &gEfiMemorySubClassGuid,
+ &gEfiMemorySubClassDriverGuid,
+ EFI_DATA_RECORD_CLASS_DATA,
+ &MemorySubClassData,
+ sizeof (EFI_SUBCLASS_TYPE1_HEADER) + sizeof (EFI_MEMORY_ARRAY_LOCATION_DATA)
+ );
+ if (EFI_ERROR (Status)) {
+ goto CleanAndExit;
+ }
+ ///
+ /// Get Memory size parameters for each rank
+ ///
+ ///
+ /// We start from a base address of 0 for rank 0. We calculate the base address based on the DIMM size.
+ ///
+ BaseAddress = 0;
+
+ for (Dimm = 0; Dimm < SA_MC_MAX_SLOTS; Dimm++) {
+ ///
+ /// Channel 0
+ ///
+ RowConfArray[Dimm].BaseAddress = BaseAddress;
+ RowConfArray[Dimm].RowLength = LShiftU64 (MemInfoHob->MemInfoData.dimmSize[Dimm], 20);
+ BaseAddress += RowConfArray[Dimm].RowLength;
+ ///
+ /// Channel 1
+ ///
+ RowConfArray[Dimm + SA_MC_MAX_SLOTS].BaseAddress = BaseAddress;
+ RowConfArray[Dimm + SA_MC_MAX_SLOTS].RowLength = LShiftU64 (MemInfoHob->MemInfoData.dimmSize[Dimm + SA_MC_MAX_SLOTS], 20);
+ BaseAddress += RowConfArray[Dimm + SA_MC_MAX_SLOTS].RowLength;
+
+ }
+ ///
+ /// For each existed socket whether it is populated or not generate Type 17.
+ /// Type 20 is optional for existed and populated socket.
+ ///
+ /// The Desktop and mobile only support 2 channels * 2 slots per channel = 4 sockets totally
+ /// So there is rule here for Desktop and mobile that there are no more 4 DIMMS totally in a system:
+ /// Channel A/ Slot 0 --> SpdAddressTable[0] --> DimmToDevLocator[0] --> MemInfoHobProtocol.MemInfoData.dimmSize[0]
+ /// Channel A/ Slot 1 --> SpdAddressTable[1] --> DimmToDevLocator[1] --> MemInfoHobProtocol.MemInfoData.dimmSize[1]
+ /// Channel B/ Slot 0 --> SpdAddressTable[2] --> DimmToDevLocator[2] --> MemInfoHobProtocol.MemInfoData.dimmSize[2]
+ /// Channel B/ Slot 1 --> SpdAddressTable[3] --> DimmToDevLocator[3] --> MemInfoHobProtocol.MemInfoData.dimmSize[3]
+ ///
+ for (Dimm = 0; Dimm < SA_MC_MAX_SOCKETS; Dimm++) {
+ ///
+ /// Use channel slot map to check whether the Socket is supported in this SKU, some SKU only has 2 Sockets totally
+ ///
+ SlotPresent = FALSE;
+ if (Dimm < 2) {
+ if (ChannelASlotMap & (1 << Dimm)) {
+ SlotPresent = TRUE;
+ }
+ } else {
+ if (ChannelBSlotMap & (1 << (Dimm - 2))) {
+ SlotPresent = TRUE;
+ }
+ }
+ ///
+ /// Don't create Type 17 and Type 20 items for non-existing socket
+ ///
+ if (!SlotPresent) {
+ continue;
+ }
+ ///
+ /// Generate Memory Device info (Type 17)
+ ///
+ ZeroMem (SmbusBuffer, SmbusBufferSize);
+ ///
+ /// Only read the SPD data if the DIMM is populated in the slot.
+ ///
+ Populated = MemInfoHob->MemInfoData.DimmExist[Dimm];
+ if (Populated) {
+ WidthCount++; //AMI_OVERRIDE [EIP344598]
+ ///
+ /// Read the SPD for this DIMM
+ ///
+ SmbusSlaveAddress.SmbusDeviceAddress = (DxePlatformSaPolicy->MemoryConfig->SpdAddressTable[Dimm]) >> 1;
+
+ ///
+ /// Read only needed values from SMBus or DimmsSpdData pointer to improve performance.
+ ///
+ for (i = 0; i < sizeof SpdAddress; i++) {
+ SmbusOffset = SpdAddress[i];
+ if (MemInfoHob->MemInfoData.DimmsSpdData[Dimm] == NULL) {
+ SmbusLength = 2;
+ Status = SmbusController->Execute (
+ SmbusController,
+ SmbusSlaveAddress,
+ SmbusOffset,
+ EfiSmbusReadWord,
+ FALSE,
+ &SmbusLength,
+ &SmbusBuffer[SmbusOffset]
+ );
+ if (EFI_ERROR (Status)) {
+ Populated = FALSE;
+ break;
+ }
+ } else {
+ *(UINT16 *) (SmbusBuffer + SmbusOffset) = *(UINT16 *) (MemInfoHob->MemInfoData.DimmsSpdData[Dimm] + SmbusOffset);
+ }
+ }
+ }
+
+ ZeroMem (&MemorySubClassData, sizeof (EFI_MEMORY_SUBCLASS_DRIVER_DATA));
+
+ ///
+ /// Use SPD data to generate Device Type info
+ ///
+ MemorySubClassData.Header.Version = EFI_MEMORY_SUBCLASS_VERSION;
+ MemorySubClassData.Header.HeaderSize = sizeof (EFI_SUBCLASS_TYPE1_HEADER);
+ MemorySubClassData.Header.Instance = ArrayInstance;
+ MemorySubClassData.Header.SubInstance = (UINT16) (Dimm + 1);
+ MemorySubClassData.Header.RecordType = EFI_MEMORY_ARRAY_LINK_RECORD_NUMBER;
+
+ MemorySubClassData.Record.ArrayLink.MemoryDeviceLocator = DimmToDevLocator[Dimm];
+ MemorySubClassData.Record.ArrayLink.MemoryBankLocator = DimmToBankLocator[Dimm];
+
+#ifdef MEMORY_ASSET_TAG
+ StrCpy (StringBuffer, MEMORY_ASSET_TAG);
+ MemorySubClassData.Record.ArrayLink.MemoryAssetTag = (STRING_REF) 0;
+
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ Status = IfrLibNewString (StringPackHandle, &MemorySubClassData.Record.ArrayLink.MemoryAssetTag, StringBuffer);
+ ASSERT_EFI_ERROR (Status);
+#else
+ Status = Hii->NewString (
+ Hii,
+ NULL,
+ HiiHandle,
+ &MemorySubClassData.Record.ArrayLink.MemoryAssetTag,
+ StringBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+#endif
+
+#else
+ MemorySubClassData.Record.ArrayLink.MemoryAssetTag = STRING_TOKEN (STR_MEMORY_SUBCLASS_DEFAULT_ASSET_TAG);
+#endif
+
+ MemorySubClassData.Record.ArrayLink.MemoryArrayLink.ProducerName = gEfiMemorySubClassDriverGuid;
+ MemorySubClassData.Record.ArrayLink.MemoryArrayLink.Instance = ArrayInstance;
+ MemorySubClassData.Record.ArrayLink.MemoryArrayLink.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;
+ MemorySubClassData.Record.ArrayLink.MemorySubArrayLink.ProducerName = gEfiMemorySubClassDriverGuid;
+ MemorySubClassData.Record.ArrayLink.MemorySubArrayLink.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;
+ ///
+ /// Set MemoryType value to DDR3 (0x18)
+ ///
+ MemorySubClassData.Record.ArrayLink.MemoryType = EfiMemoryTypeDdr3;
+
+ ///
+ /// According to SMBIOS 2.6.1 Specification - Appendix A Conformance Guidelines
+ /// 4.8.7: Form Factor is not 00h (Reserved) or 02h (Unknown).
+ ///
+ if (Populated) {
+ switch (SmbusBuffer[DDR_MTYPE_SPD_OFFSET] & DDR_MTYPE_SPD_MASK) {
+ case DDR_MTYPE_SODIMM:
+ MemorySubClassData.Record.ArrayLink.MemoryFormFactor = EfiMemoryFormFactorSodimm;
+ break;
+
+ case DDR_MTYPE_RDIMM:
+ case DDR_MTYPE_MINI_RDIMM:
+ MemorySubClassData.Record.ArrayLink.MemoryFormFactor = EfiMemoryFormFactorRimm;
+ break;
+
+ case DDR_MTYPE_UDIMM:
+ case DDR_MTYPE_MICRO_DIMM:
+ case DDR_MTYPE_MINI_UDIMM:
+ default:
+ MemorySubClassData.Record.ArrayLink.MemoryFormFactor = EfiMemoryFormFactorDimm;
+ }
+ ///
+ /// Show name for known manufacturer or ID for unknown manufacturer
+ ///
+ StrCpy (StringBuffer, L"");
+
+ ///
+ /// Calculate index counter
+ /// Clearing Bit7 as it is the Parity Bit for Byte 117
+ ///
+ IndexCounter = SmbusBuffer[117] & (~0x80);
+
+ ///
+ /// Converter memory manufacturer ID to string
+ ///
+ for (IdListIndex = 0; MemoryModuleManufactureList[IdListIndex].Index != 0xff; IdListIndex++) {
+ if (MemoryModuleManufactureList[IdListIndex].Index == IndexCounter &&
+ MemoryModuleManufactureList[IdListIndex].ManufactureId == SmbusBuffer[118]
+ ) {
+ StrCpy (StringBuffer, MemoryModuleManufactureList[IdListIndex].ManufactureName);
+ break;
+ }
+ }
+ ///
+ /// Use original data if no conversion information in conversion table
+ ///
+ if (!(*StringBuffer)) {
+ for (Index = 117; Index < 119; Index++) {
+ ///
+ /// --cr-- EfiValueToHexStr(StringBuffer2, SmbusBuffer[Index], PREFIX_ZERO, 2);
+ ///
+ UnicodeValueToString (StringBuffer2, PREFIX_ZERO, SmbusBuffer[Index], 2);
+ StrCat (StringBuffer, StringBuffer2);
+ }
+ }
+
+ MemorySubClassData.Record.ArrayLink.MemoryManufacturer = (STRING_REF) 0;
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ Status = IfrLibNewString (
+ StringPackHandle,
+ &MemorySubClassData.Record.ArrayLink.MemoryManufacturer,
+ StringBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+#else
+ Status = Hii->NewString (
+ Hii,
+ NULL,
+ HiiHandle,
+ &MemorySubClassData.Record.ArrayLink.MemoryManufacturer,
+ StringBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+#endif
+ StrCpy (StringBuffer, L"");
+ for (Index = 122; Index < 126; Index++) {
+ EfiValueToHexStr(StringBuffer2, SmbusBuffer[Index], PREFIX_ZERO, 2);
+ StrCat (StringBuffer, StringBuffer2);
+ }
+
+ MemorySubClassData.Record.ArrayLink.MemorySerialNumber = (STRING_REF) 0;
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ Status = IfrLibNewString (
+ StringPackHandle,
+ &MemorySubClassData.Record.ArrayLink.MemorySerialNumber,
+ StringBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+#else
+ Status = Hii->NewString (
+ Hii,
+ NULL,
+ HiiHandle,
+ &MemorySubClassData.Record.ArrayLink.MemorySerialNumber,
+ StringBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+#endif
+ StrCpy (StringBuffer, L"");
+ for (Index = 128; Index < 146; Index++) {
+ UnicodeSPrint (
+ StringBuffer2,
+ 4,
+ L"%c",
+ SmbusBuffer[Index]
+ );
+ StrCat (StringBuffer, StringBuffer2);
+ }
+
+ MemorySubClassData.Record.ArrayLink.MemoryPartNumber = (STRING_REF) 0;
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ Status = IfrLibNewString (StringPackHandle, &MemorySubClassData.Record.ArrayLink.MemoryPartNumber, StringBuffer);
+ ASSERT_EFI_ERROR (Status);
+#else
+ Status = Hii->NewString (
+ Hii,
+ NULL,
+ HiiHandle,
+ &MemorySubClassData.Record.ArrayLink.MemoryPartNumber,
+ StringBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+#endif
+ ///
+ /// Get the Memory TotalWidth and DataWidth info for DDR3
+ /// refer to DDR3 SPD 1.0 spec, Byte 8: Module Memory Bus Width
+ /// SPD Offset 8 Bits [2:0] DataWidth aka Primary Bus Width
+ /// SPD Offset 8 Bits [4:3] Bus Width extension for ECC
+ ///
+ MemoryDataWidth = 8 * (1 << (SmbusBuffer[8] & 0x07));
+ MemoryTotalWidth = MemoryDataWidth + 8 * (SmbusBuffer[8] & 0x18);
+ MemorySubClassData.Record.ArrayLink.MemoryTotalWidth = MemoryTotalWidth;
+ MemorySubClassData.Record.ArrayLink.MemoryDataWidth = MemoryDataWidth;
+ DimmMemorySize = RowConfArray[Dimm].RowLength;
+
+ TotalMemorySize += DimmMemorySize;
+ MemorySubClassData.Record.ArrayLink.MemoryDeviceSize = DimmMemorySize;
+ MemorySubClassData.Record.ArrayLink.MemoryTypeDetail.Synchronous = 1;
+ if (MemorySubClassData.Record.ArrayLink.MemoryFormFactor == EfiMemoryFormFactorRimm) {
+ MemorySubClassData.Record.ArrayLink.MemoryTypeDetail.Rambus = 1;
+ }
+
+ MemorySubClassData.Record.ArrayLink.MemorySpeed = MemInfoHob->MemInfoData.ddrFreq;
+ MemorySubClassData.Record.ArrayLink.MemoryAttributes = MemInfoHob->MemInfoData.RankInDimm[Dimm] & 0x0F;
+ } else {
+ ///
+ /// Memory is not Populated in this slot.
+ ///
+ StrCpy (StringBuffer, L"");
+ MemorySubClassData.Record.ArrayLink.MemoryManufacturer = (STRING_REF) 0;
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ Status = IfrLibNewString (
+ StringPackHandle,
+ &MemorySubClassData.Record.ArrayLink.MemoryManufacturer,
+ StringBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+#else
+ Status = Hii->NewString (
+ Hii,
+ NULL,
+ HiiHandle,
+ &MemorySubClassData.Record.ArrayLink.MemoryManufacturer,
+ StringBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+#endif
+ MemorySubClassData.Record.ArrayLink.MemorySerialNumber = (STRING_REF) 0;
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ Status = IfrLibNewString (
+ StringPackHandle,
+ &MemorySubClassData.Record.ArrayLink.MemorySerialNumber,
+ StringBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+#else
+ Status = Hii->NewString (
+ Hii,
+ NULL,
+ HiiHandle,
+ &MemorySubClassData.Record.ArrayLink.MemorySerialNumber,
+ StringBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+#endif
+
+ MemorySubClassData.Record.ArrayLink.MemoryPartNumber = (STRING_REF) 0;
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ Status = IfrLibNewString (StringPackHandle, &MemorySubClassData.Record.ArrayLink.MemoryPartNumber, StringBuffer);
+ ASSERT_EFI_ERROR (Status);
+#else
+ Status = Hii->NewString (
+ Hii,
+ NULL,
+ HiiHandle,
+ &MemorySubClassData.Record.ArrayLink.MemoryPartNumber,
+ StringBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+#endif
+ DimmMemorySize = 0;
+ MemorySubClassData.Record.ArrayLink.MemorySpeed = 0;
+ MemorySubClassData.Record.ArrayLink.MemoryDeviceSize = 0;
+ MemorySubClassData.Record.ArrayLink.MemoryType = EfiMemoryTypeUnknown;
+ MemorySubClassData.Record.ArrayLink.MemoryFormFactor = EfiMemoryFormFactorDimm;
+ }
+ ///
+ /// Generate Memory Device info (Type 17)
+ ///
+ Status = DataHub->LogData (
+ DataHub,
+ &gEfiMemorySubClassGuid,
+ &gEfiMemorySubClassDriverGuid,
+ EFI_DATA_RECORD_CLASS_DATA,
+ &MemorySubClassData,
+ sizeof (EFI_SUBCLASS_TYPE1_HEADER) + sizeof (EFI_MEMORY_ARRAY_LINK)
+ );
+ if (EFI_ERROR (Status)) {
+ goto CleanAndExit;
+ }
+ ///
+ /// Memory Device Mapped Address (Type 20) is optional and it will not be generated by RC
+ ///
+// ...AMI_OVERRIDE... support Type 20
+ if ((Populated) && (DimmMemorySize != 0)) {
+ ///
+ /// Generate Memory Device Mapped Address info (Type 20)
+ ///
+ MemorySubClassData.Header.Instance = ArrayInstance;
+ MemorySubClassData.Header.SubInstance = (UINT16) (Dimm + 1);
+ MemorySubClassData.Header.RecordType = EFI_MEMORY_DEVICE_START_ADDRESS_RECORD_NUMBER;
+
+ MemorySubClassData.Record.DeviceStartAddress.MemoryDeviceStartAddress = RowConfArray[Dimm].BaseAddress;
+ MemorySubClassData.Record.DeviceStartAddress.MemoryDeviceEndAddress = MemorySubClassData.Record.
+ DeviceStartAddress.MemoryDeviceStartAddress +
+ DimmMemorySize -
+ 1;
+ ///
+ /// 1 or 2 will be applicable for lock step mode
+ ///
+ MemorySubClassData.Record.DeviceStartAddress.MemoryDevicePartitionRowPosition = 0xFF;
+
+ MemorySubClassData.Record.DeviceStartAddress.PhysicalMemoryDeviceLink.ProducerName = gEfiMemorySubClassDriverGuid;
+ MemorySubClassData.Record.DeviceStartAddress.PhysicalMemoryDeviceLink.Instance = ArrayInstance;
+ MemorySubClassData.Record.DeviceStartAddress.PhysicalMemoryDeviceLink.SubInstance = (UINT16) (Dimm + 1);
+ MemorySubClassData.Record.DeviceStartAddress.PhysicalMemoryArrayLink.ProducerName = gEfiMemorySubClassDriverGuid;
+ MemorySubClassData.Record.DeviceStartAddress.PhysicalMemoryArrayLink.Instance = ArrayInstance;
+ MemorySubClassData.Record.DeviceStartAddress.PhysicalMemoryArrayLink.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;
+
+ ///
+ /// Set Interleave Data Depth and Position.
+ ///
+ if (((Dimm >= SA_MC_MAX_SLOTS) && (MemInfoHob->MemInfoData.DimmExist[Dimm - SA_MC_MAX_SLOTS])) ||
+ ((Dimm < SA_MC_MAX_SLOTS) && (MemInfoHob->MemInfoData.DimmExist[Dimm + SA_MC_MAX_SLOTS]))
+ ) {
+ ///
+ /// If DIMMs on both channels are populated then Interleaved Data Depth is 2 and Interleave Position is 1 or 2
+ ///
+ MemorySubClassData.Record.DeviceStartAddress.MemoryDeviceInterleaveDataDepth = (UINT8) (MaxSockets >> 1);
+ MemorySubClassData.Record.DeviceStartAddress.MemoryDeviceInterleavePosition = (UINT8) (1 << (Dimm >= (MaxSockets >> 1)));
+ } else {
+ ///
+ /// Interleaved Data Depth and Position is 1
+ ///
+ MemorySubClassData.Record.DeviceStartAddress.MemoryDeviceInterleaveDataDepth = 1;
+ MemorySubClassData.Record.DeviceStartAddress.MemoryDeviceInterleavePosition = 1;
+ }
+ ///
+ /// Generate Memory Device Mapped Address info (Type 20)
+ ///
+ Status = DataHub->LogData (
+ DataHub,
+ &gEfiMemorySubClassGuid,
+ &gEfiMemorySubClassDriverGuid,
+ EFI_DATA_RECORD_CLASS_DATA,
+ &MemorySubClassData,
+ sizeof (EFI_SUBCLASS_TYPE1_HEADER) + sizeof (EFI_MEMORY_DEVICE_START_ADDRESS)
+ );
+ if (EFI_ERROR (Status)) {
+ goto CleanAndExit;
+ }
+ }
+// ...AMI_OVERRIDE... support Type 20 end
+ }
+ ///
+ /// Generate Memory Array Mapped Address info (TYPE 19)
+ ///
+ MemorySubClassData.Header.Instance = ArrayInstance;
+ MemorySubClassData.Header.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;
+ MemorySubClassData.Header.RecordType = EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER;
+
+ MemorySubClassData.Record.ArrayStartAddress.MemoryArrayStartAddress = 0;
+ MemorySubClassData.Record.ArrayStartAddress.MemoryArrayEndAddress = TotalMemorySize - 1;
+ MemorySubClassData.Record.ArrayStartAddress.PhysicalMemoryArrayLink.ProducerName = gEfiMemorySubClassDriverGuid;
+ MemorySubClassData.Record.ArrayStartAddress.PhysicalMemoryArrayLink.Instance = ArrayInstance;
+ MemorySubClassData.Record.ArrayStartAddress.PhysicalMemoryArrayLink.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;
+ //MemorySubClassData.Record.ArrayStartAddress.MemoryArrayPartitionWidth = (UINT16) (MaxSockets); //AMI_OVERRIDE [EIP344598]
+ MemorySubClassData.Record.ArrayStartAddress.MemoryArrayPartitionWidth = WidthCount; //AMI_OVERRIDE [EIP344598]
+ ///
+ /// Generate Memory Array Mapped Address info (TYPE 19)
+ ///
+ Status = DataHub->LogData (
+ DataHub,
+ &gEfiMemorySubClassGuid,
+ &gEfiMemorySubClassDriverGuid,
+ EFI_DATA_RECORD_CLASS_DATA,
+ &MemorySubClassData,
+ sizeof (EFI_SUBCLASS_TYPE1_HEADER) + sizeof (EFI_MEMORY_ARRAY_START_ADDRESS)
+ );
+CleanAndExit:
+ (gBS->FreePool) (SmbusBuffer);
+ (gBS->FreePool) (StringBuffer);
+ return Status;
+}
diff --git a/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmbiosMemory.dxs b/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmbiosMemory.dxs
new file mode 100644
index 0000000..5675c94
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmbiosMemory.dxs
@@ -0,0 +1,58 @@
+/** @file
+ Dependency expression file for the MemorySubClass Driver.
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains a 'Sample Driver' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may be modified by the user, subject to
+ the additional terms of the license agreement
+
+**/
+
+//
+// Common for R8 and R9 codebase
+//
+#include "AutoGen.h"
+#include "DxeDepex.h"
+
+//
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase;
+// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase.
+//
+#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB)
+#include "EfiDepex.h"
+
+#include EFI_PROTOCOL_DEFINITION (DataHub)
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+#include EFI_PROTOCOL_DEFINITION (HiiDatabase)
+#else
+#include EFI_PROTOCOL_DEFINITION (Hii)
+#endif
+#include EFI_PROTOCOL_DEFINITION (Smbus)
+#include EFI_PROTOCOL_DEFINITION (PciRootBridgeIo)
+#include EFI_PROTOCOL_DEPENDENCY (SaPlatformPolicy)
+#include EFI_PROTOCOL_DEPENDENCY (MemInfo)
+#endif
+
+DEPENDENCY_START
+ EFI_DATA_HUB_PROTOCOL_GUID AND
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ EFI_HII_DATABASE_PROTOCOL_GUID AND
+#else
+ EFI_HII_PROTOCOL_GUID AND
+#endif
+ EFI_SMBUS_HC_PROTOCOL_GUID AND
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID AND
+ DXE_PLATFORM_SA_POLICY_GUID AND
+ MEM_INFO_PROTOCOL_GUID
+DEPENDENCY_END
diff --git a/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmbiosMemory.h b/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmbiosMemory.h
new file mode 100644
index 0000000..9e0a641
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmbiosMemory.h
@@ -0,0 +1,127 @@
+/** @file
+ Header file for the SMBIOS Memory Driver.
+ This driver will determine memory configuration information from the chipset
+ and memory and create SMBIOS Memory structures appropriately.
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+**/
+#ifndef _SMBIOS_MEMORY_H_
+#define _SMBIOS_MEMORY_H_
+
+#include "EdkIIGlueDxe.h"
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+#include "UefiIfrLibrary.h"
+#include EFI_PROTOCOL_DEPENDENCY (HiiDatabase)
+#include EFI_PROTOCOL_DEPENDENCY (HiiString)
+#else
+#include EFI_PROTOCOL_DEPENDENCY (Hii)
+#endif
+#include "SaAccess.h"
+#include "CpuFuncs.h"
+#include "Cpu.h"
+
+///
+/// This is the generated header file which includes whatever needs to be exported (strings + IFR)
+///
+#include "SmbiosMemoryStrDefs.h"
+
+///
+/// Driver Consumed Protocol Prototypes
+///
+#include EFI_PROTOCOL_DEPENDENCY (DataHub)
+#include EFI_PROTOCOL_DEPENDENCY (Smbus)
+#include EFI_PROTOCOL_DEPENDENCY (MemInfo)
+#include EFI_PROTOCOL_DEPENDENCY (PciRootBridgeIo)
+#include EFI_PROTOCOL_DEPENDENCY (SaPlatformPolicy)
+
+///
+/// Driver private data
+///
+#include EFI_GUID_DEFINITION (DataHubRecords)
+
+#define EFI_MEMORY_SUBCLASS_DRIVER_GUID \
+ { \
+ 0x1767CEED, 0xDB82, 0x47cd, 0xBF, 0x2B, 0x68, 0x45, 0x8A, 0x8C, 0xCF, 0xFF \
+ }
+
+///
+/// Memory
+///
+#define MEM_FRQCY_BIT_SHIFT 1
+
+#define MAD_DIMM_CH0 0x5004
+#define MAD_DIMM_CH1 0x5008
+
+///
+/// Memory module type definition in DDR3 SPD Data
+///
+#define DDR_MTYPE_SPD_OFFSET 3 ///< Module type, offset 3, bits (3:0)
+#define DDR_MTYPE_SPD_MASK 0x0F ///< Module Type mask
+#define DDR_MTYPE_RDIMM 0x01 ///< Registered DIMM Memory
+#define DDR_MTYPE_UDIMM 0x02 ///< Unbuffered DIMM Memory
+#define DDR_MTYPE_SODIMM 0x03 ///< Small Outline DIMM Memory
+#define DDR_MTYPE_MICRO_DIMM 0x04 ///< Micro-DIMM Memory
+#define DDR_MTYPE_MINI_RDIMM 0x05 ///< Mini Registered DIMM Memory
+#define DDR_MTYPE_MINI_UDIMM 0x06 ///< Mini Unbuffered DIMM Memory
+///
+/// Maximum rank memory size supported by the memory controller
+/// 4 GB in terms of KB
+///
+#define MAX_RANK_CAPACITY (4 * 1024 * 1024)
+
+#ifndef MEMORY_ASSET_TAG
+#define MEMORY_ASSET_TAG L"9876543210"
+#endif
+///
+/// Memory Module Manufacture ID List Structure
+///
+typedef struct {
+ UINT8 Index;
+ UINT8 ManufactureId;
+ CHAR16 *ManufactureName;
+} MEMORY_MODULE_MANUFACTURE_LIST;
+
+///
+/// Row configuration data structure
+///
+typedef struct {
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 RowLength; ///< Size of Row in bytes
+} DDR_ROW_CONFIG;
+
+///
+/// Prototypes
+///
+/**
+ This driver will determine memory configuration information from the chipset
+ and memory and report the memory configuration info to the DataHub.
+
+ @param[in] ImageHandle - Handle for the image of this driver
+ @param[in] SystemTable - Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS - if the data is successfully reported
+ @retval EFI_NOT_FOUND - if the HOB list could not be located.
+ @retval EFI_OUT_OF_RESOURCES - if not able to get resouces.
+**/
+EFI_STATUS
+SmbiosMemoryEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+;
+
+#endif
diff --git a/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmbiosMemoryStrings.uni b/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmbiosMemoryStrings.uni
new file mode 100644
index 0000000..3b5be48
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SmbiosMemory/Dxe/SmbiosMemoryStrings.uni
Binary files differ