summaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
authorMichal Idziorek <m.i@gmx.at>2014-06-24 13:53:31 +0200
committerMichal Idziorek <m.i@gmx.at>2014-06-24 13:53:31 +0200
commita99ca43066ba246475809a0e805bf52e8195debd (patch)
tree1883030e358c15231599160ff1ce027b0cc20d22 /boot
Initial commit of FoolOS
FoolOS - the most useless OS in history.
Diffstat (limited to 'boot')
-rw-r--r--boot/GDT.asm36
-rw-r--r--boot/common.asm105
-rw-r--r--boot/common_pm.asm76
-rw-r--r--boot/fill.asm1
-rw-r--r--boot/kernel_entry.asm10
-rw-r--r--boot/mbr.asm255
-rw-r--r--boot/old.asm56
-rw-r--r--boot/pm.asm27
8 files changed, 566 insertions, 0 deletions
diff --git a/boot/GDT.asm b/boot/GDT.asm
new file mode 100644
index 0000000..27514de
--- /dev/null
+++ b/boot/GDT.asm
@@ -0,0 +1,36 @@
+gdt_start:
+
+gdt_null: ;null descriptor (2 x 4 bytes)
+ dd 0x0
+ dd 0x0
+
+gdt_code:
+ ; flags:
+ ; present: 1 / privilege: 00 / type: 1
+ ; code: 1 / conforming: 0 / readable: 1 / accessed: 0
+ ; granularity: 1 / 32-bit default: 1 / 64-bit seg: 0 / AVL: 0
+ dw 0xffff ;limit
+ dw 0x0 ;base
+ db 0x0 ;base
+ db 10011010b ;flags
+ db 11001111b ;flags & seg.limit
+ db 0x0 ;base
+
+gdt_data:
+ ; flags:
+ ; code: 0 / expand down: 0 / writable: 1 / accessed: 0
+ dw 0xffff
+ dw 0x0
+ db 0x0
+ db 10010010b
+ db 11001111b
+ db 0x0
+
+gdt_end:
+
+gdt_descriptor:
+ dw gdt_end-gdt_start-1
+ dd gdt_start
+
+CODE_SEG equ gdt_code - gdt_start
+DATA_SEG equ gdt_data - gdt_start
diff --git a/boot/common.asm b/boot/common.asm
new file mode 100644
index 0000000..02e1a0b
--- /dev/null
+++ b/boot/common.asm
@@ -0,0 +1,105 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;; Miguel's FoolOS Helper Functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[bits 16]
+
+
+;global data
+STR_HEX_OUT:
+ db "0x0000",0
+
+;print_string routine ([bx])
+;this routine will print a null terminated string at [bx] to the screen.
+print_string:
+
+ pusha ;push all registers
+ mov ah,0x0e
+
+ print_string_loop:
+
+ ;check if value at [bx] is "\0" (end of string)
+ mov cl,[bx]
+ cmp cl,0
+ je print_string_finish
+
+ ;otherwise instruct BIOS to print the current char
+ mov al,cl
+ int 0x10
+
+ ;proceed with next char
+ inc bx
+ jmp print_string_loop
+
+ print_string_finish:
+
+ popa ;pop all registers
+ ret ;return to caller
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;print_hex routine (dx)
+;will print the value of the bx register as hex to the screen
+print_hex:
+
+ pusha
+
+ ;begin with last hex val (hex_out[5])
+ mov bx,STR_HEX_OUT+5
+
+ ;lets loop throuth all 4 'digits'
+ print_hex_loop:
+
+ ;get least significan hex digit to cx
+ mov cx,dx
+ and cx,0x000F
+
+ ;check range (0-9 vs a-f)
+ cmp cx,10
+ jl print_hex_setnum
+
+ ;set hex a-f
+ mov al,'A'-10
+ add al,cl
+ jmp print_hex_al
+
+ ;set hex 0-9
+ print_hex_setnum:
+ mov al,'0'
+ add al,cl
+
+ ; set hex_out[bx] to al
+ print_hex_al:
+ mov [bx],al
+
+ ;proceed with the next significant hex 'digit'
+ dec bx
+ shr dx,4
+
+ ;check if finished (otherwise loop)
+ cmp bx,STR_HEX_OUT+1
+ jne print_hex_loop
+
+ ;output complete hex string and return to caller
+ mov bx,STR_HEX_OUT
+ call print_string
+ popa
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;disk_load routune (load dh sectors from drive dl to es:bx)
+disk_load:
+
+ pusha
+
+ mov ah,0x02 ;BIOS read sector func
+ mov al,dh ;read dh sectors (amount)
+ mov ch,0x00 ;cyl 0
+ mov dh,0x00 ;head 0
+ mov cl,0x02 ;start at sector 2
+
+ int 0x13 ;bios interrupt
+
+ popa
+ ret
+
diff --git a/boot/common_pm.asm b/boot/common_pm.asm
new file mode 100644
index 0000000..40bc32f
--- /dev/null
+++ b/boot/common_pm.asm
@@ -0,0 +1,76 @@
+[bits 32]
+
+VIDEO_MEM equ 0xb8000
+WHITE_ON_BLACK equ 0x0f
+
+;global data
+STR_HEX_OUT_PM:
+ db "0x0000",0
+
+; print [ebx] at ecx
+print_string_pm:
+ pusha
+ mov edx, VIDEO_MEM
+ add edx,ecx
+ print_string_pm_loop:
+ mov al,[ebx]
+ mov ah, WHITE_ON_BLACK
+ cmp al,0
+ je print_string_pm_done
+ mov [edx],ax
+ add ebx,1
+ add edx,2
+ jmp print_string_pm_loop
+
+print_string_pm_done:
+ popa
+ ret
+
+;print_hex_pm routine (dx) at ecx
+;will print the value of the bx register as hex to the screen
+print_hex_pm:
+
+ pusha
+
+
+ ;begin with last hex val (hex_out[5])
+ mov bx,STR_HEX_OUT_PM+5
+
+ ;lets loop throuth all 4 'digits'
+ print_hex_pm_loop:
+
+ ;get least significan hex digit to cx
+ mov cx,dx
+ and cx,0x000F
+
+ ;check range (0-9 vs a-f)
+ cmp cx,10
+ jl print_hex_pm_setnum
+
+ ;set hex a-f
+ mov al,'A'-10
+ add al,cl
+ jmp print_hex_pm_al
+
+ ;set hex 0-9
+ print_hex_pm_setnum:
+ mov al,'0'
+ add al,cl
+
+ ; set hex_out[bx] to al
+ print_hex_pm_al:
+ mov [bx],al
+
+ ;proceed with the next significant hex 'digit'
+ dec bx
+ shr dx,4
+
+ ;check if finished (otherwise loop)
+ cmp bx,STR_HEX_OUT_PM+1
+ jne print_hex_pm_loop
+
+ ;output complete hex string and return to caller
+ popa
+ mov bx,STR_HEX_OUT_PM
+ call print_string_pm
+ ret
diff --git a/boot/fill.asm b/boot/fill.asm
new file mode 100644
index 0000000..1717006
--- /dev/null
+++ b/boot/fill.asm
@@ -0,0 +1 @@
+times 2000000 db 0xff
diff --git a/boot/kernel_entry.asm b/boot/kernel_entry.asm
new file mode 100644
index 0000000..77bb2a5
--- /dev/null
+++ b/boot/kernel_entry.asm
@@ -0,0 +1,10 @@
+[bits 32]
+
+[extern kernel_main]
+[extern int0]
+
+call kernel_main ; jumps in the world of C
+call int0 ; jumps in the world of C
+ret
+
+jmp $
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 <m.i@gmx.at>
+;
+; 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:
+
+
+
+
diff --git a/boot/old.asm b/boot/old.asm
new file mode 100644
index 0000000..a7a1b24
--- /dev/null
+++ b/boot/old.asm
@@ -0,0 +1,56 @@
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;read data from disk
+;mov bx,0x9000 ;destination(es:bx)
+;mov dh,1 ;number of sectors
+;mov dl,[BOOT_DRIVE] ;source disk
+;call disk_load
+
+;print data loaded form disk
+;mov dx,[0x9000]
+;call print_hex
+
+;mov dx,[0x9000+256]
+;call print_hex
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;;; COM1 infinite loop ;;;;;
+;
+; COM1_PORT equ 0xD000
+; mov dx,COM1_PORT
+; mov ecx,160*2
+;
+; ; loop and write all data other than 0x0
+; com1_loop:
+;
+; in ax,dx ; read port val
+;
+; cmp ax,0xffff
+; je com1_skip
+;
+; cmp ax,0x0
+; je com1_skip
+;
+; call print_hex_pm
+; add ecx,14
+; pusha
+; mov dx,ax
+; call print_hex_pm
+; popa
+; add ecx,26
+;
+; com1_skip:
+;
+; inc dx
+; ;call print_hex_pm
+; cmp dx,COM1_PORT+0x300
+; jne com1_loop
+; mov dx,COM1_PORT
+; mov ecx,160*2
+; jmp com1_loop
+;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
diff --git a/boot/pm.asm b/boot/pm.asm
new file mode 100644
index 0000000..c66ab4f
--- /dev/null
+++ b/boot/pm.asm
@@ -0,0 +1,27 @@
+[bits 16]
+switch_to_pm:
+
+ cli ;switch off interrupts!
+ lgdt [gdt_descriptor] ;load descriptor table!
+
+ ;switch on 32-bit protected mode
+ mov eax, cr0
+ or eax,0x1
+ mov cr0, eax
+
+ jmp CODE_SEG:init_pm
+
+[bits 32]
+init_pm:
+
+ mov ax, DATA_SEG
+ mov ds, ax
+ mov ss, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+
+ mov ebp, 0x90000
+ mov esp, ebp
+
+ call boot_32_pm ;continue booting in 32-bit protected mode