From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
To: Pete Batard <pete@akeo.ie>
Cc: "edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Subject: Re: [PATCH v2 edk2-platforms 08/20] Platform/Broadcom/RPi3: Add Display driver
Date: Fri, 14 Dec 2018 16:06:59 +0100 [thread overview]
Message-ID: <CAKv+Gu95miOiOMmvUR7fBbCn0C7H607+dM=v9TSWhx6pQWOL6w@mail.gmail.com> (raw)
In-Reply-To: <20181210123853.4864-9-pete@akeo.ie>
On Mon, 10 Dec 2018 at 13:39, Pete Batard <pete@akeo.ie> wrote:
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Pete Batard <pete@akeo.ie>
Please fix the usual things like INF_VERSION and space before ( in
function or macro invocations.
Otherwise, this looks fine
'
> ---
> Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/ComponentName.c | 222 +++++++
> Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.c | 606 ++++++++++++++++++++
> Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.h | 43 ++
> Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.inf | 71 +++
> Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/Screenshot.c | 379 ++++++++++++
> 5 files changed, 1321 insertions(+)
>
> diff --git a/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/ComponentName.c b/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/ComponentName.c
> new file mode 100644
> index 000000000000..e639826c60b1
> --- /dev/null
> +++ b/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/ComponentName.c
> @@ -0,0 +1,222 @@
> +/** @file
> + *
> + * Copyright (c) 2018, Andrei Warkentin <andrey.warkentin@gmail.com>
> + * Copyright (c) 2006-2016, Intel Corporation. All rights reserved.
> + *
> + * This program and the accompanying materials
> + * are licensed and made available under the terms and conditions of the BSD License
> + * which accompanies this distribution. The full text of the license may be found at
> + * http://opensource.org/licenses/bsd-license.php
> + *
> + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> + *
> + **/
> +
> +#include "DisplayDxe.h"
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +ComponentNameGetDriverName (
> + IN EFI_COMPONENT_NAME_PROTOCOL *This,
> + IN CHAR8 *Language,
> + OUT CHAR16 **DriverName
> +);
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +ComponentNameGetControllerName (
> + IN EFI_COMPONENT_NAME_PROTOCOL *This,
> + IN EFI_HANDLE ControllerHandle,
> + IN EFI_HANDLE ChildHandle,
> + IN CHAR8 *Language,
> + OUT CHAR16 **ControllerName
> + );
> +
> +//
> +// EFI Component Name Protocol
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
> + ComponentNameGetDriverName,
> + ComponentNameGetControllerName,
> + "eng"
> +};
> +
> +//
> +// EFI Component Name 2 Protocol
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
> + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) ComponentNameGetDriverName,
> + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) ComponentNameGetControllerName,
> + "en"
> +};
> +
> +
> +STATIC EFI_UNICODE_STRING_TABLE mDriverName[] = {
> + {
> + "eng;en",
> + (CHAR16 *)L"Raspberry Pi Display Driver"
> + },
> + {
> + NULL,
> + NULL
> + }
> +};
> +
> +STATIC EFI_UNICODE_STRING_TABLE mDeviceName[] = {
> + {
> + "eng;en",
> + (CHAR16 *)L"Raspberry Pi Framebuffer"
> + },
> + {
> + NULL,
> + NULL
> + }
> +};
> +
> +/**
> + Retrieves a Unicode string that is the user readable name of the driver.
> +
> + This function retrieves the user readable name of a driver in the form of a
> + Unicode string. If the driver specified by This has a user readable name in
> + the language specified by Language, then a pointer to the driver name is
> + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
> + by This does not support the language specified by Language,
> + then EFI_UNSUPPORTED is returned.
> +
> + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
> + EFI_COMPONENT_NAME_PROTOCOL instance.
> +
> + @param Language[in] A pointer to a Null-terminated ASCII string
> + array indicating the language. This is the
> + language of the driver name that the caller is
> + requesting, and it must match one of the
> + languages specified in SupportedLanguages. The
> + number of languages supported by a driver is up
> + to the driver writer. Language is specified
> + in RFC 4646 or ISO 639-2 language code format.
> +
> + @param DriverName[out] A pointer to the Unicode string to return.
> + This Unicode string is the name of the
> + driver specified by This in the language
> + specified by Language.
> +
> + @retval EFI_SUCCESS The Unicode string for the Driver specified by
> + This and the language specified by Language was
> + returned in DriverName.
> +
> + @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> + @retval EFI_INVALID_PARAMETER DriverName is NULL.
> +
> + @retval EFI_UNSUPPORTED The driver specified by This does not support
> + the language specified by Language.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +ComponentNameGetDriverName (
> + IN EFI_COMPONENT_NAME_PROTOCOL *This,
> + IN CHAR8 *Language,
> + OUT CHAR16 **DriverName
> + )
> +{
> + return LookupUnicodeString2 (
> + Language,
> + This->SupportedLanguages,
> + mDriverName,
> + DriverName,
> + (BOOLEAN)(This == &gComponentName)
> + );
> +}
> +
> +/**
> + Retrieves a Unicode string that is the user readable name of the controller
> + that is being managed by a driver.
> +
> + This function retrieves the user readable name of the controller specified by
> + ControllerHandle and ChildHandle in the form of a Unicode string. If the
> + driver specified by This has a user readable name in the language specified by
> + Language, then a pointer to the controller name is returned in ControllerName,
> + and EFI_SUCCESS is returned. If the driver specified by This is not currently
> + managing the controller specified by ControllerHandle and ChildHandle,
> + then EFI_UNSUPPORTED is returned. If the driver specified by This does not
> + support the language specified by Language, then EFI_UNSUPPORTED is returned.
> +
> + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
> + EFI_COMPONENT_NAME_PROTOCOL instance.
> +
> + @param ControllerHandle[in] The handle of a controller that the driver
> + specified by This is managing. This handle
> + specifies the controller whose name is to be
> + returned.
> +
> + @param ChildHandle[in] The handle of the child controller to retrieve
> + the name of. This is an optional parameter that
> + may be NULL. It will be NULL for device
> + drivers. It will also be NULL for a bus drivers
> + that wish to retrieve the name of the bus
> + controller. It will not be NULL for a bus
> + driver that wishes to retrieve the name of a
> + child controller.
> +
> + @param Language[in] A pointer to a Null-terminated ASCII string
> + array indicating the language. This is the
> + language of the driver name that the caller is
> + requesting, and it must match one of the
> + languages specified in SupportedLanguages. The
> + number of languages supported by a driver is up
> + to the driver writer. Language is specified in
> + RFC 4646 or ISO 639-2 language code format.
> +
> + @param ControllerName[out] A pointer to the Unicode string to return.
> + This Unicode string is the name of the
> + controller specified by ControllerHandle and
> + ChildHandle in the language specified by
> + Language from the point of view of the driver
> + specified by This.
> +
> + @retval EFI_SUCCESS The Unicode string for the user readable name in
> + the language specified by Language for the
> + driver specified by This was returned in
> + DriverName.
> +
> + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
> +
> + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
> + EFI_HANDLE.
> +
> + @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> + @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> +
> + @retval EFI_UNSUPPORTED The driver specified by This is not currently
> + managing the controller specified by
> + ControllerHandle and ChildHandle.
> +
> + @retval EFI_UNSUPPORTED The driver specified by This does not support
> + the language specified by Language.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +ComponentNameGetControllerName (
> + IN EFI_COMPONENT_NAME_PROTOCOL *This,
> + IN EFI_HANDLE ControllerHandle,
> + IN EFI_HANDLE ChildHandle,
> + IN CHAR8 *Language,
> + OUT CHAR16 **ControllerName
> + )
> +{
> + return LookupUnicodeString2 (
> + Language,
> + This->SupportedLanguages,
> + mDeviceName,
> + ControllerName,
> + (BOOLEAN)(This == &gComponentName)
> + );
> +}
> diff --git a/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.c b/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.c
> new file mode 100644
> index 000000000000..e8b7f67c8870
> --- /dev/null
> +++ b/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.c
> @@ -0,0 +1,606 @@
> +/** @file
> + *
> + * Copyright (c) 2017-2018, Andrei Warkentin <andrey.warkentin@gmail.com>
> + * Copyright (c) Microsoft Corporation. All rights reserved.
> + *
> + * This program and the accompanying materials
> + * are licensed and made available under the terms and conditions of the BSD License
> + * which accompanies this distribution. The full text of the license may be found at
> + * http://opensource.org/licenses/bsd-license.php
> + *
> + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> + *
> + **/
> +
> +#include "DisplayDxe.h"
> +
> +#define POS_TO_FB(posX, posY) ((UINT8 *) \
> + ((UINTN)This->Mode->FrameBufferBase + \
> + (posY) * This->Mode->Info->PixelsPerScanLine * \
> + PI3_BYTES_PER_PIXEL + \
> + (posX) * PI3_BYTES_PER_PIXEL))
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +DriverSupported (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE Controller,
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
> + );
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +DriverStart (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE Controller,
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
> + );
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +DriverStop (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE Controller,
> + IN UINTN NumberOfChildren,
> + IN EFI_HANDLE *ChildHandleBuffer
> + );
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +DisplayQueryMode(
> + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
> + IN UINT32 ModeNumber,
> + OUT UINTN *SizeOfInfo,
> + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
> + );
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +DisplaySetMode(
> + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
> + IN UINT32 ModeNumber
> + );
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +DisplayBlt(
> + 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
> + );
> +
> +STATIC EFI_DRIVER_BINDING_PROTOCOL mDriverBinding = {
> + DriverSupported,
> + DriverStart,
> + DriverStop,
> + 0xa,
> + NULL,
> + NULL
> +};
> +
> +typedef struct {
> + VENDOR_DEVICE_PATH DisplayDevicePath;
> + EFI_DEVICE_PATH EndDevicePath;
> +} DISPLAY_DEVICE_PATH;
> +
> +typedef struct {
> + UINT32 Width;
> + UINT32 Height;
> +} GOP_MODE_DATA;
> +
> +STATIC UINT32 mBootWidth;
> +STATIC UINT32 mBootHeight;
> +STATIC EFI_HANDLE mDevice;
> +STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL *mFwProtocol;
> +STATIC EFI_CPU_ARCH_PROTOCOL *mCpu;
> +
> +STATIC UINTN mLastMode;
> +STATIC GOP_MODE_DATA mGopModeData[] = {
> + { 800, 600 }, /* Legacy */
> + { 640, 480 }, /* Legacy */
> + { 1024, 768 }, /* Legacy */
> + { 1280, 720 }, /* 720p */
> + { 1920, 1080 }, /* 1080p */
> + { 0, 0 }, /* Physical */
> +};
> +
> +STATIC DISPLAY_DEVICE_PATH mDisplayProtoDevicePath =
> + {
> + {
> + {
> + HARDWARE_DEVICE_PATH,
> + HW_VENDOR_DP,
> + {
> + (UINT8)(sizeof(VENDOR_DEVICE_PATH)),
> + (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8),
> + }
> + },
> + EFI_CALLER_ID_GUID,
> + },
> + {
> + END_DEVICE_PATH_TYPE,
> + END_ENTIRE_DEVICE_PATH_SUBTYPE,
> + {
> + sizeof(EFI_DEVICE_PATH_PROTOCOL),
> + 0
> + }
> + }
> + };
> +
> +#define PI3_BITS_PER_PIXEL (32)
> +#define PI3_BYTES_PER_PIXEL (PI3_BITS_PER_PIXEL / 8)
> +
> +EFI_GRAPHICS_OUTPUT_PROTOCOL gDisplayProto = {
> + DisplayQueryMode,
> + DisplaySetMode,
> + DisplayBlt,
> + NULL
> +};
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +DisplayQueryMode(
> + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
> + IN UINT32 ModeNumber,
> + OUT UINTN *SizeOfInfo,
> + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
> + )
> +{
> + EFI_STATUS Status;
> + GOP_MODE_DATA *Mode;
> +
> + if (ModeNumber > mLastMode) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Status = gBS->AllocatePool(
> + EfiBootServicesData,
> + sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
> + (VOID **)Info
> + );
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Mode = &mGopModeData[ModeNumber];
> +
> + *SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
> + (*Info)->Version = This->Mode->Info->Version;
> + (*Info)->HorizontalResolution = Mode->Width;
> + (*Info)->VerticalResolution = Mode->Height;
> + (*Info)->PixelFormat = This->Mode->Info->PixelFormat;
> + (*Info)->PixelsPerScanLine = Mode->Width;
> +
> + return EFI_SUCCESS;
> +}
> +
> +STATIC
> +VOID
> +ClearScreen(
> + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This
> + )
> +{
> + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fill;
> +
> + Fill.Red = 0x00;
> + Fill.Green = 0x00;
> + Fill.Blue = 0x00;
> + This->Blt (This, &Fill, EfiBltVideoFill,
> + 0, 0, 0, 0, This->Mode->Info->HorizontalResolution,
> + This->Mode->Info->VerticalResolution,
> + This->Mode->Info->HorizontalResolution *
> + sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +DisplaySetMode(
> + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
> + IN UINT32 ModeNumber
> + )
> +{
> + UINTN FbSize;
> + UINTN FbPitch;
> + EFI_STATUS Status;
> + EFI_PHYSICAL_ADDRESS FbBase;
> + GOP_MODE_DATA *Mode = &mGopModeData[ModeNumber];
> +
> + if (ModeNumber > mLastMode) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + DEBUG((DEBUG_INFO, "Setting mode %u from %u: %u x %u\n",
> + ModeNumber, This->Mode->Mode, Mode->Width, Mode->Height));
> + Status = mFwProtocol->GetFB(Mode->Width, Mode->Height,
> + PI3_BITS_PER_PIXEL, &FbBase,
> + &FbSize, &FbPitch);
> + if (EFI_ERROR(Status)) {
> + DEBUG((DEBUG_ERROR, "Could not set mode %u\n", ModeNumber));
> + return EFI_DEVICE_ERROR;
> + }
> +
> + DEBUG((DEBUG_INFO, "Mode %u: %u x %u framebuffer is %u bytes at %p\n",
> + ModeNumber, Mode->Width, Mode->Height, FbSize, FbBase));
> +
> + if (FbPitch / PI3_BYTES_PER_PIXEL != Mode->Width) {
> + DEBUG((DEBUG_ERROR, "Error: Expected width %u, got width %u\n",
> + Mode->Width, FbPitch / PI3_BYTES_PER_PIXEL));
> + return EFI_DEVICE_ERROR;
> + }
> +
> + /*
> + * WT, because certain OS loaders access the frame buffer directly
> + * and we don't want to see corruption due to missing WB cache
> + * maintenance. Performance with WT is good.
> + */
> + Status = mCpu->SetMemoryAttributes(mCpu, FbBase,
> + ALIGN_VALUE(FbSize, EFI_PAGE_SIZE),
> + EFI_MEMORY_WT);
> + if (Status != EFI_SUCCESS) {
> + DEBUG((DEBUG_ERROR, "Couldn't set framebuffer attributes: %r\n", Status));
> + return Status;
> + }
> +
> + This->Mode->Mode = ModeNumber;
> + This->Mode->Info->Version = 0;
> + This->Mode->Info->HorizontalResolution = Mode->Width;
> + This->Mode->Info->VerticalResolution = Mode->Height;
> + /*
> + * NOTE: Windows REQUIRES BGR in 32 or 24 bit format.
> + */
> + This->Mode->Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
> + This->Mode->Info->PixelsPerScanLine = Mode->Width;
> + This->Mode->SizeOfInfo = sizeof(*This->Mode->Info);
> + This->Mode->FrameBufferBase = FbBase;
> + This->Mode->FrameBufferSize = FbSize;
> +
> + ClearScreen(This);
> + return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +DisplayBlt(
> + 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
> + )
> +{
> + UINT8 *VidBuf, *BltBuf, *VidBuf1;
> + UINTN i;
> +
> + switch(BltOperation) {
> + case EfiBltVideoFill:
> + BltBuf = (UINT8 *)BltBuffer;
> +
> + for (i = 0; i < Height; i++) {
> + VidBuf = POS_TO_FB(DestinationX, DestinationY + i);
> +
> + SetMem32(VidBuf, Width * PI3_BYTES_PER_PIXEL, *(UINT32 *) BltBuf);
> + }
> + break;
> +
> + case EfiBltVideoToBltBuffer:
> + if (Delta == 0) {
> + Delta = Width * PI3_BYTES_PER_PIXEL;
> + }
> +
> + for (i = 0; i < Height; i++) {
> + VidBuf = POS_TO_FB(SourceX, SourceY + i);
> +
> + BltBuf = (UINT8 *)((UINTN)BltBuffer + (DestinationY + i) * Delta +
> + DestinationX * PI3_BYTES_PER_PIXEL);
> +
> + gBS->CopyMem((VOID *)BltBuf, (VOID *)VidBuf, PI3_BYTES_PER_PIXEL * Width);
> + }
> + break;
> +
> + case EfiBltBufferToVideo:
> + if (Delta == 0) {
> + Delta = Width * PI3_BYTES_PER_PIXEL;
> + }
> +
> + for (i = 0; i < Height; i++) {
> + VidBuf = POS_TO_FB(DestinationX, DestinationY + i);
> + BltBuf = (UINT8 *)((UINTN) BltBuffer + (SourceY + i) * Delta +
> + SourceX * PI3_BYTES_PER_PIXEL);
> +
> + gBS->CopyMem((VOID *)VidBuf, (VOID *)BltBuf, Width * PI3_BYTES_PER_PIXEL);
> + }
> + break;
> +
> + case EfiBltVideoToVideo:
> + for (i = 0; i < Height; i++) {
> + VidBuf = POS_TO_FB(SourceX, SourceY + i);
> + VidBuf1 = POS_TO_FB(DestinationX, DestinationY + i);
> +
> + gBS->CopyMem((VOID *)VidBuf1, (VOID *)VidBuf, Width * PI3_BYTES_PER_PIXEL);
> + }
> + break;
> +
> + default:
> + ASSERT_EFI_ERROR(EFI_SUCCESS);
> + break;
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Initialize the state information for the Display Dxe
> +
> + @param ImageHandle of the loaded driver
> + @param SystemTable Pointer to the System Table
> +
> + @retval EFI_SUCCESS Protocol registered
> + @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
> + @retval EFI_DEVICE_ERROR Hardware problems
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +DisplayDxeInitialize (
> + IN EFI_HANDLE ImageHandle,
> + IN EFI_SYSTEM_TABLE *SystemTable
> + )
> +{
> + EFI_STATUS Status;
> +
> + Status = gBS->LocateProtocol (&gRaspberryPiFirmwareProtocolGuid, NULL,
> + (VOID **)&mFwProtocol);
> + ASSERT_EFI_ERROR (Status);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL,
> + (VOID **) &mCpu);
> + ASSERT_EFI_ERROR (Status);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + // Query the current display resolution from mailbox
> + Status = mFwProtocol->GetFBSize(&mBootWidth, &mBootHeight);
> + if(EFI_ERROR(Status)) {
> + return Status;
> + }
> +
> + DEBUG((DEBUG_INFO, "Display boot mode is %u x %u\n",
> + mBootWidth, mBootHeight));
> +
> + Status = gBS->InstallMultipleProtocolInterfaces (
> + &mDevice, &gEfiDevicePathProtocolGuid,
> + &mDisplayProtoDevicePath, &gEfiCallerIdGuid,
> + NULL, NULL);
> + ASSERT_EFI_ERROR (Status);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = EfiLibInstallDriverBindingComponentName2 (
> + ImageHandle,
> + SystemTable,
> + &mDriverBinding,
> + ImageHandle,
> + &gComponentName,
> + &gComponentName2
> + );
> + ASSERT_EFI_ERROR (Status);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +DriverSupported (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE Controller,
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
> + )
> +{
> + VOID *Temp;
> +
> + if (Controller != mDevice) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + if (gBS->HandleProtocol(Controller, &gEfiGraphicsOutputProtocolGuid,
> + (VOID **) &Temp) == EFI_SUCCESS) {
> + return EFI_ALREADY_STARTED;
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +DriverStart (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE Controller,
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
> + )
> +{
> + UINTN Index;
> + EFI_STATUS Status;
> + VOID *Dummy;
> +
> + Status = gBS->OpenProtocol (
> + Controller,
> + &gEfiCallerIdGuid,
> + (VOID **) &Dummy,
> + This->DriverBindingHandle,
> + Controller,
> + EFI_OPEN_PROTOCOL_BY_DRIVER
> + );
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + gDisplayProto.Mode = AllocateZeroPool(sizeof(EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE));
> + if (gDisplayProto.Mode == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto done;
> + }
> +
> + gDisplayProto.Mode->Info = AllocateZeroPool(sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
> + if (gDisplayProto.Mode->Info == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto done;
> + }
> +
> +
> + if (PcdGet32(PcdDisplayEnableVModes)) {
> + mLastMode = ELES(mGopModeData) - 1;
> + } else {
> + mLastMode = 0;
> + /*
> + * mBootWidth x mBootHeight may not be sensible,
> + * so clean it up, since we won't be adding
> + * any other extra vmodes.
> + */
> + if (mBootWidth < 640 ||
> + mBootHeight < 480) {
> + mBootWidth = 640;
> + mBootHeight = 480;
> + }
> + }
> +
> + mGopModeData[mLastMode].Width = mBootWidth;
> + mGopModeData[mLastMode].Height = mBootHeight;
> +
> + for (Index = 0; Index <= mLastMode; Index++) {
> + UINTN FbSize;
> + UINTN FbPitch;
> + EFI_PHYSICAL_ADDRESS FbBase;
> +
> + GOP_MODE_DATA *Mode = &mGopModeData[Index];
> +
> + Status = mFwProtocol->GetFB(Mode->Width, Mode->Height,
> + PI3_BITS_PER_PIXEL, &FbBase,
> + &FbSize, &FbPitch);
> + if (EFI_ERROR(Status)) {
> + goto done;
> + }
> +
> + //
> + // There is no way to communicate pitch back to OS. OS and even UEFI
> + // expect a fully linear frame buffer. So the width should
> + // be based on the frame buffer's pitch value. In some cases VC
> + // firmware would allocate ao frame buffer with some padding
> + // presumably to be 8 byte align.
> + //
> + Mode->Width = FbPitch / PI3_BYTES_PER_PIXEL;
> +
> + DEBUG((DEBUG_INFO, "Mode %u: %u x %u framebuffer is %u bytes at %p\n",
> + Index, Mode->Width, Mode->Height, FbSize, FbBase));
> +
> + ASSERT (FbPitch != 0);
> + ASSERT (FbBase != 0);
> + ASSERT (FbSize != 0);
> + }
> +
> + // Both set the mode and initialize current mode information.
> + gDisplayProto.Mode->MaxMode = mLastMode + 1;
> + DisplaySetMode(&gDisplayProto, 0);
> +
> + Status = gBS->InstallMultipleProtocolInterfaces (
> + &Controller, &gEfiGraphicsOutputProtocolGuid,
> + &gDisplayProto, NULL);
> + if (EFI_ERROR (Status)) {
> + goto done;
> + }
> +
> + if (PcdGet32(PcdDisplayEnableSShot)) {
> + RegisterScreenshotHandlers();
> + } else {
> + DEBUG((DEBUG_INFO, "Screenshot capture disabled\n"));
> + }
> +
> +done:
> + if (EFI_ERROR (Status)) {
> + DEBUG((DEBUG_ERROR, "Could not start DisplayDxe: %r\n", Status));
> + if (gDisplayProto.Mode->Info != NULL) {
> + FreePool(gDisplayProto.Mode->Info);
> + gDisplayProto.Mode->Info = NULL;
> + }
> +
> + if (gDisplayProto.Mode != NULL) {
> + FreePool(gDisplayProto.Mode);
> + gDisplayProto.Mode = NULL;
> + }
> +
> + gBS->CloseProtocol (
> + Controller,
> + &gEfiCallerIdGuid,
> + This->DriverBindingHandle,
> + Controller
> + );
> + }
> + return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +DriverStop (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE Controller,
> + IN UINTN NumberOfChildren,
> + IN EFI_HANDLE *ChildHandleBuffer
> + )
> +{
> + EFI_STATUS Status;
> +
> + ClearScreen(&gDisplayProto);
> +
> + Status = gBS->UninstallMultipleProtocolInterfaces (
> + Controller, &gEfiGraphicsOutputProtocolGuid,
> + &gDisplayProto, NULL);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + FreePool(gDisplayProto.Mode->Info);
> + gDisplayProto.Mode->Info = NULL;
> + FreePool(gDisplayProto.Mode);
> + gDisplayProto.Mode = NULL;
> +
> + gBS->CloseProtocol (
> + Controller,
> + &gEfiCallerIdGuid,
> + This->DriverBindingHandle,
> + Controller
> + );
> +
> + return Status;
> +}
> diff --git a/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.h b/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.h
> new file mode 100644
> index 000000000000..9fa3d4f6af83
> --- /dev/null
> +++ b/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.h
> @@ -0,0 +1,43 @@
> +/** @file
> + *
> + * Copyright (c) 2017-2018, Andrei Warkentin <andrey.warkentin@gmail.com>
> + * Copyright (c) Microsoft Corporation. All rights reserved.
> + *
> + * This program and the accompanying materials
> + * are licensed and made available under the terms and conditions of the BSD License
> + * which accompanies this distribution. The full text of the license may be found at
> + * http://opensource.org/licenses/bsd-license.php
> + *
> + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> + *
> + **/
> +
> +#ifndef _DISPLAY_H_
> +#define _DISPLAY_H_
> +
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/TimerLib.h>
> +#include <Protocol/GraphicsOutput.h>
> +#include <Protocol/DevicePath.h>
> +#include <Protocol/RaspberryPiFirmware.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Protocol/Cpu.h>
> +#include <Utils.h>
> +
> +extern EFI_GRAPHICS_OUTPUT_PROTOCOL gDisplayProto;
> +extern EFI_COMPONENT_NAME_PROTOCOL gComponentName;
> +extern EFI_COMPONENT_NAME2_PROTOCOL gComponentName2;
> +
> +VOID
> +RegisterScreenshotHandlers(
> + VOID
> + );
> +
> +#endif /* _DISPLAY_H_ */
> diff --git a/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.inf b/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.inf
> new file mode 100644
> index 000000000000..1603edd4909d
> --- /dev/null
> +++ b/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.inf
> @@ -0,0 +1,71 @@
> +#/** @file
> +#
> +# Component description file for Graphics Output module
> +#
> +# Copyright (c) 2017, Andrei Warkentin <andrey.warkentin@gmail.com>
> +# Copyright (c) Microsoft Corporation. All rights reserved.
> +#
> +# This program and the accompanying materials
> +# are licensed and made available under the terms and conditions of the BSD License
> +# which accompanies this distribution. The full text of the license may be found at
> +# http://opensource.org/licenses/bsd-license.php
> +#
> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +#**/
> +
> +[Defines]
> + INF_VERSION = 0x00010005
> + BASE_NAME = DisplayDxe
> + FILE_GUID = c5deae31-fad2-4030-841b-cfc9644d2c5b
> + MODULE_TYPE = UEFI_DRIVER
> + VERSION_STRING = 1.0
> + ENTRY_POINT = DisplayDxeInitialize
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +# DRIVER_BINDING = gGraphicsConsoleDriverBinding
> +# COMPONENT_NAME = gGraphicsConsoleComponentName
> +# COMPONENT_NAME2 = gGraphicsConsoleComponentName2
> +#
> +
> +[Sources]
> + DisplayDxe.c
> + Screenshot.c
> + ComponentName.c
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> + MdeModulePkg/MdeModulePkg.dec
> + ArmPkg/ArmPkg.dec
> + Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec
> +
> +[LibraryClasses]
> + BaseLib
> + UefiLib
> + MemoryAllocationLib
> + UefiDriverEntryPoint
> + IoLib
> + TimerLib
> + BmpSupportLib
> + UefiRuntimeServicesTableLib
> +
> +[Protocols]
> + gEfiLoadedImageProtocolGuid
> + gEfiDevicePathProtocolGuid
> + gEfiGraphicsOutputProtocolGuid
> + gRaspberryPiFirmwareProtocolGuid
> + gEfiCpuArchProtocolGuid
> + gEfiSimpleFileSystemProtocolGuid
> + gEfiSimpleTextInputExProtocolGuid
> +
> +[Pcd]
> + gRaspberryPiTokenSpaceGuid.PcdDisplayEnableVModes
> + gRaspberryPiTokenSpaceGuid.PcdDisplayEnableSShot
> +
> +[Guids]
> +
> +[Depex]
> + gEfiCpuArchProtocolGuid AND gRaspberryPiFirmwareProtocolGuid
> diff --git a/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/Screenshot.c b/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/Screenshot.c
> new file mode 100644
> index 000000000000..a2feeba6084f
> --- /dev/null
> +++ b/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/Screenshot.c
> @@ -0,0 +1,379 @@
> +/** @file
> + *
> + * Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
> + * Copyright (c) 2018, Andrei Warkentin <andrey.warkentin@gmail.com>
> + *
> + * This program and the accompanying materials
> + * are licensed and made available under the terms and conditions of the BSD License
> + * which accompanies this distribution. The full text of the license may be found at
> + * http://opensource.org/licenses/bsd-license.php
> + *
> + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> + *
> + **/
> +
> +/*
> + * Loosely based on CrScreenShotDxe (https://github.com/LongSoft/CrScreenshotDxe).
> + *
> + * Copyright (c) 2016, Nikolaj Schlej, All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions are met:
> + * - Redistributions of source code must retain the above copyright notice,
> + * this list of conditions and the following disclaimer.
> + * - Redistributions in binary form must reproduce the above copyright notice,
> + * this list of conditions and the following disclaimer in the documentation
> + * and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
> + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
> + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
> + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
> + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
> + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
> + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include "DisplayDxe.h"
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Library/PrintLib.h>
> +#include <Library/BmpSupportLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +
> +/*
> + * ShowStatus defs.
> + */
> +#define STATUS_SQUARE_SIDE 5
> +#define STATUS_YELLOW 0xff, 0xff, 0x00
> +#define STATUS_GREEN 0x00, 0xff, 0x00
> +#define STATUS_BLUE 0x00, 0x00, 0xff
> +#define STATUS_RED 0xff, 0x00, 0x00
> +
> +EFI_STATUS
> +ShowStatus (
> + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
> + IN UINT8 Red,
> + IN UINT8 Green,
> + IN UINT8 Blue
> + )
> +{
> + UINTN Index;
> + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Square[STATUS_SQUARE_SIDE * STATUS_SQUARE_SIDE];
> + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Backup[STATUS_SQUARE_SIDE * STATUS_SQUARE_SIDE];
> +
> + for (Index = 0 ; Index < STATUS_SQUARE_SIDE * STATUS_SQUARE_SIDE; Index++) {
> + Square[Index].Blue = Blue;
> + Square[Index].Green = Green;
> + Square[Index].Red = Red;
> + Square[Index].Reserved = 0x00;
> + }
> +
> + // Backup current image.
> + GraphicsOutput->Blt(GraphicsOutput, Backup,
> + EfiBltVideoToBltBuffer, 0, 0, 0, 0,
> + STATUS_SQUARE_SIDE, STATUS_SQUARE_SIDE, 0);
> +
> + // Draw the status square.
> + GraphicsOutput->Blt(GraphicsOutput, Square,
> + EfiBltBufferToVideo, 0, 0, 0, 0,
> + STATUS_SQUARE_SIDE, STATUS_SQUARE_SIDE, 0);
> +
> + // Wait 500ms.
> + gBS->Stall(500*1000);
> +
> + // Restore the backup.
> + GraphicsOutput->Blt(GraphicsOutput, Backup,
> + EfiBltBufferToVideo, 0, 0, 0, 0,
> + STATUS_SQUARE_SIDE, STATUS_SQUARE_SIDE, 0);
> + return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +FindWritableFs (
> + OUT EFI_FILE_PROTOCOL **WritableFs
> + )
> +{
> + EFI_FILE_PROTOCOL *Fs = NULL;
> + EFI_HANDLE *HandleBuffer = NULL;
> + UINTN HandleCount;
> + UINTN Index;
> +
> + EFI_STATUS Status = gBS->LocateHandleBuffer(ByProtocol,
> + &gEfiSimpleFileSystemProtocolGuid,
> + NULL, &HandleCount, &HandleBuffer);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + for (Index = 0; Index < HandleCount; Index++) {
> + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs = NULL;
> + EFI_FILE_PROTOCOL *File = NULL;
> +
> + Status = gBS->HandleProtocol(HandleBuffer[Index],
> + &gEfiSimpleFileSystemProtocolGuid,
> + (VOID **) &SimpleFs);
> + if (EFI_ERROR (Status)) {
> + ASSERT_EFI_ERROR (Status);
> + /*
> + * Not supposed to happen.
> + */
> + continue;
> + }
> +
> + Status = SimpleFs->OpenVolume(SimpleFs, &Fs);
> + if (EFI_ERROR (Status)) {
> + DEBUG((DEBUG_ERROR, "%a OpenVolume[%u] returned %r\n", __FUNCTION__,
> + Index, Status));
> + continue;
> + }
> +
> + Status = Fs->Open(Fs, &File, L"--------.---",
> + EFI_FILE_MODE_CREATE | EFI_FILE_MODE_READ |
> + EFI_FILE_MODE_WRITE, 0);
> + if (EFI_ERROR (Status)) {
> + DEBUG((DEBUG_ERROR, "%a Open[%u] returned %r\n", __FUNCTION__,
> + Index, Status));
> + continue;
> + }
> +
> + /*
> + * Okay, we have a writable filesystem!
> + */
> + Fs->Delete(File);
> + *WritableFs = Fs;
> + Status = EFI_SUCCESS;
> + break;
> + }
> +
> + if (HandleBuffer) {
> + FreePool(HandleBuffer);
> + }
> +
> + return Status;
> +}
> +
> +STATIC
> +VOID
> +TakeScreenshot(
> + VOID
> + )
> +{
> + VOID *BmpImage = NULL;
> + EFI_FILE_PROTOCOL *Fs = NULL;
> + EFI_FILE_PROTOCOL *File = NULL;
> + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput = &gDisplayProto;
> + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Image = NULL;
> + EFI_STATUS Status;
> + CHAR16 FileName[8+1+3+1];
> + UINT32 ScreenWidth;
> + UINT32 ScreenHeight;
> + UINTN ImageSize;
> + UINTN BmpSize;
> + UINTN Index;
> + EFI_TIME Time;
> +
> + Status = FindWritableFs(&Fs);
> + if (EFI_ERROR (Status)) {
> + ShowStatus(GraphicsOutput, STATUS_YELLOW);
> + }
> +
> + ScreenWidth = GraphicsOutput->Mode->Info->HorizontalResolution;
> + ScreenHeight = GraphicsOutput->Mode->Info->VerticalResolution;
> + ImageSize = ScreenWidth * ScreenHeight;
> +
> + Status = gRT->GetTime(&Time, NULL);
> + if (!EFI_ERROR(Status)) {
> + UnicodeSPrint(FileName, sizeof(FileName), L"%02d%02d%02d%02d.bmp",
> + Time.Day, Time.Hour, Time.Minute, Time.Second);
> + } else {
> + UnicodeSPrint(FileName, sizeof(FileName), L"scrnshot.bmp");
> + }
> +
> + Image = AllocatePool(ImageSize * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
> + if (Image == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + ShowStatus(GraphicsOutput, STATUS_RED);
> + goto done;
> + }
> +
> + Status = GraphicsOutput->Blt(GraphicsOutput, Image,
> + EfiBltVideoToBltBuffer, 0, 0, 0, 0,
> + ScreenWidth, ScreenHeight, 0);
> + if (EFI_ERROR(Status)) {
> + ShowStatus(GraphicsOutput, STATUS_RED);
> + goto done;
> + }
> +
> + for (Index = 0; Index < ImageSize; Index++) {
> + if (Image[Index].Red != 0x00 ||
> + Image[Index].Green != 0x00 ||
> + Image[Index].Blue != 0x00) {
> + break;
> + }
> + }
> +
> + if (Index == ImageSize) {
> + ShowStatus(GraphicsOutput, STATUS_BLUE);
> + goto done;
> + }
> +
> + Status = TranslateGopBltToBmp(Image, ScreenHeight, ScreenWidth,
> + &BmpImage, (UINT32 *) &BmpSize);
> + if (EFI_ERROR(Status)) {
> + ShowStatus(GraphicsOutput, STATUS_RED);
> + goto done;
> + }
> +
> + Status = Fs->Open(Fs, &File, FileName, EFI_FILE_MODE_CREATE |
> + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0);
> + if (EFI_ERROR (Status)) {
> + ShowStatus(GraphicsOutput, STATUS_RED);
> + goto done;
> + }
> +
> + Status = File->Write(File, &BmpSize, BmpImage);
> + File->Close(File);
> + if (EFI_ERROR (Status)) {
> + ShowStatus(GraphicsOutput, STATUS_RED);
> + goto done;
> + }
> +
> + ShowStatus(GraphicsOutput, STATUS_GREEN);
> +done:
> + if (BmpImage != NULL) {
> + FreePool (BmpImage);
> + }
> +
> + if (Image != NULL) {
> + FreePool (Image);
> + }
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +ScreenshotKeyHandler (
> + IN EFI_KEY_DATA *KeyData
> + )
> +{
> + TakeScreenshot();
> + return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +ProcessScreenshotHandler(
> + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HANDLE Handle;
> + EFI_KEY_DATA ScreenshotKey;
> +
> + /*
> + * LCtrl+LAlt+F12
> + */
> + ScreenshotKey.Key.ScanCode = SCAN_F12;
> + ScreenshotKey.Key.UnicodeChar = 0;
> + ScreenshotKey.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID |
> + EFI_LEFT_CONTROL_PRESSED | EFI_LEFT_ALT_PRESSED;
> + ScreenshotKey.KeyState.KeyToggleState = 0;
> +
> + Status = SimpleTextInEx->RegisterKeyNotify (
> + SimpleTextInEx,
> + &ScreenshotKey,
> + ScreenshotKeyHandler,
> + &Handle
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "%a: couldn't register key notification: %r\n",
> + __FUNCTION__, Status));
> + return Status;
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +STATIC
> +VOID
> +ProcessScreenshotHandlers(
> + VOID
> + )
> +{
> + UINTN Index;
> + EFI_STATUS Status;
> + UINTN HandleCount;
> + EFI_HANDLE *HandleBuffer;
> + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx;
> +
> + Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleTextInputExProtocolGuid,
> + NULL, &HandleCount, &HandleBuffer);
> + if (EFI_ERROR (Status)) {
> + return;
> + }
> +
> + for (Index = 0; Index < HandleCount; Index++) {
> + Status = gBS->HandleProtocol (HandleBuffer[Index],
> + &gEfiSimpleTextInputExProtocolGuid,
> + (VOID **) &SimpleTextInEx);
> + if (EFI_ERROR (Status)) {
> + ASSERT_EFI_ERROR (Status);
> + /*
> + * Not supposed to happen.
> + */
> + continue;
> + }
> +
> + Status = ProcessScreenshotHandler(SimpleTextInEx);
> + if (EFI_ERROR (Status)) {
> + continue;
> + }
> + }
> +}
> +
> +STATIC
> +VOID
> +EFIAPI
> +OnTextInExInstall (
> + IN EFI_EVENT Event,
> + IN VOID *Context
> + )
> +{
> + ProcessScreenshotHandlers();
> +}
> +
> +VOID
> +RegisterScreenshotHandlers(
> + VOID
> + )
> +{
> + EFI_STATUS Status;
> + EFI_EVENT TextInExInstallEvent;
> + VOID *TextInExInstallRegistration;
> +
> + ProcessScreenshotHandlers();
> +
> + Status = gBS->CreateEvent(EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
> + OnTextInExInstall, NULL,
> + &TextInExInstallEvent);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "%a: couldn't create protocol install event: %r\n",
> + __FUNCTION__, Status));
> + return;
> + }
> +
> + Status = gBS->RegisterProtocolNotify(&gEfiSimpleTextInputExProtocolGuid,
> + TextInExInstallEvent,
> + &TextInExInstallRegistration);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "%a: couldn't register protocol install notify: %r\n",
> + __FUNCTION__, Status));
> + return;
> + }
> +}
> --
> 2.17.0.windows.1
>
next prev parent reply other threads:[~2018-12-14 15:07 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-12-10 12:38 [PATCH v2 edk2-platforms 00/20] Platform/Broadcom: Add Raspberry Pi 3 support Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 01/20] Platform/Broadcom/RPi3: Add Reset and Memory Init libraries Pete Batard
2018-12-12 20:43 ` Ard Biesheuvel
2018-12-13 10:48 ` Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 02/20] Platform/Broadcom/RPi3: Add Platform library Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 03/20] Platform/Broadcom/RPi3: Add GPIO and RTC libraries Pete Batard
2018-12-12 20:50 ` Ard Biesheuvel
2018-12-13 10:49 ` Pete Batard
2018-12-13 10:55 ` Leif Lindholm
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 04/20] Platform/Broadcom/RPi3: Add ACPI Tables Pete Batard
2018-12-12 20:52 ` Ard Biesheuvel
2018-12-13 10:49 ` Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 05/20] Platform/Broadcom/RPi3: Add Boot Manager library Pete Batard
2018-12-12 20:56 ` Ard Biesheuvel
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 06/20] Platform/Broadcom/RPi3: Add Interrupt and Device Tree drivers Pete Batard
2018-12-12 21:09 ` Ard Biesheuvel
2018-12-13 10:49 ` Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 07/20] Platform/Broadcom/RPi3: Add Firmware driver Pete Batard
2018-12-12 21:17 ` Ard Biesheuvel
2018-12-13 10:49 ` Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 08/20] Platform/Broadcom/RPi3: Add Display driver Pete Batard
2018-12-14 15:06 ` Ard Biesheuvel [this message]
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 09/20] Platform/Broadcom/RPi3: Add Graphic Console driver Pete Batard
2018-12-14 15:31 ` Ard Biesheuvel
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 10/20] Platform/Broadcom/RPi3: Add Base MMC driver Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 11/20] Platform/Broadcom/RPi3: Add Arasan " Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 12/20] Platform/Broadcom/RPi3: Add SD Host driver Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 13/20] Platform/Broadcom/RPi3: Add SMBIOS driver Pete Batard
2018-12-14 15:36 ` Ard Biesheuvel
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 14/20] Platform/Broadcom/RPi3: Add NV Storage driver Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 15/20] Platform/Broadcom/RPi3: Add Platform Config driver Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 16/20] Platform/Broadcom/RPi3: Add Raspberry Pi 3 Platform Pete Batard
2018-12-14 15:39 ` Ard Biesheuvel
2018-12-14 16:21 ` Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 17/20] Platform/Broadcom/RPi3 *NON-OSI*: Add ATF binaries Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 18/20] Platform/Broadcom/RPi3 *NON-OSI*: Add Device Tree binaries Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 19/20] Platform/Broadcom/RPi3 *NON-OSI*: Add USB Host driver Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 20/20] Platform/Broadcom/RPi3 *NON-OSI*: Add Logo driver Pete Batard
2018-12-11 18:10 ` [PATCH v2 edk2-platforms 00/20] Platform/Broadcom: Add Raspberry Pi 3 support Leif Lindholm
2018-12-11 20:16 ` Pete Batard
2018-12-11 21:20 ` Ard Biesheuvel
2018-12-12 18:32 ` Leif Lindholm
2018-12-12 19:53 ` Pete Batard
2018-12-12 20:01 ` Leif Lindholm
2018-12-14 16:14 ` Philippe Mathieu-Daudé
2018-12-14 16:36 ` Leif Lindholm
2018-12-14 17:08 ` Pete Batard
2018-12-14 18:41 ` Leif Lindholm
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAKv+Gu95miOiOMmvUR7fBbCn0C7H607+dM=v9TSWhx6pQWOL6w@mail.gmail.com' \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox