boot: merge retooled EFI loader

This commit is contained in:
K. Lange 2021-09-07 11:45:58 +09:00
parent c66f39a563
commit 1a44f8a2f3
11 changed files with 807 additions and 129 deletions

View File

@ -169,6 +169,7 @@ clean:
-rm -f $(LIBC_OBJS) $(BASE)/lib/ld.so $(BASE)/lib/libkuroko.so $(BASE)/lib/libm.so
-rm -f $(BASE)/bin/kuroko
-rm -f $(GCC_SHARED) $(LIBSTDCXX)
-rm -f boot/efi/*.o boot/bios/*.o
libc/%.o: libc/%.c base/usr/include/syscall.h
$(CC) -O2 -std=gnu11 -Wall -Wextra -Wno-unused-parameter -fPIC -c -o $@ $<
@ -214,13 +215,17 @@ $(BASE)/usr/lib:
mkdir -p $@
$(BASE)/usr/bin:
mkdir -p $@
boot/efi:
mkdir -p $@
boot/bios:
mkdir -p $@
fatbase/efi/boot:
mkdir -p $@
cdrom:
mkdir -p $@
.make:
mkdir -p .make
dirs: $(BASE)/dev $(BASE)/tmp $(BASE)/proc $(BASE)/bin $(BASE)/lib $(BASE)/cdrom $(BASE)/usr/lib $(BASE)/usr/bin $(BASE)/lib/kuroko cdrom $(BASE)/var fatbase/efi/boot .make $(BASE)/mod
dirs: $(BASE)/dev $(BASE)/tmp $(BASE)/proc $(BASE)/bin $(BASE)/lib $(BASE)/cdrom $(BASE)/usr/lib $(BASE)/usr/bin $(BASE)/lib/kuroko cdrom $(BASE)/var fatbase/efi/boot .make $(BASE)/mod boot/efi boot/bios
ifeq (,$(findstring clean,$(MAKECMDGOALS)))
-include ${APPS_Y}
@ -274,18 +279,32 @@ fatbase/kernel: misaka-kernel
cp $< $@
strip $@
cdrom/fat.img: fatbase/ramdisk.igz fatbase/kernel util/mkdisk.sh | dirs
cdrom/fat.img: fatbase/ramdisk.igz fatbase/kernel fatbase/efi/boot/bootx64.efi util/mkdisk.sh | dirs
util/mkdisk.sh $@ fatbase
cdrom/boot.sys: boot/boot.o $(patsubst %.c,%.o,$(wildcard boot/*.c)) boot/link.ld | dirs
${LD} -melf_i386 -T boot/link.ld -o $@ boot/boot.o $(patsubst %.c,%.o,$(wildcard boot/*.c))
cdrom/boot.sys: boot/bios/boot.o $(patsubst boot/%.c,boot/bios/%.o,$(wildcard boot/*.c)) boot/link.ld | dirs
${LD} -melf_i386 -T boot/link.ld -o $@ boot/bios/boot.o $(patsubst boot/%.c,boot/bios/%.o,$(wildcard boot/*.c))
boot/%.o: boot/%.c boot/*.h
${CC} -m32 -c -Os -fno-strict-aliasing -finline-functions -ffreestanding -mgeneral-regs-only -o $@ $<
boot/bios/%.o: boot/%.c boot/*.h | dirs
${CC} -m32 -c -Os -fno-pic -fno-pie -fno-strict-aliasing -finline-functions -ffreestanding -mgeneral-regs-only -o $@ $<
boot/boot.o: boot/boot.S
boot/bios/boot.o: boot/boot.S | dirs
${AS} --32 -o $@ $<
EFI_CFLAGS=-fno-stack-protector -fpic -DEFI_PLATFORM -ffreestanding -fshort-wchar -I /usr/include/efi -mno-red-zone
EFI_SECTIONS=-j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .reloc
EFI_LINK=/usr/lib/crt0-efi-x86_64.o -nostdlib -znocombreloc -T /usr/lib/elf_x86_64_efi.lds -shared -Bsymbolic -L /usr/lib -lefi -lgnuefi
boot/efi/%.o: boot/%.c boot/*.h | dirs
$(CC) ${EFI_CFLAGS} -I /usr/include/efi/x86_64 -DEFI_FUNCTION_WRAPPER -c -o $@ $<
boot/efi64.so: $(patsubst boot/%.c,boot/efi/%.o,$(wildcard boot/*.c)) boot/*.h
$(LD) $(patsubst boot/%.c,boot/efi/%.o,$(wildcard boot/*.c)) ${EFI_LINK} -o $@
fatbase/efi/boot/bootx64.efi: boot/efi64.so
mkdir -p fatbase/efi/boot
objcopy ${EFI_SECTIONS} --target=efi-app-x86_64 $< $@
image.iso: cdrom/fat.img cdrom/boot.sys util/update-extents.py
xorriso -as mkisofs -R -J -c bootcat \
-b boot.sys -no-emul-boot -boot-load-size full \

View File

@ -165,8 +165,8 @@ done:
cli
.global kmain
ljmp $0x08,$kmain
.global bios_main
ljmp $0x08,$bios_main
hang:
jmp hang

View File

@ -10,7 +10,12 @@
/* Basic text strings */
#define BASE_VERSION "ToaruOS Bootloader v4.0"
char * VERSION_TEXT = BASE_VERSION " (BIOS)";
char * VERSION_TEXT = BASE_VERSION
#ifdef EFI_PLATFORM
" (EFI)";
#else
" (BIOS)";
#endif
char * HELP_TEXT = "<Enter> to boot, <e> to edit, or select a menu option with \030/\031/\032/\033.";
char * HELP_TEXT_OPT = "<Enter> to toggle, or select another option with \030/\031/\032/\033.";
char * COPYRIGHT_TEXT = "ToaruOS is free software under the NCSA license.";
@ -22,7 +27,6 @@ char * LINK_TEXT = "https://toaruos.org - https://github.com/klange/toaruos";
#define DEFAULT_SINGLE_CMDLINE "start=terminal\037-F "
#define DEFAULT_TEXT_CMDLINE "start=--vga vid=text "
#define DEFAULT_VID_CMDLINE "vid=auto,1440,900 "
#define DEFAULT_PRESET_VID_CMDLINE "vid=preset "
#define MIGRATE_CMDLINE "migrate "
#define DEFAULT_HEADLESS_CMDLINE "start=--headless "
@ -33,18 +37,19 @@ char cmdline[1024] = {0};
/* Names of the available boot modes. */
struct bootmode boot_mode_names[] = {
{1, "normal", "Normal Boot"},
#ifdef EFI_PLATFORM
{2, "video", "Configure Video Output"},
#else
{2, "vga", "VGA Text Mode"},
#endif
{3, "single", "Single-User Graphical Terminal"},
{4, "headless", "Headless"},
};
int base_sel = BASE_SEL;
extern char _bss_start[];
extern char _bss_end[];
int base_sel = 0;
int kmain() {
memset(&_bss_start,0,(uintptr_t)&_bss_end-(uintptr_t)&_bss_start);
BOOT_SET();
BOOT_OPTION(_debug, 0, "Debug output",
"Enable debug output in the bootloader and enable the",
@ -86,6 +91,16 @@ int kmain() {
/* Loop over rendering the menu */
show_menu();
#ifdef EFI_PLATFORM
if (boot_mode == 2) {
extern int video_menu(void);
video_menu();
boot_edit = 0;
memset(cmdline, 0, 1024);
continue;
}
#endif
/* Build our command line. */
strcat(cmdline, DEFAULT_ROOT_CMDLINE);

View File

@ -1,49 +0,0 @@
#include <stddef.h>
#include "iso9660.h"
#include "util.h"
#include "text.h"
iso_9660_volume_descriptor_t * root = NULL;
iso_9660_directory_entry_t * dir_entry = NULL;
static char * dir_entries = NULL;
int navigate(char * name) {
dir_entry = (iso_9660_directory_entry_t*)&root->root;
dir_entries = (char*)(DATA_LOAD_BASE + dir_entry->extent_start_LSB * ISO_SECTOR_SIZE);
long offset = 0;
while (1) {
iso_9660_directory_entry_t * dir = (iso_9660_directory_entry_t *)(dir_entries + offset);
if (dir->length == 0) {
if (offset < dir_entry->extent_length_LSB) {
offset += 1; // this->block_size - ((uintptr_t)offset % this->block_size);
goto try_again;
}
break;
}
if (!(dir->flags & FLAG_HIDDEN)) {
char file_name[dir->name_len + 1];
memcpy(file_name, dir->name, dir->name_len);
file_name[dir->name_len] = 0;
char * s = strchr(file_name,';');
if (s) {
*s = '\0';
}
#if 1
print("Found a file: ");
print(" Name: ");
print(file_name); print("\n");
#endif
if (!strcmp(file_name, name)) {
dir_entry = dir;
return 1;
}
}
offset += dir->length;
try_again:
if ((long)(offset) > dir_entry->extent_length_LSB) break;
}
return 0;
}

View File

@ -1,5 +1,87 @@
#include "kbd.h"
#include "util.h"
#include "text.h"
#ifdef EFI_PLATFORM
#include <efi.h>
extern EFI_SYSTEM_TABLE *ST;
#define KBD_SCAN_DOWN 0x50
#define KBD_SCAN_UP 0x48
#define KBD_SCAN_LEFT 0x4B
#define KBD_SCAN_RIGHT 0x4D
#define KBD_SCAN_ENTER 0x1C
#define KBD_SCAN_1 2
#define KBD_SCAN_9 10
int read_scancode(int timeout) {
EFI_INPUT_KEY Key;
unsigned long int index;
if (timeout) {
EFI_EVENT events[] = {ST->ConIn->WaitForKey, 0};
uefi_call_wrapper(ST->BootServices->CreateEvent, 5, EVT_TIMER, 0, NULL, NULL, &events[1]);
uefi_call_wrapper(ST->BootServices->SetTimer, 3, events[1], TimerRelative, 10000000UL);
uefi_call_wrapper(ST->BootServices->WaitForEvent, 3, 2, events, &index);
} else {
uefi_call_wrapper(ST->BootServices->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &index);
}
EFI_STATUS result = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &Key);
if (result == EFI_NOT_READY) return -1;
switch (Key.ScanCode) {
case 0:
switch (Key.UnicodeChar) {
case L'\r':
return KBD_SCAN_ENTER;
case L'1':
case L'2':
case L'3':
case L'4':
case L'5':
case L'6':
case L'7':
case L'8':
case L'9':
return Key.UnicodeChar - L'1' + KBD_SCAN_1;
case L'e':
return 0x12;
default:
return 0xFF;
}
break;
case 0x01: return KBD_SCAN_UP;
case 0x02: return KBD_SCAN_DOWN;
case 0x03: return KBD_SCAN_RIGHT;
case 0x04: return KBD_SCAN_LEFT;
default:
return 0xFF;
}
}
int read_key(char * c) {
EFI_INPUT_KEY Key;
unsigned long int index;
uefi_call_wrapper(ST->BootServices->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &index);
uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &Key);
if (Key.ScanCode == 0) {
*c = Key.UnicodeChar;
if (*c == '\r') *c = '\n';
return 0;
}
switch (Key.ScanCode) {
case 0x03: return 3;
case 0x04: return 2;
case 0x09: return 4;
case 0x0a: return 5;
case 0x17: *c = 27; return 0;
}
return 1;
}
#else
int read_cmos_seconds(void) {
outportb(0x70,0);
@ -70,3 +152,4 @@ int read_scancode(int timeout) {
}
return out;
}
#endif

View File

@ -42,18 +42,6 @@ void show_menu(void) {
sel_max++;
}
sel_max += base_sel + 1;
outportb(0x3D4, 14);
outportb(0x3D5, 0xFF);
outportb(0x3D4, 15);
outportb(0x3D5, 0xFF);
inportb(0x3DA);
outportb(0x3C0, 0x30);
char b = inportb(0x3C1);
b &= ~8;
outportb(0x3c0, b);
clear_();
do {

View File

@ -7,6 +7,7 @@
#include "elf.h"
#include "options.h"
#include "iso9660.h"
#include "kbd.h"
char * kernel_load_start = 0;
@ -14,7 +15,7 @@ mboot_mod_t modules_mboot[1] = {
{0,0,0,1}
};
struct multiboot multiboot_header = {
static struct multiboot multiboot_header = {
/* flags; */ MULTIBOOT_FLAG_CMDLINE | MULTIBOOT_FLAG_MODS | MULTIBOOT_FLAG_MEM | MULTIBOOT_FLAG_MMAP | MULTIBOOT_FLAG_LOADER,
/* mem_lower; */ 0x100000,
/* mem_upper; */ 0x640000,
@ -43,22 +44,8 @@ struct multiboot multiboot_header = {
static uintptr_t ramdisk_off = 0;
static uintptr_t ramdisk_len = 0;
uint32_t _eax = 1;
uint32_t _ebx = 1;
uint32_t _xmain = 1;
struct mmap_entry {
uint64_t base;
uint64_t len;
uint32_t type;
uint32_t reserved;
};
extern unsigned short mmap_ent;
extern unsigned short lower_mem;
uintptr_t final_offset = 0;
uintptr_t _xmain = 0;
static int load_kernel(void) {
clear();
@ -95,20 +82,453 @@ static int load_kernel(void) {
return 1;
}
static void relocate_ramdisk(void) {
static void relocate_ramdisk(mboot_mod_t * mboot_mods) {
char * dest = (char*)final_offset;
char * src = (char*)ramdisk_off;
for (size_t s = 0; s < ramdisk_len; ++s) {
dest[s] = src[s];
}
modules_mboot[0].mod_start = final_offset;
modules_mboot[0].mod_end = final_offset + ramdisk_len;
mboot_mods->mod_start = final_offset;
mboot_mods->mod_end = final_offset + ramdisk_len;
final_offset += ramdisk_len;
final_offset = (final_offset & ~(0xFFF)) + ((final_offset & 0xFFF) ? 0x1000 : 0);
}
#ifdef EFI_PLATFORM
#include <efi.h>
extern EFI_GRAPHICS_OUTPUT_PROTOCOL * GOP;
/* EFI boot uses simple filesystem driver */
static EFI_GUID efi_simple_file_system_protocol_guid =
{0x0964e5b22,0x6459,0x11d2,0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b};
static EFI_GUID efi_loaded_image_protocol_guid =
{0x5B1B31A1,0x9562,0x11d2, {0x8E,0x3F,0x00,0xA0,0xC9,0x69,0x72,0x3B}};
extern EFI_SYSTEM_TABLE *ST;
extern EFI_HANDLE ImageHandleIn;
extern char do_the_nasty[];
static void finish_boot(void) {
/* Set up multiboot header */
struct multiboot * finalHeader = (void*)(uintptr_t)final_offset;
memcpy((void*)final_offset, &multiboot_header, sizeof(struct multiboot));
final_offset += sizeof(struct multiboot);
finalHeader->flags |= MULTIBOOT_FLAG_FB;
finalHeader->framebuffer_addr = GOP->Mode->FrameBufferBase;
finalHeader->framebuffer_pitch = GOP->Mode->Info->PixelsPerScanLine * 4;
finalHeader->framebuffer_width = GOP->Mode->Info->HorizontalResolution;
finalHeader->framebuffer_height = GOP->Mode->Info->VerticalResolution;
finalHeader->framebuffer_bpp = 32;
/* Copy in command line */
memcpy((void*)final_offset, cmdline, strlen(cmdline)+1);
finalHeader->cmdline = (uintptr_t)final_offset;
final_offset += strlen(cmdline) + 1;
/* Copy bootloader name */
memcpy((void*)final_offset, VERSION_TEXT, strlen(VERSION_TEXT)+1);
finalHeader->boot_loader_name = (uintptr_t)final_offset;
final_offset += strlen(VERSION_TEXT) + 1;
/* Copy module pointers */
memcpy((void*)final_offset, modules_mboot, sizeof(modules_mboot));
finalHeader->mods_addr = (uintptr_t)final_offset;
final_offset += sizeof(modules_mboot);
/* Realign for memory map */
final_offset = (final_offset & ~(0xFFF)) + ((final_offset & 0xFFF) ? 0x1000 : 0);
/* Write memory map */
mboot_memmap_t * mmap = (void*)final_offset;
memset((void*)final_offset, 0x00, 1024);
finalHeader->mmap_addr = (uint32_t)(uintptr_t)mmap;
{
EFI_STATUS e;
UINTN mapSize = 0, mapKey, descriptorSize;
UINT32 descriptorVersion;
e = uefi_call_wrapper(ST->BootServices->GetMemoryMap, 5, &mapSize, NULL, &mapKey, &descriptorSize, NULL);
EFI_MEMORY_DESCRIPTOR * efi_memory = (void*)(final_offset);
final_offset += mapSize;
while ((uintptr_t)final_offset & 0x3ff) final_offset++;
e = uefi_call_wrapper(ST->BootServices->GetMemoryMap, 5, &mapSize, efi_memory, &mapKey, &descriptorSize, NULL);
if (EFI_ERROR(e)) {
print_("EFI error.\n");
while (1) {};
}
uint64_t upper_mem = 0;
int descriptors = mapSize / descriptorSize;
for (int i = 0; i < descriptors; ++i) {
EFI_MEMORY_DESCRIPTOR * d = efi_memory;
mmap->size = sizeof(uint64_t) * 2 + sizeof(uint32_t);
mmap->base_addr = d->PhysicalStart;
mmap->length = d->NumberOfPages * 4096;
switch (d->Type) {
case EfiConventionalMemory:
case EfiLoaderCode:
case EfiLoaderData:
case EfiBootServicesCode:
case EfiBootServicesData:
case EfiRuntimeServicesCode:
case EfiRuntimeServicesData:
mmap->type = 1;
break;
case EfiReservedMemoryType:
case EfiUnusableMemory:
case EfiMemoryMappedIO:
case EfiMemoryMappedIOPortSpace:
case EfiPalCode:
case EfiACPIMemoryNVS:
case EfiACPIReclaimMemory:
default:
mmap->type = 2;
break;
}
if (mmap->type == 1 && mmap->base_addr >= 0x100000) {
upper_mem += mmap->length;
}
mmap = (mboot_memmap_t *) ((uintptr_t)mmap + mmap->size + sizeof(uint32_t));
efi_memory = (EFI_MEMORY_DESCRIPTOR *)((char *)efi_memory + descriptorSize);
}
finalHeader->mmap_length = (uintptr_t)mmap - finalHeader->mmap_addr;
finalHeader->mem_lower = 1024;
finalHeader->mem_upper = upper_mem / 1024;
}
relocate_ramdisk((void*)(uintptr_t)finalHeader->mods_addr);
{
EFI_STATUS e;
UINTN mapSize = 0, mapKey, descriptorSize;
UINT32 descriptorVersion;
uefi_call_wrapper(ST->BootServices->GetMemoryMap, 5, &mapSize, NULL, &mapKey, &descriptorSize, NULL);
e = uefi_call_wrapper(ST->BootServices->ExitBootServices, 2, ImageHandleIn, mapKey);
if (e != EFI_SUCCESS) {
print_("Exit services failed. \n");
print_hex_(e);
while (1) {};
}
}
uint64_t foobar = ((uint32_t)(uintptr_t)&do_the_nasty) | (0x10L << 32L);
uint32_t * foo = (uint32_t *)0x7c00;
foo[0] = MULTIBOOT_EAX_MAGIC;
foo[1] = (uintptr_t)finalHeader;
foo[2] = _xmain;
__asm__ __volatile__ (
"push %0\n"
"lretl\n"
: : "g"(foobar));
__asm__ (
"do_the_nasty:\n"
"cli\n"
".code32\n"
"mov %cr0, %eax\n"
"and $0x7FFeFFFF, %eax\n"
"mov %eax, %cr0\n"
"mov $0xc0000080, %ecx\n"
"rdmsr\n"
"and $0xfffffeff, %eax\n"
"wrmsr\n"
"mov $0x640, %eax\n"
"mov %eax, %cr4\n"
"mov 0x7c00, %eax\n"
"mov 0x7c04, %ebx\n"
"mov 0x7c08, %ecx\n"
"jmp *%ecx\n"
"target: jmp target\n"
".code64\n"
);
__builtin_unreachable();
}
void mode_selector(int sel, int ndx, char *str) {
set_attr(sel == ndx ? 0x70 : 0x07);
print_(str);
if (x < 40) {
while (x < 39) {
print_(" ");
}
x = 40;
} else {
print_("\n");
}
}
static char * print_int_into(char * str, unsigned int value) {
unsigned int n_width = 1;
unsigned int i = 9;
while (value > i && i < UINT32_MAX) {
n_width += 1;
i *= 10;
i += 9;
}
char buf[n_width+1];
for (int i = 0; i < n_width + 1; i++) {
buf[i] = 0;
}
i = n_width;
while (i > 0) {
unsigned int n = value / 10;
int r = value % 10;
buf[i - 1] = r + '0';
i--;
value = n;
}
for (char * c = buf; *c; c++) {
*str++ = *c;
}
return str;
}
int video_menu(void) {
clear_();
int sel = 0;
int sel_max = GOP->Mode->MaxMode;
int select_this_mode = 0;
do {
move_cursor(0,0);
set_attr(0x1f);
print_banner("Select Video Mode");
set_attr(0x07);
print_("\n");
for (int i = 0; i < GOP->Mode->MaxMode; ++i) {
EFI_STATUS status;
UINTN size;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION * info;
status = uefi_call_wrapper(GOP->QueryMode,
4, GOP, i, &size, &info);
if (EFI_ERROR(status) || info->PixelFormat != 1) {
mode_selector(sel, i, "[invalid]");
} else {
if (select_this_mode && sel == i) {
uefi_call_wrapper(GOP->SetMode, 2, GOP, i);
extern int init_graphics();
init_graphics();
return 0;
}
char tmp[100];
char * t = tmp;
t = print_int_into(t, info->HorizontalResolution); *t = 'x'; t++;
t = print_int_into(t, info->VerticalResolution); *t = '\0';
mode_selector(sel, i, tmp);
}
}
int s = read_scancode(0);
if (s == 0x50) { /* DOWN */
if (sel >= 0 && sel < sel_max - 1) {
sel = (sel + 2) % sel_max;
} else {
sel = (sel + 1) % sel_max;
}
} else if (s == 0x48) { /* UP */
if (sel >= 1) {
sel = (sel_max + sel - 2) % sel_max;
} else {
sel = (sel_max + sel - 1) % sel_max;
}
} else if (s == 0x4B) { /* LEFT */
if (sel >= 0) {
if ((sel + 1) % 2) {
sel = (sel + 1) % sel_max;
} else {
sel -= 1;
}
}
} else if (s == 0x4D) { /* RIGHT */
if (sel >= 0) {
if ((sel + 1) % 2) {
sel = (sel + 1) % sel_max;
} else {
sel -= 1;
}
}
} else if (s == 0x1c) {
select_this_mode = 1;
continue;
}
} while (1);
}
void boot(void) {
UINTN count;
EFI_HANDLE * handles;
EFI_LOADED_IMAGE * loaded_image;
EFI_FILE_IO_INTERFACE *efi_simple_filesystem;
EFI_FILE *root;
EFI_STATUS status;
uefi_call_wrapper(ST->BootServices->SetWatchdogTimer, 4, 0, 0, 0, NULL);
clear_();
for (unsigned int i = 0; i < ST->NumberOfTableEntries; ++i) {
if (ST->ConfigurationTable[i].VendorGuid.Data1 == 0xeb9d2d30 &&
ST->ConfigurationTable[i].VendorGuid.Data2 == 0x2d88 &&
ST->ConfigurationTable[i].VendorGuid.Data3 == 0x11d3) {
multiboot_header.config_table = (uintptr_t)ST->ConfigurationTable[i].VendorTable & 0xFFFFffff;
break;
}
}
status = uefi_call_wrapper(ST->BootServices->HandleProtocol,
3, ImageHandleIn, &efi_loaded_image_protocol_guid,
(void **)&loaded_image);
if (EFI_ERROR(status)) {
print_("Could not obtain loaded_image_protocol\n");
while (1) {};
}
print("Found loaded image...\n");
status = uefi_call_wrapper(ST->BootServices->HandleProtocol,
3, loaded_image->DeviceHandle, &efi_simple_file_system_protocol_guid,
(void **)&efi_simple_filesystem);
if (EFI_ERROR(status)) {
print_("Could not obtain simple_file_system_protocol.\n");
while (1) {};
}
status = uefi_call_wrapper(efi_simple_filesystem->OpenVolume,
2, efi_simple_filesystem, &root);
if (EFI_ERROR(status)) {
print_("Could not open volume.\n");
while (1) {};
}
EFI_FILE * file;
CHAR16 kernel_name[16] = {0};
{
char * c = kernel_path;
char * ascii = c;
int i = 0;
while (*ascii) {
kernel_name[i] = *ascii;
i++;
ascii++;
}
if (kernel_name[i-1] == L'.') {
kernel_name[i-1] = 0;
}
}
/* Load kernel */
status = uefi_call_wrapper(root->Open,
5, root, &file, kernel_name, EFI_FILE_MODE_READ, 0);
if (EFI_ERROR(status)) {
print_("Error opening kernel.\n");
while (1) {};
}
#define KERNEL_LOAD_START 0x4000000ULL
kernel_load_start = (char*)KERNEL_LOAD_START;
{
EFI_PHYSICAL_ADDRESS addr = KERNEL_LOAD_START;
EFI_ALLOCATE_TYPE type = AllocateAddress;
EFI_MEMORY_TYPE memtype = EfiLoaderData;
UINTN pages = 8192;
EFI_STATUS status = 0;
status = uefi_call_wrapper(ST->BootServices->AllocatePages, 4, type, memtype, pages, &addr);
if (EFI_ERROR(status)) {
print_("Could not allocate space to load boot payloads: ");
print_hex_(status);
print_(" ");
print_hex_(addr);
while (1) {};
}
}
unsigned int offset = 0;
UINTN bytes = 134217728;
status = uefi_call_wrapper(file->Read,
3, file, &bytes, (void *)KERNEL_LOAD_START);
if (EFI_ERROR(status)) {
print_("Error loading kernel.\n");
while (1) {};
}
offset += bytes;
while (offset % 4096) offset++;
{
char * c = ramdisk_path;
CHAR16 name[16] = {0};
char * ascii = c;
int i = 0;
while (*ascii) {
name[i] = *ascii;
i++;
ascii++;
}
if (name[i-1] == L'.') {
name[i-1] == 0;
}
bytes = 134217728;
status = uefi_call_wrapper(root->Open,
5, root, &file, name, EFI_FILE_MODE_READ, 0);
if (!EFI_ERROR(status)) {
status = uefi_call_wrapper(file->Read,
3, file, &bytes, (void*)(uintptr_t)(KERNEL_LOAD_START + offset));
if (!EFI_ERROR(status)) {
ramdisk_off = KERNEL_LOAD_START + offset;
ramdisk_len = bytes;
} else {
print_("Failed to read ramdisk\n");
}
} else {
print_("Error opening "); print_(c); print_("\n");
}
}
load_kernel();
finish_boot();
}
#else
struct mmap_entry {
uint64_t base;
uint64_t len;
uint32_t type;
uint32_t reserved;
};
extern unsigned short mmap_ent;
extern unsigned short lower_mem;
static void finish_boot(void) {
print("Setting up memory map...\n");
print_hex(mmap_ent);
@ -148,14 +568,11 @@ static void finish_boot(void) {
multiboot_header.mem_upper = upper_mem / 1024;
_ebx = (unsigned int)&multiboot_header;
_eax = MULTIBOOT_EAX_MAGIC;
print("Jumping to kernel...\n");
uint32_t foo[3];
foo[0] = _eax;
foo[1] = _ebx;
foo[0] = MULTIBOOT_EAX_MAGIC;
foo[1] = (unsigned int)&multiboot_header;;
foo[2] = _xmain;
__asm__ __volatile__ (
"mov %%cr0,%%eax\n"
@ -214,7 +631,7 @@ done:
}
print("Relocating ramdisk from 0x"); print_hex((uint32_t)ramdisk_off); print(":0x"); print_hex(ramdisk_len); print(" to 0x"); print_hex(final_offset); print("... ");
relocate_ramdisk();
relocate_ramdisk(modules_mboot);
finish_boot();
}
#endif

View File

@ -27,6 +27,12 @@ struct bootmode {
#define BASE_SEL ((sizeof(boot_mode_names)/sizeof(*boot_mode_names))-1)
extern int base_sel;
#define BOOT_SET() do { \
base_sel = BASE_SEL; \
_boot_offset = 0; \
memset(boot_options, 0, sizeof(boot_options)); \
} while (0)
extern char * VERSION_TEXT;
extern char * HELP_TEXT;
extern char * HELP_TEXT_OPT;

107
boot/platform.c Normal file
View File

@ -0,0 +1,107 @@
extern int kmain();
#ifdef EFI_PLATFORM
#include <efi.h>
#include <efilib.h>
EFI_HANDLE ImageHandleIn;
extern int init_graphics();
EFI_STATUS
EFIAPI
efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
InitializeLib(ImageHandle, SystemTable);
ST = SystemTable;
ImageHandleIn = ImageHandle;
init_graphics();
return kmain();
}
#else
#include <stdint.h>
#include <stddef.h>
#include "iso9660.h"
#include "util.h"
#include "text.h"
extern char _bss_start[];
extern char _bss_end[];
void * memcpy(void * restrict dest, const void * restrict src, long n) {
asm volatile("cld; rep movsb"
: "=c"((int){0})
: "D"(dest), "S"(src), "c"(n)
: "flags", "memory");
return dest;
}
void * memset(void * dest, int c, long n) {
asm volatile("cld; rep stosb"
: "=c"((int){0})
: "D"(dest), "a"(c), "c"(n)
: "flags", "memory");
return dest;
}
int bios_main(void) {
/* Zero BSS */
memset(&_bss_start,0,(uintptr_t)&_bss_end-(uintptr_t)&_bss_start);
/* Hide the cursor */
outportb(0x3D4, 14);
outportb(0x3D5, 0xFF);
outportb(0x3D4, 15);
outportb(0x3D5, 0xFF);
/* iirc this disables blink? */
inportb(0x3DA);
outportb(0x3C0, 0x30);
char b = inportb(0x3C1);
b &= ~8;
outportb(0x3c0, b);
return kmain();
}
iso_9660_volume_descriptor_t * root = NULL;
iso_9660_directory_entry_t * dir_entry = NULL;
static char * dir_entries = NULL;
int navigate(char * name) {
dir_entry = (iso_9660_directory_entry_t*)&root->root;
dir_entries = (char*)(DATA_LOAD_BASE + dir_entry->extent_start_LSB * ISO_SECTOR_SIZE);
long offset = 0;
while (1) {
iso_9660_directory_entry_t * dir = (iso_9660_directory_entry_t *)(dir_entries + offset);
if (dir->length == 0) {
if (offset < dir_entry->extent_length_LSB) {
offset += 1;
goto try_again;
}
break;
}
if (!(dir->flags & FLAG_HIDDEN)) {
char file_name[dir->name_len + 1];
memcpy(file_name, dir->name, dir->name_len);
file_name[dir->name_len] = 0;
char * s = strchr(file_name,';');
if (s) {
*s = '\0';
}
if (!strcmp(file_name, name)) {
dir_entry = dir;
return 1;
}
}
offset += dir->length;
try_again:
if ((long)(offset) > dir_entry->extent_length_LSB) break;
}
return 0;
}
#endif

View File

@ -1,7 +1,113 @@
#include "text.h"
#include "util.h"
int txt_debug = 0;
#ifdef EFI_PLATFORM
#include <efi.h>
extern EFI_SYSTEM_TABLE *ST;
#include "../apps/terminal-font.h"
#define char_height LARGE_FONT_CELL_HEIGHT
#define char_width LARGE_FONT_CELL_WIDTH
EFI_GRAPHICS_OUTPUT_PROTOCOL * GOP;
static int offset_x = 0;
static int offset_y = 0;
static EFI_GUID efi_graphics_output_protocol_guid =
{0x9042a9de,0x23dc,0x4a38, {0x96,0xfb,0x7a,0xde,0xd0,0x80,0x51,0x6a}};
int init_graphics() {
UINTN count;
EFI_HANDLE * handles;
EFI_GRAPHICS_OUTPUT_PROTOCOL * gfx;
EFI_STATUS status;
status = uefi_call_wrapper(ST->BootServices->LocateHandleBuffer,
5, ByProtocol, &efi_graphics_output_protocol_guid, NULL, &count, &handles);
if (EFI_ERROR(status)) goto no_graphics;
status = uefi_call_wrapper(ST->BootServices->HandleProtocol,
3, handles[0], &efi_graphics_output_protocol_guid, (void **)&gfx);
if (EFI_ERROR(status)) goto no_graphics;
GOP = gfx;
int total_width = GOP->Mode->Info->HorizontalResolution;
int total_height = GOP->Mode->Info->VerticalResolution;
offset_x = (total_width - 80 * char_width) / 2;
offset_y = (total_height - 24 * char_height) / 2;
return 0;
no_graphics:
return 1;
}
static uint32_t term_colors[] = {
0xFF000000,
0xFFCC0000,
0xFF4E9A06,
0xFFC4A000,
0xFF3465A4,
0xFF75507B,
0xFF06989A,
0xFFD3D7CF,
0xFF555753,
0xFFEF2929,
0xFF8AE234,
0xFFFCE94F,
0xFF729FCF,
0xFFAD7FA8,
0xFF34E2E2,
0xFFEEEEEC,
};
char vga_to_ansi[] = {
0, 4, 2, 6, 1, 5, 3, 7,
8,12,10,14, 9,13,11,15
};
static void set_point(int x, int y, uint32_t color) {
((uint32_t *)GOP->Mode->FrameBufferBase)[(x + offset_x) + (y + offset_y) * GOP->Mode->Info->PixelsPerScanLine] = color;
}
static void write_char(int x, int y, int val, int attr) {
if (val > 128) {
val = 4;
}
uint32_t fg_color = term_colors[vga_to_ansi[attr & 0xF]];
uint32_t bg_color = term_colors[vga_to_ansi[(attr >> 4) & 0xF]];
uint16_t * c = large_font[val];
for (uint8_t i = 0; i < char_height; ++i) {
for (uint8_t j = 0; j < char_width; ++j) {
if (c[i] & (1 << (LARGE_FONT_MASK-j))) {
set_point(x+j,y+i,fg_color);
} else {
set_point(x+j,y+i,bg_color);
}
}
}
}
static void placech(unsigned char c, int x, int y, int attr) {
write_char(x * char_width, y * char_height, c, attr);
}
void clear_() {
x = 0;
y = 0;
memset((void*)GOP->Mode->FrameBufferBase,0,GOP->Mode->FrameBufferSize);
}
#else
static unsigned short * textmemptr = (unsigned short *)0xB8000;
static void placech(unsigned char c, int x, int y, int attr) {
@ -11,6 +117,17 @@ static void placech(unsigned char c, int x, int y, int attr) {
*where = c | att;
}
void clear_() {
x = 0;
y = 0;
for (int y = 0; y < 24; ++y) {
for (int x = 0; x < 80; ++x) {
placech(' ', x, y, 0x00);
}
}
}
#endif
int x = 0;
int y = 0;
int attr = 0x07;
@ -84,12 +201,3 @@ void print_hex_(unsigned int value) {
print_(out);
}
void clear_() {
x = 0;
y = 0;
for (int y = 0; y < 24; ++y) {
for (int x = 0; x < 80; ++x) {
placech(' ', x, y, 0x00);
}
}
}

View File

@ -1,21 +1,5 @@
#include "util.h"
void * memcpy(void * restrict dest, const void * restrict src, long n) {
asm volatile("cld; rep movsb"
: "=c"((int){0})
: "D"(dest), "S"(src), "c"(n)
: "flags", "memory");
return dest;
}
void * memset(void * dest, int c, long n) {
asm volatile("cld; rep stosb"
: "=c"((int){0})
: "D"(dest), "a"(c), "c"(n)
: "flags", "memory");
return dest;
}
int strcmp(const char * l, const char * r) {
for (; *l == *r && *l; l++, r++);
return *(unsigned char *)l - *(unsigned char *)r;