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