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