diff --git a/stage23/fs/file.s2.c b/stage23/fs/file.s2.c index bd7a9628..1e651390 100644 --- a/stage23/fs/file.s2.c +++ b/stage23/fs/file.s2.c @@ -113,7 +113,7 @@ int fread(struct file_handle *fd, void *buf, uint64_t loc, uint64_t count) { void *freadall(struct file_handle *fd, uint32_t type) { if (fd->is_memfile) { - memmap_alloc_range((uint64_t)(size_t)fd->fd, fd->size, type, false, true, false); + memmap_alloc_range((uint64_t)(size_t)fd->fd, fd->size, type, false, true, false, false); return fd->fd; } else { void *ret = ext_mem_alloc_aligned_type(fd->size, 4096, type); diff --git a/stage23/lib/elf.c b/stage23/lib/elf.c index e8e92854..1977c8ee 100644 --- a/stage23/lib/elf.c +++ b/stage23/lib/elf.c @@ -340,7 +340,7 @@ final: load_vaddr += slide; - if (!memmap_alloc_range((size_t)load_vaddr, (size_t)phdr.p_memsz, alloc_type, true, false, simulation)) { + if (!memmap_alloc_range((size_t)load_vaddr, (size_t)phdr.p_memsz, alloc_type, true, false, simulation, false)) { if (++try_count == max_simulated_tries || simulation == false) return -1; goto again; @@ -397,7 +397,7 @@ int elf32_load(uint8_t *elf, uint32_t *entry_point, uint32_t alloc_type) { if (phdr.p_type != PT_LOAD) continue; - memmap_alloc_range((size_t)phdr.p_paddr, (size_t)phdr.p_memsz, alloc_type, true, true, false); + memmap_alloc_range((size_t)phdr.p_paddr, (size_t)phdr.p_memsz, alloc_type, true, true, false, false); memcpy((void *)(uintptr_t)phdr.p_paddr, elf + (phdr.p_offset), phdr.p_filesz); diff --git a/stage23/lib/fb.c b/stage23/lib/fb.c index c51107cf..f3a66033 100644 --- a/stage23/lib/fb.c +++ b/stage23/lib/fb.c @@ -4,14 +4,23 @@ #include #include #include +#include bool fb_init(struct fb_info *ret, uint16_t target_width, uint16_t target_height, uint16_t target_bpp) { + bool r; + #if defined (bios) - return init_vbe(ret, target_width, target_height, target_bpp); + r = init_vbe(ret, target_width, target_height, target_bpp); #elif defined (uefi) - return init_gop(ret, target_width, target_height, target_bpp); + r = init_gop(ret, target_width, target_height, target_bpp); #endif + + memmap_alloc_range(ret->framebuffer_addr, + (uint64_t)ret->framebuffer_pitch * ret->framebuffer_height, + MEMMAP_FRAMEBUFFER, false, false, false, true); + + return r; } void fb_clear(struct fb_info *fb) { diff --git a/stage23/lib/gterm.c b/stage23/lib/gterm.c index f9d1e73e..3a03acff 100644 --- a/stage23/lib/gterm.c +++ b/stage23/lib/gterm.c @@ -15,7 +15,7 @@ #define VGA_FONT_GLYPHS 256 #define VGA_FONT_MAX (VGA_FONT_HEIGHT * VGA_FONT_GLYPHS) -static struct fb_info fbinfo; +struct fb_info fbinfo; static uint32_t *gterm_framebuffer; static uint16_t gterm_pitch; static uint16_t gterm_width; diff --git a/stage23/lib/gterm.h b/stage23/lib/gterm.h index 65b7565c..382b85b9 100644 --- a/stage23/lib/gterm.h +++ b/stage23/lib/gterm.h @@ -6,6 +6,8 @@ #include #include +extern struct fb_info fbinfo; + bool gterm_init(int *rows, int *cols, uint32_t *colours, int margin, int margin_gradient, struct image *background); diff --git a/stage23/mm/pmm.h b/stage23/mm/pmm.h index 5d3d057c..251c4aa1 100644 --- a/stage23/mm/pmm.h +++ b/stage23/mm/pmm.h @@ -14,6 +14,7 @@ #define MEMMAP_BAD_MEMORY 5 #define MEMMAP_BOOTLOADER_RECLAIMABLE 0x1000 #define MEMMAP_KERNEL_AND_MODULES 0x1001 +#define MEMMAP_FRAMEBUFFER 0x1002 #define MEMMAP_EFI_RECLAIMABLE 0x2000 extern size_t bump_allocator_base; @@ -25,7 +26,7 @@ extern size_t memmap_entries; void init_memmap(void); struct e820_entry_t *get_memmap(size_t *entries); void print_memmap(struct e820_entry_t *mm, size_t size); -bool memmap_alloc_range(uint64_t base, uint64_t length, uint32_t type, bool free_only, bool panic, bool simulation); +bool memmap_alloc_range(uint64_t base, uint64_t length, uint32_t type, bool free_only, bool panic, bool simulation, bool new_entry); void *ext_mem_alloc(size_t count); void *ext_mem_alloc_type(size_t count, uint32_t type); diff --git a/stage23/mm/pmm.s2.c b/stage23/mm/pmm.s2.c index d39bbaea..1f54e2d7 100644 --- a/stage23/mm/pmm.s2.c +++ b/stage23/mm/pmm.s2.c @@ -342,7 +342,7 @@ void init_memmap(void) { memmap_alloc_range(bump_allocator_base, bump_allocator_limit - bump_allocator_base, - MEMMAP_REMOVE_RANGE, true, true, false); + MEMMAP_REMOVE_RANGE, true, true, false, false); print("pmm: Conventional mem allocator base: %X\n", bump_allocator_base); print("pmm: Conventional mem allocator limit: %X\n", bump_allocator_limit); @@ -399,7 +399,7 @@ void *ext_mem_alloc_aligned_type(size_t count, size_t alignment, uint32_t type) // We now reserve the range we need. int64_t aligned_length = entry_top - alloc_base; - memmap_alloc_range((uint64_t)alloc_base, (uint64_t)aligned_length, type, true, true, false); + memmap_alloc_range((uint64_t)alloc_base, (uint64_t)aligned_length, type, true, true, false, false); void *ret = (void *)(size_t)alloc_base; @@ -414,7 +414,7 @@ void *ext_mem_alloc_aligned_type(size_t count, size_t alignment, uint32_t type) panic("High memory allocator: Out of memory"); } -bool memmap_alloc_range(uint64_t base, uint64_t length, uint32_t type, bool free_only, bool do_panic, bool simulation) { +bool memmap_alloc_range(uint64_t base, uint64_t length, uint32_t type, bool free_only, bool do_panic, bool simulation, bool new_entry) { if (length == 0) return true; @@ -499,8 +499,19 @@ bool memmap_alloc_range(uint64_t base, uint64_t length, uint32_t type, bool free } } - if (do_panic) + if (!new_entry && do_panic) panic("Out of memory"); + if (new_entry) { + if (memmap_entries >= MEMMAP_MAX_ENTRIES) + panic("Memory map exhausted."); + + struct e820_entry_t *target = &memmap[memmap_entries++]; + + target->type = type; + target->base = base; + target->length = length; + } + return false; } diff --git a/stage23/protos/linux.c b/stage23/protos/linux.c index 513197e1..68a61636 100644 --- a/stage23/protos/linux.c +++ b/stage23/protos/linux.c @@ -417,7 +417,7 @@ void linux_load(char *config, char *cmdline) { for (;;) { if (memmap_alloc_range(kernel_load_addr, kernel->size - real_mode_code_size, - MEMMAP_BOOTLOADER_RECLAIMABLE, true, false, false)) + MEMMAP_BOOTLOADER_RECLAIMABLE, true, false, false, false)) break; kernel_load_addr += 0x100000; @@ -451,7 +451,7 @@ void linux_load(char *config, char *cmdline) { for (;;) { if (memmap_alloc_range(modules_mem_base, size_of_all_modules, - MEMMAP_BOOTLOADER_RECLAIMABLE, true, false, false)) + MEMMAP_BOOTLOADER_RECLAIMABLE, true, false, false, false)) break; modules_mem_base -= 4096; } diff --git a/stage23/protos/stivale2.c b/stage23/protos/stivale2.c index 5d167c94..26b263ee 100644 --- a/stage23/protos/stivale2.c +++ b/stage23/protos/stivale2.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,10 @@ static void append_tag(struct stivale2_struct *s, struct stivale2_tag *tag) { s->tags = (uint64_t)(size_t)tag; } +#if defined (bios) +extern symbol stivale2_term_write_entry; +#endif + void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table) { struct file_handle *kernel_file = ext_mem_alloc(sizeof(struct file_handle)); @@ -261,11 +266,36 @@ void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table // Create framebuffer struct tag ////////////////////////////////////////////// { - term_deinit(); + + struct fb_info *fb = NULL; + struct fb_info _fb; + + struct stivale2_header_tag_terminal *terminal_hdr_tag = get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_TERMINAL_ID); struct stivale2_header_tag_framebuffer *hdrtag = get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_FRAMEBUFFER_ID); + if (bits == 64 && terminal_hdr_tag != NULL && current_video_mode >= 0 && hdrtag != NULL) { + fb = &fbinfo; + + struct stivale2_struct_tag_terminal *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_terminal)); + tag->tag.identifier = STIVALE2_STRUCT_TAG_TERMINAL_ID; + +#if defined (bios) + tag->term_write = (uintptr_t)(void *)stivale2_term_write_entry; +#elif defined (uefi) + tag->term_write = (uintptr_t)term_write; +#endif + + append_tag(&stivale2_struct, (struct stivale2_tag *)tag); + + goto skip_modeset; + } else { + fb = &_fb; + } + if (hdrtag != NULL) { + term_deinit(); + int req_width = hdrtag->framebuffer_width; int req_height = hdrtag->framebuffer_height; int req_bpp = hdrtag->framebuffer_bpp; @@ -274,27 +304,27 @@ void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table if (resolution != NULL) parse_resolution(&req_width, &req_height, &req_bpp, resolution); - struct fb_info fbinfo; - if (fb_init(&fbinfo, req_width, req_height, req_bpp)) { + if (fb_init(fb, req_width, req_height, req_bpp)) { +skip_modeset:; struct stivale2_struct_tag_framebuffer *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_framebuffer)); tag->tag.identifier = STIVALE2_STRUCT_TAG_FRAMEBUFFER_ID; tag->memory_model = STIVALE2_FBUF_MMODEL_RGB; - tag->framebuffer_addr = fbinfo.framebuffer_addr; - tag->framebuffer_width = fbinfo.framebuffer_width; - tag->framebuffer_height = fbinfo.framebuffer_height; - tag->framebuffer_bpp = fbinfo.framebuffer_bpp; - tag->framebuffer_pitch = fbinfo.framebuffer_pitch; - tag->red_mask_size = fbinfo.red_mask_size; - tag->red_mask_shift = fbinfo.red_mask_shift; - tag->green_mask_size = fbinfo.green_mask_size; - tag->green_mask_shift = fbinfo.green_mask_shift; - tag->blue_mask_size = fbinfo.blue_mask_size; - tag->blue_mask_shift = fbinfo.blue_mask_shift; + tag->framebuffer_addr = fb->framebuffer_addr; + tag->framebuffer_width = fb->framebuffer_width; + tag->framebuffer_height = fb->framebuffer_height; + tag->framebuffer_bpp = fb->framebuffer_bpp; + tag->framebuffer_pitch = fb->framebuffer_pitch; + tag->red_mask_size = fb->red_mask_size; + tag->red_mask_shift = fb->red_mask_shift; + tag->green_mask_size = fb->green_mask_size; + tag->green_mask_shift = fb->green_mask_shift; + tag->blue_mask_size = fb->blue_mask_size; + tag->blue_mask_shift = fb->blue_mask_shift; append_tag(&stivale2_struct, (struct stivale2_tag *)tag); - if (get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_FB_MTRR_ID) != NULL) { + if (terminal_hdr_tag == NULL && get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_FB_MTRR_ID) != NULL) { mtrr_restore(); bool ret = mtrr_set_range(tag->framebuffer_addr, (uint64_t)tag->framebuffer_pitch * tag->framebuffer_height, diff --git a/stage23/protos/stivale2_rt.asm b/stage23/protos/stivale2_rt.asm new file mode 100644 index 00000000..8c867044 --- /dev/null +++ b/stage23/protos/stivale2_rt.asm @@ -0,0 +1,68 @@ +section .bss + +user_stack: + resq 1 + +term_buf: + resb 1024 + +section .text + +extern term_write + +bits 64 +global stivale2_term_write_entry +stivale2_term_write_entry: + push rbx + push rbp + push r12 + push r13 + push r14 + push r15 + + mov [user_stack], rsp + mov rsp, 0x7c00 + + push rsi + mov rcx, rsi + mov rsi, rdi + mov rdi, term_buf + rep movsb + pop rsi + + push 0x18 + push .mode32 + retfq +bits 32 + .mode32: + mov eax, 0x20 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + push esi + push term_buf + call term_write + add esp, 8 + push 0x28 + push .mode64 + retfd +bits 64 + .mode64: + mov eax, 0x30 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + mov rsp, [user_stack] + + pop r15 + pop r14 + pop r13 + pop r12 + pop rbp + pop rbx + + ret diff --git a/test/e9print.c b/test/e9print.c index f027e4ec..30450f5c 100644 --- a/test/e9print.c +++ b/test/e9print.c @@ -1,9 +1,13 @@ #include #include +void (*stivale2_print)(const char *buf, size_t size) = NULL; + static const char CONVERSION_TABLE[] = "0123456789abcdef"; void e9_putc(char c) { + if (stivale2_print != NULL) + stivale2_print(&c, 1); asm volatile ("out dx, al" :: "a" (c), "d" (0xE9) : "memory"); } @@ -70,7 +74,7 @@ void e9_printf(const char *format, ...) { e9_printdec(va_arg(argp, size_t)); } else if (*format == 's') { e9_print(va_arg(argp, char*)); - } + } } else { e9_putc(*format); } diff --git a/test/e9print.h b/test/e9print.h index 44ac8e2f..052dbac4 100644 --- a/test/e9print.h +++ b/test/e9print.h @@ -1,6 +1,9 @@ #pragma once #include +#include + +extern void (*stivale2_print)(const char *buf, size_t size); void e9_putc(char c); void e9_print(const char *msg); diff --git a/test/stivale2.c b/test/stivale2.c index 04711887..2ad1be1c 100644 --- a/test/stivale2.c +++ b/test/stivale2.c @@ -7,10 +7,18 @@ typedef uint8_t stack[4096]; static stack stacks[10] = {0}; void stivale2_main(struct stivale2_struct *info); +struct stivale2_header_tag_terminal terminal_request = { + .tag = { + .identifier = STIVALE2_HEADER_TAG_TERMINAL_ID, + .next = 0 + }, + .flags = 0 +}; + struct stivale2_header_tag_smp smp_request = { .tag = { .identifier = STIVALE2_HEADER_TAG_SMP_ID, - .next = 0 + .next = (uint64_t)&terminal_request }, .flags = 0 }; @@ -41,92 +49,110 @@ struct stivale2_header header2 = { static volatile int cpu_up = 0; static void ap_entry(struct stivale2_smp_info *s) { - e9_printf("\t\t\tAP %d started", s->lapic_id); + e9_printf(" AP %d started", s->lapic_id); cpu_up = 1; for (;;) asm("hlt"); } void stivale2_main(struct stivale2_struct *info) { + // Print the tags. + struct stivale2_tag *tag = (struct stivale2_tag *)info->tags; + + while (tag != NULL) { + if (tag->identifier == STIVALE2_STRUCT_TAG_TERMINAL_ID) { + struct stivale2_struct_tag_terminal *t = (void *)tag; + stivale2_print = (void *)(uintptr_t)t->term_write; + } + tag = (void *)tag->next; + } + // Print stuff. e9_puts("Stivale2 info passed to the kernel:"); e9_printf("Bootloader brand: %s", info->bootloader_brand); e9_printf("Bootloader version: %s", info->bootloader_version); // Print the tags. - struct stivale2_tag *tag = (struct stivale2_tag *)info->tags; + tag = (struct stivale2_tag *)info->tags; while (tag != NULL) { switch (tag->identifier) { case STIVALE2_STRUCT_TAG_CMDLINE_ID: { struct stivale2_struct_tag_cmdline *c = (struct stivale2_struct_tag_cmdline *)tag; e9_puts("Commandline tag:"); - e9_printf("\tCmdline: %s", (char*)(c->cmdline)); + e9_printf(" Cmdline: %s", (char*)(c->cmdline)); break; } case STIVALE2_STRUCT_TAG_MEMMAP_ID: { struct stivale2_struct_tag_memmap *m = (struct stivale2_struct_tag_memmap *)tag; e9_puts("Memmap tag:"); - e9_printf("\tEntries: %d", m->entries); + e9_printf(" Entries: %d", m->entries); for (size_t i = 0; i < m->entries; i++) { struct stivale2_mmap_entry me = m->memmap[i]; - e9_printf("\t\t[%x+%x] %x", me.base, me.length, me.type); + e9_printf(" [%x+%x] %x", me.base, me.length, me.type); } break; } case STIVALE2_STRUCT_TAG_FRAMEBUFFER_ID: { struct stivale2_struct_tag_framebuffer *f = (struct stivale2_struct_tag_framebuffer *)tag; e9_puts("Framebuffer tag:"); - e9_printf("\tAddress: %x", f->framebuffer_addr); - e9_printf("\tWidth: %d", f->framebuffer_width); - e9_printf("\tHeight: %d", f->framebuffer_height); - e9_printf("\tPitch: %d", f->framebuffer_pitch); - e9_printf("\tBPP: %d", f->framebuffer_bpp); - e9_printf("\tMemory model: %d", f->memory_model); - e9_printf("\tRed mask size: %d", f->red_mask_size); - e9_printf("\tRed mask size: %d", f->red_mask_shift); - e9_printf("\tGreen mask size: %d", f->green_mask_size); - e9_printf("\tGreen mask size: %d", f->green_mask_shift); - e9_printf("\tBlue mask size: %d", f->blue_mask_size); - e9_printf("\tBlue mask size: %d", f->blue_mask_shift); + e9_printf(" Address: %x", f->framebuffer_addr); + e9_printf(" Width: %d", f->framebuffer_width); + e9_printf(" Height: %d", f->framebuffer_height); + e9_printf(" Pitch: %d", f->framebuffer_pitch); + e9_printf(" BPP: %d", f->framebuffer_bpp); + e9_printf(" Memory model: %d", f->memory_model); + e9_printf(" Red mask size: %d", f->red_mask_size); + e9_printf(" Red mask size: %d", f->red_mask_shift); + e9_printf(" Green mask size: %d", f->green_mask_size); + e9_printf(" Green mask size: %d", f->green_mask_shift); + e9_printf(" Blue mask size: %d", f->blue_mask_size); + e9_printf(" Blue mask size: %d", f->blue_mask_shift); break; } case STIVALE2_STRUCT_TAG_EDID_ID: { struct stivale2_struct_tag_edid *edid = (struct stivale2_struct_tag_edid *)tag; e9_printf("EDID information at %x:", edid->edid_information); - e9_printf("\tSize: %d", edid->edid_size); + e9_printf(" Size: %d", edid->edid_size); } case STIVALE2_STRUCT_TAG_FB_MTRR_ID: { e9_puts("Framebuffer WC MTRR tag:"); - e9_puts("\tFramebuffer WC MTRR enabled"); + e9_puts(" Framebuffer WC MTRR enabled"); + break; + } + case STIVALE2_STRUCT_TAG_TERMINAL_ID: { + struct stivale2_struct_tag_terminal *term = (struct stivale2_struct_tag_terminal *)tag; + + e9_puts("Terminal tag:"); + e9_printf(" Terminal write entry point at: %x", term->term_write); break; } case STIVALE2_STRUCT_TAG_MODULES_ID: { struct stivale2_struct_tag_modules *m = (struct stivale2_struct_tag_modules *)tag; e9_puts("Modules tag:"); - e9_printf("\tCount: %d", m->module_count); + e9_printf(" Count: %d", m->module_count); for (size_t i = 0; i < m->module_count; i++) { struct stivale2_module me = m->modules[i]; - e9_printf("\t\t[%x+%x] %s", me.begin, me.end, me.string); + e9_printf(" [%x+%x] %s", me.begin, me.end, me.string); } break; } case STIVALE2_STRUCT_TAG_RSDP_ID: { struct stivale2_struct_tag_rsdp *r = (struct stivale2_struct_tag_rsdp *)tag; e9_puts("RSDP tag:"); - e9_printf("\tRSDP: %x", r->rsdp); + e9_printf(" RSDP: %x", r->rsdp); break; } case STIVALE2_STRUCT_TAG_EPOCH_ID: { struct stivale2_struct_tag_epoch *e = (struct stivale2_struct_tag_epoch *)tag; e9_puts("Epoch tag:"); - e9_printf("\tEpoch: %x", e->epoch); + e9_printf(" Epoch: %x", e->epoch); break; } case STIVALE2_STRUCT_TAG_FIRMWARE_ID: { struct stivale2_struct_tag_firmware *f = (struct stivale2_struct_tag_firmware *)tag; e9_puts("Firmware tag:"); - e9_printf("\tFlags: %x", f->flags); + e9_printf(" Flags: %x", f->flags); break; } case STIVALE2_STRUCT_TAG_EFI_SYSTEM_TABLE_ID: { @@ -147,16 +173,16 @@ void stivale2_main(struct stivale2_struct *info) { case STIVALE2_STRUCT_TAG_SMP_ID: { struct stivale2_struct_tag_smp *s = (struct stivale2_struct_tag_smp *)tag; e9_puts("SMP tag:"); - e9_printf("\tFlags: %x", s->flags); - e9_printf("\tBSP LAPIC ID: %d", s->bsp_lapic_id); - e9_printf("\tCPU Count: %d", s->cpu_count); + e9_printf(" Flags: %x", s->flags); + e9_printf(" BSP LAPIC ID: %d", s->bsp_lapic_id); + e9_printf(" CPU Count: %d", s->cpu_count); for (size_t i = 0; i < s->cpu_count; i++) { struct stivale2_smp_info *in = &s->smp_info[i]; - e9_printf("\t\tProcessor ID: %d", in->processor_id); - e9_printf("\t\tLAPIC ID: %d", in->lapic_id); - e9_printf("\t\tTarget Stack: %x", in->target_stack); - e9_printf("\t\tGOTO Address: %x", in->goto_address); - e9_printf("\t\tExtra Argument: %x", in->extra_argument); + e9_printf(" Processor ID: %d", in->processor_id); + e9_printf(" LAPIC ID: %d", in->lapic_id); + e9_printf(" Target Stack: %x", in->target_stack); + e9_printf(" GOTO Address: %x", in->goto_address); + e9_printf(" Extra Argument: %x", in->extra_argument); if (in->lapic_id != s->bsp_lapic_id) { in->target_stack = (uintptr_t)stacks[in->lapic_id] + sizeof(stack); in->goto_address = (uintptr_t)ap_entry; @@ -167,7 +193,7 @@ void stivale2_main(struct stivale2_struct *info) { break; } default: - e9_printf("BUG: Unidentifier tag %x", tag->identifier); + e9_printf("BUG: Unidentified tag %x", tag->identifier); } tag = (struct stivale2_tag *)tag->next;