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