Re: EFI_PIXEL_BITMASK


Konstantin Aladyshev
 

Thanks for the explanation!

Here are my investigations to complete this conversation.

https://github.com/tianocore/edk2/blob/master/OvmfPkg/OvmfPkgX64.dsc
```
DEFINE SOURCE_DEBUG_ENABLE = FALSE
...
!if $(SOURCE_DEBUG_ENABLE) == TRUE
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
!else
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F
!endif
```

https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/DebugLib.h
```
//
// Declare bits for PcdDebugPropertyMask
//
#define DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED 0x01
#define DEBUG_PROPERTY_DEBUG_PRINT_ENABLED 0x02
#define DEBUG_PROPERTY_DEBUG_CODE_ENABLED 0x04
#define DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED 0x08
#define DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED 0x10
#define DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED 0x20
```
Therefore DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED is set when SOURCE_DEBUG_ENABLE
is FALSE.

With this knowledge I've tried to recompile OVMF:
```
build --platform=OvmfPkg/OvmfPkgX64.dsc --arch=X64 --buildtarget=RELEASE
--tagname=GCC5 -D SOURCE_DEBUG_ENABLE
```

And this indeed has changed bitmask values from 0xAF to some random garbage:
```
Pixel bitmask: R(0x00000005) G(0x00000000) B(0x07AC9000)
```

Best regards,
Konstantin Aladyshev

On Thu, Jul 15, 2021 at 11:15 PM Andrew Fish <afish@apple.com> wrote:



On Jul 15, 2021, at 12:36 PM, Konstantin Aladyshev <aladyshev22@gmail.com>
wrote:

Thanks Andrew!
I've missed that part in the spec.
In my case:
```
Pixel format: 1
```
So according to the

https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/GraphicsOutput.h
my pixel format is `PixelBlueGreenRedReserved8BitPerColor`. You are
correct.
```
typedef enum {
PixelRedGreenBlueReserved8BitPerColor,
PixelBlueGreenRedReserved8BitPerColor,
PixelBitMask,
PixelBltOnly,
PixelFormatMax
} EFI_GRAPHICS_PIXEL_FORMAT;
```

When I used `dmem` in UEFI shell I've always wondered why all
uninitialized memory has this strange 0xAF value.
It's very interesting to know that it was named after you)
I've tried to find the exact commit to look at the commit message that
added this feature, but unfortunately it was before git. In the first
git commit this PCD is already present.

https://github.com/tianocore/edk2/commit/e053747a04ad7b8d71c7593b93e1575ba0057a91#diff-3de08afb0837cd4b0283b60925b72da84b616967cff4301d12929654946e75c8


Vincent added the 0xAF convention back in the early Itanium days so it
goes back to the original Intel EFI code base, so way backā€¦ Before edk2,
and before the original EDK. Ha Ha so it is actually older than git, that
is your problem :).

But I have to notice that both OVMF and my app were built in the RELEASE
mode



https://github.com/tianocore/edk2/blob/master/OvmfPkg/OvmfPkgX64.dsc#L543
OvmfPkg/OvmfPkgX64.dsc
!if $(SOURCE_DEBUG_ENABLE) == TRUE
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
!else
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F
!endif

Given:

https://github.com/tianocore/edk2/blob/master/MdePkg/MdePkg.dec#L2200
## The mask is used to control DebugLib behavior.<BR><BR>
# BIT0 - Enable Debug Assert.<BR>
# BIT1 - Enable Debug Print.<BR>
# BIT2 - Enable Debug Code.<BR>
# BIT3 - Enable Clear Memory.<BR>
# BIT4 - Enable BreakPoint as ASSERT.<BR>
# BIT5 - Enable DeadLoop as ASSERT.<BR>
# @Prompt Debug Property.
# @Expression 0x80000002 |
(gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask & 0xC0) == 0
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0|UINT8|0x00000005


So it looks like OVMF has the same settings for DEBUG and RELEASE builds.
That matches what you are seeing.


This is how the DebugLib hooks all this in.


https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/DebugLib.h#L543

#define DEBUG_CLEAR_MEMORY(Address, Length) \
do { \
if (DebugClearMemoryEnabled ()) { \
DebugClearMemory (Address, Length); \
} \
} while (FALSE)


https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/DebugLib.h#L252
/**
Returns TRUE if DEBUG_CLEAR_MEMORY() macro is enabled.
This function returns TRUE if the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit
of
PcdDebugProperyMask is set. Otherwise, FALSE is returned.
@retval TRUE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of
PcdDebugProperyMask is set.
@retval FALSE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of
PcdDebugProperyMask is clear.
**/
BOOLEAN
EFIAPI
DebugClearMemoryEnabled (
VOID
);

