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