From a99ca43066ba246475809a0e805bf52e8195debd Mon Sep 17 00:00:00 2001 From: Michal Idziorek Date: Tue, 24 Jun 2014 13:53:31 +0200 Subject: Initial commit of FoolOS FoolOS - the most useless OS in history. --- boot/mbr.asm | 255 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100644 boot/mbr.asm (limited to 'boot/mbr.asm') diff --git a/boot/mbr.asm b/boot/mbr.asm new file mode 100644 index 0000000..41568c4 --- /dev/null +++ b/boot/mbr.asm @@ -0,0 +1,255 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; FoolOS Boot Loader +; +; Copyright 2014 M.Idziorek +; +; we have just been loaded by the BIOS and are in 16-bits real mode! +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;we want 16-bit instructions, before we switch to 32-bit protected mode. +[bits 16] + +;define origin of boot record in memory: 0x7c00 +;this is where the BIOS per definition will put the first +;512 bytes of data from the boot device +;The Boot record is identified by the last 2 magic bytes: 0xaa55 (?) +[org 0x7c00] + +;define where we will load our kernel into memory +KERNEL_OFFSET equ 0x1000 + +jmp boot_16 ;start boot process + +;Global Data +INT_COUNT: + db 0 +STR_VERSION: + db "_<-Fool-Loader~0.0.8~",0 +STR_PROT: + db "Entered 32-bit Protected Mode.",0 +STR_LOADED: + db "FoolOS Kernel Loaded.",0 +BOOT_DRIVE: + db 0 + +[bits 32] +; default interrupt handler +interrupt: + + mov al, 0xA0 ; set bit 4 of OCW 2 + out 0xA0, al ; write to primary PIC command register + + mov al, 0x20 ; set bit 4 of OCW 2 + out 0x20, al ; write to primary PIC command register + + iret + +;handle keyboard interrupt +interrupt2: + + +; mov eax,[INT_COUNT] +; inc eax +; mov [INT_COUNT],eax + + in al,0x60 + mov [INT_COUNT],al + +; call KERNEL_OFFSET+(idt_end-idt_start)+1 ;jump into our Kernel it + + ; will follow our + ; interrupt table + + ; out 0x60,al + + + mov al, 0x20 ; set bit 4 of OCW 2 + out 0x20, al ; write to primary PIC command register + + iret + +;lets put our temporary GDT (Global Descriptor Table) here +%include "boot/GDT.asm" + +;include 16-bit real mode routines (print_string, print_hex, disk_load) +%include "boot/common.asm" + +;include 32-bit Protected Mode routines (print_string_pm,print_hex_pm) +%include "boot/common_pm.asm" + +;include our routines for switching to 32-bit protected mode +%include "boot/pm.asm" + +;;;;;;;; BOOT 16-bit real ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;lets start +[bits 16] +boot_16: + + ;setup the stack + mov bp,0x8000 + mov sp,bp + + ;remember BOOT_DRIVE (as was set by BIOS) + mov [BOOT_DRIVE],dl + + ;print FoolOS version info + mov bx, STR_VERSION + call print_string + + ;Load the KERNEL + mov bx,KERNEL_OFFSET + mov dh, 15 + mov dl, [BOOT_DRIVE] + call disk_load + + mov bx, STR_LOADED + call print_string + + ;lets enter Protected mode! + call switch_to_pm + +;;;;;;;; BOOT 32-bit protected mode;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +[bits 32] +boot_32_pm: + + mov ecx,160 + mov ebx,STR_PROT + call print_string_pm + + ;enable A20 + ;http://www.brokenthorn.com/Resources/OSDev9.html + ;Method 3.1: Enables A20 through keyboard controller + mov al, 0xdd ; command 0xdd: enable a20 + out 0x64, al ; send command to controller + + lidt [idt_descriptor] ;load descriptor table! + + ;pollkb example +; pollkb: +; mov cx,320 +; mov ax,0 +; in al,0x60 +; mov dx,ax +; call print_hex_pm +; jmp pollkb +; + ;mov al,11111101b + ;out 0x61, al + + + sti ;enable interrupts + +;************************************************************************ +; Map the 8259A PIC to use interrupts 32-47 within our interrupt table +;************************************************************************ + +%define ICW_1 0x11 ; 00010001 binary. Enables initialization mode and we are sending ICW 4 + +%define PIC_1_CTRL 0x20 ; Primary PIC control register +%define PIC_2_CTRL 0xA0 ; Secondary PIC control register + +%define PIC_1_DATA 0x21 ; Primary PIC data register +%define PIC_2_DATA 0xA1 ; Secondary PIC data register + +%define IRQ_0 0x20 ; IRQs 0-7 mapped to use interrupts 0x20-0x27 +%define IRQ_8 0x28 ; IRQs 8-15 mapped to use interrupts 0x28-0x36 + +MapPIC: + +; Send ICW 1 - Begin initialization ------------------------- + + ; Setup to initialize the primary PIC. Send ICW 1 + + mov al, ICW_1 + out PIC_1_CTRL, al + +; Send ICW 2 - Map IRQ base interrupt numbers --------------- + + ; Remember that we have 2 PICs. Because we are cascading with this second PIC, send ICW 1 to second PIC command register + + out PIC_2_CTRL, al + + ; send ICW 2 to primary PIC + + mov al, IRQ_0 + out PIC_1_DATA, al + + ; send ICW 2 to secondary controller + + mov al, IRQ_8 + out PIC_2_DATA, al + +; Send ICW 3 - Set the IR line to connect both PICs --------- + + ; Send ICW 3 to primary PIC + + mov al, 0x4 ; 0x04 => 0100, second bit (IR line 2) + out PIC_1_DATA, al ; write to data register of primary PIC + + ; Send ICW 3 to secondary PIC + + mov al, 0x2 ; 010=> IR line 2 + out PIC_2_DATA, al ; write to data register of secondary PIC + +; Send ICW 4 - Set x86 mode -------------------------------- + + mov al, 1 ; bit 0 enables 80x86 mode + + ; send ICW 4 to both primary and secondary PICs + + out PIC_1_DATA, al + out PIC_2_DATA, al + +; All done. Null out the data registers + + mov al, 0 + out PIC_1_DATA, al + out PIC_2_DATA, al + + ;mask +in al, 0x21 ; read in the primary PIC Interrupt Mask Register (IMR) +and al, 0x00 ; 0xEF => 11101111b. This sets the IRQ4 bit (Bit 5) in AL +out 0x21, al ; write the value back into IMR + + +in al, 0xA1 ; read in the primary PIC Interrupt Mask Register (IMR) +and al, 0x00 ; 0xEF => 11101111b. This sets the IRQ4 bit (Bit 5) in AL +out 0xA1, al ; write the value back into IMR + + + + call KERNEL_OFFSET+(idt_end-idt_start) ;jump into our Kernel it + ; will follow our + ; interrupt table + +idt_descriptor: + dw idt_end-idt_start-1 + dd KERNEL_OFFSET + + +;;;; DEBUGGING STUFF +times 8 db '@' +dw interrupt +db '@' +dw interrupt2 + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;so we get identified as MBR +times 510-($-$$) db 0 +dw 0xaa55 + +;interrupt descriptor table (hardcoded address of interrupts:) +idt_start: +times 33 db 0x50,0x7c,0x08,0x00,0x00,10001110b,0x0,0x0 +db 0x59,0x7c,0x08,0x00,0x00,10001110b,0x0,0x0 +times 253 db 0x50,0x7c,0x08,0x00,0x00,10001110b,0x0,0x0 +idt_end: + + + + -- cgit v1.2.3