Sat Mar 10 23:59:36 2012 UTC ()
Add support for directly booting from FAT12 filesystems.
This shouldn't really be needed except that Linux wont
mount a small FAT16 filesystem - it always treats it as FAT12
even when you tell it otherwise.
There was enough free space before the main FS on the USB stick
I've been using for an extra small FAT fs to boot from.


(dsl)
diff -r1.2 -r1.3 src/sys/arch/i386/stand/fatboot/Makefile
diff -r1.3 -r1.4 src/sys/arch/i386/stand/fatboot/fatboot.S
diff -r0 -r1.1 src/sys/arch/i386/stand/fatboot/fat12/Makefile

cvs diff -r1.2 -r1.3 src/sys/arch/i386/stand/fatboot/Makefile (expand / switch to unified diff)

--- src/sys/arch/i386/stand/fatboot/Makefile 2007/01/06 20:47:15 1.2
+++ src/sys/arch/i386/stand/fatboot/Makefile 2012/03/10 23:59:36 1.3
@@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
1# $NetBSD: Makefile,v 1.2 2007/01/06 20:47:15 dsl Exp $ 1# $NetBSD: Makefile,v 1.3 2012/03/10 23:59:36 dsl Exp $
2 2
3SUBDIR= fat16 3SUBDIR= fat16
 4SUBDIR+= fat12
4 5
5.include <bsd.subdir.mk> 6.include <bsd.subdir.mk>
6.include <bsd.obj.mk> 7.include <bsd.obj.mk>

cvs diff -r1.3 -r1.4 src/sys/arch/i386/stand/fatboot/fatboot.S (expand / switch to unified diff)

--- src/sys/arch/i386/stand/fatboot/fatboot.S 2008/04/29 06:53:02 1.3
+++ src/sys/arch/i386/stand/fatboot/fatboot.S 2012/03/10 23:59:36 1.4
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: fatboot.S,v 1.3 2008/04/29 06:53:02 martin Exp $ */ 1/* $NetBSD: fatboot.S,v 1.4 2012/03/10 23:59:36 dsl Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2007 The NetBSD Foundation, Inc. 4 * Copyright (c) 2007 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by David Laight. 8 * by David Laight.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -40,30 +40,32 @@ @@ -40,30 +40,32 @@
40 * correctly identifies the filesystem. 40 * correctly identifies the filesystem.
41 * 41 *
42 * On entry and exit the BIOS drive number is in %dl. 42 * On entry and exit the BIOS drive number is in %dl.
43 */ 43 */
44 44
45#include <machine/asm.h> 45#include <machine/asm.h>
46#include <sys/bootblock.h> 46#include <sys/bootblock.h>
47 47
48#ifndef FAT_ENTRY_SIZE 48#ifndef FAT_ENTRY_SIZE
49#error FAT_ENTRY_SIZE not defined 49#error FAT_ENTRY_SIZE not defined
50#endif 50#endif
51 51
52/* Support for FAT32 could be added - but hasn't been yet. */ 52/* Support for FAT32 could be added - but hasn't been yet. */
53#if FAT_ENTRY_SIZE != 16 53#if FAT_ENTRY_SIZE != 16 && FAT_ENTRY_SIZE != 12
54#error Unsupported FAT_ENTRY_SIZE value 54#error Unsupported FAT_ENTRY_SIZE value
55#endif 55#endif
56 56
 57#define FAT_SIZE_STR (('0'+ FAT_ENTRY_SIZE / 10) | ('0' + FAT_ENTRY_SIZE % 10) << 8)
 58
