public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Phil Dennis-Jordan <lists@philjordan.eu>
To: Laszlo Ersek <lersek@redhat.com>
Cc: edk2-devel-01 <edk2-devel@lists.01.org>,
	Jordan Justen <jordan.l.justen@intel.com>,
	 Phil Dennis-Jordan <phil@philjordan.eu>
Subject: Re: [PATCH v3 3/3] OvmfPkg/QemuVideoDxe: VMWare SVGA device support
Date: Thu, 6 Apr 2017 00:46:09 +1200	[thread overview]
Message-ID: <CAGCz3vuVDgZo=Bkh6B2ophaLKcu0Hx61seWap59CF9bSEhh+EA@mail.gmail.com> (raw)
In-Reply-To: <31192690-0c6a-ce61-8c8f-a19be1c3ccb4@redhat.com>

On Wed, Apr 5, 2017 at 11:41 PM, Laszlo Ersek <lersek@redhat.com> wrote:
> On 04/05/17 11:58, Phil Dennis-Jordan wrote:
>> From: Phil Dennis-Jordan <phil@philjordan.eu>
>>
>> In addition to the QXL, Cirrus, etc. VGA adapters, Qemu also implements
>> a basic version of VMWare's SVGA display device. Drivers for this
>> device exist for some guest OSes which do not support Qemu's other
>> display adapters, so supporting it in OVMF is useful in conjunction
>> with those OSes.
>>
>> This change adds support for the SVGA device's framebuffer to
>> QemuVideoDxe's graphics output protocol implementation, based on
>> VMWare's documentation. The most basic initialisation, framebuffer
>> layout query, and mode setting operations are implemented.
>>
>> The device relies on port-based 32-bit I/O, unfortunately on misaligned
>> addresses. This limits the driver's support to the x86 family of
>> platforms.
>>
>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Contributed-under: TianoCore Contribution Agreement 1.0
>> Signed-off-by: Phil Dennis-Jordan <phil@philjordan.eu>
>> ---
>>
>> Notes:
>>     v2:
>>     - Unaligned I/O helper functions moved to separate commit [Laszlo]
>>     - Multi-line function call whitespace fixes.
>>
>>     v3:
>>     - Dropped the "2" from "SVGA2" where appropriate. [Jordan, Laszlo]
>>     - Renamed various struct fields and functions with consistent prefixes [Laszlo]
>>     - #include orders fixed [Laszlo]
>>     - Renamedi/moved lots of local variables to comply with convention. [Laszlo]
>>     - Added error checking to PCI BAR queries. [Laszlo]
>>     - Moved some function definitions around for better grouping. [Laszlo]
>>     - Fixed ClearScreen() to use the correct VRAM BAR. [Laszlo]
>>     - Changed modelist initialisation to fetch all mode data on startup, so mode
>>       queries can return everything including channel masks without hitting the
>>       device. Mask calculations hopefully make more sense now. [Laszlo]
>>     - Whitespace fixes. [Laszlo]
>>     - Fixed a memory leak in BAR query.
>>
>>  OvmfPkg/QemuVideoDxe/Qemu.h       |  29 ++++
>>  OvmfPkg/QemuVideoDxe/Driver.c     | 127 ++++++++++++++-
>>  OvmfPkg/QemuVideoDxe/Gop.c        |  61 +++++++-
>>  OvmfPkg/QemuVideoDxe/Initialize.c | 161 ++++++++++++++++++++
>>  4 files changed, 371 insertions(+), 7 deletions(-)
>>
>> diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h
>> index 2ce37defc5b8..7fbb25b3efd3 100644
>> --- a/OvmfPkg/QemuVideoDxe/Qemu.h
>> +++ b/OvmfPkg/QemuVideoDxe/Qemu.h
>> @@ -92,6 +92,7 @@ typedef enum {
>>    QEMU_VIDEO_CIRRUS_5446,
>>    QEMU_VIDEO_BOCHS,
>>    QEMU_VIDEO_BOCHS_MMIO,
>> +  QEMU_VIDEO_VMWARE_SVGA,
>>  } QEMU_VIDEO_VARIANT;
>>
>>  typedef struct {
>> @@ -115,10 +116,13 @@ typedef struct {
>>    //
>>    UINTN                                 MaxMode;
>>    QEMU_VIDEO_MODE_DATA                  *ModeData;
>> +  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *VmwareSvgaModeInfo;
>>
>>    QEMU_VIDEO_VARIANT                    Variant;
>>    FRAME_BUFFER_CONFIGURE                *FrameBufferBltConfigure;
>>    UINTN                                 FrameBufferBltConfigureSize;
>> +  UINT8                                 FrameBufferVramBarIndex;
>> +  UINT16                                VmwareSvgaBasePort;
>>  } QEMU_VIDEO_PRIVATE_DATA;
>>
>>  ///
>> @@ -502,9 +506,34 @@ QemuVideoBochsModeSetup (
>>    BOOLEAN                  IsQxl
>>    );
>>
>> +EFI_STATUS
>> +QemuVideoVmwareSvgaModeSetup (
>> +  QEMU_VIDEO_PRIVATE_DATA *Private
>> +  );
>> +
>>  VOID
>>  InstallVbeShim (
>>    IN CONST CHAR16         *CardName,
>>    IN EFI_PHYSICAL_ADDRESS FrameBufferBase
>>    );
>> +
>> +VOID
>> +VmwareSvgaWrite (
>> +  QEMU_VIDEO_PRIVATE_DATA *Private,
>> +  UINT16                  Register,
>> +  UINT32                  Value
>> +  );
>> +
>> +UINT32
>> +VmwareSvgaRead (
>> +  QEMU_VIDEO_PRIVATE_DATA *Private,
>> +  UINT16                  Register
>> +  );
>> +
>> +VOID
>> +InitializeVmwareSvgaGraphicsMode (
>> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
>> +  QEMU_VIDEO_BOCHS_MODES   *ModeData
>> +  );
>> +
>>  #endif
>> diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c
>> index fc8025ec46de..79c430e920d7 100644
>> --- a/OvmfPkg/QemuVideoDxe/Driver.c
>> +++ b/OvmfPkg/QemuVideoDxe/Driver.c
>> @@ -14,8 +14,10 @@
>>
>>  **/
>>
>> -#include "Qemu.h"
>> +#include <IndustryStandard/VmwareSvga.h>
>>  #include <IndustryStandard/Acpi.h>
>> +#include "Qemu.h"
>> +#include "UnalignedIoInternal.h"
>>
>>  EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = {
>>    QemuVideoControllerDriverSupported,
>> @@ -58,6 +60,11 @@ QEMU_VIDEO_CARD gQemuVideoCardList[] = {
>>          QEMU_VIDEO_BOCHS_MMIO,
>>          L"QEMU VirtIO VGA"
>>      },{
>> +        VMWARE_PCI_VENDOR_ID_VMWARE,
>> +        VMWARE_PCI_DEVICE_ID_VMWARE_SVGA2,
>> +        QEMU_VIDEO_VMWARE_SVGA,
>> +        L"QEMU VMWare SVGA"
>> +    },{
>>          0 /* end of list */
>>      }
>>  };
>> @@ -242,6 +249,7 @@ QemuVideoControllerDriverStart (
>>      goto ClosePciIo;
>>    }
>>    Private->Variant = Card->Variant;
>> +  Private->FrameBufferVramBarIndex = PCI_BAR_IDX0;
>>
>>    //
>>    // IsQxl is based on the detected Card->Variant, which at a later point might
>> @@ -317,6 +325,59 @@ QemuVideoControllerDriverStart (
>>    }
>>
>>    //
>> +  // Check if accessing Vmware SVGA interface works
>> +  //
>> +  if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA) {
>> +    EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *IoDesc;
>> +    UINT32                            TargetId;
>> +    UINT32                            SvgaIdRead;
>> +
>> +    IoDesc = NULL;
>> +    Status = Private->PciIo->GetBarAttributes (
>> +                               Private->PciIo,
>> +                               PCI_BAR_IDX0,
>> +                               NULL,
>> +                               (VOID**) &IoDesc
>> +                               );
>> +    if (EFI_ERROR(Status) ||
>
> Missing space between "EFI_ERROR" and "(".

Augh, sorry about these, old habits die hard.

>> +        IoDesc->ResType != ACPI_ADDRESS_SPACE_TYPE_IO ||
>> +        IoDesc->AddrRangeMin >= MAX_UINT16 ||
>> +        IoDesc->AddrRangeMin + VMWARE_SVGA_VALUE_PORT >= MAX_UINT16) {
>
> If we wanted to be exact, we would likely express the last two
> conditions with a single
>
>   IoDesc->AddrRangeMin > MAX_UINT16 + 1 - (VMWARE_SVGA_VALUE_PORT + 4)
>
> but I don't necessarily want to obsess about this.

The details of this, >/+1 vs >=, and +4 vs not +4, etc. are probably
debatable, but yes, there's no need (chance of overflow) to make this
2 separate conditions. I've gone with your version.

>> +      if (IoDesc != NULL) {
>> +        FreePool (IoDesc);
>> +      }
>
> Good catch :)
>
>> +      Status = EFI_DEVICE_ERROR;
>> +      goto RestoreAttributes;
>> +    }
>> +    Private->VmwareSvgaBasePort = (UINT16) IoDesc->AddrRangeMin;
>> +    FreePool (IoDesc);
>
> Here too :)
>
>> +
>> +    TargetId = VMWARE_SVGA_ID_2;
>> +    while (TRUE) {
>> +      VmwareSvgaWrite (Private, VmwareSvgaRegId, TargetId);
>> +      SvgaIdRead = VmwareSvgaRead (Private, VmwareSvgaRegId);
>> +      if ((SvgaIdRead == TargetId) || (TargetId <= VMWARE_SVGA_ID_0)) {
>> +        break;
>> +      }
>> +      TargetId --;
>
> Hm, this change wasn't called for.
>
>   3.2.3 Formatting: Horizontal spacing
>
>         * Never put space between unary operators and the operand. See
>           "Horizontal Spacing".
>
>   5.2.2.3 Do not put space between unary operators and their object
>
>> +    }
>> +
>> +    if (SvgaIdRead != TargetId) {
>> +      DEBUG ((
>> +        DEBUG_ERROR,
>> +        "QemuVideo: QEMU_VIDEO_VMWARE_SVGA ID mismatch "
>> +        "(got 0x%x, base address 0x%x)\n",
>> +        SvgaIdRead,
>> +        Private->VmwareSvgaBasePort
>> +        ));
>> +      Status = EFI_DEVICE_ERROR;
>> +      goto RestoreAttributes;
>> +    }
>> +
>> +    Private->FrameBufferVramBarIndex = PCI_BAR_IDX1;
>> +  }
>> +
>> +  //
>>    // Get ParentDevicePath
>>    //
>>    Status = gBS->HandleProtocol (
>> @@ -371,6 +432,9 @@ QemuVideoControllerDriverStart (
>>    case QEMU_VIDEO_BOCHS:
>>      Status = QemuVideoBochsModeSetup (Private, IsQxl);
>>      break;
>> +  case QEMU_VIDEO_VMWARE_SVGA:
>> +    Status = QemuVideoVmwareSvgaModeSetup (Private);
>> +    break;
>>    default:
>>      ASSERT (FALSE);
>>      Status = EFI_DEVICE_ERROR;
>> @@ -750,7 +814,7 @@ ClearScreen (
>>    Private->PciIo->Mem.Write (
>>                          Private->PciIo,
>>                          EfiPciIoWidthFillUint32,
>> -                        0,
>> +                        Private->FrameBufferVramBarIndex,
>>                          0,
>>                          0x400000 >> 2,
>>                          &Color
>> @@ -888,6 +952,35 @@ BochsRead (
>>  }
>>
>>  VOID
>> +VmwareSvgaWrite (
>> +  QEMU_VIDEO_PRIVATE_DATA   *Private,
>> +  UINT16                    Register,
>> +  UINT32                    Value
>> +  )
>> +{
>> +  UnalignedIoWrite32 (
>> +    Private->VmwareSvgaBasePort + VMWARE_SVGA_INDEX_PORT,
>> +    Register
>> +    );
>> +  UnalignedIoWrite32 (
>> +    Private->VmwareSvgaBasePort + VMWARE_SVGA_VALUE_PORT,
>> +    Value);
>
> Please break the closing paren off to a new line.
>
>> +}
>> +
>> +UINT32
>> +VmwareSvgaRead (
>> +  QEMU_VIDEO_PRIVATE_DATA   *Private,
>> +  UINT16                    Register
>> +  )
>> +{
>> +  UnalignedIoWrite32 (
>> +    Private->VmwareSvgaBasePort + VMWARE_SVGA_INDEX_PORT,
>> +    Register);
>
> Please break the closing paren off to a new line.
>
>> +  return UnalignedIoRead32 (
>> +           Private->VmwareSvgaBasePort + VMWARE_SVGA_VALUE_PORT);
>
> Please break the closing paren off to a new line.
>
>> +}
>> +
>> +VOID
>>  VgaOutb (
>>    QEMU_VIDEO_PRIVATE_DATA  *Private,
>>    UINTN                    Reg,
>> @@ -941,6 +1034,35 @@ InitializeBochsGraphicsMode (
>>    ClearScreen (Private);
>>  }
>>
>> +VOID
>> +InitializeVmwareSvgaGraphicsMode (
>> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
>> +  QEMU_VIDEO_BOCHS_MODES   *ModeData
>> +  )
>> +{
>> +  UINT32 Capabilities;
>> +
>> +  VmwareSvgaWrite (Private, VmwareSvgaRegWidth, ModeData->Width);
>> +  VmwareSvgaWrite (Private, VmwareSvgaRegHeight, ModeData->Height);
>> +
>> +  Capabilities = VmwareSvgaRead (
>> +                   Private,
>> +                   VmwareSvgaRegCapabilities
>> +                   );
>> +  if ((Capabilities & VMWARE_SVGA_CAP_8BIT_EMULATION) != 0) {
>> +    VmwareSvgaWrite (
>> +      Private,
>> +      VmwareSvgaRegBitsPerPixel,
>> +      ModeData->ColorDepth
>> +      );
>> +  }
>> +
>> +  VmwareSvgaWrite (Private, VmwareSvgaRegEnable, 1);
>> +
>> +  SetDefaultPalette (Private);
>> +  ClearScreen (Private);
>> +}
>> +
>>  EFI_STATUS
>>  EFIAPI
>>  InitializeQemuVideo (
>> @@ -975,3 +1097,4 @@ InitializeQemuVideo (
>>
>>    return Status;
>>  }
>> +
>
> No need to add an empty line here.

Whoops, leftover from moved function.

>> diff --git a/OvmfPkg/QemuVideoDxe/Gop.c b/OvmfPkg/QemuVideoDxe/Gop.c
>> index 359e9217d3d1..934c9f39b459 100644
>> --- a/OvmfPkg/QemuVideoDxe/Gop.c
>> +++ b/OvmfPkg/QemuVideoDxe/Gop.c
>> @@ -13,6 +13,7 @@
>>
>>  **/
>>
>> +#include <IndustryStandard/VmwareSvga.h>
>>  #include "Qemu.h"
>>
>>  STATIC
>> @@ -75,6 +76,42 @@ QemuVideoCompleteModeData (
>>    return EFI_SUCCESS;
>>  }
>>
>> +STATIC
>> +EFI_STATUS
>> +QemuVideoVmwareSvgaCompleteModeData (
>
> Huh, thanks for making this STATIC :)
>
>> +  IN  QEMU_VIDEO_PRIVATE_DATA           *Private,
>> +  OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode
>> +  )
>> +{
>> +  EFI_STATUS                            Status;
>> +  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info;
>> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR     *FrameBufDesc;
>> +  UINT32                                BytesPerLine, FbOffset, BytesPerPixel;
>> +
>> +  Info = Mode->Info;
>> +  CopyMem (Info, &Private->VmwareSvgaModeInfo[Mode->Mode], sizeof(*Info));
>
> Please write "sizeof (*Info)" or "sizeof *Info".
>
>> +  BytesPerPixel = Private->ModeData[Mode->Mode].ColorDepth / 8;
>> +  BytesPerLine = Info->PixelsPerScanLine * BytesPerPixel;
>> +
>> +  FbOffset = VmwareSvgaRead (Private, VmwareSvgaRegFbOffset);
>> +
>> +  Status = Private->PciIo->GetBarAttributes (
>> +                             Private->PciIo,
>> +                             PCI_BAR_IDX1,
>> +                             NULL,
>> +                             (VOID**) &FrameBufDesc
>> +                             );
>> +  if (EFI_ERROR(Status)) {
>
> Missing space between "EFI_ERROR" and "(".
>
>> +    return EFI_DEVICE_ERROR;
>> +  }
>> +
>> +  Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin + FbOffset;
>> +  Mode->FrameBufferSize = BytesPerLine * Info->VerticalResolution;
>> +
>> +  FreePool (FrameBufDesc);
>> +  return Status;
>> +}
>> +
>>
>>  //
>>  // Graphics Output Protocol Member Functions
>> @@ -124,10 +161,14 @@ Routine Description:
>>
>>    *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
>>
>> -  ModeData = &Private->ModeData[ModeNumber];
>> -  (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
>> -  (*Info)->VerticalResolution   = ModeData->VerticalResolution;
>> -  QemuVideoCompleteModeInfo (ModeData, *Info);
>> +  if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA) {
>> +    **Info = Private->VmwareSvgaModeInfo[ModeNumber];
>
> In edk2, structure assignment is not allowed (because some compilers
> cannot be prevented from generating intrinsics for them). Please use an
> explicit CopyMem (), like you do above in
> QemuVideoVmwareSvgaCompleteModeData ().
>
>> +  } else {
>> +    ModeData = &Private->ModeData[ModeNumber];
>> +    (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
>> +    (*Info)->VerticalResolution   = ModeData->VerticalResolution;
>> +    QemuVideoCompleteModeInfo (ModeData, *Info);
>> +  }
>>
>>    return EFI_SUCCESS;
>>  }
>> @@ -176,6 +217,12 @@ Routine Description:
>>    case QEMU_VIDEO_BOCHS:
>>      InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]);
>>      break;
>> +  case QEMU_VIDEO_VMWARE_SVGA:
>> +    InitializeVmwareSvgaGraphicsMode (
>> +      Private,
>> +      &QemuVideoBochsModes[ModeData->InternalModeIndex]
>> +      );
>> +    break;
>>    default:
>>      ASSERT (FALSE);
>>      return EFI_DEVICE_ERROR;
>> @@ -186,7 +233,11 @@ Routine Description:
>>    This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
>>    This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
>>
>> -  QemuVideoCompleteModeData (Private, This->Mode);
>> +  if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA) {
>> +    QemuVideoVmwareSvgaCompleteModeData (Private, This->Mode);
>> +  } else {
>> +    QemuVideoCompleteModeData (Private, This->Mode);
>> +  }
>>
>>    //
>>    // Re-initialize the frame buffer configure when mode changes.
>> diff --git a/OvmfPkg/QemuVideoDxe/Initialize.c b/OvmfPkg/QemuVideoDxe/Initialize.c
>> index d5d8cfef9661..8c5c993c7d0e 100644
>> --- a/OvmfPkg/QemuVideoDxe/Initialize.c
>> +++ b/OvmfPkg/QemuVideoDxe/Initialize.c
>> @@ -13,6 +13,7 @@
>>
>>  **/
>>
>> +#include <IndustryStandard/VmwareSvga.h>
>>  #include "Qemu.h"
>>
>>
>> @@ -346,3 +347,163 @@ QemuVideoBochsModeSetup (
>>    return EFI_SUCCESS;
>>  }
>>
>> +EFI_STATUS
>> +QemuVideoVmwareSvgaModeSetup (
>> +  QEMU_VIDEO_PRIVATE_DATA *Private
>> +  )
>> +{
>> +  EFI_STATUS                            Status;
>> +  UINT32                                FbSize;
>> +  UINT32                                MaxWidth, MaxHeight;
>> +  UINT32                                Capabilities;
>> +  UINT32                                BitsPerPixel;
>> +  UINT32                                Index;
>> +  QEMU_VIDEO_MODE_DATA                  *ModeData;
>> +  QEMU_VIDEO_BOCHS_MODES                *VideoMode;
>> +  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *ModeInfo;
>> +
>> +  VmwareSvgaWrite (Private, VmwareSvgaRegEnable, 0);
>> +
>> +  Private->ModeData =
>> +    AllocatePool (sizeof (Private->ModeData[0]) * QEMU_VIDEO_BOCHS_MODE_COUNT);
>> +  if (Private->ModeData == NULL) {
>> +    Status = EFI_OUT_OF_RESOURCES;
>> +    goto ModeDataAllocError;
>> +  }
>> +
>> +  Private->VmwareSvgaModeInfo =
>> +    AllocatePool (
>> +      sizeof (Private->VmwareSvgaModeInfo[0]) * QEMU_VIDEO_BOCHS_MODE_COUNT
>> +      );
>> +  if (Private->VmwareSvgaModeInfo == NULL) {
>> +    Status = EFI_OUT_OF_RESOURCES;
>> +    goto ModeInfoAllocError;
>> +  }
>> +
>> +  FbSize =       VmwareSvgaRead (Private, VmwareSvgaRegFbSize);
>> +  MaxWidth =     VmwareSvgaRead (Private, VmwareSvgaRegMaxWidth);
>> +  MaxHeight =    VmwareSvgaRead (Private, VmwareSvgaRegMaxHeight);
>> +  Capabilities = VmwareSvgaRead (Private, VmwareSvgaRegCapabilities);
>> +  if ((Capabilities & VMWARE_SVGA_CAP_8BIT_EMULATION) != 0) {
>> +    BitsPerPixel = VmwareSvgaRead (
>> +                     Private,
>> +                     VmwareSvgaRegHostBitsPerPixel
>> +                     );
>> +    VmwareSvgaWrite (
>> +      Private,
>> +      VmwareSvgaRegBitsPerPixel,
>> +      BitsPerPixel
>> +      );
>> +  } else {
>> +    BitsPerPixel = VmwareSvgaRead (
>> +                     Private,
>> +                     VmwareSvgaRegBitsPerPixel
>> +                     );
>> +  }
>> +
>> +  if (FbSize == 0       ||
>> +      MaxWidth == 0     ||
>> +      MaxHeight == 0    ||
>> +      BitsPerPixel == 0 ||
>> +      BitsPerPixel % 8 != 0) {
>> +    Status = EFI_DEVICE_ERROR;
>> +    goto Rollback;
>> +  }
>> +
>> +  ModeData = Private->ModeData;
>> +  ModeInfo = Private->VmwareSvgaModeInfo;
>> +  VideoMode = &QemuVideoBochsModes[0];
>> +  for (Index = 0; Index < QEMU_VIDEO_BOCHS_MODE_COUNT; Index ++) {
>
> Hm, yeah, I see this comes from existing code, but please drop the " "
> in "Index ++".
>
>> +    UINTN RequiredFbSize;
>> +
>> +    RequiredFbSize = (UINTN) VideoMode->Width * VideoMode->Height *
>> +                     (BitsPerPixel / 8);
>> +    if (RequiredFbSize <= FbSize     &&
>> +        VideoMode->Width <= MaxWidth &&
>> +        VideoMode->Height <= MaxHeight) {
>> +      UINT32  BytesPerLine;
>> +      UINT32  RedMask, GreenMask, BlueMask, PixelMask;
>> +
>> +      VmwareSvgaWrite (
>> +        Private,
>> +        VmwareSvgaRegWidth,
>> +        VideoMode->Width
>> +        );
>> +      VmwareSvgaWrite (
>> +        Private,
>> +        VmwareSvgaRegHeight,
>> +        VideoMode->Height
>> +        );
>> +      BytesPerLine = VmwareSvgaRead (
>> +                       Private,
>> +                       VmwareSvgaRegBytesPerLine
>> +                       );
>> +
>> +      ModeData->InternalModeIndex    = Index;
>> +      ModeData->HorizontalResolution = VideoMode->Width;
>> +      ModeData->VerticalResolution   = VideoMode->Height;
>> +      ModeData->ColorDepth           = BitsPerPixel;
>> +
>> +      //
>> +      // Setting VmwareSvgaRegWidth/VmwareSvgaRegHeight actually changes
>> +      // the device's display mode, so we all properties of each mode up front
>
> I think you accidentally the verb :)
>
>> +      // to avoid inadvertent mode changes later.
>> +      //
>> +      ModeInfo->Version = 0;
>> +      ModeInfo->HorizontalResolution = ModeData->HorizontalResolution;
>> +      ModeInfo->VerticalResolution   = ModeData->VerticalResolution;
>> +
>> +      ModeInfo->PixelFormat = PixelBitMask;
>> +
>> +      RedMask   = VmwareSvgaRead (Private, VmwareSvgaRegRedMask);
>> +      ModeInfo->PixelInformation.RedMask = RedMask;
>> +
>> +      GreenMask = VmwareSvgaRead (Private, VmwareSvgaRegGreenMask);
>> +      ModeInfo->PixelInformation.GreenMask = GreenMask;
>> +
>> +      BlueMask  = VmwareSvgaRead (Private, VmwareSvgaRegBlueMask);
>> +      ModeInfo->PixelInformation.BlueMask = BlueMask;
>> +
>> +      BytesPerLine = VmwareSvgaRead (Private, VmwareSvgaRegBytesPerLine);
>> +
>> +      if (BitsPerPixel == 32) {
>> +        if (BlueMask == 0xff && GreenMask == 0xff00 && RedMask == 0xff0000) {
>> +          ModeInfo->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
>> +        } else if (BlueMask == 0xff0000 &&
>> +                   GreenMask == 0xff00 &&
>> +                   RedMask == 0xff) {
>> +          ModeInfo->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;
>> +        }
>> +      }
>> +
>> +      //
>> +      // Reserved mask is whatever bits in the pixel are not used for RGB.
>> +      // PixelMask is as many binary 1s as BitsPerPixel, but shifting UINT32 by
>> +      // 32 is undefined, so work around that. BitsPerPixel isn't 0 so
>> +      // (BitsPerPixel - 1u) is ok.
>> +      //
>
> Ah, OK. I've used this elsewhere, just in reverse order (first shift by
> variable count - 1, then by 1). However, Jordan disliked the trick, and
> ultimately we replaced it with a simple "if".
>
> In fact, above you already have a (BitsPerPixel == 32) check. At the end
> of that block, you could set PixelMask to MAX_UINT32 explicitly. And,
> you could add an "else" branch, simply with
>
>   PixelMask = (1u << (BitsPerPixel - 1)) - 1;
>
> What do you think?

I'm pretty sure you mean

  PixelMask = (1u << BitsPerPixel) - 1;

but yes, that's definitely more readable.

>> +      PixelMask = ((0x1u << 1u) << (BitsPerPixel - 1u)) - 1u;
>> +      ModeInfo->PixelInformation.ReservedMask =
>> +        PixelMask & ~(RedMask | GreenMask | BlueMask);
>> +
>> +      ModeInfo->PixelsPerScanLine = BytesPerLine / (BitsPerPixel / 8);
>> +
>> +      ModeData ++;
>> +      ModeInfo ++;
>> +    }
>> +    VideoMode ++;
>
> Please drop all the spaces before "++".
>
>> +  }
>> +  Private->MaxMode = ModeData - Private->ModeData;
>> +  return EFI_SUCCESS;
>> +
>> +Rollback:
>> +  FreePool(Private->VmwareSvgaModeInfo);
>
> Missing space between "FreePool" and "(".
>
>> +  Private->VmwareSvgaModeInfo = NULL;
>> +
>> +ModeInfoAllocError:
>> +  FreePool(Private->ModeData);
>
> Missing space between "FreePool" and "(".
>
>> +  Private->ModeData = NULL;
>> +
>> +ModeDataAllocError:
>> +  return Status;
>> +}
>>
>
> I think this is a very good update. All my fresh comments have been
> cosmetic. Please submit v4; I expect it to be the final version.

