Annotation of src/sbin/fsck_msdos/boot.c, Revision 1.6
1.6 ! ws 1: /* $NetBSD: boot.c,v 1.5 1997/10/17 11:19:23 ws Exp $ */
1.1 ws 2:
3: /*
1.5 ws 4: * Copyright (C) 1995, 1997 Wolfgang Solfrank
1.1 ws 5: * Copyright (c) 1995 Martin Husemann
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by Martin Husemann
18: * and Wolfgang Solfrank.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26: * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33: */
34:
35:
1.4 lukem 36: #include <sys/cdefs.h>
1.1 ws 37: #ifndef lint
1.6 ! ws 38: __RCSID("$NetBSD: boot.c,v 1.5 1997/10/17 11:19:23 ws Exp $");
1.1 ws 39: #endif /* not lint */
40:
41: #include <stdlib.h>
42: #include <string.h>
43: #include <ctype.h>
44: #include <stdio.h>
45: #include <unistd.h>
46:
47: #include "ext.h"
1.3 christos 48: #include "fsutil.h"
1.1 ws 49:
50: int
51: readboot(dosfs, boot)
52: int dosfs;
53: struct bootblock *boot;
54: {
55: u_char block[DOSBOOTBLOCKSIZE];
1.5 ws 56: u_char fsinfo[2 * DOSBOOTBLOCKSIZE];
57: u_char backup[DOSBOOTBLOCKSIZE];
58: int ret = FSOK;
1.1 ws 59:
1.5 ws 60: if (read(dosfs, block, sizeof block) < sizeof block) {
61: perror("could not read boot block");
1.1 ws 62: return FSFATAL;
63: }
64:
1.5 ws 65: if (block[510] != 0x55 || block[511] != 0xaa) {
66: pfatal("Invalid signature in boot block: %02x%02x", block[511], block[510]);
67: return FSFATAL;
68: }
69:
70: memset(boot, 0, sizeof *boot);
71: boot->ValidFat = -1;
72:
1.1 ws 73: /* decode bios parameter block */
74: boot->BytesPerSec = block[11] + (block[12] << 8);
75: boot->SecPerClust = block[13];
76: boot->ResSectors = block[14] + (block[15] << 8);
77: boot->FATs = block[16];
78: boot->RootDirEnts = block[17] + (block[18] << 8);
79: boot->Sectors = block[19] + (block[20] << 8);
80: boot->Media = block[21];
1.5 ws 81: boot->FATsmall = block[22] + (block[23] << 8);
1.1 ws 82: boot->SecPerTrack = block[24] + (block[25] << 8);
83: boot->Heads = block[26] + (block[27] << 8);
84: boot->HiddenSecs = block[28] + (block[29] << 8) + (block[30] << 16) + (block[31] << 24);
85: boot->HugeSectors = block[32] + (block[33] << 8) + (block[34] << 16) + (block[35] << 24);
1.5 ws 86:
87: boot->FATsecs = boot->FATsmall;
88:
89: if (!boot->RootDirEnts)
90: boot->flags |= FAT32;
91: if (boot->flags & FAT32) {
92: boot->FATsecs = block[36] + (block[37] << 8)
93: + (block[38] << 16) + (block[39] << 24);
94: if (block[40] & 0x80)
95: boot->ValidFat = block[40] & 0x0f;
96:
97: /* check version number: */
98: if (block[42] || block[43]) {
99: /* Correct? XXX */
100: pfatal("Unknown filesystem version: %x.%x",
101: block[43], block[42]);
102: return FSFATAL;
103: }
104: boot->RootCl = block[44] + (block[45] << 8)
105: + (block[46] << 16) + (block[47] << 24);
106: boot->FSInfo = block[48] + (block[49] << 8);
107: boot->Backup = block[50] + (block[51] << 8);
108:
109: if (lseek(dosfs, boot->FSInfo * boot->BytesPerSec, SEEK_SET)
110: != boot->FSInfo * boot->BytesPerSec
111: || read(dosfs, fsinfo, sizeof fsinfo)
112: != sizeof fsinfo) {
113: perror("could not read fsinfo block");
114: return FSFATAL;
115: }
116: if (memcmp(fsinfo, "RRaA", 4)
117: || memcmp(fsinfo + 0x1e4, "rrAa", 4)
118: || fsinfo[0x1fc]
119: || fsinfo[0x1fd]
120: || fsinfo[0x1fe] != 0x55
121: || fsinfo[0x1ff] != 0xaa
122: || fsinfo[0x3fc]
123: || fsinfo[0x3fd]
124: || fsinfo[0x3fe] != 0x55
125: || fsinfo[0x3ff] != 0xaa) {
126: pwarn("Invalid signature in fsinfo block");
127: if (ask(0, "fix")) {
128: memcpy(fsinfo, "RRaA", 4);
129: memcpy(fsinfo + 0x1e4, "rrAa", 4);
130: fsinfo[0x1fc] = fsinfo[0x1fd] = 0;
131: fsinfo[0x1fe] = 0x55;
132: fsinfo[0x1ff] = 0xaa;
133: fsinfo[0x3fc] = fsinfo[0x3fd] = 0;
134: fsinfo[0x3fe] = 0x55;
135: fsinfo[0x3ff] = 0xaa;
136: if (lseek(dosfs, boot->FSInfo * boot->BytesPerSec, SEEK_SET)
137: != boot->FSInfo * boot->BytesPerSec
138: || write(dosfs, fsinfo, sizeof fsinfo)
139: != sizeof fsinfo) {
140: perror("Unable to write FSInfo");
141: return FSFATAL;
142: }
143: ret = FSBOOTMOD;
144: } else
145: boot->FSInfo = 0;
146: }
147: if (boot->FSInfo) {
148: boot->FSFree = fsinfo[0x1e8] + (fsinfo[0x1e9] << 8)
149: + (fsinfo[0x1ea] << 16)
150: + (fsinfo[0x1eb] << 24);
151: boot->FSNext = fsinfo[0x1ec] + (fsinfo[0x1ed] << 8)
152: + (fsinfo[0x1ee] << 16)
153: + (fsinfo[0x1ef] << 24);
154: }
155:
156: if (lseek(dosfs, boot->Backup * boot->BytesPerSec, SEEK_SET)
157: != boot->Backup * boot->BytesPerSec
158: || read(dosfs, backup, sizeof backup) != sizeof backup) {
159: perror("could not read backup bootblock");
160: return FSFATAL;
161: }
162: if (memcmp(block, backup, DOSBOOTBLOCKSIZE)) {
163: /* Correct? XXX */
164: pfatal("backup doesn't compare to primary bootblock");
165: return FSFATAL;
166: }
167: /* Check backup FSInfo? XXX */
168: }
169:
1.1 ws 170: boot->ClusterOffset = (boot->RootDirEnts * 32 + boot->BytesPerSec - 1)
171: / boot->BytesPerSec
172: + boot->ResSectors
173: + boot->FATs * boot->FATsecs
174: - CLUST_FIRST * boot->SecPerClust;
175:
176: if (boot->BytesPerSec % DOSBOOTBLOCKSIZE != 0) {
1.5 ws 177: pfatal("Invalid sector size: %u", boot->BytesPerSec);
1.1 ws 178: return FSFATAL;
179: }
180: if (boot->SecPerClust == 0) {
1.5 ws 181: pfatal("Invalid cluster size: %u", boot->SecPerClust);
1.1 ws 182: return FSFATAL;
183: }
184: if (boot->Sectors) {
185: boot->HugeSectors = 0;
186: boot->NumSectors = boot->Sectors;
187: } else
188: boot->NumSectors = boot->HugeSectors;
189: boot->NumClusters = (boot->NumSectors - boot->ClusterOffset) / boot->SecPerClust;
190:
1.5 ws 191: if (boot->flags&FAT32)
192: boot->ClustMask = CLUST32_MASK;
193: else if (boot->NumClusters < (CLUST_RSRVD&CLUST12_MASK))
194: boot->ClustMask = CLUST12_MASK;
195: else if (boot->NumClusters < (CLUST_RSRVD&CLUST16_MASK))
196: boot->ClustMask = CLUST16_MASK;
197: else {
198: pfatal("Filesystem too big (%u clusters) for non-FAT32 partition",
199: boot->NumClusters);
200: return FSFATAL;
201: }
202:
203: switch (boot->ClustMask) {
204: case CLUST32_MASK:
205: boot->NumFatEntries = (boot->FATsecs * boot->BytesPerSec) / 4;
206: break;
207: case CLUST16_MASK:
1.1 ws 208: boot->NumFatEntries = (boot->FATsecs * boot->BytesPerSec) / 2;
1.5 ws 209: break;
210: default:
1.1 ws 211: boot->NumFatEntries = (boot->FATsecs * boot->BytesPerSec * 2) / 3;
1.5 ws 212: break;
213: }
214:
1.1 ws 215: if (boot->NumFatEntries < boot->NumClusters) {
1.5 ws 216: pfatal("FAT size too small, %u entries won't fit into %u sectors\n",
1.1 ws 217: boot->NumClusters, boot->FATsecs);
218: return FSFATAL;
219: }
220: boot->ClusterSize = boot->BytesPerSec * boot->SecPerClust;
221:
222: boot->NumFiles = 1;
223: boot->NumFree = 0;
1.5 ws 224:
225: return ret;
226: }
227:
228: int
229: writefsinfo(dosfs, boot)
230: int dosfs;
231: struct bootblock *boot;
232: {
233: u_char fsinfo[2 * DOSBOOTBLOCKSIZE];
234:
235: if (lseek(dosfs, boot->FSInfo * boot->BytesPerSec, SEEK_SET)
236: != boot->FSInfo * boot->BytesPerSec
237: || read(dosfs, fsinfo, sizeof fsinfo) != sizeof fsinfo) {
238: perror("could not read fsinfo block");
239: return FSFATAL;
240: }
241: fsinfo[0x1e8] = (u_char)boot->FSFree;
242: fsinfo[0x1e9] = (u_char)(boot->FSFree >> 8);
243: fsinfo[0x1ea] = (u_char)(boot->FSFree >> 16);
244: fsinfo[0x1eb] = (u_char)(boot->FSFree >> 24);
245: fsinfo[0x1ec] = (u_char)boot->FSNext;
246: fsinfo[0x1ed] = (u_char)(boot->FSNext >> 8);
247: fsinfo[0x1ee] = (u_char)(boot->FSNext >> 16);
248: fsinfo[0x1ef] = (u_char)(boot->FSNext >> 24);
249: if (lseek(dosfs, boot->FSInfo * boot->BytesPerSec, SEEK_SET)
250: != boot->FSInfo * boot->BytesPerSec
251: || write(dosfs, fsinfo, sizeof fsinfo)
252: != sizeof fsinfo) {
253: perror("Unable to write FSInfo");
254: return FSFATAL;
255: }
1.6 ! ws 256: /*
! 257: * Technically, we should return FSBOOTMOD here.
! 258: *
! 259: * However, since Win95 OSR2 (the first M$ OS that has
! 260: * support for FAT32) doesn't maintain the FSINFO block
! 261: * correctly, it has to be fixed pretty often.
! 262: *
! 263: * Therefor, we handle the FSINFO block only informally,
! 264: * fixing it if neccessary, but otherwise ignoring the
! 265: * fact that it was incorrect.
! 266: */
! 267: return 0;
1.1 ws 268: }
CVSweb <webmaster@jp.NetBSD.org>