|
|
|
|
@@ -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
|
|
|
|
|
|