--- /dev/null
+/*++\r
+\r
+Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved.\r
+ \r\r
+ This program and the accompanying materials are licensed and made available under\r\r
+ the terms and conditions of the BSD License that accompanies this distribution. \r\r
+ The full text of the license may be found at \r\r
+ http://opensource.org/licenses/bsd-license.php. \r\r
+ \r\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r\r
+ \r\r
+\r
+\r
+\r
+Module Name:\r
+\r
+ MiscOemType0x88Function.c\r
+\r
+Abstract:\r
+\r
+ The function that processes the Smbios data type 0x88 before they\r
+ are submitted to Data Hub\r
+\r
+--*/\r
+\r
+#include "CommonHeader.h"\r
+\r
+#include "MiscSubclassDriver.h"\r
+#include <Library/PrintLib.h>\r
+#include <Library/CpuIA32.h>\r
+#include <Protocol/DxeSmmReadyToLock.h>\r
+\r
+\r
+VOID\r
+GetCPUStepping ( )\r
+{\r
+ CHAR16 Buffer[40];\r
+\r
+ UINT16 FamilyId;\r
+ UINT8 Model;\r
+ UINT8 SteppingId;\r
+ UINT8 ProcessorType;\r
+\r
+\r
+ EfiCpuVersion (&FamilyId, &Model, &SteppingId, &ProcessorType);\r
+\r
+ //\r
+ //we need raw Model data\r
+ //\r
+ Model = Model & 0xf;\r
+\r
+ //\r
+ //Family/Model/Step\r
+ //\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%d/%d/%d", FamilyId, Model, SteppingId);\r
+ HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_PROCESSOR_STEPPING), Buffer, NULL);\r
+\r
+}\r
+\r
+EFI_STATUS\r
+SearchChildHandle(\r
+ EFI_HANDLE Father,\r
+ EFI_HANDLE *Child\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN HandleIndex;\r
+ EFI_GUID **ProtocolGuidArray = NULL;\r
+ UINTN ArrayCount;\r
+ UINTN ProtocolIndex;\r
+ UINTN OpenInfoCount;\r
+ UINTN OpenInfoIndex;\r
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo = NULL;\r
+ UINTN mHandleCount;\r
+ EFI_HANDLE *mHandleBuffer= NULL;\r
+\r
+ //\r
+ // Retrieve the list of all handles from the handle database\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ AllHandles,\r
+ NULL,\r
+ NULL,\r
+ &mHandleCount,\r
+ &mHandleBuffer\r
+ );\r
+\r
+ for (HandleIndex = 0; HandleIndex < mHandleCount; HandleIndex++) {\r
+ //\r
+ // Retrieve the list of all the protocols on each handle\r
+ //\r
+ Status = gBS->ProtocolsPerHandle (\r
+ mHandleBuffer[HandleIndex],\r
+ &ProtocolGuidArray,\r
+ &ArrayCount\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {\r
+ Status = gBS->OpenProtocolInformation (\r
+ mHandleBuffer[HandleIndex],\r
+ ProtocolGuidArray[ProtocolIndex],\r
+ &OpenInfo,\r
+ &OpenInfoCount\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {\r
+ if(OpenInfo[OpenInfoIndex].AgentHandle == Father) {\r
+ if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {\r
+ *Child = mHandleBuffer[HandleIndex];\r
+ Status = EFI_SUCCESS;\r
+ goto TryReturn;\r
+ }\r
+ }\r
+ }\r
+ Status = EFI_NOT_FOUND;\r
+ }\r
+ }\r
+ if(OpenInfo != NULL) {\r
+ FreePool(OpenInfo);\r
+ OpenInfo = NULL;\r
+ }\r
+ }\r
+ if(ProtocolGuidArray != NULL) {\r
+ FreePool (ProtocolGuidArray);\r
+ ProtocolGuidArray = NULL;\r
+ }\r
+ }\r
+TryReturn:\r
+ if(OpenInfo != NULL) {\r
+ FreePool (OpenInfo);\r
+ OpenInfo = NULL;\r
+ }\r
+ if(ProtocolGuidArray != NULL) {\r
+ FreePool(ProtocolGuidArray);\r
+ ProtocolGuidArray = NULL;\r
+ }\r
+ if(mHandleBuffer != NULL) {\r
+ FreePool (mHandleBuffer);\r
+ mHandleBuffer = NULL;\r
+ }\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+JudgeHandleIsPCIDevice(\r
+ EFI_HANDLE Handle,\r
+ UINT8 Device,\r
+ UINT8 Funs\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH *DPath;\r
+ EFI_DEVICE_PATH *DevicePath;\r
+\r
+ Status = gBS->HandleProtocol (\r
+ Handle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &DPath\r
+ );\r
+ if(!EFI_ERROR(Status)) {\r
+ DevicePath = DPath;\r
+ while(!IsDevicePathEnd(DPath)) {\r
+ if((DPath->Type == HARDWARE_DEVICE_PATH) && (DPath->SubType == HW_PCI_DP)) {\r
+ PCI_DEVICE_PATH *PCIPath;\r
+ PCIPath = (PCI_DEVICE_PATH*) DPath;\r
+ DPath = NextDevicePathNode(DPath);\r
+\r
+ if(IsDevicePathEnd(DPath) && (PCIPath->Device == Device) && (PCIPath->Function == Funs)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ } else {\r
+ DPath = NextDevicePathNode(DPath);\r
+ }\r
+ }\r
+ }\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+EFI_STATUS\r
+GetDriverName(\r
+ EFI_HANDLE Handle\r
+)\r
+{\r
+ EFI_DRIVER_BINDING_PROTOCOL *BindHandle = NULL;\r
+ EFI_STATUS Status;\r
+ UINT32 Version;\r
+ UINT16 *Ptr;\r
+ CHAR16 Buffer[40];\r
+ STRING_REF TokenToUpdate;\r
+ Status = gBS->OpenProtocol(\r
+ Handle,\r
+ &gEfiDriverBindingProtocolGuid,\r
+ (VOID**)&BindHandle,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Version = BindHandle->Version;\r
+ Ptr = (UINT16*)&Version;\r
+ UnicodeSPrint(Buffer, sizeof (Buffer), L"%d.%d.%d", Version >> 24 , (Version >>16)& 0x0f ,*(Ptr));\r
+\r
+ TokenToUpdate = (STRING_REF)STR_MISC_GOP_VERSION;\r
+ HiiSetString(mHiiHandle, TokenToUpdate, Buffer, NULL);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+GetGOPDriverName()\r
+{\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *Handles= NULL;\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Child = 0;\r
+\r
+ Status = gBS->LocateHandleBuffer(\r
+ ByProtocol,\r
+ &gEfiDriverBindingProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &Handles\r
+ );\r
+\r
+ for (Index = 0; Index < HandleCount ; Index++) {\r
+ Status = SearchChildHandle(Handles[Index], &Child);\r
+ if(!EFI_ERROR(Status)) {\r
+ Status = JudgeHandleIsPCIDevice(Child, 0x02, 0x00);\r
+ if(!EFI_ERROR(Status)) {\r
+ return GetDriverName(Handles[Index]);\r
+ }\r
+ }\r
+ }\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+VOID\r
+GetUcodeVersion()\r
+{\r
+ UINT32 MicroCodeVersion;\r
+ CHAR16 Buffer[40];\r
+\r
+ //\r
+ // Microcode Revision\r
+ //\r
+ EfiWriteMsr (EFI_MSR_IA32_BIOS_SIGN_ID, 0);\r
+ EfiCpuid (EFI_CPUID_VERSION_INFO, NULL);\r
+ MicroCodeVersion = (UINT32) RShiftU64 (EfiReadMsr (EFI_MSR_IA32_BIOS_SIGN_ID), 32);\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%x", MicroCodeVersion);\r
+ HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_UCODE_VERSION), Buffer, NULL);\r
+}\r
+\r
+/**\r
+ Publish the smbios OEM type 0x90.\r
+\r
+ @param Event - Event whose notification function is being invoked (gEfiDxeSmmReadyToLockProtocolGuid).\r
+ @param Context - Pointer to the notification functions context, which is implementation dependent.\r
+\r
+ @retval None\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AddSmbiosT0x90Callback (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN SECVerStrLen = 0;\r
+ UINTN uCodeVerStrLen = 0;\r
+ UINTN GOPStrLen = 0;\r
+ UINTN SteppingStrLen = 0;\r
+ SMBIOS_TABLE_TYPE90 *SmbiosRecord;\r
+ EFI_SMBIOS_HANDLE SmbiosHandle;\r
+ EFI_MISC_OEM_TYPE_0x90 *ForType90InputData;\r
+ CHAR16 *SECVer;\r
+ CHAR16 *uCodeVer;\r
+ CHAR16 *GOPVer;\r
+ CHAR16 *Stepping;\r
+ STRING_REF TokenToGet;\r
+ CHAR8 *OptionalStrStart;\r
+ EFI_SMBIOS_PROTOCOL *SmbiosProtocol;\r
+\r
+ ForType90InputData = (EFI_MISC_OEM_TYPE_0x90 *)Context;\r
+\r
+ DEBUG ((EFI_D_INFO, "Executing SMBIOS T0x90 callback.\n"));\r
+\r
+ gBS->CloseEvent (Event); // Unload this event.\r
+\r
+ //\r
+ // First check for invalid parameters.\r
+ //\r
+ if (Context == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiSmbiosProtocolGuid,\r
+ NULL,\r
+ (VOID *) &SmbiosProtocol\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ GetUcodeVersion();\r
+ GetGOPDriverName();\r
+ GetCPUStepping();\r
+\r
+ TokenToGet = STRING_TOKEN (STR_MISC_SEC_VERSION);\r
+ SECVer = SmbiosMiscGetString (TokenToGet);\r
+ SECVerStrLen = StrLen(SECVer);\r
+ if (SECVerStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ TokenToGet = STRING_TOKEN (STR_MISC_UCODE_VERSION);\r
+ uCodeVer = SmbiosMiscGetString (TokenToGet);\r
+ uCodeVerStrLen = StrLen(uCodeVer);\r
+ if (uCodeVerStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ TokenToGet = STRING_TOKEN (STR_MISC_GOP_VERSION);\r
+ GOPVer = SmbiosMiscGetString (TokenToGet);\r
+ GOPStrLen = StrLen(GOPVer);\r
+ if (GOPStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ TokenToGet = STRING_TOKEN (STR_MISC_PROCESSOR_STEPPING);\r
+ Stepping = SmbiosMiscGetString (TokenToGet);\r
+ SteppingStrLen = StrLen(Stepping);\r
+\r
+\r
+ if (SteppingStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE90) + SECVerStrLen + 1 + uCodeVerStrLen + 1 + GOPStrLen + 1 + SteppingStrLen + 1 + 1);\r
+ ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE90) + SECVerStrLen + 1 + uCodeVerStrLen + 1 + GOPStrLen + 1 + SteppingStrLen + 1 + 1);\r
+\r
+ SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_FIRMWARE_VERSION_INFO;\r
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE90);\r
+\r
+ //\r
+ // Make handle chosen by smbios protocol.add automatically.\r
+ //\r
+ SmbiosRecord->Hdr.Handle = 0;\r
+\r
+ //\r
+ // SEC VERSION will be the 1st optional string following the formatted structure.\r
+ //\r
+ SmbiosRecord->SECVersion = 0;\r
+\r
+ //\r
+ // Microcode VERSION will be the 2nd optional string following the formatted structure.\r
+ //\r
+ SmbiosRecord->uCodeVersion = 2;\r
+\r
+ //\r
+ // GOP VERSION will be the 3rd optional string following the formatted structure.\r
+ //\r
+ SmbiosRecord->GOPVersion = 3;\r
+\r
+ //\r
+ // CPU Stepping will be the 4th optional string following the formatted structure.\r
+ //\r
+ SmbiosRecord->CpuStepping = 4;\r
+\r
+ OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);\r
+ UnicodeStrToAsciiStr(SECVer, OptionalStrStart);\r
+ UnicodeStrToAsciiStr(uCodeVer, OptionalStrStart + SECVerStrLen + 1);\r
+ UnicodeStrToAsciiStr(GOPVer, OptionalStrStart + SECVerStrLen + 1 + uCodeVerStrLen + 1);\r
+ UnicodeStrToAsciiStr(Stepping, OptionalStrStart + SECVerStrLen + 1 + uCodeVerStrLen + 1 + GOPStrLen + 1);\r
+\r
+ //\r
+ // Now we have got the full smbios record, call smbios protocol to add this record.\r
+ //\r
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r
+ Status = SmbiosProtocol-> Add(\r
+ SmbiosProtocol,\r
+ NULL,\r
+ &SmbiosHandle,\r
+ (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord\r
+ );\r
+\r
+ FreePool(SmbiosRecord);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function makes boot time changes to the contents of the\r
+ MiscOemType0x90 (Type 0x90).\r
+\r
+ @param RecordData Pointer to copy of RecordData from the Data Table.\r
+\r
+ @retval EFI_SUCCESS All parameters were valid.\r
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.\r
+\r
+**/\r
+MISC_SMBIOS_TABLE_FUNCTION(MiscOemType0x90)\r
+{\r
+ EFI_STATUS Status;\r
+ static BOOLEAN CallbackIsInstalledT0x90 = FALSE;\r
+ VOID *AddSmbiosT0x90CallbackNotifyReg;\r
+ EFI_EVENT AddSmbiosT0x90CallbackEvent;\r
+\r
+ //\r
+ // This callback will create a OEM Type 0x90 record.\r
+ //\r
+ if (CallbackIsInstalledT0x90 == FALSE) {\r
+ CallbackIsInstalledT0x90 = TRUE; // Prevent more than 1 callback.\r
+ DEBUG ((EFI_D_INFO, "Create Smbios T0x90 callback.\n"));\r
+\r
+ //\r
+ // gEfiDxeSmmReadyToLockProtocolGuid is ready\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ (EFI_EVENT_NOTIFY)AddSmbiosT0x90Callback,\r
+ RecordData,\r
+ &AddSmbiosT0x90CallbackEvent\r
+ );\r
+\r
+ ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+\r
+ }\r
+\r
+ Status = gBS->RegisterProtocolNotify (\r
+ &gEfiDxeSmmReadyToLockProtocolGuid,\r
+ AddSmbiosT0x90CallbackEvent,\r
+ &AddSmbiosT0x90CallbackNotifyReg\r
+ );\r
+\r
+ return Status;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r