Home | History | Annotate | Download | only in SmBiosMiscDxe
      1 /*++
      2 
      3 Copyright (c) 2006  - 2014, Intel Corporation. All rights reserved.<BR>
      4 
      5   This program and the accompanying materials are licensed and made available under
      7   the terms and conditions of the BSD License that accompanies this distribution.
      9   The full text of the license may be found at
     11   http://opensource.org/licenses/bsd-license.php.
     13 
     15   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     17   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     19 
     21 
     23 
     24 Module Name:
     25 
     26   MiscMemoryDeviceFunction.c
     27 
     28 Abstract:
     29 
     30    Memory Device
     31    Misc. subclass type 17.
     32    SMBIOS type 17.
     33 
     34 --*/
     35 
     36 
     37 #include "CommonHeader.h"
     38 #include "MiscSubclassDriver.h"
     39 #include <Protocol/DataHub.h>
     40 #include <Guid/DataHubRecords.h>
     41 #include <Protocol/MemInfo.h>
     42 
     43 
     44 #define FREQ_800           0x00
     45 #define FREQ_1066          0x01
     46 #define FREQ_1333          0x02
     47 #define FREQ_1600          0x03
     48 
     49 #define MAX_SOCKETS  2
     50 #define EfiMemoryTypeDdr3  0x18
     51 
     52 enum {
     53     DDRType_DDR3 = 0,
     54     DDRType_DDR3L = 1,
     55     DDRType_DDR3U = 2,
     56     DDRType_DDR3All = 3,
     57     DDRType_LPDDR2 = 4,
     58     DDRType_LPDDR3 = 5,
     59     DDRType_DDR4 = 6
     60 };
     61 
     62 
     63 typedef struct {
     64   EFI_PHYSICAL_ADDRESS        MemoryArrayStartAddress;
     65   EFI_PHYSICAL_ADDRESS        MemoryArrayEndAddress;
     66   EFI_INTER_LINK_DATA         PhysicalMemoryArrayLink;
     67   UINT16                      MemoryArrayPartitionWidth;
     68 } EFI_MEMORY_ARRAY_START_ADDRESS;
     69 
     70 /**
     71   This function makes boot time changes to the contents of the
     72   MiscBiosVendor (Type 0).
     73 
     74   @param  RecordData                 Pointer to copy of RecordData from the Data Table.
     75 
     76   @retval EFI_SUCCESS                All parameters were valid.
     77   @retval EFI_UNSUPPORTED            Unexpected RecordType value.
     78   @retval EFI_INVALID_PARAMETER      Invalid parameter was found.
     79 
     80 **/
     81 VOID
     82 GetType16Hndl (
     83   IN  EFI_SMBIOS_PROTOCOL      *Smbios,
     84   OUT  EFI_SMBIOS_HANDLE       *Handle
     85   )
     86 {
     87   EFI_STATUS                 Status;
     88   EFI_SMBIOS_TYPE            RecordType;
     89   EFI_SMBIOS_TABLE_HEADER    *Buffer;
     90 
     91   *Handle = 0;
     92    RecordType = EFI_SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY;
     93 
     94     Status = Smbios->GetNext (
     95                        Smbios,
     96                        Handle,
     97                        &RecordType,
     98                        &Buffer,
     99                        NULL
    100                        );
    101     if (!EFI_ERROR(Status)) {
    102         return;
    103       }
    104   *Handle = 0xFFFF;
    105 }
    106 
    107 MISC_SMBIOS_TABLE_FUNCTION( MiscMemoryDevice )
    108 {
    109     CHAR8                           *OptionalStrStart;
    110     UINTN                           MemDeviceStrLen;
    111     UINTN                           MemBankLocatorStrLen;
    112     UINTN                           MemManufacturerStrLen;
    113     UINTN                           MemSerialNumberStrLen;
    114     UINTN                           MemAssetTagStrLen;
    115     UINTN                           MemPartNumberStrLen;
    116     CHAR16                          *MemDevice;
    117     CHAR16                          *MemBankLocator;
    118     CHAR16                          *MemManufacturer;
    119     CHAR16                          *MemSerialNumber;
    120     CHAR16                          *MemAssetTag;
    121     CHAR16                          *MemPartNumber;
    122     EFI_STATUS                      Status;
    123     STRING_REF                      TokenToGet;
    124     SMBIOS_TABLE_TYPE17             *SmbiosRecord;
    125     EFI_SMBIOS_HANDLE               SmbiosHandle;
    126     EFI_MEMORY_ARRAY_LINK_DATA      *ForType17InputData;
    127     UINT16                          DdrFreq=0;
    128     UINT16                          Type16Handle=0;
    129     MEM_INFO_PROTOCOL               *MemInfoHob;
    130     UINT8                           MemoryType;
    131 
    132     UINT8                           Dimm;
    133     UINT8                           NumSlots;
    134     STRING_REF                      DevLocator[] = {
    135       STRING_TOKEN(STR_MISC_MEM_DEV_LOCATOR0), STRING_TOKEN(STR_MISC_MEM_DEV_LOCATOR1)
    136     };
    137     STRING_REF                      BankLocator[] = {
    138       STRING_TOKEN(STR_MISC_MEM_BANK_LOCATOR0), STRING_TOKEN(STR_MISC_MEM_BANK_LOCATOR1)
    139     };
    140 
    141     //
    142     // First check for invalid parameters.
    143     //
    144     if (RecordData == NULL) {
    145         return EFI_INVALID_PARAMETER;
    146     }
    147     ForType17InputData        = (EFI_MEMORY_ARRAY_LINK_DATA *)RecordData;
    148 
    149     //
    150     // Get Memory size parameters for each rank from the chipset registers
    151     //
    152     Status = gBS->LocateProtocol (
    153                     &gMemInfoProtocolGuid,
    154                     NULL,
    155                     (void **)&MemInfoHob
    156                     );
    157     ASSERT_EFI_ERROR (Status);
    158 
    159     NumSlots = (UINT8)(MAX_SOCKETS);
    160 
    161     //
    162     // Memory Freq
    163     //
    164     switch (MemInfoHob->MemInfoData.ddrFreq){
    165         case FREQ_800:
    166           DdrFreq = 800;
    167           break;
    168         case FREQ_1066:
    169           DdrFreq = 1066;
    170           break;
    171         case FREQ_1333:
    172           DdrFreq = 1333;
    173           break;
    174         case FREQ_1600:
    175           DdrFreq = 1600;
    176           break;
    177         default:
    178           DdrFreq = 0;
    179           break;
    180     }
    181 
    182     //
    183     // Memory Type
    184     //
    185     switch  (MemInfoHob->MemInfoData.ddrType) {
    186         case DDRType_LPDDR2:
    187           MemoryType  = EfiMemoryTypeDdr2;
    188           break;
    189         case DDRType_DDR3:
    190         case DDRType_DDR3L:
    191         case DDRType_DDR3U:
    192         case DDRType_LPDDR3:
    193           MemoryType = EfiMemoryTypeDdr3;
    194           break;
    195         default:
    196           MemoryType = EfiMemoryTypeUnknown;
    197           break;
    198     }
    199 
    200     for (Dimm = 0; Dimm < NumSlots; Dimm++) {
    201     //
    202     // Memory Device Locator
    203     //
    204     TokenToGet = DevLocator[Dimm];
    205     MemDevice = SmbiosMiscGetString (TokenToGet);
    206     MemDeviceStrLen = StrLen(MemDevice);
    207     if (MemDeviceStrLen > SMBIOS_STRING_MAX_LENGTH) {
    208       return EFI_UNSUPPORTED;
    209     }
    210 
    211     TokenToGet = DevLocator[Dimm];
    212     MemDevice = SmbiosMiscGetString (TokenToGet);
    213     MemDeviceStrLen = StrLen(MemDevice);
    214     if (MemDeviceStrLen > SMBIOS_STRING_MAX_LENGTH) {
    215       return EFI_UNSUPPORTED;
    216     }
    217 
    218     //
    219     // Memory Bank Locator
    220     //
    221     TokenToGet = BankLocator[Dimm];
    222     MemBankLocator = SmbiosMiscGetString (TokenToGet);
    223     MemBankLocatorStrLen = StrLen(MemBankLocator);
    224     if (MemBankLocatorStrLen > SMBIOS_STRING_MAX_LENGTH) {
    225       return EFI_UNSUPPORTED;
    226     }
    227 
    228     //
    229     // Memory Manufacturer
    230     //
    231     TokenToGet = STRING_TOKEN (STR_MISC_MEM_MANUFACTURER);
    232     MemManufacturer = SmbiosMiscGetString (TokenToGet);
    233     MemManufacturerStrLen = StrLen(MemManufacturer);
    234     if (MemManufacturerStrLen > SMBIOS_STRING_MAX_LENGTH) {
    235       return EFI_UNSUPPORTED;
    236     }
    237 
    238     //
    239     // Memory Serial Number
    240     //
    241     TokenToGet = STRING_TOKEN (STR_MISC_MEM_SERIAL_NO);
    242     MemSerialNumber = SmbiosMiscGetString (TokenToGet);
    243     MemSerialNumberStrLen = StrLen(MemSerialNumber);
    244     if (MemSerialNumberStrLen > SMBIOS_STRING_MAX_LENGTH) {
    245       return EFI_UNSUPPORTED;
    246     }
    247 
    248     //
    249     // Memory Asset Tag Number
    250     //
    251     TokenToGet = STRING_TOKEN (STR_MISC_MEM_ASSET_TAG);
    252     MemAssetTag = SmbiosMiscGetString (TokenToGet);
    253     MemAssetTagStrLen = StrLen(MemAssetTag);
    254     if (MemAssetTagStrLen > SMBIOS_STRING_MAX_LENGTH) {
    255       return EFI_UNSUPPORTED;
    256     }
    257 
    258     //
    259     // Memory Part Number
    260     //
    261     TokenToGet = STRING_TOKEN (STR_MISC_MEM_PART_NUMBER);
    262     MemPartNumber = SmbiosMiscGetString (TokenToGet);
    263     MemPartNumberStrLen = StrLen(MemPartNumber);
    264     if (MemPartNumberStrLen > SMBIOS_STRING_MAX_LENGTH) {
    265       return EFI_UNSUPPORTED;
    266     }
    267 
    268     //
    269     // Two zeros following the last string.
    270     //
    271     SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE17) + MemDeviceStrLen + 1 + MemBankLocatorStrLen + 1 + MemManufacturerStrLen + 1 + MemSerialNumberStrLen + 1 + MemAssetTagStrLen+1 + MemPartNumberStrLen + 1 + 1);
    272     ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE17) +  MemDeviceStrLen + 1 + MemBankLocatorStrLen + 1 + MemManufacturerStrLen + 1 + MemSerialNumberStrLen + 1 + MemAssetTagStrLen+1 + MemPartNumberStrLen + 1 + 1);
    273 
    274     SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_DEVICE;
    275     SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE17);
    276 
    277     //
    278     // Make handle chosen by smbios protocol.add automatically.
    279     //
    280     SmbiosRecord->Hdr.Handle = 0;
    281 
    282     //
    283     // Memory Array Handle will be the 3rd optional string following the formatted structure.
    284     //
    285     GetType16Hndl( Smbios, &Type16Handle);
    286     SmbiosRecord->MemoryArrayHandle = Type16Handle;
    287 
    288     //
    289     // Memory Size
    290     //
    291     if ((MemInfoHob->MemInfoData.dimmSize[Dimm])!=0){
    292     SmbiosRecord->TotalWidth = 32;
    293     SmbiosRecord->DataWidth = 32;
    294     SmbiosRecord->Size = MemInfoHob->MemInfoData.dimmSize[Dimm];
    295     SmbiosRecord->Speed = DdrFreq;
    296     SmbiosRecord->ConfiguredMemoryClockSpeed = DdrFreq;
    297     SmbiosRecord->FormFactor = EfiMemoryFormFactorDimm;
    298     }
    299 
    300     SmbiosRecord->DeviceSet =(UINT8) ForType17InputData->MemoryDeviceSet;
    301     SmbiosRecord->DeviceLocator= 1;
    302     SmbiosRecord->BankLocator = 2;
    303 
    304 
    305     SmbiosRecord->Manufacturer = 3;
    306     SmbiosRecord->SerialNumber= 4;
    307     SmbiosRecord->AssetTag= 5;
    308     SmbiosRecord->PartNumber= 6;
    309     SmbiosRecord->Attributes = (UINT8) ForType17InputData->MemoryState;
    310     SmbiosRecord->MemoryType = MemoryType;
    311 
    312     OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
    313     UnicodeStrToAsciiStr(MemDevice, OptionalStrStart);
    314     UnicodeStrToAsciiStr(MemBankLocator, OptionalStrStart + MemDeviceStrLen + 1);
    315     UnicodeStrToAsciiStr(MemManufacturer, OptionalStrStart + MemDeviceStrLen + 1 + MemBankLocatorStrLen + 1);
    316     UnicodeStrToAsciiStr(MemSerialNumber, OptionalStrStart + MemDeviceStrLen + 1 + MemBankLocatorStrLen + 1 + MemManufacturerStrLen + 1);
    317     UnicodeStrToAsciiStr(MemAssetTag, OptionalStrStart + MemDeviceStrLen + 1 + MemBankLocatorStrLen + 1 + MemManufacturerStrLen + 1 + MemSerialNumberStrLen + 1);
    318     UnicodeStrToAsciiStr(MemPartNumber, OptionalStrStart + MemDeviceStrLen + 1 + MemBankLocatorStrLen + 1 + MemManufacturerStrLen + 1 + MemSerialNumberStrLen + 1+ MemAssetTagStrLen+1 );
    319 
    320     //
    321     // Now we have got the full smbios record, call smbios protocol to add this record.
    322     //
    323     SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
    324     Status = Smbios-> Add(
    325                         Smbios,
    326                         NULL,
    327                         &SmbiosHandle,
    328                         (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord
    329                         );
    330     FreePool(SmbiosRecord);
    331     }
    332     return Status;
    333 }
    334