Created
October 14, 2012 00:17
-
-
Save graphitemaster/3886709 to your computer and use it in GitHub Desktop.
gmbootloader
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "config.h" | |
/* | |
* The initial entry point called by the bootloader assembly routine stuff | |
* this is stage 2 (so to speak) | |
*/ | |
void gmboot_entry(void) { | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef GMBOOT_CONFIG_HDR | |
#define GMBOOT_CONFIG_HDR | |
#define GMBOOT_EXTMEM 0x100000 /* start of extended memory */ | |
#define GMBOOT_PHYTOP 0xE000000 /* top of physical memory */ | |
#define GMBOOT_DEVBEG 0xFE00000 /* device address space */ | |
#define GMBOOT_KERNEL 0x8000000 /* first kernel virtual address */ | |
/* | |
* Configuration settings below shouldn't need to be changed ever, | |
* unless you're a pro doing some serious crazy shit :P. | |
*/ | |
/* address where kernel is linked */ | |
#define GMBOOT_LINKED (GMBOOT_KERNEL + GMBOOT_EXTMEM) | |
/* | |
* Conversion between virtual and physical addresses used for the | |
* bootloaders C code | |
*/ | |
#define GMBOOT_VIRT2PHYS(A) (((unsigned int)(A)) - GMBOOT_KERNEL) | |
#define GMBOOT_PHYS2VIRT(A) (((void *) (A)) + GMBOOT_KERNEL) | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "config.h" | |
/* | |
* Some helper macros to better visualize how the GDT works, based on the X86 MMU | |
* these constants are pulled from the intel software manuals | |
*/ | |
#define SEG_NULLASM \ | |
.word 0, 0; \ | |
.byte 0, 0, 0, 0 | |
#define SEG_ASM(TYPE,BASE,LIMIT) \ | |
.word (((LIMIT) >> 12) & 0xFFFF), ((BASE) & 0xFFFF); \ | |
.byte (((BASE) >> 16) & 0xFF), (0x90 | (TYPE)), (0xC0 | (((LIMIT) >> 28) & 0xF)), (((BASE) >> 24) & 0xFF) | |
#define STA_X 0x8 /* executable */ | |
#define STA_E 0x4 /* expand down (non executable) */ | |
#define STA_C 0x4 /* conforming code (executbale only) */ | |
#define STA_W 0x2 /* writable (non-executable) */ | |
#define STA_R 0x2 /* readable (executable) */ | |
#define STA_A 0x1 /* accessed */ | |
/* | |
* Start the CPU in 16 bit mode, switches to 32-bit protected mode, and enters C | |
* the BIOS will load this code from the FIRST sector of the HDD into memory at | |
* physical address 0x7C00, and will start executing in real mode with %cs=0 and | |
* %ip=0x7C00. Once the A20-line is set it will long jump into 32-bit protected | |
* mode and call the second-stage boot-loader C code. | |
*/ | |
.code16 | |
.global gmboot_start | |
gmboot_start: | |
cli | |
// clear data and segment registers | |
xorw %ax,%ax | |
movw %ax,%ds | |
movw %ax,%es | |
movw %ax,%ss | |
// test and set A20 line | |
#define WAIT_A20(X) \ | |
inb $0x64, %al; \ | |
testb $0x02, %al; \ | |
jnz X | |
gmboot_a20_beg: | |
WAIT_A20(gmboot_a20_beg) | |
movb $0xD1, %al | |
outb %al, $0x64 | |
gmboot_a20_set: | |
WAIT_A20(gmboot_a20_set) | |
movb $0xDF, %al | |
outb %al, $0x60 | |
/* | |
* Switch from real to protected memory mode. This requires | |
* a boot-straped GDT that makes virtual addresses map to | |
* physicals ones, so that the effective memory map doesn't | |
* change during the transition into A20. | |
*/ | |
lgdt gmboot_gdtdesc | |
movl %cr0, %eax | |
orl $1, %eax /* CRO_PE: protection enabled is 1 */ | |
movl %eax, %cr0 | |
/* | |
* We now have set the A20 line, we can now jump into our 32-bit | |
* protected mode by using a long jump to reload %cs and %eip. | |
* The segement descriptors are set up with no translation to | |
* allow us to keep the mapping as the identity mapping. | |
*/ | |
ljmp $(1 << 3), $gmboot_main | |
.code32 | |
.extern gmboot_entry | |
gmboot_main: | |
movw $(1 << 3), %ax | |
movw %ax, %ds | |
movw %ax, %es | |
movw %ax, %ss | |
movw $0, %ax | |
movw %ax, %fs | |
movw %ax, %gs | |
/* | |
* Write the stage description piece, then jump into stage2 | |
* where all the magic happens :) | |
*/ | |
mov $65, %al | |
call gmboot_putch | |
/* | |
* Setup the protected-mode data segment registers, then we can | |
* setup our stack pointer to call into the actual bootloaders | |
* C code. | |
*/ | |
movl $gmboot_start, %esp | |
call gmboot_entry | |
/* | |
* gmboot_entry shouldn't return, unless there is some serious | |
* problems. So we can trigger a break-point for bochs for | |
* debugging, this is a feature :) | |
*/ | |
#ifdef GMBOOT_DEBUG | |
movw $0x8A00, %ax | |
movw %ax, %dx | |
outw %ax, %dx | |
movw $0x8AE0, %ax | |
outw %ax, %dx | |
/* | |
* Once entered it will never return/exit | |
* (required for debuggin in bochs) | |
*/ | |
jmp gmboot_halt | |
#endif | |
/* | |
* Used to halt if there is an error in the first-stage bootloader | |
* think of this is a for(;;) | |
*/ | |
gmboot_halt: | |
jmp gmboot_halt | |
/* | |
* Bootstraped global descriptor table, this needs to be aligned | |
* for 4-bytes. | |
*/ | |
.p2align 2 | |
gmboot_gdt: | |
SEG_NULLASM | |
SEG_ASM(STA_X|STA_R, 0x0, 0xFFFFFFFF) | |
SEG_ASM(STA_W, 0x0, 0xFFFFFFFF) | |
gmboot_gdtdesc: | |
.word (gmboot_gdtdesc - gmboot_gdt - 1) /* sizeof(gmboot_gdt) - 1 */ | |
.long gmboot_gdt /* addr of descriptor table */ | |
.org 510, 0 | |
.byte 0x55 | |
.byte 0xAA |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CFLAGS = -nostdinc -nostdlib -ffreestanding -m32 -fno-pic | |
CC ?= gcc | |
DD ?= dd | |
OBJDUMP = objdump | |
OBJCOPY = objcopy | |
HEXDUMP = hexdump | |
boot: main.S boot.c | |
$(CC) $(CFLAGS) -c boot.c | |
$(CC) $(CFLAGS) -c main.S | |
$(LD) -m elf_i386 -N -e gmboot_start -Ttext 0x7C00 -o boot.bin main.o boot.o | |
$(OBJCOPY) -S -O binary -j .text boot.bin boot.bin | |
$(DD) if=/dev/zero of=boot.img bs=512 count=1 | |
$(DD) if=boot.bin of=boot.img conv=notrunc bs=512 | |
$(HEXDUMP) -C boot.img |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment