]> git.dujemihanovic.xyz Git - nameless-os.git/blob - boot/x86/mbr.s
613b24894d993a26fac2891e3ecad4768028cb7d
[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 ; we really don't want to be interrupted during relocation
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 si, part_1
31 mov cx, 4
32 .check_part_loop:
33 mov al, [si]
34 test al, 0x80
35 jnz .part_found
36 add si, 16
37 loop .check_part_loop
38 .error:
39 mov si, no_os
40 call print
41 hlt
42 jmp short $-1
43 .part_found:
44 ; look for any other active partitions, if they exist the partition table is invalid
45 cmp cx, 0
46 je .load_vbr
47 push si
48 .look_other_loop:
49 add si, 16
50 mov al, [si]
51 test al, 0x80
52 jnz .invalid_mbr
53 loop .look_other_loop
54 .load_vbr:
55 ; load active partition's VBR
56 pop si
57 mov ax, 0x7c0
58 add si, 8
59 mov edx, [si]
60 xor bx, bx
61 call read_sector
62 ; check is the VBR bootable (ends with 0x55 0xaa), if not halt
63 cmp word [0x7dfe], 0xaa55
64 jne .not_bootable
65 mov dl, [BOOT_DRIVE]
66 call 0x7c00
67 .not_bootable:
68 mov si, no_os
69 call print
70 hlt
71 jmp short $-1
72 .invalid_mbr:
73 mov si, invalid_mbr
74 call print
75 hlt
76 jmp short $-1
77 check_int13_ext:
78 pusha
79 mov ah, 0x41
80 mov bx, 0x55aa
81 mov dl, 0x80
82 int 0x13
83 jc .no_ext
84 test cx, 1
85 jz .no_ext
86 popa
87 ret
88 .no_ext:
89 mov si, no_int13_ext
90 call print
91 hlt
92 jmp short $-1
93
94 ; ax = segment
95 ; bx = offset
96 ; edx = start LBA of where to read
97 read_sector:
98 pusha
99 ; set up temporary DAP
100 push dword 0
101 push edx
102 push ax
103 push bx
104 push word 1
105 push word 0x10
106 mov ah, 0x42
107 mov dl, byte [BOOT_DRIVE]
108 mov si, sp
109 int 0x13
110 jc .error
111 add sp, 16 ; dump our temporary DAP
112 popa
113 ret
114 .error:
115 mov si, read_fail
116 call print
117 hlt
118 jmp short $-1
119
120 ; DS:SI = string
121 print:
122 pusha
123 mov ah, 0xe
124 xor bh, bh
125 .loop:
126 lodsb
127 cmp al, 0
128 je .done
129 int 10h
130 jmp .loop
131 .done:
132 mov al, 0xd
133 int 10h
134 mov al, 0xa
135 int 10h
136 popa
137 ret
138
139 BOOT_DRIVE: resb 1
140
141 read_fail: db "Error reading stage 2", 0
142 invalid_mbr: db "Invalid partition table", 0
143 no_os: db "No OS found", 0
144 no_int13_ext: db "INT 13h extensions not found", 0
145
146 times 440-($-$$) db 0
147
148 part_table:
149 disk_id: dd 0
150 reserved: dw 0
151 part_1:
152 .attrib db 0
153 .chs_start times 3 db 0
154 .part_type db 0
155 .chs_end times 3 db 0
156 .lba_start dd 0
157 .sect_count dd 0
158 part_2:
159 .attrib db 0
160 .chs_start times 3 db 0
161 .part_type db 0
162 .chs_end times 3 db 0
163 .lba_start dd 0
164 .sect_count dd 0
165 part_3:
166 .attrib db 0
167 .chs_start times 3 db 0
168 .part_type db 0
169 .chs_end times 3 db 0
170 .lba_start dd 0
171 .sect_count dd 0
172 part_4:
173 .attrib db 0
174 .chs_start times 3 db 0
175 .part_type db 0
176 .chs_end times 3 db 0
177 .lba_start dd 0
178 .sect_count dd 0
179 signature: dw 0xaa55