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