]> pd.if.org Git - zos/commitdiff
kernel startup and linker script
authorNathan Wagner <nw@hydaspes.if.org>
Tue, 25 Oct 2016 01:36:32 +0000 (20:36 -0500)
committerNathan Wagner <nw@hydaspes.if.org>
Tue, 25 Oct 2016 04:00:24 +0000 (23:00 -0500)
kernel.c [new file with mode: 0644]
kernel.h [new file with mode: 0644]
link64.ld [new file with mode: 0644]
multiboot.h [new file with mode: 0644]

diff --git a/kernel.c b/kernel.c
new file mode 100644 (file)
index 0000000..aed3d72
--- /dev/null
+++ b/kernel.c
@@ -0,0 +1,130 @@
+#include <stddef.h>
+#include <stdint.h>
+#include <time.h>
+
+#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 <smp.h>
+#include <syscall.h>
+
+#include <string.h>
+
+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;n<mbinfo->mods_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 (file)
index 0000000..825f2d5
--- /dev/null
+++ b/kernel.h
@@ -0,0 +1,20 @@
+#ifndef KERNEL_H_
+#define KERNEL_H_
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <stddef.h>
+
+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 (file)
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 (file)
index 0000000..a05d402
--- /dev/null
@@ -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 <stdint.h>
+
+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