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 */
|
||||
/* bss */
|
||||
.section .bss
|
||||
|
@ -26,6 +30,14 @@ _exit:
|
|||
jmp 1b
|
||||
|
||||
|
||||
/* setidt */
|
||||
.global _setidt
|
||||
.type _setidt,function
|
||||
_setidt:
|
||||
lidt (idt)
|
||||
ret
|
||||
|
||||
|
||||
/* start */
|
||||
.global _start
|
||||
.type _start, @function
|
||||
|
@ -45,6 +57,11 @@ _start:
|
|||
/* call the global constructors */
|
||||
call _init
|
||||
|
||||
/* set the interrupt descriptor */
|
||||
call _setidt
|
||||
|
||||
/* FIXME setup paging */
|
||||
|
||||
/* start the kernel */
|
||||
xor %rdi, %rdi
|
||||
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 */
|
||||
#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
|
||||
#include "multiboot.S"
|
||||
|
||||
|
||||
/* bss */
|
||||
|
@ -54,6 +39,8 @@ _start:
|
|||
mov $stack_top, %esp
|
||||
xor %ebp, %ebp
|
||||
|
||||
push %eax
|
||||
|
||||
#if defined(__SSP__)
|
||||
/* initialize SSP */
|
||||
call __stack_chk_setup
|
||||
|
@ -62,8 +49,16 @@ _start:
|
|||
/* call the global constructors */
|
||||
call _init
|
||||
|
||||
/* start the kernel */
|
||||
/* detect multiboot */
|
||||
pop %eax
|
||||
cmp $MAGIC2, %eax
|
||||
jne 1f
|
||||
push %ebx
|
||||
call multiboot
|
||||
1:
|
||||
|
||||
/* start the kernel */
|
||||
push $0x0
|
||||
call main
|
||||
add $0x4, %esp
|
||||
|
||||
|
|
|
@ -5,22 +5,7 @@
|
|||
|
||||
|
||||
|
||||
/* 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 MAGIC 0x1badb002 /* magic number */
|
||||
#define CHECKSUM -(MAGIC + FLAGS) /* checksum for the above */
|
||||
|
||||
|
||||
/* sections */
|
||||
/* multiboot */
|
||||
.section .multiboot
|
||||
.align 4
|
||||
.long MAGIC
|
||||
.long FLAGS
|
||||
.long CHECKSUM
|
||||
#include "multiboot.S"
|
||||
|
||||
|
||||
/* bss */
|
||||
|
@ -31,12 +16,6 @@ stack_bottom:
|
|||
stack_top:
|
||||
|
||||
|
||||
/* data */
|
||||
.section .data
|
||||
k_ptr:
|
||||
.long 0x0
|
||||
|
||||
|
||||
/* text */
|
||||
.section .text
|
||||
/* exit */
|
||||
|
@ -49,75 +28,6 @@ _exit:
|
|||
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 */
|
||||
.global _start
|
||||
.type _start, @function
|
||||
|
@ -127,6 +37,8 @@ _start:
|
|||
|
||||
/* initialize the stack */
|
||||
mov $stack_top, %esp
|
||||
xor %ebp, %ebp
|
||||
push %eax
|
||||
|
||||
#if defined(__SSP__)
|
||||
/* initialize SSP */
|
||||
|
@ -136,10 +48,19 @@ _start:
|
|||
/* call the global constructors */
|
||||
call _init
|
||||
|
||||
/* start the loader */
|
||||
/* detect multiboot */
|
||||
pop %eax
|
||||
cmp $MAGIC2, %eax
|
||||
jne 1f
|
||||
push %ebx
|
||||
call multiboot
|
||||
1:
|
||||
|
||||
/* start the loader */
|
||||
push $0x0
|
||||
push $0x0
|
||||
call main
|
||||
add $0x4, %esp
|
||||
add $0x8, %esp
|
||||
|
||||
/* exit the kernel */
|
||||
call _exit
|
||||
|
@ -147,10 +68,3 @@ _start:
|
|||
hlt
|
||||
|
||||
.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 <stdint.h>
|
||||
# include <elf.h>
|
||||
|
||||
|
||||
/* types */
|
||||
|
@ -102,4 +103,11 @@ struct _ukBootMultibootMod
|
|||
# define BOOT_MULTIBOOT_INFO_HAS_LOADER_NAME 0x00000200
|
||||
# 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 */
|
||||
|
|
|
@ -1 +1,18 @@
|
|||
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 "drivers/boot/multiboot.h"
|
||||
#include "drivers/bus.h"
|
||||
#include "drivers/console.h"
|
||||
|
||||
|
@ -20,12 +19,16 @@
|
|||
/* public */
|
||||
/* functions */
|
||||
/* main */
|
||||
int main(ukMultibootInfo * mi)
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
ukBus * bus;
|
||||
int i;
|
||||
|
||||
bus = bus_init(KERNEL_BUS);
|
||||
console_init(bus, KERNEL_CONSOLE);
|
||||
puts("Starting DeforaOS...");
|
||||
for(i = 0; i < argc; i++)
|
||||
printf("%s%s%s", (i > 0) ? " " : "", argv[i],
|
||||
(i + 1 == argc) ? "\n" : "");
|
||||
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]
|
||||
type=binary
|
||||
sources=arch.S,start.S,main.c
|
||||
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
|
||||
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
|
||||
sources=arch.S,gdt.c,main.c,multiboot.c,start.S
|
||||
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/boot/multiboot.o,$(OBJDIR)../drivers/bus.o,$(OBJDIR)../drivers/console.o,$(OBJDIR)../lib/libuKernel.a,../arch/amd64/uKernel.ld,../arch/i386/uKernel.ld
|
||||
|
||||
#sources
|
||||
[arch.S]
|
||||
|
@ -40,8 +40,8 @@ depends=../arch/amd64/crti.S,../arch/i386/crti.S
|
|||
[../common/crtn.S]
|
||||
depends=../arch/amd64/crtn.S,../arch/i386/crtn.S
|
||||
|
||||
[main.c]
|
||||
depends=../drivers/bus.h,../drivers/console.h
|
||||
[multiboot.c]
|
||||
depends=../loader/multiboot.c,../drivers/boot/multiboot.h
|
||||
|
||||
[start.S]
|
||||
depends=../arch/i386/kernel.S
|
||||
|
|
|
@ -6,8 +6,11 @@
|
|||
|
||||
/* check for supported architectures */
|
||||
#if defined(__amd64__)
|
||||
# include "arch/amd64/gdt.S"
|
||||
# include "arch/amd64/kernel.S"
|
||||
#elif defined(__i386__)
|
||||
# include "arch/i386/gdt.S"
|
||||
# include "arch/i386/idt.S"
|
||||
# include "arch/i386/kernel.S"
|
||||
#else
|
||||
# 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/unistd.c"
|
||||
|
||||
#include "drivers/boot/multiboot.c"
|
||||
#include "drivers/bus.c"
|
||||
#include "drivers/console.c"
|
||||
|
|
|
@ -4,265 +4,19 @@
|
|||
|
||||
|
||||
|
||||
#include <stdint.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 */
|
||||
/* functions */
|
||||
/* main */
|
||||
int main(ukMultibootInfo * mi)
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
ukBus * bus;
|
||||
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;
|
||||
int i;
|
||||
|
||||
bus = bus_init(LOADER_BUS);
|
||||
console_init(bus, LOADER_CONSOLE);
|
||||
puts("Booting DeforaOS...");
|
||||
if(mi->flags & BOOT_MULTIBOOT_INFO_HAS_LOADER_NAME)
|
||||
printf("Loader: %s\n", mi->loader_name);
|
||||
if(mi->flags & BOOT_MULTIBOOT_INFO_HAS_CMDLINE)
|
||||
printf("Command line: %s\n", mi->cmdline);
|
||||
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);
|
||||
for(i = 0; i < argc; i++)
|
||||
printf("%s%s%s", (i > 0) ? " " : "", argv[i],
|
||||
(i + 1 == argc) ? "\n" : "");
|
||||
return 0;
|
||||
}
|
||||
|
|
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]
|
||||
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
|
||||
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]
|
||||
depends=../arch/amd64/crtn.S,../arch/i386/crtn.S
|
||||
|
||||
[main.c]
|
||||
[multiboot.c]
|
||||
depends=../drivers/boot/multiboot.h,../drivers/bus.h,../drivers/console.h
|
||||
|
||||
[start.S]
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
/* check for supported architectures */
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
# include "../arch/i386/gdt.S"
|
||||
# include "../arch/i386/loader.S"
|
||||
#else
|
||||
# warning Unsupported architecture
|
||||
|
|
|
@ -57,6 +57,8 @@ _grub()
|
|||
amd64|i?86)
|
||||
_info "Testing multiboot conformance ($machine)"
|
||||
$GRUBFILE --is-x86-multiboot "$OBJDIR$UKERNELBIN"
|
||||
#FIXME look for multiboot2 instead?
|
||||
#$GRUBFILE --is-x86-multiboot2 "$OBJDIR$UKERNELBIN"
|
||||
ret=$?
|
||||
if [ $ret -eq 127 ]; then
|
||||
_error "Cannot test: $GRUBFILE not available (ignored)"
|
||||
|
|
|
@ -6,4 +6,6 @@
|
|||
|
||||
#define KERNEL_BUS "tty"
|
||||
#define KERNEL_CONSOLE "stdio"
|
||||
|
||||
|
||||
#include "../src/kernel/main.c"
|
||||
|
|
Loading…
Reference in New Issue
Block a user