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