57#define PBR_AFTERBPB 62 /* BPB size in floppy master BR */ 59#define PBR_AFTERBPB 62 /* BPB size in floppy master BR */
58 60
59#ifdef TERSE_ERROR 61#ifdef TERSE_ERROR
60/* 62/*
61 * Error codes. Done this way to save space. 63 * Error codes. Done this way to save space.
62 */ 64 */
63#define ERR_READ 'R' /* Read error */ 65#define ERR_READ 'R' /* Read error */
64#define ERR_NO_BOOT 'B' /* No /boot */ 66#define ERR_NO_BOOT 'B' /* No /boot */
65#define ERR_NOT_FAT16 'F' /* Not a FAT16 filesystem */ 67#define ERR_NOT_FAT16 'F' /* Not a FAT16 filesystem */
66#define ERR_NO_BOOT_MAGIC_2 'M' /* No magic in loaded /boot */ 68#define ERR_NO_BOOT_MAGIC_2 'M' /* No magic in loaded /boot */
67 69
68#define set_err(err) movb $err, %al 70#define set_err(err) movb $err, %al
69 71
@@ -102,64 +104,76 @@ oem_name: .ascii "NetBSD40 @@ -102,64 +104,76 @@ oem_name: .ascii "NetBSD40
102#define sec_p_cl_w 0x2c /* 16bit bpb_sec_per_clust */ 104#define sec_p_cl_w 0x2c /* 16bit bpb_sec_per_clust */
103#define fat_sector 0x30 /* start of FAT in sectors */ 105#define fat_sector 0x30 /* start of FAT in sectors */
104 106
105 . = start + PBR_AFTERBPB /* skip BPB */ 107 . = start + PBR_AFTERBPB /* skip BPB */
106start0: 108start0:
107 xor %eax, %eax /* don't trust values of ds, es or ss */ 109 xor %eax, %eax /* don't trust values of ds, es or ss */
108 mov %ax, %ds 110 mov %ax, %ds
109 mov %ax, %es 111 mov %ax, %es
110 mov %ax, %ss 112 mov %ax, %ss
111 mov $start, %sp 113 mov $start, %sp
112 mov %sp, %bp /* to access the pbp */ 114 mov %sp, %bp /* to access the pbp */
113 push %dx /* save drive at -2(%bp) */ 115 push %dx /* save drive at -2(%bp) */
114 116
 117/* We put the LBA bios command block on stack.
 118 * Since we only want a 32bit sector number, stack a zero */
 119 push %cs /* %cs is zero */
 120 push %cs /* 64-bit for LBA read */
 121
115 set_err(ERR_NOT_FAT16) 122 set_err(ERR_NOT_FAT16)
116 cmpl $'A'|'T'<<8|'1'<<16|'6'<<24, bs_file_sys_type+1(%bp) 123 cmpl $'A'|'T'<<8|FAT_SIZE_STR<<16, bs_file_sys_type+1(%bp)
117 jne error 124 jne error
118 125
119/* Add 'reserved' (inside ptn) to 'hidden' (ptn offset) */ 126/* Add 'reserved' (inside ptn) to 'hidden' (ptn offset) */
120 mov bpb_res_sectors(%bp), %ax 127 mov bpb_res_sectors(%bp), %ax
121 addl bpb_hidden_secs(%bp), %eax 128 addl bpb_hidden_secs(%bp), %eax
122 mov %eax, fat_sector(%bp) /* To get first sector of FAT */ 129 mov %eax, fat_sector(%bp) /* To get first sector of FAT */
123 130
 131#if FAT_ENTRY_SIZE == 12
 132/* Read the entire FAT */
 133 push %eax
 134 push %ds
 135 push $fat_buffer
 136 push $12 /* 12 sectors is assumed 6k */
 137 call read_lba
 138#endif
 139
