Add the beginning of support for kernel graphics to bootloader.

* Load a font file off disk to pass to kernel
* Expose a framebuffer to the kernel
* Currently the kernel just paints the screen red
This commit is contained in:
Justin C. Miller
2018-04-01 22:48:46 -07:00
parent 23365b39c7
commit 4577c2d10c
10 changed files with 338 additions and 104 deletions

View File

@@ -8,6 +8,7 @@ VERSION ?= $(shell git describe --dirty --always)
GITSHA ?= $(shell git rev-parse --short HEAD) GITSHA ?= $(shell git rev-parse --short HEAD)
KERNEL_FILENAME:= popcorn.bin KERNEL_FILENAME:= popcorn.bin
KERNEL_FONT := assets/fonts/tamsyn10x20r.psf
MODULES := main MODULES := main
@@ -183,7 +184,10 @@ $(BUILD_D)/arch/%.c.o: $(ARCH_D)/%.c $(INIT_DEP)
$(BUILD_D)/flash.img: $(OVMF) $(BUILD_D)/flash.img: $(OVMF)
cp $^ $@ cp $^ $@
$(BUILD_D)/fs.img: $(BUILD_D)/boot.efi $(BUILD_D)/kernel.bin $(BUILD_D)/screenfont.psf: $(KERNEL_FONT)
cp $^ $@
$(BUILD_D)/fs.img: $(BUILD_D)/boot.efi $(BUILD_D)/kernel.bin $(BUILD_D)/screenfont.psf
$(eval TEMPFILE := $(shell mktemp --suffix=.img)) $(eval TEMPFILE := $(shell mktemp --suffix=.img))
dd if=/dev/zero of=$@.tmp bs=512 count=93750 dd if=/dev/zero of=$@.tmp bs=512 count=93750
$(PARTED) $@.tmp -s -a minimal mklabel gpt $(PARTED) $@.tmp -s -a minimal mklabel gpt
@@ -195,6 +199,7 @@ $(BUILD_D)/fs.img: $(BUILD_D)/boot.efi $(BUILD_D)/kernel.bin
mmd -i $(TEMPFILE) ::/EFI/BOOT mmd -i $(TEMPFILE) ::/EFI/BOOT
mcopy -i $(TEMPFILE) $(BUILD_D)/boot.efi ::/EFI/BOOT/BOOTX64.efi mcopy -i $(TEMPFILE) $(BUILD_D)/boot.efi ::/EFI/BOOT/BOOTX64.efi
mcopy -i $(TEMPFILE) $(BUILD_D)/kernel.bin ::$(KERNEL_FILENAME) mcopy -i $(TEMPFILE) $(BUILD_D)/kernel.bin ::$(KERNEL_FILENAME)
mcopy -i $(TEMPFILE) $(BUILD_D)/screenfont.psf ::screenfont.psf
mlabel -i $(TEMPFILE) ::Popcorn_OS mlabel -i $(TEMPFILE) ::Popcorn_OS
dd if=$(TEMPFILE) of=$@.tmp bs=512 count=91669 seek=2048 conv=notrunc dd if=$(TEMPFILE) of=$@.tmp bs=512 count=91669 seek=2048 conv=notrunc
rm $(TEMPFILE) rm $(TEMPFILE)

Binary file not shown.

View File

@@ -15,25 +15,24 @@ static EFI_SIMPLE_TEXT_OUT_PROTOCOL *con_out = 0;
const CHAR16 digits[] = {u'0', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'a', u'b', u'c', u'd', u'e', u'f'}; const CHAR16 digits[] = {u'0', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'a', u'b', u'c', u'd', u'e', u'f'};
EFI_STATUS EFI_STATUS
con_initialize(EFI_SYSTEM_TABLE *system_table, const CHAR16 *version) con_pick_mode(EFI_BOOT_SERVICES *bootsvc)
{ {
EFI_STATUS status; EFI_STATUS status;
EFI_BOOT_SERVICES *bootsvc = system_table->BootServices;
con_out = system_table->ConOut;
EFI_GRAPHICS_OUTPUT_PROTOCOL *gfx_out_proto; EFI_GRAPHICS_OUTPUT_PROTOCOL *gfx_out_proto;
status = bootsvc->LocateProtocol(&guid_gfx_out, NULL, (void **)&gfx_out_proto); status = bootsvc->LocateProtocol(&guid_gfx_out, NULL, (void **)&gfx_out_proto);
CHECK_EFI_STATUS_OR_RETURN(status, "LocateProtocol gfx"); CHECK_EFI_STATUS_OR_RETURN(status, "LocateProtocol gfx");
const uint32_t modes = gfx_out_proto->Mode->MaxMode; const uint32_t modes = gfx_out_proto->Mode->MaxMode;
uint32_t res = gfx_out_proto->Mode->Info->HorizontalResolution *
gfx_out_proto->Mode->Info->VerticalResolution;
uint32_t best = gfx_out_proto->Mode->Mode; uint32_t best = gfx_out_proto->Mode->Mode;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info =
(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *)gfx_out_proto->Mode;
uint32_t res = info->HorizontalResolution * info->VerticalResolution;
int is_fb = info->PixelFormat != PixelBltOnly;
for (uint32_t i = 0; i < modes; ++i) { for (uint32_t i = 0; i < modes; ++i) {
UINTN size = 0; size_t size = 0;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info = NULL;
status = gfx_out_proto->QueryMode(gfx_out_proto, i, &size, &info); status = gfx_out_proto->QueryMode(gfx_out_proto, i, &size, &info);
CHECK_EFI_STATUS_OR_RETURN(status, "QueryMode"); CHECK_EFI_STATUS_OR_RETURN(status, "QueryMode");
@@ -42,8 +41,9 @@ con_initialize(EFI_SYSTEM_TABLE *system_table, const CHAR16 *version)
#endif #endif
const uint32_t new_res = info->HorizontalResolution * info->VerticalResolution; const uint32_t new_res = info->HorizontalResolution * info->VerticalResolution;
const int new_is_fb = info->PixelFormat == PixelBltOnly;
if (new_res > res) { if (new_is_fb > is_fb && new_res >= res) {
best = i; best = i;
res = new_res; res = new_res;
} }
@@ -51,6 +51,21 @@ con_initialize(EFI_SYSTEM_TABLE *system_table, const CHAR16 *version)
status = gfx_out_proto->SetMode(gfx_out_proto, best); status = gfx_out_proto->SetMode(gfx_out_proto, best);
CHECK_EFI_STATUS_OR_RETURN(status, "SetMode %d/%d", best, modes); CHECK_EFI_STATUS_OR_RETURN(status, "SetMode %d/%d", best, modes);
return EFI_SUCCESS;
}
EFI_STATUS
con_initialize(EFI_SYSTEM_TABLE *system_table, const CHAR16 *version)
{
EFI_STATUS status;
EFI_BOOT_SERVICES *bootsvc = system_table->BootServices;
con_out = system_table->ConOut;
// Might not find a video device at all, so ignore not found errors
status = con_pick_mode(bootsvc);
if (status != EFI_NOT_FOUND)
CHECK_EFI_STATUS_OR_RETURN(status, "con_pick_mode");
status = con_out->QueryMode(con_out, con_out->Mode->Mode, &COLS, &ROWS); status = con_out->QueryMode(con_out, con_out->Mode->Mode, &COLS, &ROWS);
CHECK_EFI_STATUS_OR_RETURN(status, "QueryMode"); CHECK_EFI_STATUS_OR_RETURN(status, "QueryMode");
@@ -70,14 +85,6 @@ con_initialize(EFI_SYSTEM_TABLE *system_table, const CHAR16 *version)
return status; return status;
} }
size_t
con_wstrlen(const CHAR16 *s)
{
size_t count = 0;
while (s && *s++) count++;
return count;
}
size_t size_t
con_print_hex(uint32_t n) con_print_hex(uint32_t n)
{ {
@@ -178,7 +185,7 @@ con_printf(const CHAR16 *fmt, ...)
case L's': case L's':
{ {
CHAR16 *s = va_arg(args, CHAR16*); CHAR16 *s = va_arg(args, CHAR16*);
count += con_wstrlen(s); count += wstrlen(s);
con_out->OutputString(con_out, s); con_out->OutputString(con_out, s);
} }
break; break;
@@ -244,3 +251,58 @@ con_status_fail(const CHAR16 *error)
con_out->SetAttribute(con_out, EFI_LIGHTGRAY); con_out->SetAttribute(con_out, EFI_LIGHTGRAY);
con_out->OutputString(con_out, (CHAR16 *)L"\r\n"); con_out->OutputString(con_out, (CHAR16 *)L"\r\n");
} }
EFI_STATUS
con_get_framebuffer(
EFI_BOOT_SERVICES *bootsvc,
void **buffer,
size_t *buffer_size,
uint32_t *hres,
uint32_t *vres,
uint32_t *rmask,
uint32_t *gmask,
uint32_t *bmask)
{
EFI_STATUS status;
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
status = bootsvc->LocateProtocol(&guid_gfx_out, NULL, (void **)&gop);
if (status != EFI_NOT_FOUND) {
CHECK_EFI_STATUS_OR_RETURN(status, "LocateProtocol gfx");
*buffer = (void *)gop->Mode->FrameBufferBase;
*buffer_size = gop->Mode->FrameBufferSize;
*hres = gop->Mode->Info->HorizontalResolution;
*vres = gop->Mode->Info->VerticalResolution;
switch (gop->Mode->Info->PixelFormat) {
case PixelRedGreenBlueReserved8BitPerColor:
*rmask = 0x0000ff;
*gmask = 0x00ff00;
*bmask = 0xff0000;
return EFI_SUCCESS;
case PixelBlueGreenRedReserved8BitPerColor:
*bmask = 0x0000ff;
*gmask = 0x00ff00;
*rmask = 0xff0000;
return EFI_SUCCESS;
case PixelBitMask:
*rmask = gop->Mode->Info->PixelInformation.RedMask;
*gmask = gop->Mode->Info->PixelInformation.GreenMask;
*bmask = gop->Mode->Info->PixelInformation.BlueMask;
return EFI_SUCCESS;
default:
// Not a framebuffer, fall through to zeroing out
// values below.
break;
}
}
*buffer = NULL;
*buffer_size = *hres = *vres = 0;
*rmask = *gmask = *bmask = 0;
return EFI_SUCCESS;
}

View File

@@ -7,3 +7,14 @@ void con_status_begin(const CHAR16 *message);
void con_status_ok(); void con_status_ok();
void con_status_fail(const CHAR16 *error); void con_status_fail(const CHAR16 *error);
size_t con_printf(const CHAR16 *fmt, ...); size_t con_printf(const CHAR16 *fmt, ...);
EFI_STATUS
con_get_framebuffer(
EFI_BOOT_SERVICES *bootsvc,
void **buffer,
size_t *buffer_size,
uint32_t *hres,
uint32_t *vres,
uint32_t *rmask,
uint32_t *gmask,
uint32_t *bmask);

View File

@@ -1,97 +1,147 @@
#include "guids.h" #include "guids.h"
#include "loader.h" #include "loader.h"
#include "memory.h"
#include "utility.h" #include "utility.h"
#define PAGE_SIZE 0x1000
static CHAR16 kernel_name[] = KERNEL_FILENAME; static CHAR16 kernel_name[] = KERNEL_FILENAME;
static CHAR16 font_name[] = KERNEL_FONT;
EFI_STATUS
loader_alloc_pages(
EFI_BOOT_SERVICES *bootsvc,
EFI_MEMORY_TYPE mem_type,
size_t *length,
void **pages,
void **next)
{
EFI_STATUS status;
size_t page_count = ((*length - 1) / PAGE_SIZE) + 1;
EFI_PHYSICAL_ADDRESS addr = (EFI_PHYSICAL_ADDRESS)*pages;
status = bootsvc->AllocatePages(AllocateAddress, mem_type, page_count, &addr);
if (status == EFI_NOT_FOUND || status == EFI_OUT_OF_RESOURCES) {
// couldn't get the address we wanted, try loading the kernel anywhere
status =
bootsvc->AllocatePages(AllocateAnyPages, mem_type, page_count, &addr);
}
CHECK_EFI_STATUS_OR_RETURN(status, L"Allocating kernel pages type %x", mem_type);
*length = page_count * PAGE_SIZE;
*pages = (void *)addr;
*next = (void*)(addr + *length);
return EFI_SUCCESS;
}
EFI_STATUS
loader_load_file(
EFI_BOOT_SERVICES *bootsvc,
EFI_FILE_PROTOCOL *root,
const CHAR16 *filename,
EFI_MEMORY_TYPE mem_type,
void **data,
size_t *length,
void **next)
{
EFI_STATUS status;
EFI_FILE_PROTOCOL *file = NULL;
status = root->Open(root, &file, (CHAR16 *)filename, EFI_FILE_MODE_READ,
EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);
if (status == EFI_NOT_FOUND)
return status;
CHECK_EFI_STATUS_OR_RETURN(status, L"Opening file %s", filename);
char info[sizeof(EFI_FILE_INFO) + 100];
size_t info_length = sizeof(info);
status = file->GetInfo(file, &guid_file_info, &info_length, info);
CHECK_EFI_STATUS_OR_RETURN(status, L"Getting file info");
*length = ((EFI_FILE_INFO *)info)->FileSize;
status = loader_alloc_pages(bootsvc, mem_type, length, data, next);
CHECK_EFI_STATUS_OR_RETURN(status, L"Allocating pages");
status = file->Read(file, length, *data);
CHECK_EFI_STATUS_OR_RETURN(status, L"Reading file");
status = file->Close(file);
CHECK_EFI_STATUS_OR_RETURN(status, L"Closing file handle");
return EFI_SUCCESS;
}
EFI_STATUS EFI_STATUS
loader_load_kernel( loader_load_kernel(
EFI_BOOT_SERVICES *bootsvc, EFI_BOOT_SERVICES *bootsvc,
void **kernel_image, struct loader_data *data)
uint64_t *kernel_length,
void **kernel_data,
uint64_t *data_length)
{ {
if (kernel_image == 0 || kernel_length == 0) if (data == NULL)
CHECK_EFI_STATUS_OR_RETURN(EFI_INVALID_PARAMETER, "NULL kernel_image or length pointer"); CHECK_EFI_STATUS_OR_RETURN(EFI_INVALID_PARAMETER, L"NULL loader_data");
if (kernel_data == 0 || data_length == 0)
CHECK_EFI_STATUS_OR_RETURN(EFI_INVALID_PARAMETER, "NULL kernel_data or length pointer");
EFI_STATUS status; EFI_STATUS status;
EFI_HANDLE *handles = NULL; EFI_HANDLE *handles = NULL;
UINTN handleCount = 0; size_t handleCount = 0;
status = bootsvc->LocateHandleBuffer(ByProtocol, &guid_simple_filesystem, NULL, &handleCount, &handles); status = bootsvc->LocateHandleBuffer(ByProtocol, &guid_simple_filesystem, NULL, &handleCount, &handles);
CHECK_EFI_STATUS_OR_RETURN(status, "LocateHandleBuffer"); CHECK_EFI_STATUS_OR_RETURN(status, L"LocateHandleBuffer");
for (unsigned i = 0; i < handleCount; ++i) { for (unsigned i = 0; i < handleCount; ++i) {
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fileSystem = NULL; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fileSystem = NULL;
status = bootsvc->HandleProtocol(handles[i], &guid_simple_filesystem, (void **)&fileSystem); status = bootsvc->HandleProtocol(handles[i], &guid_simple_filesystem, (void **)&fileSystem);
CHECK_EFI_STATUS_OR_RETURN(status, "HandleProtocol"); CHECK_EFI_STATUS_OR_RETURN(status, L"HandleProtocol");
EFI_FILE_PROTOCOL *root = NULL; EFI_FILE_PROTOCOL *root = NULL;
status = fileSystem->OpenVolume(fileSystem, &root); status = fileSystem->OpenVolume(fileSystem, &root);
CHECK_EFI_STATUS_OR_RETURN(status, "OpenVolume"); CHECK_EFI_STATUS_OR_RETURN(status, L"OpenVolume");
EFI_FILE_PROTOCOL *file = NULL; void *next = NULL;
status = root->Open(root, &file, kernel_name, EFI_FILE_MODE_READ,
EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);
if (!EFI_ERROR(status)) { data->kernel_image = (void *)KERNEL_PHYS_ADDRESS;
void *buffer = NULL; status = loader_load_file(
UINTN buffer_size = sizeof(EFI_FILE_INFO) + sizeof(kernel_name); bootsvc,
root,
kernel_name,
KERNEL_MEMTYPE,
&data->kernel_image,
&data->kernel_image_length,
&next);
if (status == EFI_NOT_FOUND)
continue;
status = bootsvc->AllocatePool(EfiLoaderCode, buffer_size, &buffer); CHECK_EFI_STATUS_OR_RETURN(status, L"loader_load_file: %s", kernel_name);
CHECK_EFI_STATUS_OR_RETURN(status, "Allocating kernel file info memory");
status = file->GetInfo(file, &guid_file_info, &buffer_size, buffer); data->screen_font = next;
CHECK_EFI_STATUS_OR_RETURN(status, "Getting kernel file info"); status = loader_load_file(
bootsvc,
root,
font_name,
KERNEL_FONT_MEMTYPE,
&data->screen_font,
&data->screen_font_length,
&next);
buffer_size = ((EFI_FILE_INFO *)buffer)->FileSize; CHECK_EFI_STATUS_OR_RETURN(status, L"loader_load_file: %s", font_name);
status = bootsvc->FreePool(buffer); data->kernel_data = next;
CHECK_EFI_STATUS_OR_RETURN(status, "Freeing kernel file info memory"); data->kernel_data_length += PAGE_SIZE; // extra page for map growth
status = loader_alloc_pages(
bootsvc,
KERNEL_DATA_MEMTYPE,
&data->kernel_data_length,
&data->kernel_data,
&next);
CHECK_EFI_STATUS_OR_RETURN(status, L"loader_alloc_pages: kernel data");
UINTN page_count = ((buffer_size - 1) / 0x1000) + 1; return EFI_SUCCESS;
EFI_PHYSICAL_ADDRESS addr = KERNEL_PHYS_ADDRESS;
EFI_MEMORY_TYPE mem_type = KERNEL_MEMTYPE; // Special value to tell the kernel it's here
status = bootsvc->AllocatePages(AllocateAddress, mem_type, page_count, &addr);
if (status == EFI_NOT_FOUND) {
// couldn't get the address we wanted, try loading the kernel anywhere
status =
bootsvc->AllocatePages(AllocateAnyPages, mem_type, page_count, &addr);
}
CHECK_EFI_STATUS_OR_RETURN(status, "Allocating kernel pages");
buffer = (void *)addr;
status = file->Read(file, &buffer_size, buffer);
CHECK_EFI_STATUS_OR_RETURN(status, "Reading kernel file");
status = file->Close(file);
CHECK_EFI_STATUS_OR_RETURN(status, "Closing kernel file handle");
*kernel_length = buffer_size;
*kernel_image = buffer;
addr += page_count * 0x1000; // Get the next page after the kernel pages
mem_type = KERNEL_DATA_MEMTYPE; // Special value for kernel data
page_count = ((*data_length - 1) / 0x1000) + 1;
status = bootsvc->AllocatePages(AllocateAddress, mem_type, page_count, &addr);
if (status == EFI_NOT_FOUND) {
// couldn't get the address we wanted, try loading anywhere
status =
bootsvc->AllocatePages(AllocateAnyPages, mem_type, page_count, &addr);
}
CHECK_EFI_STATUS_OR_RETURN(status, "Allocating kernel data pages");
*data_length = page_count * 0x1000;
*kernel_data = (void *)addr;
bootsvc->SetMem(*kernel_data, *data_length, 0);
return EFI_SUCCESS;
}
} }
return EFI_NOT_FOUND; return EFI_NOT_FOUND;

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <efi.h> #include <efi.h>
#include <stddef.h>
#ifndef KERNEL_PHYS_ADDRESS #ifndef KERNEL_PHYS_ADDRESS
#define KERNEL_PHYS_ADDRESS 0x100000 #define KERNEL_PHYS_ADDRESS 0x100000
@@ -13,8 +14,12 @@
#define KERNEL_MEMTYPE 0x80000000 #define KERNEL_MEMTYPE 0x80000000
#endif #endif
#ifndef KERNEL_FONT_MEMTYPE
#define KERNEL_FONT_MEMTYPE 0x80000001
#endif
#ifndef KERNEL_DATA_MEMTYPE #ifndef KERNEL_DATA_MEMTYPE
#define KERNEL_DATA_MEMTYPE 0x80000001 #define KERNEL_DATA_MEMTYPE 0x80000002
#endif #endif
#ifndef KERNEL_DATA_PAGES #ifndef KERNEL_DATA_PAGES
@@ -25,9 +30,19 @@
#define KERNEL_FILENAME L"kernel.bin" #define KERNEL_FILENAME L"kernel.bin"
#endif #endif
EFI_STATUS loader_load_kernel( #ifndef KERNEL_FONT
EFI_BOOT_SERVICES *bootsvc, #define KERNEL_FONT L"screenfont.psf"
void **kernel_image, #endif
uint64_t *kernel_length,
void **kernel_data, struct loader_data {
uint64_t *data_length); void *kernel_image;
size_t kernel_image_length;
void *kernel_data;
size_t kernel_data_length;
void *screen_font;
size_t screen_font_length;
};
EFI_STATUS loader_load_kernel(EFI_BOOT_SERVICES *bootsvc, struct loader_data *data);

View File

@@ -39,13 +39,28 @@ struct popcorn_data {
uint16_t version; uint16_t version;
uint16_t length; uint16_t length;
uint16_t data_pages; uint32_t _reserved0;
uint16_t _reserverd;
uint32_t flags; uint32_t flags;
void *font;
size_t font_length;
void *data;
size_t data_length;
EFI_MEMORY_DESCRIPTOR *memory_map; EFI_MEMORY_DESCRIPTOR *memory_map;
EFI_RUNTIME_SERVICES *runtime; EFI_RUNTIME_SERVICES *runtime;
void *acpi_table; void *acpi_table;
void *frame_buffer;
size_t frame_buffer_size;
uint32_t hres;
uint32_t vres;
uint32_t rmask;
uint32_t gmask;
uint32_t bmask;
uint32_t _reserved1;
} }
__attribute__((aligned(_Alignof(EFI_MEMORY_DESCRIPTOR)))); __attribute__((aligned(_Alignof(EFI_MEMORY_DESCRIPTOR))));
#pragma pack(pop) #pragma pack(pop)
@@ -95,13 +110,16 @@ efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
uint64_t kernel_length = 0; uint64_t kernel_length = 0;
con_printf(L"Loading kernel into memory...\r\n"); con_printf(L"Loading kernel into memory...\r\n");
status = loader_load_kernel(bootsvc, &kernel_image, &kernel_length, &kernel_data, &data_length); struct loader_data load;
load.kernel_data_length = data_length;
status = loader_load_kernel(bootsvc, &load);
CHECK_EFI_STATUS_OR_FAIL(status); CHECK_EFI_STATUS_OR_FAIL(status);
con_printf(L" %u bytes at 0x%x\r\n", kernel_length, kernel_image); con_printf(L" %u image bytes at 0x%x\r\n", load.kernel_image_length, load.kernel_image);
con_printf(L" %u data bytes at 0x%x\r\n", data_length, kernel_data); con_printf(L" %u font bytes at 0x%x\r\n", load.screen_font_length, load.screen_font);
con_printf(L" %u data bytes at 0x%x\r\n", load.kernel_data_length, load.kernel_data);
struct kernel_header *version = (struct kernel_header *)kernel_image; struct kernel_header *version = (struct kernel_header *)load.kernel_image;
if (version->magic != KERNEL_HEADER_MAGIC) { if (version->magic != KERNEL_HEADER_MAGIC) {
con_printf(L" bad magic %x\r\n", version->magic); con_printf(L" bad magic %x\r\n", version->magic);
CHECK_EFI_STATUS_OR_FAIL(EFI_CRC_ERROR); CHECK_EFI_STATUS_OR_FAIL(EFI_CRC_ERROR);
@@ -115,22 +133,45 @@ efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
// Set up the kernel data pages to pass to the kernel // Set up the kernel data pages to pass to the kernel
// //
struct popcorn_data *data_header = (struct popcorn_data *)kernel_data; struct popcorn_data *data_header = (struct popcorn_data *)load.kernel_data;
data_header->magic = DATA_HEADER_MAGIC; data_header->magic = DATA_HEADER_MAGIC;
data_header->version = DATA_HEADER_VERSION; data_header->version = DATA_HEADER_VERSION;
data_header->length = sizeof(struct popcorn_data); data_header->length = sizeof(struct popcorn_data);
data_header->data_pages = data_length / 0x1000;
data_header->_reserverd = 0;
data_header->flags = 0; data_header->flags = 0;
data_header->font = load.screen_font;
data_header->font_length = load.screen_font_length;
data_header->data = load.screen_font;
data_header->data_length = load.screen_font_length;
data_header->memory_map = (EFI_MEMORY_DESCRIPTOR *)(data_header + 1); data_header->memory_map = (EFI_MEMORY_DESCRIPTOR *)(data_header + 1);
data_header->runtime = system_table->RuntimeServices; data_header->runtime = system_table->RuntimeServices;
data_header->acpi_table = acpi_table; data_header->acpi_table = acpi_table;
data_header->_reserved0 = 0;
data_header->_reserved1 = 0;
// Figure out the framebuffer (if any) and add that to the data header
//
status = con_get_framebuffer(
bootsvc,
&data_header->frame_buffer,
&data_header->frame_buffer_size,
&data_header->hres,
&data_header->vres,
&data_header->rmask,
&data_header->gmask,
&data_header->bmask);
CHECK_EFI_STATUS_OR_FAIL(status);
// Save the memory map and tell the firmware we're taking control. // Save the memory map and tell the firmware we're taking control.
// //
struct memory_map map; struct memory_map map;
map.entries = data_header->memory_map; map.entries = data_header->memory_map;
map.length = (data_length - header_size); map.length = (load.kernel_data_length - header_size);
status = memory_get_map(bootsvc, &map); status = memory_get_map(bootsvc, &map);
CHECK_EFI_STATUS_OR_FAIL(status); CHECK_EFI_STATUS_OR_FAIL(status);

View File

@@ -1,4 +1,4 @@
#include <efi.h> #include "utility.h"
struct error_code_desc { struct error_code_desc {
EFI_STATUS code; EFI_STATUS code;
@@ -60,3 +60,12 @@ util_error_message(EFI_STATUS status)
else else
return L"Unknown Warning"; return L"Unknown Warning";
} }
size_t
wstrlen(const CHAR16 *s)
{
size_t count = 0;
while (s && *s++) count++;
return count;
}

View File

@@ -1,14 +1,16 @@
#include "console.h" #include "console.h"
#include <efi.h> #include <efi.h>
#include <efilib.h> #include <efilib.h>
#include <stddef.h>
#define UNUSED __attribute__((unused)) #define UNUSED __attribute__((unused))
size_t wstrlen(const CHAR16 *s);
const CHAR16 *util_error_message(EFI_STATUS status); const CHAR16 *util_error_message(EFI_STATUS status);
#define CHECK_EFI_STATUS_OR_RETURN(s, msg, ...) \ #define CHECK_EFI_STATUS_OR_RETURN(s, msg, ...) \
if (EFI_ERROR((s))) { \ if (EFI_ERROR((s))) { \
con_printf(L"EFI_ERROR: " msg L": %s\n", ##__VA_ARGS__, util_error_message(s)); \ con_printf(L"ERROR: " msg L": %s\r\n", ##__VA_ARGS__, util_error_message(s)); \
return (s); \ return (s); \
} }

View File

@@ -1,7 +1,46 @@
#include <stddef.h>
#include <stdint.h>
void do_the_set_registers(); void do_the_set_registers();
#pragma pack(push, 1)
struct popcorn_data {
uint32_t magic;
uint16_t version;
uint16_t length;
uint32_t _reserverd0;
uint32_t flags;
void *font;
size_t font_length;
void *data;
size_t data_length;
void *memory_map;
void *runtime;
void *acpi_table;
void *frame_buffer;
size_t frame_buffer_size;
uint32_t hres;
uint32_t vres;
uint32_t rmask;
uint32_t gmask;
uint32_t bmask;
uint32_t _reserved1;
}
__attribute__((aligned(8)));
#pragma pack(pop)
void void
kernel_main(void *header) kernel_main(struct popcorn_data *header)
{ {
uint32_t *p = header->frame_buffer;
uint32_t *end = p + (header->frame_buffer_size / sizeof(uint32_t));
while (p < end) *p++ = header->rmask;
do_the_set_registers(header); do_the_set_registers(header);
} }