1 /** @file 2 * 3 * Copyright (c) 2015, Hisilicon Limited. All rights reserved. 4 * Copyright (c) 2015, Linaro Limited. All rights reserved. 5 * 6 * This program and the accompanying materials 7 * are licensed and made available under the terms and conditions of the BSD License 8 * which accompanies this distribution. The full text of the license may be found at 9 * http://opensource.org/licenses/bsd-license.php 10 * 11 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 * 14 **/ 15 16 17 #include "MemorySubClass.h" 18 19 EFI_SMBIOS_PROTOCOL *mSmbios = NULL; 20 EFI_HII_HANDLE mHiiHandle; 21 22 UINT8 mMaxSkt; 23 UINT8 mMaxCh; 24 25 VOID 26 SmbiosGetManufacturer ( 27 IN UINT8 MfgIdLSB, 28 IN UINT8 MfgIdMSB, 29 OUT CHAR16 *Manufacturer 30 ) 31 { 32 UINT32 Index = 0; 33 34 (VOID)StrCpyS(Manufacturer, SMBIOS_STRING_MAX_LENGTH - 1, L"Unknown"); 35 while (JEP106[Index].MfgIdLSB != 0xFF && JEP106[Index].MfgIdMSB != 0xFF ) 36 { 37 if (JEP106[Index].MfgIdLSB == MfgIdLSB && JEP106[Index].MfgIdMSB == MfgIdMSB) 38 { 39 (VOID)StrCpyS (Manufacturer, SMBIOS_STRING_MAX_LENGTH - 1, JEP106[Index].Name); 40 break; 41 } 42 Index++; 43 } 44 } 45 46 VOID 47 SmbiosGetPartNumber ( 48 IN pGBL_DATA pGblData, 49 IN UINT8 Skt, 50 IN UINT8 Ch, 51 IN UINT8 Dimm, 52 OUT CHAR16 *PartNumber 53 ) 54 { 55 CHAR16 StringBuffer2[SMBIOS_STRING_MAX_LENGTH]; 56 UINT32 Index2; 57 58 (VOID)StrCpyS(PartNumber, SMBIOS_STRING_MAX_LENGTH - 1, L""); 59 if (pGblData->Channel[Skt][Ch].Dimm[Dimm].DramType == SPD_TYPE_DDR3) 60 { 61 for (Index2 = 0; Index2 < SPD_MODULE_PART; Index2++) 62 { 63 UnicodeSPrint (StringBuffer2, SMBIOS_STRING_MAX_LENGTH - 1, L"%c", pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdModPart[Index2]); 64 (VOID)StrCatS(PartNumber, SMBIOS_STRING_MAX_LENGTH - 1, StringBuffer2); 65 } 66 } 67 else 68 { 69 for (Index2 = 0; Index2 < SPD_MODULE_PART_DDR4; Index2++) 70 { 71 UnicodeSPrint (StringBuffer2, SMBIOS_STRING_MAX_LENGTH - 1, L"%c", pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdModPartDDR4[Index2]); 72 (VOID)StrCatS(PartNumber, SMBIOS_STRING_MAX_LENGTH - 1, StringBuffer2); 73 } 74 } 75 76 return; 77 } 78 79 VOID 80 SmbiosGetSerialNumber ( 81 IN pGBL_DATA pGblData, 82 IN UINT8 Skt, 83 IN UINT8 Ch, 84 IN UINT8 Dimm, 85 OUT CHAR16 *SerialNumber 86 ) 87 { 88 UINT32 Temp; 89 90 Temp = SwapBytes32 (pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdSerialNum); 91 92 UnicodeSPrint(SerialNumber, SMBIOS_STRING_MAX_LENGTH, L"0x%08x", Temp); 93 94 return; 95 } 96 97 BOOLEAN 98 IsDimmPresent ( 99 IN pGBL_DATA pGblData, 100 IN UINT8 Skt, 101 IN UINT8 Ch, 102 IN UINT8 Dimm 103 ) 104 { 105 if (pGblData->Channel[Skt][Ch].Status == FALSE || 106 pGblData->Channel[Skt][Ch].Dimm[Dimm].Status == FALSE) 107 { 108 return FALSE; 109 } 110 else 111 { 112 return TRUE; 113 } 114 } 115 116 UINT8 117 SmbiosGetMemoryType ( 118 IN pGBL_DATA pGblData, 119 IN UINT8 Skt, 120 IN UINT8 Ch, 121 IN UINT8 Dimm 122 ) 123 { 124 UINT8 MemoryType; 125 126 if(!IsDimmPresent(pGblData, Skt, Ch, Dimm)) 127 { 128 return MemoryTypeUnknown; 129 } 130 131 if (pGblData->Channel[Skt][Ch].Dimm[Dimm].DramType == SPD_TYPE_DDR3) 132 { 133 MemoryType = MemoryTypeDdr3; 134 } 135 else if (pGblData->Channel[Skt][Ch].Dimm[Dimm].DramType == SPD_TYPE_DDR4) 136 { 137 MemoryType = MemoryTypeDdr4; 138 } 139 else 140 { 141 MemoryType = MemoryTypeUnknown; 142 } 143 144 return MemoryType; 145 } 146 147 VOID 148 SmbiosGetTypeDetail ( 149 IN pGBL_DATA pGblData, 150 IN UINT8 Skt, 151 IN UINT8 Ch, 152 IN UINT8 Dimm, 153 IN OUT MEMORY_DEVICE_TYPE_DETAIL *TypeDetail 154 ) 155 { 156 if (NULL == TypeDetail) 157 { 158 return; 159 } 160 161 if(!IsDimmPresent(pGblData, Skt, Ch, Dimm)) 162 { 163 TypeDetail->Unknown = 1; 164 return; 165 } 166 167 switch (pGblData->Channel[Skt][Ch].Dimm[Dimm].ModuleType) 168 { 169 case SPD_UDIMM: 170 TypeDetail->Unbuffered = 1; 171 break; 172 173 case SPD_LRDIMM: 174 TypeDetail->LrDimm = 1; 175 break; 176 177 case SPD_RDIMM: 178 TypeDetail->Registered = 1; 179 break; 180 181 default: 182 TypeDetail->Unknown = 1; 183 break; 184 } 185 } 186 187 VOID 188 SmbiosGetDimmVoltageInfo ( 189 IN pGBL_DATA pGblData, 190 IN UINT8 Skt, 191 IN UINT8 Ch, 192 IN UINT8 Dimm, 193 IN OUT SMBIOS_TABLE_TYPE17 *Type17Record 194 195 ) 196 { 197 if(!IsDimmPresent(pGblData, Skt, Ch, Dimm)) 198 { 199 return; 200 } 201 202 if (pGblData->Channel[Skt][Ch].Dimm[Dimm].DramType == SPD_TYPE_DDR3) 203 { 204 Type17Record->MinimumVoltage = 1250; 205 Type17Record->MaximumVoltage = 1500; 206 207 switch (pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdVdd) 208 { 209 case SPD_VDD_150: 210 Type17Record->ConfiguredVoltage = 1500; 211 break; 212 213 case SPD_VDD_135: 214 Type17Record->ConfiguredVoltage = 1350; 215 break; 216 217 case SPD_VDD_125: 218 Type17Record->ConfiguredVoltage = 1250; 219 break; 220 221 default: 222 break; 223 } 224 } 225 else if (pGblData->Channel[Skt][Ch].Dimm[Dimm].DramType == SPD_TYPE_DDR4) 226 { 227 Type17Record->MinimumVoltage = 1200; 228 Type17Record->MaximumVoltage = 2000; 229 switch (pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdVdd) 230 { 231 case SPD_VDD_120: 232 Type17Record->ConfiguredVoltage = 1200; 233 break; 234 235 default: 236 break; 237 } 238 } 239 } 240 241 VOID 242 SmbiosGetMemoryDevicesNumber ( 243 IN OUT UINT16 *NumberOfDevices 244 ) 245 { 246 UINT8 Skt, Ch, Dimm; 247 248 for(Skt = 0; Skt < mMaxSkt; Skt++) 249 { 250 for(Ch = 0; Ch < mMaxCh; Ch++) 251 { 252 for(Dimm = 0; Dimm < OemGetDimmSlot(Skt, Ch); Dimm++) 253 { 254 (*NumberOfDevices)++; 255 } 256 } 257 } 258 } 259 260 UINT8 261 SmbiosGetPartitionWidth ( 262 ) 263 { 264 265 UINT8 Skt, Ch, Dimm; 266 UINT8 PartitionWidth = 0; 267 268 for(Skt = 0; Skt < mMaxSkt; Skt++) 269 { 270 for(Ch = 0; Ch < mMaxCh; Ch++) 271 { 272 for(Dimm = 0; Dimm < OemGetDimmSlot(Skt, Ch); Dimm++) 273 { 274 PartitionWidth++; 275 } 276 } 277 } 278 279 return PartitionWidth; 280 } 281 282 EFI_STATUS 283 SmbiosAddType16Table ( 284 IN pGBL_DATA pGblData, 285 OUT EFI_SMBIOS_HANDLE *MemArraySmbiosHandle 286 ) 287 { 288 EFI_STATUS Status; 289 UINT64 MemoryCapacity; 290 SMBIOS_TABLE_TYPE16 *Type16Record; 291 292 UINT16 NumberOfMemoryDevices = 0; 293 294 SmbiosGetMemoryDevicesNumber (&NumberOfMemoryDevices); 295 296 MemoryCapacity = (UINT64) LShiftU64 (NumberOfMemoryDevices * MAX_DIMM_SIZE, 20); // GB to KB. 297 298 // 299 // Type 16 SMBIOS Record 300 // 301 Type16Record = AllocateZeroPool(sizeof(SMBIOS_TABLE_TYPE16) + 1 + 1); 302 if (NULL == Type16Record) 303 { 304 return EFI_OUT_OF_RESOURCES; 305 } 306 307 Type16Record->Hdr.Type = EFI_SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY; 308 Type16Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE16); 309 Type16Record->Hdr.Handle = 0x0; 310 Type16Record->Location = MemoryArrayLocationSystemBoard; 311 Type16Record->Use = MemoryArrayUseSystemMemory; 312 Type16Record->MemoryErrorInformationHandle = 0xFFFE; 313 Type16Record->NumberOfMemoryDevices = NumberOfMemoryDevices; 314 315 if(pGblData->EccEn) 316 { 317 Type16Record->MemoryErrorCorrection = MemoryErrorCorrectionSingleBitEcc; 318 } 319 else 320 { 321 Type16Record->MemoryErrorCorrection = MemoryErrorCorrectionNone; 322 } 323 324 if (MemoryCapacity >= 0x80000000) 325 { 326 Type16Record->MaximumCapacity = 0x80000000; // in KB; 327 Type16Record->ExtendedMaximumCapacity = MemoryCapacity << 10; // Extended Max capacity should be stored in bytes. 328 } 329 else 330 { 331 Type16Record->MaximumCapacity = (UINT32)MemoryCapacity; // Max capacity should be stored in kilo bytes. 332 Type16Record->ExtendedMaximumCapacity = 0; 333 } 334 335 *MemArraySmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; 336 Status = mSmbios->Add (mSmbios, NULL, MemArraySmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *)Type16Record); 337 if(EFI_ERROR(Status)) 338 { 339 DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type16 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status)); 340 } 341 342 FreePool(Type16Record); 343 return Status; 344 } 345 346 EFI_STATUS 347 SmbiosAddType19Table ( 348 IN pGBL_DATA pGblData, 349 IN EFI_SMBIOS_HANDLE MemArraySmbiosHandle 350 ) 351 { 352 EFI_STATUS Status; 353 UINT32 MemInfoTotalMem; 354 UINT64 TotalMemorySize; 355 EFI_SMBIOS_HANDLE MemArrayMappedAddrSmbiosHandle; 356 SMBIOS_TABLE_TYPE19 *Type19Record; 357 358 MemInfoTotalMem = pGblData->MemSize; // In MB 359 360 if (MemInfoTotalMem == 0) 361 { 362 return EFI_NOT_FOUND; 363 } 364 365 TotalMemorySize = (UINT64) LShiftU64 (MemInfoTotalMem, 10); // MB to KB. 366 367 // 368 // Type 19 SMBIOS Record 369 // 370 Type19Record = AllocateZeroPool(sizeof(SMBIOS_TABLE_TYPE19) + 1 + 1); 371 if (NULL == Type19Record) 372 { 373 return EFI_OUT_OF_RESOURCES; 374 } 375 376 Type19Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS; 377 Type19Record->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE19); 378 Type19Record->Hdr.Handle = 0x0; 379 Type19Record->StartingAddress = 0x0; 380 Type19Record->EndingAddress = (UINT32) (TotalMemorySize - 1); // in KB; 381 Type19Record->MemoryArrayHandle = MemArraySmbiosHandle; 382 Type19Record->PartitionWidth = SmbiosGetPartitionWidth (); 383 Type19Record->ExtendedStartingAddress = 0x0; 384 Type19Record->ExtendedEndingAddress = 0x0; 385 386 MemArrayMappedAddrSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; 387 Status = mSmbios->Add (mSmbios, NULL, &MemArrayMappedAddrSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *)Type19Record); 388 if(EFI_ERROR(Status)) 389 { 390 DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type19 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status)); 391 } 392 393 FreePool(Type19Record); 394 return Status; 395 } 396 397 398 EFI_STATUS 399 SmbiosAddType17Table ( 400 IN pGBL_DATA pGblData, 401 IN UINT8 Skt, 402 IN UINT8 Ch, 403 IN UINT8 Dimm, 404 IN EFI_SMBIOS_HANDLE MemArraySmbiosHandle 405 ) 406 { 407 EFI_STATUS Status; 408 SMBIOS_TABLE_TYPE17 *Type17Record; 409 EFI_SMBIOS_HANDLE MemDevSmbiosHandle; 410 UINTN TableSize; 411 412 UINTN StringBufferSize; 413 EFI_STRING StringBuffer; 414 UINT16 MemInfoMemFreq; 415 UINT16 MemoryTotalWidth; 416 UINT16 MemoryDataWidth; 417 UINT16 MemoryDeviceSize; 418 UINT16 MemorySpeed; 419 UINT8 Attributes; 420 UINT32 MemoryDeviceExtendSize; 421 UINT16 CfgMemorySpeed; 422 423 CHAR8 *OptionalStrStart; 424 UINTN DeviceLocatorStrLen; 425 UINTN BankLocatorStrLen; 426 UINTN ManufactureStrLen; 427 UINTN SerialNumberStrLen; 428 UINTN AssertTagStrLen; 429 UINTN PartNumberStrLen; 430 EFI_STRING DeviceLocatorStr; 431 EFI_STRING BankLocatorStr; 432 EFI_STRING ManufactureStr; 433 EFI_STRING SerialNumberStr; 434 EFI_STRING AssertTagStr; 435 EFI_STRING PartNumberStr; 436 EFI_STRING_ID DeviceLocator; 437 438 Type17Record = NULL; 439 DeviceLocatorStr = NULL; 440 BankLocatorStr = NULL; 441 ManufactureStr = NULL; 442 SerialNumberStr = NULL; 443 AssertTagStr = NULL; 444 PartNumberStr = NULL; 445 446 MemoryTotalWidth = 0; 447 MemoryDataWidth = 0; 448 MemoryDeviceSize = 0; 449 MemoryDeviceExtendSize = 0; 450 MemorySpeed = 0; 451 Attributes = 0; 452 CfgMemorySpeed = 0; 453 454 // 455 // Allocate Buffers 456 // 457 StringBufferSize = (sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH; 458 StringBuffer = AllocateZeroPool (StringBufferSize); 459 if(NULL == StringBuffer) 460 { 461 return EFI_OUT_OF_RESOURCES; 462 } 463 464 465 // 466 // Manufacture 467 // 468 ManufactureStr = AllocateZeroPool (StringBufferSize); 469 if(NULL == ManufactureStr) 470 { 471 Status = EFI_OUT_OF_RESOURCES; 472 goto FREE_STR_BUF; 473 } 474 UnicodeSPrint(ManufactureStr, SMBIOS_STRING_MAX_LENGTH - 1, L"NO DIMM"); 475 476 // 477 // SerialNumber 478 // 479 SerialNumberStr = AllocateZeroPool (StringBufferSize); 480 if(NULL == SerialNumberStr) 481 { 482 Status = EFI_OUT_OF_RESOURCES; 483 goto FREE_STR_MAN; 484 } 485 UnicodeSPrint(SerialNumberStr, SMBIOS_STRING_MAX_LENGTH - 1, L"NO DIMM"); 486 487 // 488 // AssetTag 489 // 490 AssertTagStr = AllocateZeroPool (StringBufferSize); 491 if(NULL == AssertTagStr) 492 { 493 Status = EFI_OUT_OF_RESOURCES; 494 goto FREE_STR_SN; 495 } 496 UnicodeSPrint(AssertTagStr, SMBIOS_STRING_MAX_LENGTH - 1, L"NO DIMM"); 497 498 // 499 // PartNumber 500 // 501 PartNumberStr = AllocateZeroPool (StringBufferSize); 502 if(NULL == PartNumberStr) 503 { 504 Status = EFI_OUT_OF_RESOURCES; 505 goto FREE_STR_AST; 506 } 507 UnicodeSPrint(PartNumberStr, SMBIOS_STRING_MAX_LENGTH - 1, L"NO DIMM"); 508 509 510 if(IsDimmPresent(pGblData, Skt, Ch, Dimm)) 511 { 512 MemoryDataWidth = pGblData->Channel[Skt][Ch].Dimm[Dimm].PrimaryBusWidth; 513 MemoryTotalWidth = MemoryDataWidth + pGblData->Channel[Skt][Ch].Dimm[Dimm].ExtensionBusWidth; 514 515 MemoryDeviceSize = pGblData->Channel[Skt][Ch].Dimm[Dimm].DimmSize; //in MB 516 MemoryDeviceExtendSize = 0; 517 518 if (MemoryDeviceSize >= 0x7fff) 519 { 520 MemoryDeviceExtendSize = MemoryDeviceSize; // in MB 521 MemoryDeviceSize = 0x7fff; // max value 522 } 523 524 MemInfoMemFreq = pGblData->Freq; 525 MemorySpeed = pGblData->Channel[Skt][Ch].Dimm[Dimm].DimmSpeed; 526 Attributes = pGblData->Channel[Skt][Ch].Dimm[Dimm].RankNum; 527 CfgMemorySpeed = MemInfoMemFreq; 528 529 // 530 // Manufacturer 531 // 532 SmbiosGetManufacturer (pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdMMfgId & 0xFF, 533 pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdMMfgId >> 8, 534 ManufactureStr 535 ); 536 537 // 538 // SerialNumber 539 // 540 SmbiosGetSerialNumber(pGblData, Skt, Ch, Dimm, SerialNumberStr); 541 542 // 543 // AssetTag 544 // 545 UnicodeSPrint(AssertTagStr, SMBIOS_STRING_MAX_LENGTH - 1, L"Unknown"); 546 547 // 548 // PartNumber 549 // 550 SmbiosGetPartNumber(pGblData, Skt, Ch, Dimm, PartNumberStr); 551 } 552 553 // 554 // DeviceLocator 555 // 556 DeviceLocatorStr = AllocateZeroPool ((sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH); 557 if(NULL == DeviceLocatorStr) 558 { 559 Status = EFI_OUT_OF_RESOURCES; 560 goto FREE_STR_PN; 561 } 562 DeviceLocator = gDimmToDevLocator[Skt][Ch][Dimm]; 563 if (DeviceLocator != 0xFFFF) 564 { 565 UnicodeSPrint(DeviceLocatorStr, SMBIOS_STRING_MAX_LENGTH, L"DIMM%x%x%x ", Skt, Ch, Dimm); 566 StringBuffer = HiiGetPackageString (&gEfiCallerIdGuid, DeviceLocator, NULL); 567 (VOID)StrCatS(DeviceLocatorStr, SMBIOS_STRING_MAX_LENGTH, StringBuffer); 568 } 569 else 570 { 571 UnicodeSPrint(DeviceLocatorStr, SMBIOS_STRING_MAX_LENGTH, L"DIMM%x%x%x", Skt, Ch, Dimm); 572 } 573 DeviceLocatorStrLen = StrLen (DeviceLocatorStr); 574 575 // 576 // BankLocator 577 // 578 BankLocatorStr = AllocateZeroPool ((sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH); 579 if(NULL == BankLocatorStr) 580 { 581 Status = EFI_OUT_OF_RESOURCES; 582 goto FREE_STR_DEV; 583 } 584 UnicodeSPrint(BankLocatorStr, SMBIOS_STRING_MAX_LENGTH, L"SOCKET %x CHANNEL %x DIMM %x", Skt, Ch, Dimm); 585 BankLocatorStrLen = StrLen (BankLocatorStr); 586 587 ManufactureStrLen = StrLen (ManufactureStr); 588 SerialNumberStrLen = StrLen (SerialNumberStr); 589 AssertTagStrLen = StrLen (AssertTagStr); 590 PartNumberStrLen = StrLen (PartNumberStr); 591 592 // 593 // Report Type 17 SMBIOS Record 594 // 595 TableSize = sizeof(SMBIOS_TABLE_TYPE17) + DeviceLocatorStrLen + 1 + BankLocatorStrLen + 1 + ManufactureStrLen + 1 + SerialNumberStrLen + 1 + AssertTagStrLen + 1 + PartNumberStrLen + 1 + 1; 596 Type17Record = AllocateZeroPool (TableSize); 597 if(NULL == Type17Record) 598 { 599 Status = EFI_OUT_OF_RESOURCES; 600 goto FREE_BL; 601 } 602 603 Type17Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_DEVICE; 604 Type17Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE17); 605 Type17Record->Hdr.Handle = 0; 606 Type17Record->MemoryArrayHandle = MemArraySmbiosHandle; 607 Type17Record->MemoryErrorInformationHandle = 0xFFFE; 608 Type17Record->TotalWidth = MemoryTotalWidth; 609 Type17Record->DataWidth = MemoryDataWidth; 610 Type17Record->Size = MemoryDeviceSize; // in MB 611 Type17Record->FormFactor = MemoryFormFactorDimm; 612 Type17Record->DeviceLocator = 1; 613 Type17Record->BankLocator = 2; 614 Type17Record->MemoryType = SmbiosGetMemoryType (pGblData, Skt, Ch, Dimm); 615 616 Type17Record->TypeDetail.Synchronous = 1; 617 618 SmbiosGetTypeDetail (pGblData, Skt, Ch, Dimm, &(Type17Record->TypeDetail)); 619 620 Type17Record->Speed = MemorySpeed; // in MHZ 621 Type17Record->Manufacturer = 3; 622 Type17Record->SerialNumber = 4; 623 Type17Record->AssetTag = 5; 624 Type17Record->PartNumber = 6; 625 Type17Record->Attributes = Attributes; 626 Type17Record->ExtendedSize = MemoryDeviceExtendSize; 627 Type17Record->ConfiguredMemoryClockSpeed = CfgMemorySpeed; 628 // 629 // Add for smbios 2.8.0 630 // 631 SmbiosGetDimmVoltageInfo (pGblData, Skt, Ch, Dimm, Type17Record); 632 633 OptionalStrStart = (CHAR8 *) (Type17Record + 1); 634 UnicodeStrToAsciiStr (DeviceLocatorStr, OptionalStrStart); 635 UnicodeStrToAsciiStr (BankLocatorStr, OptionalStrStart + DeviceLocatorStrLen + 1); 636 UnicodeStrToAsciiStr (ManufactureStr, OptionalStrStart + DeviceLocatorStrLen + 1 + BankLocatorStrLen + 1); 637 UnicodeStrToAsciiStr (SerialNumberStr, OptionalStrStart + DeviceLocatorStrLen + 1 + BankLocatorStrLen + 1 + ManufactureStrLen + 1); 638 UnicodeStrToAsciiStr (AssertTagStr, OptionalStrStart + DeviceLocatorStrLen + 1 + BankLocatorStrLen + 1 + ManufactureStrLen + 1 + SerialNumberStrLen + 1); 639 UnicodeStrToAsciiStr (PartNumberStr, OptionalStrStart + DeviceLocatorStrLen + 1 + BankLocatorStrLen + 1 + ManufactureStrLen + 1 + SerialNumberStrLen + 1 + AssertTagStrLen + 1); 640 641 MemDevSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; 642 Status = mSmbios->Add (mSmbios, NULL, &MemDevSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) Type17Record); 643 if(EFI_ERROR(Status)) 644 { 645 DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type17 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status)); 646 } 647 648 FreePool (Type17Record); 649 650 FREE_BL: 651 FreePool (BankLocatorStr); 652 653 FREE_STR_DEV: 654 FreePool (DeviceLocatorStr); 655 656 FREE_STR_PN: 657 FreePool (PartNumberStr); 658 659 FREE_STR_AST: 660 FreePool (AssertTagStr); 661 662 FREE_STR_SN: 663 FreePool (SerialNumberStr); 664 665 FREE_STR_MAN: 666 FreePool (ManufactureStr); 667 668 FREE_STR_BUF: 669 FreePool (StringBuffer); 670 671 return Status; 672 } 673 674 675 /** 676 Standard EFI driver point. This driver locates the MemoryConfigurationData Variable, 677 if it exists, add the related SMBIOS tables by PI SMBIOS protocol. 678 679 @param ImageHandle Handle for the image of this driver 680 @param SystemTable Pointer to the EFI System Table 681 682 @retval EFI_SUCCESS The data was successfully stored. 683 684 **/ 685 EFI_STATUS 686 EFIAPI 687 MemorySubClassEntryPoint( 688 IN EFI_HANDLE ImageHandle, 689 IN EFI_SYSTEM_TABLE *SystemTable 690 ) 691 { 692 EFI_STATUS Status; 693 EFI_SMBIOS_PROTOCOL *Smbios; 694 EFI_HOB_GUID_TYPE *GuidHob; 695 pGBL_DATA pGblData; 696 EFI_SMBIOS_HANDLE MemArraySmbiosHandle; 697 UINT8 Skt, Ch, Dimm; 698 699 GuidHob = GetFirstGuidHob(&gHisiEfiMemoryMapGuid); 700 if(NULL == GuidHob) 701 { 702 DEBUG((EFI_D_ERROR, "Could not get MemoryMap Guid hob. %r\n")); 703 return EFI_NOT_FOUND; 704 } 705 pGblData = (pGBL_DATA) GET_GUID_HOB_DATA(GuidHob); 706 707 // 708 // Locate dependent protocols 709 // 710 Status = gBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, (VOID**)&Smbios); 711 if (EFI_ERROR(Status)) 712 { 713 DEBUG((EFI_D_ERROR, "Could not locate SMBIOS protocol. %r\n", Status)); 714 return Status; 715 } 716 mSmbios = Smbios; 717 718 // 719 // Add our default strings to the HII database. They will be modified later. 720 // 721 mHiiHandle = OemGetPackages(); 722 if(NULL == mHiiHandle) 723 { 724 return EFI_OUT_OF_RESOURCES; 725 } 726 727 mMaxSkt = OemGetSocketNumber(); 728 mMaxCh = OemGetDdrChannel(); 729 // Get DIMM slot number on Socket 0 Channel 0 730 // TODO: Assume all channels have same slot number 731 732 Status = SmbiosAddType16Table (pGblData, &MemArraySmbiosHandle); 733 if(EFI_ERROR(Status)) 734 { 735 DEBUG((EFI_D_ERROR, "Smbios Add Type16 Table Failed. %r\n", Status)); 736 return Status; 737 } 738 739 Status = SmbiosAddType19Table (pGblData, MemArraySmbiosHandle); 740 if(EFI_ERROR(Status)) 741 { 742 DEBUG((EFI_D_ERROR, "Smbios Add Type19 Table Failed. %r\n", Status)); 743 return Status; 744 } 745 746 for(Skt = 0; Skt < mMaxSkt; Skt++) 747 { 748 for(Ch = 0; Ch < mMaxCh; Ch++) 749 { 750 for(Dimm = 0; Dimm < OemGetDimmSlot(Skt, Ch); Dimm++) 751 { 752 Status = SmbiosAddType17Table (pGblData, Skt, Ch, Dimm, MemArraySmbiosHandle); 753 if(EFI_ERROR(Status)) 754 { 755 DEBUG((EFI_D_ERROR, "Smbios Add Type17 Table Failed. %r\n", Status)); 756 } 757 } 758 } 759 } 760 761 return Status; 762 } 763