working on the boot loader
[bootcensus] / src / boot / boot.s
1         .code16
2         .section .boot,"a"
3
4         cli
5         cld
6         # move stack to the top of 512k
7         mov $0x7000, %ax
8         mov %ax, %ss
9         xor %sp, %sp
10         # use the code segment for data access
11         mov %cs, %ax
12         mov %ax, %ds
13         mov %ax, %es
14
15         mov %dl, drive_number
16
17         call clearscr
18
19         mov $_boot2_size, %eax
20         call print_num
21
22         # load the second stage boot loader and jump to it
23         mov $_boot2_size, %eax
24         mov %eax, %ebx
25         shr $9, %eax
26         and $0x1ff, %ebx
27         jz 0f
28         inc %eax
29 0:      pushw %ax
30         pushw $1
31         # set es to the start of the destination buffer to allow reading in
32         # full 64k chunks
33         mov $boot2_addr, %bx
34         shr $4, %bx
35         mov %bx, %es
36         xor %bx, %bx
37         call read_sect
38         jmp boot2_addr
39
40         cli
41         hlt
42
43         .set SECT_PER_TRACK, 18
44
45         .set ARG_NSECT, 6
46         .set ARG_SIDX, 4
47
48 # read_sect(first, num)
49 read_sect:
50         push %bp
51         mov %sp, %bp
52
53         mov ARG_SIDX(%bp), %ax
54         mov ARG_NSECT(%bp), %cx
55
56         jmp 1f
57 0:      push %ax
58         call read_sector
59         add $2, %sp
60 1:      cmp ARG_NSECT(%bp), %cx
61         jnz 0b
62
63         pop %bp
64         ret
65
66 # read_sector(sidx)
67 read_sector:
68         push %bp
69         mov %sp, %bp
70         push %cx
71         push %dx
72
73         # calculate the track (sidx / sectors_per_track)
74         mov 4(%bp), %ax
75         xor %dx, %dx
76         mov $SECT_PER_TRACK, %cx
77         div %cx
78         mov %ax, %cx
79         # save the remainder in ax
80         mov %dx, %ax
81         # head in dh
82         mov %cl, %dh
83         and $1, %dh
84         # cylinder (track/2) in ch [0-7] and cl[6,7]<-[8,9]
85         rol $7, %cx
86         ror $2, %cl
87         and $0xc0, %cl
88         # sector num cl[0-5] is sidx % sectors_per_track (saved in ax)
89         inc %al
90         or %al, %cl 
91         # ah = 2 (read), al = 1 sectors
92         mov $0x0201, %ax
93         movb drive_number, %dl
94         int $0x13
95
96         # increment es:bx accordingly (advance es if bx overflows)
97         add $512, %bx
98         jno 0f
99         mov %es, %ax
100         add $4096, %ax
101         mov %ax, %es
102
103         pop %dx
104         pop %cx
105         pop %bp
106         ret
107
108 clearscr:
109         push %es
110         pushw $0xb800
111         pop %es
112         xor %eax, %eax
113         xor %di, %di
114         movl $500, %ecx
115         rep stosl
116         pop %es
117         ret
118
119 # expects number in eax
120 print_num:
121         # save es
122         push %es
123
124         xor %cx, %cx
125         movw $numbuf, %si
126         mov $10, %ebx
127
128 0:      xor %edx, %edx
129         div %ebx
130         add $48, %dl
131         mov %dl, (%si)
132         inc %si
133         inc %cx
134         cmp $0, %eax
135         jnz 0b
136
137         # print the backwards string
138         pushw $0xb800
139         pop %es
140         xor %di, %di
141
142 0:      dec %si
143         mov (%si), %al
144         movb %al, %es:(%di)
145         inc %di
146         mov $7, %al
147         movb %al, %es:(%di)
148         inc %di
149         dec %cx
150         jnz 0b
151
152         # restore es
153         pop %es
154         ret
155
156 drive_number: .byte 0
157 numbuf: .space 10
158         .org 510
159         .byte 0x55
160         .byte 0xaa
161
162 boot2_addr: