diff --git a/sdk/xtdk/xtfw.h b/sdk/xtdk/xtfw.h index 022fef9..87d173e 100644 --- a/sdk/xtdk/xtfw.h +++ b/sdk/xtdk/xtfw.h @@ -82,10 +82,24 @@ typedef struct _FIRMWARE_INFORMATION_BLOCK }; } FIRMWARE_INFORMATION_BLOCK, *PFIRMWARE_INFORMATION_BLOCK; +/* Boot Loader FrameBuffer information block */ +typedef struct _LOADER_GRAPHICS_INFORMATION_BLOCK +{ + BOOLEAN Initialized; + EFI_GRAPHICS_PROTOCOL Protocol; + PVOID Address; + UINT BufferSize; + UINT Width; + UINT Height; + UINT PixelsPerScanLine; + UINT BitsPerPixel; +} LOADER_GRAPHICS_INFORMATION_BLOCK, *PLOADER_GRAPHICS_INFORMATION_BLOCK; + /* Boot Loader information block */ typedef struct _LOADER_INFORMATION_BLOCK { PVOID DbgPrint; + LOADER_GRAPHICS_INFORMATION_BLOCK FrameBuffer; } LOADER_INFORMATION_BLOCK, *PLOADER_INFORMATION_BLOCK; typedef struct _LOADER_MEMORY_MAPPING diff --git a/xtldr/includes/bldefs.h b/xtldr/includes/bldefs.h index cfdc8bb..92cc018 100644 --- a/xtldr/includes/bldefs.h +++ b/xtldr/includes/bldefs.h @@ -22,6 +22,7 @@ /* EFI XT protocols GUIDs */ #define XT_BOOT_LOADER_PROTOCOL_GUID {0x21FF49E8, 0x5854, 0x424C, {0xE9, 0x11, 0x00, 0x86, 0xE1, 0x2C, 0xD9, 0xC1}} #define XT_ELF_IMAGE_PROTOCOL_GUID {0x9B539887, 0x5854, 0x424C, {0x42, 0xFA, 0x00, 0x90, 0xC9, 0x04, 0x66, 0xA4}} +#define XT_FRAMEBUFFER_PROTOCOL_GUID {0x99A87C23, 0x5854, 0x424C, {0xE0, 0x10, 0x00, 0xAA, 0xC0, 0x00, 0xDB, 0xFF}} #define XT_HIVE_IMAGE_PROTOCOL_GUID {0x5A3688A2, 0x5854, 0x424C, {0xBC, 0xDF, 0x00, 0x8F, 0xAA, 0x52, 0x63, 0xD4}} #define XT_PECOFF_IMAGE_PROTOCOL_GUID {0x85DAFF92, 0x5854, 0x424C, {0xB1, 0xBF, 0x00, 0x79, 0x39, 0xEA, 0x6E, 0xFD}} diff --git a/xtldr/includes/blmod.h b/xtldr/includes/blmod.h index fddb05a..5da7470 100644 --- a/xtldr/includes/blmod.h +++ b/xtldr/includes/blmod.h @@ -21,6 +21,10 @@ typedef struct _XT_PECOFFF_IMAGE_PROTOCOL XT_PECOFF_IMAGE_PROTOCOL, *PXT_PECOFF_ /* Pointers to the routines provided by the modules */ typedef EFI_STATUS (*PXT_BOOTPROTO_BOOT_SYSTEM)(IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters); +typedef VOID (*PXT_FRAMEBUFFER_GET_DISPLAY_DRIVER)(OUT PWCHAR *DriverName); +typedef VOID (*PXT_FRAMEBUFFER_GET_DISPLAY_INFORMATION)(OUT PLOADER_GRAPHICS_INFORMATION_BLOCK InformationBlock); +typedef EFI_STATUS (*PXT_FRAMEBUFFER_INITIALIZE)(); +typedef VOID (*PXT_FRAMEBUFFER_PRINT_DISPLAY_INFORMATION)(); typedef EFI_STATUS (*PXT_PECOFF_GET_ENTRY_POINT)(IN PPECOFF_IMAGE_CONTEXT Image, OUT PVOID *EntryPoint); typedef EFI_STATUS (*PXT_PECOFF_GET_MACHINE_TYPE)(IN PPECOFF_IMAGE_CONTEXT Image, OUT PUSHORT MachineType); typedef EFI_STATUS (*PXT_PECOFF_GET_SUBSYSTEM)(IN PPECOFF_IMAGE_CONTEXT Image, OUT PUSHORT SubSystem); @@ -47,6 +51,35 @@ typedef struct _XT_BOOT_PROTOCOL_PARAMETERS PWCHAR Arguments; } XT_BOOT_PROTOCOL_PARAMETERS, *PXT_BOOT_PROTOCOL_PARAMETERS; +/* XT framebuffer support protocol */ +typedef struct _XT_FRAMEBUFFER_PROTOCOL +{ + PXT_FRAMEBUFFER_GET_DISPLAY_DRIVER GetDisplayDriver; + PXT_FRAMEBUFFER_GET_DISPLAY_INFORMATION GetDisplayInformation; + PXT_FRAMEBUFFER_INITIALIZE Initialize; + PXT_FRAMEBUFFER_PRINT_DISPLAY_INFORMATION PrintDisplayInformation; +} XT_FRAMEBUFFER_PROTOCOL, *PXT_FRAMEBUFFER_PROTOCOL; + +/* XT framebuffer information structure definition */ +typedef struct _XT_FRAMEBUFFER_INFORMATION +{ + BOOLEAN Initialized; + EFI_GRAPHICS_PROTOCOL Protocol; + union + { + PEFI_GRAPHICS_OUTPUT_PROTOCOL GOP; + PEFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL UGA; + } Adapter; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + UINT32 BitsPerPixel; + UINT32 BytesPerPixel; + UINT32 PixelsPerScanLine; + EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; + EFI_PHYSICAL_ADDRESS FrameBufferBase; + UINT_PTR FrameBufferSize; +} XT_FRAMEBUFFER_INFORMATION, *PXT_FRAMEBUFFER_INFORMATION; + /* EFI XT PE/COFF Image Protocol */ typedef struct _XT_PECOFFF_IMAGE_PROTOCOL { diff --git a/xtldr/modules/CMakeLists.txt b/xtldr/modules/CMakeLists.txt index 03752af..27e5cb8 100644 --- a/xtldr/modules/CMakeLists.txt +++ b/xtldr/modules/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(dummy) +add_subdirectory(framebuf) add_subdirectory(pecoff) add_subdirectory(xtos) diff --git a/xtldr/modules/framebuf/CMakeLists.txt b/xtldr/modules/framebuf/CMakeLists.txt new file mode 100644 index 0000000..41ebc4c --- /dev/null +++ b/xtldr/modules/framebuf/CMakeLists.txt @@ -0,0 +1,28 @@ +# XT Boot Loader +PROJECT(XTLDR_FRAMEBUF) + +# Specify include directories +include_directories( + ${EXECTOS_SOURCE_DIR}/sdk/xtdk + ${XTLDR_SOURCE_DIR}/includes + ${XTLDR_FRAMEBUF_SOURCE_DIR}/includes) + +# Specify list of source code files +list(APPEND XTLDR_FRAMEBUF_SOURCE + ${XTLDR_SOURCE_DIR}/blproto.c + ${XTLDR_FRAMEBUF_SOURCE_DIR}/framebuf.c + ${XTLDR_FRAMEBUF_SOURCE_DIR}/gop.c) + +# Link bootloader executable +add_executable(framebuf ${XTLDR_FRAMEBUF_SOURCE}) + +# Add linker libraries +target_link_libraries(framebuf libxtos) + +# Set proper binary name and install target +set_target_properties(framebuf PROPERTIES SUFFIX .efi) +set_install_target(framebuf efi/boot/xtldr) + +# Set module entrypoint and subsystem +set_entrypoint(framebuf "BlXtLdrModuleMain") +set_subsystem(framebuf efi_boot_service_driver) diff --git a/xtldr/modules/framebuf/framebuf.c b/xtldr/modules/framebuf/framebuf.c new file mode 100644 index 0000000..baf6b8f --- /dev/null +++ b/xtldr/modules/framebuf/framebuf.c @@ -0,0 +1,274 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/framebuf/framebuf.c + * DESCRIPTION: Boot loader framebuffer support + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/* EFI Image Handle */ +EFI_HANDLE EfiImageHandle; + +/* EFI System Table */ +PEFI_SYSTEM_TABLE EfiSystemTable; + +/* EFI XT Loader Protocol */ +PXT_BOOT_LOADER_PROTOCOL XtLdrProtocol; + +/* XT FrameBuffer Information */ +XT_FRAMEBUFFER_INFORMATION FrameBufferInfo; + +/* XT FrameBuffer Protocol */ +XT_FRAMEBUFFER_PROTOCOL XtFramebufferProtocol; + +/** + * Provides a current FrameBuffer driver name. + * + * @param DriverName + * Supplies a pointer to the memory area where FB driver name will be stored. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +FbGetDisplayDriver(OUT PWCHAR *DriverName) +{ + switch(FrameBufferInfo.Protocol) + { + case GOP: + *DriverName = L"GOP"; + break; + case UGA: + *DriverName = L"UGA"; + break; + default: + *DriverName = L"NONE"; + break; + } +} + +/** + * Returns information about frame buffer in XTOS compatible format. + * + * @param InformationBlock + * A pointer to memory area containing XT structure where all the information will be stored. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +FbGetDisplayInformation(OUT PLOADER_GRAPHICS_INFORMATION_BLOCK InformationBlock) +{ + InformationBlock->Initialized = FrameBufferInfo.Initialized; + InformationBlock->Protocol = FrameBufferInfo.Protocol; + InformationBlock->Address = (PVOID)(UINT_PTR)FrameBufferInfo.FrameBufferBase; + InformationBlock->BufferSize = FrameBufferInfo.FrameBufferSize; + InformationBlock->Width = FrameBufferInfo.HorizontalResolution; + InformationBlock->Height = FrameBufferInfo.VerticalResolution; + InformationBlock->BitsPerPixel = FrameBufferInfo.BitsPerPixel; + InformationBlock->PixelsPerScanLine = FrameBufferInfo.PixelsPerScanLine; +} + +/** + * Initializes FrameBuffer device on GOP and UGA compatible adapters. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +FbInitializeDisplay() +{ + EFI_GUID GopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; + EFI_GUID UgaGuid = EFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL_GUID; + UINT32 Parameter1, Parameter2; + EFI_STATUS Status; + + /* Check if framebuffer already initialized */ + if(!FrameBufferInfo.Initialized) + { + /* Initialize framebuffer */ + XtLdrProtocol->DbgPrint(L"Initializing framebuffer device\n"); + FrameBufferInfo.Protocol = NONE; + FrameBufferInfo.Initialized = FALSE; + + /* Check if GOP already in use */ + Status = EfiSystemTable->BootServices->HandleProtocol(EfiSystemTable->ConsoleOutHandle, &GopGuid, + (PVOID*)&FrameBufferInfo.Adapter.GOP); + if(Status != STATUS_EFI_SUCCESS) + { + /* Locate GOP protocol */ + Status = EfiSystemTable->BootServices->LocateProtocol(&GopGuid, NULL, (PVOID *)&FrameBufferInfo.Adapter.GOP); + } + + /* Check if Graphics Output Protocol is available */ + if(Status == STATUS_EFI_SUCCESS) + { + /* Found GOP */ + XtLdrProtocol->DbgPrint(L"Found GOP compatible display adapter\n"); + + /* Set framebuffer parameters */ + FrameBufferInfo.HorizontalResolution = FrameBufferInfo.Adapter.GOP->Mode->Info->HorizontalResolution; + FrameBufferInfo.VerticalResolution = FrameBufferInfo.Adapter.GOP->Mode->Info->VerticalResolution; + FrameBufferInfo.BitsPerPixel = GoppGetBitsPerPixel(); + FrameBufferInfo.BytesPerPixel = FrameBufferInfo.BitsPerPixel >> 3; + FrameBufferInfo.PixelsPerScanLine = FrameBufferInfo.Adapter.GOP->Mode->Info->PixelsPerScanLine; + FrameBufferInfo.PixelFormat = FrameBufferInfo.Adapter.GOP->Mode->Info->PixelFormat; + FrameBufferInfo.FrameBufferBase = FrameBufferInfo.Adapter.GOP->Mode->FrameBufferBase; + FrameBufferInfo.FrameBufferSize = FrameBufferInfo.Adapter.GOP->Mode->FrameBufferSize; + FrameBufferInfo.Protocol = GOP; + FrameBufferInfo.Initialized = TRUE; + } + else + { + /* GOP is unavailable */ + FrameBufferInfo.Adapter.GOP = NULL; + + /* Check if UGA already in use */ + Status = EfiSystemTable->BootServices->HandleProtocol(EfiSystemTable->ConsoleOutHandle, &UgaGuid, + (PVOID*)&FrameBufferInfo.Adapter.UGA); + if(Status != STATUS_EFI_SUCCESS) + { + /* Locate UGA protocol */ + Status = EfiSystemTable->BootServices->LocateProtocol(&UgaGuid, NULL, + (PVOID*)&FrameBufferInfo.Adapter.UGA); + } + + /* Check if Universal Graphics Adapter is available */ + if(Status == STATUS_EFI_SUCCESS) + { + /* Found UGA */ + XtLdrProtocol->DbgPrint(L"Found UGA compatible display adapter\n"); + + /* Get current mode */ + Status = FrameBufferInfo.Adapter.UGA->GetMode(FrameBufferInfo.Adapter.UGA, + &FrameBufferInfo.HorizontalResolution, + &FrameBufferInfo.VerticalResolution, + &Parameter1, &Parameter2); + if(Status != STATUS_EFI_SUCCESS) + { + /* Unable to get current UGA mode */ + XtLdrProtocol->DbgPrint(L"Failed to get current UGA mode (Status code: %lx)\n", Status); + FrameBufferInfo.Adapter.UGA = NULL; + } + else + { + /* Set framebuffer parameters */ + FrameBufferInfo.BitsPerPixel = 32; + FrameBufferInfo.BytesPerPixel = 4; + FrameBufferInfo.PixelsPerScanLine = FrameBufferInfo.HorizontalResolution; + FrameBufferInfo.PixelFormat = PixelBlueGreenRedReserved8BitPerColor; + FrameBufferInfo.FrameBufferBase = 0; + FrameBufferInfo.FrameBufferSize = FrameBufferInfo.HorizontalResolution * + FrameBufferInfo.VerticalResolution * + FrameBufferInfo.BytesPerPixel + 1024; + FrameBufferInfo.Protocol = UGA; + + /* Temporarily set this to FALSE, as we don't set FB base and we cannot use it anyway */ + FrameBufferInfo.Initialized = FALSE; + } + } + } + + /* Make sure framebuffer initialized properly */ + if(!FrameBufferInfo.Initialized) + { + /* GOP and UGA unavailable */ + XtLdrProtocol->DbgPrint(L"No display adapter found\n"); + return STATUS_EFI_NOT_FOUND; + } + } + + /* Return success */ + return STATUS_SUCCESS; +} + +/** + * Prints important information about framebuffer. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +FbPrintDisplayInformation() +{ + PWCHAR DriverName; + + /* Make sure frame buffer is initialized */ + if(!FrameBufferInfo.Initialized) + { + /* No FrameBuffer */ + XtLdrProtocol->DbgPrint(L"No display adapters initialized, unable to print video information\n"); + return; + } + + /* Get display driver name */ + FbGetDisplayDriver(&DriverName); + + /* Print video information */ + XtLdrProtocol->DbgPrint(L"XTLDR Framebuffer information:\n" + L" FrameBuffer Address: 0x%lx\n" + L" FrameBuffer Size: %lu\n" + L" FrameBuffer Driver: %S\n" + L" Current Resolution: %ux%ux%u\n" + L" Pixel Format: %u\n" + L" Pixels Per ScanLine: %u\n", + FrameBufferInfo.FrameBufferBase, FrameBufferInfo.FrameBufferSize, DriverName, + FrameBufferInfo.HorizontalResolution, FrameBufferInfo.VerticalResolution, + FrameBufferInfo.BitsPerPixel, FrameBufferInfo.PixelFormat, + FrameBufferInfo.PixelsPerScanLine); +} + +/** + * This routine is the entry point of the XT EFI boot loader module. + * + * @param ImageHandle + * Firmware-allocated handle that identifies the image. + * + * @param SystemTable + * Provides the EFI system table. + * + * @return This routine returns status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable) +{ + EFI_GUID Guid = XT_FRAMEBUFFER_PROTOCOL_GUID; + EFI_HANDLE Handle = NULL; + EFI_STATUS Status; + + /* Set the system table and image handle */ + EfiImageHandle = ImageHandle; + EfiSystemTable = SystemTable; + + /* Open the XTLDR protocol */ + Status = BlGetXtLoaderProtocol(&XtLdrProtocol); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to open loader protocol */ + return STATUS_EFI_PROTOCOL_ERROR; + } + + XtFramebufferProtocol.GetDisplayDriver = FbGetDisplayDriver; + XtFramebufferProtocol.GetDisplayInformation = FbGetDisplayInformation; + XtFramebufferProtocol.Initialize = FbInitializeDisplay; + XtFramebufferProtocol.PrintDisplayInformation = FbPrintDisplayInformation; + + /* Register XTOS boot protocol */ + return EfiSystemTable->BootServices->InstallProtocolInterface(&Handle, &Guid, EFI_NATIVE_INTERFACE, + &XtFramebufferProtocol); +} diff --git a/xtldr/modules/framebuf/gop.c b/xtldr/modules/framebuf/gop.c new file mode 100644 index 0000000..ea9c732 --- /dev/null +++ b/xtldr/modules/framebuf/gop.c @@ -0,0 +1,51 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/framebuf/gop.c + * DESCRIPTION: Graphical Output Protocol (GOP) support + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/** + * Returns a number of bits per pixel (BPP) in the current video mode. + * + * @return A number of bits per pixel. + * + * @since XT 1.0 + */ +XTCDECL +UINT32 +GoppGetBitsPerPixel() +{ + UINT32 BitsPerPixel, CompoundMask; + + switch(FrameBufferInfo.Adapter.GOP->Mode->Info->PixelFormat) + { + case PixelBlueGreenRedReserved8BitPerColor: + case PixelRedGreenBlueReserved8BitPerColor: + case PixelBltOnly: + BitsPerPixel = 32; + break; + case PixelBitMask: + BitsPerPixel = 32; + CompoundMask = FrameBufferInfo.Adapter.GOP->Mode->Info->PixelInformation.RedMask | + FrameBufferInfo.Adapter.GOP->Mode->Info->PixelInformation.GreenMask | + FrameBufferInfo.Adapter.GOP->Mode->Info->PixelInformation.BlueMask | + FrameBufferInfo.Adapter.GOP->Mode->Info->PixelInformation.ReservedMask; + while((CompoundMask & (1 << 31)) == 0) + { + BitsPerPixel--; + CompoundMask <<= 1; + } + break; + default: + BitsPerPixel = 0; + break; + } + + /* Return bpp */ + return BitsPerPixel; +} diff --git a/xtldr/modules/framebuf/includes/framebuf.h b/xtldr/modules/framebuf/includes/framebuf.h new file mode 100644 index 0000000..12f54c3 --- /dev/null +++ b/xtldr/modules/framebuf/includes/framebuf.h @@ -0,0 +1,44 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/framebuf/includes/framebuf.h + * DESCRIPTION: Framebuffer support module header file + * DEVELOPERS: Rafal Kupiec + */ + +#ifndef __XTLDR_MODULES_FRAMEBUF_H +#define __XTLDR_MODULES_FRAMEBUF_H + +#include + + +/* XT FrameBuffer Information */ +EXTERN XT_FRAMEBUFFER_INFORMATION FrameBufferInfo; + +/* FrameBuffer support protocol related routines forward references */ +XTCDECL +VOID +FbGetDisplayDriver(OUT PWCHAR *DriverName); + +XTCDECL +VOID +FbGetDisplayInformation(OUT PLOADER_GRAPHICS_INFORMATION_BLOCK InformationBlock); + +XTCDECL +EFI_STATUS +FbInitializeDisplay(); + +XTCDECL +VOID +FbPrintDisplayInformation(); + +XTCDECL +UINT32 +GoppGetBitsPerPixel(); + +XTCDECL +EFI_STATUS +BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable); + +#endif /* __XTLDR_MODULES_FRAMEBUF_H */