Added framebuffer initialization using GOP.
This commit is contained in:
parent
bf8949113b
commit
9962ef21f2
@ -63,4 +63,19 @@ struct EfiMemoryMap
|
||||
}
|
||||
};
|
||||
|
||||
struct EfiDisplayInfo
|
||||
{
|
||||
void* frameBufferBase;
|
||||
uint64_t frameBufferSize;
|
||||
uint32_t frameBufferWidth;
|
||||
uint32_t frameBufferHeight;
|
||||
uint32_t frameBufferPitch;
|
||||
};
|
||||
|
||||
struct EfiBootInfo
|
||||
{
|
||||
EfiMemoryMap memoryMap;
|
||||
EfiDisplayInfo displayInfo;
|
||||
};
|
||||
|
||||
#endif // BOOT_HPP_INCLUDED
|
||||
|
@ -12,7 +12,7 @@ stack_top:
|
||||
.type _start, @function
|
||||
_start:
|
||||
// store the memory map
|
||||
mov %rbx, (gMemoryMap)
|
||||
mov %rbx, (gBootInfo)
|
||||
|
||||
// setup stack
|
||||
mov $stack_top, %rsp
|
||||
|
@ -61,7 +61,7 @@ void initGlobals()
|
||||
|
||||
extern "C"
|
||||
{
|
||||
EfiMemoryMap* gMemoryMap;
|
||||
EfiBootInfo* gBootInfo;
|
||||
|
||||
void _init();
|
||||
void _fini();
|
||||
@ -76,10 +76,30 @@ void kernel_main()
|
||||
|
||||
std::printf("Kernel End: %p\n", &gKernelEnd);
|
||||
|
||||
struct Pixel
|
||||
{
|
||||
uint8_t blue = 0;
|
||||
uint8_t green = 0;
|
||||
uint8_t red = 0;
|
||||
uint8_t reserved = 0;
|
||||
};
|
||||
auto setPixel = [](unsigned x, unsigned y, Pixel color)
|
||||
{
|
||||
Pixel* framebuffer = static_cast<Pixel*>(gBootInfo->displayInfo.frameBufferBase);
|
||||
framebuffer[y * gBootInfo->displayInfo.frameBufferPitch / 4 + x] = color;
|
||||
};
|
||||
for (int x = 0; x < 100; ++x)
|
||||
{
|
||||
for (int y = 0; y < 100; ++y)
|
||||
{
|
||||
setPixel(x, y, {.red = 255});
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize the heap */
|
||||
// assert(gMultibootHeader->flags & MULTIBOOT_INFO_MEM_MAP);
|
||||
// initHeapFromMultibootHeader(gMultibootHeader->mmap_addr, gMultibootHeader->mmap_length);
|
||||
initHeapFromEfiMemoryMap(*gMemoryMap);
|
||||
initHeapFromEfiMemoryMap(gBootInfo->memoryMap);
|
||||
|
||||
main();
|
||||
|
||||
|
@ -9,6 +9,7 @@ extern "C"
|
||||
#include "miniprintf.hpp"
|
||||
|
||||
// debug stuff
|
||||
// #define DUMP_DISPLAY_MODES
|
||||
// #define DUMP_MEMORY_MAP
|
||||
// #define DUMP_ELF
|
||||
|
||||
@ -16,6 +17,7 @@ namespace
|
||||
{
|
||||
EFI_SYSTEM_TABLE* gSystemTable;
|
||||
EFI_BOOT_SERVICES* gBootServices;
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL* gGraphicsOutputProtocol;
|
||||
|
||||
EFI_STATUS openImageVolume(EFI_HANDLE image, EFI_FILE_HANDLE& outHandle)
|
||||
{
|
||||
@ -132,6 +134,59 @@ EFI_STATUS getEfiMemoryMap(EfiMemoryMap& outMemoryMap)
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS getEfiGraphicsOutputProtocol(EFI_GRAPHICS_OUTPUT_PROTOCOL*& outGOP)
|
||||
{
|
||||
static const EFI_GUID GOP_GUID = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
||||
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL* gop;
|
||||
EFI_STATUS status = gBootServices->LocateProtocol(const_cast<EFI_GUID*>(&GOP_GUID), nullptr, reinterpret_cast<void**>(&gop));
|
||||
if (EFI_ERROR(status)) {
|
||||
return status;
|
||||
}
|
||||
outGOP = gop;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS queryEfiDisplayModes(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION*& outModes)
|
||||
{
|
||||
UINTN sizeOfInfo = gGraphicsOutputProtocol->Mode->SizeOfInfo;
|
||||
outModes = new EFI_GRAPHICS_OUTPUT_MODE_INFORMATION[gGraphicsOutputProtocol->Mode->MaxMode];
|
||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* buffer = static_cast<EFI_GRAPHICS_OUTPUT_MODE_INFORMATION*>(malloc(sizeOfInfo));
|
||||
|
||||
for (UINT32 modeIdx = 0; modeIdx < gGraphicsOutputProtocol->Mode->MaxMode; ++modeIdx)
|
||||
{
|
||||
EFI_STATUS status = gGraphicsOutputProtocol->QueryMode(gGraphicsOutputProtocol, modeIdx, &sizeOfInfo, &buffer);
|
||||
if (EFI_ERROR(status))
|
||||
{
|
||||
delete[] outModes;
|
||||
free(buffer);
|
||||
return status;
|
||||
}
|
||||
outModes[modeIdx] = *buffer;
|
||||
}
|
||||
free(buffer);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
UINT32 findBestDisplayMode(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* displayModes)
|
||||
{
|
||||
UINT32 bestMode = 0;
|
||||
uint32_t bestModePixels = 0;
|
||||
for (UINT32 modeIdx = 0; modeIdx < gGraphicsOutputProtocol->Mode->MaxMode; ++modeIdx)
|
||||
{
|
||||
if (displayModes[modeIdx].PixelFormat != PixelBlueGreenRedReserved8BitPerColor) {
|
||||
continue; // we don't care about anything but RGB
|
||||
}
|
||||
const uint32_t pixels = displayModes[modeIdx].VerticalResolution * displayModes[modeIdx].HorizontalResolution;
|
||||
if (pixels > bestModePixels)
|
||||
{
|
||||
bestMode = modeIdx;
|
||||
bestModePixels = pixels;
|
||||
}
|
||||
}
|
||||
return bestMode;
|
||||
}
|
||||
|
||||
bool isEfiMemoryTypeUsable(EFI_MEMORY_TYPE type)
|
||||
{
|
||||
switch (type)
|
||||
@ -167,17 +222,56 @@ if (EFI_ERROR(status)) \
|
||||
|
||||
extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable)
|
||||
{
|
||||
/* Store the system table for future use in other functions */
|
||||
// store the system table for future use in other functions
|
||||
gSystemTable = systemTable;
|
||||
gBootServices = systemTable->BootServices;
|
||||
|
||||
initMiniMalloc();
|
||||
initMiniPrintf(&putchar);
|
||||
|
||||
// this will be passed to the OS
|
||||
EfiBootInfo* bootInfo = new EfiBootInfo;
|
||||
|
||||
gSystemTable->ConOut->ClearScreen(gSystemTable->ConOut);
|
||||
|
||||
// load GOP and detect modes
|
||||
EFI_STATUS status = getEfiGraphicsOutputProtocol(gGraphicsOutputProtocol);
|
||||
DIE_ON_ERROR(L"Error getting EFI GOP.");
|
||||
|
||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* displayModes = nullptr;
|
||||
status = queryEfiDisplayModes(displayModes);
|
||||
DIE_ON_ERROR(L"Error querying EFI display modes.");
|
||||
|
||||
const UINT32 bestModeIdx = findBestDisplayMode(displayModes);
|
||||
status = gGraphicsOutputProtocol->SetMode(gGraphicsOutputProtocol, bestModeIdx);
|
||||
DIE_ON_ERROR(L"Error setting display mode.");
|
||||
|
||||
bootInfo->displayInfo = {
|
||||
.frameBufferBase = reinterpret_cast<void*>(gGraphicsOutputProtocol->Mode->FrameBufferBase),
|
||||
.frameBufferSize = gGraphicsOutputProtocol->Mode->FrameBufferSize,
|
||||
.frameBufferWidth = gGraphicsOutputProtocol->Mode->Info->HorizontalResolution,
|
||||
.frameBufferHeight = gGraphicsOutputProtocol->Mode->Info->VerticalResolution,
|
||||
.frameBufferPitch = 4 * gGraphicsOutputProtocol->Mode->Info->PixelsPerScanLine
|
||||
};
|
||||
|
||||
#if defined(DUMP_DISPLAY_MODES)
|
||||
printf("Display modes:\n");
|
||||
for (UINT32 modeIdx = 0; modeIdx < gGraphicsOutputProtocol->Mode->MaxMode; ++modeIdx)
|
||||
{
|
||||
const EFI_GRAPHICS_OUTPUT_MODE_INFORMATION& mode = displayModes[modeIdx];
|
||||
printf(
|
||||
"Mode %d: width=%d, height=%d, format=%d%s\n",
|
||||
modeIdx,
|
||||
mode.HorizontalResolution,
|
||||
mode.VerticalResolution,
|
||||
mode.PixelFormat,
|
||||
modeIdx == gGraphicsOutputProtocol->Mode->Mode ? " (current)" : ""
|
||||
);
|
||||
}
|
||||
#endif // defined(DUMP_DISPLAY_MODES)
|
||||
|
||||
EFI_FILE_HANDLE volume;
|
||||
EFI_STATUS status = openImageVolume(imageHandle, volume);
|
||||
status = openImageVolume(imageHandle, volume);
|
||||
DIE_ON_ERROR(L"Error opening image volume.");
|
||||
|
||||
const CHAR16* fileName = L"kernel.bin";
|
||||
@ -204,7 +298,7 @@ extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemT
|
||||
for (uint16_t phtEntry = 0; phtEntry < header.phtEntryCount; ++phtEntry)
|
||||
{
|
||||
status = fileHandle->SetPosition(fileHandle, header.phtOffset + phtEntry * header.phtEntrySize);
|
||||
DIE_ON_ERROR("Error seeking in EFI64 file.");
|
||||
DIE_ON_ERROR(L"Error seeking in EFI64 file.");
|
||||
Efi64ProgramHeader programHeader = {};
|
||||
bufferSize = sizeof(Efi64ProgramHeader);
|
||||
status = fileHandle->Read(fileHandle, &bufferSize, &programHeader);
|
||||
@ -230,8 +324,7 @@ extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemT
|
||||
DIE_ON_ERROR("Error reading ELF64 section.");
|
||||
}
|
||||
|
||||
EfiMemoryMap* memoryMap = new EfiMemoryMap;
|
||||
status = getEfiMemoryMap(*memoryMap);
|
||||
status = getEfiMemoryMap(bootInfo->memoryMap);
|
||||
DIE_ON_ERROR("Error getting EFI memory map.");
|
||||
|
||||
#if defined(DUMP_MEMORY_MAP)
|
||||
@ -245,7 +338,7 @@ extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemT
|
||||
continue;
|
||||
}
|
||||
printf(
|
||||
"Entry %d: type: %d, physicalStart: 0x%lX, numberOfPages: %ld\n",
|
||||
"Entry %d: type=%d, physicalStart=0x%lX, numberOfPages=%ld\n",
|
||||
entry,
|
||||
static_cast<int>(descriptor.Type),
|
||||
static_cast<unsigned long>(descriptor.PhysicalStart),
|
||||
@ -259,7 +352,7 @@ extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemT
|
||||
#undef DUMP_MEMORY_MAP
|
||||
#endif // defined(DUMP_MEMORY_MAP)
|
||||
|
||||
status = gBootServices->ExitBootServices(imageHandle, memoryMap->mapKey);
|
||||
status = gBootServices->ExitBootServices(imageHandle, bootInfo->memoryMap.mapKey);
|
||||
DIE_ON_ERROR("Error exiting EFI boot services.");
|
||||
|
||||
// up up and away!
|
||||
@ -267,7 +360,7 @@ extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemT
|
||||
(
|
||||
"jmp %0"
|
||||
:
|
||||
: "a"(header.entry), "b"(memoryMap)
|
||||
: "a"(header.entry), "b"(bootInfo)
|
||||
);
|
||||
|
||||
// we should never get here
|
||||
|
Loading…
x
Reference in New Issue
Block a user