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/GDT.asm | 36 +++++++ boot/common.asm | 105 +++++++++++++++++++++ boot/common_pm.asm | 76 +++++++++++++++ boot/fill.asm | 1 + boot/kernel_entry.asm | 10 ++ boot/mbr.asm | 255 ++++++++++++++++++++++++++++++++++++++++++++++++++ boot/old.asm | 56 +++++++++++ boot/pm.asm | 27 ++++++ 8 files changed, 566 insertions(+) create mode 100644 boot/GDT.asm create mode 100644 boot/common.asm create mode 100644 boot/common_pm.asm create mode 100644 boot/fill.asm create mode 100644 boot/kernel_entry.asm create mode 100644 boot/mbr.asm create mode 100644 boot/old.asm create mode 100644 boot/pm.asm (limited to 'boot') 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 +; +; 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 -- cgit v1.2.3