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