If you search for DEBUG_CLEAR_MEMORY that is the code in the DXE Core (
MdeModulePkg/Core/Dxe/Mem/Pool.c) that is doing the clear on free.

Thanks,

Andrew Fish


Best regards,
Konstantin Aladyshev

On Thu, Jul 15, 2021 at 8:54 PM Andrew Fish <afish@apple.com> wrote:




On Jul 15, 2021, at 10:09 AM, Konstantin Aladyshev <aladyshev22@gmail.com>
wrote:

I've written an UEFI_APPLICATION that shows the current GOP mode
information.
This is example output from it, when it is run in the UEFI shell of
OVMF under QEMU:
```
FS0:\> GOPInfo.efi
Framebuffer base: 0000000080000000
Framebuffer size: 0000000000500000

Current mode: 14
Version: 0
Resolution: 1280x1024
Pixel format: 1
Pixel bitmask: R(0xAFAFAFAF) G(0xAFAFAFAF) B(0xAFAFAFAF)


Konstantin,

If you look more closely at the UEFI Spec you will see that
EFI_PIXEL_BITMASK (PixelInformation) is only valid if PixelFormat ==
PixelBlitMask. PixelRedGreenBlueReserved8BitPerColor and
PixelBlueGreenRedReserved8BitPerColor define a specific mapping for the
bits. So you should only display EFI_PIXEL_BITMASK if PixelFormat ==
PixelBitMask. Looks like in your case it is
PixelBlueGreenRedReserved8BitPerColor?


FYI 0xAF (my initials thanks to Vincent Zimmer) is the pattern for cleared
memory. The DEBUG_CLEAR_MEMORY() function is called by the DXE Core when
pool is freed. It is usually only enabled on a DEBUG build. The value comes
from PcdDebugClearMemoryValue

$ git grep PcdDebugClearMemoryValue -- *.dec
MdePkg/MdePkg.dec:2242:
gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue|0xAF|UINT8|0x00000008

So the value never got initialized and it is a reused allocation thus the
malloc buffer in the QEMU graphics driver is full of 0xAF. This is also a
common patter on use after free bugs.

Thanks,

Andrew Fish

PixelsPerScanLine: 1280
```
My question is about the `Pixel bitmask` string. According to the UEFI
specification it is defined like this:
```
typedef struct {
UINT32 RedMask;
UINT32 GreenMask;
UINT32 BlueMask;
UINT32 ReservedMask;
} EFI_PIXEL_BITMASK;

If a bit is set in RedMask, GreenMask, or BlueMask then those bits of
the pixel represent the corresponding color. Bits in RedMask,
GreenMask, BlueMask, and ReserverdMask must not overlap bit positions.
The values for the red, green, and blue components in the bit mask
represent the color intensity. The color intensities must increase as
the color values for a each color mask increase with a minimum
intensity of all bits in a color mask clear to a maximum intensity of
all bits in a color mask set.
```

From this definition I was expecting something like this:
```
Pixel bitmask: R(0x00FF0000) G(0x0000FF00) B(0x000000FF)
```
But my program gives me this:
```
Pixel bitmask: R(0xAFAFAFAF) G(0xAFAFAFAF) B(0xAFAFAFAF)
```
What does it mean?

Just in case I did something silly here is a code of my simple app:
```
VOID PrintGOPModeInfo(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* GOPModeInfo)
{
Print(L"Version: %x\n", GOPModeInfo->Version);
Print(L"Resolution: %dx%d\n", GOPModeInfo->HorizontalResolution,
GOPModeInfo->VerticalResolution);
Print(L"Pixel format: %d\n", GOPModeInfo->PixelFormat);
Print(L"Pixel bitmask: R(0x%08x) G(0x%08x) B(0x%08x)\n",
GOPModeInfo->PixelInformation.RedMask,

GOPModeInfo->PixelInformation.GreenMask,

GOPModeInfo->PixelInformation.BlueMask);

Print(L"PixelsPerScanLine: %d\n", GOPModeInfo->PixelsPerScanLine);
}


EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_GRAPHICS_OUTPUT_PROTOCOL* GOP;

EFI_STATUS Status = gBS->LocateProtocol(
&gEfiGraphicsOutputProtocolGuid,
NULL,
(VOID **)&GOP);
if (EFI_ERROR(Status)) {
Print(L"Can't get GOP: %r\n", Status);
return Status;
}
Print(L"Framebuffer base: %016llx\n", GOP->Mode->FrameBufferBase);
Print(L"Framebuffer size: %016llx\n", GOP->Mode->FrameBufferSize);

Print(L"\n");
Print(L"Current mode: %d\n", GOP->Mode->Mode);
PrintGOPModeInfo(GOP->Mode->Info);
return EFI_SUCCESS;
}
```

Best regards,
Konstantin Aladyshev







Join discuss@edk2.groups.io to automatically receive all group messages.