Просмотр исходного кода

Platform/Socionext/DeveloperBox: add SMBIOS type 17 table

This commit adds the SMBIOS type 17 table support for Developerbox.
The SPD can be accessed only from the SCP through I2C bus,
so this commit expects that SCP-firmware reads the SPD and
stores it in the non-secure SRAM.

This commit also reduces the edk2 stack size to allocate
the space for storing SPD. It requires 2KB, 512bytes * 4 DIMMs.

Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Masami Hiramatsu <masami.hiramatsu@linaro.org>
Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Masahisa Kojima 2 лет назад
Родитель
Сommit
c718abce99

+ 3 - 0
Platform/Socionext/DeveloperBox/DeveloperBox.dsc

@@ -185,6 +185,9 @@
 
   gSynQuacerTokenSpaceGuid.PcdDramInfoBase|0x2E00FFC0
 
+  # SCP-firmware stored SPD DDR4 data in non-secure SRAM
+  gSynQuacerTokenSpaceGuid.PcdStoredSpdDDR4Address|0x2E00F000
+
   #
   # 96boards mezzanine support
   #

+ 1 - 1
Platform/Socionext/DeveloperBox/DeveloperBox.dsc.inc

@@ -147,7 +147,7 @@
 
   # non-secure SRAM
   gArmPlatformTokenSpaceGuid.PcdCPUCoresStackBase|0x2E000000
-  gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize|0xFFC0
+  gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize|0xF000
 
   gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|24
 

+ 431 - 122
Platform/Socionext/DeveloperBox/SmbiosPlatformDxe/SmbiosPlatformDxe.c

@@ -10,17 +10,52 @@
 **/
 
 #include <PiDxe.h>
+#include <IndustryStandard/SdramSpdDdr4.h>
 #include <IndustryStandard/SmBios.h>
 #include <Library/BaseLib.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
 #include <Library/HobLib.h>
 #include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Protocol/Smbios.h>
 
 STATIC EFI_SMBIOS_PROTOCOL       *mSmbios;
 
+#define SPD4_MEM_BUS_WIDTH_8BIT    (0x00)
+#define SPD4_MEM_BUS_WIDTH_16BIT   (BIT0)
+#define SPD4_MEM_BUS_WIDTH_32BIT   (BIT1)
+#define SPD4_MEM_BUS_WIDTH_64BIT   (BIT0 | BIT1)
+
+#define SPD4_MEM_DEV_WIDTH_4BIT    (0x00)
+#define SPD4_MEM_DEV_WIDTH_8BIT    (BIT0)
+#define SPD4_MEM_DEV_WIDTH_16BIT   (BIT1)
+#define SPD4_MEM_DEV_WIDTH_32BIT   (BIT0 | BIT1)
+
+#define SPD4_DDR4_SDRAM_TYPE          (0x0C)
+
+#define SPD4_MEM_MODULE_TYPE_RDIMM    (0x01)
+#define SPD4_MEM_MODULE_TYPE_UDIMM    (0x02)
+#define SPD4_MEM_MODULE_TYPE_SODIMM   (0x03)
+
+#define TYPE17_DEVICE_LOCATOR_LEN     (8 + 1)
+#define TYPE17_BANK_LOCATOR_LEN       (20 + 1)
+#define TYPE17_MANUFACTURER_NAME_LEN  (30 + 1)
+#define TYPE17_SERIAL_NUMBER_LEN      (16 + 1)
+#define TYPE17_ASSETTAG_LEN           (16 + 1)
+#define TYPE17_MODULE_PART_NUMBER_LEN (20 + 1)
+#define TYPE17_FIRMWARE_VERSION_LEN   (8 + 1)
+
+#define TYPE17_STRINGS_MAX_LEN        (TYPE17_DEVICE_LOCATOR_LEN + \
+                                       TYPE17_BANK_LOCATOR_LEN + \
+                                       TYPE17_MANUFACTURER_NAME_LEN + \
+                                       TYPE17_SERIAL_NUMBER_LEN + \
+                                       TYPE17_ASSETTAG_LEN + \
+                                       TYPE17_MODULE_PART_NUMBER_LEN + \
+                                       TYPE17_FIRMWARE_VERSION_LEN + \
+                                       1/* null SMBIOS_TABLE_STRING terminator */ )
+
 //
 // Type definition and contents of the default SMBIOS table.
 // This table covers only the minimum structures required by
