MiscOemType0x90Function.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /*++
  2. Copyright (c) 1999 - 2014, 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. EFI_SMBIOS_PROTOCOL *SmbiosProtocol;
  250. DEBUG ((EFI_D_INFO, "Executing SMBIOS T0x90 callback.\n"));
  251. gBS->CloseEvent (Event); // Unload this event.
  252. //
  253. // First check for invalid parameters.
  254. //
  255. if (Context == NULL) {
  256. return EFI_INVALID_PARAMETER;
  257. }
  258. Status = gBS->LocateProtocol (
  259. &gEfiSmbiosProtocolGuid,
  260. NULL,
  261. (VOID *) &SmbiosProtocol
  262. );
  263. ASSERT_EFI_ERROR (Status);
  264. GetUcodeVersion();
  265. GetGOPDriverName();
  266. GetCPUStepping();
  267. TokenToGet = STRING_TOKEN (STR_MISC_SEC_VERSION);
  268. SECVer = SmbiosMiscGetString (TokenToGet);
  269. SECVerStrLen = StrLen(SECVer);
  270. if (SECVerStrLen > SMBIOS_STRING_MAX_LENGTH) {
  271. return EFI_UNSUPPORTED;
  272. }
  273. TokenToGet = STRING_TOKEN (STR_MISC_UCODE_VERSION);
  274. uCodeVer = SmbiosMiscGetString (TokenToGet);
  275. uCodeVerStrLen = StrLen(uCodeVer);
  276. if (uCodeVerStrLen > SMBIOS_STRING_MAX_LENGTH) {
  277. return EFI_UNSUPPORTED;
  278. }
  279. TokenToGet = STRING_TOKEN (STR_MISC_GOP_VERSION);
  280. GOPVer = SmbiosMiscGetString (TokenToGet);
  281. GOPStrLen = StrLen(GOPVer);
  282. if (GOPStrLen > SMBIOS_STRING_MAX_LENGTH) {
  283. return EFI_UNSUPPORTED;
  284. }
  285. TokenToGet = STRING_TOKEN (STR_MISC_PROCESSOR_STEPPING);
  286. Stepping = SmbiosMiscGetString (TokenToGet);
  287. SteppingStrLen = StrLen(Stepping);
  288. if (SteppingStrLen > SMBIOS_STRING_MAX_LENGTH) {
  289. return EFI_UNSUPPORTED;
  290. }
  291. SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE90) + SECVerStrLen + 1 + uCodeVerStrLen + 1 + GOPStrLen + 1 + SteppingStrLen + 1 + 1);
  292. ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE90) + SECVerStrLen + 1 + uCodeVerStrLen + 1 + GOPStrLen + 1 + SteppingStrLen + 1 + 1);
  293. SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_FIRMWARE_VERSION_INFO;
  294. SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE90);
  295. //
  296. // Make handle chosen by smbios protocol.add automatically.
  297. //
  298. SmbiosRecord->Hdr.Handle = 0;
  299. //
  300. // SEC VERSION will be the 1st optional string following the formatted structure.
  301. //
  302. SmbiosRecord->SECVersion = 0;
  303. //
  304. // Microcode VERSION will be the 2nd optional string following the formatted structure.
  305. //
  306. SmbiosRecord->uCodeVersion = 2;
  307. //
  308. // GOP VERSION will be the 3rd optional string following the formatted structure.
  309. //
  310. SmbiosRecord->GOPVersion = 3;
  311. //
  312. // CPU Stepping will be the 4th optional string following the formatted structure.
  313. //
  314. SmbiosRecord->CpuStepping = 4;
  315. OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
  316. UnicodeStrToAsciiStr(SECVer, OptionalStrStart);
  317. UnicodeStrToAsciiStr(uCodeVer, OptionalStrStart + SECVerStrLen + 1);
  318. UnicodeStrToAsciiStr(GOPVer, OptionalStrStart + SECVerStrLen + 1 + uCodeVerStrLen + 1);
  319. UnicodeStrToAsciiStr(Stepping, OptionalStrStart + SECVerStrLen + 1 + uCodeVerStrLen + 1 + GOPStrLen + 1);
  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 = SmbiosProtocol-> Add(
  325. SmbiosProtocol,
  326. NULL,
  327. &SmbiosHandle,
  328. (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord
  329. );
  330. FreePool(SmbiosRecord);
  331. return Status;
  332. }
  333. /**
  334. This function makes boot time changes to the contents of the
  335. MiscOemType0x90 (Type 0x90).
  336. @param RecordData Pointer to copy of RecordData from the Data Table.
  337. @retval EFI_SUCCESS All parameters were valid.
  338. @retval EFI_UNSUPPORTED Unexpected RecordType value.
  339. @retval EFI_INVALID_PARAMETER Invalid parameter was found.
  340. **/
  341. MISC_SMBIOS_TABLE_FUNCTION(MiscOemType0x90)
  342. {
  343. EFI_STATUS Status;
  344. static BOOLEAN CallbackIsInstalledT0x90 = FALSE;
  345. VOID *AddSmbiosT0x90CallbackNotifyReg;
  346. EFI_EVENT AddSmbiosT0x90CallbackEvent;
  347. //
  348. // This callback will create a OEM Type 0x90 record.
  349. //
  350. if (CallbackIsInstalledT0x90 == FALSE) {
  351. CallbackIsInstalledT0x90 = TRUE; // Prevent more than 1 callback.
  352. DEBUG ((EFI_D_INFO, "Create Smbios T0x90 callback.\n"));
  353. //
  354. // gEfiDxeSmmReadyToLockProtocolGuid is ready
  355. //
  356. Status = gBS->CreateEvent (
  357. EVT_NOTIFY_SIGNAL,
  358. TPL_CALLBACK,
  359. (EFI_EVENT_NOTIFY)AddSmbiosT0x90Callback,
  360. RecordData,
  361. &AddSmbiosT0x90CallbackEvent
  362. );
  363. ASSERT_EFI_ERROR (Status);
  364. if (EFI_ERROR (Status)) {
  365. return Status;
  366. }
  367. Status = gBS->RegisterProtocolNotify (
  368. &gEfiDxeSmmReadyToLockProtocolGuid,
  369. AddSmbiosT0x90CallbackEvent,
  370. &AddSmbiosT0x90CallbackNotifyReg
  371. );
  372. return Status;
  373. }
  374. return EFI_SUCCESS;
  375. }