cdboot.S revision 1.1 1 1.1 junyoung /* $NetBSD: cdboot.S,v 1.1 2005/06/15 06:38:45 junyoung Exp $ */
2 1.1 junyoung
3 1.1 junyoung /*-
4 1.1 junyoung * Copyright (c) 2005 The NetBSD Foundation, Inc.
5 1.1 junyoung * All rights reserved.
6 1.1 junyoung *
7 1.1 junyoung * This code is derived from software contributed to The NetBSD Foundation
8 1.1 junyoung * by Bang Jun-Young.
9 1.1 junyoung *
10 1.1 junyoung * Redistribution and use in source and binary forms, with or without
11 1.1 junyoung * modification, are permitted provided that the following conditions
12 1.1 junyoung * are met:
13 1.1 junyoung * 1. Redistributions of source code must retain the above copyright
14 1.1 junyoung * notice, this list of conditions and the following disclaimer.
15 1.1 junyoung * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 junyoung * notice, this list of conditions and the following disclaimer in the
17 1.1 junyoung * documentation and/or other materials provided with the distribution.
18 1.1 junyoung * 3. All advertising materials mentioning features or use of this software
19 1.1 junyoung * must display the following acknowledgement:
20 1.1 junyoung * This product includes software developed by the NetBSD
21 1.1 junyoung * Foundation, Inc. and its contributors.
22 1.1 junyoung * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.1 junyoung * contributors may be used to endorse or promote products derived
24 1.1 junyoung * from this software without specific prior written permission.
25 1.1 junyoung *
26 1.1 junyoung * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.1 junyoung * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.1 junyoung * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.1 junyoung * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.1 junyoung * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.1 junyoung * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.1 junyoung * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.1 junyoung * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.1 junyoung * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.1 junyoung * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.1 junyoung * POSSIBILITY OF SUCH DAMAGE.
37 1.1 junyoung */
38 1.1 junyoung
39 1.1 junyoung /*
40 1.1 junyoung * This is a primary boot loader that loads a secondary boot loader
41 1.1 junyoung * directly from CD without performing floppy/hard disk emulation as
42 1.1 junyoung * described by the El Torito specification.
43 1.1 junyoung *
44 1.1 junyoung * TODO:
45 1.1 junyoung * - Support for loading secondary boot loader > 64kB
46 1.1 junyoung */
47 1.1 junyoung
48 1.1 junyoung #include <machine/asm.h>
49 1.1 junyoung
50 1.1 junyoung #define BOOT_ADDR 0x7c00
51 1.1 junyoung #define BLOCK_SIZE 2048 /* Default for ISO 9660 */
52 1.1 junyoung #define VD_LBA 16 /* LBA of Volume Descriptor (VD) */
53 1.1 junyoung #define PVD_ADDR 0x1000 /* Where Primary VD is loaded */
54 1.1 junyoung #define ROOTDIR_ADDR 0x1800 /* Where Root Directory is loaded */
55 1.1 junyoung #define LOADER_ADDR SECONDARY_LOAD_ADDRESS
56 1.1 junyoung
57 1.1 junyoung /*
58 1.1 junyoung * Disk error codes
59 1.1 junyoung */
60 1.1 junyoung #define ERROR_TIMEOUT 0x80
61 1.1 junyoung
62 1.1 junyoung /*
63 1.1 junyoung * Volume Descriptor types.
64 1.1 junyoung */
65 1.1 junyoung #define VD_PRIMARY 1
66 1.1 junyoung #define VD_SUPPLEMENTARY 2
67 1.1 junyoung #define VD_TERMINATOR 255
68 1.1 junyoung
69 1.1 junyoung /* Only actually used entries are listed below */
70 1.1 junyoung
71 1.1 junyoung /*
72 1.1 junyoung * Format of Primary Volume Descriptor (8.4)
73 1.1 junyoung */
74 1.1 junyoung #define PVD_ROOT_DR 156 /* Offset of Root Directory Record */
75 1.1 junyoung
76 1.1 junyoung /*
77 1.1 junyoung * Format of Directory Record (9.1)
78 1.1 junyoung */
79 1.1 junyoung #define DR_LEN 0
80 1.1 junyoung #define DR_EXTENT 2
81 1.1 junyoung #define DR_DATA_LEN 10
82 1.1 junyoung #define DR_NAME_LEN 32
83 1.1 junyoung #define DR_NAME 33
84 1.1 junyoung
85 1.1 junyoung .text
86 1.1 junyoung .code16
87 1.1 junyoung ENTRY(start)
88 1.1 junyoung xorw %ax, %ax
89 1.1 junyoung movw %ax, %ds
90 1.1 junyoung movw %ax, %es
91 1.1 junyoung movw %ax, %ss
92 1.1 junyoung movw $BOOT_ADDR, %sp
93 1.1 junyoung movw %sp, %si
94 1.1 junyoung movw $start, %di
95 1.1 junyoung movw $BLOCK_SIZE/2, %cx
96 1.1 junyoung rep
97 1.1 junyoung movsw
98 1.1 junyoung ljmp $0, $real_start
99 1.1 junyoung
100 1.1 junyoung real_start:
101 1.1 junyoung movb %dl, boot_drive /* Save boot drive number */
102 1.1 junyoung movw $str_press_key, %si
103 1.1 junyoung call message
104 1.1 junyoung next_second:
105 1.1 junyoung movw $str_dot, %si
106 1.1 junyoung call message
107 1.1 junyoung decb wait_count
108 1.1 junyoung jz boot_hard_disk
109 1.1 junyoung xorb %ah, %ah /* Get system time */
110 1.1 junyoung int $0x1a
111 1.1 junyoung movw %dx, %di /* %cx:%dx = number of clock ticks */
112 1.1 junyoung addw $19, %di /* 19 ~= 18.2 Hz */
113 1.1 junyoung wait_key:
114 1.1 junyoung movb $1, %ah /* Check for keystroke */
115 1.1 junyoung int $0x16
116 1.1 junyoung jz not_avail /* ZF clear if keystroke available */
117 1.1 junyoung xorb %ah, %ah /* Read key to flush keyboard buf */
118 1.1 junyoung int $0x16
119 1.1 junyoung jmp boot_cdrom
120 1.1 junyoung not_avail:
121 1.1 junyoung xorb %ah, %ah /* Get system time */
122 1.1 junyoung int $0x1a
123 1.1 junyoung cmpw %dx, %di /* Compare with saved time */
124 1.1 junyoung jnz wait_key
125 1.1 junyoung jmp next_second
126 1.1 junyoung
127 1.1 junyoung boot_hard_disk:
128 1.1 junyoung movw $str_crlf, %si
129 1.1 junyoung call message
130 1.1 junyoung movw $0x0201, %ax /* %al = number of sectors to read */
131 1.1 junyoung movw $BOOT_ADDR, %bx /* %es:%bx = data buffer */
132 1.1 junyoung movw $0x0001, %cx /* %ch = low 8 bits of cylinder no */
133 1.1 junyoung /* %cl = high 2 bits of cyl no & */
134 1.1 junyoung /* sector number */
135 1.1 junyoung movw $0x0080, %dx /* %dh = head number */
136 1.1 junyoung /* %dl = disk number */
137 1.1 junyoung int $0x13 /* Read MBR into memory */
138 1.1 junyoung jc panic /* CF set on error */
139 1.1 junyoung movw %cs, %ax /* Restore initial state */
140 1.1 junyoung movw %ax, %ds
141 1.1 junyoung movw %ax, %es
142 1.1 junyoung movw $0x0080, %dx /* %dl = boot drive number */
143 1.1 junyoung jmp $0, $BOOT_ADDR /* Jump to MBR! */
144 1.1 junyoung
145 1.1 junyoung panic:
146 1.1 junyoung hlt
147 1.1 junyoung jmp panic
148 1.1 junyoung
149 1.1 junyoung boot_cdrom:
150 1.1 junyoung movw $str_banner, %si
151 1.1 junyoung call message
152 1.1 junyoung movl $VD_LBA, %eax
153 1.1 junyoung next_block:
154 1.1 junyoung movb $1, %dh /* Number of sectors to read */
155 1.1 junyoung movl $PVD_ADDR, %ebx
156 1.1 junyoung call read_sectors
157 1.1 junyoung cmpb $VD_PRIMARY, (%bx) /* Is it Primary Volume Descriptor? */
158 1.1 junyoung jz pvd_found
159 1.1 junyoung incl %eax
160 1.1 junyoung cmpb $VD_TERMINATOR, (%bx)
161 1.1 junyoung jnz next_block
162 1.1 junyoung movw $str_no_pvd, %si
163 1.1 junyoung call message
164 1.1 junyoung jmp panic
165 1.1 junyoung
166 1.1 junyoung pvd_found:
167 1.1 junyoung movw $PVD_ADDR+PVD_ROOT_DR, %bx
168 1.1 junyoung movl DR_EXTENT(%bx), %eax /* LBA of the root directory */
169 1.1 junyoung movl DR_DATA_LEN(%bx), %edx
170 1.1 junyoung shrl $11, %edx /* Convert to number of sectors */
171 1.1 junyoung movb %dl, %dh /* ... and load it to %dh */
172 1.1 junyoung movl $ROOTDIR_ADDR, %ebx
173 1.1 junyoung call read_sectors
174 1.1 junyoung next_entry:
175 1.1 junyoung cmpb $0, DR_LEN(%bx)
176 1.1 junyoung jz last_entry
177 1.1 junyoung movw %bx, %si
178 1.1 junyoung addw $DR_NAME, %si
179 1.1 junyoung movb DR_NAME_LEN(%bx), %cl
180 1.1 junyoung movw $str_loader, %di
181 1.1 junyoung 1:
182 1.1 junyoung movb (%si), %al
183 1.1 junyoung cmpb %al, (%di)
184 1.1 junyoung jnz fail
185 1.1 junyoung incw %si
186 1.1 junyoung incw %di
187 1.1 junyoung decb %cl
188 1.1 junyoung jnz 1b
189 1.1 junyoung jmp load_loader
190 1.1 junyoung fail:
191 1.1 junyoung addw DR_LEN(%bx), %bx
192 1.1 junyoung jmp next_entry
193 1.1 junyoung last_entry:
194 1.1 junyoung movw $str_no_loader, %si
195 1.1 junyoung call message
196 1.1 junyoung jmp panic
197 1.1 junyoung
198 1.1 junyoung load_loader:
199 1.1 junyoung movl DR_EXTENT(%bx), %eax
200 1.1 junyoung movl DR_DATA_LEN(%bx), %edx
201 1.1 junyoung addl $(BLOCK_SIZE-1), %edx /* Convert file length to */
202 1.1 junyoung shrl $11, %edx /* ... number of sectors */
203 1.1 junyoung movb %dl, %dh
204 1.1 junyoung movl $LOADER_ADDR, %ebx
205 1.1 junyoung call read_sectors
206 1.1 junyoung xorl %esi, %esi /* Don't provide boot_params */
207 1.1 junyoung xorl %edx, %edx
208 1.1 junyoung movb boot_drive, %dl
209 1.1 junyoung xorl %ebx, %ebx /* Zero sector number */
210 1.1 junyoung lcall $LOADER_ADDR/16, $0
211 1.1 junyoung jmp panic
212 1.1 junyoung
213 1.1 junyoung /*
214 1.1 junyoung * Read disk sector(s) into memory
215 1.1 junyoung *
216 1.1 junyoung * %eax = LBA of starting sector
217 1.1 junyoung * %ebx = buffer to store sectors
218 1.1 junyoung * %dh = number of sectors to read
219 1.1 junyoung */
220 1.1 junyoung read_sectors:
221 1.1 junyoung pusha
222 1.1 junyoung movl %eax, edd_lba /* Convert LBA to segment */
223 1.1 junyoung shrl $4, %ebx
224 1.1 junyoung movw %bx, edd_segment
225 1.1 junyoung movb %dh, edd_nsecs
226 1.1 junyoung movb boot_drive, %dl
227 1.1 junyoung movw $edd_packet, %si
228 1.1 junyoung read_again:
229 1.1 junyoung movb $0x42, %ah
230 1.1 junyoung int $0x13
231 1.1 junyoung jc read_fail
232 1.1 junyoung popa
233 1.1 junyoung ret
234 1.1 junyoung read_fail:
235 1.1 junyoung cmpb $ERROR_TIMEOUT, %ah
236 1.1 junyoung jz read_again
237 1.1 junyoung movw $str_read_error, %si
238 1.1 junyoung call message
239 1.1 junyoung jmp panic
240 1.1 junyoung
241 1.1 junyoung /*
242 1.1 junyoung * For debugging purpose
243 1.1 junyoung */
244 1.1 junyoung put_char:
245 1.1 junyoung pusha
246 1.1 junyoung movb $0x0e, %ah
247 1.1 junyoung movw $0x0001, %bx
248 1.1 junyoung int $0x10
249 1.1 junyoung popa
250 1.1 junyoung ret
251 1.1 junyoung
252 1.1 junyoung #include <message.S>
253 1.1 junyoung
254 1.1 junyoung edd_packet:
255 1.1 junyoung edd_len: .word 16
256 1.1 junyoung edd_nsecs: .word 0 /* Number of sectors to transfer */
257 1.1 junyoung edd_offset: .word 0
258 1.1 junyoung edd_segment: .word 0
259 1.1 junyoung edd_lba: .quad 0
260 1.1 junyoung
261 1.1 junyoung wait_count: .byte 6
262 1.1 junyoung boot_drive: .byte 0
263 1.1 junyoung
264 1.1 junyoung str_banner: .ascii "\r\nNetBSD/i386 cd9660 Primary Bootstrap"
265 1.1 junyoung str_crlf: .asciz "\r\n"
266 1.1 junyoung str_press_key: .asciz "\r\nPress any key to boot from CD"
267 1.1 junyoung str_dot: .asciz "."
268 1.1 junyoung str_read_error: .asciz "Can't read CD"
269 1.1 junyoung str_no_pvd: .asciz "Can't find Primary Volume Descriptor"
270 1.1 junyoung str_no_loader: .asciz "Can't find /boot"
271 1.1 junyoung str_loader: .asciz "BOOT.;1"
272 1.1 junyoung
273 1.1 junyoung /* Used to calculate free bytes */
274 1.1 junyoung free_space = end - .
275 1.1 junyoung
276 1.1 junyoung . = start + BLOCK_SIZE
277 1.1 junyoung end:
278