@@ -69,7 +104,7 @@ typedef struct {
 
 typedef struct {
   SMBIOS_TABLE_TYPE17 Base;
-  CHAR8               Strings[];
+  CHAR8               Strings[TYPE17_STRINGS_MAX_LEN];
 } ARM_TYPE17;
 
 typedef struct {
@@ -94,6 +129,69 @@ enum {
   SMBIOS_HANDLE_MEMORY,
 };
 
+struct JEP106_MANUFACTURER_TABLE {
+  UINT16 ManufacturerId;
+  CHAR8  ManufacturerName[TYPE17_MANUFACTURER_NAME_LEN];
+};
+
+STATIC CONST struct JEP106_MANUFACTURER_TABLE Manufacturer[] = {
+  {0x0010, "NEC\0"},
+  {0x002C, "Micron Technology\0"},
+  {0x003D, "Tektronix\0"},
+  {0x0097, "Texas Instruments\0"},
+  {0x00AD, "SK Hynix\0"},
+  {0x00B3, "IDT\0"},
+  {0x00C1, "Infineon\0"},
+  {0x00CE, "Samsung\0"},
+  {0x00DA, "Winbond Electronic\0"},
+  {0x014F, "Transcend Information\0"},
+  {0x0194, "Smart Modular\0"},
+  {0x0198, "Kingston\0"},
+  {0x02C8, "Agilent Technologies\0"},
+  {0x02FE, "Elpida\0"},
+  {0x030B, "Nanya Technology\0"},
+  {0x0443, "Ramaxel Technology\0"},
+  {0x04B3, "Inphi Corporation\0"},
+  {0x04C8, "Powerchip Semiconductor\0"},
+  {0x0551, "Qimonda\0"},
+  {0x0557, "AENEON\0"},
+  {0x059B, "Crucial Technology\0"},
+  {0xFFFF, "Unknown\0"}
+};
+
+enum SPD4_SDRAM_CAPACITY {
+  SPD4_SDRAM_CAPACITY_256MBIT = 0,
+  SPD4_SDRAM_CAPACITY_512MBIT,
+  SPD4_SDRAM_CAPACITY_1GBIT,
+  SPD4_SDRAM_CAPACITY_2GBIT,
+  SPD4_SDRAM_CAPACITY_4GBIT,
+  SPD4_SDRAM_CAPACITY_8GBIT,
+  SPD4_SDRAM_CAPACITY_16GBIT,
+  SPD4_SDRAM_CAPACITY_32GBIT,
+  SPD4_SDRAM_CAPACITY_12GBIT,
+  SPD4_SDRAM_CAPACITY_24GBIT,
+  SPD4_SDRAM_CAPACITY_INVALID = 0xFF,
+};
+
+struct SPD4_SDRAM_CAPACITY_TABLE {
+  enum SPD4_SDRAM_CAPACITY        Capacity;
+  UINT16                          SizeMbit;
+};
+
+STATIC CONST struct SPD4_SDRAM_CAPACITY_TABLE CapacityTable[]  = {
+  {SPD4_SDRAM_CAPACITY_256MBIT,     256        },
+  {SPD4_SDRAM_CAPACITY_512MBIT,     512        },
+  {SPD4_SDRAM_CAPACITY_1GBIT,       (1 * 1024) },
+  {SPD4_SDRAM_CAPACITY_2GBIT,       (2 * 1024) },
+  {SPD4_SDRAM_CAPACITY_4GBIT,       (4 * 1024) },
+  {SPD4_SDRAM_CAPACITY_8GBIT,       (8 * 1024) },
+  {SPD4_SDRAM_CAPACITY_16GBIT,      (16 * 1024)},
+  {SPD4_SDRAM_CAPACITY_32GBIT,      (32 * 1024)},
+  {SPD4_SDRAM_CAPACITY_12GBIT,      (12 * 1024)},
+  {SPD4_SDRAM_CAPACITY_24GBIT,      (24 * 1024)},
+  {SPD4_SDRAM_CAPACITY_INVALID,     0          },
+};
+
 // BIOS information (section 7.1)
 STATIC CONST ARM_TYPE0 mArmDefaultType0 = {
   {
@@ -394,123 +492,6 @@ STATIC CONST ARM_TYPE16 mArmDefaultType16 = {
   }
 };
 
-// Memory device
-STATIC CONST ARM_TYPE17 mArmDefaultType17_1 = {
-  {
-    { // SMBIOS_STRUCTURE Hdr
-      EFI_SMBIOS_TYPE_MEMORY_DEVICE,
-      sizeof (SMBIOS_TABLE_TYPE17),
-      SMBIOS_HANDLE_PI_RESERVED,
-    },
-    SMBIOS_HANDLE_MEMORY,           // array to which this module belongs
-    0xFFFE,                         // no errors
-    72,                             // single DIMM with ECC
-    64,                             // data width of this device (64-bits)
-    0xFFFF,                         // size unknown
-    0x09,                           // DIMM
-    1,                              // part of a set
-    1,                              // device locator
-    0,                              // bank locator
-    MemoryTypeDdr4,                 // DDR4
-    {},                             // type detail
-    0,                              // ? MHz
-    0,                              // manufacturer
-    0,                              // serial
-    0,                              // asset tag
-    0,                              // part number
-    0,                              // rank
-  }, {
-    "DIMM1\0"
-  }
-};
-
-STATIC CONST ARM_TYPE17 mArmDefaultType17_2 = {
-  {
-    { // SMBIOS_STRUCTURE Hdr
-      EFI_SMBIOS_TYPE_MEMORY_DEVICE,
-      sizeof (SMBIOS_TABLE_TYPE17),
-      SMBIOS_HANDLE_PI_RESERVED,
-    },
-    SMBIOS_HANDLE_MEMORY,           // array to which this module belongs
-    0xFFFE,                         // no errors
-    72,                             // single DIMM with ECC
-    64,                             // data width of this device (64-bits)
-    0xFFFF,                         // size unknown
-    0x09,                           // DIMM
-    1,                              // part of a set
-    1,                              // device locator
-    0,                              // bank locator
-    MemoryTypeDdr4,                 // DDR4
-    {},                             // type detail
-    0,                              // ? MHz
-    0,                              // manufacturer
-    0,                              // serial
-    0,                              // asset tag
-    0,                              // part number
-    0,                              // rank
-  }, {
-    "DIMM2\0"
-  }
-};
-
-STATIC CONST ARM_TYPE17 mArmDefaultType17_3 = {
-  {
-    { // SMBIOS_STRUCTURE Hdr
-      EFI_SMBIOS_TYPE_MEMORY_DEVICE,
-      sizeof (SMBIOS_TABLE_TYPE17),
-      SMBIOS_HANDLE_PI_RESERVED,
-    },
-    SMBIOS_HANDLE_MEMORY,           // array to which this module belongs
-    0xFFFE,                         // no errors
-    72,                             // single DIMM with ECC
-    64,                             // data width of this device (64-bits)
-    0xFFFF,                         // size unknown
-    0x09,                           // DIMM
-    1,                              // part of a set
-    1,                              // device locator
-    0,                              // bank locator
-    MemoryTypeDdr4,                 // DDR4
-    {},                             // type detail
-    0,                              // ? MHz
-    0,                              // manufacturer
-    0,                              // serial
-    0,                              // asset tag
-    0,                              // part number
-    0,                              // rank
-  }, {
-    "DIMM3\0"
-  }
-};
-
-STATIC CONST ARM_TYPE17 mArmDefaultType17_4 = {
-  {
-    { // SMBIOS_STRUCTURE Hdr
-      EFI_SMBIOS_TYPE_MEMORY_DEVICE,
-      sizeof (SMBIOS_TABLE_TYPE17),
-      SMBIOS_HANDLE_PI_RESERVED,
-    },
-    SMBIOS_HANDLE_MEMORY,           // array to which this module belongs
-    0xFFFE,                         // no errors
-    72,                             // single DIMM with ECC
-    64,                             // data width of this device (64-bits)
-    0xFFFF,                         // size unknown
-    0x09,                           // DIMM
-    1,                              // part of a set
-    1,                              // device locator
-    0,                              // bank locator
-    MemoryTypeDdr4,                 // DDR4
-    {},                             // type detail
-    0,                              // ? MHz
-    0,                              // manufacturer
-    0,                              // serial
-    0,                              // asset tag
-    0,                              // part number
-    0,                              // rank
-  }, {
-    "DIMM4\0"
-  }
-};
-
 // Memory array mapped address, this structure
 // is overridden by InstallMemoryStructure
 STATIC CONST ARM_TYPE19 mArmDefaultType19 = {
@@ -559,13 +540,330 @@ STATIC SMBIOS_STRUCTURE * CONST FixedTables[] = {
   (SMBIOS_STRUCTURE *)&mArmDefaultType9_1.Base.Hdr,
   (SMBIOS_STRUCTURE *)&mArmDefaultType9_2.Base.Hdr,
   (SMBIOS_STRUCTURE *)&mArmDefaultType16.Base.Hdr,
-  (SMBIOS_STRUCTURE *)&mArmDefaultType17_1.Base.Hdr,
-  (SMBIOS_STRUCTURE *)&mArmDefaultType17_2.Base.Hdr,
-  (SMBIOS_STRUCTURE *)&mArmDefaultType17_3.Base.Hdr,
-  (SMBIOS_STRUCTURE *)&mArmDefaultType17_4.Base.Hdr,
   (SMBIOS_STRUCTURE *)&mArmDefaultType32.Base.Hdr,
 };
 
+STATIC
+UINT16
+GetPrimaryBusWidth (
+  IN UINT8           SpdPrimaryBusWidth
+  )
+{
+  UINT16                    PrimaryBusWidth;
+
+  switch (SpdPrimaryBusWidth) {
+  case SPD4_MEM_BUS_WIDTH_8BIT:
+    PrimaryBusWidth = 8;
+    break;
+  case SPD4_MEM_BUS_WIDTH_16BIT:
+    PrimaryBusWidth = 16;
+    break;
+  case SPD4_MEM_BUS_WIDTH_32BIT:
+    PrimaryBusWidth = 32;
+    break;
+  case SPD4_MEM_BUS_WIDTH_64BIT:
+    PrimaryBusWidth = 64;
+    break;
+  default:
+    PrimaryBusWidth = 0xFFFF;
+    ASSERT(FALSE);
+    break;
+  }
+
+  return PrimaryBusWidth;
+}
+
+STATIC
+UINT16
+GetSdramDeviceWidth (
+  IN UINT8            SpdSdramDeviceWidth
+  )
+{
+  UINT16                    SdramDeviceWidth;
+
+  switch (SpdSdramDeviceWidth) {
+  case SPD4_MEM_DEV_WIDTH_4BIT:
+    SdramDeviceWidth = 4;
+    break;
+  case SPD4_MEM_DEV_WIDTH_8BIT:
+    SdramDeviceWidth = 8;
+    break;
+  case SPD4_MEM_DEV_WIDTH_16BIT:
+    SdramDeviceWidth = 16;
+    break;
+  case SPD4_MEM_DEV_WIDTH_32BIT:
+    SdramDeviceWidth = 32;
+    break;
+  default:
+    SdramDeviceWidth = 0;
+    ASSERT(FALSE);
+    break;
+  }
+
+  return SdramDeviceWidth;
+}
+
+STATIC
+UINT16
+CalculateModuleDramCapacityMB (
+ IN SPD4_BASE_SECTION            *Spd4Base
+ )
+{
+  UINT32                    SdramCapacityMbit;
+  UINT16                    PrimaryBusWidth;
+  UINT8                     SdramDeviceWidth;
+  UINT8                     SdramDeviceWidthShiftNum;
+  UINT8                     RankCount;
+  UINT16                    DramSize;
+  UINT32                    Index;
+
+  SdramCapacityMbit = 0;
+
+  for (Index = 0; CapacityTable[Index].Capacity != SPD4_SDRAM_CAPACITY_INVALID; Index++) {
+    if (Spd4Base->SdramDensityAndBanks.Bits.Density == CapacityTable[Index].Capacity) {
+      SdramCapacityMbit = CapacityTable[Index].SizeMbit;
+      break;
+    }
+  }
+
+  PrimaryBusWidth = GetPrimaryBusWidth (Spd4Base->ModuleMemoryBusWidth.Bits.PrimaryBusWidth);
+  SdramDeviceWidth = GetSdramDeviceWidth (Spd4Base->ModuleOrganization.Bits.SdramDeviceWidth);
+  RankCount = Spd4Base->ModuleOrganization.Bits.RankCount + 1;
+
+  if ((SdramCapacityMbit == 0) || (PrimaryBusWidth == 0xFFFF) ||
+      (SdramDeviceWidth == 0) || RankCount == 0) {
+    DEBUG ((DEBUG_ERROR, "Calculate DRAM size failed. Cap:%d, BusWidth:%d, "
+                         "DevWidth:%d, Rank:%d\n", SdramCapacityMbit,
+                         PrimaryBusWidth, SdramDeviceWidth, RankCount));
+    return 0;
+  }
+
+  //
+  //Total[MB] = SDRAM Capacity[Mb] / 8 * Primary Bus Width /
+  //            SDRAM Width * Logical Ranks per DIMM
+  //
+  switch (SdramDeviceWidth) {
+  case 4:
+    SdramDeviceWidthShiftNum = 2;
+    break;
+  case 8:
+    SdramDeviceWidthShiftNum = 3;
+    break;
+  case 16:
+    SdramDeviceWidthShiftNum = 4;
+    break;
+  case 32:
+    SdramDeviceWidthShiftNum = 5;
+    break;
+  default:
+    SdramDeviceWidthShiftNum = 0;
+    ASSERT(FALSE);
+    break;
+  };
+  DramSize = (((SdramCapacityMbit >> 3) * PrimaryBusWidth) >> SdramDeviceWidthShiftNum) * RankCount;
+
+  return DramSize;
+}
+
+STATIC
+VOID
+GetManufacturerName (
+  IN UINT16           SpdManufacturerId,
+  OUT CHAR8           *ManufacturerStr
+  )
+{
+  UINT16                    ManufacturerId;
+  UINT32                    Index;
+  RETURN_STATUS             RetStatus;
+
+  ManufacturerId = SwapBytes16 (SpdManufacturerId);
+  ManufacturerId &= 0x7FFF; // ignore odd parity bit
+
+  for (Index = 0; Manufacturer[Index].ManufacturerId != 0xFFFF; Index++) {
+    if (ManufacturerId == Manufacturer[Index].ManufacturerId) {
+      RetStatus = AsciiStrCpyS (ManufacturerStr, TYPE17_MANUFACTURER_NAME_LEN,
+                                Manufacturer[Index].ManufacturerName);
+      ASSERT_RETURN_ERROR (RetStatus);
+      return;
+    }
+  }
+
+  RetStatus = AsciiStrCpyS (ManufacturerStr, TYPE17_MANUFACTURER_NAME_LEN,
+                            Manufacturer[Index].ManufacturerName);
+  ASSERT_RETURN_ERROR (RetStatus);
+}
+
+STATIC
+BOOLEAN
+IsValidSPD (
+  IN SPD4_BASE_SECTION            *Spd4Base
+  )
+{
+  //
+  // Developerbox only supports DDR4.
+  // If the device type is not DDR4 SDRAM, the SPD is invalid
+  //
+  if (Spd4Base->DramDeviceType.Bits.Type == SPD4_DDR4_SDRAM_TYPE) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+STATIC
+EFI_STATUS
+InstallMemoryDeviceStructure (
+  VOID
+  )
+{
+  EFI_SMBIOS_HANDLE         SmbiosHandle;
+  ARM_TYPE17                *Descriptor;
+  SPD_DDR4                  *Spd;
+  UINT8                     Slot;
+  CHAR8                     *StringPtr;
+
+  CHAR8                     DeviceLocatorStr[TYPE17_DEVICE_LOCATOR_LEN];
+  CHAR8                     BankLocatorStr[TYPE17_BANK_LOCATOR_LEN];
+  CHAR8                     ManufacturerStr[TYPE17_MANUFACTURER_NAME_LEN];
+  CHAR8                     SerialNumberStr[TYPE17_SERIAL_NUMBER_LEN];
+  CHAR8                     PartNumberStr[TYPE17_MODULE_PART_NUMBER_LEN];
+  CHAR8                     FirmwareVersionStr[TYPE17_FIRMWARE_VERSION_LEN];
+
+  Descriptor = AllocateZeroPool(sizeof (ARM_TYPE17));
+  if (Descriptor == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Spd = (SPD_DDR4 *) FixedPcdGet32 (PcdStoredSpdDDR4Address);
+
+  for (Slot = 0; Slot < 4; Slot++, Spd++) {
+    SetMem (Descriptor, sizeof (ARM_TYPE17), 0);
+    // fill fixed parameters
+    Descriptor->Base.Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_DEVICE;
+    Descriptor->Base.Hdr.Length = sizeof (SMBIOS_TABLE_TYPE17);
+    Descriptor->Base.Hdr.Handle = SMBIOS_HANDLE_PI_RESERVED;
+    Descriptor->Base.MemoryArrayHandle = SMBIOS_HANDLE_MEMORY;
+    Descriptor->Base.MemoryErrorInformationHandle = 0xFFFE;
+    Descriptor->Base.ExtendedSize = 0;
+    Descriptor->Base.ExtendedSpeed = 0;
+    Descriptor->Base.ExtendedConfiguredMemorySpeed = 0;
+    Descriptor->Base.MemoryOperatingModeCapability.Bits.VolatileMemory = 1;
+    Descriptor->Base.DeviceSet = 1;
+    Descriptor->Base.MemoryType = MemoryTypeDdr4;
+    Descriptor->Base.DeviceLocator = 1;
+    Descriptor->Base.BankLocator = 2;
+
+    AsciiSPrint (DeviceLocatorStr, sizeof(DeviceLocatorStr), "DIMM %d\0", (Slot + 1));
+    AsciiSPrint (BankLocatorStr, sizeof(BankLocatorStr), "CHANNEL %d SLOT %d\0", (Slot / 2), (Slot % 2));
+
+    StringPtr = Descriptor->Strings;
+    AsciiStrnCpyS (StringPtr, TYPE17_DEVICE_LOCATOR_LEN, DeviceLocatorStr,
+                   TYPE17_DEVICE_LOCATOR_LEN - 1);
+    StringPtr += AsciiStrSize (StringPtr);
+    AsciiStrnCpyS (StringPtr, TYPE17_BANK_LOCATOR_LEN, BankLocatorStr,
+                   TYPE17_BANK_LOCATOR_LEN - 1);
+    StringPtr += AsciiStrSize (StringPtr);
+
+    if (IsValidSPD ((SPD4_BASE_SECTION *)Spd)) {
+      Descriptor->Base.Manufacturer = 3;
+      Descriptor->Base.SerialNumber = 4;
+      Descriptor->Base.AssetTag = 5;
+      Descriptor->Base.PartNumber = 6;
+      Descriptor->Base.FirmwareVersion = 7;
+
+      Descriptor->Base.TotalWidth = Descriptor->Base.DataWidth =
+        GetPrimaryBusWidth (Spd->Base.ModuleMemoryBusWidth.Bits.PrimaryBusWidth);
+      if (Spd->Base.ModuleMemoryBusWidth.Bits.BusWidthExtension) {
+        if (Descriptor->Base.TotalWidth != 0xFFFF) {
+          Descriptor->Base.TotalWidth += 8;
+        }
+      }
+
+      Descriptor->Base.Size = CalculateModuleDramCapacityMB ((SPD4_BASE_SECTION *)Spd);
+
+      switch (Spd->Base.ModuleType.Bits.ModuleType) {
+      case SPD4_MEM_MODULE_TYPE_RDIMM:
+        Descriptor->Base.FormFactor = 0x09;
+        Descriptor->Base.TypeDetail.Registered = 1;
+        Descriptor->Base.TypeDetail.Unbuffered = 0;
+        break;
+      case SPD4_MEM_MODULE_TYPE_UDIMM:
+        Descriptor->Base.FormFactor = 0x09;
+        Descriptor->Base.TypeDetail.Registered = 0;
+        Descriptor->Base.TypeDetail.Unbuffered = 1;
+        break;
+      case SPD4_MEM_MODULE_TYPE_SODIMM:
+        Descriptor->Base.FormFactor = 0x0D;
+        Descriptor->Base.TypeDetail.Registered = 0;
+        Descriptor->Base.TypeDetail.Unbuffered = 1;
+        break;
+      default:
+        Descriptor->Base.FormFactor = 0x01;
+        Descriptor->Base.TypeDetail.Registered = 0;
+        Descriptor->Base.TypeDetail.Unbuffered = 0;
+        break;
+      }
+
+      Descriptor->Base.Attributes = Spd->Base.ModuleOrganization.Bits.RankCount + 1;
+      Descriptor->Base.Speed = 2133;
+      Descriptor->Base.ConfiguredMemoryClockSpeed = 2133;
+      Descriptor->Base.MinimumVoltage = 1200;
+      Descriptor->Base.MaximumVoltage = 1200;
+      Descriptor->Base.ConfiguredVoltage = 1200;
+      Descriptor->Base.MemoryTechnology = MemoryTechnologyDram;
+      Descriptor->Base.ModuleManufacturerID = Spd->ManufactureInfo.ModuleId.IdCode.Data;
+
+      GetManufacturerName (Spd->ManufactureInfo.ModuleId.IdCode.Data, ManufacturerStr);
+      AsciiSPrint (SerialNumberStr, TYPE17_SERIAL_NUMBER_LEN, "0x%08X\0",
+                   SwapBytes32(Spd->ManufactureInfo.ModuleId.SerialNumber.Data));
+      //
+      // Module part number is not null terminated string in SPD DDR4,
+      // unused digits are coded as ASCII blanks(0x20).
+      //
+      ZeroMem(PartNumberStr, TYPE17_MODULE_PART_NUMBER_LEN);
+      CopyMem (PartNumberStr,
+               (CHAR8 *)Spd->ManufactureInfo.ModulePartNumber.ModulePartNumber,
+               TYPE17_MODULE_PART_NUMBER_LEN - 1);
+
+      AsciiSPrint (FirmwareVersionStr, sizeof(FirmwareVersionStr), "%d\0", FixedPcdGet32 (PcdFirmwareRevision));
+
+      AsciiStrnCpyS (StringPtr, TYPE17_MANUFACTURER_NAME_LEN, ManufacturerStr,
+                     TYPE17_MANUFACTURER_NAME_LEN - 1);
+      StringPtr += AsciiStrSize (StringPtr);
+      AsciiStrnCpyS (StringPtr, TYPE17_SERIAL_NUMBER_LEN, SerialNumberStr,
+                     TYPE17_SERIAL_NUMBER_LEN - 1);
+      StringPtr += AsciiStrSize (StringPtr);
+      AsciiStrnCpyS (StringPtr, TYPE17_ASSETTAG_LEN, "-\0",
+                     TYPE17_ASSETTAG_LEN - 1);
+      StringPtr += AsciiStrSize (StringPtr);
+      AsciiStrnCpyS (StringPtr, TYPE17_MODULE_PART_NUMBER_LEN, PartNumberStr,
+                     TYPE17_MODULE_PART_NUMBER_LEN - 1);
+      StringPtr += AsciiStrSize (StringPtr);
+      AsciiStrnCpyS (StringPtr, TYPE17_FIRMWARE_VERSION_LEN, FirmwareVersionStr,
+                     TYPE17_FIRMWARE_VERSION_LEN - 1);
+    } else {
+      Descriptor->Base.TotalWidth = 0xFFFF;
+      Descriptor->Base.DataWidth = 0xFFFF;
+      Descriptor->Base.Size = 0;
+      Descriptor->Base.FormFactor = 0x09;
+      Descriptor->Base.DeviceSet = 1;
+      Descriptor->Base.Attributes = 0;
+      Descriptor->Base.Speed = 0;
+      Descriptor->Base.ConfiguredMemoryClockSpeed = 0;
+      Descriptor->Base.MinimumVoltage = 0;
+      Descriptor->Base.MaximumVoltage = 0;
+      Descriptor->Base.ConfiguredVoltage = 0;
+    }
+
+    SmbiosHandle = Descriptor->Base.Hdr.Handle;
+    mSmbios->Add (mSmbios, NULL, &SmbiosHandle, &Descriptor->Base.Hdr);
+  }
+
+  FreePool (Descriptor);
+
+  return EFI_SUCCESS;
+}
+
 STATIC
 EFI_STATUS
 InstallMemoryStructure (
@@ -587,6 +885,7 @@ InstallMemoryStructure (
   return mSmbios->Add (mSmbios, NULL, &SmbiosHandle, &Descriptor->Base.Hdr);
 }
 
+
 STATIC
 VOID
 InstallAllStructures (
@@ -608,6 +907,16 @@ InstallAllStructures (
     }
   }
 
+  //
+  // SPD_DDR4 data is stored in Non Secure SRAM by SCP-firmware.
+  // Install Type17 record by analyzing SPD_DDR4 information.
+  //
+  Status = InstallMemoryDeviceStructure();
+  if (EFI_ERROR(Status)) {
+      DEBUG ((DEBUG_WARN, "%a: failed to add SMBIOS type 17 table - %r\n",
+        __FUNCTION__, Status));
+  }
+
   for (Hob.Raw = GetHobList ();
        !END_OF_HOB_LIST (Hob);
        Hob.Raw = GET_NEXT_HOB (Hob)) {

+ 2 - 0
Platform/Socionext/DeveloperBox/SmbiosPlatformDxe/SmbiosPlatformDxe.inf

@@ -21,6 +21,7 @@
   ArmPkg/ArmPkg.dec
   MdeModulePkg/MdeModulePkg.dec
   MdePkg/MdePkg.dec
+  Silicon/Socionext/SynQuacer/SynQuacer.dec
 
 [LibraryClasses]
   BaseMemoryLib
@@ -34,6 +35,7 @@
 [FixedPcd]
   gArmTokenSpaceGuid.PcdFdSize
   gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareRevision
+  gSynQuacerTokenSpaceGuid.PcdStoredSpdDDR4Address
 
 [Protocols]
   gEfiSmbiosProtocolGuid                      # PROTOCOL ALWAYS_CONSUMED

+ 3 - 0
Silicon/Socionext/SynQuacer/SynQuacer.dec

@@ -43,6 +43,9 @@
   # for capsule update
   gSynQuacerTokenSpaceGuid.PcdLowestSupportedFirmwareVersion|1|UINT32|0x00000009
 
+  # for SMBIOS Type17
+  gSynQuacerTokenSpaceGuid.PcdStoredSpdDDR4Address|0|UINT32|0x0000000A
+
 [PcdsPatchableInModule, PcdsDynamic]
   # Enable both RC #0 and RC #1 by default
   gSynQuacerTokenSpaceGuid.PcdPcieEnableMask|0x3|UINT8|0x00000007