diff --git a/Makefile b/Makefile index 9b6d0f88..66606126 100644 --- a/Makefile +++ b/Makefile @@ -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 \ diff --git a/boot/boot.S b/boot/boot.S index c45e7f49..e056df03 100644 --- a/boot/boot.S +++ b/boot/boot.S @@ -165,8 +165,8 @@ done: cli -.global kmain - ljmp $0x08,$kmain +.global bios_main + ljmp $0x08,$bios_main hang: jmp hang diff --git a/boot/config.c b/boot/config.c index 6921448c..4fb63614 100644 --- a/boot/config.c +++ b/boot/config.c @@ -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 = " to boot, to edit, or select a menu option with \030/\031/\032/\033."; char * HELP_TEXT_OPT = " 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); diff --git a/boot/iso9660.c b/boot/iso9660.c deleted file mode 100644 index 71cebeb7..00000000 --- a/boot/iso9660.c +++ /dev/null @@ -1,49 +0,0 @@ -#include -#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; -} - - diff --git a/boot/kbd.c b/boot/kbd.c index 485dbeef..d7cafe96 100644 --- a/boot/kbd.c +++ b/boot/kbd.c @@ -1,5 +1,87 @@ #include "kbd.h" #include "util.h" +#include "text.h" + +#ifdef EFI_PLATFORM +#include +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 diff --git a/boot/menu.c b/boot/menu.c index 669c662d..33a8cbf6 100644 --- a/boot/menu.c +++ b/boot/menu.c @@ -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 { diff --git a/boot/multiboot.c b/boot/multiboot.c index 45caa4de..da820b91 100644 --- a/boot/multiboot.c +++ b/boot/multiboot.c @@ -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 +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 diff --git a/boot/options.h b/boot/options.h index 068bafc9..5c1d213e 100644 --- a/boot/options.h +++ b/boot/options.h @@ -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; diff --git a/boot/platform.c b/boot/platform.c new file mode 100644 index 00000000..2caba806 --- /dev/null +++ b/boot/platform.c @@ -0,0 +1,107 @@ +extern int kmain(); + +#ifdef EFI_PLATFORM +#include +#include +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 +#include +#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 diff --git a/boot/text.c b/boot/text.c index 4813c844..ed827334 100644 --- a/boot/text.c +++ b/boot/text.c @@ -1,7 +1,113 @@ #include "text.h" - +#include "util.h" int txt_debug = 0; +#ifdef EFI_PLATFORM +#include +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); - } - } -} diff --git a/boot/util.c b/boot/util.c index 12be3ab5..1000667f 100644 --- a/boot/util.c +++ b/boot/util.c @@ -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;