MiscOemType0x90Function.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. /*++
  2. Copyright (c) 1999 - 2020, Intel Corporation. All rights reserved.
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. Module Name:
  5. MiscOemType0x88Function.c
  6. Abstract:
  7. The function that processes the Smbios data type 0x88 before they
  8. are submitted to Data Hub
  9. --*/
  10. #include "CommonHeader.h"
  11. #include "MiscSubclassDriver.h"
  12. #include <Library/PrintLib.h>
  13. #include <Protocol/DxeSmmReadyToLock.h>
  14. #include <Register/Cpuid.h>
  15. #include <Register/Msr.h>
  16. VOID
  17. GetCPUStepping ( )
  18. {
  19. CHAR16 Buffer[40];
  20. UINT32 FamilyId;
  21. UINT32 Model;
  22. UINT32 SteppingId;
  23. CPUID_VERSION_INFO_EAX Eax;
  24. CPUID_VERSION_INFO_EBX Ebx;
  25. CPUID_VERSION_INFO_ECX Ecx;
  26. CPUID_VERSION_INFO_EDX Edx;
  27. AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32);
  28. FamilyId = Eax.Bits.FamilyId;
  29. if (Eax.Bits.FamilyId == 0x0F) {
  30. FamilyId |= (Eax.Bits.ExtendedFamilyId << 4);
  31. }
  32. Model = Eax.Bits.Model;
  33. if (Eax.Bits.FamilyId == 0x06 || Eax.Bits.FamilyId == 0x0f) {
  34. Model |= (Eax.Bits.ExtendedModelId << 4);
  35. }
  36. SteppingId = Eax.Bits.SteppingId;
  37. //
  38. //Family/Model/Step
  39. //
  40. UnicodeSPrint (Buffer, sizeof (Buffer), L"%d/%d/%d", FamilyId, Model, SteppingId);
  41. HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_PROCESSOR_STEPPING), Buffer, NULL);
  42. }
  43. EFI_STATUS
  44. SearchChildHandle(
  45. EFI_HANDLE Father,
  46. EFI_HANDLE *Child
  47. )
  48. {
  49. EFI_STATUS Status;
  50. UINTN HandleIndex;
  51. EFI_GUID **ProtocolGuidArray = NULL;
  52. UINTN ArrayCount;
  53. UINTN ProtocolIndex;
  54. UINTN OpenInfoCount;
  55. UINTN OpenInfoIndex;
  56. EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo = NULL;
  57. UINTN mHandleCount;
  58. EFI_HANDLE *mHandleBuffer= NULL;
  59. //
  60. // Retrieve the list of all handles from the handle database
  61. //
  62. Status = gBS->LocateHandleBuffer (
  63. AllHandles,
  64. NULL,
  65. NULL,
  66. &mHandleCount,
  67. &mHandleBuffer
  68. );
  69. for (HandleIndex = 0; HandleIndex < mHandleCount; HandleIndex++) {
  70. //
  71. // Retrieve the list of all the protocols on each handle
  72. //
  73. Status = gBS->ProtocolsPerHandle (
  74. mHandleBuffer[HandleIndex],
  75. &ProtocolGuidArray,
  76. &ArrayCount
  77. );
  78. if (!EFI_ERROR (Status)) {
  79. for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
  80. Status = gBS->OpenProtocolInformation (
  81. mHandleBuffer[HandleIndex],
  82. ProtocolGuidArray[ProtocolIndex],
  83. &OpenInfo,
  84. &OpenInfoCount
  85. );
  86. if (!EFI_ERROR (Status)) {
  87. for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
  88. if(OpenInfo[OpenInfoIndex].AgentHandle == Father) {
  89. if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
  90. *Child = mHandleBuffer[HandleIndex];
  91. Status = EFI_SUCCESS;
  92. goto TryReturn;
  93. }
  94. }
  95. }
  96. Status = EFI_NOT_FOUND;
  97. }
  98. }
  99. if(OpenInfo != NULL) {
  100. FreePool(OpenInfo);
  101. OpenInfo = NULL;
  102. }
  103. }
  104. if(ProtocolGuidArray != NULL) {
  105. FreePool (ProtocolGuidArray);
  106. ProtocolGuidArray = NULL;
  107. }
  108. }
  109. TryReturn:
  110. if(OpenInfo != NULL) {
  111. FreePool (OpenInfo);
  112. OpenInfo = NULL;
  113. }
  114. if(ProtocolGuidArray != NULL) {
  115. FreePool(ProtocolGuidArray);
  116. ProtocolGuidArray = NULL;
  117. }
  118. if(mHandleBuffer != NULL) {
  119. FreePool (mHandleBuffer);
  120. mHandleBuffer = NULL;
  121. }
  122. return Status;
  123. }
  124. EFI_STATUS
  125. JudgeHandleIsPCIDevice(
  126. EFI_HANDLE Handle,
  127. UINT8 Device,
  128. UINT8 Funs
  129. )
  130. {
  131. EFI_STATUS Status;
  132. EFI_DEVICE_PATH *DPath;
  133. Status = gBS->HandleProtocol (
  134. Handle,
  135. &gEfiDevicePathProtocolGuid,
  136. (VOID **) &DPath
  137. );
  138. if(!EFI_ERROR(Status)) {
  139. while(!IsDevicePathEnd(DPath)) {
  140. if((DPath->Type == HARDWARE_DEVICE_PATH) && (DPath->SubType == HW_PCI_DP)) {
  141. PCI_DEVICE_PATH *PCIPath;
  142. PCIPath = (PCI_DEVICE_PATH*) DPath;
  143. DPath = NextDevicePathNode(DPath);
  144. if(IsDevicePathEnd(DPath) && (PCIPath->Device == Device) && (PCIPath->Function == Funs)) {
  145. return EFI_SUCCESS;
  146. }
  147. } else {
  148. DPath = NextDevicePathNode(DPath);
  149. }
  150. }
  151. }
  152. return EFI_UNSUPPORTED;
  153. }
  154. EFI_STATUS
  155. GetDriverName(
  156. EFI_HANDLE Handle
  157. )
  158. {
  159. EFI_DRIVER_BINDING_PROTOCOL *BindHandle = NULL;
  160. EFI_STATUS Status;
  161. UINT32 Version;
  162. UINT16 *Ptr;
  163. CHAR16 Buffer[40];
  164. STRING_REF TokenToUpdate;
  165. Status = gBS->OpenProtocol(
  166. Handle,
  167. &gEfiDriverBindingProtocolGuid,
  168. (VOID**)&BindHandle,
  169. NULL,
  170. NULL,
  171. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  172. );
  173. if (EFI_ERROR(Status)) {
  174. return EFI_NOT_FOUND;
  175. }
  176. Version = BindHandle->Version;
  177. Ptr = (UINT16*)&Version;
  178. UnicodeSPrint(Buffer, sizeof (Buffer), L"%d.%d.%d", Version >> 24 , (Version >>16)& 0x0f ,*(Ptr));
  179. TokenToUpdate = (STRING_REF)STR_MISC_GOP_VERSION;
  180. HiiSetString(mHiiHandle, TokenToUpdate, Buffer, NULL);
  181. return EFI_SUCCESS;
  182. }
  183. EFI_STATUS
  184. GetGOPDriverName()
  185. {
  186. UINTN HandleCount;
  187. EFI_HANDLE *Handles= NULL;
  188. UINTN Index;
  189. EFI_STATUS Status;
  190. EFI_HANDLE Child = 0;
  191. Status = gBS->LocateHandleBuffer(
  192. ByProtocol,
  193. &gEfiDriverBindingProtocolGuid,
  194. NULL,
  195. &HandleCount,
  196. &Handles
  197. );
  198. for (Index = 0; Index < HandleCount ; Index++) {
  199. Status = SearchChildHandle(Handles[Index], &Child);
  200. if(!EFI_ERROR(Status)) {
  201. Status = JudgeHandleIsPCIDevice(Child, 0x02, 0x00);
  202. if(!EFI_ERROR(Status)) {
  203. return GetDriverName(Handles[Index]);
  204. }
  205. }
  206. }
  207. return EFI_UNSUPPORTED;
  208. }
  209. VOID
  210. GetUcodeVersion()
  211. {
  212. UINT32 MicroCodeVersion;
  213. CHAR16 Buffer[40];
  214. //
  215. // Microcode Revision
  216. //
  217. AsmWriteMsr64 (MSR_IA32_BIOS_SIGN_ID, 0);
  218. AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, NULL);
  219. MicroCodeVersion = (UINT32) RShiftU64 (AsmReadMsr64 (MSR_IA32_BIOS_SIGN_ID), 32);
  220. UnicodeSPrint (Buffer, sizeof (Buffer), L"%x", MicroCodeVersion);
  221. HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_UCODE_VERSION), Buffer, NULL);
  222. }
  223. /**
  224. Publish the smbios OEM type 0x90.
  225. @param Event - Event whose notification function is being invoked (gEfiDxeSmmReadyToLockProtocolGuid).
  226. @param Context - Pointer to the notification functions context, which is implementation dependent.
  227. @retval None
  228. **/
  229. EFI_STATUS
  230. EFIAPI
  231. AddSmbiosT0x90Callback (
  232. IN EFI_EVENT Event,
  233. IN VOID *Context
  234. )
  235. {
  236. EFI_STATUS Status;
  237. UINTN SECVerStrLen = 0;
  238. UINTN uCodeVerStrLen = 0;
  239. UINTN GOPStrLen = 0;
  240. UINTN SteppingStrLen = 0;
  241. SMBIOS_TABLE_TYPE90 *SmbiosRecord;
  242. EFI_SMBIOS_HANDLE SmbiosHandle;
  243. CHAR16 *SECVer;
  244. CHAR16 *uCodeVer;
  245. CHAR16 *GOPVer;
  246. CHAR16 *Stepping;
  247. STRING_REF TokenToGet;
  248. CHAR8 *OptionalStrStart;
  249. UINTN OptionalStrSize;
  250. EFI_SMBIOS_PROTOCOL *SmbiosProtocol;
  251. DEBUG ((EFI_D_INFO, "Executing SMBIOS T0x90 callback.\n"));
  252. gBS->CloseEvent (Event); // Unload this event.
  253. //
  254. // First check for invalid parameters.
  255. //
  256. if (Context == NULL) {
  257. return EFI_INVALID_PARAMETER;
  258. }
  259. Status = gBS->LocateProtocol (
  260. &gEfiSmbiosProtocolGuid,
  261. NULL,
  262. (VOID *) &SmbiosProtocol
  263. );
  264. ASSERT_EFI_ERROR (Status);
  265. GetUcodeVersion();
  266. GetGOPDriverName();
  267. GetCPUStepping();
  268. TokenToGet = STRING_TOKEN (STR_MISC_SEC_VERSION);
  269. SECVer = SmbiosMiscGetString (TokenToGet);
  270. SECVerStrLen = StrLen(SECVer);
  271. if (SECVerStrLen > SMBIOS_STRING_MAX_LENGTH) {
  272. return EFI_UNSUPPORTED;
  273. }
  274. TokenToGet = STRING_TOKEN (STR_MISC_UCODE_VERSION);
  275. uCodeVer = SmbiosMiscGetString (TokenToGet);
  276. uCodeVerStrLen = StrLen(uCodeVer);
  277. if (uCodeVerStrLen > SMBIOS_STRING_MAX_LENGTH) {
  278. return EFI_UNSUPPORTED;
  279. }
  280. TokenToGet = STRING_TOKEN (STR_MISC_GOP_VERSION);
  281. GOPVer = SmbiosMiscGetString (TokenToGet);
  282. GOPStrLen = StrLen(GOPVer);
  283. if (GOPStrLen > SMBIOS_STRING_MAX_LENGTH) {
  284. return EFI_UNSUPPORTED;
  285. }
  286. TokenToGet = STRING_TOKEN (STR_MISC_PROCESSOR_STEPPING);
  287. Stepping = SmbiosMiscGetString (TokenToGet);
  288. SteppingStrLen = StrLen(Stepping);
  289. if (SteppingStrLen > SMBIOS_STRING_MAX_LENGTH) {
  290. return EFI_UNSUPPORTED;
  291. }
  292. OptionalStrSize = SECVerStrLen + 1 + uCodeVerStrLen + 1 + GOPStrLen + 1 + SteppingStrLen + 1 + 1;
  293. SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE90) + OptionalStrSize);
  294. ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE90) + OptionalStrSize);
  295. SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_FIRMWARE_VERSION_INFO;
  296. SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE90);
  297. //
  298. // Make handle chosen by smbios protocol.add automatically.
  299. //
  300. SmbiosRecord->Hdr.Handle = 0;
  301. //
  302. // SEC VERSION will be the 1st optional string following the formatted structure.
  303. //
  304. SmbiosRecord->SECVersion = 0;
  305. //
  306. // Microcode VERSION will be the 2nd optional string following the formatted structure.
  307. //
  308. SmbiosRecord->uCodeVersion = 2;
  309. //
  310. // GOP VERSION will be the 3rd optional string following the formatted structure.
  311. //
  312. SmbiosRecord->GOPVersion = 3;
  313. //
  314. // CPU Stepping will be the 4th optional string following the formatted structure.
  315. //
  316. SmbiosRecord->CpuStepping = 4;
  317. OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
  318. UnicodeStrToAsciiStrS (SECVer, OptionalStrStart, OptionalStrSize);
  319. OptionalStrStart += (SECVerStrLen + 1);
  320. OptionalStrSize -= (SECVerStrLen + 1);
  321. UnicodeStrToAsciiStrS (uCodeVer, OptionalStrStart, OptionalStrSize);
  322. OptionalStrStart += (uCodeVerStrLen + 1);
  323. OptionalStrSize -= (uCodeVerStrLen + 1);
  324. UnicodeStrToAsciiStrS (GOPVer, OptionalStrStart, OptionalStrSize);
  325. OptionalStrStart += (GOPStrLen + 1);
  326. OptionalStrSize -= (GOPStrLen + 1);
  327. UnicodeStrToAsciiStrS (Stepping, OptionalStrStart, OptionalStrSize);
  328. //
  329. // Now we have got the full smbios record, call smbios protocol to add this record.
  330. //
  331. SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
  332. Status = SmbiosProtocol-> Add(
  333. SmbiosProtocol,
  334. NULL,
  335. &SmbiosHandle,
  336. (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord
  337. );
  338. FreePool(SmbiosRecord);
  339. return Status;
  340. }
  341. /**
  342. This function makes boot time changes to the contents of the
  343. MiscOemType0x90 (Type 0x90).
  344. @param RecordData Pointer to copy of RecordData from the Data Table.
  345. @retval EFI_SUCCESS All parameters were valid.
  346. @retval EFI_UNSUPPORTED Unexpected RecordType value.
  347. @retval EFI_INVALID_PARAMETER Invalid parameter was found.
  348. **/
  349. MISC_SMBIOS_TABLE_FUNCTION(MiscOemType0x90)
  350. {
  351. EFI_STATUS Status;
  352. static BOOLEAN CallbackIsInstalledT0x90 = FALSE;
  353. VOID *AddSmbiosT0x90CallbackNotifyReg;
  354. EFI_EVENT AddSmbiosT0x90CallbackEvent;
  355. //
  356. // This callback will create a OEM Type 0x90 record.
  357. //
  358. if (CallbackIsInstalledT0x90 == FALSE) {
  359. CallbackIsInstalledT0x90 = TRUE; // Prevent more than 1 callback.
  360. DEBUG ((EFI_D_INFO, "Create Smbios T0x90 callback.\n"));
  361. //
  362. // gEfiDxeSmmReadyToLockProtocolGuid is ready
  363. //
  364. Status = gBS->CreateEvent (
  365. EVT_NOTIFY_SIGNAL,
  366. TPL_CALLBACK,
  367. (EFI_EVENT_NOTIFY)AddSmbiosT0x90Callback,
  368. RecordData,
  369. &AddSmbiosT0x90CallbackEvent
  370. );
  371. ASSERT_EFI_ERROR (Status);
  372. if (EFI_ERROR (Status)) {
  373. return Status;
  374. }
  375. Status = gBS->RegisterProtocolNotify (
  376. &gEfiDxeSmmReadyToLockProtocolGuid,
  377. AddSmbiosT0x90CallbackEvent,
  378. &AddSmbiosT0x90CallbackNotifyReg
  379. );
  380. return Status;
  381. }
  382. return EFI_SUCCESS;
  383. }