MemorySubClass.c 23 KB

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