diff --git a/xtldr2/modules/CMakeLists.txt b/xtldr2/modules/CMakeLists.txt index cde0c5e..ffdddb3 100644 --- a/xtldr2/modules/CMakeLists.txt +++ b/xtldr2/modules/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(dummy) +add_subdirectory(fb_o) add_subdirectory(pecoff_o) diff --git a/xtldr2/modules/fb_o/CMakeLists.txt b/xtldr2/modules/fb_o/CMakeLists.txt new file mode 100644 index 0000000..f8d811b --- /dev/null +++ b/xtldr2/modules/fb_o/CMakeLists.txt @@ -0,0 +1,27 @@ +# XT Boot Loader +PROJECT(XTLDR_FB_O) + +# Specify include directories +include_directories( + ${EXECTOS_SOURCE_DIR}/sdk/xtdk + ${XTLDR_FB_O_SOURCE_DIR}/includes) + +# Specify list of source code files +list(APPEND XTLDR_FB_O_SOURCE + ${XTLDR_FB_O_SOURCE_DIR}/framebuf.c + ${XTLDR_FB_O_SOURCE_DIR}/gop.c) + +# Link bootloader executable +add_executable(fb_o ${XTLDR_FB_O_SOURCE}) + +# Add linker libraries +target_link_libraries(fb_o libxtos libxtldr) + +# Set proper binary name and install target +set_target_properties(fb_o PROPERTIES SUFFIX .efi) +set_install_target(fb_o efi/boot/xtldr/modules) + +# Set module entrypoint and subsystem +set_entrypoint(fb_o "XtLdrModuleMain") +set_linker_map(fb_o TRUE) +set_subsystem(fb_o efi_boot_service_driver) diff --git a/xtldr2/modules/fb_o/framebuf.c b/xtldr2/modules/fb_o/framebuf.c new file mode 100644 index 0000000..cd8db2e --- /dev/null +++ b/xtldr2/modules/fb_o/framebuf.c @@ -0,0 +1,256 @@ +/** + * 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 + + +/* PE/COFF_O module information */ +XTBL_MODINFO = L"EFI FB (FrameBuffer) support"; + +/* EFI XT Loader Protocol */ +PXTBL_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)(ULONG_PTR)FrameBufferInfo.FrameBufferBase; + InformationBlock->BufferSize = FrameBufferInfo.FrameBufferSize; + InformationBlock->Width = FrameBufferInfo.HorizontalResolution; + InformationBlock->Height = FrameBufferInfo.VerticalResolution; + InformationBlock->BitsPerPixel = FrameBufferInfo.BitsPerPixel; + InformationBlock->PixelsPerScanLine = FrameBufferInfo.PixelsPerScanLine; + InformationBlock->Pitch = FrameBufferInfo.Pitch; +} + +/** + * 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->Debug.Print(L"Initializing framebuffer device\n"); + FrameBufferInfo.Protocol = NONE; + FrameBufferInfo.Initialized = FALSE; + + /* Attempt to open GOP protocol */ + Status = XtLdrProtocol->Protocol.Open((PVOID*)&FrameBufferInfo.Adapter.GOP, &GopGuid); + + /* Check if Graphics Output Protocol is available */ + if(Status == STATUS_EFI_SUCCESS) + { + /* Found GOP */ + XtLdrProtocol->Debug.Print(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.Pitch = FrameBufferInfo.PixelsPerScanLine * (FrameBufferInfo.BitsPerPixel / 8); + 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; + + /* Attempt to open UGA protocol */ + Status = XtLdrProtocol->Protocol.Open((PVOID*)&FrameBufferInfo.Adapter.UGA, &UgaGuid); + + /* Check if Universal Graphics Adapter is available */ + if(Status == STATUS_EFI_SUCCESS) + { + /* Found UGA */ + XtLdrProtocol->Debug.Print(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->Debug.Print(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.Pitch = FrameBufferInfo.PixelsPerScanLine * (FrameBufferInfo.BitsPerPixel / 8); + 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->Debug.Print(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->Debug.Print(L"No display adapters initialized, unable to print video information\n"); + return; + } + + /* Get display driver name */ + FbGetDisplayDriver(DriverName); + + /* Print video information */ + XtLdrProtocol->Debug.Print(L"TEST: %S\n", DriverName); + XtLdrProtocol->Debug.Print(L"XTLDR Framebuffer information:\n" + L" FrameBuffer Address: 0x%lx\n" + L" FrameBuffer Size: %lu\n" + L" FrameBuffer Driver: %S\n", + FrameBufferInfo.FrameBufferBase, FrameBufferInfo.FrameBufferSize, DriverName); + XtLdrProtocol->Debug.Print(L" Current Resolution: %dx%dx%d\n" + L" Pixel Format: %u\n" + L" Pixels Per ScanLine: %u\n", + 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 +XtLdrModuleMain(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable) +{ + EFI_GUID Guid = XT_FRAMEBUFFER_PROTOCOL_GUID; + EFI_STATUS Status; + + /* Open the XTLDR protocol */ + Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &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 XtLdrProtocol->Protocol.Register(&Guid, &XtFramebufferProtocol); +} diff --git a/xtldr2/modules/fb_o/gop.c b/xtldr2/modules/fb_o/gop.c new file mode 100644 index 0000000..baa746f --- /dev/null +++ b/xtldr2/modules/fb_o/gop.c @@ -0,0 +1,51 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/fb_o/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/xtldr2/modules/fb_o/includes/framebuf.h b/xtldr2/modules/fb_o/includes/framebuf.h new file mode 100644 index 0000000..164eae4 --- /dev/null +++ b/xtldr2/modules/fb_o/includes/framebuf.h @@ -0,0 +1,79 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/fb_o/includes/framebuf.h + * DESCRIPTION: Framebuffer support module header file + * DEVELOPERS: Rafal Kupiec + */ + +#ifndef __XTLDR_MODULES_FRAMEBUF_H +#define __XTLDR_MODULES_FRAMEBUF_H + +#include + + +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)(); + +/* 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; + UINT HorizontalResolution; + UINT VerticalResolution; + UINT BitsPerPixel; + UINT BytesPerPixel; + UINT PixelsPerScanLine; + UINT Pitch; + EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; + EFI_PHYSICAL_ADDRESS FrameBufferBase; + ULONG_PTR FrameBufferSize; +} XT_FRAMEBUFFER_INFORMATION, *PXT_FRAMEBUFFER_INFORMATION; + +/* 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 */