1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1999 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * fsck_pcfs -- routines for manipulating the FAT. 31 */ 32 #include <stdio.h> 33 #include <unistd.h> 34 #include <stdlib.h> 35 #include <libintl.h> 36 #include <sys/dktp/fdisk.h> 37 #include <sys/fs/pc_fs.h> 38 #include <sys/fs/pc_dir.h> 39 #include <sys/fs/pc_label.h> 40 #include "pcfs_common.h" 41 #include "fsck_pcfs.h" 42 43 extern int32_t BytesPerCluster; 44 extern int32_t TotalClusters; 45 extern int32_t LastCluster; 46 extern off64_t FirstClusterOffset; 47 extern off64_t PartitionOffset; 48 extern bpb_t TheBIOSParameterBlock; 49 extern int ReadOnly; 50 extern int IsFAT32; 51 extern int Verbose; 52 53 static uchar_t *TheFAT; 54 static int FATRewriteNeeded = 0; 55 56 int32_t FATSize; 57 short FATEntrySize; 58 59 static off64_t 60 seekFAT(int fd) 61 { 62 off64_t seekto; 63 /* 64 * The FAT(s) immediately follows the reserved sectors. 65 */ 66 seekto = TheBIOSParameterBlock.bpb.resv_sectors * 67 TheBIOSParameterBlock.bpb.bytes_per_sector + PartitionOffset; 68 return (lseek64(fd, seekto, SEEK_SET)); 69 } 70 71 void 72 getFAT(int fd) 73 { 74 ssize_t bytesRead; 75 76 if (TheFAT != NULL) { 77 return; 78 } else if ((TheFAT = (uchar_t *)malloc(FATSize)) == NULL) { 79 mountSanityCheckFails(); 80 perror(gettext("No memory for a copy of the FAT")); 81 (void) close(fd); 82 exit(7); 83 } 84 if (seekFAT(fd) < 0) { 85 mountSanityCheckFails(); 86 perror(gettext("Cannot seek to FAT")); 87 (void) close(fd); 88 exit(7); 89 } 90 if (Verbose) 91 (void) fprintf(stderr, 92 gettext("Reading FAT\n")); 93 if ((bytesRead = read(fd, TheFAT, FATSize)) != FATSize) { 94 mountSanityCheckFails(); 95 if (bytesRead < 0) { 96 perror(gettext("Cannot read a FAT")); 97 } else { 98 (void) fprintf(stderr, 99 gettext("Short read of FAT.")); 100 } 101 (void) close(fd); 102 exit(7); 103 } 104 /* 105 * XXX - might want to read the other copies of the FAT 106 * for comparison and/or to use if the first one seems hosed. 107 */ 108 if (Verbose) { 109 (void) fprintf(stderr, 110 gettext("Dump of FAT's first 32 bytes.\n")); 111 header_for_dump(); 112 dump_bytes(TheFAT, 32); 113 } 114 } 115 116 void 117 writeFATMods(int fd) 118 { 119 ssize_t bytesWritten; 120 121 if (TheFAT == NULL) { 122 (void) fprintf(stderr, 123 gettext("Internal error: No FAT to write\n")); 124 (void) close(fd); 125 exit(11); 126 } 127 if (!FATRewriteNeeded) { 128 if (Verbose) { 129 (void) fprintf(stderr, 130 gettext("No FAT changes need to be written.\n")); 131 } 132 return; 133 } 134 if (ReadOnly) 135 return; 136 if (Verbose) 137 (void) fprintf(stderr, gettext("Writing FAT\n")); 138 if (seekFAT(fd) < 0) { 139 perror(gettext("Cannot seek to FAT")); 140 (void) close(fd); 141 exit(11); 142 } 143 if ((bytesWritten = write(fd, TheFAT, FATSize)) != FATSize) { 144 if (bytesWritten < 0) { 145 perror(gettext("Cannot write FAT")); 146 } else { 147 (void) fprintf(stderr, 148 gettext("Short write of FAT.")); 149 } 150 (void) close(fd); 151 exit(11); 152 } 153 FATRewriteNeeded = 0; 154 } 155 156 /* 157 * checkFAT32CleanBit() 158 * Return non-zero if the bit indicating proper Windows shutdown has 159 * been set. 160 */ 161 int 162 checkFAT32CleanBit(int fd) 163 { 164 getFAT(fd); 165 return (TheFAT[WIN_SHUTDOWN_STATUS_BYTE] & WIN_SHUTDOWN_BIT_MASK); 166 } 167 168 static uchar_t * 169 findClusterEntryInFAT(int32_t currentCluster) 170 { 171 int32_t idx; 172 if (FATEntrySize == 32) { 173 idx = currentCluster * 4; 174 } else if (FATEntrySize == 16) { 175 idx = currentCluster * 2; 176 } else { 177 idx = currentCluster + currentCluster/2; 178 } 179 return (TheFAT + idx); 180 } 181 182 /* 183 * {read,write}FATentry 184 * For the 16 and 32 bit FATs these routines are relatively easy 185 * to follow. 186 * 187 * 12 bit FATs are kind of strange, though. The magic index for 188 * 12 bit FATS computed below, 1.5 * clusterNum, is a 189 * simplification that there are 8 bits in a byte, so you need 190 * 1.5 bytes per entry. 191 * 192 * It's easiest to think about FAT12 entries in pairs: 193 * 194 * --------------------------------------------- 195 * | mid1 | low1 | low2 | high1 | high2 | mid2 | 196 * --------------------------------------------- 197 * 198 * Each box in the diagram represents a nibble (4 bits) of a FAT 199 * entry. A FAT entry is made up of three nibbles. So if you 200 * look closely, you'll see that first byte of the pair of 201 * entries contains the low and middle nibbles of the first 202 * entry. The second byte has the low nibble of the second entry 203 * and the high nibble of the first entry. Those two bytes alone 204 * are enough to read the first entry. The second FAT entry is 205 * finished out by the last nibble pair. 206 */ 207 int32_t 208 readFATEntry(int32_t currentCluster) 209 { 210 int32_t value; 211 uchar_t *ep; 212 213 ep = findClusterEntryInFAT(currentCluster); 214 if (FATEntrySize == 32) { 215 read_32_bits(ep, (uint32_t *)&value); 216 } else if (FATEntrySize == 16) { 217 read_16_bits(ep, (uint32_t *)&value); 218 /* 219 * Convert 16 bit entry to 32 bit if we are 220 * into the reserved or higher values. 221 */ 222 if (value >= PCF_RESCLUSTER) 223 value |= 0xFFF0000; 224 } else { 225 value = 0; 226 if (currentCluster & 1) { 227 /* 228 * Odd numbered cluster 229 */ 230 value = (((unsigned int)*ep++ & 0xf0) >> 4); 231 value += (*ep << 4); 232 } else { 233 value = *ep++; 234 value += ((*ep & 0x0f) << 8); 235 } 236 /* 237 * Convert 12 bit entry to 32 bit if we are 238 * into the reserved or higher values. 239 */ 240 if (value >= PCF_12BCLUSTER) 241 value |= 0xFFFF000; 242 } 243 return (value); 244 } 245 246 void 247 writeFATEntry(int32_t currentCluster, int32_t value) 248 { 249 uchar_t *ep; 250 251 FATRewriteNeeded = 1; 252 ep = findClusterEntryInFAT(currentCluster); 253 if (FATEntrySize == 32) { 254 store_32_bits(&ep, value); 255 } else if (FATEntrySize == 16) { 256 store_16_bits(&ep, value); 257 } else { 258 if (currentCluster & 1) { 259 /* 260 * Odd numbered cluster 261 */ 262 *ep = (*ep & 0x0f) | ((value << 4) & 0xf0); 263 ep++; 264 *ep = (value >> 4) & 0xff; 265 } else { 266 *ep++ = value & 0xff; 267 *ep = (*ep & 0xf0) | ((value >> 8) & 0x0f); 268 } 269 } 270 } 271 272 /* 273 * reservedInFAT - Is this cluster marked in the reserved range? 274 * The range from PCF_RESCLUSTER32 to PCF_BADCLUSTER32 - 1, 275 * have been reserved by Microsoft. No cluster should be 276 * marked with these; they are effectively invalid cluster values. 277 */ 278 int 279 reservedInFAT(int32_t clusterNum) 280 { 281 int32_t e; 282 283 e = readFATEntry(clusterNum); 284 return (e >= PCF_RESCLUSTER32 && e < PCF_BADCLUSTER32); 285 } 286 287 /* 288 * badInFAT - Is this cluster marked as bad? I.e., is it inaccessible? 289 */ 290 int 291 badInFAT(int32_t clusterNum) 292 { 293 return (readFATEntry(clusterNum) == PCF_BADCLUSTER32); 294 } 295 296 /* 297 * lastInFAT - Is this cluster marked as free? I.e., is it available 298 * for use? 299 */ 300 int 301 freeInFAT(int32_t clusterNum) 302 { 303 return (readFATEntry(clusterNum) == PCF_FREECLUSTER); 304 } 305 306 /* 307 * lastInFAT - Is this cluster the last in its cluster chain? 308 */ 309 int 310 lastInFAT(int32_t clusterNum) 311 { 312 return (readFATEntry(clusterNum) == PCF_LASTCLUSTER32); 313 } 314 315 /* 316 * markLastInFAT - Mark this cluster as the last in its cluster chain. 317 */ 318 void 319 markLastInFAT(int32_t clusterNum) 320 { 321 writeFATEntry(clusterNum, PCF_LASTCLUSTER32); 322 } 323 324 void 325 markFreeInFAT(int32_t clusterNum) 326 { 327 writeFATEntry(clusterNum, PCF_FREECLUSTER); 328 } 329 330 void 331 markBadInFAT(int32_t clusterNum) 332 { 333 writeFATEntry(clusterNum, PCF_BADCLUSTER32); 334 } 335