From ad37ae9264a7390aa6bbff5080ea3310f200c4d7 Mon Sep 17 00:00:00 2001 From: Nathan Wagner Date: Mon, 24 Oct 2016 20:36:32 -0500 Subject: [PATCH] kernel startup and linker script --- kernel.c | 130 +++++++++++++++++++++++++++++++++++++ kernel.h | 20 ++++++ link64.ld | 70 ++++++++++++++++++++ multiboot.h | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 402 insertions(+) create mode 100644 kernel.c create mode 100644 kernel.h create mode 100644 link64.ld create mode 100644 multiboot.h diff --git a/kernel.c b/kernel.c new file mode 100644 index 0000000..aed3d72 --- /dev/null +++ b/kernel.c @@ -0,0 +1,130 @@ +#include +#include + +#include + +#include "multiboot.h" +#include "kernel.h" +#include "interrupt.h" +#include "timer.h" +#include "mem.h" +#include "process.h" + +#include "tty.h" +#include "kbd.h" +#include "pci/pci.h" + +#include +#include + +#include + +int global_errno; + +extern uint64_t _asm_physmap; + +/* Check if the compiler thinks if we are targeting the wrong operating system. */ +#if defined(__linux__) +#error "compiling for linux, not target os" +#endif + +#define STACK_SIZE 65536 +__attribute__((aligned(16))) size_t stack[STACK_SIZE / sizeof(size_t)]; + +static void check_mbmagic(uint64_t magic) { + if (magic != MULTIBOOT_BOOTLOADER_MAGIC) { + printk("Invalid magic number: 0x%x\n", (unsigned) magic); + allstop(); + } +} + +void kernel_main(struct multiboot_info *mbinfo, uint64_t mbmagic) { + + /* we do this first so we can print debug messages */ + terminal_initialize(); + + terminal.writestring("ZOS 64 bit booting...\n"); + check_mbmagic(mbmagic); + + printk("kernel_vma = 0x%llx\n", (uint64_t)_kernel_vma); + printk("kernel_end = 0x%llx\n", (uint64_t)_kernel_end); + printk("kernel_phys_end = 0x%llx\n", (uint64_t)_kernel_phys_end); + printk("kernel_size = %llu KB\n", (uint64_t)_kernel_size/1024); + printk("_asm_physmap = %llx\n", _asm_physmap); + +#define MBADDR(x) (PHY2VIRTP((paddr_t)(x))) + + /* get modules */ + if (mbinfo->mods_count > 0) { + void *mod; + struct multiboot_mod_list *modlist; + char *start; + int n; + + mod = MBADDR(mbinfo->mods_addr); + modlist = mod; + for (n=0;nmods_count;n++) { + char line[80]; + printk("Module: %s\n", MBADDR(modlist[n].cmdline)); + start = MBADDR(modlist[n].mod_start); + memcpy(line, start,80); + line[79] = 0; + printk("%s\n", line); + } + } + + mem_init(mbinfo); + + printk("mem.kend = 0x%llx\n", (uint64_t)memory.kend); + + vmem_test(); + + pci_init(); + init_smp(); + init_interrupts(); + init_timer(200); /* arg is timer tick interrupt Hz */ + /* klog isn't really useful before here */ + init_syscalls(); + init_tasking(); + + /* from here on out, we may be interrupted */ + init_keyboard(); + + while (1) { + schedule(); + /* since we're the current task when we call schedule, + * we won't get back on the runqueue. The 0 task + * will still be allocated. That's ok, it's a static + * structure in process.c anyway. + * If it changes to dynamic alloc, would want to + * clean it up + */ + printk("shouldn't happen\n"); + halt(); + } + + return; +} + +void klog(int level, const char *fmt, ...) { + va_list ap; + + printk("[%u.%u] ", system_time.tv_sec, system_time.tv_nsec/1000000); + + va_start(ap, fmt); + printkv(fmt, ap); + va_end(ap); +} + +void panic(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + printkv(fmt, ap); + va_end(ap); + + while (1) { + allstop(); + halt(); + } +} diff --git a/kernel.h b/kernel.h new file mode 100644 index 0000000..825f2d5 --- /dev/null +++ b/kernel.h @@ -0,0 +1,20 @@ +#ifndef KERNEL_H_ +#define KERNEL_H_ + +#include +#include +#include + +void terminal_putchar(int ch); +int printk(const char *fmt, ...); +void klog(int level, const char *fmt, ...); +void panic(const char *fmt, ...); +int printkv(const char *fmt, va_list ap); + +void *memmove(void *s1, const void *s2, size_t n); + +/* in bootz.s */ +void halt(); /* this will return after a ret, waitforinterrupt() might be better */ +void allstop(); + +#endif diff --git a/link64.ld b/link64.ld new file mode 100644 index 0000000..f70d97a --- /dev/null +++ b/link64.ld @@ -0,0 +1,70 @@ +KERNEL_VMA = 0xFFFFFFFF80000000 ; +KERNEL_LMA = 0x100000 ; + +ENTRY(_multiboot_entry) +SECTIONS +{ + . = KERNEL_LMA; + + .bootstrap : + { + boot32.o ( .multiboot ) + boot32.o (.text) + boot32.o (.data) + } + + . += KERNEL_VMA; /* += so that the code can just run, might be able to "org" the code */ + + .text : AT(ADDR(.text) - KERNEL_VMA) + { + _code = .; + *(EXCLUDE_FILE(*boot32.o) .text) + *(.rodata*) + . = ALIGN(4096); + } + + .data : AT(ADDR(.data) - KERNEL_VMA) + { + _data = .; + *(EXCLUDE_FILE(*boot32.o) .data) + . = ALIGN(8); + + _kernel_vma = .; + QUAD(KERNEL_VMA); + . += 8; + _kernel_end = .; + QUAD(KERNEL_END); + . += 8; + _kernel_phys_end = .; + QUAD(KERNEL_PHYS_END); + . += 8; + _kernel_size = .; + QUAD(KERNEL_SIZE); + . += 8; + + . = ALIGN(4096); + } + + .bss : AT(ADDR(.bss) - KERNEL_VMA) + { + _bss = .; + *(.bss) + + /* + * You usually need to include generated COMMON symbols + * under kernel BSS section or use gcc's -fno-common + */ + + *(COMMON) + . = ALIGN(4096); + } + + KERNEL_SIZE = . - KERNEL_VMA - KERNEL_LMA; + KERNEL_PHYS_END = . - KERNEL_VMA; + KERNEL_END = .; + + /DISCARD/ : + { + *(.comment) + } +} diff --git a/multiboot.h b/multiboot.h new file mode 100644 index 0000000..a05d402 --- /dev/null +++ b/multiboot.h @@ -0,0 +1,182 @@ +#ifndef MULTIBOOT_HEADER +#define MULTIBOOT_HEADER 1 + +/* How many bytes from the start of the file to search for the header. */ +#define MULTIBOOT_SEARCH 8192 + +/* the magic field should contain this. */ +#define MULTIBOOT_HEADER_MAGIC 0x1badb002 + +/* this should be in eax */ +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2badb002 + +/* bits in the required part of flags field we don't support */ +#define MULTIBOOT_UNSUPPORTED 0x0000fffc + +/* alignment of multiboot modules */ +#define MULTIBOOT_MOD_ALIGN 0x00001000 + +/* alignment of the multiboot info structure */ +#define MULTIBOOT_INFO_ALIGN 0x00000004 + +/* + * multiboot header flags + */ + +/* align each boot module on 4KB page boundary */ +#define MULTIBOOT_PAGE_ALIGN 0x00000001 + +/* pass memory information to OS */ +#define MULTIBOOT_MEMORY_INFO 0x00000002 + +/* pass video information to OS */ +#define MULTIBOOT_VIDEO_MODE 0x00000004 + +/* This flag indicates the use of the address fields in the header */ +#define MULTIBOOT_AOUT_KLUDGE 0x00010000 + +/* + * multiboot info flags + */ + +/* has basic memory information */ +#define MULTIBOOT_INFO_MEMORY 0x00000001 + +/* has boot device */ +#define MULTIBOOT_INFO_BOOTDEV 0x00000002 + +/* has command-line */ +#define MULTIBOOT_INFO_CMDLINE 0x00000004 + +/* has modules */ +#define MULTIBOOT_INFO_MODS 0x00000008 + + +/* only one of the next two should be set */ +/* has a.out symbol table */ +#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010 +/* has ELF section header table */ +#define MULTIBOOT_INFO_ELF_SHDR 0X00000020 + +/* has complete memory map */ +#define MULTIBOOT_INFO_MEM_MAP 0x00000040 + +/* has drive info */ +#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080 + +/* has config table */ +#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100 + +/* has boot loader name */ +#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200 + +/* has APM table */ +#define MULTIBOOT_INFO_APM_TABLE 0x00000400 + +/* has video information */ +#define MULTIBOOT_INFO_VIDEO_INFO 0x00000800 + +#include + +struct multiboot_header { + uint32_t magic; /* should == MULTIBOOT_MAGIC */ + + uint32_t flags; + + uint32_t checksum; /* magic + flags + checksum & 0xffffffff == 0 */ + + /* only valid if MULTIBOOT_AOUT_KLUDGE is set */ + uint32_t header_addr; + uint32_t load_addr; + uint32_t load_end_addr; + uint32_t bss_end_addr; + uint32_t entry_addr; + + /* only valid if MULTIBOOT_VIDEO_MODE is set */ + uint32_t mode_type; + uint32_t width; + uint32_t height; + uint32_t depth; +}; + +/* a.out symbol table */ +struct multiboot_aout_symbol_table { + uint32_t tabsize; + uint32_t strsize; + uint32_t addr; + uint32_t reserved; +}; + +/* ELF section header table */ +struct multiboot_elf_section_header_table { + uint32_t num; + uint32_t size; + uint32_t addr; + uint32_t shndx; +}; + +struct multiboot_info { + uint32_t flags; + + /* available memory from BIOS */ + uint32_t mem_lower; + uint32_t mem_upper; + + uint32_t boot_device; /* root partition */ + + uint32_t cmdline; /* kernel command line */ + + uint32_t mods_count; /* number of mods */ + uint32_t mods_addr; /* physical address of list */ + + union { + struct multiboot_aout_symbol_table aout_sym; + struct multiboot_elf_section_header_table elf_sec; + } u; + + /* memory map */ + uint32_t mmap_length; + uint32_t mmap_addr; + + /* drive info */ + uint32_t drives_length; + uint32_t drives_addr; + + /* ROM configuration table */ + uint32_t config_table; + + /* boot loader Name */ + uint32_t boot_loader_name; + + /* APM table */ + uint32_t apm_table; + + /* video information */ + uint32_t vbe_control_info; + uint32_t vbe_mode_info; + uint16_t vbe_mode; + uint16_t vbe_interface_seg; + uint16_t vbe_interface_off; + uint16_t vbe_interface_len; +}; + +#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 +struct multiboot_mmap_entry { + uint32_t size; + uint64_t addr; + uint64_t len; + uint32_t type; +} __attribute__((packed)); + +struct multiboot_mod_list { + /* memory used goes from mod_start through mod_end-1 */ + uint32_t mod_start; + uint32_t mod_end; + + uint32_t cmdline; + + uint32_t padding; /* each entry is 16 bytes */ +}; + +#endif -- 2.40.0