1 /** @file 2 Implementation for a generic GOP driver. 3 4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 14 **/ 15 16 #include "GraphicsOutput.h" 17 CONST ACPI_ADR_DEVICE_PATH mGraphicsOutputAdrNode = { 18 { 19 ACPI_DEVICE_PATH, 20 ACPI_ADR_DP, 21 { sizeof (ACPI_ADR_DEVICE_PATH), 0 }, 22 }, 23 ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0) 24 }; 25 26 EFI_PEI_GRAPHICS_DEVICE_INFO_HOB mDefaultGraphicsDeviceInfo = { 27 MAX_UINT16, MAX_UINT16, MAX_UINT16, MAX_UINT16, MAX_UINT8, MAX_UINT8 28 }; 29 30 // 31 // The driver should only start on one graphics controller. 32 // So a global flag is used to remember that the driver is already started. 33 // 34 BOOLEAN mDriverStarted = FALSE; 35 36 /** 37 Returns information for an available graphics mode that the graphics device 38 and the set of active video output devices supports. 39 40 @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance. 41 @param ModeNumber The mode number to return information on. 42 @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer. 43 @param Info A pointer to callee allocated buffer that returns information about ModeNumber. 44 45 @retval EFI_SUCCESS Valid mode information was returned. 46 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode. 47 @retval EFI_INVALID_PARAMETER ModeNumber is not valid. 48 49 **/ 50 EFI_STATUS 51 EFIAPI 52 GraphicsOutputQueryMode ( 53 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, 54 IN UINT32 ModeNumber, 55 OUT UINTN *SizeOfInfo, 56 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info 57 ) 58 { 59 if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) { 60 return EFI_INVALID_PARAMETER; 61 } 62 63 *SizeOfInfo = This->Mode->SizeOfInfo; 64 *Info = AllocateCopyPool (*SizeOfInfo, This->Mode->Info); 65 return EFI_SUCCESS; 66 } 67 68 /** 69 Set the video device into the specified mode and clears the visible portions of 70 the output display to black. 71 72 @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance. 73 @param ModeNumber Abstraction that defines the current video mode. 74 75 @retval EFI_SUCCESS The graphics mode specified by ModeNumber was selected. 76 @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. 77 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device. 78 79 **/ 80 EFI_STATUS 81 EFIAPI 82 GraphicsOutputSetMode ( 83 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, 84 IN UINT32 ModeNumber 85 ) 86 { 87 RETURN_STATUS Status; 88 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black; 89 GRAPHICS_OUTPUT_PRIVATE_DATA *Private; 90 91 if (ModeNumber >= This->Mode->MaxMode) { 92 return EFI_UNSUPPORTED; 93 } 94 95 Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (This); 96 97 Black.Blue = 0; 98 Black.Green = 0; 99 Black.Red = 0; 100 Black.Reserved = 0; 101 102 Status = FrameBufferBlt ( 103 Private->FrameBufferBltLibConfigure, 104 &Black, 105 EfiBltVideoFill, 106 0, 0, 107 0, 0, 108 This->Mode->Info->HorizontalResolution, 109 This->Mode->Info->VerticalResolution, 110 0 111 ); 112 return RETURN_ERROR (Status) ? EFI_DEVICE_ERROR : EFI_SUCCESS; 113 } 114 115 /** 116 Blt a rectangle of pixels on the graphics screen. Blt stands for BLock Transfer. 117 118 @param This Protocol instance pointer. 119 @param BltBuffer The data to transfer to the graphics screen. 120 Size is at least Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL). 121 @param BltOperation The operation to perform when copying BltBuffer on to the graphics screen. 122 @param SourceX The X coordinate of source for the BltOperation. 123 @param SourceY The Y coordinate of source for the BltOperation. 124 @param DestinationX The X coordinate of destination for the BltOperation. 125 @param DestinationY The Y coordinate of destination for the BltOperation. 126 @param Width The width of a rectangle in the blt rectangle in pixels. 127 @param Height The height of a rectangle in the blt rectangle in pixels. 128 @param Delta Not used for EfiBltVideoFill or the EfiBltVideoToVideo operation. 129 If a Delta of zero is used, the entire BltBuffer is being operated on. 130 If a subrectangle of the BltBuffer is being used then Delta 131 represents the number of bytes in a row of the BltBuffer. 132 133 @retval EFI_SUCCESS BltBuffer was drawn to the graphics screen. 134 @retval EFI_INVALID_PARAMETER BltOperation is not valid. 135 @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. 136 137 **/ 138 EFI_STATUS 139 EFIAPI 140 GraphicsOutputBlt ( 141 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, 142 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL 143 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, 144 IN UINTN SourceX, 145 IN UINTN SourceY, 146 IN UINTN DestinationX, 147 IN UINTN DestinationY, 148 IN UINTN Width, 149 IN UINTN Height, 150 IN UINTN Delta OPTIONAL 151 ) 152 { 153 RETURN_STATUS Status; 154 EFI_TPL Tpl; 155 GRAPHICS_OUTPUT_PRIVATE_DATA *Private; 156 157 Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (This); 158 // 159 // We have to raise to TPL_NOTIFY, so we make an atomic write to the frame buffer. 160 // We would not want a timer based event (Cursor, ...) to come in while we are 161 // doing this operation. 162 // 163 Tpl = gBS->RaiseTPL (TPL_NOTIFY); 164 Status = FrameBufferBlt ( 165 Private->FrameBufferBltLibConfigure, 166 BltBuffer, 167 BltOperation, 168 SourceX, SourceY, 169 DestinationX, DestinationY, Width, Height, 170 Delta 171 ); 172 gBS->RestoreTPL (Tpl); 173 174 return RETURN_ERROR (Status) ? EFI_INVALID_PARAMETER : EFI_SUCCESS; 175 } 176 177 CONST GRAPHICS_OUTPUT_PRIVATE_DATA mGraphicsOutputInstanceTemplate = { 178 GRAPHICS_OUTPUT_PRIVATE_DATA_SIGNATURE, // Signature 179 NULL, // GraphicsOutputHandle 180 { 181 GraphicsOutputQueryMode, 182 GraphicsOutputSetMode, 183 GraphicsOutputBlt, 184 NULL // Mode 185 }, 186 { 187 1, // MaxMode 188 0, // Mode 189 NULL, // Info 190 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), // SizeOfInfo 191 0, // FrameBufferBase 192 0 // FrameBufferSize 193 }, 194 NULL, // DevicePath 195 NULL, // PciIo 196 0, // PciAttributes 197 NULL, // FrameBufferBltLibConfigure 198 0 // FrameBufferBltLibConfigureSize 199 }; 200 201 /** 202 Test whether the Controller can be managed by the driver. 203 204 @param This Driver Binding protocol instance pointer. 205 @param Controller The PCI controller. 206 @param RemainingDevicePath Optional parameter use to pick a specific child 207 device to start. 208 209 @retval EFI_SUCCESS The driver can manage the video device. 210 @retval other The driver cannot manage the video device. 211 **/ 212 EFI_STATUS 213 EFIAPI 214 GraphicsOutputDriverBindingSupported ( 215 IN EFI_DRIVER_BINDING_PROTOCOL *This, 216 IN EFI_HANDLE Controller, 217 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 218 ) 219 { 220 EFI_STATUS Status; 221 EFI_PCI_IO_PROTOCOL *PciIo; 222 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 223 224 // 225 // Since there is only one GraphicsInfo HOB, the driver only manages one video device. 226 // 227 if (mDriverStarted) { 228 return EFI_ALREADY_STARTED; 229 } 230 231 // 232 // Test the PCI I/O Protocol 233 // 234 Status = gBS->OpenProtocol ( 235 Controller, 236 &gEfiPciIoProtocolGuid, 237 (VOID **) &PciIo, 238 This->DriverBindingHandle, 239 Controller, 240 EFI_OPEN_PROTOCOL_BY_DRIVER 241 ); 242 if (Status == EFI_ALREADY_STARTED) { 243 Status = EFI_SUCCESS; 244 } 245 if (EFI_ERROR (Status)) { 246 return Status; 247 } 248 gBS->CloseProtocol ( 249 Controller, 250 &gEfiPciIoProtocolGuid, 251 This->DriverBindingHandle, 252 Controller 253 ); 254 255 // 256 // Test the DevicePath protocol 257 // 258 Status = gBS->OpenProtocol ( 259 Controller, 260 &gEfiDevicePathProtocolGuid, 261 (VOID **) &DevicePath, 262 This->DriverBindingHandle, 263 Controller, 264 EFI_OPEN_PROTOCOL_BY_DRIVER 265 ); 266 if (Status == EFI_ALREADY_STARTED) { 267 Status = EFI_SUCCESS; 268 } 269 if (EFI_ERROR (Status)) { 270 return Status; 271 } 272 gBS->CloseProtocol ( 273 Controller, 274 &gEfiDevicePathProtocolGuid, 275 This->DriverBindingHandle, 276 Controller 277 ); 278 279 if ((RemainingDevicePath == NULL) || 280 IsDevicePathEnd (RemainingDevicePath) || 281 CompareMem (RemainingDevicePath, &mGraphicsOutputAdrNode, sizeof (mGraphicsOutputAdrNode)) == 0) { 282 return EFI_SUCCESS; 283 } else { 284 return EFI_INVALID_PARAMETER; 285 } 286 } 287 288 /** 289 Start the video controller. 290 291 @param This Driver Binding protocol instance pointer. 292 @param ControllerHandle The PCI controller. 293 @param RemainingDevicePath Optional parameter use to pick a specific child 294 device to start. 295 296 @retval EFI_SUCCESS The driver starts to manage the video device. 297 @retval other The driver cannot manage the video device. 298 **/ 299 EFI_STATUS 300 EFIAPI 301 GraphicsOutputDriverBindingStart ( 302 IN EFI_DRIVER_BINDING_PROTOCOL *This, 303 IN EFI_HANDLE Controller, 304 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 305 ) 306 { 307 EFI_STATUS Status; 308 RETURN_STATUS ReturnStatus; 309 GRAPHICS_OUTPUT_PRIVATE_DATA *Private; 310 EFI_PCI_IO_PROTOCOL *PciIo; 311 EFI_DEVICE_PATH *PciDevicePath; 312 PCI_TYPE00 Pci; 313 UINT8 Index; 314 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources; 315 VOID *HobStart; 316 EFI_PEI_GRAPHICS_INFO_HOB *GraphicsInfo; 317 EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *DeviceInfo; 318 EFI_PHYSICAL_ADDRESS FrameBufferBase; 319 320 FrameBufferBase = 0; 321 322 HobStart = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid); 323 ASSERT ((HobStart != NULL) && (GET_GUID_HOB_DATA_SIZE (HobStart) == sizeof (EFI_PEI_GRAPHICS_INFO_HOB))); 324 GraphicsInfo = (EFI_PEI_GRAPHICS_INFO_HOB *) (GET_GUID_HOB_DATA (HobStart)); 325 326 HobStart = GetFirstGuidHob (&gEfiGraphicsDeviceInfoHobGuid); 327 if ((HobStart == NULL) || (GET_GUID_HOB_DATA_SIZE (HobStart) < sizeof (*DeviceInfo))) { 328 // 329 // Use default device infomation when the device info HOB doesn't exist 330 // 331 DeviceInfo = &mDefaultGraphicsDeviceInfo; 332 DEBUG ((EFI_D_INFO, "[%a]: GraphicsDeviceInfo HOB doesn't exist!\n", gEfiCallerBaseName)); 333 } else { 334 DeviceInfo = (EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *) (GET_GUID_HOB_DATA (HobStart)); 335 DEBUG ((EFI_D_INFO, "[%a]: GraphicsDeviceInfo HOB:\n" 336 " VendorId = %04x, DeviceId = %04x,\n" 337 " RevisionId = %02x, BarIndex = %x,\n" 338 " SubsystemVendorId = %04x, SubsystemId = %04x\n", 339 gEfiCallerBaseName, 340 DeviceInfo->VendorId, DeviceInfo->DeviceId, 341 DeviceInfo->RevisionId, DeviceInfo->BarIndex, 342 DeviceInfo->SubsystemVendorId, DeviceInfo->SubsystemId)); 343 } 344 345 // 346 // Open the PCI I/O Protocol 347 // 348 Status = gBS->OpenProtocol ( 349 Controller, 350 &gEfiPciIoProtocolGuid, 351 (VOID **) &PciIo, 352 This->DriverBindingHandle, 353 Controller, 354 EFI_OPEN_PROTOCOL_BY_DRIVER 355 ); 356 if (Status == EFI_ALREADY_STARTED) { 357 Status = EFI_SUCCESS; 358 } 359 ASSERT_EFI_ERROR (Status); 360 361 Status = gBS->OpenProtocol ( 362 Controller, 363 &gEfiDevicePathProtocolGuid, 364 (VOID **) &PciDevicePath, 365 This->DriverBindingHandle, 366 Controller, 367 EFI_OPEN_PROTOCOL_BY_DRIVER 368 ); 369 if (Status == EFI_ALREADY_STARTED) { 370 Status = EFI_SUCCESS; 371 } 372 ASSERT_EFI_ERROR (Status); 373 374 // 375 // Read the PCI Class Code from the PCI Device 376 // 377 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0, sizeof (Pci), &Pci); 378 if (!EFI_ERROR (Status)) { 379 if (!IS_PCI_DISPLAY (&Pci) || ( 380 ((DeviceInfo->VendorId != MAX_UINT16) && (DeviceInfo->VendorId != Pci.Hdr.VendorId)) || 381 ((DeviceInfo->DeviceId != MAX_UINT16) && (DeviceInfo->DeviceId != Pci.Hdr.DeviceId)) || 382 ((DeviceInfo->RevisionId != MAX_UINT8) && (DeviceInfo->RevisionId != Pci.Hdr.RevisionID)) || 383 ((DeviceInfo->SubsystemVendorId != MAX_UINT16) && (DeviceInfo->SubsystemVendorId != Pci.Device.SubsystemVendorID)) || 384 ((DeviceInfo->SubsystemId != MAX_UINT16) && (DeviceInfo->SubsystemId != Pci.Device.SubsystemID)) 385 ) 386 ) { 387 // 388 // It's not a video device, or device infomation doesn't match. 389 // 390 Status = EFI_UNSUPPORTED; 391 } else { 392 // 393 // If it's a video device and device information matches, use the BarIndex 394 // from device information, or any BAR if BarIndex is not specified 395 // whose size >= the frame buffer size from GraphicsInfo HOB. 396 // Store the new frame buffer base. 397 // 398 for (Index = 0; Index < MAX_PCI_BAR; Index++) { 399 if ((DeviceInfo->BarIndex != MAX_UINT8) && (DeviceInfo->BarIndex != Index)) { 400 continue; 401 } 402 Status = PciIo->GetBarAttributes (PciIo, Index, NULL, (VOID**) &Resources); 403 if (!EFI_ERROR (Status)) { 404 DEBUG ((EFI_D_INFO, "[%a]: BAR[%d]: Base = %lx, Length = %lx\n", 405 gEfiCallerBaseName, Index, Resources->AddrRangeMin, Resources->AddrLen)); 406 if ((Resources->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) && 407 (Resources->Len == (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3)) && 408 (Resources->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) && 409 (Resources->AddrLen >= GraphicsInfo->FrameBufferSize) 410 ) { 411 FrameBufferBase = Resources->AddrRangeMin; 412 DEBUG ((EFI_D_INFO, "[%a]: ... matched!\n", gEfiCallerBaseName)); 413 break; 414 } 415 } 416 } 417 if (Index == MAX_PCI_BAR) { 418 Status = EFI_UNSUPPORTED; 419 } 420 } 421 } 422 423 if (EFI_ERROR (Status)) { 424 goto CloseProtocols; 425 } 426 427 if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) { 428 return EFI_SUCCESS; 429 } 430 431 Private = AllocateCopyPool (sizeof (mGraphicsOutputInstanceTemplate), &mGraphicsOutputInstanceTemplate); 432 if (Private == NULL) { 433 Status = EFI_OUT_OF_RESOURCES; 434 goto CloseProtocols; 435 } 436 437 Private->GraphicsOutputMode.FrameBufferBase = FrameBufferBase; 438 Private->GraphicsOutputMode.FrameBufferSize = GraphicsInfo->FrameBufferSize; 439 Private->GraphicsOutputMode.Info = &GraphicsInfo->GraphicsMode; 440 441 // 442 // Fix up Mode pointer in GraphicsOutput 443 // 444 Private->GraphicsOutput.Mode = &Private->GraphicsOutputMode; 445 446 // 447 // Set attributes 448 // 449 Status = PciIo->Attributes ( 450 PciIo, 451 EfiPciIoAttributeOperationGet, 452 0, 453 &Private->PciAttributes 454 ); 455 if (!EFI_ERROR (Status)) { 456 Status = PciIo->Attributes ( 457 PciIo, 458 EfiPciIoAttributeOperationEnable, 459 EFI_PCI_DEVICE_ENABLE, 460 NULL 461 ); 462 } 463 464 if (EFI_ERROR (Status)) { 465 goto FreeMemory; 466 } 467 468 // 469 // Create the FrameBufferBltLib configuration. 470 // 471 ReturnStatus = FrameBufferBltConfigure ( 472 (VOID *) (UINTN) Private->GraphicsOutput.Mode->FrameBufferBase, 473 Private->GraphicsOutput.Mode->Info, 474 Private->FrameBufferBltLibConfigure, 475 &Private->FrameBufferBltLibConfigureSize 476 ); 477 if (ReturnStatus == RETURN_BUFFER_TOO_SMALL) { 478 Private->FrameBufferBltLibConfigure = AllocatePool (Private->FrameBufferBltLibConfigureSize); 479 if (Private->FrameBufferBltLibConfigure != NULL) { 480 ReturnStatus = FrameBufferBltConfigure ( 481 (VOID *) (UINTN) Private->GraphicsOutput.Mode->FrameBufferBase, 482 Private->GraphicsOutput.Mode->Info, 483 Private->FrameBufferBltLibConfigure, 484 &Private->FrameBufferBltLibConfigureSize 485 ); 486 } 487 } 488 if (RETURN_ERROR (ReturnStatus)) { 489 Status = EFI_OUT_OF_RESOURCES; 490 goto RestorePciAttributes; 491 } 492 493 Private->DevicePath = AppendDevicePathNode (PciDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &mGraphicsOutputAdrNode); 494 if (Private->DevicePath == NULL) { 495 Status = EFI_OUT_OF_RESOURCES; 496 goto RestorePciAttributes; 497 } 498 499 Status = gBS->InstallMultipleProtocolInterfaces ( 500 &Private->GraphicsOutputHandle, 501 &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput, 502 &gEfiDevicePathProtocolGuid, Private->DevicePath, 503 NULL 504 ); 505 506 if (!EFI_ERROR (Status)) { 507 Status = gBS->OpenProtocol ( 508 Controller, 509 &gEfiPciIoProtocolGuid, 510 (VOID **) &Private->PciIo, 511 This->DriverBindingHandle, 512 Private->GraphicsOutputHandle, 513 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 514 ); 515 if (!EFI_ERROR (Status)) { 516 mDriverStarted = TRUE; 517 } else { 518 gBS->UninstallMultipleProtocolInterfaces ( 519 Private->GraphicsOutputHandle, 520 &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput, 521 &gEfiDevicePathProtocolGuid, Private->DevicePath, 522 NULL 523 ); 524 } 525 } 526 527 RestorePciAttributes: 528 if (EFI_ERROR (Status)) { 529 // 530 // Restore original PCI attributes 531 // 532 PciIo->Attributes ( 533 PciIo, 534 EfiPciIoAttributeOperationSet, 535 Private->PciAttributes, 536 NULL 537 ); 538 } 539 540 FreeMemory: 541 if (EFI_ERROR (Status)) { 542 if (Private != NULL) { 543 if (Private->DevicePath != NULL) { 544 FreePool (Private->DevicePath); 545 } 546 if (Private->FrameBufferBltLibConfigure != NULL) { 547 FreePool (Private->FrameBufferBltLibConfigure); 548 } 549 FreePool (Private); 550 } 551 } 552 553 CloseProtocols: 554 if (EFI_ERROR (Status)) { 555 // 556 // Close the PCI I/O Protocol 557 // 558 gBS->CloseProtocol ( 559 Controller, 560 &gEfiDevicePathProtocolGuid, 561 This->DriverBindingHandle, 562 Controller 563 ); 564 565 // 566 // Close the PCI I/O Protocol 567 // 568 gBS->CloseProtocol ( 569 Controller, 570 &gEfiPciIoProtocolGuid, 571 This->DriverBindingHandle, 572 Controller 573 ); 574 } 575 return Status; 576 } 577 578 /** 579 Stop the video controller. 580 581 @param This Driver Binding protocol instance pointer. 582 @param Controller The PCI controller. 583 @param NumberOfChildren The number of child device handles in ChildHandleBuffer. 584 @param ChildHandleBuffer An array of child handles to be freed. May be NULL 585 if NumberOfChildren is 0. 586 587 @retval EFI_SUCCESS The device was stopped. 588 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. 589 **/ 590 EFI_STATUS 591 EFIAPI 592 GraphicsOutputDriverBindingStop ( 593 IN EFI_DRIVER_BINDING_PROTOCOL *This, 594 IN EFI_HANDLE Controller, 595 IN UINTN NumberOfChildren, 596 IN EFI_HANDLE *ChildHandleBuffer 597 ) 598 { 599 EFI_STATUS Status; 600 EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop; 601 GRAPHICS_OUTPUT_PRIVATE_DATA *Private; 602 603 if (NumberOfChildren == 0) { 604 605 // 606 // Close the PCI I/O Protocol 607 // 608 Status = gBS->CloseProtocol ( 609 Controller, 610 &gEfiPciIoProtocolGuid, 611 This->DriverBindingHandle, 612 Controller 613 ); 614 ASSERT_EFI_ERROR (Status); 615 616 Status = gBS->CloseProtocol ( 617 Controller, 618 &gEfiDevicePathProtocolGuid, 619 This->DriverBindingHandle, 620 Controller 621 ); 622 ASSERT_EFI_ERROR (Status); 623 return EFI_SUCCESS; 624 } 625 626 ASSERT (NumberOfChildren == 1); 627 Status = gBS->OpenProtocol ( 628 ChildHandleBuffer[0], 629 &gEfiGraphicsOutputProtocolGuid, 630 (VOID **) &Gop, 631 This->DriverBindingHandle, 632 ChildHandleBuffer[0], 633 EFI_OPEN_PROTOCOL_GET_PROTOCOL 634 ); 635 if (EFI_ERROR (Status)) { 636 return Status; 637 } 638 639 Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (Gop); 640 641 Status = gBS->CloseProtocol ( 642 Controller, 643 &gEfiPciIoProtocolGuid, 644 This->DriverBindingHandle, 645 Private->GraphicsOutputHandle 646 ); 647 ASSERT_EFI_ERROR (Status); 648 // 649 // Remove the GOP protocol interface from the system 650 // 651 Status = gBS->UninstallMultipleProtocolInterfaces ( 652 Private->GraphicsOutputHandle, 653 &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput, 654 &gEfiDevicePathProtocolGuid, Private->DevicePath, 655 NULL 656 ); 657 if (!EFI_ERROR (Status)) { 658 // 659 // Restore original PCI attributes 660 // 661 Status = Private->PciIo->Attributes ( 662 Private->PciIo, 663 EfiPciIoAttributeOperationSet, 664 Private->PciAttributes, 665 NULL 666 ); 667 ASSERT_EFI_ERROR (Status); 668 669 FreePool (Private->DevicePath); 670 FreePool (Private->FrameBufferBltLibConfigure); 671 mDriverStarted = FALSE; 672 } else { 673 Status = gBS->OpenProtocol ( 674 Controller, 675 &gEfiPciIoProtocolGuid, 676 (VOID **) &Private->PciIo, 677 This->DriverBindingHandle, 678 Private->GraphicsOutputHandle, 679 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 680 ); 681 ASSERT_EFI_ERROR (Status); 682 } 683 return Status; 684 } 685 686 EFI_DRIVER_BINDING_PROTOCOL mGraphicsOutputDriverBinding = { 687 GraphicsOutputDriverBindingSupported, 688 GraphicsOutputDriverBindingStart, 689 GraphicsOutputDriverBindingStop, 690 0x10, 691 NULL, 692 NULL 693 }; 694 695 /** 696 The Entry Point for GraphicsOutput driver. 697 698 It installs DriverBinding, ComponentName and ComponentName2 protocol if there is 699 GraphicsInfo HOB passed from Graphics PEIM. 700 701 @param[in] ImageHandle The firmware allocated handle for the EFI image. 702 @param[in] SystemTable A pointer to the EFI System Table. 703 704 @retval EFI_SUCCESS The entry point is executed successfully. 705 @retval other Some error occurs when executing this entry point. 706 707 **/ 708 EFI_STATUS 709 EFIAPI 710 InitializeGraphicsOutput ( 711 IN EFI_HANDLE ImageHandle, 712 IN EFI_SYSTEM_TABLE *SystemTable 713 ) 714 { 715 EFI_STATUS Status; 716 VOID *HobStart; 717 718 HobStart = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid); 719 720 if ((HobStart == NULL) || (GET_GUID_HOB_DATA_SIZE (HobStart) < sizeof (EFI_PEI_GRAPHICS_INFO_HOB))) { 721 return EFI_NOT_FOUND; 722 } 723 724 Status = EfiLibInstallDriverBindingComponentName2 ( 725 ImageHandle, 726 SystemTable, 727 &mGraphicsOutputDriverBinding, 728 ImageHandle, 729 &mGraphicsOutputComponentName, 730 &mGraphicsOutputComponentName2 731 ); 732 ASSERT_EFI_ERROR (Status); 733 734 return Status; 735 } 736