]> git.dujemihanovic.xyz Git - nameless-os.git/blob - boot/x86/mbr.s
8089b2f27e244bbbe1aeecb1477f691d77152b77
[nameless-os.git] / boot / x86 / mbr.s
1 ; x86 bootloader for nameless-os, MBR portion
2
3 bits 16
4 cpu 686
5 org 0x600
6
7 _start:
8 cli
9 ; set up segment registers
10 xor ax, ax
11 mov ds, ax
12 mov es, ax
13 mov ss, ax
14 mov sp, 0x7c00 ; just under the soon-to-be-loaded VBR, should be more than sufficient space
15
16 ; perform self-relocation
17 cld
18 mov si, 0x7c00
19 mov di, 0x600
20 mov cx, 0x100 ; 256 words = 512 bytes
21 rep movsw
22 ; some BIOSes may set CS to 0x7c0, work around that
23 jmp 0:real_start
24 real_start:
25 sti
26 ; check for int 13h ext
27 call check_int13_ext
28 mov byte [BOOT_DRIVE], dl
29 ; look for active partition
30 mov bx, part_1
31 mov cx, 4
32 .check_part_loop:
33 mov al, [bx]
34 test al, 0x80
35 jnz .part_found
36 add bx, 16
37 loop .check_part_loop
38 .error:
39 mov si, no_os
40 call print
41 cli
42 hlt
43 jmp short $-1
44 .part_found:
45 ; look for any other active partitions, if they exist the partition table is invalid
46 cmp cx, 0
47 je .load_vbr
48 push bx
49 .look_other_loop:
50 add bx, 16
51 mov al, [bx]
52 test al, 0x80
53 jnz .invalid_mbr
54 loop .look_other_loop
55 .load_vbr:
56 ; load active partition's VBR
57 pop bx
58 mov ax, 0x7c0
59 mov edx, [bx+0x8]
60 push bx ; save pointer to partition table entry
61 xor bx, bx
62 call read_sector
63 ; check is the VBR bootable (ends with 0x55 0xaa), if not halt
64 cmp word [0x7dfe], 0xaa55
65 jne .not_bootable
66 mov dl, [BOOT_DRIVE]
67 pop si ; hand off partition table entry to VBR
68 jmp 0x7c00
69 .not_bootable:
70 mov si, no_os
71 call print
72 cli
73 hlt
74 jmp short $-1
75 .invalid_mbr:
76 mov si, invalid_mbr
77 call print
78 cli
79 hlt
80 jmp short $-1
81 check_int13_ext:
82 pusha
83 mov ah, 0x41
84 mov bx, 0x55aa
85 mov dl, 0x80
86 int 0x13
87 jc .no_ext
88 test cx, 1
89 jz .no_ext
90 popa
91 ret
92 .no_ext:
93 mov si, no_int13_ext
94 call print
95 cli
96 hlt
97 jmp short $-1
98
99 ; ax = segment
100 ; bx = offset
101 ; edx = start LBA of where to read
102 read_sector:
103 pusha
104 ; set up temporary DAP
105 push dword 0
106 push edx
107 push ax
108 push bx
109 push word 1
110 push word 0x10
111 mov ah, 0x42
112 mov dl, byte [BOOT_DRIVE]
113 mov si, sp
114 int 0x13
115 jc .error
116 add sp, 16 ; dump our temporary DAP
117 popa
118 ret
119 .error:
120 mov si, read_fail
121 call print
122 cli
123 hlt
124 jmp short $-1
125
126 ; DS:SI = string
127 print:
128 pusha
129 mov ah, 0xe
130 xor bh, bh
131 .loop:
132 lodsb
133 cmp al, 0
134 je .done
135 int 10h
136 jmp .loop
137 .done:
138 mov al, 0xd
139 int 10h
140 mov al, 0xa
141 int 10h
142 popa
143 ret
144
145 BOOT_DRIVE: resb 1
146
147 read_fail: db "Error reading stage 2", 0
148 invalid_mbr: db "Invalid partition table", 0
149 no_os: db "No OS found", 0
150 no_int13_ext: db "INT 13h extensions not found", 0
151
152 times 440-($-$$) db 0
153
154 part_table:
155 disk_id: dd 0
156 reserved: dw 0
157 part_1:
158 .attrib db 0
159 .chs_start times 3 db 0
160 .part_type db 0
161 .chs_end times 3 db 0
162 .lba_start dd 0
163 .sect_count dd 0
164 part_2:
165 .attrib db 0
166 .chs_start times 3 db 0
167 .part_type db 0
168 .chs_end times 3 db 0
169 .lba_start dd 0
170 .sect_count dd 0
171 part_3:
172 .attrib db 0
173 .chs_start times 3 db 0
174 .part_type db 0
175 .chs_end times 3 db 0
176 .lba_start dd 0
177 .sect_count dd 0
178 part_4:
179 .attrib db 0
180 .chs_start times 3 db 0
181 .part_type db 0
182 .chs_end times 3 db 0
183 .lba_start dd 0
184 .sect_count dd 0
185 signature: dw 0xaa55