summaryrefslogtreecommitdiff
path: root/boot/mbr.asm
blob: 41568c43e6aa83c44ad06e6ce74859f91fbe09a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
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: