1 /** @file 2 ConsoleOut Routines that speak VGA. 3 4 Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR> 5 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions 8 of the BSD License which accompanies this distribution. The 9 full text of the license may be found at 10 http://opensource.org/licenses/bsd-license.php 11 12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 14 15 **/ 16 17 #include "FbGop.h" 18 19 EFI_PIXEL_BITMASK mPixelBitMask = {0x0000FF, 0x00FF00, 0xFF0000, 0x000000}; 20 21 // 22 // Save controller attributes during first start 23 // 24 UINT64 mOriginalPciAttributes; 25 BOOLEAN mPciAttributesSaved = FALSE; 26 27 28 // 29 // EFI Driver Binding Protocol Instance 30 // 31 EFI_DRIVER_BINDING_PROTOCOL gFbGopDriverBinding = { 32 FbGopDriverBindingSupported, 33 FbGopDriverBindingStart, 34 FbGopDriverBindingStop, 35 0x3, 36 NULL, 37 NULL 38 }; 39 40 // 41 // Native resolution in EDID DetailedTiming[0] 42 // 43 UINT32 mNativeModeHorizontal; 44 UINT32 mNativeModeVertical; 45 46 /** 47 Supported. 48 49 @param This Pointer to driver binding protocol 50 @param Controller Controller handle to connect 51 @param RemainingDevicePath A pointer to the remaining portion of a device 52 path 53 54 @retval EFI_STATUS EFI_SUCCESS:This controller can be managed by this 55 driver, Otherwise, this controller cannot be 56 managed by this driver 57 58 **/ 59 EFI_STATUS 60 EFIAPI 61 FbGopDriverBindingSupported ( 62 IN EFI_DRIVER_BINDING_PROTOCOL *This, 63 IN EFI_HANDLE Controller, 64 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 65 ) 66 { 67 EFI_STATUS Status; 68 EFI_PCI_IO_PROTOCOL *PciIo; 69 PCI_TYPE00 Pci; 70 EFI_DEV_PATH *Node; 71 72 // 73 // Open the IO Abstraction(s) needed to perform the supported test 74 // 75 Status = gBS->OpenProtocol ( 76 Controller, 77 &gEfiPciIoProtocolGuid, 78 (VOID **) &PciIo, 79 This->DriverBindingHandle, 80 Controller, 81 EFI_OPEN_PROTOCOL_BY_DRIVER 82 ); 83 if (EFI_ERROR (Status)) { 84 return Status; 85 } 86 87 // 88 // See if this is a PCI Graphics Controller by looking at the Command register and 89 // Class Code Register 90 // 91 Status = PciIo->Pci.Read ( 92 PciIo, 93 EfiPciIoWidthUint32, 94 0, 95 sizeof (Pci) / sizeof (UINT32), 96 &Pci 97 ); 98 if (EFI_ERROR (Status)) { 99 Status = EFI_UNSUPPORTED; 100 goto Done; 101 } 102 103 Status = EFI_UNSUPPORTED; 104 if (Pci.Hdr.ClassCode[2] == 0x03 || (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01)) { 105 106 Status = EFI_SUCCESS; 107 // 108 // If this is a graphics controller, 109 // go further check RemainingDevicePath validation 110 // 111 if (RemainingDevicePath != NULL) { 112 Node = (EFI_DEV_PATH *) RemainingDevicePath; 113 // 114 // Check if RemainingDevicePath is the End of Device Path Node, 115 // if yes, return EFI_SUCCESS 116 // 117 if (!IsDevicePathEnd (Node)) { 118 // 119 // If RemainingDevicePath isn't the End of Device Path Node, 120 // check its validation 121 // 122 if (Node->DevPath.Type != ACPI_DEVICE_PATH || 123 Node->DevPath.SubType != ACPI_ADR_DP || 124 DevicePathNodeLength(&Node->DevPath) < sizeof(ACPI_ADR_DEVICE_PATH)) { 125 Status = EFI_UNSUPPORTED; 126 } 127 } 128 } 129 } 130 131 Done: 132 gBS->CloseProtocol ( 133 Controller, 134 &gEfiPciIoProtocolGuid, 135 This->DriverBindingHandle, 136 Controller 137 ); 138 139 return Status; 140 } 141 142 143 /** 144 Install Graphics Output Protocol onto VGA device handles. 145 146 @param This Pointer to driver binding protocol 147 @param Controller Controller handle to connect 148 @param RemainingDevicePath A pointer to the remaining portion of a device 149 path 150 151 @return EFI_STATUS 152 153 **/ 154 EFI_STATUS 155 EFIAPI 156 FbGopDriverBindingStart ( 157 IN EFI_DRIVER_BINDING_PROTOCOL *This, 158 IN EFI_HANDLE Controller, 159 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 160 ) 161 { 162 EFI_STATUS Status; 163 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; 164 EFI_PCI_IO_PROTOCOL *PciIo; 165 UINT64 Supports; 166 167 DEBUG ((EFI_D_INFO, "GOP START\n")); 168 169 // 170 // Initialize local variables 171 // 172 PciIo = NULL; 173 ParentDevicePath = NULL; 174 175 // 176 // Prepare for status code 177 // 178 Status = gBS->HandleProtocol ( 179 Controller, 180 &gEfiDevicePathProtocolGuid, 181 (VOID **) &ParentDevicePath 182 ); 183 if (EFI_ERROR (Status)) { 184 return Status; 185 } 186 187 // 188 // Open the IO Abstraction(s) needed 189 // 190 Status = gBS->OpenProtocol ( 191 Controller, 192 &gEfiPciIoProtocolGuid, 193 (VOID **) &PciIo, 194 This->DriverBindingHandle, 195 Controller, 196 EFI_OPEN_PROTOCOL_BY_DRIVER 197 ); 198 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) { 199 return Status; 200 } 201 202 // 203 // Save original PCI attributes 204 // 205 if (!mPciAttributesSaved) { 206 Status = PciIo->Attributes ( 207 PciIo, 208 EfiPciIoAttributeOperationGet, 209 0, 210 &mOriginalPciAttributes 211 ); 212 213 if (EFI_ERROR (Status)) { 214 goto Done; 215 } 216 mPciAttributesSaved = TRUE; 217 } 218 219 // 220 // Get supported PCI attributes 221 // 222 Status = PciIo->Attributes ( 223 PciIo, 224 EfiPciIoAttributeOperationSupported, 225 0, 226 &Supports 227 ); 228 if (EFI_ERROR (Status)) { 229 goto Done; 230 } 231 232 Supports &= (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16); 233 if (Supports == 0 || Supports == (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) { 234 Status = EFI_UNSUPPORTED; 235 goto Done; 236 } 237 238 REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 239 EFI_PROGRESS_CODE, 240 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE, 241 ParentDevicePath 242 ); 243 // 244 // Enable the device and make sure VGA cycles are being forwarded to this VGA device 245 // 246 Status = PciIo->Attributes ( 247 PciIo, 248 EfiPciIoAttributeOperationEnable, 249 EFI_PCI_DEVICE_ENABLE, 250 NULL 251 ); 252 if (EFI_ERROR (Status)) { 253 REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 254 EFI_ERROR_CODE | EFI_ERROR_MINOR, 255 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_RESOURCE_CONFLICT, 256 ParentDevicePath 257 ); 258 goto Done; 259 } 260 261 if (RemainingDevicePath != NULL) { 262 if (IsDevicePathEnd (RemainingDevicePath)) { 263 // 264 // If RemainingDevicePath is the End of Device Path Node, 265 // don't create any child device and return EFI_SUCESS 266 Status = EFI_SUCCESS; 267 goto Done; 268 } 269 } 270 271 // 272 // Create child handle and install GraphicsOutputProtocol on it 273 // 274 Status = FbGopChildHandleInstall ( 275 This, 276 Controller, 277 PciIo, 278 NULL, 279 ParentDevicePath, 280 RemainingDevicePath 281 ); 282 283 Done: 284 if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) { 285 286 REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 287 EFI_PROGRESS_CODE, 288 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_DISABLE, 289 ParentDevicePath 290 ); 291 292 REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 293 EFI_PROGRESS_CODE, 294 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_NOT_DETECTED, 295 ParentDevicePath 296 ); 297 if (!HasChildHandle (Controller)) { 298 if (mPciAttributesSaved) { 299 // 300 // Restore original PCI attributes 301 // 302 PciIo->Attributes ( 303 PciIo, 304 EfiPciIoAttributeOperationSet, 305 mOriginalPciAttributes, 306 NULL 307 ); 308 } 309 } 310 // 311 // Release PCI I/O Protocols on the controller handle. 312 // 313 gBS->CloseProtocol ( 314 Controller, 315 &gEfiPciIoProtocolGuid, 316 This->DriverBindingHandle, 317 Controller 318 ); 319 } 320 321 return Status; 322 } 323 324 325 /** 326 Stop. 327 328 @param This Pointer to driver binding protocol 329 @param Controller Controller handle to connect 330 @param NumberOfChildren Number of children handle created by this driver 331 @param ChildHandleBuffer Buffer containing child handle created 332 333 @retval EFI_SUCCESS Driver disconnected successfully from controller 334 @retval EFI_UNSUPPORTED Cannot find FB_VIDEO_DEV structure 335 336 **/ 337 EFI_STATUS 338 EFIAPI 339 FbGopDriverBindingStop ( 340 IN EFI_DRIVER_BINDING_PROTOCOL *This, 341 IN EFI_HANDLE Controller, 342 IN UINTN NumberOfChildren, 343 IN EFI_HANDLE *ChildHandleBuffer 344 ) 345 { 346 EFI_STATUS Status; 347 BOOLEAN AllChildrenStopped; 348 UINTN Index; 349 EFI_PCI_IO_PROTOCOL *PciIo; 350 351 AllChildrenStopped = TRUE; 352 353 if (NumberOfChildren == 0) { 354 // 355 // Close PCI I/O protocol on the controller handle 356 // 357 gBS->CloseProtocol ( 358 Controller, 359 &gEfiPciIoProtocolGuid, 360 This->DriverBindingHandle, 361 Controller 362 ); 363 364 return EFI_SUCCESS; 365 } 366 367 for (Index = 0; Index < NumberOfChildren; Index++) { 368 369 Status = EFI_SUCCESS; 370 371 FbGopChildHandleUninstall (This, Controller, ChildHandleBuffer[Index]); 372 373 if (EFI_ERROR (Status)) { 374 AllChildrenStopped = FALSE; 375 } 376 } 377 378 if (!AllChildrenStopped) { 379 return EFI_DEVICE_ERROR; 380 } 381 382 if (!HasChildHandle (Controller)) { 383 if (mPciAttributesSaved) { 384 Status = gBS->HandleProtocol ( 385 Controller, 386 &gEfiPciIoProtocolGuid, 387 (VOID **) &PciIo 388 ); 389 ASSERT_EFI_ERROR (Status); 390 391 // 392 // Restore original PCI attributes 393 // 394 Status = PciIo->Attributes ( 395 PciIo, 396 EfiPciIoAttributeOperationSet, 397 mOriginalPciAttributes, 398 NULL 399 ); 400 ASSERT_EFI_ERROR (Status); 401 } 402 } 403 404 405 return EFI_SUCCESS; 406 } 407 408 409 /** 410 Install child handles if the Handle supports MBR format. 411 412 @param This Calling context. 413 @param ParentHandle Parent Handle 414 @param ParentPciIo Parent PciIo interface 415 @param ParentLegacyBios Parent LegacyBios interface 416 @param ParentDevicePath Parent Device Path 417 @param RemainingDevicePath Remaining Device Path 418 419 @retval EFI_SUCCESS If a child handle was added 420 @retval other A child handle was not added 421 422 **/ 423 EFI_STATUS 424 FbGopChildHandleInstall ( 425 IN EFI_DRIVER_BINDING_PROTOCOL *This, 426 IN EFI_HANDLE ParentHandle, 427 IN EFI_PCI_IO_PROTOCOL *ParentPciIo, 428 IN VOID *ParentLegacyBios, 429 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, 430 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 431 ) 432 { 433 EFI_STATUS Status; 434 FB_VIDEO_DEV *FbGopPrivate; 435 PCI_TYPE00 Pci; 436 ACPI_ADR_DEVICE_PATH AcpiDeviceNode; 437 BOOLEAN ProtocolInstalled; 438 439 // 440 // Allocate the private device structure for video device 441 // 442 FbGopPrivate = (FB_VIDEO_DEV *) AllocateZeroPool ( 443 sizeof (FB_VIDEO_DEV) 444 ); 445 if (NULL == FbGopPrivate) { 446 Status = EFI_OUT_OF_RESOURCES; 447 goto Done; 448 } 449 450 // 451 // See if this is a VGA compatible controller or not 452 // 453 Status = ParentPciIo->Pci.Read ( 454 ParentPciIo, 455 EfiPciIoWidthUint32, 456 0, 457 sizeof (Pci) / sizeof (UINT32), 458 &Pci 459 ); 460 if (EFI_ERROR (Status)) { 461 REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 462 EFI_ERROR_CODE | EFI_ERROR_MINOR, 463 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR, 464 ParentDevicePath 465 ); 466 goto Done; 467 } 468 469 // 470 // Initialize the child private structure 471 // 472 FbGopPrivate->Signature = FB_VIDEO_DEV_SIGNATURE; 473 474 // 475 // Fill in Graphics Output specific mode structures 476 // 477 FbGopPrivate->ModeData = NULL; 478 479 FbGopPrivate->VbeFrameBuffer = NULL; 480 481 FbGopPrivate->EdidDiscovered.SizeOfEdid = 0; 482 FbGopPrivate->EdidDiscovered.Edid = NULL; 483 FbGopPrivate->EdidActive.SizeOfEdid = 0; 484 FbGopPrivate->EdidActive.Edid = NULL; 485 486 // 487 // Fill in the Graphics Output Protocol 488 // 489 FbGopPrivate->GraphicsOutput.QueryMode = FbGopGraphicsOutputQueryMode; 490 FbGopPrivate->GraphicsOutput.SetMode = FbGopGraphicsOutputSetMode; 491 492 493 // 494 // Allocate buffer for Graphics Output Protocol mode information 495 // 496 FbGopPrivate->GraphicsOutput.Mode = (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *) AllocatePool ( 497 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE) 498 ); 499 if (NULL == FbGopPrivate->GraphicsOutput.Mode) { 500 Status = EFI_OUT_OF_RESOURCES; 501 goto Done; 502 } 503 504 FbGopPrivate->GraphicsOutput.Mode->Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool ( 505 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) 506 ); 507 if (NULL == FbGopPrivate->GraphicsOutput.Mode->Info) { 508 Status = EFI_OUT_OF_RESOURCES; 509 goto Done; 510 } 511 512 // 513 // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node. 514 // 515 if ((RemainingDevicePath == NULL) || (!IsDevicePathEnd (RemainingDevicePath))) { 516 if (RemainingDevicePath == NULL) { 517 ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH)); 518 AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH; 519 AcpiDeviceNode.Header.SubType = ACPI_ADR_DP; 520 AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0); 521 SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH)); 522 523 FbGopPrivate->GopDevicePath = AppendDevicePathNode ( 524 ParentDevicePath, 525 (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode 526 ); 527 } else { 528 FbGopPrivate->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath); 529 } 530 531 // 532 // Creat child handle and device path protocol firstly 533 // 534 FbGopPrivate->Handle = NULL; 535 Status = gBS->InstallMultipleProtocolInterfaces ( 536 &FbGopPrivate->Handle, 537 &gEfiDevicePathProtocolGuid, 538 FbGopPrivate->GopDevicePath, 539 NULL 540 ); 541 if (EFI_ERROR (Status)) { 542 goto Done; 543 } 544 } 545 546 // 547 // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally 548 // 549 FbGopPrivate->PciIo = ParentPciIo; 550 551 // 552 // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output 553 // 554 Status = FbGopCheckForVbe (FbGopPrivate); 555 DEBUG ((EFI_D_INFO, "FbGopCheckForVbe - %r\n", Status)); 556 557 if (EFI_ERROR (Status)) { 558 Status = EFI_UNSUPPORTED; 559 //goto Done; 560 } 561 562 ProtocolInstalled = FALSE; 563 564 // 565 // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol 566 // 567 Status = gBS->InstallMultipleProtocolInterfaces ( 568 &FbGopPrivate->Handle, 569 &gEfiGraphicsOutputProtocolGuid, 570 &FbGopPrivate->GraphicsOutput, 571 &gEfiEdidDiscoveredProtocolGuid, 572 &FbGopPrivate->EdidDiscovered, 573 &gEfiEdidActiveProtocolGuid, 574 &FbGopPrivate->EdidActive, 575 NULL 576 ); 577 578 if (!EFI_ERROR (Status)) { 579 // 580 // Open the Parent Handle for the child 581 // 582 Status = gBS->OpenProtocol ( 583 ParentHandle, 584 &gEfiPciIoProtocolGuid, 585 (VOID **) &FbGopPrivate->PciIo, 586 This->DriverBindingHandle, 587 FbGopPrivate->Handle, 588 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 589 ); 590 if (EFI_ERROR (Status)) { 591 goto Done; 592 } 593 ProtocolInstalled = TRUE; 594 } 595 596 Done: 597 if (EFI_ERROR (Status)) { 598 // 599 // Free private data structure 600 // 601 FbGopDeviceReleaseResource (FbGopPrivate); 602 } 603 604 return Status; 605 } 606 607 608 /** 609 Deregister an video child handle and free resources. 610 611 @param This Protocol instance pointer. 612 @param Controller Video controller handle 613 @param Handle Video child handle 614 615 @return EFI_STATUS 616 617 **/ 618 EFI_STATUS 619 FbGopChildHandleUninstall ( 620 EFI_DRIVER_BINDING_PROTOCOL *This, 621 EFI_HANDLE Controller, 622 EFI_HANDLE Handle 623 ) 624 { 625 EFI_STATUS Status; 626 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; 627 FB_VIDEO_DEV *FbGopPrivate; 628 EFI_PCI_IO_PROTOCOL *PciIo; 629 630 FbGopPrivate = NULL; 631 GraphicsOutput = NULL; 632 PciIo = NULL; 633 Status = EFI_UNSUPPORTED; 634 635 Status = gBS->OpenProtocol ( 636 Handle, 637 &gEfiGraphicsOutputProtocolGuid, 638 (VOID **) &GraphicsOutput, 639 This->DriverBindingHandle, 640 Handle, 641 EFI_OPEN_PROTOCOL_GET_PROTOCOL 642 ); 643 if (!EFI_ERROR (Status)) { 644 FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput); 645 } 646 647 if (FbGopPrivate == NULL) { 648 return EFI_UNSUPPORTED; 649 } 650 651 // 652 // Close PCI I/O protocol that opened by child handle 653 // 654 Status = gBS->CloseProtocol ( 655 Controller, 656 &gEfiPciIoProtocolGuid, 657 This->DriverBindingHandle, 658 Handle 659 ); 660 661 // 662 // Uninstall protocols on child handle 663 // 664 Status = gBS->UninstallMultipleProtocolInterfaces ( 665 FbGopPrivate->Handle, 666 &gEfiDevicePathProtocolGuid, 667 FbGopPrivate->GopDevicePath, 668 &gEfiGraphicsOutputProtocolGuid, 669 &FbGopPrivate->GraphicsOutput, 670 NULL 671 ); 672 673 if (EFI_ERROR (Status)) { 674 gBS->OpenProtocol ( 675 Controller, 676 &gEfiPciIoProtocolGuid, 677 (VOID **) &PciIo, 678 This->DriverBindingHandle, 679 Handle, 680 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 681 ); 682 return Status; 683 } 684 685 // 686 // Release all allocated resources 687 // 688 FbGopDeviceReleaseResource (FbGopPrivate); 689 690 return EFI_SUCCESS; 691 } 692 693 694 /** 695 Release resource for biso video instance. 696 697 @param FbGopPrivate Video child device private data structure 698 699 **/ 700 VOID 701 FbGopDeviceReleaseResource ( 702 FB_VIDEO_DEV *FbGopPrivate 703 ) 704 { 705 if (FbGopPrivate == NULL) { 706 return ; 707 } 708 709 // 710 // Release all the resourses occupied by the FB_VIDEO_DEV 711 // 712 713 // 714 // Free VBE Frame Buffer 715 // 716 if (FbGopPrivate->VbeFrameBuffer != NULL) { 717 FreePool (FbGopPrivate->VbeFrameBuffer); 718 } 719 720 // 721 // Free mode data 722 // 723 if (FbGopPrivate->ModeData != NULL) { 724 FreePool (FbGopPrivate->ModeData); 725 } 726 727 // 728 // Free graphics output protocol occupied resource 729 // 730 if (FbGopPrivate->GraphicsOutput.Mode != NULL) { 731 if (FbGopPrivate->GraphicsOutput.Mode->Info != NULL) { 732 FreePool (FbGopPrivate->GraphicsOutput.Mode->Info); 733 FbGopPrivate->GraphicsOutput.Mode->Info = NULL; 734 } 735 FreePool (FbGopPrivate->GraphicsOutput.Mode); 736 FbGopPrivate->GraphicsOutput.Mode = NULL; 737 } 738 739 if (FbGopPrivate->GopDevicePath!= NULL) { 740 FreePool (FbGopPrivate->GopDevicePath); 741 } 742 743 FreePool (FbGopPrivate); 744 745 return ; 746 } 747 748 749 750 /** 751 Check if all video child handles have been uninstalled. 752 753 @param Controller Video controller handle 754 755 @return TRUE Child handles exist. 756 @return FALSE All video child handles have been uninstalled. 757 758 **/ 759 BOOLEAN 760 HasChildHandle ( 761 IN EFI_HANDLE Controller 762 ) 763 { 764 UINTN Index; 765 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; 766 UINTN EntryCount; 767 BOOLEAN HasChild; 768 EFI_STATUS Status; 769 770 EntryCount = 0; 771 HasChild = FALSE; 772 Status = gBS->OpenProtocolInformation ( 773 Controller, 774 &gEfiPciIoProtocolGuid, 775 &OpenInfoBuffer, 776 &EntryCount 777 ); 778 for (Index = 0; Index < EntryCount; Index++) { 779 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { 780 HasChild = TRUE; 781 } 782 } 783 784 return HasChild; 785 } 786 787 /** 788 Check for VBE device. 789 790 @param FbGopPrivate Pointer to FB_VIDEO_DEV structure 791 792 @retval EFI_SUCCESS VBE device found 793 794 **/ 795 EFI_STATUS 796 FbGopCheckForVbe ( 797 IN OUT FB_VIDEO_DEV *FbGopPrivate 798 ) 799 { 800 EFI_STATUS Status; 801 FB_VIDEO_MODE_DATA *ModeBuffer; 802 FB_VIDEO_MODE_DATA *CurrentModeData; 803 UINTN ModeNumber; 804 UINTN BitsPerPixel; 805 UINTN BytesPerScanLine; 806 UINT32 HorizontalResolution; 807 UINT32 VerticalResolution; 808 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer; 809 EFI_HOB_GUID_TYPE *GuidHob; 810 FRAME_BUFFER_INFO *pFbInfo; 811 812 Status = EFI_SUCCESS; 813 // 814 // Find the frame buffer information guid hob 815 // 816 GuidHob = GetFirstGuidHob (&gUefiFrameBufferInfoGuid); 817 ASSERT (GuidHob != NULL); 818 pFbInfo = (FRAME_BUFFER_INFO *)GET_GUID_HOB_DATA (GuidHob); 819 820 // 821 // Add mode to the list of available modes 822 // 823 VbeFrameBuffer = NULL; 824 ModeBuffer = NULL; 825 826 ModeNumber = 1; 827 BitsPerPixel = pFbInfo->BitsPerPixel; 828 HorizontalResolution = pFbInfo->HorizontalResolution; 829 VerticalResolution = pFbInfo->VerticalResolution; 830 BytesPerScanLine = HorizontalResolution * (BitsPerPixel / 8); 831 832 ModeBuffer = (FB_VIDEO_MODE_DATA *) AllocatePool ( 833 ModeNumber * sizeof (FB_VIDEO_MODE_DATA) 834 ); 835 if (NULL == ModeBuffer) { 836 Status = EFI_OUT_OF_RESOURCES; 837 goto Done; 838 } 839 840 VbeFrameBuffer = 841 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocatePool ( 842 BytesPerScanLine * VerticalResolution 843 ); 844 if (NULL == VbeFrameBuffer) { 845 Status = EFI_OUT_OF_RESOURCES; 846 goto Done; 847 } 848 849 if (FbGopPrivate->ModeData != NULL) { 850 FreePool (FbGopPrivate->ModeData); 851 } 852 853 if (FbGopPrivate->VbeFrameBuffer != NULL) { 854 FreePool (FbGopPrivate->VbeFrameBuffer); 855 } 856 857 CurrentModeData = &ModeBuffer[ModeNumber - 1]; 858 CurrentModeData->BytesPerScanLine = (UINT16)BytesPerScanLine; 859 860 CurrentModeData->Red = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Red); 861 CurrentModeData->Blue = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Blue); 862 CurrentModeData->Green = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Green); 863 CurrentModeData->Reserved = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Reserved); 864 865 CurrentModeData->BitsPerPixel = (UINT32)BitsPerPixel; 866 CurrentModeData->HorizontalResolution = HorizontalResolution; 867 CurrentModeData->VerticalResolution = VerticalResolution; 868 CurrentModeData->FrameBufferSize = CurrentModeData->BytesPerScanLine * CurrentModeData->VerticalResolution; 869 CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN) pFbInfo->LinearFrameBuffer; 870 CurrentModeData->VbeModeNumber = 0; 871 CurrentModeData->ColorDepth = 32; 872 CurrentModeData->RefreshRate = 60; 873 874 CurrentModeData->PixelFormat = PixelBitMask; 875 if ((CurrentModeData->BitsPerPixel == 32) && 876 (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) { 877 if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) { 878 CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor; 879 } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) { 880 CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor; 881 } 882 } 883 884 CopyMem (&(CurrentModeData->PixelBitMask), &mPixelBitMask, sizeof (EFI_PIXEL_BITMASK)); 885 886 FbGopPrivate->ModeData = ModeBuffer; 887 FbGopPrivate->VbeFrameBuffer = VbeFrameBuffer; 888 889 // 890 // Assign Gop's Blt function 891 // 892 FbGopPrivate->GraphicsOutput.Blt = FbGopGraphicsOutputVbeBlt; 893 894 FbGopPrivate->GraphicsOutput.Mode->MaxMode = 1; 895 FbGopPrivate->GraphicsOutput.Mode->Mode = 0; 896 FbGopPrivate->GraphicsOutput.Mode->Info->Version = 0; 897 FbGopPrivate->GraphicsOutput.Mode->Info->HorizontalResolution = HorizontalResolution; 898 FbGopPrivate->GraphicsOutput.Mode->Info->VerticalResolution = VerticalResolution; 899 FbGopPrivate->GraphicsOutput.Mode->Info->PixelFormat = CurrentModeData->PixelFormat; 900 CopyMem (&(FbGopPrivate->GraphicsOutput.Mode->Info->PixelInformation), &mPixelBitMask, sizeof (EFI_PIXEL_BITMASK)); 901 FbGopPrivate->GraphicsOutput.Mode->Info->PixelsPerScanLine = HorizontalResolution; 902 FbGopPrivate->GraphicsOutput.Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); 903 FbGopPrivate->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) CurrentModeData->LinearFrameBuffer; 904 FbGopPrivate->GraphicsOutput.Mode->FrameBufferSize = CurrentModeData->FrameBufferSize; 905 906 // 907 // Find the best mode to initialize 908 // 909 910 Done: 911 // 912 // If there was an error, then free the mode structure 913 // 914 if (EFI_ERROR (Status)) { 915 916 if (VbeFrameBuffer != NULL) { 917 FreePool (VbeFrameBuffer); 918 } 919 920 if (ModeBuffer != NULL) { 921 FreePool (ModeBuffer); 922 } 923 } 924 925 return Status; 926 } 927 928 929 // 930 // Graphics Output Protocol Member Functions for VESA BIOS Extensions 931 // 932 933 /** 934 Graphics Output protocol interface to get video mode. 935 936 @param This Protocol instance pointer. 937 @param ModeNumber The mode number to return information on. 938 @param SizeOfInfo A pointer to the size, in bytes, of the Info 939 buffer. 940 @param Info Caller allocated buffer that returns information 941 about ModeNumber. 942 943 @retval EFI_SUCCESS Mode information returned. 944 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the 945 video mode. 946 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode () 947 @retval EFI_INVALID_PARAMETER One of the input args was NULL. 948 949 **/ 950 EFI_STATUS 951 EFIAPI 952 FbGopGraphicsOutputQueryMode ( 953 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, 954 IN UINT32 ModeNumber, 955 OUT UINTN *SizeOfInfo, 956 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info 957 ) 958 { 959 FB_VIDEO_DEV *FbGopPrivate; 960 FB_VIDEO_MODE_DATA *ModeData; 961 962 FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); 963 964 if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) { 965 return EFI_INVALID_PARAMETER; 966 } 967 968 *Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool ( 969 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) 970 ); 971 if (NULL == *Info) { 972 return EFI_OUT_OF_RESOURCES; 973 } 974 975 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); 976 977 ModeData = &FbGopPrivate->ModeData[ModeNumber]; 978 (*Info)->Version = 0; 979 (*Info)->HorizontalResolution = ModeData->HorizontalResolution; 980 (*Info)->VerticalResolution = ModeData->VerticalResolution; 981 (*Info)->PixelFormat = ModeData->PixelFormat; 982 CopyMem (&((*Info)->PixelInformation), &(ModeData->PixelBitMask), sizeof(ModeData->PixelBitMask)); 983 984 (*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel; 985 986 return EFI_SUCCESS; 987 } 988 989 /** 990 Graphics Output protocol interface to set video mode. 991 992 @param This Protocol instance pointer. 993 @param ModeNumber The mode number to be set. 994 995 @retval EFI_SUCCESS Graphics mode was changed. 996 @retval EFI_DEVICE_ERROR The device had an error and could not complete the 997 request. 998 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device. 999 1000 **/ 1001 EFI_STATUS 1002 EFIAPI 1003 FbGopGraphicsOutputSetMode ( 1004 IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This, 1005 IN UINT32 ModeNumber 1006 ) 1007 { 1008 FB_VIDEO_DEV *FbGopPrivate; 1009 FB_VIDEO_MODE_DATA *ModeData; 1010 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; 1011 1012 if (This == NULL) { 1013 return EFI_INVALID_PARAMETER; 1014 } 1015 1016 FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); 1017 1018 ModeData = &FbGopPrivate->ModeData[ModeNumber]; 1019 1020 if (ModeNumber >= This->Mode->MaxMode) { 1021 return EFI_UNSUPPORTED; 1022 } 1023 1024 if (ModeNumber == This->Mode->Mode) { 1025 // 1026 // Clear screen to black 1027 // 1028 ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); 1029 FbGopGraphicsOutputVbeBlt ( 1030 This, 1031 &Background, 1032 EfiBltVideoFill, 1033 0, 1034 0, 1035 0, 1036 0, 1037 ModeData->HorizontalResolution, 1038 ModeData->VerticalResolution, 1039 0 1040 ); 1041 return EFI_SUCCESS; 1042 } else { 1043 return EFI_UNSUPPORTED; 1044 } 1045 1046 } 1047 1048 /** 1049 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes. 1050 1051 @param PciIo The pointer of EFI_PCI_IO_PROTOCOL 1052 @param VbeBuffer The data to transfer to screen 1053 @param MemAddress Physical frame buffer base address 1054 @param DestinationX The X coordinate of the destination for BltOperation 1055 @param DestinationY The Y coordinate of the destination for BltOperation 1056 @param TotalBytes The total bytes of copy 1057 @param VbePixelWidth Bytes per pixel 1058 @param BytesPerScanLine Bytes per scan line 1059 1060 **/ 1061 VOID 1062 CopyVideoBuffer ( 1063 IN EFI_PCI_IO_PROTOCOL *PciIo, 1064 IN UINT8 *VbeBuffer, 1065 IN VOID *MemAddress, 1066 IN UINTN DestinationX, 1067 IN UINTN DestinationY, 1068 IN UINTN TotalBytes, 1069 IN UINT32 VbePixelWidth, 1070 IN UINTN BytesPerScanLine 1071 ) 1072 { 1073 UINTN FrameBufferAddr; 1074 UINTN CopyBlockNum; 1075 UINTN RemainingBytes; 1076 UINTN UnalignedBytes; 1077 EFI_STATUS Status; 1078 1079 FrameBufferAddr = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth; 1080 1081 // 1082 // If TotalBytes is less than 4 bytes, only start byte copy. 1083 // 1084 if (TotalBytes < 4) { 1085 Status = PciIo->Mem.Write ( 1086 PciIo, 1087 EfiPciIoWidthUint8, 1088 EFI_PCI_IO_PASS_THROUGH_BAR, 1089 (UINT64) FrameBufferAddr, 1090 TotalBytes, 1091 VbeBuffer 1092 ); 1093 ASSERT_EFI_ERROR (Status); 1094 return; 1095 } 1096 1097 // 1098 // If VbeBuffer is not 4-byte aligned, start byte copy. 1099 // 1100 UnalignedBytes = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3; 1101 1102 if (UnalignedBytes != 0) { 1103 Status = PciIo->Mem.Write ( 1104 PciIo, 1105 EfiPciIoWidthUint8, 1106 EFI_PCI_IO_PASS_THROUGH_BAR, 1107 (UINT64) FrameBufferAddr, 1108 UnalignedBytes, 1109 VbeBuffer 1110 ); 1111 ASSERT_EFI_ERROR (Status); 1112 FrameBufferAddr += UnalignedBytes; 1113 VbeBuffer += UnalignedBytes; 1114 } 1115 1116 // 1117 // Calculate 4-byte block count and remaining bytes. 1118 // 1119 CopyBlockNum = (TotalBytes - UnalignedBytes) >> 2; 1120 RemainingBytes = (TotalBytes - UnalignedBytes) & 3; 1121 1122 // 1123 // Copy 4-byte block and remaining bytes to physical frame buffer. 1124 // 1125 if (CopyBlockNum != 0) { 1126 Status = PciIo->Mem.Write ( 1127 PciIo, 1128 EfiPciIoWidthUint32, 1129 EFI_PCI_IO_PASS_THROUGH_BAR, 1130 (UINT64) FrameBufferAddr, 1131 CopyBlockNum, 1132 VbeBuffer 1133 ); 1134 ASSERT_EFI_ERROR (Status); 1135 } 1136 1137 if (RemainingBytes != 0) { 1138 FrameBufferAddr += (CopyBlockNum << 2); 1139 VbeBuffer += (CopyBlockNum << 2); 1140 Status = PciIo->Mem.Write ( 1141 PciIo, 1142 EfiPciIoWidthUint8, 1143 EFI_PCI_IO_PASS_THROUGH_BAR, 1144 (UINT64) FrameBufferAddr, 1145 RemainingBytes, 1146 VbeBuffer 1147 ); 1148 ASSERT_EFI_ERROR (Status); 1149 } 1150 } 1151 1152 /** 1153 Worker function to block transfer for VBE device. 1154 1155 @param FbGopPrivate Instance of FB_VIDEO_DEV 1156 @param BltBuffer The data to transfer to screen 1157 @param BltOperation The operation to perform 1158 @param SourceX The X coordinate of the source for BltOperation 1159 @param SourceY The Y coordinate of the source for BltOperation 1160 @param DestinationX The X coordinate of the destination for 1161 BltOperation 1162 @param DestinationY The Y coordinate of the destination for 1163 BltOperation 1164 @param Width The width of a rectangle in the blt rectangle in 1165 pixels 1166 @param Height The height of a rectangle in the blt rectangle in 1167 pixels 1168 @param Delta Not used for EfiBltVideoFill and 1169 EfiBltVideoToVideo operation. If a Delta of 0 is 1170 used, the entire BltBuffer will be operated on. If 1171 a subrectangle of the BltBuffer is used, then 1172 Delta represents the number of bytes in a row of 1173 the BltBuffer. 1174 @param Mode Mode data. 1175 1176 @retval EFI_INVALID_PARAMETER Invalid parameter passed in 1177 @retval EFI_SUCCESS Blt operation success 1178 1179 **/ 1180 EFI_STATUS 1181 FbGopVbeBltWorker ( 1182 IN FB_VIDEO_DEV *FbGopPrivate, 1183 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL 1184 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, 1185 IN UINTN SourceX, 1186 IN UINTN SourceY, 1187 IN UINTN DestinationX, 1188 IN UINTN DestinationY, 1189 IN UINTN Width, 1190 IN UINTN Height, 1191 IN UINTN Delta, 1192 IN FB_VIDEO_MODE_DATA *Mode 1193 ) 1194 { 1195 EFI_PCI_IO_PROTOCOL *PciIo; 1196 EFI_TPL OriginalTPL; 1197 UINTN DstY; 1198 UINTN SrcY; 1199 UINTN DstX; 1200 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt; 1201 VOID *MemAddress; 1202 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer; 1203 UINTN BytesPerScanLine; 1204 UINTN Index; 1205 UINT8 *VbeBuffer; 1206 UINT8 *VbeBuffer1; 1207 UINT8 *BltUint8; 1208 UINT32 VbePixelWidth; 1209 UINT32 Pixel; 1210 UINTN TotalBytes; 1211 1212 PciIo = FbGopPrivate->PciIo; 1213 1214 VbeFrameBuffer = FbGopPrivate->VbeFrameBuffer; 1215 MemAddress = Mode->LinearFrameBuffer; 1216 BytesPerScanLine = Mode->BytesPerScanLine; 1217 VbePixelWidth = Mode->BitsPerPixel / 8; 1218 BltUint8 = (UINT8 *) BltBuffer; 1219 TotalBytes = Width * VbePixelWidth; 1220 1221 if (((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) { 1222 return EFI_INVALID_PARAMETER; 1223 } 1224 1225 if (Width == 0 || Height == 0) { 1226 return EFI_INVALID_PARAMETER; 1227 } 1228 // 1229 // We need to fill the Virtual Screen buffer with the blt data. 1230 // The virtual screen is upside down, as the first row is the bootom row of 1231 // the image. 1232 // 1233 if (BltOperation == EfiBltVideoToBltBuffer) { 1234 // 1235 // Video to BltBuffer: Source is Video, destination is BltBuffer 1236 // 1237 if (SourceY + Height > Mode->VerticalResolution) { 1238 return EFI_INVALID_PARAMETER; 1239 } 1240 1241 if (SourceX + Width > Mode->HorizontalResolution) { 1242 return EFI_INVALID_PARAMETER; 1243 } 1244 } else { 1245 // 1246 // BltBuffer to Video: Source is BltBuffer, destination is Video 1247 // 1248 if (DestinationY + Height > Mode->VerticalResolution) { 1249 return EFI_INVALID_PARAMETER; 1250 } 1251 1252 if (DestinationX + Width > Mode->HorizontalResolution) { 1253 return EFI_INVALID_PARAMETER; 1254 } 1255 } 1256 // 1257 // If Delta is zero, then the entire BltBuffer is being used, so Delta 1258 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size, 1259 // the number of bytes in each row can be computed. 1260 // 1261 if (Delta == 0) { 1262 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); 1263 } 1264 // 1265 // We have to raise to TPL Notify, so we make an atomic write the frame buffer. 1266 // We would not want a timer based event (Cursor, ...) to come in while we are 1267 // doing this operation. 1268 // 1269 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY); 1270 1271 switch (BltOperation) { 1272 case EfiBltVideoToBltBuffer: 1273 for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) { 1274 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); 1275 // 1276 // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL 1277 // 1278 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth)); 1279 for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) { 1280 Pixel = VbeBuffer[0] | VbeBuffer[1] << 8 | VbeBuffer[2] << 16 | VbeBuffer[3] << 24; 1281 Blt->Red = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask); 1282 Blt->Blue = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask); 1283 Blt->Green = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask); 1284 Blt->Reserved = 0; 1285 Blt++; 1286 VbeBuffer += VbePixelWidth; 1287 } 1288 1289 } 1290 break; 1291 1292 case EfiBltVideoToVideo: 1293 for (Index = 0; Index < Height; Index++) { 1294 if (DestinationY <= SourceY) { 1295 SrcY = SourceY + Index; 1296 DstY = DestinationY + Index; 1297 } else { 1298 SrcY = SourceY + Height - Index - 1; 1299 DstY = DestinationY + Height - Index - 1; 1300 } 1301 1302 VbeBuffer = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth); 1303 VbeBuffer1 = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth); 1304 1305 gBS->CopyMem ( 1306 VbeBuffer, 1307 VbeBuffer1, 1308 TotalBytes 1309 ); 1310 1311 // 1312 // Update physical frame buffer. 1313 // 1314 CopyVideoBuffer ( 1315 PciIo, 1316 VbeBuffer, 1317 MemAddress, 1318 DestinationX, 1319 DstY, 1320 TotalBytes, 1321 VbePixelWidth, 1322 BytesPerScanLine 1323 ); 1324 } 1325 break; 1326 1327 case EfiBltVideoFill: 1328 VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth); 1329 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8; 1330 // 1331 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer 1332 // 1333 Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) | 1334 ( 1335 (Blt->Green & Mode->Green.Mask) << 1336 Mode->Green.Position 1337 ) | 1338 ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position); 1339 1340 for (Index = 0; Index < Width; Index++) { 1341 gBS->CopyMem ( 1342 VbeBuffer, 1343 &Pixel, 1344 VbePixelWidth 1345 ); 1346 VbeBuffer += VbePixelWidth; 1347 } 1348 1349 VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth); 1350 for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) { 1351 gBS->CopyMem ( 1352 (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth), 1353 VbeBuffer, 1354 TotalBytes 1355 ); 1356 } 1357 1358 for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) { 1359 // 1360 // Update physical frame buffer. 1361 // 1362 CopyVideoBuffer ( 1363 PciIo, 1364 VbeBuffer, 1365 MemAddress, 1366 DestinationX, 1367 DstY, 1368 TotalBytes, 1369 VbePixelWidth, 1370 BytesPerScanLine 1371 ); 1372 } 1373 break; 1374 1375 case EfiBltBufferToVideo: 1376 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) { 1377 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); 1378 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth)); 1379 for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) { 1380 // 1381 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer 1382 // 1383 Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) | 1384 ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) | 1385 ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position); 1386 gBS->CopyMem ( 1387 VbeBuffer, 1388 &Pixel, 1389 VbePixelWidth 1390 ); 1391 Blt++; 1392 VbeBuffer += VbePixelWidth; 1393 } 1394 1395 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth)); 1396 1397 // 1398 // Update physical frame buffer. 1399 // 1400 CopyVideoBuffer ( 1401 PciIo, 1402 VbeBuffer, 1403 MemAddress, 1404 DestinationX, 1405 DstY, 1406 TotalBytes, 1407 VbePixelWidth, 1408 BytesPerScanLine 1409 ); 1410 } 1411 break; 1412 1413 default: ; 1414 } 1415 1416 gBS->RestoreTPL (OriginalTPL); 1417 1418 return EFI_SUCCESS; 1419 } 1420 1421 /** 1422 Graphics Output protocol instance to block transfer for VBE device. 1423 1424 @param This Pointer to Graphics Output protocol instance 1425 @param BltBuffer The data to transfer to screen 1426 @param BltOperation The operation to perform 1427 @param SourceX The X coordinate of the source for BltOperation 1428 @param SourceY The Y coordinate of the source for BltOperation 1429 @param DestinationX The X coordinate of the destination for 1430 BltOperation 1431 @param DestinationY The Y coordinate of the destination for 1432 BltOperation 1433 @param Width The width of a rectangle in the blt rectangle in 1434 pixels 1435 @param Height The height of a rectangle in the blt rectangle in 1436 pixels 1437 @param Delta Not used for EfiBltVideoFill and 1438 EfiBltVideoToVideo operation. If a Delta of 0 is 1439 used, the entire BltBuffer will be operated on. If 1440 a subrectangle of the BltBuffer is used, then 1441 Delta represents the number of bytes in a row of 1442 the BltBuffer. 1443 1444 @retval EFI_INVALID_PARAMETER Invalid parameter passed in 1445 @retval EFI_SUCCESS Blt operation success 1446 1447 **/ 1448 EFI_STATUS 1449 EFIAPI 1450 FbGopGraphicsOutputVbeBlt ( 1451 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, 1452 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL 1453 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, 1454 IN UINTN SourceX, 1455 IN UINTN SourceY, 1456 IN UINTN DestinationX, 1457 IN UINTN DestinationY, 1458 IN UINTN Width, 1459 IN UINTN Height, 1460 IN UINTN Delta 1461 ) 1462 { 1463 FB_VIDEO_DEV *FbGopPrivate; 1464 FB_VIDEO_MODE_DATA *Mode; 1465 1466 if (This == NULL) { 1467 return EFI_INVALID_PARAMETER; 1468 } 1469 1470 FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); 1471 Mode = &FbGopPrivate->ModeData[This->Mode->Mode]; 1472 1473 return FbGopVbeBltWorker ( 1474 FbGopPrivate, 1475 BltBuffer, 1476 BltOperation, 1477 SourceX, 1478 SourceY, 1479 DestinationX, 1480 DestinationY, 1481 Width, 1482 Height, 1483 Delta, 1484 Mode 1485 ); 1486 } 1487 1488 1489 /** 1490 The user Entry Point for module UefiFbGop. The user code starts with this function. 1491 1492 @param[in] ImageHandle The firmware allocated handle for the EFI image. 1493 @param[in] SystemTable A pointer to the EFI System Table. 1494 1495 @retval EFI_SUCCESS The entry point is executed successfully. 1496 @retval other Some error occurs when executing this entry point. 1497 1498 **/ 1499 EFI_STATUS 1500 EFIAPI 1501 FbGopEntryPoint( 1502 IN EFI_HANDLE ImageHandle, 1503 IN EFI_SYSTEM_TABLE *SystemTable 1504 ) 1505 { 1506 EFI_STATUS Status; 1507 EFI_HOB_GUID_TYPE *GuidHob; 1508 1509 // 1510 // Find the frame buffer information guid hob 1511 // 1512 GuidHob = GetFirstGuidHob (&gUefiFrameBufferInfoGuid); 1513 if (GuidHob != NULL) { 1514 // 1515 // Install driver model protocol(s). 1516 // 1517 Status = EfiLibInstallDriverBindingComponentName2 ( 1518 ImageHandle, 1519 SystemTable, 1520 &gFbGopDriverBinding, 1521 ImageHandle, 1522 &gFbGopComponentName, 1523 &gFbGopComponentName2 1524 ); 1525 ASSERT_EFI_ERROR (Status); 1526 } else { 1527 DEBUG ((EFI_D_ERROR, "No FrameBuffer information from coreboot. NO GOP driver !!!\n")); 1528 Status = EFI_ABORTED; 1529 } 1530 return Status; 1531 } 1532 1533