diff --git a/arch/Makefile b/arch/Makefile index d7540a4..5748167 100644 --- a/arch/Makefile +++ b/arch/Makefile @@ -12,7 +12,7 @@ $(TARGET_ISO): clean $(kernel_target) $(HIDE)mkdir -p build_dir/boot/grub $(HIDE)cp $(kernel_target) build_dir/boot - $(HIDE)echo 'set timeout=1' > build_dir/boot/grub/grub.cfg + $(HIDE)echo 'set timeout=0' > build_dir/boot/grub/grub.cfg $(HIDE)echo 'set default=0' >> build_dir/boot/grub/grub.cfg $(HIDE)echo 'menuentry "HelloOS" {' >> build_dir/boot/grub/grub.cfg $(HIDE)echo ' multiboot2 /boot/kernel.elf "HelloOS"' >> build_dir/boot/grub/grub.cfg diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c new file mode 100644 index 0000000..3794a8c --- /dev/null +++ b/arch/x86/kernel/e820.c @@ -0,0 +1,85 @@ +#include +#include + +#include +#include + +struct e820map e820; + +static void early_panic(char *msg) { + early_printk(msg); + early_printk("\npanic in e820"); + __asm__("hlt"); +} + +static void e820_print_map(char *who) { + int i; + + for (i = 0; i < e820.nr_map; i++) { + printk(KERN_INFO " %s: %016Lx - %016Lx ", who, + (unsigned long long) e820.map[i].addr, + (unsigned long long) + (e820.map[i].addr + e820.map[i].size)); + switch (e820.map[i].type) { + case E820_RAM: + printk(KERN_CONT "(usable)\n"); + break; + case E820_RESERVED: + printk(KERN_CONT "(reserved)\n"); + break; + case E820_ACPI: + printk(KERN_CONT "(ACPI data)\n"); + break; + case E820_NVS: + printk(KERN_CONT "(ACPI NVS)\n"); + break; + default: + printk(KERN_CONT "type %u\n", e820.map[i].type); + break; + } + } +} + +static int copy_e820_map(struct e820entry *biosmap, int nr_map) { + if (nr_map < 2) { + return -1; + } + + do { + uint64_t start = biosmap->addr; + uint64_t size = biosmap->size; + uint64_t end = start + size; + uint32_t type = biosmap->type; + + /* Overflow in 64 bits? Ignore the memory map. */ + if (start > end) + return -1; + int x = e820.nr_map; + + if (x == E820MAX) { + printk(KERN_ERR "Ooops! Too many entries in the memory map!\n"); + return; + } + + e820.map[x].addr = start; + e820.map[x].size = size; + e820.map[x].type = type; + e820.nr_map++; + } while (biosmap++, --nr_map); + return 0; +} + +char *machine_specific_memory_setup() { + char *who = "BIOS-e820"; + + // e820 数组中,可能存在某些内存段重复,需要将重复的部分分离; + // 而我们暂不处理这种情况,认为 multiboot2 中的内存段不存在重复。 + // 复制 e820 信息 + if (copy_e820_map(boot_params.e820_map, boot_params.e820_entries) < 0) { + early_panic("Cannot find a valid memory map"); + } + printk(KERN_INFO "BIOS-provided physical RAM map:\n"); + + e820_print_map(who); + return who; +} \ No newline at end of file diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index ddf7ced..e0bed19 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -4,17 +4,53 @@ #include #include +#include +#include + +extern uint64_t mb2_info; + void clear_bss() { memset(__bss_start, 0, (unsigned long) __bss_stop - (unsigned long) __bss_start); } +static void mem_info(struct multiboot_tag *tag) { + struct multiboot_tag_mmap *mmap = (struct multiboot_tag_mmap*) tag; + struct multiboot_mmap_entry *entry = mmap->entries; -void x86_64_start_kernel() { - early_printk("x86_64_start_kernel running..."); + uint32_t i = 0; + while ((uint8_t*)entry < (uint8_t*)mmap + mmap->size) { + boot_params.e820_map[i].addr = entry->addr; + boot_params.e820_map[i].size = entry->len; + boot_params.e820_map[i].type = entry->type; + + i++; + entry = (struct multiboot_mmap_entry*)((uint8_t*)entry + mmap->entry_size); + } + boot_params.e820_entries = i; +} + +void parse_sys_info() { + struct multiboot_tag *tag; + for (tag = (struct multiboot_tag*)(mb2_info + MULTIBOOT_TAG_ALIGN); + tag->type != MULTIBOOT_TAG_TYPE_END; + tag = (struct multiboot_tag*)((multiboot_uint8_t *)tag + ((tag->size + 7) & ~7))) { + switch (tag->type) { + case MULTIBOOT_TAG_TYPE_MMAP: + mem_info(tag); + break; + default: + break; + } + } +} +void x86_64_start_kernel() { + early_printk("x86_64_start_kernel running\n"); // bss 段清零 clear_bss(); + // 解析系统信息 + parse_sys_info(); start_kernel(); } \ No newline at end of file diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 693a86e..ce9c57a 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -8,6 +8,8 @@ .global startup_64 .extern print startup_64: + mov %ebx, mb2_info + /* 开启 PAE */ movl %cr4, %eax btsl $5, %eax @@ -63,6 +65,8 @@ secondary_startup_64: ENTRY(init_rsp) .quad init_thread_union+THREAD_SIZE-8 +ENTRY(mb2_info) + .quad 0x00 .text .code64 diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c new file mode 100644 index 0000000..3248a1f --- /dev/null +++ b/arch/x86/kernel/setup.c @@ -0,0 +1,13 @@ +#include + +#include + +struct boot_params boot_params; + +void memory_setup() { + machine_specific_memory_setup(); +} + +void setup_arch() { + memory_setup(); +} \ No newline at end of file diff --git a/include/asm/bootparam.h b/include/asm/bootparam.h new file mode 100644 index 0000000..aeb0e95 --- /dev/null +++ b/include/asm/bootparam.h @@ -0,0 +1,13 @@ +#ifndef _ASM_X86_BOOTPARAM_H +#define _ASM_X86_BOOTPARAM_H + +#include + +struct boot_params { + __u32 e820_entries; + struct e820entry e820_map[E820MAX]; +}; + +extern struct boot_params boot_params; + +#endif \ No newline at end of file diff --git a/include/asm/desc.h b/include/asm/desc.h new file mode 100644 index 0000000..1b8d22d --- /dev/null +++ b/include/asm/desc.h @@ -0,0 +1,67 @@ +#ifndef _ASM_X86_DESC_H +#define _ASM_X86_DESC_H + +#include +#include + +#include + +#define PTR_LOW(x) ((unsigned long long)(x) & 0xFFFF) +#define PTR_MIDDLE(x) (((unsigned long long)(x) >> 16) & 0xFFFF) +#define PTR_HIGH(x) ((unsigned long long)(x) >> 32) + +extern gate_desc idt_table[]; + +struct gate_struct64 { + uint16_t offset_low; + uint16_t segment; + unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1; + uint16_t offset_middle; + uint32_t offset_high; + uint32_t zero1; +} __attribute__((packed)); + +typedef struct gate_struct64 gate_desc; + +enum { + GATE_INTERRUPT = 0xE, + GATE_TRAP = 0xF, + GATE_CALL = 0xC, + GATE_TASK = 0x5, +}; + +static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func, + unsigned dpl, unsigned ist, unsigned seg) { + gate->offset_low = PTR_LOW(func); + gate->segment = __KERNEL_CS; + gate->ist = ist; + gate->p = 1; + gate->dpl = dpl; + gate->zero0 = 0; + gate->zero1 = 0; + gate->type = type; + gate->offset_middle = PTR_MIDDLE(func); + gate->offset_high = PTR_HIGH(func); +} + +static inline void write_idt_entry(gate_desc *idt, int entry, + const gate_desc *gate) { + memcpy(&idt[entry], gate, sizeof(*gate)); +} + +static inline void _set_gate(int gate, unsigned type, void *addr, + unsigned dpl, unsigned ist, unsigned seg) { + gate_desc s; + pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg); + /* + * does not need to be atomic because it is only done once at + * setup time + */ + write_idt_entry(idt_table, gate, &s); +} + +static inline void set_intr_gate(unsigned int n, void *addr) { + _set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS); +} + +#endif \ No newline at end of file diff --git a/include/asm/e820.h b/include/asm/e820.h index af9daf6..204d0f3 100644 --- a/include/asm/e820.h +++ b/include/asm/e820.h @@ -3,12 +3,23 @@ #include +#define E820MAX 128 + +#define E820_RAM 1 +#define E820_RESERVED 2 +#define E820_ACPI 3 +#define E820_NVS 4 + struct e820entry { __u64 addr; /* start of memory segment */ __u64 size; /* size of memory segment */ __u32 type; /* type of memory segment */ } __attribute__((packed)); +struct e820map { + __u32 nr_map; + struct e820entry map[E820MAX]; +}; - +extern struct e820map e820; #endif \ No newline at end of file diff --git a/include/asm/page.h b/include/asm/page.h index 6f09b7a..9b01070 100644 --- a/include/asm/page.h +++ b/include/asm/page.h @@ -29,6 +29,8 @@ #define KERNEL_IMAGE_SIZE (512 * 1024 * 1024) #define KERNEL_IMAGE_START _AC(0xffffffff80000000, UL) +#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) +#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) #endif \ No newline at end of file diff --git a/include/asm/setup.h b/include/asm/setup.h new file mode 100644 index 0000000..073dbc1 --- /dev/null +++ b/include/asm/setup.h @@ -0,0 +1,6 @@ +#ifndef _ASM_X86_SETUP_H +#define _ASM_X86_SETUP_H + +char *machine_specific_memory_setup(); + +#endif \ No newline at end of file diff --git a/include/os/init.h b/include/os/init.h new file mode 100644 index 0000000..71091c6 --- /dev/null +++ b/include/os/init.h @@ -0,0 +1,7 @@ +#ifndef _OS_INIT_H +#define _OS_INIT_H + +void setup_arch(); + + +#endif \ No newline at end of file diff --git a/include/os/kernel.h b/include/os/kernel.h index 75f4d10..c5d4a2c 100644 --- a/include/os/kernel.h +++ b/include/os/kernel.h @@ -4,6 +4,17 @@ #include #include +#define KERN_EMERG "<0>" /* system is unusable */ +#define KERN_ALERT "<1>" /* action must be taken immediately */ +#define KERN_CRIT "<2>" /* critical conditions */ +#define KERN_ERR "<3>" /* error conditions */ +#define KERN_WARNING "<4>" /* warning conditions */ +#define KERN_NOTICE "<5>" /* normal but significant condition */ +#define KERN_INFO "<6>" /* informational */ +#define KERN_DEBUG "<7>" /* debug-level messages */ + +#define KERN_CONT "" + extern void __attribute__((format(printf, 1, 2))) early_printk(const char *fmt, ...); @@ -13,4 +24,10 @@ extern int vscnprintf(char *buf, size_t size, const char *fmt, va_list args) extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) __attribute__ ((format (printf, 3, 0))); +// extern int printk(const char * fmt, ...) +// __attribute__((format (printf, 1, 2))); +#define printk(...) { \ + early_printk(__VA_ARGS__); \ +} + #endif \ No newline at end of file diff --git a/include/os/string.h b/include/os/string.h index 4da1697..fb6a359 100644 --- a/include/os/string.h +++ b/include/os/string.h @@ -10,4 +10,8 @@ extern void *memset(void *,int,__kernel_size_t); extern __kernel_size_t strnlen(const char *,__kernel_size_t); #endif +#ifndef __HAVE_ARCH_MEMCPY +extern void* memcpy(void *dest, const void *src, size_t count); +#endif + #endif \ No newline at end of file diff --git a/init/main.c b/init/main.c index a58d037..1ebda6f 100644 --- a/init/main.c +++ b/init/main.c @@ -1,6 +1,9 @@ - +#include void start_kernel() { + + setup_arch(); + __asm__ __volatile__("hlt"); } diff --git a/kernel/printk.c b/kernel/printk.c index e69de29..ccf8815 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/lib/string.c b/lib/string.c index d632864..c9ac804 100644 --- a/lib/string.c +++ b/lib/string.c @@ -18,4 +18,16 @@ __kernel_size_t strnlen(const char *s, __kernel_size_t count) { /* nothing */; return sc - s; } +#endif + +#ifndef __HAVE_ARCH_MEMCPY +void *memcpy(void *dest, const void *src, size_t count) +{ + char *tmp = dest; + const char *s = src; + + while (count--) + *tmp++ = *s++; + return dest; +} #endif \ No newline at end of file