Thanks for your patience and perseverance with this patch! v4 coming
up, hopefully this one's a charm…

Phil

> Thank you,
> Laszlo


  reply	other threads:[~2017-04-05 12:46 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-05  9:57 [PATCH v3 0/3] OvmfPkg/QemuVideoDxe: Add VMWare SVGA framebuffer support Phil Dennis-Jordan
2017-04-05  9:57 ` [PATCH v3 1/3] OvmfPkg: VMWare SVGA display device register definitions Phil Dennis-Jordan
2017-04-05 10:05   ` Laszlo Ersek
2017-04-05  9:57 ` [PATCH v3 2/3] OvmfPkg/QemuVideoDxe: Helper functions for unaligned port I/O Phil Dennis-Jordan
2017-04-05 10:16   ` Laszlo Ersek
2017-04-05  9:58 ` [PATCH v3 3/3] OvmfPkg/QemuVideoDxe: VMWare SVGA device support Phil Dennis-Jordan
2017-04-05 11:41   ` Laszlo Ersek
2017-04-05 12:46     ` Phil Dennis-Jordan [this message]
     [not found]     ` <CAAibmn3sm+QGwp1QaBq+_m4UQy1L1rcG7Z3RRq=L4sY-1WmJyQ@mail.gmail.com>
2017-04-05 12:58       ` Laszlo Ersek

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='CAGCz3vuVDgZo=Bkh6B2ophaLKcu0Hx61seWap59CF9bSEhh+EA@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