summaryrefslogtreecommitdiffstats
path: root/arch/x86/boot/setup.s
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/boot/setup.s')
-rw-r--r--arch/x86/boot/setup.s111
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