| /** @file | |
| Implementation for a generic GOP driver. | |
| Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include "GraphicsOutput.h" | |
| CONST ACPI_ADR_DEVICE_PATH mGraphicsOutputAdrNode = { | |
| { | |
| ACPI_DEVICE_PATH, | |
| ACPI_ADR_DP, | |
| { sizeof (ACPI_ADR_DEVICE_PATH), 0 }, | |
| }, | |
| ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0) | |
| }; | |
| EFI_PEI_GRAPHICS_DEVICE_INFO_HOB mDefaultGraphicsDeviceInfo = { | |
| MAX_UINT16, MAX_UINT16, MAX_UINT16, MAX_UINT16, MAX_UINT8, MAX_UINT8 | |
| }; | |
| // | |
| // The driver should only start on one graphics controller. | |
| // So a global flag is used to remember that the driver is already started. | |
| // | |
| BOOLEAN mDriverStarted = FALSE; | |
| /** | |
| Returns information for an available graphics mode that the graphics device | |
| and the set of active video output devices supports. | |
| @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance. | |
| @param ModeNumber The mode number to return information on. | |
| @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer. | |
| @param Info A pointer to callee allocated buffer that returns information about ModeNumber. | |
| @retval EFI_SUCCESS Valid mode information was returned. | |
| @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode. | |
| @retval EFI_INVALID_PARAMETER ModeNumber is not valid. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| GraphicsOutputQueryMode ( | |
| IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, | |
| IN UINT32 ModeNumber, | |
| OUT UINTN *SizeOfInfo, | |
| OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info | |
| ) | |
| { | |
| if ((This == NULL) || (Info == NULL) || (SizeOfInfo == NULL) || (ModeNumber >= This->Mode->MaxMode)) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| *SizeOfInfo = This->Mode->SizeOfInfo; | |
| *Info = AllocateCopyPool (*SizeOfInfo, This->Mode->Info); | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Set the video device into the specified mode and clears the visible portions of | |
| the output display to black. | |
| @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance. | |
| @param ModeNumber Abstraction that defines the current video mode. | |
| @retval EFI_SUCCESS The graphics mode specified by ModeNumber was selected. | |
| @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. | |
| @retval EFI_UNSUPPORTED ModeNumber is not supported by this device. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| GraphicsOutputSetMode ( | |
| IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, | |
| IN UINT32 ModeNumber | |
| ) | |
| { | |
| RETURN_STATUS Status; | |
| EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black; | |
| GRAPHICS_OUTPUT_PRIVATE_DATA *Private; | |
| if (ModeNumber >= This->Mode->MaxMode) { | |
| return EFI_UNSUPPORTED; | |
| } | |
| Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (This); | |
| Black.Blue = 0; | |
| Black.Green = 0; | |
| Black.Red = 0; | |
| Black.Reserved = 0; | |
| Status = FrameBufferBlt ( | |
| Private->FrameBufferBltLibConfigure, | |
| &Black, | |
| EfiBltVideoFill, | |
| 0, | |
| 0, | |
| 0, | |
| 0, | |
| This->Mode->Info->HorizontalResolution, | |
| This->Mode->Info->VerticalResolution, | |
| 0 | |
| ); | |
| return RETURN_ERROR (Status) ? EFI_DEVICE_ERROR : EFI_SUCCESS; | |
| } | |
| /** | |
| Blt a rectangle of pixels on the graphics screen. Blt stands for BLock Transfer. | |
| @param This Protocol instance pointer. | |
| @param BltBuffer The data to transfer to the graphics screen. | |
| Size is at least Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL). | |
| @param BltOperation The operation to perform when copying BltBuffer on to the graphics screen. | |
| @param SourceX The X coordinate of source for the BltOperation. | |
| @param SourceY The Y coordinate of source for the BltOperation. | |
| @param DestinationX The X coordinate of destination for the BltOperation. | |
| @param DestinationY The Y coordinate of destination for the BltOperation. | |
| @param Width The width of a rectangle in the blt rectangle in pixels. | |
| @param Height The height of a rectangle in the blt rectangle in pixels. | |
| @param Delta Not used for EfiBltVideoFill or the EfiBltVideoToVideo operation. | |
| If a Delta of zero is used, the entire BltBuffer is being operated on. | |
| If a subrectangle of the BltBuffer is being used then Delta | |
| represents the number of bytes in a row of the BltBuffer. | |
| @retval EFI_SUCCESS BltBuffer was drawn to the graphics screen. | |
| @retval EFI_INVALID_PARAMETER BltOperation is not valid. | |
| @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| GraphicsOutputBlt ( | |
| IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, | |
| IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL, | |
| IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, | |
| IN UINTN SourceX, | |
| IN UINTN SourceY, | |
| IN UINTN DestinationX, | |
| IN UINTN DestinationY, | |
| IN UINTN Width, | |
| IN UINTN Height, | |
| IN UINTN Delta OPTIONAL | |
| ) | |
| { | |
| RETURN_STATUS Status; | |
| EFI_TPL Tpl; | |
| GRAPHICS_OUTPUT_PRIVATE_DATA *Private; | |
| Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (This); | |
| // | |
| // We have to raise to TPL_NOTIFY, so we make an atomic write to the frame buffer. | |
| // We would not want a timer based event (Cursor, ...) to come in while we are | |
| // doing this operation. | |
| // | |
| Tpl = gBS->RaiseTPL (TPL_NOTIFY); | |
| Status = FrameBufferBlt ( | |
| Private->FrameBufferBltLibConfigure, | |
| BltBuffer, | |
| BltOperation, | |
| SourceX, | |
| SourceY, | |
| DestinationX, | |
| DestinationY, | |
| Width, | |
| Height, | |
| Delta | |
| ); | |
| gBS->RestoreTPL (Tpl); | |
| return RETURN_ERROR (Status) ? EFI_INVALID_PARAMETER : EFI_SUCCESS; | |
| } | |
| CONST GRAPHICS_OUTPUT_PRIVATE_DATA mGraphicsOutputInstanceTemplate = { | |
| GRAPHICS_OUTPUT_PRIVATE_DATA_SIGNATURE, // Signature | |
| NULL, // GraphicsOutputHandle | |
| { | |
| GraphicsOutputQueryMode, | |
| GraphicsOutputSetMode, | |
| GraphicsOutputBlt, | |
| NULL // Mode | |
| }, | |
| { | |
| 1, // MaxMode | |
| 0, // Mode | |
| NULL, // Info | |
| sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), // SizeOfInfo | |
| 0, // FrameBufferBase | |
| 0 // FrameBufferSize | |
| }, | |
| NULL, // DevicePath | |
| NULL, // PciIo | |
| 0, // PciAttributes | |
| NULL, // FrameBufferBltLibConfigure | |
| 0 // FrameBufferBltLibConfigureSize | |
| }; | |
| /** | |
| Test whether the Controller can be managed by the driver. | |
| @param This Driver Binding protocol instance pointer. | |
| @param Controller The PCI controller. | |
| @param RemainingDevicePath Optional parameter use to pick a specific child | |
| device to start. | |
| @retval EFI_SUCCESS The driver can manage the video device. | |
| @retval other The driver cannot manage the video device. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| GraphicsOutputDriverBindingSupported ( | |
| IN EFI_DRIVER_BINDING_PROTOCOL *This, | |
| IN EFI_HANDLE Controller, | |
| IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| EFI_PCI_IO_PROTOCOL *PciIo; | |
| EFI_DEVICE_PATH_PROTOCOL *DevicePath; | |
| // | |
| // Since there is only one GraphicsInfo HOB, the driver only manages one video device. | |
| // | |
| if (mDriverStarted) { | |
| return EFI_ALREADY_STARTED; | |
| } | |
| // | |
| // Test the PCI I/O Protocol | |
| // | |
| Status = gBS->OpenProtocol ( | |
| Controller, | |
| &gEfiPciIoProtocolGuid, | |
| (VOID **)&PciIo, | |
| This->DriverBindingHandle, | |
| Controller, | |
| EFI_OPEN_PROTOCOL_BY_DRIVER | |
| ); | |
| if (Status == EFI_ALREADY_STARTED) { | |
| Status = EFI_SUCCESS; | |
| } | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| gBS->CloseProtocol ( | |
| Controller, | |
| &gEfiPciIoProtocolGuid, | |
| This->DriverBindingHandle, | |
| Controller | |
| ); | |
| // | |
| // Test the DevicePath protocol | |
| // | |
| Status = gBS->OpenProtocol ( | |
| Controller, | |
| &gEfiDevicePathProtocolGuid, | |
| (VOID **)&DevicePath, | |
| This->DriverBindingHandle, | |
| Controller, | |
| EFI_OPEN_PROTOCOL_BY_DRIVER | |
| ); | |
| if (Status == EFI_ALREADY_STARTED) { | |
| Status = EFI_SUCCESS; | |
| } | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| gBS->CloseProtocol ( | |
| Controller, | |
| &gEfiDevicePathProtocolGuid, | |
| This->DriverBindingHandle, | |
| Controller | |
| ); | |
| if ((RemainingDevicePath == NULL) || | |
| IsDevicePathEnd (RemainingDevicePath) || | |
| (CompareMem (RemainingDevicePath, &mGraphicsOutputAdrNode, sizeof (mGraphicsOutputAdrNode)) == 0)) | |
| { | |
| return EFI_SUCCESS; | |
| } else { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| } | |
| /** | |
| Start the video controller. | |
| @param This Driver Binding protocol instance pointer. | |
| @param ControllerHandle The PCI controller. | |
| @param RemainingDevicePath Optional parameter use to pick a specific child | |
| device to start. | |
| @retval EFI_SUCCESS The driver starts to manage the video device. | |
| @retval other The driver cannot manage the video device. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| GraphicsOutputDriverBindingStart ( | |
| IN EFI_DRIVER_BINDING_PROTOCOL *This, | |
| IN EFI_HANDLE Controller, | |
| IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| RETURN_STATUS ReturnStatus; | |
| GRAPHICS_OUTPUT_PRIVATE_DATA *Private; | |
| EFI_PCI_IO_PROTOCOL *PciIo; | |
| EFI_DEVICE_PATH *PciDevicePath; | |
| PCI_TYPE00 Pci; | |
| UINT8 Index; | |
| EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources; | |
| VOID *HobStart; | |
| EFI_PEI_GRAPHICS_INFO_HOB *GraphicsInfo; | |
| EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *DeviceInfo; | |
| EFI_PHYSICAL_ADDRESS FrameBufferBase; | |
| FrameBufferBase = 0; | |
| HobStart = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid); | |
| ASSERT ((HobStart != NULL) && (GET_GUID_HOB_DATA_SIZE (HobStart) == sizeof (EFI_PEI_GRAPHICS_INFO_HOB))); | |
| GraphicsInfo = (EFI_PEI_GRAPHICS_INFO_HOB *)(GET_GUID_HOB_DATA (HobStart)); | |
| HobStart = GetFirstGuidHob (&gEfiGraphicsDeviceInfoHobGuid); | |
| if ((HobStart == NULL) || (GET_GUID_HOB_DATA_SIZE (HobStart) < sizeof (*DeviceInfo))) { | |
| // | |
| // Use default device infomation when the device info HOB doesn't exist | |
| // | |
| DeviceInfo = &mDefaultGraphicsDeviceInfo; | |
| DEBUG ((DEBUG_INFO, "[%a]: GraphicsDeviceInfo HOB doesn't exist!\n", gEfiCallerBaseName)); | |
| } else { | |
| DeviceInfo = (EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *)(GET_GUID_HOB_DATA (HobStart)); | |
| DEBUG (( | |
| DEBUG_INFO, | |
| "[%a]: GraphicsDeviceInfo HOB:\n" | |
| " VendorId = %04x, DeviceId = %04x,\n" | |
| " RevisionId = %02x, BarIndex = %x,\n" | |
| " SubsystemVendorId = %04x, SubsystemId = %04x\n", | |
| gEfiCallerBaseName, | |
| DeviceInfo->VendorId, | |
| DeviceInfo->DeviceId, | |
| DeviceInfo->RevisionId, | |
| DeviceInfo->BarIndex, | |
| DeviceInfo->SubsystemVendorId, | |
| DeviceInfo->SubsystemId | |
| )); | |
| } | |
| // | |
| // Open the PCI I/O Protocol | |
| // | |
| Status = gBS->OpenProtocol ( | |
| Controller, | |
| &gEfiPciIoProtocolGuid, | |
| (VOID **)&PciIo, | |
| This->DriverBindingHandle, | |
| Controller, | |
| EFI_OPEN_PROTOCOL_BY_DRIVER | |
| ); | |
| if (Status == EFI_ALREADY_STARTED) { | |
| Status = EFI_SUCCESS; | |
| } | |
| ASSERT_EFI_ERROR (Status); | |
| Status = gBS->OpenProtocol ( | |
| Controller, | |
| &gEfiDevicePathProtocolGuid, | |
| (VOID **)&PciDevicePath, | |
| This->DriverBindingHandle, | |
| Controller, | |
| EFI_OPEN_PROTOCOL_BY_DRIVER | |
| ); | |
| if (Status == EFI_ALREADY_STARTED) { | |
| Status = EFI_SUCCESS; | |
| } | |
| ASSERT_EFI_ERROR (Status); | |
| // | |
| // Read the PCI Class Code from the PCI Device | |
| // | |
| Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0, sizeof (Pci), &Pci); | |
| if (!EFI_ERROR (Status)) { | |
| if (!IS_PCI_DISPLAY (&Pci) || ( | |
| ((DeviceInfo->VendorId != MAX_UINT16) && (DeviceInfo->VendorId != Pci.Hdr.VendorId)) || | |
| ((DeviceInfo->DeviceId != MAX_UINT16) && (DeviceInfo->DeviceId != Pci.Hdr.DeviceId)) || | |
| ((DeviceInfo->RevisionId != MAX_UINT8) && (DeviceInfo->RevisionId != Pci.Hdr.RevisionID)) || | |
| ((DeviceInfo->SubsystemVendorId != MAX_UINT16) && (DeviceInfo->SubsystemVendorId != Pci.Device.SubsystemVendorID)) || | |
| ((DeviceInfo->SubsystemId != MAX_UINT16) && (DeviceInfo->SubsystemId != Pci.Device.SubsystemID)) | |
| ) | |
| ) | |
| { | |
| // | |
| // It's not a video device, or device infomation doesn't match. | |
| // | |
| Status = EFI_UNSUPPORTED; | |
| } else { | |
| // | |
| // If it's a video device and device information matches, use the BarIndex | |
| // from device information, or any BAR if BarIndex is not specified | |
| // whose size >= the frame buffer size from GraphicsInfo HOB. | |
| // Store the new frame buffer base. | |
| // | |
| for (Index = 0; Index < MAX_PCI_BAR; Index++) { | |
| if ((DeviceInfo->BarIndex != MAX_UINT8) && (DeviceInfo->BarIndex != Index)) { | |
| continue; | |
| } | |
| Status = PciIo->GetBarAttributes (PciIo, Index, NULL, (VOID **)&Resources); | |
| if (!EFI_ERROR (Status)) { | |
| DEBUG (( | |
| DEBUG_INFO, | |
| "[%a]: BAR[%d]: Base = %lx, Length = %lx\n", | |
| gEfiCallerBaseName, | |
| Index, | |
| Resources->AddrRangeMin, | |
| Resources->AddrLen | |
| )); | |
| if ((Resources->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) && | |
| (Resources->Len == (UINT16)(sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3)) && | |
| (Resources->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) && | |
| (Resources->AddrLen >= GraphicsInfo->FrameBufferSize) | |
| ) | |
| { | |
| if (FrameBufferBase == 0) { | |
| FrameBufferBase = Resources->AddrRangeMin; | |
| } | |
| if (DeviceInfo->BarIndex == MAX_UINT8) { | |
| if (Resources->AddrRangeMin == GraphicsInfo->FrameBufferBase) { | |
| FrameBufferBase = Resources->AddrRangeMin; | |
| break; | |
| } | |
| } else { | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| if (Index == MAX_PCI_BAR) { | |
| Status = EFI_UNSUPPORTED; | |
| } else { | |
| DEBUG ((DEBUG_INFO, "[%a]: ... matched!\n", gEfiCallerBaseName)); | |
| } | |
| } | |
| } | |
| if (EFI_ERROR (Status)) { | |
| goto CloseProtocols; | |
| } | |
| if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) { | |
| return EFI_SUCCESS; | |
| } | |
| Private = AllocateCopyPool (sizeof (mGraphicsOutputInstanceTemplate), &mGraphicsOutputInstanceTemplate); | |
| if (Private == NULL) { | |
| Status = EFI_OUT_OF_RESOURCES; | |
| goto CloseProtocols; | |
| } | |
| Private->GraphicsOutputMode.FrameBufferBase = FrameBufferBase; | |
| Private->GraphicsOutputMode.FrameBufferSize = GraphicsInfo->FrameBufferSize; | |
| Private->GraphicsOutputMode.Info = &GraphicsInfo->GraphicsMode; | |
| // | |
| // Fix up Mode pointer in GraphicsOutput | |
| // | |
| Private->GraphicsOutput.Mode = &Private->GraphicsOutputMode; | |
| // | |
| // Set attributes | |
| // | |
| Status = PciIo->Attributes ( | |
| PciIo, | |
| EfiPciIoAttributeOperationGet, | |
| 0, | |
| &Private->PciAttributes | |
| ); | |
| if (!EFI_ERROR (Status)) { | |
| Status = PciIo->Attributes ( | |
| PciIo, | |
| EfiPciIoAttributeOperationEnable, | |
| EFI_PCI_DEVICE_ENABLE, | |
| NULL | |
| ); | |
| } | |
| if (EFI_ERROR (Status)) { | |
| goto FreeMemory; | |
| } | |
| // | |
| // Create the FrameBufferBltLib configuration. | |
| // | |
| ReturnStatus = FrameBufferBltConfigure ( | |
| (VOID *)(UINTN)Private->GraphicsOutput.Mode->FrameBufferBase, | |
| Private->GraphicsOutput.Mode->Info, | |
| Private->FrameBufferBltLibConfigure, | |
| &Private->FrameBufferBltLibConfigureSize | |
| ); | |
| if (ReturnStatus == RETURN_BUFFER_TOO_SMALL) { | |
| Private->FrameBufferBltLibConfigure = AllocatePool (Private->FrameBufferBltLibConfigureSize); | |
| if (Private->FrameBufferBltLibConfigure != NULL) { | |
| ReturnStatus = FrameBufferBltConfigure ( | |
| (VOID *)(UINTN)Private->GraphicsOutput.Mode->FrameBufferBase, | |
| Private->GraphicsOutput.Mode->Info, | |
| Private->FrameBufferBltLibConfigure, | |
| &Private->FrameBufferBltLibConfigureSize | |
| ); | |
| } | |
| } | |
| if (RETURN_ERROR (ReturnStatus)) { | |
| Status = EFI_OUT_OF_RESOURCES; | |
| goto RestorePciAttributes; | |
| } | |
| Private->DevicePath = AppendDevicePathNode (PciDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&mGraphicsOutputAdrNode); | |
| if (Private->DevicePath == NULL) { | |
| Status = EFI_OUT_OF_RESOURCES; | |
| goto RestorePciAttributes; | |
| } | |
| Status = gBS->InstallMultipleProtocolInterfaces ( | |
| &Private->GraphicsOutputHandle, | |
| &gEfiGraphicsOutputProtocolGuid, | |
| &Private->GraphicsOutput, | |
| &gEfiDevicePathProtocolGuid, | |
| Private->DevicePath, | |
| NULL | |
| ); | |
| if (!EFI_ERROR (Status)) { | |
| Status = gBS->OpenProtocol ( | |
| Controller, | |
| &gEfiPciIoProtocolGuid, | |
| (VOID **)&Private->PciIo, | |
| This->DriverBindingHandle, | |
| Private->GraphicsOutputHandle, | |
| EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER | |
| ); | |
| if (!EFI_ERROR (Status)) { | |
| mDriverStarted = TRUE; | |
| } else { | |
| gBS->UninstallMultipleProtocolInterfaces ( | |
| Private->GraphicsOutputHandle, | |
| &gEfiGraphicsOutputProtocolGuid, | |
| &Private->GraphicsOutput, | |
| &gEfiDevicePathProtocolGuid, | |
| Private->DevicePath, | |
| NULL | |
| ); | |
| } | |
| } | |
| RestorePciAttributes: | |
| if (EFI_ERROR (Status)) { | |
| // | |
| // Restore original PCI attributes | |
| // | |
| PciIo->Attributes ( | |
| PciIo, | |
| EfiPciIoAttributeOperationSet, | |
| Private->PciAttributes, | |
| NULL | |
| ); | |
| } | |
| FreeMemory: | |
| if (EFI_ERROR (Status)) { | |
| if (Private != NULL) { | |
| if (Private->DevicePath != NULL) { | |
| FreePool (Private->DevicePath); | |
| } | |
| if (Private->FrameBufferBltLibConfigure != NULL) { | |
| FreePool (Private->FrameBufferBltLibConfigure); | |
| } | |
| FreePool (Private); | |
| } | |
| } | |
| CloseProtocols: | |
| if (EFI_ERROR (Status)) { | |
| // | |
| // Close the PCI I/O Protocol | |
| // | |
| gBS->CloseProtocol ( | |
| Controller, | |
| &gEfiDevicePathProtocolGuid, | |
| This->DriverBindingHandle, | |
| Controller | |
| ); | |
| // | |
| // Close the PCI I/O Protocol | |
| // | |
| gBS->CloseProtocol ( | |
| Controller, | |
| &gEfiPciIoProtocolGuid, | |
| This->DriverBindingHandle, | |
| Controller | |
| ); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Stop the video controller. | |
| @param This Driver Binding protocol instance pointer. | |
| @param Controller The PCI controller. | |
| @param NumberOfChildren The number of child device handles in ChildHandleBuffer. | |
| @param ChildHandleBuffer An array of child handles to be freed. May be NULL | |
| if NumberOfChildren is 0. | |
| @retval EFI_SUCCESS The device was stopped. | |
| @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| GraphicsOutputDriverBindingStop ( | |
| IN EFI_DRIVER_BINDING_PROTOCOL *This, | |
| IN EFI_HANDLE Controller, | |
| IN UINTN NumberOfChildren, | |
| IN EFI_HANDLE *ChildHandleBuffer | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop; | |
| GRAPHICS_OUTPUT_PRIVATE_DATA *Private; | |
| if (NumberOfChildren == 0) { | |
| // | |
| // Close the PCI I/O Protocol | |
| // | |
| Status = gBS->CloseProtocol ( | |
| Controller, | |
| &gEfiPciIoProtocolGuid, | |
| This->DriverBindingHandle, | |
| Controller | |
| ); | |
| ASSERT_EFI_ERROR (Status); | |
| Status = gBS->CloseProtocol ( | |
| Controller, | |
| &gEfiDevicePathProtocolGuid, | |
| This->DriverBindingHandle, | |
| Controller | |
| ); | |
| ASSERT_EFI_ERROR (Status); | |
| return EFI_SUCCESS; | |
| } | |
| ASSERT (NumberOfChildren == 1); | |
| Status = gBS->OpenProtocol ( | |
| ChildHandleBuffer[0], | |
| &gEfiGraphicsOutputProtocolGuid, | |
| (VOID **)&Gop, | |
| This->DriverBindingHandle, | |
| ChildHandleBuffer[0], | |
| EFI_OPEN_PROTOCOL_GET_PROTOCOL | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (Gop); | |
| Status = gBS->CloseProtocol ( | |
| Controller, | |
| &gEfiPciIoProtocolGuid, | |
| This->DriverBindingHandle, | |
| Private->GraphicsOutputHandle | |
| ); | |
| ASSERT_EFI_ERROR (Status); | |
| // | |
| // Remove the GOP protocol interface from the system | |
| // | |
| Status = gBS->UninstallMultipleProtocolInterfaces ( | |
| Private->GraphicsOutputHandle, | |
| &gEfiGraphicsOutputProtocolGuid, | |
| &Private->GraphicsOutput, | |
| &gEfiDevicePathProtocolGuid, | |
| Private->DevicePath, | |
| NULL | |
| ); | |
| if (!EFI_ERROR (Status)) { | |
| // | |
| // Restore original PCI attributes | |
| // | |
| Status = Private->PciIo->Attributes ( | |
| Private->PciIo, | |
| EfiPciIoAttributeOperationSet, | |
| Private->PciAttributes, | |
| NULL | |
| ); | |
| ASSERT_EFI_ERROR (Status); | |
| FreePool (Private->DevicePath); | |
| FreePool (Private->FrameBufferBltLibConfigure); | |
| mDriverStarted = FALSE; | |
| } else { | |
| Status = gBS->OpenProtocol ( | |
| Controller, | |
| &gEfiPciIoProtocolGuid, | |
| (VOID **)&Private->PciIo, | |
| This->DriverBindingHandle, | |
| Private->GraphicsOutputHandle, | |
| EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER | |
| ); | |
| ASSERT_EFI_ERROR (Status); | |
| } | |
| return Status; | |
| } | |
| EFI_DRIVER_BINDING_PROTOCOL mGraphicsOutputDriverBinding = { | |
| GraphicsOutputDriverBindingSupported, | |
| GraphicsOutputDriverBindingStart, | |
| GraphicsOutputDriverBindingStop, | |
| 0x10, | |
| NULL, | |
| NULL | |
| }; | |
| /** | |
| The Entry Point for GraphicsOutput driver. | |
| It installs DriverBinding, ComponentName and ComponentName2 protocol if there is | |
| GraphicsInfo HOB passed from Graphics PEIM. | |
| @param[in] ImageHandle The firmware allocated handle for the EFI image. | |
| @param[in] SystemTable A pointer to the EFI System Table. | |
| @retval EFI_SUCCESS The entry point is executed successfully. | |
| @retval other Some error occurs when executing this entry point. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| InitializeGraphicsOutput ( | |
| IN EFI_HANDLE ImageHandle, | |
| IN EFI_SYSTEM_TABLE *SystemTable | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| VOID *HobStart; | |
| HobStart = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid); | |
| if ((HobStart == NULL) || (GET_GUID_HOB_DATA_SIZE (HobStart) < sizeof (EFI_PEI_GRAPHICS_INFO_HOB))) { | |
| return EFI_NOT_FOUND; | |
| } | |
| Status = EfiLibInstallDriverBindingComponentName2 ( | |
| ImageHandle, | |
| SystemTable, | |
| &mGraphicsOutputDriverBinding, | |
| ImageHandle, | |
| &mGraphicsOutputComponentName, | |
| &mGraphicsOutputComponentName2 | |
| ); | |
| ASSERT_EFI_ERROR (Status); | |
| return Status; | |
| } |