arch/i386: Boot to kernel main() with proper initial segmentation/paging setup
This commit is contained in:
parent
cee0ac7dda
commit
c51062ce87
@ -1,30 +0,0 @@
|
|||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
void main();
|
|
||||||
|
|
||||||
void i386_main(void)
|
|
||||||
{
|
|
||||||
extern uint32_t magic;
|
|
||||||
|
|
||||||
/* Uncomment the following if you want to be able to access the multiboot header */
|
|
||||||
/* extern void *mbd; */
|
|
||||||
|
|
||||||
if ( magic != 0x2BADB002 )
|
|
||||||
{
|
|
||||||
/* Something went not according to specs. Print an error */
|
|
||||||
/* message and halt, but do *not* rely on the multiboot */
|
|
||||||
/* data structure. */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* You could either use multiboot.h */
|
|
||||||
/* (http://www.gnu.org/software/grub/manual/multiboot/multiboot.html#multiboot_002eh) */
|
|
||||||
/* or do your offsets yourself. The following is merely an example. */
|
|
||||||
//char * boot_loader_name =(char*) ((long*)mbd)[16];
|
|
||||||
|
|
||||||
/* Print a letter to screen to see everything is working: */
|
|
||||||
unsigned char *videoram = (unsigned char *)0xB8000;
|
|
||||||
videoram[0] = 65; /* character 'A' */
|
|
||||||
videoram[1] = 0x07; /* light grey (7) on black (0). */
|
|
||||||
|
|
||||||
main();
|
|
||||||
}
|
|
26
arch/i386/include/arch/segmentation.h
Normal file
26
arch/i386/include/arch/segmentation.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2012, Aaron Lindsay <aaron@aclindsay.com>
|
||||||
|
|
||||||
|
This file is part of Aedrix.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SEGMENT_SELECTOR_KERNEL_PRIVILEGE 0x0
|
||||||
|
#define SEGMENT_SELECTOR_KERNEL_CS (0x10 | SEGMENT_SELECTOR_KERNEL_PRIVILEGE)
|
||||||
|
#define SEGMENT_SELECTOR_KERNEL_DS (0x18 | SEGMENT_SELECTOR_KERNEL_PRIVILEGE)
|
||||||
|
#define SEGMENT_SELECTOR_USER_PRIVILEGE 0x3
|
||||||
|
#define SEGMENT_SELECTOR_USER_CS (0x20 | SEGMENT_SELECTOR_USER_PRIVILEGE)
|
||||||
|
#define SEGMENT_SELECTOR_USER_DS (0x28 | SEGMENT_SELECTOR_USER_PRIVILEGE)
|
@ -2,9 +2,12 @@ ENTRY (start)
|
|||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
. = 0x00100000;
|
. = 0xc0100000;
|
||||||
.text ALIGN (0x1000) : { *(.text*) *(.rodata*) }
|
kernel_start = .;
|
||||||
.init : {
|
.text ALIGN(0x1000) : AT(ADDR(.text) - 0xc0000000) {
|
||||||
|
*(.text*) *(.rodata*)
|
||||||
|
}
|
||||||
|
.init : AT(ADDR(.init) - 0xc0000000) {
|
||||||
early_initcalls_start = .;
|
early_initcalls_start = .;
|
||||||
*(.earlyinitcalls*)
|
*(.earlyinitcalls*)
|
||||||
early_initcalls_end = .;
|
early_initcalls_end = .;
|
||||||
@ -12,7 +15,13 @@ SECTIONS
|
|||||||
*(.driversubsysinitcalls*)
|
*(.driversubsysinitcalls*)
|
||||||
*(.deviceinitcalls*)
|
*(.deviceinitcalls*)
|
||||||
initcalls_end = .;
|
initcalls_end = .;
|
||||||
|
*(.init*)
|
||||||
}
|
}
|
||||||
.data ALIGN (0x1000) : { *(.data*) }
|
.data ALIGN(0x1000) : AT(ADDR(.data) - 0xc0000000) {
|
||||||
.bss : { *(.bss*) *(COMMON*) }
|
*(.data*)
|
||||||
|
}
|
||||||
|
.bss : AT(ADDR(.bss) - 0xc0000000) {
|
||||||
|
*(.bss*) *(COMMON*)
|
||||||
|
}
|
||||||
|
kernel_end = .;
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,7 @@ aedrix-boot.img: aedrix-kernel.elf
|
|||||||
$(V)mcopy -i "$@" aedrix-kernel.elf ::kernel.bin
|
$(V)mcopy -i "$@" aedrix-kernel.elf ::kernel.bin
|
||||||
$(V)mcopy -i "$@" arch/i386/syslinux.cfg ::syslinux.cfg
|
$(V)mcopy -i "$@" arch/i386/syslinux.cfg ::syslinux.cfg
|
||||||
|
|
||||||
OBJS_$(d) := $(d)/start.o \
|
OBJS_$(d) := $(d)/start.o
|
||||||
$(d)/i386_main.o
|
|
||||||
|
|
||||||
KOBJS += $(OBJS_$(d))
|
KOBJS += $(OBJS_$(d))
|
||||||
|
|
||||||
|
@ -18,39 +18,128 @@
|
|||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.global start /* making entry point visible to linker */
|
#include <arch/segmentation.h>
|
||||||
|
|
||||||
/* setting up the Multiboot header - see GRUB docs for details */
|
#define KERNEL_START_VIRTUAL 0xc0000000
|
||||||
.set ALIGN, 1<<0 /* align loaded modules on page boundaries */
|
#define KERNEL_START_PAGE (KERNEL_START_VIRTUAL >> 22)
|
||||||
.set MEMINFO, 1<<1 /* provide memory map */
|
#define virt_to_phys(addr) (addr - KERNEL_START_VIRTUAL)
|
||||||
.set FLAGS, ALIGN | MEMINFO /* this is the Multiboot 'flag' field */
|
|
||||||
.set MAGIC, 0x1BADB002 /* 'magic number' lets bootloader find the header */
|
#define STACK_SIZE 0x4000 /* 16k */
|
||||||
.set CHECKSUM, -(MAGIC + FLAGS) /* checksum required */
|
|
||||||
|
/* setup multiboot header */
|
||||||
|
#define ALIGN (1<<0) /* align loaded modules on page boundaries */
|
||||||
|
#define MEMINFO (1<<1) /* provide memory map */
|
||||||
|
#define FLAGS (ALIGN | MEMINFO) /* this is the Multiboot 'flag' field */
|
||||||
|
#define MAGIC 0x1BADB002 /* 'magic number' lets bootloader find the header */
|
||||||
|
#define CHECKSUM (-(MAGIC + FLAGS)) /* checksum required */
|
||||||
|
|
||||||
.align 4
|
.align 4
|
||||||
.long MAGIC
|
.long MAGIC
|
||||||
.long FLAGS
|
.long FLAGS
|
||||||
.long CHECKSUM
|
.long CHECKSUM
|
||||||
|
|
||||||
/* reserve initial kernel stack space */
|
/*
|
||||||
.set STACKSIZE, 0x4000 /* that is, 16k. */
|
* Kernel entry in assembly for i386 architecture. This handles saving off
|
||||||
.align 32
|
* multiboot information, setting up initial page tables to map the kernel to
|
||||||
.lcomm stack, STACKSIZE /* reserve 16k stack on a doubleword boundary */
|
* where it is linked against, ensures segmentation is setup right (large segments
|
||||||
.comm mbd, 4 /* we will use this in i386_main */
|
* over entire address range), and finally jumps to the kernel's main() function
|
||||||
.comm magic, 4 /* we will use this in i386_main */
|
* in C.
|
||||||
|
*/
|
||||||
|
.global start
|
||||||
start:
|
start:
|
||||||
movl $(stack + STACKSIZE), %esp /* set up the stack */
|
movl %eax, virt_to_phys(magic) /* Save off multiboot magic number */
|
||||||
movl %eax, magic /* Multiboot magic number */
|
movl %ebx, virt_to_phys(mbd) /* Save off multiboot data structure */
|
||||||
movl %ebx, mbd /* Multiboot data structure */
|
|
||||||
|
|
||||||
call i386_main /* call kernel proper */
|
movl $virt_to_phys(init_page_dir), %eax /* load page directory base register */
|
||||||
|
movl %eax, %cr3
|
||||||
|
|
||||||
|
movl %cr4, %eax
|
||||||
|
orl $0x00000010, %eax /* set PSE bit for 4mb pages */
|
||||||
|
movl %eax, %cr4
|
||||||
|
|
||||||
|
movl %cr0, %eax
|
||||||
|
orl $0x80000000, %eax /* set PG bit to enable paging */
|
||||||
|
movl %eax, %cr0
|
||||||
|
|
||||||
|
lea paging_enabled, %eax
|
||||||
|
jmp *%eax
|
||||||
|
paging_enabled:
|
||||||
|
movl $0, init_page_dir /* unmap identity mapping and invalidate */
|
||||||
|
invlpg 0
|
||||||
|
|
||||||
|
movl $(stack + STACK_SIZE), %esp /* set up the stack */
|
||||||
|
|
||||||
|
/* setup two large kernel segments over entire 4gb address range */
|
||||||
|
pushl $initial_gdt /* setup the pointer to the GDT */
|
||||||
|
pushw $(INITIAL_GDT_SIZE-1)
|
||||||
|
lgdt (%esp)
|
||||||
|
addl $6, %esp
|
||||||
|
ljmp $SEGMENT_SELECTOR_KERNEL_CS, $gdt_reload /* long jump to set %cs */
|
||||||
|
gdt_reload:
|
||||||
|
|
||||||
|
/* reset remaining segment registers */
|
||||||
|
movl $SEGMENT_SELECTOR_KERNEL_DS, %eax
|
||||||
|
movl %eax, %ds
|
||||||
|
movl %eax, %es
|
||||||
|
movl %eax, %fs
|
||||||
|
movl %eax, %gs
|
||||||
|
movl %eax, %ss
|
||||||
|
|
||||||
|
call main /* call kernel proper */
|
||||||
|
|
||||||
cli
|
cli
|
||||||
hang:
|
hang:
|
||||||
hlt /* halt machine should kernel return */
|
hlt /* halt machine should kernel return */
|
||||||
jmp hang
|
jmp hang
|
||||||
|
|
||||||
.globl atags_ptr
|
.section .init
|
||||||
|
|
||||||
|
/* Note: if the offsets into the GDT change, they must be updated in arch/segmentation.h */
|
||||||
|
.set INITIAL_GDT_SIZE, 8*6
|
||||||
|
initial_gdt:
|
||||||
|
.long 0x00000000 /* 0x00 intentionally empty */
|
||||||
|
.long 0x00000000
|
||||||
|
.long 0x00000000 /* 0x08 TODO TSS */
|
||||||
|
.long 0x00000000
|
||||||
|
.long 0x0000ffff /* 0x10 kernel code segment (%cs) */
|
||||||
|
.long 0x00cf9a00
|
||||||
|
.long 0x0000ffff /* 0x18 kernel data segment (%ds) */
|
||||||
|
.long 0x00cf9200
|
||||||
|
.long 0x0000ffff /* 0x20 userspace code segment (%cs) */
|
||||||
|
.long 0x00cffa00
|
||||||
|
.long 0x0000ffff /* 0x28 userspace data segment (%ds) */
|
||||||
|
.long 0x00cff200
|
||||||
|
|
||||||
|
.align 0x1000
|
||||||
|
init_page_dir:
|
||||||
|
/* This page directory entry identity-maps the first 4MB of the 32-bit physical address space.
|
||||||
|
All bits are clear except the following:
|
||||||
|
bit 7: PS The kernel page is 4MB.
|
||||||
|
bit 1: RW The kernel page is read/write.
|
||||||
|
bit 0: P The kernel page is present.
|
||||||
|
This entry must be here -- otherwise the kernel will crash immediately after paging is
|
||||||
|
enabled because it can't fetch the next instruction! It's ok to unmap this page later. */
|
||||||
|
.long 0x00000083
|
||||||
|
.rept (KERNEL_START_PAGE - 1)
|
||||||
|
.long 0 /* Pages before kernel space. */
|
||||||
|
.endr
|
||||||
|
/* This page directory entry defines a 4MB page containing the kernel. */
|
||||||
|
.long 0x00000083
|
||||||
|
.rept (1024 - KERNEL_START_PAGE - 1)
|
||||||
|
.long 0 /* Pages after the kernel image. */
|
||||||
|
.endr
|
||||||
|
|
||||||
|
/* reserve initial kernel stack space */
|
||||||
|
.align 32
|
||||||
|
.lcomm stack, STACK_SIZE /* reserve stack space on a doubleword boundary */
|
||||||
|
|
||||||
|
/* place to store multiboot header information */
|
||||||
|
.global mbd
|
||||||
|
.comm mbd, 4 /* we will use this in i386_main */
|
||||||
|
.global magic
|
||||||
|
.comm magic, 4 /* we will use this in i386_main */
|
||||||
|
|
||||||
|
/* TODO FIXME remove this - needs fix to dependencies first */
|
||||||
|
.global atags_ptr
|
||||||
atags_ptr:
|
atags_ptr:
|
||||||
.word 0
|
.long 0
|
||||||
|
Loading…
Reference in New Issue
Block a user