mirror of
https://github.com/justinian/jsix.git
synced 2025-12-09 16:04:32 -08:00
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:
7
Makefile
7
Makefile
@@ -8,6 +8,7 @@ VERSION ?= $(shell git describe --dirty --always)
|
||||
GITSHA ?= $(shell git rev-parse --short HEAD)
|
||||
|
||||
KERNEL_FILENAME:= popcorn.bin
|
||||
KERNEL_FONT := assets/fonts/tamsyn10x20r.psf
|
||||
|
||||
MODULES := main
|
||||
|
||||
@@ -183,7 +184,10 @@ $(BUILD_D)/arch/%.c.o: $(ARCH_D)/%.c $(INIT_DEP)
|
||||
$(BUILD_D)/flash.img: $(OVMF)
|
||||
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))
|
||||
dd if=/dev/zero of=$@.tmp bs=512 count=93750
|
||||
$(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
|
||||
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)/screenfont.psf ::screenfont.psf
|
||||
mlabel -i $(TEMPFILE) ::Popcorn_OS
|
||||
dd if=$(TEMPFILE) of=$@.tmp bs=512 count=91669 seek=2048 conv=notrunc
|
||||
rm $(TEMPFILE)
|
||||
|
||||
BIN
assets/fonts/tamsyn10x20r.psf
Normal file
BIN
assets/fonts/tamsyn10x20r.psf
Normal file
Binary file not shown.
@@ -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'};
|
||||
|
||||
EFI_STATUS
|
||||
con_initialize(EFI_SYSTEM_TABLE *system_table, const CHAR16 *version)
|
||||
con_pick_mode(EFI_BOOT_SERVICES *bootsvc)
|
||||
{
|
||||
EFI_STATUS status;
|
||||
|
||||
EFI_BOOT_SERVICES *bootsvc = system_table->BootServices;
|
||||
con_out = system_table->ConOut;
|
||||
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL *gfx_out_proto;
|
||||
status = bootsvc->LocateProtocol(&guid_gfx_out, NULL, (void **)&gfx_out_proto);
|
||||
CHECK_EFI_STATUS_OR_RETURN(status, "LocateProtocol gfx");
|
||||
|
||||
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;
|
||||
|
||||
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) {
|
||||
UINTN size = 0;
|
||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info = NULL;
|
||||
size_t size = 0;
|
||||
status = gfx_out_proto->QueryMode(gfx_out_proto, i, &size, &info);
|
||||
CHECK_EFI_STATUS_OR_RETURN(status, "QueryMode");
|
||||
|
||||
@@ -42,8 +41,9 @@ con_initialize(EFI_SYSTEM_TABLE *system_table, const CHAR16 *version)
|
||||
#endif
|
||||
|
||||
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;
|
||||
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);
|
||||
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);
|
||||
CHECK_EFI_STATUS_OR_RETURN(status, "QueryMode");
|
||||
@@ -70,14 +85,6 @@ con_initialize(EFI_SYSTEM_TABLE *system_table, const CHAR16 *version)
|
||||
return status;
|
||||
}
|
||||
|
||||
size_t
|
||||
con_wstrlen(const CHAR16 *s)
|
||||
{
|
||||
size_t count = 0;
|
||||
while (s && *s++) count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
size_t
|
||||
con_print_hex(uint32_t n)
|
||||
{
|
||||
@@ -178,7 +185,7 @@ con_printf(const CHAR16 *fmt, ...)
|
||||
case L's':
|
||||
{
|
||||
CHAR16 *s = va_arg(args, CHAR16*);
|
||||
count += con_wstrlen(s);
|
||||
count += wstrlen(s);
|
||||
con_out->OutputString(con_out, s);
|
||||
}
|
||||
break;
|
||||
@@ -244,3 +251,58 @@ con_status_fail(const CHAR16 *error)
|
||||
con_out->SetAttribute(con_out, EFI_LIGHTGRAY);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -7,3 +7,14 @@ void con_status_begin(const CHAR16 *message);
|
||||
void con_status_ok();
|
||||
void con_status_fail(const CHAR16 *error);
|
||||
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);
|
||||
|
||||
@@ -1,97 +1,147 @@
|
||||
#include "guids.h"
|
||||
#include "loader.h"
|
||||
#include "memory.h"
|
||||
#include "utility.h"
|
||||
|
||||
#define PAGE_SIZE 0x1000
|
||||
|
||||
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
|
||||
loader_load_kernel(
|
||||
EFI_BOOT_SERVICES *bootsvc,
|
||||
void **kernel_image,
|
||||
uint64_t *kernel_length,
|
||||
void **kernel_data,
|
||||
uint64_t *data_length)
|
||||
struct loader_data *data)
|
||||
{
|
||||
if (kernel_image == 0 || kernel_length == 0)
|
||||
CHECK_EFI_STATUS_OR_RETURN(EFI_INVALID_PARAMETER, "NULL kernel_image or length pointer");
|
||||
|
||||
if (kernel_data == 0 || data_length == 0)
|
||||
CHECK_EFI_STATUS_OR_RETURN(EFI_INVALID_PARAMETER, "NULL kernel_data or length pointer");
|
||||
if (data == NULL)
|
||||
CHECK_EFI_STATUS_OR_RETURN(EFI_INVALID_PARAMETER, L"NULL loader_data");
|
||||
|
||||
EFI_STATUS status;
|
||||
EFI_HANDLE *handles = NULL;
|
||||
UINTN handleCount = 0;
|
||||
size_t handleCount = 0;
|
||||
|
||||
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) {
|
||||
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fileSystem = NULL;
|
||||
|
||||
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;
|
||||
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;
|
||||
status = root->Open(root, &file, kernel_name, EFI_FILE_MODE_READ,
|
||||
EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);
|
||||
void *next = NULL;
|
||||
|
||||
if (!EFI_ERROR(status)) {
|
||||
void *buffer = NULL;
|
||||
UINTN buffer_size = sizeof(EFI_FILE_INFO) + sizeof(kernel_name);
|
||||
data->kernel_image = (void *)KERNEL_PHYS_ADDRESS;
|
||||
status = loader_load_file(
|
||||
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, "Allocating kernel file info memory");
|
||||
CHECK_EFI_STATUS_OR_RETURN(status, L"loader_load_file: %s", kernel_name);
|
||||
|
||||
status = file->GetInfo(file, &guid_file_info, &buffer_size, buffer);
|
||||
CHECK_EFI_STATUS_OR_RETURN(status, "Getting kernel file info");
|
||||
data->screen_font = next;
|
||||
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);
|
||||
CHECK_EFI_STATUS_OR_RETURN(status, "Freeing kernel file info memory");
|
||||
data->kernel_data = next;
|
||||
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;
|
||||
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_SUCCESS;
|
||||
}
|
||||
|
||||
return EFI_NOT_FOUND;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include <efi.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef KERNEL_PHYS_ADDRESS
|
||||
#define KERNEL_PHYS_ADDRESS 0x100000
|
||||
@@ -13,8 +14,12 @@
|
||||
#define KERNEL_MEMTYPE 0x80000000
|
||||
#endif
|
||||
|
||||
#ifndef KERNEL_FONT_MEMTYPE
|
||||
#define KERNEL_FONT_MEMTYPE 0x80000001
|
||||
#endif
|
||||
|
||||
#ifndef KERNEL_DATA_MEMTYPE
|
||||
#define KERNEL_DATA_MEMTYPE 0x80000001
|
||||
#define KERNEL_DATA_MEMTYPE 0x80000002
|
||||
#endif
|
||||
|
||||
#ifndef KERNEL_DATA_PAGES
|
||||
@@ -25,9 +30,19 @@
|
||||
#define KERNEL_FILENAME L"kernel.bin"
|
||||
#endif
|
||||
|
||||
EFI_STATUS loader_load_kernel(
|
||||
EFI_BOOT_SERVICES *bootsvc,
|
||||
void **kernel_image,
|
||||
uint64_t *kernel_length,
|
||||
void **kernel_data,
|
||||
uint64_t *data_length);
|
||||
#ifndef KERNEL_FONT
|
||||
#define KERNEL_FONT L"screenfont.psf"
|
||||
#endif
|
||||
|
||||
struct loader_data {
|
||||
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);
|
||||
|
||||
@@ -39,13 +39,28 @@ struct popcorn_data {
|
||||
uint16_t version;
|
||||
uint16_t length;
|
||||
|
||||
uint16_t data_pages;
|
||||
uint16_t _reserverd;
|
||||
uint32_t _reserved0;
|
||||
uint32_t flags;
|
||||
|
||||
void *font;
|
||||
size_t font_length;
|
||||
|
||||
void *data;
|
||||
size_t data_length;
|
||||
|
||||
EFI_MEMORY_DESCRIPTOR *memory_map;
|
||||
EFI_RUNTIME_SERVICES *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(_Alignof(EFI_MEMORY_DESCRIPTOR))));
|
||||
#pragma pack(pop)
|
||||
@@ -95,13 +110,16 @@ efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
|
||||
uint64_t kernel_length = 0;
|
||||
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);
|
||||
|
||||
con_printf(L" %u bytes at 0x%x\r\n", kernel_length, kernel_image);
|
||||
con_printf(L" %u data bytes at 0x%x\r\n", data_length, kernel_data);
|
||||
con_printf(L" %u image bytes at 0x%x\r\n", load.kernel_image_length, load.kernel_image);
|
||||
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) {
|
||||
con_printf(L" bad magic %x\r\n", version->magic);
|
||||
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
|
||||
//
|
||||
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->version = DATA_HEADER_VERSION;
|
||||
data_header->length = sizeof(struct popcorn_data);
|
||||
data_header->data_pages = data_length / 0x1000;
|
||||
data_header->_reserverd = 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->runtime = system_table->RuntimeServices;
|
||||
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.
|
||||
//
|
||||
struct memory_map 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);
|
||||
CHECK_EFI_STATUS_OR_FAIL(status);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <efi.h>
|
||||
#include "utility.h"
|
||||
|
||||
struct error_code_desc {
|
||||
EFI_STATUS code;
|
||||
@@ -60,3 +60,12 @@ util_error_message(EFI_STATUS status)
|
||||
else
|
||||
return L"Unknown Warning";
|
||||
}
|
||||
|
||||
size_t
|
||||
wstrlen(const CHAR16 *s)
|
||||
{
|
||||
size_t count = 0;
|
||||
while (s && *s++) count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
#include "console.h"
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define UNUSED __attribute__((unused))
|
||||
|
||||
size_t wstrlen(const CHAR16 *s);
|
||||
const CHAR16 *util_error_message(EFI_STATUS status);
|
||||
|
||||
#define CHECK_EFI_STATUS_OR_RETURN(s, msg, ...) \
|
||||
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); \
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,46 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user