2019-09-03 11:58:42 +02:00
|
|
|
/** @file
|
|
|
|
|
|
|
|
Driver with Apple image decode protocol implementation
|
|
|
|
for PNG.
|
|
|
|
|
|
|
|
**/
|
|
|
|
|
2020-02-14 05:48:30 +01:00
|
|
|
#include <Uefi.h>
|
|
|
|
#include <Library/BaseLib.h>
|
2019-09-03 11:58:42 +02:00
|
|
|
#include <Library/UefiLib.h>
|
|
|
|
#include <Library/BaseMemoryLib.h>
|
2020-02-14 12:20:27 +01:00
|
|
|
#include <Library/MemoryAllocationLib.h>
|
2019-09-03 11:58:42 +02:00
|
|
|
#include <Library/DebugLib.h>
|
|
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
|
|
|
|
|
|
#include <Protocol/UgaDraw.h>
|
|
|
|
#include <Protocol/AppleImageCodecProtocol.h>
|
|
|
|
|
2022-08-16 20:30:49 +02:00
|
|
|
//#include "XImage.h"
|
|
|
|
|
2019-09-03 11:58:42 +02:00
|
|
|
#include "picopng.h"
|
2022-08-16 20:30:49 +02:00
|
|
|
//#include "lodepng.h"
|
2019-09-03 11:58:42 +02:00
|
|
|
|
|
|
|
//#define DBG(...) AsciiPrint(__VA_ARGS__);
|
|
|
|
#define DBG(...)
|
|
|
|
|
|
|
|
struct EFI_RES_ENTRY {
|
|
|
|
CHAR8 Name[64];
|
|
|
|
UINT32 DataOffset;
|
|
|
|
UINT32 DataLength;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct EFI_RES {
|
|
|
|
UINT16 Magic; // 0x200 (BigEndian) or 0x02 (LE)
|
|
|
|
UINT16 Num; // LE
|
|
|
|
struct EFI_RES_ENTRY Entries[1]; //NUM - dynamic array
|
|
|
|
};
|
|
|
|
|
|
|
|
//Fool Proof
|
|
|
|
/*
|
|
|
|
02 00 14 00 61 76 61 74 61 72 2E 70 6E 67 00 00
|
|
|
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
|
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
|
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
|
|
00 00 00 00 EC 05 00 00 AF 2D 00 00
|
|
|
|
|
|
|
|
61 76 61 74 61 72 40 32 78 2E 70 6E 67 00 00 00
|
|
|
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
|
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
|
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
|
|
9B 33 00 00 32 84 00 00
|
|
|
|
|
|
|
|
Num=20
|
|
|
|
1. avatar.png Offset=0x05EC (LittleEndian) Size=0x2DAF Offset+Size=0x339B
|
|
|
|
2. avatar@2x.png Offset=0x339C (!) Aligned Size=0x8432 End=0xB7CE
|
|
|
|
3. Offset=0xB7CD = 0x339B+0x8432 Not alinged(!!!) File=0xB7CE Aligned
|
|
|
|
*/
|
|
|
|
|
|
|
|
static EG_IMAGE * egDecodeAny(IN UINT8 *FileData, IN UINTN FileDataLength,
|
|
|
|
IN BOOLEAN WantAlpha)
|
|
|
|
{
|
|
|
|
EG_IMAGE *NewImage;
|
|
|
|
|
|
|
|
//automatic choose format
|
|
|
|
NewImage = egDecodePNG(FileData, FileDataLength, WantAlpha);
|
|
|
|
|
|
|
|
if (!NewImage) {
|
|
|
|
DBG(" ..png is wrong try to decode icns\n");
|
|
|
|
NewImage = egDecodeICNS(FileData, FileDataLength, 128, WantAlpha);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!NewImage) {
|
|
|
|
DBG(" ..png and icns is wrong try to decode bmp\n");
|
|
|
|
NewImage = egDecodeBMP(FileData, FileDataLength, WantAlpha);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NewImage;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// PNG Image codec protocol instance implementation
|
|
|
|
//
|
|
|
|
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
RecognizeImageData (//IN APPLE_IMAGE_CODEC_PROTOCOL* This,
|
|
|
|
VOID *ImageBuffer,
|
|
|
|
UINTN ImageSize,
|
|
|
|
OUT VOID **OutBuffer
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EG_IMAGE *Image;
|
|
|
|
|
|
|
|
if (!ImageBuffer) {
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
if (*(UINT16*)ImageBuffer == 0x02) {
|
|
|
|
return EFI_SUCCESS; //this is efires image
|
|
|
|
}
|
|
|
|
|
|
|
|
DBG("AppleImageCodec RecognizeImageData: Status = ");
|
|
|
|
Image = egDecodeAny((UINT8*)ImageBuffer, ImageSize, FALSE);
|
|
|
|
if (Image == NULL) {
|
|
|
|
DBG("EFI_UNSUPPORTED\n");
|
|
|
|
return EFI_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
DBG("EFI_SUCCESS\n");
|
|
|
|
DBG("ImageBuffer=%p, ImageSize=%d\n", ImageBuffer, ImageSize);
|
|
|
|
DBG("Decoded: W=%d, H=%d\n", Image->Width, Image->Height);
|
|
|
|
egFreeImage(Image);
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
GetImageDims (//IN APPLE_IMAGE_CODEC_PROTOCOL* This,
|
|
|
|
VOID *ImageBuffer,
|
|
|
|
UINTN ImageSize,
|
|
|
|
UINT32 *ImageWidth,
|
|
|
|
UINT32 *ImageHeight
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EG_IMAGE *Image;
|
|
|
|
|
|
|
|
DBG("AppleImageCodec GetImageDims: Status = ");
|
|
|
|
Image = egDecodeAny((UINT8*)ImageBuffer, ImageSize, FALSE);
|
|
|
|
if (Image == NULL) {
|
|
|
|
DBG("EFI_UNSUPPORTED\n");
|
|
|
|
return EFI_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
*ImageWidth = (UINT32)Image->Width;
|
|
|
|
*ImageHeight = (UINT32)Image->Height;
|
|
|
|
|
|
|
|
DBG("EFI_SUCCESS, Width=%d, Height=%d\n", *ImageWidth, *ImageHeight);
|
|
|
|
DBG("ImageBuffer=%p, ImageSize=%d\n", ImageBuffer, ImageSize);
|
|
|
|
DBG("ImageWidth=%p, ImageHeight=%p\n", ImageWidth, ImageHeight);
|
|
|
|
DBG("Decoded: W=%d, H=%d\n", Image->Width, Image->Height);
|
|
|
|
egFreeImage(Image);
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
DecodeImageData (//IN APPLE_IMAGE_CODEC_PROTOCOL* This,
|
|
|
|
VOID *ImageBuffer,
|
|
|
|
UINTN ImageSize,
|
|
|
|
EFI_UGA_PIXEL **RawImageData,
|
|
|
|
UINT32 *RawImageDataSize
|
|
|
|
)
|
|
|
|
{
|
2020-02-14 12:20:27 +01:00
|
|
|
EFI_STATUS Status;
|
2019-09-03 11:58:42 +02:00
|
|
|
EG_IMAGE *Image;
|
|
|
|
INTN Index;
|
|
|
|
//automatic choose format
|
|
|
|
if (!RawImageData || !RawImageDataSize) {
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
DBG("AppleImageCodec DecodeImageData: Status = ");
|
|
|
|
Image = egDecodeAny((UINT8*)ImageBuffer, ImageSize, FALSE);
|
|
|
|
if (Image == NULL) {
|
|
|
|
DBG("EFI_UNSUPPORTED\n");
|
|
|
|
return EFI_UNSUPPORTED;
|
|
|
|
}
|
2020-02-14 12:20:27 +01:00
|
|
|
|
|
|
|
*RawImageDataSize = (UINT32)(Image->Width * Image->Height * sizeof(EFI_UGA_PIXEL));
|
|
|
|
Status = gBS->AllocatePool(EfiBootServicesData, *RawImageDataSize, (VOID **)RawImageData);
|
|
|
|
if (!EFI_ERROR(Status)) {
|
|
|
|
CopyMem(*RawImageData, (VOID*)Image->PixelData, *RawImageDataSize);
|
2019-09-03 11:58:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
DBG("EFI_SUCCESS, RawImageDataSize=%d\n", *RawImageDataSize);
|
2024-06-08 21:51:49 +02:00
|
|
|
DBG("ImageBuffer, ImageSize=%d\n", ImageSize);
|
2019-09-03 11:58:42 +02:00
|
|
|
DBG("Decoded: W=%d, H=%d\n", Image->Width, Image->Height);
|
|
|
|
for (Index=0; Index<10; Index++) {
|
|
|
|
DBG("P%d: r,g,b,a= %x, %x, %x, %x\n", Index, (*RawImageData)[Index].Red, (*RawImageData)[Index].Green, (*RawImageData)[Index].Blue, (*RawImageData)[Index].Reserved);
|
|
|
|
}
|
|
|
|
egFreeImage(Image);
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
Unknown1 (VOID* ImageBuffer, UINTN Param1, UINTN Param2, UINTN Param3)
|
|
|
|
{
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
Unknown2 (VOID* ImageBuffer, UINTN Param1, UINTN Param2, UINTN Param3)
|
|
|
|
{
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Image codec protocol instance. */
|
|
|
|
APPLE_IMAGE_CODEC_PROTOCOL gAppleImageCodec = {
|
|
|
|
// Version
|
|
|
|
1,
|
|
|
|
// FileExt
|
|
|
|
0,
|
|
|
|
|
|
|
|
RecognizeImageData,
|
|
|
|
GetImageDims,
|
|
|
|
DecodeImageData,
|
|
|
|
|
|
|
|
Unknown1,
|
|
|
|
Unknown2,
|
|
|
|
};
|
|
|
|
|
|
|
|
/** Driver's entry point. Installs our StartImage to detect boot loader start. */
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
AppleImageCodecEntrypoint (
|
|
|
|
IN EFI_HANDLE ImageHandle,
|
|
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
2021-02-10 13:32:07 +01:00
|
|
|
// EFI_HANDLE NewHandle;
|
2019-09-03 11:58:42 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// Install instance of Apple image codec protocol for
|
|
|
|
// PNG files
|
|
|
|
//
|
2021-02-10 13:32:07 +01:00
|
|
|
// NewHandle = NULL; // install to a new handle
|
2019-09-03 11:58:42 +02:00
|
|
|
// Status = gBS->InstallMultipleProtocolInterfaces(&NewHandle, &gAppleImageCodecProtocolGuid, &gAppleImageCodec, NULL);
|
|
|
|
Status = gBS->InstallProtocolInterface (
|
|
|
|
&ImageHandle,
|
|
|
|
&gAppleImageCodecProtocolGuid,
|
|
|
|
EFI_NATIVE_INTERFACE,
|
|
|
|
(VOID *)&gAppleImageCodec
|
|
|
|
);
|
|
|
|
|
|
|
|
if (EFI_ERROR(Status)) {
|
|
|
|
DBG("AppleImageCodec: error installing protocol, Status = %r\n", Status);
|
|
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|