• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*++
2 
3 Copyright (c) 1999  - 2014, Intel Corporation.  All rights reserved.
4 
5 
6   This program and the accompanying materials are licensed and made available under
7 
8   the terms and conditions of the BSD License that accompanies this distribution.
9 
10   The full text of the license may be found at
11 
12   http://opensource.org/licenses/bsd-license.php.
13 
14 
15 
16   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17 
18   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 
20 
21 
22 
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 
GetCPUStepping()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;
JudgeHandleIsPCIDevice(EFI_HANDLE Handle,UINT8 Device,UINT8 Funs)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   EFI_DEVICE_PATH   *DevicePath;
165 
166   Status = gBS->HandleProtocol (
167                   Handle,
168                   &gEfiDevicePathProtocolGuid,
169                   (VOID **) &DPath
170                   );
171   if(!EFI_ERROR(Status)) {
172     DevicePath = DPath;
173     while(!IsDevicePathEnd(DPath)) {
174       if((DPath->Type == HARDWARE_DEVICE_PATH) && (DPath->SubType == HW_PCI_DP)) {
175         PCI_DEVICE_PATH   *PCIPath;
176         PCIPath = (PCI_DEVICE_PATH*) DPath;
177         DPath = NextDevicePathNode(DPath);
178 
179         if(IsDevicePathEnd(DPath) && (PCIPath->Device == Device) && (PCIPath->Function == Funs)) {
180           return EFI_SUCCESS;
181         }
GetDriverName(EFI_HANDLE Handle)182       } else {
183         DPath = NextDevicePathNode(DPath);
184       }
185     }
186   }
187   return EFI_UNSUPPORTED;
188 }
189 
190 EFI_STATUS
191 GetDriverName(
192   EFI_HANDLE   Handle
193 )
194 {
195   EFI_DRIVER_BINDING_PROTOCOL        *BindHandle = NULL;
196   EFI_STATUS                         Status;
197   UINT32                             Version;
198   UINT16                             *Ptr;
199   CHAR16                             Buffer[40];
200   STRING_REF                  TokenToUpdate;
201   Status = gBS->OpenProtocol(
202                   Handle,
203                   &gEfiDriverBindingProtocolGuid,
204                   (VOID**)&BindHandle,
205                    NULL,
206                    NULL,
207                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
208                    );
209 
210   if (EFI_ERROR(Status)) {
211     return EFI_NOT_FOUND;
212   }
213 
214   Version = BindHandle->Version;
215   Ptr = (UINT16*)&Version;
GetGOPDriverName()216   UnicodeSPrint(Buffer, sizeof (Buffer), L"%d.%d.%d", Version >> 24 , (Version >>16)& 0x0f ,*(Ptr));
217 
218   TokenToUpdate = (STRING_REF)STR_MISC_GOP_VERSION;
219   HiiSetString(mHiiHandle, TokenToUpdate, Buffer, NULL);
220 
221   return EFI_SUCCESS;
222 }
223 
224 EFI_STATUS
225 GetGOPDriverName()
226 {
227   UINTN                         HandleCount;
228   EFI_HANDLE                *Handles= NULL;
229   UINTN                         Index;
230   EFI_STATUS                Status;
231   EFI_HANDLE                Child = 0;
232 
233   Status = gBS->LocateHandleBuffer(
234 		              ByProtocol,
235 		              &gEfiDriverBindingProtocolGuid,
236 		              NULL,
237 		              &HandleCount,
238 		              &Handles
239                   );
240 
241   for (Index = 0; Index < HandleCount ; Index++) {
242     Status = SearchChildHandle(Handles[Index], &Child);
243     if(!EFI_ERROR(Status)) {
244       Status = JudgeHandleIsPCIDevice(Child, 0x02, 0x00);
GetUcodeVersion()245       if(!EFI_ERROR(Status)) {
246         return GetDriverName(Handles[Index]);
247       }
248     }
249   }
250   return EFI_UNSUPPORTED;
251 }
252 
253 VOID
254 GetUcodeVersion()
255 {
256   UINT32                   MicroCodeVersion;
257   CHAR16                   Buffer[40];
258 
259   //
260   // Microcode Revision
261   //
262   EfiWriteMsr (EFI_MSR_IA32_BIOS_SIGN_ID, 0);
263   EfiCpuid (EFI_CPUID_VERSION_INFO, NULL);
264   MicroCodeVersion = (UINT32) RShiftU64 (EfiReadMsr (EFI_MSR_IA32_BIOS_SIGN_ID), 32);
265   UnicodeSPrint (Buffer, sizeof (Buffer), L"%x", MicroCodeVersion);
266   HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_UCODE_VERSION), Buffer, NULL);
267 }
268 
269 /**
270   Publish the smbios OEM type 0x90.
AddSmbiosT0x90Callback(IN EFI_EVENT Event,IN VOID * Context)271 
272   @param Event   - Event whose notification function is being invoked (gEfiDxeSmmReadyToLockProtocolGuid).
273   @param Context - Pointer to the notification functions context, which is implementation dependent.
274 
275   @retval None
276 
277 **/
278 EFI_STATUS
279 EFIAPI
280 AddSmbiosT0x90Callback (
281   IN EFI_EVENT  Event,
282   IN VOID       *Context
283   )
284 {
285   EFI_STATUS            Status;
286   UINTN                 SECVerStrLen = 0;
287   UINTN                 uCodeVerStrLen = 0;
288   UINTN                 GOPStrLen = 0;
289   UINTN                 SteppingStrLen = 0;
290   SMBIOS_TABLE_TYPE90    *SmbiosRecord;
291   EFI_SMBIOS_HANDLE     SmbiosHandle;
292   EFI_MISC_OEM_TYPE_0x90  *ForType90InputData;
293   CHAR16                *SECVer;
294   CHAR16                *uCodeVer;
295   CHAR16                *GOPVer;
296   CHAR16                *Stepping;
297   STRING_REF            TokenToGet;
298   CHAR8                 *OptionalStrStart;
299   EFI_SMBIOS_PROTOCOL               *SmbiosProtocol;
300 
301   ForType90InputData        = (EFI_MISC_OEM_TYPE_0x90 *)Context;
302 
303   DEBUG ((EFI_D_INFO, "Executing SMBIOS T0x90 callback.\n"));
304 
305   gBS->CloseEvent (Event);    // Unload this event.
306 
307   //
308   // First check for invalid parameters.
309   //
310   if (Context == NULL) {
311     return EFI_INVALID_PARAMETER;
312   }
313 
314   Status = gBS->LocateProtocol (
315                   &gEfiSmbiosProtocolGuid,
316                   NULL,
317                   (VOID *) &SmbiosProtocol
318                   );
319   ASSERT_EFI_ERROR (Status);
320 
321   GetUcodeVersion();
322   GetGOPDriverName();
323   GetCPUStepping();
324 
325   TokenToGet = STRING_TOKEN (STR_MISC_SEC_VERSION);
326   SECVer = SmbiosMiscGetString (TokenToGet);
327   SECVerStrLen = StrLen(SECVer);
328   if (SECVerStrLen > SMBIOS_STRING_MAX_LENGTH) {
329     return EFI_UNSUPPORTED;
330   }
331 
332   TokenToGet = STRING_TOKEN (STR_MISC_UCODE_VERSION);
333   uCodeVer = SmbiosMiscGetString (TokenToGet);
334   uCodeVerStrLen = StrLen(uCodeVer);
335   if (uCodeVerStrLen > SMBIOS_STRING_MAX_LENGTH) {
336     return EFI_UNSUPPORTED;
337   }
338 
339   TokenToGet = STRING_TOKEN (STR_MISC_GOP_VERSION);
340   GOPVer = SmbiosMiscGetString (TokenToGet);
341   GOPStrLen = StrLen(GOPVer);
342   if (GOPStrLen > SMBIOS_STRING_MAX_LENGTH) {
343     return EFI_UNSUPPORTED;
344   }
345 
346   TokenToGet = STRING_TOKEN (STR_MISC_PROCESSOR_STEPPING);
347   Stepping = SmbiosMiscGetString (TokenToGet);
348   SteppingStrLen = StrLen(Stepping);
349 
350 
351   if (SteppingStrLen > SMBIOS_STRING_MAX_LENGTH) {
352     return EFI_UNSUPPORTED;
353   }
354 
355   SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE90) + SECVerStrLen + 1 + uCodeVerStrLen + 1 + GOPStrLen + 1 + SteppingStrLen + 1 + 1);
356   ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE90) + SECVerStrLen + 1 + uCodeVerStrLen + 1 + GOPStrLen + 1 + SteppingStrLen + 1 + 1);
357 
358   SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_FIRMWARE_VERSION_INFO;
359   SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE90);
360 
361   //
362   // Make handle chosen by smbios protocol.add automatically.
363   //
364   SmbiosRecord->Hdr.Handle = 0;
365 
366   //
367   // SEC VERSION will be the 1st optional string following the formatted structure.
368   //
369   SmbiosRecord->SECVersion = 0;
370 
371   //
372   // Microcode VERSION will be the 2nd optional string following the formatted structure.
373   //
374   SmbiosRecord->uCodeVersion = 2;
375 
376   //
377   // GOP VERSION will be the 3rd optional string following the formatted structure.
378   //
379   SmbiosRecord->GOPVersion = 3;
380 
381   //
382   // CPU Stepping will be the 4th optional string following the formatted structure.
383   //
384   SmbiosRecord->CpuStepping = 4;
385 
386   OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
387   UnicodeStrToAsciiStr(SECVer, OptionalStrStart);
388   UnicodeStrToAsciiStr(uCodeVer, OptionalStrStart + SECVerStrLen + 1);
389   UnicodeStrToAsciiStr(GOPVer, OptionalStrStart + SECVerStrLen + 1 + uCodeVerStrLen + 1);
390   UnicodeStrToAsciiStr(Stepping, OptionalStrStart + SECVerStrLen + 1 + uCodeVerStrLen + 1 + GOPStrLen + 1);
391 
392   //
393   // Now we have got the full smbios record, call smbios protocol to add this record.
394   //
395   SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
396   Status = SmbiosProtocol-> Add(
397                               SmbiosProtocol,
398                               NULL,
399                               &SmbiosHandle,
400                               (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord
401                               );
402 
403   FreePool(SmbiosRecord);
404   return Status;
405 }
406 
407 
408 /**
409   This function makes boot time changes to the contents of the
MISC_SMBIOS_TABLE_FUNCTION(MiscOemType0x90)410   MiscOemType0x90 (Type 0x90).
411 
412   @param  RecordData                 Pointer to copy of RecordData from the Data Table.
413 
414   @retval EFI_SUCCESS                All parameters were valid.
415   @retval EFI_UNSUPPORTED            Unexpected RecordType value.
416   @retval EFI_INVALID_PARAMETER      Invalid parameter was found.
417 
418 **/
419 MISC_SMBIOS_TABLE_FUNCTION(MiscOemType0x90)
420 {
421   EFI_STATUS                    Status;
422   static BOOLEAN                CallbackIsInstalledT0x90 = FALSE;
423   VOID                           *AddSmbiosT0x90CallbackNotifyReg;
424   EFI_EVENT                      AddSmbiosT0x90CallbackEvent;
425 
426   //
427   // This callback will create a OEM Type 0x90 record.
428   //
429   if (CallbackIsInstalledT0x90 == FALSE) {
430     CallbackIsInstalledT0x90 = TRUE;        	// Prevent more than 1 callback.
431     DEBUG ((EFI_D_INFO, "Create Smbios T0x90 callback.\n"));
432 
433   //
434   // gEfiDxeSmmReadyToLockProtocolGuid is ready
435   //
436   Status = gBS->CreateEvent (
437                   EVT_NOTIFY_SIGNAL,
438                   TPL_CALLBACK,
439                   (EFI_EVENT_NOTIFY)AddSmbiosT0x90Callback,
440                   RecordData,
441                   &AddSmbiosT0x90CallbackEvent
442                   );
443 
444   ASSERT_EFI_ERROR (Status);
445   if (EFI_ERROR (Status)) {
446     return Status;
447 
448   }
449 
450   Status = gBS->RegisterProtocolNotify (
451                   &gEfiDxeSmmReadyToLockProtocolGuid,
452                   AddSmbiosT0x90CallbackEvent,
453                   &AddSmbiosT0x90CallbackNotifyReg
454                   );
455 
456   return Status;
457   }
458 
459   return EFI_SUCCESS;
460 
461 }
462