Make it a little less broken.
[pintos-anon] / src / threads / loader.S
1 #include "threads/loader.h"
2         
3         .intel_syntax noprefix
4         
5 #### Kernel loader.
6
7 # Runs in real mode, which is a 16-bit segment.
8         .code16
9
10 # Set up segment registers.
11 # Stack grows downward starting from us.
12
13 .globl start
14 start:
15         sub ax, ax
16         mov ds, ax
17         mov ss, ax
18         mov sp, 0x7c00
19         cld
20
21         mov ax, 0x00e3
22         sub dx, dx
23         int 0x14
24
25 # Scan floppy disks.
26
27         sub dl, dl
28         sub ebx, ebx
29         mov eax, 0x7e00
30         mov es, ax
31 1:      call scan_partitions
32         inc dl
33         jnc 1b
34
35 # Scan hard disks.
36         mov dl, 0x80
37 1:      call outw
38         call scan_partitions
39         inc dl
40         jnc 1b
41
42 1:      jmp 1b
43
44 scan_partitions:
45         # EBX = sector number of partition table
46         # DL = drive number
47         # ES:0000 -> buffer for partition table
48         # Returns CF set if drive does not exist, CF clear otherwise.
49         call read_sector
50         jc no_such_drive
51         
52 2:      pusha
53         mov edx, [es:508]
54         call outw
55         popa
56         
57         cmp word ptr [es:510], 0xaa55
58         jnz no_boot_partition
59         
60         mov si, 446
61 1:      mov al, [es:si+4]
62         cmp al, 0x20
63         jz found_boot_partition
64         cmp al, 0x05
65         jz found_extended_partition
66         cmp al, 0x0f
67         jz found_extended_partition
68         cmp al, 0x85
69         jz found_extended_partition
70         cmp al, 0xc5
71         jz found_extended_partition
72 next_parttbl_entry:     
73         add si, 16
74         cmp si, 510
75         jb 1b
76
77 no_boot_partition:      
78         clc
79         ret
80 no_such_drive:
81         stc
82         ret
83
84 found_extended_partition:
85         # DL = drive number.
86         # ES:SI -> partition table entry for extended partition.
87         # Recursively examine it.
88         pusha
89         mov ebx, es:[si+8]
90         mov ax, es
91         add ax, 0x20
92         mov es, ax
93         call scan_partitions
94         popa
95         jmp next_parttbl_entry
96
97 found_boot_partition:
98         mov ebx, [es:si+8]              # EBX = first sector
99         mov cx, [es:si+12]              # CX = number of sectors
100         mov ax, 0x1000                  # ES:0000 -> load address
101         mov es, ax
102 1:      call read_sector
103         add ax, 0x20
104         mov es, ax
105         loop 1b
106
107         ljmp 0x1000, 0
108
109         # ebx: sector number
110         # dl: drive number
111         # es:0000: destination buffer
112         # returns error flag in CF
113 read_sector:
114         pusha
115         or dl, dl                       # Floppy drives: DL >= 0
116         jns read_floppy_sector
117
118 read_harddrv_sector:
119         sub eax, eax
120         push eax                        # LBA sector number [32:63]
121         push ebx                        # LBA sector number [0:31]
122         push es
123         push 0
124         push 1                          # Transfer one sector
125         push 16                         # Packet size
126         mov ah, 0x42                    # Extended read
127         mov si, sp                      # DS:SI -> packet
128         int 0x13                        # Error code in CF
129         lahf
130         add sp, 16
131         sahf
132 read_sector_done:
133         popa
134         ret                             # Error code in CF
135
136 read_floppy_sector:
137         #define HEADS 2
138         #define SECTORS 36
139
140         # In: BX = LBA sector number, DL = drive.
141         # Out: BL = drive, DX = cylinder, AL = head, AH = sector.
142         sub ax, ax
143         xchg dx, bx                     # DX = LBA sector number, BL = drive
144         mov cx, HEADS * SECTORS
145         div cx                          # AX = cyl, DX = hd + (sec-1) * SECTORS
146         xchg ax, dx                     # DX = cyl, AX = hd + (sec-1) * SECTORS
147         mov cl, SECTORS
148         div cl                          # AL = head, AH = sector - 1
149         inc ah
150
151         # Read sector.
152         mov ch, dl                      # CH = cylinder
153         mov cl, ah                      # CL = sector
154         mov dh, al                      # DH = head
155         mov dl, bl                      # DL = drive
156         mov ax, 0x0201                  # AH = function, AL = sectors to read
157         sub bx, bx                      # ES:BX -> buffer
158         mov di, 3                       # Number of tries left.
159         
160 try_read_floppy:
161         pusha
162         int 0x13
163         popa
164         jnc read_sector_done
165         dec di
166         jnz 1f
167         stc
168         jmp read_sector_done    
169
170 1:      # Reset floppy drive motor, try again.
171         pusha
172         sub ah, ah
173         int 0x13
174         popa
175         jmp try_read_floppy
176
177 outw:   pushf
178         pusha
179         
180         mov cx, 8
181         mov ebx, edx
182         mov dx, 0xe9
183 1:      rol ebx, 4
184         mov al, bl
185         and al, 15
186         add al, '0'
187         cmp al, '9'
188         jbe 2f
189         add al, 'a' - '0' - 10
190 2:      out dx, al
191         loop 1b
192
193         mov al, '\n'
194         out dx, al
195
196         popa
197         popf
198         ret
199         
200 #### The partition table goes here.
201         .org 446
202 part_tbl:
203         
204
205 #### Boot-sector signature for BIOS inspection.
206         .org 510
207         .word 0xaa55