Reorganize the whole thing
This commit is contained in:
parent
89f9b74a83
commit
9e30bc0315
34
src/arch/amd64/gdt.S
Normal file
34
src/arch/amd64/gdt.S
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright (c) 2018 Pierre Pronchery <khorben@defora.org> */
|
||||||
|
/* This file is part of DeforaOS uKernel */
|
||||||
|
/* Originally from https://wiki.osdev.org/Bare_Bones */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* text */
|
||||||
|
.section .text
|
||||||
|
/* arch_setgdt */
|
||||||
|
.global __arch_setgdt
|
||||||
|
.type __arch_setgdt,function
|
||||||
|
__arch_setgdt:
|
||||||
|
#if 0
|
||||||
|
lea gdt_descriptor, %rcx
|
||||||
|
#else
|
||||||
|
mov (gdt_descriptor), %rcx
|
||||||
|
#endif
|
||||||
|
/* set the offset of the GDT */
|
||||||
|
mov %rsi, 0x2(%rcx)
|
||||||
|
/* set the size of the GDT */
|
||||||
|
dec %rdi
|
||||||
|
mov %di, (%rcx)
|
||||||
|
/* load the GDT */
|
||||||
|
lgdt (%rcx)
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
/* bss */
|
||||||
|
.section .bss
|
||||||
|
.align 16
|
||||||
|
gdt_descriptor:
|
||||||
|
.skip 2 /* size */
|
||||||
|
.skip 4 /* offset */
|
17
src/arch/amd64/gdt.h
Normal file
17
src/arch/amd64/gdt.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright (c) 2018 Pierre Pronchery <khorben@defora.org> */
|
||||||
|
/* This file is part of DeforaOS uKernel */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef UKERNEL_ARCH_AMD64_GDT_H
|
||||||
|
# define UKERNEL_ARCH_AMD64_GDT_H
|
||||||
|
|
||||||
|
# include "../i386/gdt.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* public */
|
||||||
|
/* prototypes */
|
||||||
|
int _arch_setgdt64(GDT const * gdt, size_t count);
|
||||||
|
|
||||||
|
#endif /* !UKERNEL_ARCH_I386_GDT_H */
|
|
@ -5,6 +5,10 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "../i386/multiboot/header.S"
|
||||||
|
#include "../i386/idt.S"
|
||||||
|
|
||||||
|
|
||||||
/* sections */
|
/* sections */
|
||||||
/* bss */
|
/* bss */
|
||||||
.section .bss
|
.section .bss
|
||||||
|
@ -26,6 +30,14 @@ _exit:
|
||||||
jmp 1b
|
jmp 1b
|
||||||
|
|
||||||
|
|
||||||
|
/* setidt */
|
||||||
|
.global _setidt
|
||||||
|
.type _setidt,function
|
||||||
|
_setidt:
|
||||||
|
lidt (idt)
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
/* start */
|
/* start */
|
||||||
.global _start
|
.global _start
|
||||||
.type _start, @function
|
.type _start, @function
|
||||||
|
@ -45,6 +57,11 @@ _start:
|
||||||
/* call the global constructors */
|
/* call the global constructors */
|
||||||
call _init
|
call _init
|
||||||
|
|
||||||
|
/* set the interrupt descriptor */
|
||||||
|
call _setidt
|
||||||
|
|
||||||
|
/* FIXME setup paging */
|
||||||
|
|
||||||
/* start the kernel */
|
/* start the kernel */
|
||||||
xor %rdi, %rdi
|
xor %rdi, %rdi
|
||||||
call main
|
call main
|
||||||
|
|
36
src/arch/i386/gdt.S
Normal file
36
src/arch/i386/gdt.S
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright (c) 2018 Pierre Pronchery <khorben@defora.org> */
|
||||||
|
/* This file is part of DeforaOS uKernel */
|
||||||
|
/* Originally from https://wiki.osdev.org/Bare_Bones */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* text */
|
||||||
|
.section .text
|
||||||
|
/* arch_setgdt */
|
||||||
|
.global __arch_setgdt
|
||||||
|
.type __arch_setgdt,function
|
||||||
|
__arch_setgdt:
|
||||||
|
#if 0
|
||||||
|
lea gdt_descriptor, %ecx
|
||||||
|
#else
|
||||||
|
mov (gdt_descriptor), %ecx
|
||||||
|
#endif
|
||||||
|
/* set the offset of the GDT */
|
||||||
|
mov 0x4(%esp), %eax
|
||||||
|
mov %eax, 0x2(%ecx)
|
||||||
|
/* set the size of the GDT */
|
||||||
|
mov 0x8(%esp), %eax
|
||||||
|
dec %eax
|
||||||
|
mov %ax, (%ecx)
|
||||||
|
/* load the GDT */
|
||||||
|
lgdt (%ecx)
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
/* bss */
|
||||||
|
.section .bss
|
||||||
|
.align 16
|
||||||
|
gdt_descriptor:
|
||||||
|
.skip 2 /* size */
|
||||||
|
.skip 4 /* offset */
|
27
src/arch/i386/gdt.h
Normal file
27
src/arch/i386/gdt.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright (c) 2018 Pierre Pronchery <khorben@defora.org> */
|
||||||
|
/* This file is part of DeforaOS uKernel */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef UKERNEL_ARCH_I386_GDT_H
|
||||||
|
# define UKERNEL_ARCH_I386_GDT_H
|
||||||
|
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* public */
|
||||||
|
/* types */
|
||||||
|
typedef struct _GDT
|
||||||
|
{
|
||||||
|
vaddr_t base;
|
||||||
|
vaddr_t limit;
|
||||||
|
uint8_t type;
|
||||||
|
} GDT;
|
||||||
|
|
||||||
|
|
||||||
|
/* prototypes */
|
||||||
|
int _arch_setgdt(GDT const * gdt, size_t count);
|
||||||
|
|
||||||
|
#endif /* !UKERNEL_ARCH_I386_GDT_H */
|
23
src/arch/i386/idt.S
Normal file
23
src/arch/i386/idt.S
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright (c) 2018 Pierre Pronchery <khorben@defora.org> */
|
||||||
|
/* This file is part of DeforaOS uKernel */
|
||||||
|
/* Originally from https://wiki.osdev.org/Bare_Bones */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* text */
|
||||||
|
.section .text
|
||||||
|
/* arch_setidt */
|
||||||
|
.global __arch_setidt
|
||||||
|
.type __arch_setidt,function
|
||||||
|
__arch_setidt:
|
||||||
|
lidt (idt)
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
/* bss */
|
||||||
|
.section .bss
|
||||||
|
.align 16
|
||||||
|
idt:
|
||||||
|
.short 0x0 /* size */
|
||||||
|
.long 0x0 /* offset */
|
15
src/arch/i386/idt.h
Normal file
15
src/arch/i386/idt.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright (c) 2018 Pierre Pronchery <khorben@defora.org> */
|
||||||
|
/* This file is part of DeforaOS uKernel */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef UKERNEL_ARCH_I386_IDT_H
|
||||||
|
# define UKERNEL_ARCH_I386_IDT_H
|
||||||
|
|
||||||
|
|
||||||
|
/* public */
|
||||||
|
/* prototypes */
|
||||||
|
int _arch_setidt(void);
|
||||||
|
|
||||||
|
#endif /* !UKERNEL_ARCH_I386_IDT_H */
|
|
@ -5,22 +5,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* variables */
|
#include "multiboot.S"
|
||||||
#define ALIGN (1 << 0) /* align the modules loaded on */
|
|
||||||
/* page boundaries */
|
|
||||||
#define MEMINFO (1 << 1) /* provide the memory map */
|
|
||||||
#define FLAGS ALIGN | MEMINFO /* multiboot flags */
|
|
||||||
#define MAGIC 0x1badb002 /* magic number */
|
|
||||||
#define CHECKSUM -(MAGIC + FLAGS) /* checksum for the above */
|
|
||||||
|
|
||||||
|
|
||||||
/* sections */
|
|
||||||
/* multiboot */
|
|
||||||
.section .multiboot
|
|
||||||
.align 4
|
|
||||||
.long MAGIC
|
|
||||||
.long FLAGS
|
|
||||||
.long CHECKSUM
|
|
||||||
|
|
||||||
|
|
||||||
/* bss */
|
/* bss */
|
||||||
|
@ -54,6 +39,8 @@ _start:
|
||||||
mov $stack_top, %esp
|
mov $stack_top, %esp
|
||||||
xor %ebp, %ebp
|
xor %ebp, %ebp
|
||||||
|
|
||||||
|
push %eax
|
||||||
|
|
||||||
#if defined(__SSP__)
|
#if defined(__SSP__)
|
||||||
/* initialize SSP */
|
/* initialize SSP */
|
||||||
call __stack_chk_setup
|
call __stack_chk_setup
|
||||||
|
@ -62,8 +49,16 @@ _start:
|
||||||
/* call the global constructors */
|
/* call the global constructors */
|
||||||
call _init
|
call _init
|
||||||
|
|
||||||
/* start the kernel */
|
/* detect multiboot */
|
||||||
|
pop %eax
|
||||||
|
cmp $MAGIC2, %eax
|
||||||
|
jne 1f
|
||||||
push %ebx
|
push %ebx
|
||||||
|
call multiboot
|
||||||
|
1:
|
||||||
|
|
||||||
|
/* start the kernel */
|
||||||
|
push $0x0
|
||||||
call main
|
call main
|
||||||
add $0x4, %esp
|
add $0x4, %esp
|
||||||
|
|
||||||
|
|
|
@ -5,22 +5,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* variables */
|
#include "multiboot.S"
|
||||||
#define ALIGN (1 << 0) /* align the modules loaded on */
|
|
||||||
/* page boundaries */
|
|
||||||
#define MEMINFO (1 << 1) /* provide the memory map */
|
|
||||||
#define FLAGS ALIGN | MEMINFO /* multiboot flags */
|
|
||||||
#define MAGIC 0x1badb002 /* magic number */
|
|
||||||
#define CHECKSUM -(MAGIC + FLAGS) /* checksum for the above */
|
|
||||||
|
|
||||||
|
|
||||||
/* sections */
|
|
||||||
/* multiboot */
|
|
||||||
.section .multiboot
|
|
||||||
.align 4
|
|
||||||
.long MAGIC
|
|
||||||
.long FLAGS
|
|
||||||
.long CHECKSUM
|
|
||||||
|
|
||||||
|
|
||||||
/* bss */
|
/* bss */
|
||||||
|
@ -31,12 +16,6 @@ stack_bottom:
|
||||||
stack_top:
|
stack_top:
|
||||||
|
|
||||||
|
|
||||||
/* data */
|
|
||||||
.section .data
|
|
||||||
k_ptr:
|
|
||||||
.long 0x0
|
|
||||||
|
|
||||||
|
|
||||||
/* text */
|
/* text */
|
||||||
.section .text
|
.section .text
|
||||||
/* exit */
|
/* exit */
|
||||||
|
@ -49,75 +28,6 @@ _exit:
|
||||||
jmp 1b
|
jmp 1b
|
||||||
|
|
||||||
|
|
||||||
.global _kernel32
|
|
||||||
.type _kernel32,function
|
|
||||||
_kernel32:
|
|
||||||
/* jump into the 32-bit kernel */
|
|
||||||
mov 0x4(%esp), %ebx
|
|
||||||
mov 0x8(%esp), %eax
|
|
||||||
call *%eax
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
.global _kernel64
|
|
||||||
.type _kernel64,function
|
|
||||||
_kernel64:
|
|
||||||
/* check for 64-bit capability */
|
|
||||||
pushf
|
|
||||||
pop %eax
|
|
||||||
mov %eax, %ecx
|
|
||||||
xor $0x00200000, %eax
|
|
||||||
push %eax
|
|
||||||
popf
|
|
||||||
pushf
|
|
||||||
pop %eax
|
|
||||||
cmp %ecx, %eax
|
|
||||||
jz 1f /* CPUID is not supported */
|
|
||||||
push %ebx
|
|
||||||
mov $0x80000001, %eax
|
|
||||||
cpuid
|
|
||||||
pop %ebx
|
|
||||||
cmp $0x80000000, %eax
|
|
||||||
jl 1f /* 64-bit mode is not supported */
|
|
||||||
|
|
||||||
/* jump into the 64-bit kernel */
|
|
||||||
mov 0x8(%esp), %esi
|
|
||||||
mov %esi, (k_ptr)
|
|
||||||
|
|
||||||
lgdt (_gdt64)
|
|
||||||
|
|
||||||
mov _gdt64_data, %ax
|
|
||||||
mov %ax, %ss
|
|
||||||
mov %ax, %ds
|
|
||||||
mov %ax, %es
|
|
||||||
jmp _gdt64_code
|
|
||||||
.jmp_k:
|
|
||||||
mov 0x4(%esp), %edi
|
|
||||||
mov k_ptr, %eax
|
|
||||||
.long 0x0
|
|
||||||
jmp *%eax
|
|
||||||
|
|
||||||
1:
|
|
||||||
mov $-1, %eax
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
.global _setgdt
|
|
||||||
.type _setgdt,function
|
|
||||||
_setgdt:
|
|
||||||
lea gdt_descriptor, %ecx
|
|
||||||
/* set the offset of the GDT */
|
|
||||||
mov 0x4(%esp), %eax
|
|
||||||
mov %eax, 0x2(%ecx)
|
|
||||||
/* set the size of the GDT */
|
|
||||||
mov 0x8(%esp), %eax
|
|
||||||
dec %eax
|
|
||||||
mov %ax, (%ecx)
|
|
||||||
/* load the GDT */
|
|
||||||
lgdt (%ecx)
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
/* start */
|
/* start */
|
||||||
.global _start
|
.global _start
|
||||||
.type _start, @function
|
.type _start, @function
|
||||||
|
@ -127,6 +37,8 @@ _start:
|
||||||
|
|
||||||
/* initialize the stack */
|
/* initialize the stack */
|
||||||
mov $stack_top, %esp
|
mov $stack_top, %esp
|
||||||
|
xor %ebp, %ebp
|
||||||
|
push %eax
|
||||||
|
|
||||||
#if defined(__SSP__)
|
#if defined(__SSP__)
|
||||||
/* initialize SSP */
|
/* initialize SSP */
|
||||||
|
@ -136,10 +48,19 @@ _start:
|
||||||
/* call the global constructors */
|
/* call the global constructors */
|
||||||
call _init
|
call _init
|
||||||
|
|
||||||
/* start the loader */
|
/* detect multiboot */
|
||||||
|
pop %eax
|
||||||
|
cmp $MAGIC2, %eax
|
||||||
|
jne 1f
|
||||||
push %ebx
|
push %ebx
|
||||||
|
call multiboot
|
||||||
|
1:
|
||||||
|
|
||||||
|
/* start the loader */
|
||||||
|
push $0x0
|
||||||
|
push $0x0
|
||||||
call main
|
call main
|
||||||
add $0x4, %esp
|
add $0x8, %esp
|
||||||
|
|
||||||
/* exit the kernel */
|
/* exit the kernel */
|
||||||
call _exit
|
call _exit
|
||||||
|
@ -147,10 +68,3 @@ _start:
|
||||||
hlt
|
hlt
|
||||||
|
|
||||||
.size _start, . - _start
|
.size _start, . - _start
|
||||||
|
|
||||||
|
|
||||||
.section .bss
|
|
||||||
.align 16
|
|
||||||
gdt_descriptor:
|
|
||||||
.skip 2 /* size */
|
|
||||||
.skip 4 /* offset */
|
|
||||||
|
|
81
src/arch/i386/multiboot.S
Normal file
81
src/arch/i386/multiboot.S
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright (c) 2018 Pierre Pronchery <khorben@defora.org> */
|
||||||
|
/* This file is part of DeforaOS uKernel */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "multiboot/header.S"
|
||||||
|
|
||||||
|
|
||||||
|
/* sections */
|
||||||
|
/* data */
|
||||||
|
.section .data
|
||||||
|
k_ptr:
|
||||||
|
.long 0x0
|
||||||
|
|
||||||
|
|
||||||
|
/* text */
|
||||||
|
/* multiboot_boot_kernel32 */
|
||||||
|
.global multiboot_boot_kernel32
|
||||||
|
.type multiboot_boot_kernel32,function
|
||||||
|
multiboot_boot_kernel32:
|
||||||
|
/* jump into the 32-bit kernel */
|
||||||
|
#if 0
|
||||||
|
mov 0x4(%esp), %ebx
|
||||||
|
mov 0x8(%esp), %eax
|
||||||
|
call *%eax
|
||||||
|
ret
|
||||||
|
#else
|
||||||
|
push %ebp
|
||||||
|
mov %esp, %ebp
|
||||||
|
|
||||||
|
mov 0x8(%ebp), %ebx
|
||||||
|
mov 0xc(%ebp), %eax
|
||||||
|
jmp *%eax
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
.global multiboot_boot_kernel64
|
||||||
|
.type multiboot_boot_kernel64,function
|
||||||
|
multiboot_boot_kernel64:
|
||||||
|
/* check for 64-bit capability */
|
||||||
|
pushf
|
||||||
|
pop %eax
|
||||||
|
mov %eax, %ecx
|
||||||
|
xor $0x00200000, %eax
|
||||||
|
push %eax
|
||||||
|
popf
|
||||||
|
pushf
|
||||||
|
pop %eax
|
||||||
|
cmp %ecx, %eax
|
||||||
|
jz 1f /* CPUID is not supported */
|
||||||
|
push %ebx
|
||||||
|
mov $0x80000001, %eax
|
||||||
|
cpuid
|
||||||
|
pop %ebx
|
||||||
|
cmp $0x80000000, %eax
|
||||||
|
jl 1f /* 64-bit mode is not supported */
|
||||||
|
|
||||||
|
/* jump into the 64-bit kernel */
|
||||||
|
mov 0x8(%esp), %esi
|
||||||
|
mov %esi, (k_ptr)
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
lgdt (_gdt64)
|
||||||
|
|
||||||
|
mov _gdt64_data, %ax
|
||||||
|
mov %ax, %ss
|
||||||
|
mov %ax, %ds
|
||||||
|
mov %ax, %es
|
||||||
|
jmp _gdt64_code
|
||||||
|
.jmp_k:
|
||||||
|
mov 0x4(%esp), %edi
|
||||||
|
mov k_ptr, %eax
|
||||||
|
.long 0x0
|
||||||
|
jmp *%eax
|
||||||
|
#endif
|
||||||
|
|
||||||
|
1:
|
||||||
|
mov $-1, %eax
|
||||||
|
ret
|
23
src/arch/i386/multiboot/header.S
Normal file
23
src/arch/i386/multiboot/header.S
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright (c) 2018 Pierre Pronchery <khorben@defora.org> */
|
||||||
|
/* This file is part of DeforaOS uKernel */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* variables */
|
||||||
|
#define ALIGN (1 << 0) /* align the modules loaded on */
|
||||||
|
/* page boundaries */
|
||||||
|
#define MEMINFO (1 << 1) /* provide the memory map */
|
||||||
|
#define FLAGS ALIGN | MEMINFO /* multiboot flags */
|
||||||
|
#define MAGIC1 0x1badb002 /* magic number */
|
||||||
|
#define MAGIC2 0x2badb002 /* magic number */
|
||||||
|
#define CHECKSUM -(MAGIC1 + FLAGS) /* checksum for the above */
|
||||||
|
|
||||||
|
|
||||||
|
/* sections */
|
||||||
|
/* multiboot */
|
||||||
|
.section .multiboot
|
||||||
|
.align 4
|
||||||
|
.long MAGIC1
|
||||||
|
.long FLAGS
|
||||||
|
.long CHECKSUM
|
|
@ -1 +1 @@
|
||||||
dist=Makefile,arch.h,crti.S,crtn.S,kernel.S,ioport.S,loader.S,uKernel.ld
|
dist=Makefile,arch.h,crti.S,crtn.S,gdt.S,idt.S,kernel.S,ioport.S,loader.S,uKernel.ld
|
||||||
|
|
116
src/drivers/boot/multiboot.c
Normal file
116
src/drivers/boot/multiboot.c
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright (c) 2018 Pierre Pronchery <khorben@defora.org> */
|
||||||
|
/* This file is part of DeforaOS uKernel */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
|
# include <stdint.h>
|
||||||
|
# include <stdio.h>
|
||||||
|
# include <string.h>
|
||||||
|
# include <elf.h>
|
||||||
|
# include "arch/amd64/gdt.h"
|
||||||
|
# include "arch/i386/gdt.h"
|
||||||
|
# include "drivers/boot/multiboot.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* private */
|
||||||
|
/* prototypes */
|
||||||
|
extern int _kernel32(ukMultibootInfo * mi, vaddr_t entrypoint);
|
||||||
|
extern int _kernel64(ukMultibootInfo * mi, vaddr_t entrypoint);
|
||||||
|
|
||||||
|
|
||||||
|
/* public */
|
||||||
|
/* functions */
|
||||||
|
/* multiboot_load_module */
|
||||||
|
static int _load_module32(ukMultibootMod * mod, vaddr_t * entrypoint,
|
||||||
|
Elf32_Ehdr * ehdr);
|
||||||
|
static int _load_module64(ukMultibootMod * mod, vaddr_t * entrypoint,
|
||||||
|
Elf64_Ehdr * ehdr);
|
||||||
|
|
||||||
|
int multiboot_load_module(ukMultibootMod * mod, unsigned char * elfclass,
|
||||||
|
vaddr_t * entrypoint)
|
||||||
|
{
|
||||||
|
Elf32_Ehdr * ehdr;
|
||||||
|
|
||||||
|
if(mod->end < mod->start || mod->end - mod->start < sizeof(ehdr))
|
||||||
|
{
|
||||||
|
puts("Could not load module: Invalid format");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ehdr = (Elf32_Ehdr *)mod->start;
|
||||||
|
if(elfclass != NULL)
|
||||||
|
*elfclass = ehdr->e_ident[EI_CLASS];
|
||||||
|
switch(ehdr->e_ident[EI_CLASS])
|
||||||
|
{
|
||||||
|
case ELFCLASS32:
|
||||||
|
return _load_module32(mod, entrypoint, ehdr);
|
||||||
|
case ELFCLASS64:
|
||||||
|
return _load_module64(mod, entrypoint,
|
||||||
|
(Elf64_Ehdr *)ehdr);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _load_module32(ukMultibootMod * mod, vaddr_t * entrypoint,
|
||||||
|
Elf32_Ehdr * ehdr)
|
||||||
|
{
|
||||||
|
Elf32_Phdr * phdr;
|
||||||
|
Elf32_Half i;
|
||||||
|
|
||||||
|
if(mod->start + ehdr->e_phoff + (ehdr->e_phnum * sizeof(*phdr))
|
||||||
|
> mod->end)
|
||||||
|
{
|
||||||
|
puts("Could not load 32-bit module: Invalid format");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
phdr = (Elf32_Phdr *)(mod->start + ehdr->e_phoff);
|
||||||
|
for(i = 0; i < ehdr->e_phnum; i++)
|
||||||
|
{
|
||||||
|
if(phdr[i].p_type != PT_LOAD)
|
||||||
|
continue;
|
||||||
|
if(phdr[i].p_vaddr > ehdr->e_entry
|
||||||
|
|| phdr[i].p_vaddr + phdr[i].p_filesz
|
||||||
|
<= ehdr->e_entry)
|
||||||
|
continue;
|
||||||
|
if(entrypoint != NULL)
|
||||||
|
*entrypoint = mod->start + ehdr->e_entry
|
||||||
|
- phdr[i].p_vaddr + phdr[i].p_offset;
|
||||||
|
/* FIXME really look for main() directly? */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
puts("Could not load 32-bit module: Invalid entrypoint");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _load_module64(ukMultibootMod * mod, vaddr_t * entrypoint,
|
||||||
|
Elf64_Ehdr * ehdr)
|
||||||
|
{
|
||||||
|
Elf64_Phdr * phdr;
|
||||||
|
Elf64_Quarter i;
|
||||||
|
|
||||||
|
if(mod->start + ehdr->e_phoff + (ehdr->e_phnum * sizeof(*phdr))
|
||||||
|
> mod->end)
|
||||||
|
{
|
||||||
|
puts("Could not load 64-bit module: Invalid format");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
phdr = (Elf64_Phdr *)(mod->start + ehdr->e_phoff);
|
||||||
|
for(i = 0; i < ehdr->e_phnum; i++)
|
||||||
|
{
|
||||||
|
if(phdr[i].p_type != PT_LOAD)
|
||||||
|
continue;
|
||||||
|
if(phdr[i].p_vaddr > ehdr->e_entry
|
||||||
|
|| phdr[i].p_vaddr + phdr[i].p_filesz
|
||||||
|
<= ehdr->e_entry)
|
||||||
|
continue;
|
||||||
|
if(entrypoint != NULL)
|
||||||
|
*entrypoint = mod->start + ehdr->e_entry
|
||||||
|
- phdr[i].p_vaddr + phdr[i].p_offset;
|
||||||
|
/* FIXME really look for main() directly? */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
puts("Could not load 64-bit module: Invalid entrypoint");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
|
# include <elf.h>
|
||||||
|
|
||||||
|
|
||||||
/* types */
|
/* types */
|
||||||
|
@ -102,4 +103,11 @@ struct _ukBootMultibootMod
|
||||||
# define BOOT_MULTIBOOT_INFO_HAS_LOADER_NAME 0x00000200
|
# define BOOT_MULTIBOOT_INFO_HAS_LOADER_NAME 0x00000200
|
||||||
# define BOOT_MULTIBOOT_INFO_HAS_VBE 0x00000800
|
# define BOOT_MULTIBOOT_INFO_HAS_VBE 0x00000800
|
||||||
|
|
||||||
|
/* prototypes */
|
||||||
|
int multiboot_boot_kernel32(ukMultibootInfo * info, vaddr_t entrypoint);
|
||||||
|
int multiboot_boot_kernel64(ukMultibootInfo * info, vaddr_t entrypoint);
|
||||||
|
|
||||||
|
int multiboot_load_module(ukMultibootMod * mod, unsigned char * elfclass,
|
||||||
|
vaddr_t * entrypoint);
|
||||||
|
|
||||||
#endif /* !UKERNEL_DRIVERS_BOOT_MULTIBOOT_H */
|
#endif /* !UKERNEL_DRIVERS_BOOT_MULTIBOOT_H */
|
||||||
|
|
|
@ -1 +1,18 @@
|
||||||
dist=Makefile,multiboot.h
|
dist=Makefile,multiboot.h
|
||||||
|
targets=multiboot.o
|
||||||
|
cppflags_force=-nostdinc -isystem ../../../include -I../..
|
||||||
|
as=$(CC)
|
||||||
|
asflags_force=$(CFLAGSF) $(CFLAGS) -c
|
||||||
|
cflags_force=`../../../tools/platform.sh -V UKERNEL_CFLAGS -C "$$ARCH"`
|
||||||
|
cflags=-W -Wall -g -O2
|
||||||
|
ldflags_force=`../../../tools/platform.sh -V UKERNEL_LDFLAGS -C "$$ARCH"`
|
||||||
|
dist=Makefile,bus.h,console.h
|
||||||
|
|
||||||
|
#targets
|
||||||
|
[multiboot.o]
|
||||||
|
type=object
|
||||||
|
sources=multiboot.c
|
||||||
|
|
||||||
|
#sources
|
||||||
|
[multiboot.c]
|
||||||
|
depends=multiboot.h
|
||||||
|
|
7
src/kernel/gdt.c
Normal file
7
src/kernel/gdt.c
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright (c) 2018 Pierre Pronchery <khorben@defora.org> */
|
||||||
|
/* This file is part of DeforaOS uKernel */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "../loader/gdt.c"
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "drivers/boot/multiboot.h"
|
|
||||||
#include "drivers/bus.h"
|
#include "drivers/bus.h"
|
||||||
#include "drivers/console.h"
|
#include "drivers/console.h"
|
||||||
|
|
||||||
|
@ -20,12 +19,16 @@
|
||||||
/* public */
|
/* public */
|
||||||
/* functions */
|
/* functions */
|
||||||
/* main */
|
/* main */
|
||||||
int main(ukMultibootInfo * mi)
|
int main(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
ukBus * bus;
|
ukBus * bus;
|
||||||
|
int i;
|
||||||
|
|
||||||
bus = bus_init(KERNEL_BUS);
|
bus = bus_init(KERNEL_BUS);
|
||||||
console_init(bus, KERNEL_CONSOLE);
|
console_init(bus, KERNEL_CONSOLE);
|
||||||
puts("Starting DeforaOS...");
|
puts("Starting DeforaOS...");
|
||||||
|
for(i = 0; i < argc; i++)
|
||||||
|
printf("%s%s%s", (i > 0) ? " " : "", argv[i],
|
||||||
|
(i + 1 == argc) ? "\n" : "");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
76
src/kernel/multiboot.c
Normal file
76
src/kernel/multiboot.c
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright (c) 2018 Pierre Pronchery <khorben@defora.org> */
|
||||||
|
/* This file is part of DeforaOS uKernel */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
|
# include <stdio.h>
|
||||||
|
# include "arch/amd64/gdt.h"
|
||||||
|
# include "arch/i386/gdt.h"
|
||||||
|
# include "drivers/boot/multiboot.h"
|
||||||
|
# include "drivers/bus.h"
|
||||||
|
# include "drivers/console.h"
|
||||||
|
|
||||||
|
# ifndef LOADER_BUS
|
||||||
|
# define LOADER_BUS "ioport"
|
||||||
|
# endif
|
||||||
|
# ifndef LOADER_CONSOLE
|
||||||
|
# define LOADER_CONSOLE "vga"
|
||||||
|
# endif
|
||||||
|
|
||||||
|
|
||||||
|
/* private */
|
||||||
|
/* constants */
|
||||||
|
/* GDT: 4GB flat memory setup */
|
||||||
|
static const GDT _gdt_4gb[4] =
|
||||||
|
{
|
||||||
|
{ 0x00000000, 0x00000000, 0x00 },
|
||||||
|
{ 0x00000000, 0xffffffff, 0x9a },
|
||||||
|
{ 0x00000000, 0xffffffff, 0x92 },
|
||||||
|
{ 0x00000000, 0x00000000, 0x89 }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* public */
|
||||||
|
/* functions */
|
||||||
|
/* multiboot */
|
||||||
|
int multiboot(ukMultibootInfo * mi)
|
||||||
|
{
|
||||||
|
ukBus * bus;
|
||||||
|
size_t i;
|
||||||
|
ukMultibootMod * mod;
|
||||||
|
|
||||||
|
bus = bus_init(LOADER_BUS);
|
||||||
|
console_init(bus, LOADER_CONSOLE);
|
||||||
|
puts("DeforaOS Multiboot");
|
||||||
|
if(mi->loader_name != NULL)
|
||||||
|
printf("Loader: %s\n", mi->loader_name);
|
||||||
|
if(mi->cmdline != NULL)
|
||||||
|
printf("Command line: %s\n", mi->cmdline);
|
||||||
|
printf("%u MB memory available\n",
|
||||||
|
(mi->mem_upper - mi->mem_lower) / 1024);
|
||||||
|
printf("Booted from %#x\n", mi->boot_device_drive);
|
||||||
|
if(!(mi->flags & BOOT_MULTIBOOT_HEADER_HAS_MODS))
|
||||||
|
{
|
||||||
|
puts("No modules provided");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
#if defined(__amd64__)
|
||||||
|
if(_arch_setgdt64(_gdt_4gb, sizeof(_gdt_4gb) / sizeof(*_gdt_4gb)) != 0)
|
||||||
|
#else
|
||||||
|
if(_arch_setgdt(_gdt_4gb, sizeof(_gdt_4gb) / sizeof(*_gdt_4gb)) != 0)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
puts("Could not setup the GDT");
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
puts("Loading modules...");
|
||||||
|
for(i = 0; i < mi->mods_count; i++)
|
||||||
|
{
|
||||||
|
mod = &mi->mods_addr[i];
|
||||||
|
multiboot_load_module(mod, NULL, NULL);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -26,9 +26,9 @@ sources=../common/crtn.S
|
||||||
|
|
||||||
[uKernel.bin]
|
[uKernel.bin]
|
||||||
type=binary
|
type=binary
|
||||||
sources=arch.S,start.S,main.c
|
sources=arch.S,gdt.c,main.c,multiboot.c,start.S
|
||||||
ldflags=$(OBJDIR)crti.o $(OBJDIR)crtbegin.o $(OBJDIR)../drivers/bus.o $(OBJDIR)../drivers/console.o $(OBJDIR)../lib/libuKernel.a $(OBJDIR)crtend.o $(OBJDIR)crtn.o
|
ldflags=$(OBJDIR)crti.o $(OBJDIR)crtbegin.o $(OBJDIR)../drivers/boot/multiboot.o $(OBJDIR)../drivers/bus.o $(OBJDIR)../drivers/console.o $(OBJDIR)../lib/libuKernel.a $(OBJDIR)crtend.o $(OBJDIR)crtn.o
|
||||||
depends=$(OBJDIR)crtbegin.o,$(OBJDIR)crtend.o,$(OBJDIR)crti.o,$(OBJDIR)crtn.o,$(OBJDIR)../drivers/bus.o,$(OBJDIR)../drivers/console.o,$(OBJDIR)../lib/libuKernel.a,../arch/amd64/uKernel.ld,../arch/i386/uKernel.ld
|
depends=$(OBJDIR)crtbegin.o,$(OBJDIR)crtend.o,$(OBJDIR)crti.o,$(OBJDIR)crtn.o,$(OBJDIR)../drivers/boot/multiboot.o,$(OBJDIR)../drivers/bus.o,$(OBJDIR)../drivers/console.o,$(OBJDIR)../lib/libuKernel.a,../arch/amd64/uKernel.ld,../arch/i386/uKernel.ld
|
||||||
|
|
||||||
#sources
|
#sources
|
||||||
[arch.S]
|
[arch.S]
|
||||||
|
@ -40,8 +40,8 @@ depends=../arch/amd64/crti.S,../arch/i386/crti.S
|
||||||
[../common/crtn.S]
|
[../common/crtn.S]
|
||||||
depends=../arch/amd64/crtn.S,../arch/i386/crtn.S
|
depends=../arch/amd64/crtn.S,../arch/i386/crtn.S
|
||||||
|
|
||||||
[main.c]
|
[multiboot.c]
|
||||||
depends=../drivers/bus.h,../drivers/console.h
|
depends=../loader/multiboot.c,../drivers/boot/multiboot.h
|
||||||
|
|
||||||
[start.S]
|
[start.S]
|
||||||
depends=../arch/i386/kernel.S
|
depends=../arch/i386/kernel.S
|
||||||
|
|
|
@ -6,8 +6,11 @@
|
||||||
|
|
||||||
/* check for supported architectures */
|
/* check for supported architectures */
|
||||||
#if defined(__amd64__)
|
#if defined(__amd64__)
|
||||||
|
# include "arch/amd64/gdt.S"
|
||||||
# include "arch/amd64/kernel.S"
|
# include "arch/amd64/kernel.S"
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__)
|
||||||
|
# include "arch/i386/gdt.S"
|
||||||
|
# include "arch/i386/idt.S"
|
||||||
# include "arch/i386/kernel.S"
|
# include "arch/i386/kernel.S"
|
||||||
#else
|
#else
|
||||||
# warning Unsupported architecture
|
# warning Unsupported architecture
|
||||||
|
|
112
src/loader/gdt.c
Normal file
112
src/loader/gdt.c
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright (c) 2018 Pierre Pronchery <khorben@defora.org> */
|
||||||
|
/* This file is part of DeforaOS uKernel */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
|
# include <stdint.h>
|
||||||
|
# include <string.h>
|
||||||
|
# include <errno.h>
|
||||||
|
# include "arch/amd64/gdt.h"
|
||||||
|
# include "arch/i386/gdt.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* prototypes */
|
||||||
|
extern void __arch_setgdt(uint8_t * buf, size_t count);
|
||||||
|
|
||||||
|
|
||||||
|
/* variables */
|
||||||
|
static uint8_t _buf[65536];
|
||||||
|
|
||||||
|
|
||||||
|
/* functions */
|
||||||
|
/* arch_setgdt */
|
||||||
|
int _arch_setgdt(GDT const * gdt, size_t count)
|
||||||
|
{
|
||||||
|
uint8_t * buf = _buf;
|
||||||
|
size_t i;
|
||||||
|
GDT g;
|
||||||
|
|
||||||
|
memset(&_buf, 0, sizeof(_buf));
|
||||||
|
/* check for errors */
|
||||||
|
if(count == 0 || count > sizeof(_buf) / sizeof(*gdt))
|
||||||
|
{
|
||||||
|
errno = ERANGE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for(i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
g = gdt[i];
|
||||||
|
buf = &_buf[sizeof(g) * i];
|
||||||
|
if(g.limit > 65536)
|
||||||
|
{
|
||||||
|
/* make sure the limit can be encoded */
|
||||||
|
if((g.limit & 0xfff) != 0xfff)
|
||||||
|
return -1;
|
||||||
|
g.limit = g.limit >> 12;
|
||||||
|
buf[6] = 0xc0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
buf[6] = 0x40;
|
||||||
|
//encode the limit
|
||||||
|
buf[0] = g.limit & 0xff;
|
||||||
|
buf[1] = (g.limit >> 8) & 0xff;
|
||||||
|
buf[6] |= (g.limit >> 16) & 0xf;
|
||||||
|
//encode the base
|
||||||
|
buf[2] = g.base & 0xff;
|
||||||
|
buf[3] = (g.base >> 8) & 0xff;
|
||||||
|
buf[4] = (g.base >> 16) & 0xff;
|
||||||
|
buf[7] = (g.base >> 24) & 0xff;
|
||||||
|
//encode the type
|
||||||
|
buf[5] = g.type;
|
||||||
|
}
|
||||||
|
__arch_setgdt(_buf, count);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* arch_setgdt64 */
|
||||||
|
int _arch_setgdt64(GDT const * gdt, size_t count)
|
||||||
|
{
|
||||||
|
uint8_t * buf;
|
||||||
|
size_t i;
|
||||||
|
GDT g;
|
||||||
|
|
||||||
|
memset(&_buf, 0, sizeof(_buf));
|
||||||
|
/* check for errors */
|
||||||
|
if(count == 0 || count > sizeof(_buf) / sizeof(*gdt))
|
||||||
|
{
|
||||||
|
errno = ERANGE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for(i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
g = gdt[i];
|
||||||
|
buf = &_buf[sizeof(g) * i];
|
||||||
|
if(g.limit > 65536)
|
||||||
|
{
|
||||||
|
/* make sure the limit can be encoded */
|
||||||
|
if((g.limit & 0xfff) != 0xfff)
|
||||||
|
return -1;
|
||||||
|
g.limit = g.limit >> 12;
|
||||||
|
buf[6] = 0xa0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
buf[6] = 0x20;
|
||||||
|
//encode the limit
|
||||||
|
buf[0] = g.limit & 0xff;
|
||||||
|
buf[1] = (g.limit >> 8) & 0xff;
|
||||||
|
buf[6] |= (g.limit >> 16) & 0xf;
|
||||||
|
//encode the base
|
||||||
|
buf[2] = g.base & 0xff;
|
||||||
|
buf[3] = (g.base >> 8) & 0xff;
|
||||||
|
buf[4] = (g.base >> 16) & 0xff;
|
||||||
|
buf[7] = (g.base >> 24) & 0xff;
|
||||||
|
//encode the type
|
||||||
|
buf[5] = g.type;
|
||||||
|
}
|
||||||
|
__arch_setgdt(_buf, count);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -17,5 +17,6 @@
|
||||||
#include "lib/string.c"
|
#include "lib/string.c"
|
||||||
#include "lib/unistd.c"
|
#include "lib/unistd.c"
|
||||||
|
|
||||||
|
#include "drivers/boot/multiboot.c"
|
||||||
#include "drivers/bus.c"
|
#include "drivers/bus.c"
|
||||||
#include "drivers/console.c"
|
#include "drivers/console.c"
|
||||||
|
|
|
@ -4,265 +4,19 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <elf.h>
|
|
||||||
#include "drivers/boot/multiboot.h"
|
|
||||||
#include "drivers/bus.h"
|
|
||||||
#include "drivers/console.h"
|
|
||||||
|
|
||||||
#ifndef LOADER_BUS
|
|
||||||
# define LOADER_BUS "ioport"
|
|
||||||
#endif
|
|
||||||
#ifndef LOADER_CONSOLE
|
|
||||||
# define LOADER_CONSOLE "vga"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* private */
|
|
||||||
/* types */
|
|
||||||
typedef int (*LoaderCallback)(ukMultibootInfo * mi, vaddr_t entrypoint);
|
|
||||||
|
|
||||||
|
|
||||||
/* prototypes */
|
|
||||||
static LoaderCallback _loader_kernel(ukMultibootMod * mod,
|
|
||||||
vaddr_t * entrypoint);
|
|
||||||
static int _loader_module(ukMultibootMod * mod);
|
|
||||||
|
|
||||||
extern int _kernel32(ukMultibootInfo * mi, vaddr_t entrypoint);
|
|
||||||
extern int _kernel64(ukMultibootInfo * mi, vaddr_t entrypoint);
|
|
||||||
|
|
||||||
/* platform-dependent */
|
|
||||||
#if defined(__i386__)
|
|
||||||
/* types */
|
|
||||||
typedef struct _GDT
|
|
||||||
{
|
|
||||||
vaddr_t base;
|
|
||||||
vaddr_t limit;
|
|
||||||
uint8_t type;
|
|
||||||
} GDT;
|
|
||||||
|
|
||||||
/* prototypes */
|
|
||||||
static int _loader_gdt(GDT const * gdt, size_t size);
|
|
||||||
extern void _setgdt(uint8_t * buf, size_t size);
|
|
||||||
|
|
||||||
/* constants */
|
|
||||||
/* GDT: flat memory setup */
|
|
||||||
static const GDT _gdt_4gb[4] =
|
|
||||||
{
|
|
||||||
{ 0x00000000, 0x00000000, 0x00 },
|
|
||||||
{ 0x00000000, 0xffffffff, 0x9a },
|
|
||||||
{ 0x00000000, 0xffffffff, 0x92 },
|
|
||||||
{ 0x00000000, 0x00000000, 0x89 }
|
|
||||||
};
|
|
||||||
|
|
||||||
/* variables */
|
|
||||||
static uint8_t _buf[65536];
|
|
||||||
|
|
||||||
/* functions */
|
|
||||||
/* loader_gdt */
|
|
||||||
static int _loader_gdt(GDT const * gdt, size_t size)
|
|
||||||
{
|
|
||||||
uint8_t * buf;
|
|
||||||
size_t i;
|
|
||||||
GDT g;
|
|
||||||
|
|
||||||
if(size == 0 || size > sizeof(_buf) / sizeof(*gdt))
|
|
||||||
{
|
|
||||||
errno = ERANGE;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
for(i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
g = gdt[i];
|
|
||||||
buf = &_buf[sizeof(g) * i];
|
|
||||||
if(g.limit > 65536)
|
|
||||||
{
|
|
||||||
/* make sure the limit can be encoded */
|
|
||||||
if((g.limit & 0xfff) != 0xfff)
|
|
||||||
return -1;
|
|
||||||
g.limit = g.limit >> 12;
|
|
||||||
buf[6] = 0xc0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
buf[6] = 0x40;
|
|
||||||
//encode the limit
|
|
||||||
buf[0] = g.limit & 0xff;
|
|
||||||
buf[1] = (g.limit >> 8) & 0xff;
|
|
||||||
buf[6] |= (g.limit >> 16) & 0xf;
|
|
||||||
//encode the base
|
|
||||||
buf[2] = g.base & 0xff;
|
|
||||||
buf[3] = (g.base >> 8) & 0xff;
|
|
||||||
buf[4] = (g.base >> 16) & 0xff;
|
|
||||||
buf[7] = (g.base >> 24) & 0xff;
|
|
||||||
//encode the type
|
|
||||||
buf[5] = g.type;
|
|
||||||
}
|
|
||||||
_setgdt(_buf, size);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* functions */
|
|
||||||
/* loader_kernel */
|
|
||||||
static LoaderCallback _loader_kernel32(ukMultibootMod * mod,
|
|
||||||
vaddr_t * entrypoint, Elf32_Ehdr * ehdr);
|
|
||||||
static LoaderCallback _loader_kernel64(ukMultibootMod * mod,
|
|
||||||
vaddr_t * entrypoint, Elf64_Ehdr * ehdr);
|
|
||||||
|
|
||||||
static LoaderCallback _loader_kernel(ukMultibootMod * mod, vaddr_t * entrypoint)
|
|
||||||
{
|
|
||||||
Elf32_Ehdr * ehdr;
|
|
||||||
|
|
||||||
printf("Loading kernel: %s (%#x, %#x)\n", mod->cmdline, mod->start,
|
|
||||||
mod->end);
|
|
||||||
if(mod->end < mod->start || mod->end - mod->start < sizeof(ehdr))
|
|
||||||
{
|
|
||||||
puts("Could not load kernel: Invalid format");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
ehdr = (Elf32_Ehdr *)mod->start;
|
|
||||||
switch(ehdr->e_ident[EI_CLASS])
|
|
||||||
{
|
|
||||||
case ELFCLASS32:
|
|
||||||
puts("Detected 32-bit kernel");
|
|
||||||
return _loader_kernel32(mod, entrypoint, ehdr);
|
|
||||||
case ELFCLASS64:
|
|
||||||
puts("Detected 64-bit kernel");
|
|
||||||
return _loader_kernel64(mod, entrypoint,
|
|
||||||
(Elf64_Ehdr *)ehdr);
|
|
||||||
default:
|
|
||||||
puts("Could not load kernel: Invalid class");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static LoaderCallback _loader_kernel32(ukMultibootMod * mod,
|
|
||||||
vaddr_t * entrypoint, Elf32_Ehdr * ehdr)
|
|
||||||
{
|
|
||||||
Elf32_Phdr * phdr;
|
|
||||||
Elf32_Half i;
|
|
||||||
|
|
||||||
if(mod->start + ehdr->e_phoff + (ehdr->e_phnum * sizeof(*phdr))
|
|
||||||
> mod->end)
|
|
||||||
{
|
|
||||||
puts("Could not load 32-bit kernel: Invalid format");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
phdr = (Elf32_Phdr *)(mod->start + ehdr->e_phoff);
|
|
||||||
for(i = 0; i < ehdr->e_phnum; i++)
|
|
||||||
{
|
|
||||||
if(phdr[i].p_type != PT_LOAD)
|
|
||||||
continue;
|
|
||||||
if(phdr[i].p_vaddr > ehdr->e_entry
|
|
||||||
|| phdr[i].p_vaddr + phdr[i].p_filesz
|
|
||||||
<= ehdr->e_entry)
|
|
||||||
continue;
|
|
||||||
*entrypoint = mod->start + ehdr->e_entry - phdr[i].p_vaddr
|
|
||||||
+ phdr[i].p_offset;
|
|
||||||
return _kernel32;
|
|
||||||
}
|
|
||||||
puts("Could not load 32-bit kernel: Invalid entrypoint");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static LoaderCallback _loader_kernel64(ukMultibootMod * mod,
|
|
||||||
vaddr_t * entrypoint, Elf64_Ehdr * ehdr)
|
|
||||||
{
|
|
||||||
Elf64_Phdr * phdr;
|
|
||||||
Elf64_Quarter i;
|
|
||||||
|
|
||||||
if(mod->start + ehdr->e_phoff + (ehdr->e_phnum * sizeof(*phdr))
|
|
||||||
> mod->end)
|
|
||||||
{
|
|
||||||
puts("Could not load 64-bit kernel: Invalid format");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
phdr = (Elf64_Phdr *)(mod->start + ehdr->e_phoff);
|
|
||||||
for(i = 0; i < ehdr->e_phnum; i++)
|
|
||||||
{
|
|
||||||
if(phdr[i].p_type != PT_LOAD)
|
|
||||||
continue;
|
|
||||||
if(phdr[i].p_vaddr > ehdr->e_entry
|
|
||||||
|| phdr[i].p_vaddr + phdr[i].p_filesz
|
|
||||||
<= ehdr->e_entry)
|
|
||||||
continue;
|
|
||||||
*entrypoint = mod->start + ehdr->e_entry - phdr[i].p_vaddr
|
|
||||||
+ phdr[i].p_offset;
|
|
||||||
return _kernel64;
|
|
||||||
}
|
|
||||||
puts("Could not load 64-bit kernel: Invalid entrypoint");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* loader_module */
|
|
||||||
static int _loader_module(ukMultibootMod * mod)
|
|
||||||
{
|
|
||||||
const char msg_loading[] = "Loading module: ";
|
|
||||||
|
|
||||||
puts(msg_loading);
|
|
||||||
puts(mod->cmdline);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* public */
|
/* public */
|
||||||
/* functions */
|
/* functions */
|
||||||
/* main */
|
/* main */
|
||||||
int main(ukMultibootInfo * mi)
|
int main(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
ukBus * bus;
|
int i;
|
||||||
size_t i;
|
|
||||||
const char msg_failed2[] = "No modules provided";
|
|
||||||
const char msg_failed3[] = "No kernel provided";
|
|
||||||
ukMultibootMod * mod;
|
|
||||||
LoaderCallback callback = NULL;
|
|
||||||
vaddr_t entrypoint;
|
|
||||||
|
|
||||||
bus = bus_init(LOADER_BUS);
|
|
||||||
console_init(bus, LOADER_CONSOLE);
|
|
||||||
puts("Booting DeforaOS...");
|
puts("Booting DeforaOS...");
|
||||||
if(mi->flags & BOOT_MULTIBOOT_INFO_HAS_LOADER_NAME)
|
for(i = 0; i < argc; i++)
|
||||||
printf("Loader: %s\n", mi->loader_name);
|
printf("%s%s%s", (i > 0) ? " " : "", argv[i],
|
||||||
if(mi->flags & BOOT_MULTIBOOT_INFO_HAS_CMDLINE)
|
(i + 1 == argc) ? "\n" : "");
|
||||||
printf("Command line: %s\n", mi->cmdline);
|
return 0;
|
||||||
printf("%u MB memory available\n",
|
|
||||||
(mi->mem_upper - mi->mem_lower) / 1024);
|
|
||||||
if(!(mi->flags & BOOT_MULTIBOOT_INFO_HAS_MODS))
|
|
||||||
{
|
|
||||||
puts(msg_failed2);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
if(mi->mods_count == 0)
|
|
||||||
{
|
|
||||||
puts(msg_failed3);
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
#if defined(__i386__)
|
|
||||||
if(_loader_gdt(_gdt_4gb, sizeof(_gdt_4gb) / sizeof(*_gdt_4gb)) != 0)
|
|
||||||
{
|
|
||||||
puts("Could not setup the GDT");
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
puts("Loading modules...");
|
|
||||||
for(i = 0; i < mi->mods_count; i++)
|
|
||||||
{
|
|
||||||
mod = &mi->mods_addr[i];
|
|
||||||
if(i == 0)
|
|
||||||
callback = _loader_kernel(mod, &entrypoint);
|
|
||||||
else
|
|
||||||
_loader_module(mod);
|
|
||||||
}
|
|
||||||
if(callback == NULL)
|
|
||||||
{
|
|
||||||
puts("Could not load the kernel");
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
return callback(mi, entrypoint);
|
|
||||||
}
|
}
|
||||||
|
|
105
src/loader/multiboot.c
Normal file
105
src/loader/multiboot.c
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright (c) 2018 Pierre Pronchery <khorben@defora.org> */
|
||||||
|
/* This file is part of DeforaOS uKernel */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__i386__)
|
||||||
|
# include <stdint.h>
|
||||||
|
# include <stdio.h>
|
||||||
|
# include <string.h>
|
||||||
|
# include "arch/amd64/gdt.h"
|
||||||
|
# include "arch/i386/gdt.h"
|
||||||
|
# include "drivers/boot/multiboot.h"
|
||||||
|
# include "drivers/bus.h"
|
||||||
|
# include "drivers/console.h"
|
||||||
|
|
||||||
|
# ifndef LOADER_BUS
|
||||||
|
# define LOADER_BUS "ioport"
|
||||||
|
# endif
|
||||||
|
# ifndef LOADER_CONSOLE
|
||||||
|
# define LOADER_CONSOLE "vga"
|
||||||
|
# endif
|
||||||
|
|
||||||
|
|
||||||
|
/* private */
|
||||||
|
/* constants */
|
||||||
|
/* GDT: 4GB flat memory setup */
|
||||||
|
static const GDT _gdt_4gb[4] =
|
||||||
|
{
|
||||||
|
{ 0x00000000, 0x00000000, 0x00 },
|
||||||
|
{ 0x00000000, 0xffffffff, 0x9a },
|
||||||
|
{ 0x00000000, 0xffffffff, 0x92 },
|
||||||
|
{ 0x00000000, 0x00000000, 0x89 }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* public */
|
||||||
|
/* functions */
|
||||||
|
/* multiboot */
|
||||||
|
int multiboot(ukMultibootInfo * mi)
|
||||||
|
{
|
||||||
|
ukBus * bus;
|
||||||
|
size_t i;
|
||||||
|
ukMultibootMod * mod;
|
||||||
|
int res = -1;
|
||||||
|
unsigned char elfclass;
|
||||||
|
vaddr_t entrypoint;
|
||||||
|
|
||||||
|
bus = bus_init(LOADER_BUS);
|
||||||
|
console_init(bus, LOADER_CONSOLE);
|
||||||
|
puts("DeforaOS Multiboot");
|
||||||
|
if(mi->loader_name != NULL)
|
||||||
|
printf("Loader: %s\n", mi->loader_name);
|
||||||
|
if(mi->cmdline != NULL)
|
||||||
|
printf("Command line: %s\n", mi->cmdline);
|
||||||
|
printf("%u MB memory available\n",
|
||||||
|
(mi->mem_upper - mi->mem_lower) / 1024);
|
||||||
|
printf("Booted from %#x\n", mi->boot_device_drive);
|
||||||
|
if(!(mi->flags & BOOT_MULTIBOOT_HEADER_HAS_MODS))
|
||||||
|
{
|
||||||
|
puts("No modules provided");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if(mi->mods_count == 0)
|
||||||
|
{
|
||||||
|
puts("No kernel provided");
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if(_arch_setgdt(_gdt_4gb, sizeof(_gdt_4gb) / sizeof(*_gdt_4gb)) != 0)
|
||||||
|
{
|
||||||
|
puts("Could not setup the GDT");
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
puts("Loading modules...");
|
||||||
|
for(i = 0; i < mi->mods_count; i++)
|
||||||
|
{
|
||||||
|
mod = &mi->mods_addr[i];
|
||||||
|
printf("Loading module: %s\n", mod->cmdline);
|
||||||
|
if(i == 0)
|
||||||
|
res = multiboot_load_module(mod, &elfclass,
|
||||||
|
&entrypoint);
|
||||||
|
else
|
||||||
|
multiboot_load_module(mod, NULL, NULL);
|
||||||
|
}
|
||||||
|
if(res != 0)
|
||||||
|
{
|
||||||
|
puts("Could not load the kernel");
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
printf("Jumping into the kernel at %#x (%u, %u, %#x) %p\n", entrypoint,
|
||||||
|
mi->elfshdr_num, mi->elfshdr_size, mi->elfshdr_addr,
|
||||||
|
multiboot);
|
||||||
|
switch(elfclass)
|
||||||
|
{
|
||||||
|
case ELFCLASS32:
|
||||||
|
puts("Detected 32-bit kernel");
|
||||||
|
return multiboot_boot_kernel32(mi, entrypoint);
|
||||||
|
case ELFCLASS64:
|
||||||
|
puts("Detected 64-bit kernel");
|
||||||
|
return multiboot_boot_kernel64(mi, entrypoint);
|
||||||
|
}
|
||||||
|
puts("Unsupported ELF class for the kernel");
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -30,7 +30,7 @@ sources=lib.c
|
||||||
|
|
||||||
[uLoader.bin]
|
[uLoader.bin]
|
||||||
type=binary
|
type=binary
|
||||||
sources=arch.S,start.S,main.c
|
sources=arch.S,gdt.c,main.c,multiboot.c,start.S
|
||||||
ldflags=$(OBJDIR)crti.o $(OBJDIR)crtbegin.o $(OBJDIR)crtend.o $(OBJDIR)crtn.o $(OBJDIR)libuLoader.a
|
ldflags=$(OBJDIR)crti.o $(OBJDIR)crtbegin.o $(OBJDIR)crtend.o $(OBJDIR)crtn.o $(OBJDIR)libuLoader.a
|
||||||
depends=$(OBJDIR)crtbegin.o,$(OBJDIR)crtend.o,$(OBJDIR)crti.o,$(OBJDIR)crtn.o,$(OBJDIR)libuLoader.a,../arch/amd64/uKernel.ld,../arch/i386/uKernel.ld
|
depends=$(OBJDIR)crtbegin.o,$(OBJDIR)crtend.o,$(OBJDIR)crti.o,$(OBJDIR)crtn.o,$(OBJDIR)libuLoader.a,../arch/amd64/uKernel.ld,../arch/i386/uKernel.ld
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ depends=../arch/amd64/crti.S,../arch/i386/crti.S
|
||||||
[../common/crtn.S]
|
[../common/crtn.S]
|
||||||
depends=../arch/amd64/crtn.S,../arch/i386/crtn.S
|
depends=../arch/amd64/crtn.S,../arch/i386/crtn.S
|
||||||
|
|
||||||
[main.c]
|
[multiboot.c]
|
||||||
depends=../drivers/boot/multiboot.h,../drivers/bus.h,../drivers/console.h
|
depends=../drivers/boot/multiboot.h,../drivers/bus.h,../drivers/console.h
|
||||||
|
|
||||||
[start.S]
|
[start.S]
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
/* check for supported architectures */
|
/* check for supported architectures */
|
||||||
#if defined(__amd64__) || defined(__i386__)
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
|
# include "../arch/i386/gdt.S"
|
||||||
# include "../arch/i386/loader.S"
|
# include "../arch/i386/loader.S"
|
||||||
#else
|
#else
|
||||||
# warning Unsupported architecture
|
# warning Unsupported architecture
|
||||||
|
|
|
@ -57,6 +57,8 @@ _grub()
|
||||||
amd64|i?86)
|
amd64|i?86)
|
||||||
_info "Testing multiboot conformance ($machine)"
|
_info "Testing multiboot conformance ($machine)"
|
||||||
$GRUBFILE --is-x86-multiboot "$OBJDIR$UKERNELBIN"
|
$GRUBFILE --is-x86-multiboot "$OBJDIR$UKERNELBIN"
|
||||||
|
#FIXME look for multiboot2 instead?
|
||||||
|
#$GRUBFILE --is-x86-multiboot2 "$OBJDIR$UKERNELBIN"
|
||||||
ret=$?
|
ret=$?
|
||||||
if [ $ret -eq 127 ]; then
|
if [ $ret -eq 127 ]; then
|
||||||
_error "Cannot test: $GRUBFILE not available (ignored)"
|
_error "Cannot test: $GRUBFILE not available (ignored)"
|
||||||
|
|
|
@ -6,4 +6,6 @@
|
||||||
|
|
||||||
#define KERNEL_BUS "tty"
|
#define KERNEL_BUS "tty"
|
||||||
#define KERNEL_CONSOLE "stdio"
|
#define KERNEL_CONSOLE "stdio"
|
||||||
|
|
||||||
|
|
||||||
#include "../src/kernel/main.c"
|
#include "../src/kernel/main.c"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user