]> git.proxmox.com Git - mirror_edk2.git/blame - Vlv2TbltDevicePkg/VlvPlatformInitDxe/IgdOpRegion.c
Vlv2TbltDevicePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / Vlv2TbltDevicePkg / VlvPlatformInitDxe / IgdOpRegion.c
CommitLineData
3cbfba02
DW
1\r
2/*++\r
3\r
a4712bea 4Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved\r
3cbfba02 5 \r\r
9dc8036d
MK
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
3cbfba02
DW
8 \r\r
9\r
10\r
11Module Name:\r
12\r
13 IgdOpRegion.c\r
14\r
15Abstract:\r
16\r
17 This is part of the implementation of an Intel Graphics drivers OpRegion /\r
18 Software SCI interface between system BIOS, ASL code, and Graphics drivers.\r
19 The code in this file will load the driver and initialize the interface\r
20\r
21 Supporting Specifiction: OpRegion / Software SCI SPEC 0.70\r
22\r
23 Acronyms:\r
24 IGD: Internal Graphics Device\r
25 NVS: ACPI Non Volatile Storage\r
26 OpRegion: ACPI Operational Region\r
27 VBT: Video BIOS Table (OEM customizable data)\r
28\r
29--*/\r
30\r
31//\r
32// Include files\r
33//\r
34\r
35\r
36#include "IgdOpRegion.h"\r
37#include "VlvPlatformInit.h"\r
38#include <FrameworkDxe.h>\r
39#include <Uefi.h>\r
40#include <PchRegs.h>\r
41\r
42#include <Guid/DataHubRecords.h>\r
43\r
44#include <Protocol/IgdOpRegion.h>\r
45#include <Protocol/FrameworkHii.h>\r
a4712bea 46#include <Protocol/FirmwareVolume2.h>\r
3cbfba02
DW
47#include <Protocol/PlatformGopPolicy.h>\r
48#include <Protocol/PciIo.h>\r
49#include <Protocol/CpuIo.h>\r
50#include <Protocol/GlobalNvsArea.h>\r
51#include <Protocol/DxeSmmReadyToLock.h>\r
52#include <Protocol/PciRootBridgeIo.h>\r
53\r
54#include <Library/MemoryAllocationLib.h>\r
55#include <Library/BaseLib.h>\r
56#include <Library/S3BootScriptLib.h>\r
57#include <Library/IoLib.h>\r
58#include <Library/DevicePathLib.h>\r
59#include <Protocol/DriverBinding.h>\r
60#include <Library/PrintLib.h>\r
61#include <Library/BaseMemoryLib.h>\r
62\r
63\r
64\r
65UINT8 gSVER[12] = "Intel";\r
66\r
67extern DXE_VLV_PLATFORM_POLICY_PROTOCOL *DxePlatformSaPolicy;\r
68\r
69//\r
70// Global variables\r
71//\r
72\r
73IGD_OPREGION_PROTOCOL mIgdOpRegion;\r
74EFI_GUID mMiscSubClass = EFI_MISC_SUBCLASS_GUID;\r
75EFI_EVENT mConOutEvent;\r
76EFI_EVENT mSetGOPverEvent;\r
77VOID *mConOutReg;\r
78\r
79#define DEFAULT_FORM_BUFFER_SIZE 0xFFFF\r
80#ifndef ECP_FLAG\r
81#if 0\r
82/**\r
83\r
84 Get the HII protocol interface\r
85\r
86 @param Hii HII protocol interface\r
87\r
88 @retval Status code\r
89\r
90**/\r
91static\r
92EFI_STATUS\r
93GetHiiInterface (\r
94 OUT EFI_HII_PROTOCOL **Hii\r
95 )\r
96{\r
97 EFI_STATUS Status;\r
98\r
99 //\r
100 // There should only be one HII protocol\r
101 //\r
102 Status = gBS->LocateProtocol (\r
103 &gEfiHiiProtocolGuid,\r
104 NULL,\r
105 (VOID **) Hii\r
106 );\r
107\r
108 return Status;;\r
109}\r
110#endif\r
111#endif\r
112\r
113/**\r
114\r
115 Get VBT data.\r
116\r
117 @param[in] VbtFileBuffer Pointer to VBT data buffer.\r
118\r
119 @retval EFI_SUCCESS VBT data was returned.\r
120 @retval EFI_NOT_FOUND VBT data not found.\r
121 @exception EFI_UNSUPPORTED Invalid signature in VBT data.\r
122\r
123**/\r
124EFI_STATUS\r
125GetIntegratedIntelVbtPtr (\r
126 OUT VBIOS_VBT_STRUCTURE **VbtFileBuffer\r
127 )\r
128{\r
129 EFI_STATUS Status;\r
130 EFI_PHYSICAL_ADDRESS VbtAddress = 0;\r
3cbfba02
DW
131 UINTN FvProtocolCount;\r
132 EFI_HANDLE *FvHandles;\r
a4712bea 133 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
3cbfba02
DW
134 UINTN Index;\r
135 UINT32 AuthenticationStatus;\r
136\r
137 UINT8 *Buffer;\r
138 UINTN VbtBufferSize = 0;\r
139\r
140 Buffer = 0;\r
141 FvHandles = NULL;\r
142 *VbtFileBuffer = NULL;\r
143 Status = gBS->LocateHandleBuffer (\r
144 ByProtocol,\r
a4712bea 145 &gEfiFirmwareVolume2ProtocolGuid,\r
3cbfba02
DW
146 NULL,\r
147 &FvProtocolCount,\r
148 &FvHandles\r
149 );\r
150\r
151 if (!EFI_ERROR (Status)) {\r
152 for (Index = 0; Index < FvProtocolCount; Index++) {\r
153 Status = gBS->HandleProtocol (\r
154 FvHandles[Index],\r
a4712bea 155 &gEfiFirmwareVolume2ProtocolGuid,\r
3cbfba02
DW
156 (VOID **) &Fv\r
157 );\r
158 VbtBufferSize = 0;\r
159 Status = Fv->ReadSection (\r
160 Fv,\r
161 &gBmpImageGuid,\r
162 EFI_SECTION_RAW,\r
163 0,\r
164 (void **)&Buffer,\r
165 &VbtBufferSize,\r
166 &AuthenticationStatus\r
167 );\r
168\r
169 if (!EFI_ERROR (Status)) {\r
170 VbtAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer;\r
3cbfba02
DW
171 Status = EFI_SUCCESS;\r
172 break;\r
173 }\r
174 }\r
175 } else {\r
176 Status = EFI_NOT_FOUND;\r
177 }\r
178\r
179 if (FvHandles != NULL) {\r
180 FreePool(FvHandles);\r
181 FvHandles = NULL;\r
182 }\r
183\r
184\r
185 //\r
186 // Check VBT signature\r
187 //\r
188 *VbtFileBuffer = (VBIOS_VBT_STRUCTURE *) (UINTN) VbtAddress;\r
189 if (*VbtFileBuffer != NULL) {\r
190 if ((*((UINT32 *) ((*VbtFileBuffer)->HeaderSignature))) != VBT_SIGNATURE) {\r
191 if (*VbtFileBuffer != NULL) {\r
192 *VbtFileBuffer = NULL;\r
193 }\r
194 return EFI_UNSUPPORTED;\r
195 }\r
196 //\r
197 // Check VBT size\r
198 //\r
199 if ((*VbtFileBuffer)->HeaderVbtSize > VbtBufferSize) {\r
200 (*VbtFileBuffer)->HeaderVbtSize = (UINT16) VbtBufferSize;\r
201 }\r
202 }\r
203\r
204 return EFI_SUCCESS;\r
205}\r
206\r
207//\r
208// Function implementations.\r
209//\r
210/**\r
211\r
212 Get a pointer to an uncompressed image of the Intel video BIOS.\r
213\r
214 Note: This function would only be called if the video BIOS at 0xC000 is\r
215 missing or not an Intel video BIOS. It may not be an Intel video BIOS\r
216 if the Intel graphic contoller is considered a secondary adapter.\r
217\r
218\r
219 @param VBiosROMImage Pointer to an uncompressed Intel video BIOS. This pointer must\r
220 be set to NULL if an uncompressed image of the Intel Video BIOS\r
221 is not obtainable.\r
222\r
223\r
224 @retval EFI_SUCCESS VBiosPtr is updated.\r
225\r
226**/\r
227EFI_STATUS\r
228GetIntegratedIntelVBiosPtr (\r
229 INTEL_VBIOS_OPTION_ROM_HEADER **VBiosImage\r
230 )\r
231{\r
232 EFI_HANDLE *HandleBuffer;\r
233 UINTN HandleCount;\r
234 UINTN Index;\r
235 INTEL_VBIOS_PCIR_STRUCTURE *PcirBlockPtr;\r
236 EFI_STATUS Status;\r
237 EFI_PCI_IO_PROTOCOL *PciIo;\r
238 INTEL_VBIOS_OPTION_ROM_HEADER *VBiosRomImage;\r
239\r
240 //\r
241 // Set as if an umcompressed Intel video BIOS image was not obtainable.\r
242 //\r
243 VBiosRomImage = NULL;\r
244 *VBiosImage = NULL;\r
245\r
246 //\r
247 // Get all PCI IO protocols\r
248 //\r
249 Status = gBS->LocateHandleBuffer (\r
250 ByProtocol,\r
251 &gEfiPciIoProtocolGuid,\r
252 NULL,\r
253 &HandleCount,\r
254 &HandleBuffer\r
255 );\r
256 ASSERT_EFI_ERROR (Status);\r
257\r
258 //\r
259 // Find the video BIOS by checking each PCI IO handle for an Intel video\r
260 // BIOS OPROM.\r
261 //\r
262 for (Index = 0; Index < HandleCount; Index++) {\r
263 Status = gBS->HandleProtocol (\r
264 HandleBuffer[Index],\r
265 &gEfiPciIoProtocolGuid,\r
266 (void **)&PciIo\r
267 );\r
268 ASSERT_EFI_ERROR (Status);\r
269\r
270 VBiosRomImage = PciIo->RomImage;\r
271\r
272 //\r
273 // If this PCI device doesn't have a ROM image, skip to the next device.\r
274 //\r
275 if (!VBiosRomImage) {\r
276 continue;\r
277 }\r
278\r
279 //\r
280 // Get pointer to PCIR structure\r
281 //\r
282 PcirBlockPtr = (INTEL_VBIOS_PCIR_STRUCTURE *)((UINT8 *) VBiosRomImage + VBiosRomImage->PcirOffset);\r
283\r
284 //\r
285 // Check if we have an Intel video BIOS OPROM.\r
286 //\r
287 if ((VBiosRomImage->Signature == OPTION_ROM_SIGNATURE) &&\r
288 (PcirBlockPtr->VendorId == IGD_VID) &&\r
289 (PcirBlockPtr->ClassCode[0] == 0x00) &&\r
290 (PcirBlockPtr->ClassCode[1] == 0x00) &&\r
291 (PcirBlockPtr->ClassCode[2] == 0x03)\r
292 ) {\r
293 //\r
294 // Found Intel video BIOS.\r
295 //\r
296 *VBiosImage = VBiosRomImage;\r
297 return EFI_SUCCESS;\r
298 }\r
299 }\r
300\r
301 //\r
302 // No Intel video BIOS found.\r
303 //\r
304\r
305 //\r
306 // Free any allocated buffers\r
307 //\r
308 return EFI_UNSUPPORTED;\r
309}\r
310\r
311EFI_STATUS\r
312SearchChildHandle(\r
313 EFI_HANDLE Father,\r
314 EFI_HANDLE *Child\r
315 )\r
316{\r
317 EFI_STATUS Status;\r
318 UINTN HandleIndex;\r
319 EFI_GUID **ProtocolGuidArray = NULL;\r
320 UINTN ArrayCount;\r
321 UINTN ProtocolIndex;\r
322 UINTN OpenInfoCount;\r
323 UINTN OpenInfoIndex;\r
324 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo = NULL;\r
325 UINTN mHandleCount;\r
326 EFI_HANDLE *mHandleBuffer= NULL;\r
327\r
328 //\r
329 // Retrieve the list of all handles from the handle database\r
330 //\r
331 Status = gBS->LocateHandleBuffer (\r
332 AllHandles,\r
333 NULL,\r
334 NULL,\r
335 &mHandleCount,\r
336 &mHandleBuffer\r
337 );\r
338\r
339 for (HandleIndex = 0; HandleIndex < mHandleCount; HandleIndex++) {\r
340 //\r
341 // Retrieve the list of all the protocols on each handle\r
342 //\r
343 Status = gBS->ProtocolsPerHandle (\r
344 mHandleBuffer[HandleIndex],\r
345 &ProtocolGuidArray,\r
346 &ArrayCount\r
347 );\r
348 if (!EFI_ERROR (Status)) {\r
349 for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {\r
350 Status = gBS->OpenProtocolInformation (\r
351 mHandleBuffer[HandleIndex],\r
352 ProtocolGuidArray[ProtocolIndex],\r
353 &OpenInfo,\r
354 &OpenInfoCount\r
355 );\r
356 if (!EFI_ERROR (Status)) {\r
357 for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {\r
358 if(OpenInfo[OpenInfoIndex].AgentHandle == Father) {\r
359 if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {\r
360 *Child = mHandleBuffer[HandleIndex];\r
361 Status = EFI_SUCCESS;\r
362 goto TryReturn;\r
363 }\r
364 }\r
365 }\r
366 Status = EFI_NOT_FOUND;\r
367 }\r
368 }\r
369 if(OpenInfo != NULL) {\r
370 FreePool(OpenInfo);\r
371 OpenInfo = NULL;\r
372 }\r
373 }\r
374 FreePool (ProtocolGuidArray);\r
375 ProtocolGuidArray = NULL;\r
376 }\r
377TryReturn:\r
378 if(OpenInfo != NULL) {\r
379 FreePool (OpenInfo);\r
380 OpenInfo = NULL;\r
381 }\r
382 if(ProtocolGuidArray != NULL) {\r
383 FreePool(ProtocolGuidArray);\r
384 ProtocolGuidArray = NULL;\r
385 }\r
386 if(mHandleBuffer != NULL) {\r
387 FreePool (mHandleBuffer);\r
388 mHandleBuffer = NULL;\r
389 }\r
390 return Status;\r
391}\r
392\r
393EFI_STATUS\r
394JudgeHandleIsPCIDevice(\r
395 EFI_HANDLE Handle,\r
396 UINT8 Device,\r
397 UINT8 Funs\r
398 )\r
399{\r
400 EFI_STATUS Status;\r
401 EFI_DEVICE_PATH *DPath;\r
3cbfba02
DW
402\r
403 Status = gBS->HandleProtocol (\r
404 Handle,\r
405 &gEfiDevicePathProtocolGuid,\r
406 (VOID **) &DPath\r
407 );\r
408 if(!EFI_ERROR(Status)) {\r
3cbfba02
DW
409 while(!IsDevicePathEnd(DPath)) {\r
410 if((DPath->Type == HARDWARE_DEVICE_PATH) && (DPath->SubType == HW_PCI_DP)) {\r
411 PCI_DEVICE_PATH *PCIPath;\r
412\r
413 PCIPath = (PCI_DEVICE_PATH*) DPath;\r
414 DPath = NextDevicePathNode(DPath);\r
415 if(IsDevicePathEnd(DPath) && (PCIPath->Device == Device) && (PCIPath->Function == Funs)) {\r
416 return EFI_SUCCESS;\r
417 }\r
418 } else {\r
419 DPath = NextDevicePathNode(DPath);\r
420 }\r
421 }\r
422 }\r
423 return EFI_UNSUPPORTED;\r
424}\r
425\r
426EFI_STATUS\r
427GetDriverName(\r
428 EFI_HANDLE Handle,\r
429 CHAR16 *GopVersion\r
430 )\r
431{\r
432 EFI_DRIVER_BINDING_PROTOCOL *BindHandle = NULL;\r
433 EFI_STATUS Status;\r
434 UINT32 Version;\r
435 UINT16 *Ptr;\r
436\r
437 Status = gBS->OpenProtocol(\r
438 Handle,\r
439 &gEfiDriverBindingProtocolGuid,\r
440 (VOID**)&BindHandle,\r
441 NULL,\r
442 NULL,\r
443 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
444 );\r
445 if (EFI_ERROR(Status)) {\r
446 return EFI_NOT_FOUND;\r
447 }\r
448\r
449 Version = BindHandle->Version;\r
450 Ptr = (UINT16*)&Version;\r
451 UnicodeSPrint(GopVersion, 40, L"7.0.%04d", *(Ptr));\r
452 return EFI_SUCCESS;\r
453}\r
454\r
455EFI_STATUS\r
456GetGOPDriverVersion(\r
457 CHAR16 *GopVersion\r
458 )\r
459{\r
460 UINTN HandleCount;\r
461 EFI_HANDLE *Handles= NULL;\r
462 UINTN Index;\r
463 EFI_STATUS Status;\r
464 EFI_HANDLE Child = 0;\r
465\r
466 Status = gBS->LocateHandleBuffer(\r
467 ByProtocol,\r
468 &gEfiDriverBindingProtocolGuid,\r
469 NULL,\r
470 &HandleCount,\r
471 &Handles\r
472 );\r
473 for (Index = 0; Index < HandleCount ; Index++) {\r
474 Status = SearchChildHandle(Handles[Index], &Child);\r
475 if(!EFI_ERROR(Status)) {\r
476 Status = JudgeHandleIsPCIDevice(Child, 0x02, 0x00);\r
477 if(!EFI_ERROR(Status)) {\r
478 return GetDriverName(Handles[Index], GopVersion);\r
479 }\r
480 }\r
481 }\r
482 return EFI_UNSUPPORTED;\r
483}\r
484\r
485\r
486/**\r
487 Get Intel GOP driver version and copy it into IGD OpRegion GVER. This version\r
488 is picked up by IGD driver and displayed in CUI.\r
489\r
490 @param Event A pointer to the Event that triggered the callback.\r
491 @param Context A pointer to private data registered with the callback function.\r
492\r
493 @retval EFI_SUCCESS Video BIOS VBT information returned.\r
494 @retval EFI_UNSUPPORTED Could not find VBT information (*VBiosVbtPtr = NULL).\r
495\r
496**/\r
497EFI_STATUS\r
498EFIAPI\r
499SetGOPVersionCallback (\r
500 IN EFI_EVENT Event,\r
501 IN VOID *Context\r
502 )\r
503{\r
504 CHAR16 GopVersion[16] = {0};\r
505 EFI_STATUS Status;\r
506\r
507 Status = GetGOPDriverVersion(GopVersion);\r
508 if(!EFI_ERROR(Status)) {\r
509 StrCpy((CHAR16*)&(mIgdOpRegion.OpRegion->Header.GOPV[0]), GopVersion);\r
510 return Status;\r
511 }\r
512 return EFI_UNSUPPORTED;\r
513}\r
514\r
515/**\r
516 Get Intel video BIOS VBT information (i.e. Pointer to VBT and VBT size).\r
517 The VBT (Video BIOS Table) is a block of customizable data that is built\r
518 within the video BIOS and edited by customers.\r
519\r
520 @param Event A pointer to the Event that triggered the callback.\r
521 @param Context A pointer to private data registered with the callback function.\r
522\r
523 @retval EFI_SUCCESS Video BIOS VBT information returned.\r
524 @retval EFI_UNSUPPORTED Could not find VBT information (*VBiosVbtPtr = NULL).\r
525\r
526**/\r
527EFI_STATUS\r
528GetVBiosVbtCallback (\r
529 IN EFI_EVENT Event,\r
530 IN VOID *Context\r
531 )\r
532{\r
533 INTEL_VBIOS_PCIR_STRUCTURE *PcirBlockPtr;\r
534 UINT16 PciVenderId;\r
535 UINT16 PciDeviceId;\r
536 INTEL_VBIOS_OPTION_ROM_HEADER *VBiosPtr;\r
537 VBIOS_VBT_STRUCTURE *VBiosVbtPtr;\r
538 VBIOS_VBT_STRUCTURE *VbtFileBuffer = NULL;\r
539\r
540 VBiosPtr = (INTEL_VBIOS_OPTION_ROM_HEADER *)(UINTN)(VBIOS_LOCATION_PRIMARY);\r
541 PcirBlockPtr = (INTEL_VBIOS_PCIR_STRUCTURE *)((UINT8 *)VBiosPtr + VBiosPtr->PcirOffset);\r
542 PciVenderId = PcirBlockPtr->VendorId;\r
543 PciDeviceId = PcirBlockPtr->DeviceId;\r
544\r
545 //\r
546 // If the video BIOS is not at 0xC0000 or it is not an Intel video BIOS get\r
547 // the integrated Intel video BIOS (must be uncompressed).\r
548 //\r
549 if ((VBiosPtr->Signature != OPTION_ROM_SIGNATURE) || (PciVenderId != IGD_VID) || (PciDeviceId != IGD_DID_VLV)) {\r
550 GetIntegratedIntelVBiosPtr (&VBiosPtr);\r
551\r
552 if(VBiosPtr) {\r
553 //\r
554 // Video BIOS found.\r
555 //\r
556 PcirBlockPtr = (INTEL_VBIOS_PCIR_STRUCTURE *)((UINT8 *)VBiosPtr + VBiosPtr->PcirOffset);\r
557 PciVenderId = PcirBlockPtr->VendorId;\r
558 if( (VBiosPtr->Signature != OPTION_ROM_SIGNATURE) || (PciVenderId != IGD_VID)) {\r
559 //\r
560 // Intel video BIOS not found.\r
561 //\r
562 VBiosVbtPtr = NULL;\r
563 return EFI_UNSUPPORTED;\r
564 }\r
565 } else {\r
566 //\r
567 // No Video BIOS found, try to get VBT from FV.\r
568 //\r
569 GetIntegratedIntelVbtPtr (&VbtFileBuffer);\r
570 if (VbtFileBuffer != NULL) {\r
571 //\r
572 // Video BIOS not found, use VBT from FV\r
573 //\r
574 DEBUG ((EFI_D_ERROR, "VBT data found\n"));\r
575 (gBS->CopyMem) (\r
576 mIgdOpRegion.OpRegion->VBT.GVD1,\r
577 VbtFileBuffer,\r
578 VbtFileBuffer->HeaderVbtSize\r
579 );\r
580 FreePool (VbtFileBuffer);\r
581 return EFI_SUCCESS;\r
582 }\r
583 }\r
584 if ((VBiosPtr == NULL) ) {\r
585 //\r
586 // Intel video BIOS not found.\r
587 //\r
588 VBiosVbtPtr = NULL;\r
589 return EFI_UNSUPPORTED;\r
590 }\r
591 }\r
592\r
593 DEBUG ((EFI_D_ERROR, "VBIOS found at 0x%X\n", VBiosPtr));\r
594 VBiosVbtPtr = (VBIOS_VBT_STRUCTURE *) ((UINT8 *) VBiosPtr + VBiosPtr->VbtOffset);\r
595\r
596 if ((*((UINT32 *) (VBiosVbtPtr->HeaderSignature))) != VBT_SIGNATURE) {\r
597 return EFI_UNSUPPORTED;\r
598 }\r
599\r
600 //\r
601 // Initialize Video BIOS version with its build number.\r
602 //\r
603 mIgdOpRegion.OpRegion->Header.VVER[0] = VBiosVbtPtr->CoreBlockBiosBuild[0];\r
604 mIgdOpRegion.OpRegion->Header.VVER[1] = VBiosVbtPtr->CoreBlockBiosBuild[1];\r
605 mIgdOpRegion.OpRegion->Header.VVER[2] = VBiosVbtPtr->CoreBlockBiosBuild[2];\r
606 mIgdOpRegion.OpRegion->Header.VVER[3] = VBiosVbtPtr->CoreBlockBiosBuild[3];\r
607 (gBS->CopyMem) (\r
608 mIgdOpRegion.OpRegion->VBT.GVD1,\r
609 VBiosVbtPtr,\r
610 VBiosVbtPtr->HeaderVbtSize\r
611 );\r
612\r
613 //\r
614 // Return final status\r
615 //\r
616 return EFI_SUCCESS;\r
617}\r
618\r
619/**\r
620 Graphics OpRegion / Software SCI driver installation function.\r
621\r
622 @param ImageHandle Handle for this drivers loaded image protocol.\r
623 @param SystemTable EFI system table.\r
624\r
625 @retval EFI_SUCCESS The driver installed without error.\r
626 @retval EFI_ABORTED The driver encountered an error and could not complete\r
627 installation of the ACPI tables.\r
628\r
629**/\r
630EFI_STATUS\r
631IgdOpRegionInit (\r
632 void\r
633 )\r
634{\r
635 EFI_HANDLE Handle;\r
636 EFI_STATUS Status;\r
637 EFI_GLOBAL_NVS_AREA_PROTOCOL *GlobalNvsArea;\r
638 UINT32 DwordData;\r
639 EFI_CPU_IO_PROTOCOL *CpuIo;\r
640 UINT16 Data16;\r
641 UINT16 AcpiBase;\r
642 VOID *gConOutNotifyReg;\r
643\r
644\r
645 //\r
646 // Locate the Global NVS Protocol.\r
647 //\r
648 Status = gBS->LocateProtocol (\r
649 &gEfiGlobalNvsAreaProtocolGuid,\r
650 NULL,\r
651 (void **)&GlobalNvsArea\r
652 );\r
653 ASSERT_EFI_ERROR (Status);\r
654\r
655 //\r
656 // Allocate an ACPI NVS memory buffer as the IGD OpRegion, zero initialize\r
657 // the first 1K, and set the IGD OpRegion pointer in the Global NVS\r
658 // area structure.\r
659 //\r
660 Status = (gBS->AllocatePool) (\r
661 EfiACPIMemoryNVS,\r
662 sizeof (IGD_OPREGION_STRUC),\r
663 (void **)&mIgdOpRegion.OpRegion\r
664 );\r
665 ASSERT_EFI_ERROR (Status);\r
666 (gBS->SetMem) (\r
667 mIgdOpRegion.OpRegion,\r
668 sizeof (IGD_OPREGION_STRUC),\r
669 0\r
670 );\r
671 GlobalNvsArea->Area->IgdOpRegionAddress = (UINT32)(UINTN)(mIgdOpRegion.OpRegion);\r
672\r
673 //\r
674 // If IGD is disabled return\r
675 //\r
676 if (IgdMmPci32 (0) == 0xFFFFFFFF) {\r
677 return EFI_SUCCESS;\r
678 }\r
679\r
680 //\r
681 // Initialize OpRegion Header\r
682 //\r
683\r
684 (gBS->CopyMem) (\r
685 mIgdOpRegion.OpRegion->Header.SIGN,\r
686 HEADER_SIGNATURE,\r
687 sizeof(HEADER_SIGNATURE)\r
688 );\r
689\r
690\r
691 //\r
692 // Set OpRegion Size in KBs\r
693 //\r
694 mIgdOpRegion.OpRegion->Header.SIZE = HEADER_SIZE/1024;\r
695\r
696 //\r
697 // FIXME: Need to check Header OVER Field and the supported version.\r
698 //\r
699 mIgdOpRegion.OpRegion->Header.OVER = (UINT32) (LShiftU64 (HEADER_OPREGION_VER, 16) + LShiftU64 (HEADER_OPREGION_REV, 8));\r
700#ifdef ECP_FLAG\r
701 CopyMem(mIgdOpRegion.OpRegion->Header.SVER, gSVER, sizeof(gSVER));\r
702#else\r
703 gBS->CopyMem(\r
704 mIgdOpRegion.OpRegion->Header.SVER,\r
705 gSVER,\r
706 sizeof(gSVER)\r
707 );\r
708#endif\r
709 DEBUG ((EFI_D_ERROR, "System BIOS ID is %a\n", mIgdOpRegion.OpRegion->Header.SVER));\r
710\r
711\r
712 mIgdOpRegion.OpRegion->Header.MBOX = HEADER_MBOX_SUPPORT;\r
713\r
714 if( 1 == DxePlatformSaPolicy->IdleReserve) {\r
715 mIgdOpRegion.OpRegion->Header.PCON = (mIgdOpRegion.OpRegion->Header.PCON & 0xFFFC) | BIT1;\r
716 } else {\r
717 mIgdOpRegion.OpRegion->Header.PCON = (mIgdOpRegion.OpRegion->Header.PCON & 0xFFFC) | (BIT1 | BIT0);\r
718 }\r
719\r
720 //\r
721 //For graphics driver to identify if LPE Audio/HD Audio is enabled on the platform\r
722 //\r
723 mIgdOpRegion.OpRegion->Header.PCON &= AUDIO_TYPE_SUPPORT_MASK;\r
724 mIgdOpRegion.OpRegion->Header.PCON &= AUDIO_TYPE_FIELD_MASK;\r
725 if ( 1 == DxePlatformSaPolicy->AudioTypeSupport ) {\r
726 mIgdOpRegion.OpRegion->Header.PCON = HD_AUDIO_SUPPORT;\r
727 mIgdOpRegion.OpRegion->Header.PCON |= AUDIO_TYPE_FIELD_VALID;\r
728 }\r
729\r
730 //\r
731 // Initialize OpRegion Mailbox 1 (Public ACPI Methods).\r
732 //\r
733 //<TODO> The initial setting of mailbox 1 fields is implementation specific.\r
734 // Adjust them as needed many even coming from user setting in setup.\r
735 //\r
736 //Workaround to solve LVDS is off after entering OS in desktop platform\r
737 //\r
738 mIgdOpRegion.OpRegion->MBox1.CLID = DxePlatformSaPolicy->IgdPanelFeatures.LidStatus;\r
739\r
740 //\r
741 // Initialize OpRegion Mailbox 3 (ASLE Interrupt and Power Conservation).\r
742 //\r
743 //<TODO> The initial setting of mailbox 3 fields is implementation specific.\r
744 // Adjust them as needed many even coming from user setting in setup.\r
745 //\r
746\r
747 //\r
748 // Do not initialize TCHE. This field is written by the graphics driver only.\r
749 //\r
750\r
751 //\r
752 // The ALSI field is generally initialized by ASL code by reading the embedded controller.\r
753 //\r
754\r
755 mIgdOpRegion.OpRegion->MBox3.BCLP = BACKLIGHT_BRIGHTNESS;\r
756\r
757 mIgdOpRegion.OpRegion->MBox3.PFIT = (FIELD_VALID_BIT | PFIT_STRETCH);\r
758 if ( DxePlatformSaPolicy->IgdPanelFeatures.PFITStatus == 2) {\r
759 //\r
760 // Center\r
761 //\r
762 mIgdOpRegion.OpRegion->MBox3.PFIT = (FIELD_VALID_BIT | PFIT_CENTER);\r
763 } else if (DxePlatformSaPolicy->IgdPanelFeatures.PFITStatus == 1) {\r
764 //\r
765 // Stretch\r
766 //\r
767 mIgdOpRegion.OpRegion->MBox3.PFIT = (FIELD_VALID_BIT | PFIT_STRETCH);\r
768 } else {\r
769 //\r
770 // Auto\r
771 //\r
772 mIgdOpRegion.OpRegion->MBox3.PFIT = (FIELD_VALID_BIT | PFIT_SETUP_AUTO);\r
773 }\r
774\r
775 //\r
776 // Set Initial current Brightness\r
777 //\r
778 mIgdOpRegion.OpRegion->MBox3.CBLV = (INIT_BRIGHT_LEVEL | FIELD_VALID_BIT);\r
779\r
780 //\r
781 // <EXAMPLE> Create a static Backlight Brightness Level Duty cycle Mapping Table\r
782 // Possible 20 entries (example used 10), each 16 bits as follows:\r
783 // [15] = Field Valid bit, [14:08] = Level in Percentage (0-64h), [07:00] = Desired duty cycle (0 - FFh).\r
784 //\r
785 // % Brightness\r
786 mIgdOpRegion.OpRegion->MBox3.BCLM[0] = ( ( 0 << 8 ) + ( 0xFF - 0xFC ) + WORD_FIELD_VALID_BIT);\r
787 mIgdOpRegion.OpRegion->MBox3.BCLM[1] = ( ( 1 << 8 ) + ( 0xFF - 0xFC ) + WORD_FIELD_VALID_BIT);\r
788 mIgdOpRegion.OpRegion->MBox3.BCLM[2] = ( ( 10 << 8 ) + ( 0xFF - 0xE5 ) + WORD_FIELD_VALID_BIT);\r
789 mIgdOpRegion.OpRegion->MBox3.BCLM[3] = ( ( 19 << 8 ) + ( 0xFF - 0xCE ) + WORD_FIELD_VALID_BIT);\r
790 mIgdOpRegion.OpRegion->MBox3.BCLM[4] = ( ( 28 << 8 ) + ( 0xFF - 0xB7 ) + WORD_FIELD_VALID_BIT);\r
791 mIgdOpRegion.OpRegion->MBox3.BCLM[5] = ( ( 37 << 8 ) + ( 0xFF - 0xA0 ) + WORD_FIELD_VALID_BIT);\r
792 mIgdOpRegion.OpRegion->MBox3.BCLM[6] = ( ( 46 << 8 ) + ( 0xFF - 0x89 ) + WORD_FIELD_VALID_BIT);\r
793 mIgdOpRegion.OpRegion->MBox3.BCLM[7] = ( ( 55 << 8 ) + ( 0xFF - 0x72 ) + WORD_FIELD_VALID_BIT);\r
794 mIgdOpRegion.OpRegion->MBox3.BCLM[8] = ( ( 64 << 8 ) + ( 0xFF - 0x5B ) + WORD_FIELD_VALID_BIT);\r
795 mIgdOpRegion.OpRegion->MBox3.BCLM[9] = ( ( 73 << 8 ) + ( 0xFF - 0x44 ) + WORD_FIELD_VALID_BIT);\r
796 mIgdOpRegion.OpRegion->MBox3.BCLM[10] = ( ( 82 << 8 ) + ( 0xFF - 0x2D ) + WORD_FIELD_VALID_BIT);\r
797 mIgdOpRegion.OpRegion->MBox3.BCLM[11] = ( ( 91 << 8 ) + ( 0xFF - 0x16 ) + WORD_FIELD_VALID_BIT);\r
798 mIgdOpRegion.OpRegion->MBox3.BCLM[12] = ( (100 << 8 ) + ( 0xFF - 0x00 ) + WORD_FIELD_VALID_BIT);\r
799\r
800 mIgdOpRegion.OpRegion->MBox3.PCFT = ((UINT32) GlobalNvsArea->Area->IgdPowerConservation) | BIT31;\r
801 //\r
802 // Create the notification and register callback function on the PciIo installation,\r
803 //\r
804 //\r
805 Status = gBS->CreateEvent (\r
806 EVT_NOTIFY_SIGNAL,\r
807 TPL_CALLBACK,\r
808 (EFI_EVENT_NOTIFY)GetVBiosVbtCallback,\r
809 NULL,\r
810 &mConOutEvent\r
811 );\r
812\r
813 ASSERT_EFI_ERROR (Status);\r
814 if (EFI_ERROR (Status)) {\r
815 return Status;\r
816\r
817 }\r
818\r
819 Status = gBS->RegisterProtocolNotify (\r
820#ifdef ECP_FLAG\r
821 &gExitPmAuthProtocolGuid,\r
822#else\r
823 &gEfiDxeSmmReadyToLockProtocolGuid,\r
824#endif\r
825 mConOutEvent,\r
826 &gConOutNotifyReg\r
827 );\r
828\r
829 Status = gBS->CreateEvent (\r
830 EVT_NOTIFY_SIGNAL,\r
831 TPL_CALLBACK,\r
832 (EFI_EVENT_NOTIFY)SetGOPVersionCallback,\r
833 NULL,\r
834 &mSetGOPverEvent\r
835 );\r
836\r
837 ASSERT_EFI_ERROR (Status);\r
838 if (EFI_ERROR (Status)) {\r
839 return Status;\r
840 }\r
841\r
842 Status = gBS->RegisterProtocolNotify (\r
843 &gEfiGraphicsOutputProtocolGuid,\r
844 mSetGOPverEvent,\r
845 &gConOutNotifyReg\r
846 );\r
847\r
848\r
849 //\r
850 // Initialize hardware state:\r
851 // Set ASLS Register to the OpRegion physical memory address.\r
852 // Set SWSCI register bit 15 to a "1" to activate SCI interrupts.\r
853 //\r
854\r
855 IgdMmPci32 (IGD_ASLS_OFFSET) = (UINT32)(UINTN)(mIgdOpRegion.OpRegion);\r
856 IgdMmPci16AndThenOr (IGD_SWSCI_OFFSET, ~(BIT0), BIT15);\r
857\r
858 DwordData = IgdMmPci32 (IGD_ASLS_OFFSET);\r
859 S3BootScriptSavePciCfgWrite (\r
860 S3BootScriptWidthUint32,\r
861 (UINTN) (EFI_PCI_ADDRESS (IGD_BUS, IGD_DEV, IGD_FUN_0, IGD_ASLS_OFFSET)),\r
862 1,\r
863 &DwordData\r
864 );\r
865\r
866\r
867 DwordData = IgdMmPci32 (IGD_SWSCI_OFFSET);\r
868 S3BootScriptSavePciCfgWrite (\r
869 S3BootScriptWidthUint32,\r
870 (UINTN) (EFI_PCI_ADDRESS (IGD_BUS, IGD_DEV, IGD_FUN_0, IGD_SWSCI_OFFSET)),\r
871 1,\r
872 &DwordData\r
873 );\r
874\r
875 AcpiBase = MmPci16 (\r
876 0,\r
877 DEFAULT_PCI_BUS_NUMBER_PCH,\r
878 PCI_DEVICE_NUMBER_PCH_LPC,\r
879 PCI_FUNCTION_NUMBER_PCH_LPC,\r
880 R_PCH_LPC_ACPI_BASE\r
881 ) & B_PCH_LPC_ACPI_BASE_BAR;\r
882\r
883 //\r
884 // Find the CPU I/O Protocol. ASSERT if not found.\r
885 //\r
886 Status = gBS->LocateProtocol (\r
887 &gEfiCpuIoProtocolGuid,\r
888 NULL,\r
889 (void **)&CpuIo\r
890 );\r
891 ASSERT_EFI_ERROR (Status);\r
892\r
893 CpuIo->Io.Read (\r
894 CpuIo,\r
895 EfiCpuIoWidthUint16,\r
896 AcpiBase + R_PCH_ACPI_GPE0a_STS,\r
897 1,\r
898 &Data16\r
899 );\r
900 //\r
901 // Clear the B_PCH_ACPI_GPE0a_STS_GUNIT_SCI bit in R_PCH_ACPI_GPE0a_STS by writing a '1'.\r
902 //\r
903 Data16 |= B_PCH_ACPI_GPE0a_STS_GUNIT_SCI;\r
904\r
905 CpuIo->Io.Write (\r
906 CpuIo,\r
907 EfiCpuIoWidthUint16,\r
908 AcpiBase + R_PCH_ACPI_GPE0a_STS,\r
909 1,\r
910 &Data16\r
911 );\r
912\r
913 //\r
914 // Install OpRegion / Software SCI protocol\r
915 //\r
916 Handle = NULL;\r
917 Status = gBS->InstallMultipleProtocolInterfaces (\r
918 &Handle,\r
919 &gIgdOpRegionProtocolGuid,\r
920 &mIgdOpRegion,\r
921 NULL\r
922 );\r
923 ASSERT_EFI_ERROR (Status);\r
924\r
925 //\r
926 // Return final status\r
927 //\r
928 return EFI_SUCCESS;\r
929}\r