124/* Determine base of root directory */ 140/* Determine base of root directory */
125 movzbw bpb_FATs(%bp), %ax /* Count of FATs */ 141 movzbw bpb_FATs(%bp), %ax /* Count of FATs */
126 mulw bpb_FAT_secs(%bp) /* FAT size in %dx:%ax */ 142 mulw bpb_FAT_secs(%bp) /* FAT size in %dx:%ax */
127 shl $16,%edx 143 shl $16,%edx
128 xchg %ax,%dx /* FAT size now in %edx */ 144 xchg %ax,%dx /* FAT size now in %edx */
129 addl fat_sector(%bp), %edx /* Directory is after FATs */ 145 addl fat_sector(%bp), %edx /* Directory is after FATs */
130 push %cs /* %cs is zero */ 
131 push %cs /* 64-bit for LBA read */ 
132 pushl %edx /* Sector number of root dir */ 146 pushl %edx /* Sector number of root dir */
133 147
134 push $0x1000 /* Read to 0x10000:0 */ 148 push $0x1000 /* Read to 0x10000:0 */
135 pop %es /* Which we need in %es later */ 149 pop %es /* Which we need in %es later */
136 push %es 150 push %es
137 push %cs /* Offset zero */ 151 push %cs /* Offset zero */
138 152
139/* Convert the root directory size to sectors */ 153/* Convert the root directory size to sectors */
140 push %dx 154 push %dx
141 mov bpb_root_dir_ents(%bp), %ax 155 mov bpb_root_dir_ents(%bp), %ax
142 mov $0x20, %dx 156 mov $0x20, %dx
143 mul %dx 157 mul %dx
144 divw bpb_bytes_per_sec(%bp) 158 divw bpb_bytes_per_sec(%bp)
145 add $0xffff, %dx /* Set carry if remainder non-zero */ 159 add $0xffff, %dx /* Set carry if remainder non-zero */
146 adc $0, %ax /* and round up the division */ 160 adc $0, %ax /* and round up the division */
147 pop %dx 161 pop %dx
148 162
149/* Read in the entire root directory */ 163/* Read in the entire root directory */
150 push %ax /* Sectors in root directory */ 164 push %ax /* Sectors in root directory */
151 cwtl 165 cwtl
152 addl %eax, %edx /* %edx now sector of first file */ 166 addl %eax, %edx /* %edx now sector of first cluster */
153 call read_lba /* Read entire directory */ 167 call read_lba /* Read entire directory */
154 168
155/* Scan directory for our file */ 169/* Scan directory for our file */
156 xor %di, %di 170 xor %di, %di
157scan_dir: 171scan_dir:
158 mov $boot_filename, %si 172 mov $boot_filename, %si
159 mov $11, %cx 173 mov $11, %cx
160 repz cmpsb 174 repz cmpsb
161 je found_boot 175 je found_boot
162 or $31,%di 176 or $31,%di
163 inc %di 177 inc %di
164 cmp %ch, %es:(%di) /* %ch is zero - test end of dir */ 178 cmp %ch, %es:(%di) /* %ch is zero - test end of dir */
165 jz 1f 179 jz 1f
@@ -185,87 +199,102 @@ error: @@ -185,87 +199,102 @@ error:
185 hlt 199 hlt
186 jmp 1b 200 jmp 1b
187 201
188found_boot: 202found_boot:
189 movzbl bpb_sec_per_clust(%bp), %eax 203 movzbl bpb_sec_per_clust(%bp), %eax
190 movw %ax, sec_p_cl_w(%bp) 204 movw %ax, sec_p_cl_w(%bp)
191 add %ax, %ax 205 add %ax, %ax
192 subl %eax, %edx /* 1st file sector is cluster 2 */ 206 subl %eax, %edx /* 1st file sector is cluster 2 */
1931: inc %cl /* Convert power of 2 ... */ 2071: inc %cl /* Convert power of 2 ... */
194 shr $1, %ax /* ... to shift */ 208 shr $1, %ax /* ... to shift */
195 jnz 1b 209 jnz 1b
196 dec %cx 210 dec %cx
197 dec %cx 211 dec %cx
198 movw %es:15(%di), %ax /* Cluster number for file start */ 212 movw %es:(26-11)(%di), %ax /* Cluster number for file start */
199 push %es /* We increment the 'segment' ... */ 213 push %es /* We increment the 'segment' ... */
200 pop %di /* ... after each read, offset is 0 */ 214 pop %di /* ... after each read, offset is 0 */
201 215
202read_data_block: 216read_data_block:
203 mov %ax, %bx /* Save cluster number */ 217 mov %ax, %bx /* Save cluster number */
204 shl %cl, %eax /* Convert to sector number */ 218 shl %cl, %eax /* Convert to sector number */
205 add %eax, %edx 219 jz error /* Sanity bail-out */
206 pushl %edx /* Sector to read */ 220 add %edx, %eax
207 sub %eax, %edx /* Recover base segment */ 221 pushl %eax /* Sector to read */
208 push %di /* Target address segment! */ 222 push %di /* Target address segment! */
209 push $0 223 push $0
210 push sec_p_cl_w(%bp) 224 push sec_p_cl_w(%bp)
211 call read_lba /* Read a cluster */ 225 call read_lba /* Read a cluster */
212 226
213/* Update read ptr for next cluster */ 227/* Update read ptr for next cluster */
214 mov bpb_bytes_per_sec(%bp), %ax 228 mov bpb_bytes_per_sec(%bp), %ax
215 shr $4, %ax /* x86 segment count */ 229 shr $4, %ax /* x86 segment count */
216 shl %cl, %ax /* for a cluster */ 230 shl %cl, %ax /* for a cluster */
217 add %ax, %di 231 add %ax, %di
218 232
219/* Lookup FAT slot number in FAT table */ 233/* Lookup FAT slot number in FAT table */
220 mov %bx, %ax /* Recover cluster number */ 234 mov %bx, %ax /* Recover cluster number */
 235#if FAT_ENTRY_SIZE == 12
 236 shr $1, %ax
 237 jc 1f
 238 add %ax, %bx
 239 mov fat_buffer(%bx), %ax
 240 and $0xf,%ah
 241 jmp 2f
 2421: add %ax, %bx
 243 mov fat_buffer(%bx), %ax
 244 shr $4, %ax
 2452:
 246 cmp $0x0fff, %ax
 247 jb read_data_block
 248#else
221 push %dx 249 push %dx
222 xor %dx, %dx 250 xor %dx, %dx
223 divw bpb_bytes_per_sec(%bp) 251 divw bpb_bytes_per_sec(%bp)
224 mov %dx, %bx /* Entry in FAT block */ 252 mov %dx, %bx /* Entry in FAT block */
225 pop %dx 253 pop %dx
226 cmp %ax, fat_cache 254 cmp %ax, fat_cache
227 je lookup_fat 255 je lookup_fat
228 256
229/* We must read a different chuck of the FAT */ 257/* We must read a different chuck of the FAT */
230 mov %ax, fat_cache 258 mov %ax, fat_cache
231 cwtl 259 cwtl
232 shl $1, %ax 260 shl $1, %ax
233 addl fat_sector(%bp), %eax 261 addl fat_sector(%bp), %eax
234 push %eax 262 push %eax
235 push %ds 263 push %ds
236 push $fat_buffer 264 push $fat_buffer
237 push $2 /* Always read 2 sectors of FAT */ 265 push $2 /* Always read 2 sectors of FAT */
238 call read_lba 266 call read_lba
239 267
240/* Now use low part of cluster number to index FAT sector */ 268/* Now use low part of cluster number to index FAT sector */
241lookup_fat: 269lookup_fat:
242 add %bx, %bx /* 2 bytes per entry... */ 270 add %bx, %bx /* 2 bytes per entry... */
243 movzwl fat_buffer(%bx), %eax /* Next FAT slot */ 271 movzwl fat_buffer(%bx), %eax /* Next FAT slot */
244 cmp $0xfff0, %ax 272 cmp $0xfff0, %ax
245 jb read_data_block 273 jb read_data_block
 274#endif
246 275
247/* Found end of FAT chain - must be EOF - leap into loaded code */ 276/* Found end of FAT chain - must be EOF - leap into loaded code */
248 mov $0x1000, %ax 277 mov $0x1000, %ax
249 mov %ax, %es 278 mov %ax, %es
250 cmpl $X86_BOOT_MAGIC_2, %es:4 279 cmpl $X86_BOOT_MAGIC_2, %es:4
251 je magic_ok 280 je magic_ok
252 set_err(ERR_NO_BOOT_MAGIC_2) 281 set_err(ERR_NO_BOOT_MAGIC_2)
253err1: jmp error 282err1: jmp error
254 283
255/* Set parameters expected by /boot */ 284/* Set parameters expected by /boot */
256magic_ok: 285magic_ok:
257 mov bpb_hidden_secs(%bp), %ebx /* ptn base sector */ 286 mov bpb_hidden_secs(%bp), %ebx /* ptn base sector */
258 movb -2(%bp), %dl /* disk number (could pop %dx) */ 287 movb -2(%bp), %dl /* disk number */
259 mov $boot_params + 4, %si 288 mov $boot_params + 4, %si
260 push %es 289 push %es
261 push $0 290 push $0
262 lret 291 lret
263 292
264/* Read disk using on-stack int13-extension parameter block */ 293/* Read disk using on-stack int13-extension parameter block */
265read_lba: 294read_lba:
266 pop %ax /* Save rtn addr */ 295 pop %ax /* Save rtn addr */
267 pushw $16 /* Stack ctl block length */ 296 pushw $16 /* Stack ctl block length */
268 mov %sp, %si /* Address ctl block */ 297 mov %sp, %si /* Address ctl block */
269 push %ax /* restack rtn addr */ 298 push %ax /* restack rtn addr */
270 pushal /* Save everything except %si and %ax*/ 299 pushal /* Save everything except %si and %ax*/
271 mov -2(%bp), %dl /* Disk # saved on entry */ 300 mov -2(%bp), %dl /* Disk # saved on entry */
@@ -276,48 +305,52 @@ read_lba: @@ -276,48 +305,52 @@ read_lba:
276 set_err(ERR_READ) 305 set_err(ERR_READ)
277 jc err1 306 jc err1
278 ret $12 /* Discard all except high LBA zeros */ 307 ret $12 /* Discard all except high LBA zeros */
279 308
280/* 309/*
281 * I hate #including source files, but pbr_magic below has to be at 310 * I hate #including source files, but pbr_magic below has to be at
282 * the correct absolute address. 311 * the correct absolute address.
283 * Clearly this could be done with a linker script. 312 * Clearly this could be done with a linker script.
284 */ 313 */
285 314
286#include <message.S> 315#include <message.S>
287#if 0 316#if 0
288#include <dump_eax.S> 317#include <dump_eax.S>
 318dump_eax_buff = start
