Repository navigation
Expand file tree
/
Copy pathboot.asm
More file actions
117 lines (95 loc) · 2.79 KB
/
Copy pathboot.asm
File metadata and controls
117 lines (95 loc) · 2.79 KB
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
[org 0x7C00]
[bits 16]
start:
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7C00
KERNEL_LOAD_ADDR equ 0x7E00
mov [boot_drive], dl ; BIOS passes boot drive number in dl — save it
mov si, msg
call print_string
mov bx, 0x7E00 ; destination offset (es already 0)
mov dh, 128 ; number of sectors to read (64KB kernel budget)
mov dl, [boot_drive]
call disk_load
call switch_to_pm
jmp $ ; jump into protected mode here
enable_a20:
in al, 0x92
or al, 2
out 0x92, al ; fast A20 enable via system control port
ret
gdt_start:
dq 0x0 ; null descriptor
gdt_code: ; code segment descriptor
dw 0xFFFF ; limit (low)
dw 0x0 ; base (low)
db 0x0 ; base (mid)
db 10011010b ; access: present, ring0, code, exec/read
db 11001111b ; flags + limit (high): 4K granularity, 32-bit
db 0x0 ; base (high)
gdt_data: ; data segment descriptor
dw 0xFFFF
dw 0x0
db 0x0
db 10010010b ; access: present, ring0, data, read/write
db 11001111b
db 0x0
gdt_end:
gdt_descriptor:
dw gdt_end - gdt_start - 1 ; size of GDT, minus 1
dd gdt_start ; linear address of GDT
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start
switch_to_pm:
call enable_a20
cli ; no interrupts during the switch
lgdt [gdt_descriptor]
mov eax, cr0
or eax, 0x1
mov cr0, eax ; set PE bit — we are now in protected mode
jmp CODE_SEG:init_pm ; far jump: flushes CPU pipeline, loads CS
[bits 32]
init_pm:
mov ax, DATA_SEG ; reload all data-segment registers
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, 0x90000 ; new 32-bit stack
mov ebp, esp
jmp KERNEL_LOAD_ADDR ; hand off to loaded kernel
disk_load:
push dx
mov ah, 0x02
mov al, dh
mov ch, 0x00
mov cl, 0x02
mov dh, 0x00
int 0x13
jc disk_error
pop dx ; restore original dx (with requested sector count in dh)
cmp al, dh
jne disk_error
ret
disk_error:
mov si, disk_err_msg
call print_string
jmp $
print_string:
lodsb
or al, al
jz .done
mov ah, 0x0E
int 0x10
jmp print_string
.done:
ret
boot_drive db 0
msg db 'Booting...', 0
disk_err_msg db 'Disk error!', 0
times 510-($-$$) db 0
dw 0xAA55