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