[BACK]Return to boot.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sbin / fsck_msdos

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>