289#endif 319#endif
290 320
291errtxt: .ascii "Error " /* runs into newline... */ 321errtxt: .ascii "Error " /* runs into newline... */
292errcod: .byte 0 /* ... if errcod set */ 322errcod: .byte 0 /* ... if errcod set */
293newline: 323newline:
294 .asciz "\r\n" 324 .asciz "\r\n"
295 325
296#ifndef TERSE_ERROR 326#ifndef TERSE_ERROR
297ERR_READ: .asciz "Disk read" 327ERR_READ: .asciz "Disk read"
298ERR_NO_BOOT: .asciz "No /boot" 328ERR_NO_BOOT: .asciz "No /boot"
299ERR_NOT_FAT16: .asciz "Not FAT16 ptn" 329ERR_NOT_FAT16: .ascii "Not FAT"
 330 .word FAT_SIZE_STR
 331 .asciz " ptn"
300ERR_NO_BOOT_MAGIC_2: .asciz "No magic in /boot" 332ERR_NO_BOOT_MAGIC_2: .asciz "No magic in /boot"
301#endif 333#endif
302 334
303boot_filename: .ascii "BOOT " 335boot_filename: .ascii "BOOT "
304 336
305space: 337space:
306pbr_space = boot_params - . 338pbr_space = boot_params - .
307 339
308/* 340/*
309 * Add magic number, with a zero sized patchable area - just in case something 341 * Add magic number, with a zero sized patchable area - just in case something
310 * finds it and tries to update the area. 342 * finds it and tries to update the area.
311 * Boot options can be set using 'installboot -e boot' so we don't need to 343 * Boot options can be set using 'installboot -e boot' so we don't need to
312 * use any of our valuable bytes. 344 * use any of our valuable bytes.
313 */ 345 */
314 346
315 . = _C_LABEL(start) + 0x1fe - 2 - 4 - 4 347 . = _C_LABEL(start) + 0x1fe - 2 - 4 - 4
316boot_params: 348boot_params:
317 .long X86_BOOT_MAGIC_FAT 349 .long X86_BOOT_MAGIC_FAT
318 .long 1f - . 350 .long 1f - .
3191: 3511:
320fat_cache: .word 0xffff /* Sector number in buffer */ 352fat_cache: .word 0xffff /* Sector number in buffer */
321 . = _C_LABEL(start) + 0x1fe 353 . = _C_LABEL(start) + 0x1fe
322 .word 0xaa55 354 .word 0xaa55
323fat_buffer: /* 2 sectors worth of FAT table */ 355fat_buffer: /* 2 sectors worth of FAT table */
 356 /* 6k for FAT12 */

File Added: src/sys/arch/i386/stand/fatboot/fat12/Makefile
# $NetBSD: Makefile,v 1.1 2012/03/10 23:59:36 dsl Exp $

PROG=bootxx_fat12
FAT_ENTRY_SIZE=12

.include <../Makefile.fat>