diff options
Diffstat (limited to 'arch/x86/boot/setup.s')
-rw-r--r-- | arch/x86/boot/setup.s | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/arch/x86/boot/setup.s b/arch/x86/boot/setup.s new file mode 100644 index 0000000..2a0ab15 --- /dev/null +++ b/arch/x86/boot/setup.s @@ -0,0 +1,111 @@ +/* + setup.s is second stage bootloader loaded at 0x90200 (by + first stage), is responsible for getting the system data + from the BIOS. + + System data puts at special place: 0x90000-0x901FF. +*/ + +.code16 # Tell GAS to generate 16 bit code + +.include "bios.inc" +.include "rm_seg.inc" + +# Define some constants for the GDT segment descriptor offsets +.set CODESEG, gdt_code - gdt_start +.set DATASEG, gdt_data - gdt_start + +.global _start # Make the symbol visible to ld +_start: + mov $SDATASEG, %ax + mov %ax, %ds + mov $KERNSEG, %ax + mov %ax, %es + + BIOS_PRINT $get_data_msg + # TODO: get memory size + # TODO: get video infos + +load_kernel: # Load our kernel + BIOS_PRINT $boot_load_kern_msg + + mov $0x02, %ah # Set BIOS read sector routine + mov (0), %dl # Read drive boot + mov $0x00, %ch # Select cylinder 0 + mov $0x00, %dh # Select head 0 [has a base of 0] + mov $0x02+SETUPLEN, %cl # Select sector 2 (next after the + # boot sector) [has a base of 1] + mov $0x10, %al # Read 16 sectors + mov $0x00, %bx # Load sectors to ES:BX ($KERNSEG:0) + int $0x13 # Start reading from drive + jc disk_error # If carry flag set, bios failed to read + +switch_to_pm: + BIOS_PRINT $boot_prot_mode_msg + cli # Switch of interrupt until we have set + # up the protected mode interrupt vector + lgdt gdt_descriptor # Load our global descriptor table + + mov %cr0, %eax # Set the first bit of CR0 + or $0x01, %eax # to make the switch to protected mode + mov %eax, %cr0 + + # Make a far jump to our 32-bit code. + # This also forces the CPU to flush its cache of pre-fetched + # and real-mode decoded instructions, which can cause problems + jmp $CODESEG, $KERNADDR + +disk_error: + BIOS_PRINT $disk_error_msg + jmp . + +# Global Descriptor Table (contains 8-byte entries) +gdt_start: +gdt_null: # The mandatory null descriptor + .quad 0x0 + +gdt_code: # The code segment descriptor + # Base = 0x0, limit = 0xfffff + # 1st flags: (present)1 (privilege)00 (descriptor type)1 -> b1001 + # Type flags: (code)1 (conforming)0 (readable)1 (accessed)0 -> b1010 + # 2nd flags: (granularity)1 (size)1 (64-bit seg)0 (AVL)0 -> b1100 + .word 0xffff # Limit (bits 0-15) + .word 0x0 # Base (bits 0-15) + .byte 0x0 # Base (bits 16-23) + .byte 0b10011010 # 1st flags, type flags + .byte 0b11001111 # 2nd flags, limit (bits 16-19) + .byte 0x0 # Base (bits 24-31) + +gdt_data: # the data segment descriptor + # Same as code segment except for the type flags: + # Type flags: (code)0 (direction)0 (writable)1, (accessed)0 -> b0010 + # P.S: direction bit: 0 the segment grows up + .word 0xffff # Limit (bits 0-15) + .word 0x0 # Base (bits 0-15) + .byte 0x0 # Base (bits 16-23) + .byte 0b10010010 # 1st flags, type flags + .byte 0b11001111 # 2nd flags, limit (bits 16-19) + .byte 0x0 # Base (bits 24-31) +gdt_end: + +# Global variables +gdt_descriptor: + # The 6-byte GDT structure containing: + # - GDT size, 2 bytes (size always less one of the real size): + .word gdt_end - gdt_start - 1 + # - GDT address, 4 bytes: + .word gdt_start, 0x9 + +get_data_msg: + .asciz "Getting the system data from the BIOS\r\n" + +boot_prot_mode_msg: + .asciz "Entering 32-bit protected mode\r\n" + +boot_load_kern_msg: + .asciz "Loading kernel into memory\r\n" + +disk_error_msg: + .asciz "Disk read error!" + +.space (512 * SETUPLEN) - (. - _start), 0 |