1f9f848faSopenharmony_ci/*- 2f9f848faSopenharmony_ci * SPDX-License-Identifier: BSD-2-Clause 3f9f848faSopenharmony_ci * 4f9f848faSopenharmony_ci * Copyright (C) 1995, 1997 Wolfgang Solfrank 5f9f848faSopenharmony_ci * Copyright (c) 1995 Martin Husemann 6f9f848faSopenharmony_ci * 7f9f848faSopenharmony_ci * Redistribution and use in source and binary forms, with or without 8f9f848faSopenharmony_ci * modification, are permitted provided that the following conditions 9f9f848faSopenharmony_ci * are met: 10f9f848faSopenharmony_ci * 1. Redistributions of source code must retain the above copyright 11f9f848faSopenharmony_ci * notice, this list of conditions and the following disclaimer. 12f9f848faSopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 13f9f848faSopenharmony_ci * notice, this list of conditions and the following disclaimer in the 14f9f848faSopenharmony_ci * documentation and/or other materials provided with the distribution. 15f9f848faSopenharmony_ci * 16f9f848faSopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 17f9f848faSopenharmony_ci * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18f9f848faSopenharmony_ci * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19f9f848faSopenharmony_ci * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20f9f848faSopenharmony_ci * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21f9f848faSopenharmony_ci * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22f9f848faSopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23f9f848faSopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24f9f848faSopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25f9f848faSopenharmony_ci * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26f9f848faSopenharmony_ci */ 27f9f848faSopenharmony_ci 28f9f848faSopenharmony_ci 29f9f848faSopenharmony_ci#include <sys/cdefs.h> 30f9f848faSopenharmony_ci#ifndef lint 31f9f848faSopenharmony_ci__RCSID("$NetBSD: boot.c,v 1.22 2020/01/11 16:29:07 christos Exp $"); 32f9f848faSopenharmony_ci#endif /* not lint */ 33f9f848faSopenharmony_ci 34f9f848faSopenharmony_ci#include <sys/param.h> 35f9f848faSopenharmony_ci 36f9f848faSopenharmony_ci#include <stdint.h> 37f9f848faSopenharmony_ci#include <stdlib.h> 38f9f848faSopenharmony_ci#include <string.h> 39f9f848faSopenharmony_ci#include <stdio.h> 40f9f848faSopenharmony_ci#include <unistd.h> 41f9f848faSopenharmony_ci 42f9f848faSopenharmony_ci#include "ext.h" 43f9f848faSopenharmony_ci#include "fsutil.h" 44f9f848faSopenharmony_ci 45f9f848faSopenharmony_ciint 46f9f848faSopenharmony_cireadboot(int dosfs, struct bootblock *boot) 47f9f848faSopenharmony_ci{ 48f9f848faSopenharmony_ci u_char block[DOSBOOTBLOCKSIZE]; 49f9f848faSopenharmony_ci u_char fsinfo[2 * DOSBOOTBLOCKSIZE]; 50f9f848faSopenharmony_ci int ret = FSOK; 51f9f848faSopenharmony_ci 52f9f848faSopenharmony_ci if ((size_t)read(dosfs, block, sizeof block) != sizeof block) { 53f9f848faSopenharmony_ci perr("could not read boot block"); 54f9f848faSopenharmony_ci return FSFATAL; 55f9f848faSopenharmony_ci } 56f9f848faSopenharmony_ci 57f9f848faSopenharmony_ci if (block[510] != 0x55 || block[511] != 0xaa) { 58f9f848faSopenharmony_ci pfatal("Invalid signature in boot block: %02x%02x", 59f9f848faSopenharmony_ci block[511], block[510]); 60f9f848faSopenharmony_ci return FSFATAL; 61f9f848faSopenharmony_ci } 62f9f848faSopenharmony_ci 63f9f848faSopenharmony_ci memset(boot, 0, sizeof *boot); 64f9f848faSopenharmony_ci boot->ValidFat = -1; 65f9f848faSopenharmony_ci 66f9f848faSopenharmony_ci /* Decode BIOS Parameter Block */ 67f9f848faSopenharmony_ci 68f9f848faSopenharmony_ci /* Bytes per sector: can only be 512, 1024, 2048 and 4096. */ 69f9f848faSopenharmony_ci boot->bpbBytesPerSec = block[11] + (block[12] << 8); 70f9f848faSopenharmony_ci if (boot->bpbBytesPerSec < DOSBOOTBLOCKSIZE_REAL || 71f9f848faSopenharmony_ci boot->bpbBytesPerSec > DOSBOOTBLOCKSIZE || 72f9f848faSopenharmony_ci !powerof2(boot->bpbBytesPerSec)) { 73f9f848faSopenharmony_ci pfatal("Invalid sector size: %u", boot->bpbBytesPerSec); 74f9f848faSopenharmony_ci return FSFATAL; 75f9f848faSopenharmony_ci } 76f9f848faSopenharmony_ci 77f9f848faSopenharmony_ci /* Sectors per cluster: can only be: 1, 2, 4, 8, 16, 32, 64, 128. */ 78f9f848faSopenharmony_ci boot->bpbSecPerClust = block[13]; 79f9f848faSopenharmony_ci if (boot->bpbSecPerClust == 0 || !powerof2(boot->bpbSecPerClust)) { 80f9f848faSopenharmony_ci pfatal("Invalid cluster size: %u", boot->bpbSecPerClust); 81f9f848faSopenharmony_ci return FSFATAL; 82f9f848faSopenharmony_ci } 83f9f848faSopenharmony_ci 84f9f848faSopenharmony_ci /* Reserved sectors: must be non-zero */ 85f9f848faSopenharmony_ci boot->bpbResSectors = block[14] + (block[15] << 8); 86f9f848faSopenharmony_ci if (boot->bpbResSectors < 1) { 87f9f848faSopenharmony_ci pfatal("Invalid reserved sectors: %u", 88f9f848faSopenharmony_ci boot->bpbResSectors); 89f9f848faSopenharmony_ci return FSFATAL; 90f9f848faSopenharmony_ci } 91f9f848faSopenharmony_ci 92f9f848faSopenharmony_ci /* Number of FATs */ 93f9f848faSopenharmony_ci boot->bpbFATs = block[16]; 94f9f848faSopenharmony_ci if (boot->bpbFATs == 0) { 95f9f848faSopenharmony_ci pfatal("Invalid number of FATs: %u", boot->bpbFATs); 96f9f848faSopenharmony_ci return FSFATAL; 97f9f848faSopenharmony_ci } 98f9f848faSopenharmony_ci 99f9f848faSopenharmony_ci /* Root directory entries for FAT12 and FAT16 */ 100f9f848faSopenharmony_ci boot->bpbRootDirEnts = block[17] + (block[18] << 8); 101f9f848faSopenharmony_ci if (!boot->bpbRootDirEnts) { 102f9f848faSopenharmony_ci /* bpbRootDirEnts = 0 suggests that we are FAT32 */ 103f9f848faSopenharmony_ci boot->flags |= FAT32; 104f9f848faSopenharmony_ci } 105f9f848faSopenharmony_ci 106f9f848faSopenharmony_ci /* Total sectors (16 bits) */ 107f9f848faSopenharmony_ci boot->bpbSectors = block[19] + (block[20] << 8); 108f9f848faSopenharmony_ci if (boot->bpbSectors != 0 && (boot->flags & FAT32)) { 109f9f848faSopenharmony_ci pfatal("Invalid 16-bit total sector count on FAT32: %u", 110f9f848faSopenharmony_ci boot->bpbSectors); 111f9f848faSopenharmony_ci return FSFATAL; 112f9f848faSopenharmony_ci } 113f9f848faSopenharmony_ci 114f9f848faSopenharmony_ci /* Media type: ignored */ 115f9f848faSopenharmony_ci boot->bpbMedia = block[21]; 116f9f848faSopenharmony_ci 117f9f848faSopenharmony_ci /* FAT12/FAT16: 16-bit count of sectors per FAT */ 118f9f848faSopenharmony_ci boot->bpbFATsmall = block[22] + (block[23] << 8); 119f9f848faSopenharmony_ci if (boot->bpbFATsmall != 0 && (boot->flags & FAT32)) { 120f9f848faSopenharmony_ci pfatal("Invalid 16-bit FAT sector count on FAT32: %u", 121f9f848faSopenharmony_ci boot->bpbFATsmall); 122f9f848faSopenharmony_ci return FSFATAL; 123f9f848faSopenharmony_ci } 124f9f848faSopenharmony_ci 125f9f848faSopenharmony_ci /* Legacy CHS geometry numbers: ignored */ 126f9f848faSopenharmony_ci boot->SecPerTrack = block[24] + (block[25] << 8); 127f9f848faSopenharmony_ci boot->bpbHeads = block[26] + (block[27] << 8); 128f9f848faSopenharmony_ci 129f9f848faSopenharmony_ci /* Hidden sectors: ignored */ 130f9f848faSopenharmony_ci boot->bpbHiddenSecs = block[28] + (block[29] << 8) + 131f9f848faSopenharmony_ci (block[30] << 16) + (block[31] << 24); 132f9f848faSopenharmony_ci 133f9f848faSopenharmony_ci /* Total sectors (32 bits) */ 134f9f848faSopenharmony_ci boot->bpbHugeSectors = block[32] + (block[33] << 8) + 135f9f848faSopenharmony_ci (block[34] << 16) + (block[35] << 24); 136f9f848faSopenharmony_ci if (boot->bpbHugeSectors == 0) { 137f9f848faSopenharmony_ci if (boot->flags & FAT32) { 138f9f848faSopenharmony_ci pfatal("FAT32 with sector count of zero"); 139f9f848faSopenharmony_ci return FSFATAL; 140f9f848faSopenharmony_ci } else if (boot->bpbSectors == 0) { 141f9f848faSopenharmony_ci pfatal("FAT with sector count of zero"); 142f9f848faSopenharmony_ci return FSFATAL; 143f9f848faSopenharmony_ci } 144f9f848faSopenharmony_ci boot->NumSectors = boot->bpbSectors; 145f9f848faSopenharmony_ci } else { 146f9f848faSopenharmony_ci if (boot->bpbSectors != 0) { 147f9f848faSopenharmony_ci pfatal("Invalid FAT sector count"); 148f9f848faSopenharmony_ci return FSFATAL; 149f9f848faSopenharmony_ci } 150f9f848faSopenharmony_ci boot->NumSectors = boot->bpbHugeSectors; 151f9f848faSopenharmony_ci } 152f9f848faSopenharmony_ci 153f9f848faSopenharmony_ci if (boot->flags & FAT32) { 154f9f848faSopenharmony_ci /* If the OEM Name field is EXFAT, it's not FAT32, so bail */ 155f9f848faSopenharmony_ci if (!memcmp(&block[3], "EXFAT ", 8)) { 156f9f848faSopenharmony_ci pfatal("exFAT filesystem is not supported."); 157f9f848faSopenharmony_ci return FSFATAL; 158f9f848faSopenharmony_ci } 159f9f848faSopenharmony_ci 160f9f848faSopenharmony_ci /* 32-bit count of sectors per FAT */ 161f9f848faSopenharmony_ci boot->FATsecs = block[36] + (block[37] << 8) 162f9f848faSopenharmony_ci + (block[38] << 16) + (block[39] << 24); 163f9f848faSopenharmony_ci 164f9f848faSopenharmony_ci if (block[40] & 0x80) 165f9f848faSopenharmony_ci boot->ValidFat = block[40] & 0x0f; 166f9f848faSopenharmony_ci 167f9f848faSopenharmony_ci /* FAT32 version, bail out if not 0.0 */ 168f9f848faSopenharmony_ci if (block[42] || block[43]) { 169f9f848faSopenharmony_ci pfatal("Unknown file system version: %x.%x", 170f9f848faSopenharmony_ci block[43], block[42]); 171f9f848faSopenharmony_ci return FSFATAL; 172f9f848faSopenharmony_ci } 173f9f848faSopenharmony_ci 174f9f848faSopenharmony_ci /* 175f9f848faSopenharmony_ci * Cluster number of the first cluster of root directory. 176f9f848faSopenharmony_ci * 177f9f848faSopenharmony_ci * Should be 2 but do not require it. 178f9f848faSopenharmony_ci */ 179f9f848faSopenharmony_ci boot->bpbRootClust = block[44] + (block[45] << 8) 180f9f848faSopenharmony_ci + (block[46] << 16) + (block[47] << 24); 181f9f848faSopenharmony_ci 182f9f848faSopenharmony_ci /* Sector number of the FSInfo structure, usually 1 */ 183f9f848faSopenharmony_ci boot->bpbFSInfo = block[48] + (block[49] << 8); 184f9f848faSopenharmony_ci 185f9f848faSopenharmony_ci /* Sector number of the backup boot block, ignored */ 186f9f848faSopenharmony_ci boot->bpbBackup = block[50] + (block[51] << 8); 187f9f848faSopenharmony_ci 188f9f848faSopenharmony_ci /* Check basic parameters */ 189f9f848faSopenharmony_ci if (boot->bpbFSInfo == 0) { 190f9f848faSopenharmony_ci /* 191f9f848faSopenharmony_ci * Either the BIOS Parameter Block has been corrupted, 192f9f848faSopenharmony_ci * or this is not a FAT32 filesystem, most likely an 193f9f848faSopenharmony_ci * exFAT filesystem. 194f9f848faSopenharmony_ci */ 195f9f848faSopenharmony_ci pfatal("Invalid FAT32 Extended BIOS Parameter Block"); 196f9f848faSopenharmony_ci return FSFATAL; 197f9f848faSopenharmony_ci } 198f9f848faSopenharmony_ci 199f9f848faSopenharmony_ci /* Read in and verify the FSInfo block */ 200f9f848faSopenharmony_ci if (lseek(dosfs, boot->bpbFSInfo * boot->bpbBytesPerSec, 201f9f848faSopenharmony_ci SEEK_SET) != boot->bpbFSInfo * boot->bpbBytesPerSec 202f9f848faSopenharmony_ci || read(dosfs, fsinfo, sizeof fsinfo) != sizeof fsinfo) { 203f9f848faSopenharmony_ci perr("could not read fsinfo block"); 204f9f848faSopenharmony_ci return FSFATAL; 205f9f848faSopenharmony_ci } 206f9f848faSopenharmony_ci if (memcmp(fsinfo, "RRaA", 4) 207f9f848faSopenharmony_ci || memcmp(fsinfo + 0x1e4, "rrAa", 4) 208f9f848faSopenharmony_ci || fsinfo[0x1fc] 209f9f848faSopenharmony_ci || fsinfo[0x1fd] 210f9f848faSopenharmony_ci || fsinfo[0x1fe] != 0x55 211f9f848faSopenharmony_ci || fsinfo[0x1ff] != 0xaa 212f9f848faSopenharmony_ci || fsinfo[0x3fc] 213f9f848faSopenharmony_ci || fsinfo[0x3fd] 214f9f848faSopenharmony_ci || fsinfo[0x3fe] != 0x55 215f9f848faSopenharmony_ci || fsinfo[0x3ff] != 0xaa) { 216f9f848faSopenharmony_ci pwarn("Invalid signature in fsinfo block\n"); 217f9f848faSopenharmony_ci if (ask(0, "Fix")) { 218f9f848faSopenharmony_ci memcpy(fsinfo, "RRaA", 4); 219f9f848faSopenharmony_ci memcpy(fsinfo + 0x1e4, "rrAa", 4); 220f9f848faSopenharmony_ci fsinfo[0x1fc] = fsinfo[0x1fd] = 0; 221f9f848faSopenharmony_ci fsinfo[0x1fe] = 0x55; 222f9f848faSopenharmony_ci fsinfo[0x1ff] = 0xaa; 223f9f848faSopenharmony_ci fsinfo[0x3fc] = fsinfo[0x3fd] = 0; 224f9f848faSopenharmony_ci fsinfo[0x3fe] = 0x55; 225f9f848faSopenharmony_ci fsinfo[0x3ff] = 0xaa; 226f9f848faSopenharmony_ci if (lseek(dosfs, boot->bpbFSInfo * 227f9f848faSopenharmony_ci boot->bpbBytesPerSec, SEEK_SET) 228f9f848faSopenharmony_ci != boot->bpbFSInfo * boot->bpbBytesPerSec 229f9f848faSopenharmony_ci || write(dosfs, fsinfo, sizeof fsinfo) 230f9f848faSopenharmony_ci != sizeof fsinfo) { 231f9f848faSopenharmony_ci perr("Unable to write bpbFSInfo"); 232f9f848faSopenharmony_ci return FSFATAL; 233f9f848faSopenharmony_ci } 234f9f848faSopenharmony_ci ret = FSBOOTMOD; 235f9f848faSopenharmony_ci } else 236f9f848faSopenharmony_ci boot->bpbFSInfo = 0; 237f9f848faSopenharmony_ci } else { 238f9f848faSopenharmony_ci /* We appear to have a valid FSInfo block, decode */ 239f9f848faSopenharmony_ci boot->FSFree = fsinfo[0x1e8] + (fsinfo[0x1e9] << 8) 240f9f848faSopenharmony_ci + (fsinfo[0x1ea] << 16) 241f9f848faSopenharmony_ci + (fsinfo[0x1eb] << 24); 242f9f848faSopenharmony_ci boot->FSNext = fsinfo[0x1ec] + (fsinfo[0x1ed] << 8) 243f9f848faSopenharmony_ci + (fsinfo[0x1ee] << 16) 244f9f848faSopenharmony_ci + (fsinfo[0x1ef] << 24); 245f9f848faSopenharmony_ci } 246f9f848faSopenharmony_ci } else { 247f9f848faSopenharmony_ci /* !FAT32: FAT12/FAT16 */ 248f9f848faSopenharmony_ci boot->FATsecs = boot->bpbFATsmall; 249f9f848faSopenharmony_ci } 250f9f848faSopenharmony_ci 251f9f848faSopenharmony_ci if (boot->FATsecs < 1 || boot->FATsecs > UINT32_MAX / boot->bpbFATs) { 252f9f848faSopenharmony_ci pfatal("Invalid FATs(%u) with FATsecs(%zu)", 253f9f848faSopenharmony_ci boot->bpbFATs, (size_t)boot->FATsecs); 254f9f848faSopenharmony_ci return FSFATAL; 255f9f848faSopenharmony_ci } 256f9f848faSopenharmony_ci 257f9f848faSopenharmony_ci boot->FirstCluster = (boot->bpbRootDirEnts * 32 + 258f9f848faSopenharmony_ci boot->bpbBytesPerSec - 1) / boot->bpbBytesPerSec + 259f9f848faSopenharmony_ci boot->bpbResSectors + boot->bpbFATs * boot->FATsecs; 260f9f848faSopenharmony_ci 261f9f848faSopenharmony_ci if (boot->FirstCluster + boot->bpbSecPerClust > boot->NumSectors) { 262f9f848faSopenharmony_ci pfatal("Cluster offset too large (%u clusters)\n", 263f9f848faSopenharmony_ci boot->FirstCluster); 264f9f848faSopenharmony_ci return FSFATAL; 265f9f848faSopenharmony_ci } 266f9f848faSopenharmony_ci 267f9f848faSopenharmony_ci /* 268f9f848faSopenharmony_ci * The number of clusters is derived from available data sectors, 269f9f848faSopenharmony_ci * divided by sectors per cluster. 270f9f848faSopenharmony_ci */ 271f9f848faSopenharmony_ci boot->NumClusters = 272f9f848faSopenharmony_ci (boot->NumSectors - boot->FirstCluster) / boot->bpbSecPerClust; 273f9f848faSopenharmony_ci 274f9f848faSopenharmony_ci if (boot->flags & FAT32) { 275f9f848faSopenharmony_ci if (boot->NumClusters > (CLUST_RSRVD & CLUST32_MASK)) { 276f9f848faSopenharmony_ci pfatal("Filesystem too big (%u clusters) for FAT32 partition", 277f9f848faSopenharmony_ci boot->NumClusters); 278f9f848faSopenharmony_ci return FSFATAL; 279f9f848faSopenharmony_ci } 280f9f848faSopenharmony_ci if (boot->NumClusters < (CLUST_RSRVD & CLUST16_MASK)) { 281f9f848faSopenharmony_ci pfatal("Filesystem too small (%u clusters) for FAT32 partition", 282f9f848faSopenharmony_ci boot->NumClusters); 283f9f848faSopenharmony_ci return FSFATAL; 284f9f848faSopenharmony_ci } 285f9f848faSopenharmony_ci boot->ClustMask = CLUST32_MASK; 286f9f848faSopenharmony_ci 287f9f848faSopenharmony_ci if (boot->bpbRootClust < CLUST_FIRST || 288f9f848faSopenharmony_ci boot->bpbRootClust >= boot->NumClusters) { 289f9f848faSopenharmony_ci pfatal("Root directory starts with cluster out of range(%u)", 290f9f848faSopenharmony_ci boot->bpbRootClust); 291f9f848faSopenharmony_ci return FSFATAL; 292f9f848faSopenharmony_ci } 293f9f848faSopenharmony_ci } else if (boot->NumClusters < (CLUST_RSRVD&CLUST12_MASK)) { 294f9f848faSopenharmony_ci boot->ClustMask = CLUST12_MASK; 295f9f848faSopenharmony_ci } else if (boot->NumClusters < (CLUST_RSRVD&CLUST16_MASK)) { 296f9f848faSopenharmony_ci boot->ClustMask = CLUST16_MASK; 297f9f848faSopenharmony_ci } else { 298f9f848faSopenharmony_ci pfatal("Filesystem too big (%u clusters) for non-FAT32 partition", 299f9f848faSopenharmony_ci boot->NumClusters); 300f9f848faSopenharmony_ci return FSFATAL; 301f9f848faSopenharmony_ci } 302f9f848faSopenharmony_ci 303f9f848faSopenharmony_ci switch (boot->ClustMask) { 304f9f848faSopenharmony_ci case CLUST32_MASK: 305f9f848faSopenharmony_ci boot->NumFatEntries = (boot->FATsecs * boot->bpbBytesPerSec) / 4; 306f9f848faSopenharmony_ci break; 307f9f848faSopenharmony_ci case CLUST16_MASK: 308f9f848faSopenharmony_ci boot->NumFatEntries = (boot->FATsecs * boot->bpbBytesPerSec) / 2; 309f9f848faSopenharmony_ci break; 310f9f848faSopenharmony_ci default: 311f9f848faSopenharmony_ci boot->NumFatEntries = (boot->FATsecs * boot->bpbBytesPerSec * 2) / 3; 312f9f848faSopenharmony_ci break; 313f9f848faSopenharmony_ci } 314f9f848faSopenharmony_ci 315f9f848faSopenharmony_ci if (boot->NumFatEntries < boot->NumClusters) { 316f9f848faSopenharmony_ci pfatal("FAT size too small, %u entries won't fit into %u sectors\n", 317f9f848faSopenharmony_ci boot->NumClusters, boot->FATsecs); 318f9f848faSopenharmony_ci return FSFATAL; 319f9f848faSopenharmony_ci } 320f9f848faSopenharmony_ci 321f9f848faSopenharmony_ci /* 322f9f848faSopenharmony_ci * There are two reserved clusters. To avoid adding CLUST_FIRST every 323f9f848faSopenharmony_ci * time we perform boundary checks, we increment the NumClusters by 2, 324f9f848faSopenharmony_ci * which is CLUST_FIRST to denote the first out-of-range cluster number. 325f9f848faSopenharmony_ci */ 326f9f848faSopenharmony_ci boot->NumClusters += CLUST_FIRST; 327f9f848faSopenharmony_ci 328f9f848faSopenharmony_ci boot->ClusterSize = boot->bpbBytesPerSec * boot->bpbSecPerClust; 329f9f848faSopenharmony_ci 330f9f848faSopenharmony_ci boot->NumFiles = 1; 331f9f848faSopenharmony_ci boot->NumFree = 0; 332f9f848faSopenharmony_ci 333f9f848faSopenharmony_ci return ret; 334f9f848faSopenharmony_ci} 335f9f848faSopenharmony_ci 336f9f848faSopenharmony_ciint 337f9f848faSopenharmony_ciwritefsinfo(int dosfs, struct bootblock *boot) 338f9f848faSopenharmony_ci{ 339f9f848faSopenharmony_ci u_char fsinfo[2 * DOSBOOTBLOCKSIZE]; 340f9f848faSopenharmony_ci 341f9f848faSopenharmony_ci if (lseek(dosfs, boot->bpbFSInfo * boot->bpbBytesPerSec, SEEK_SET) 342f9f848faSopenharmony_ci != boot->bpbFSInfo * boot->bpbBytesPerSec 343f9f848faSopenharmony_ci || read(dosfs, fsinfo, sizeof fsinfo) != sizeof fsinfo) { 344f9f848faSopenharmony_ci perr("could not read fsinfo block"); 345f9f848faSopenharmony_ci return FSFATAL; 346f9f848faSopenharmony_ci } 347f9f848faSopenharmony_ci fsinfo[0x1e8] = (u_char)boot->FSFree; 348f9f848faSopenharmony_ci fsinfo[0x1e9] = (u_char)(boot->FSFree >> 8); 349f9f848faSopenharmony_ci fsinfo[0x1ea] = (u_char)(boot->FSFree >> 16); 350f9f848faSopenharmony_ci fsinfo[0x1eb] = (u_char)(boot->FSFree >> 24); 351f9f848faSopenharmony_ci fsinfo[0x1ec] = (u_char)boot->FSNext; 352f9f848faSopenharmony_ci fsinfo[0x1ed] = (u_char)(boot->FSNext >> 8); 353f9f848faSopenharmony_ci fsinfo[0x1ee] = (u_char)(boot->FSNext >> 16); 354f9f848faSopenharmony_ci fsinfo[0x1ef] = (u_char)(boot->FSNext >> 24); 355f9f848faSopenharmony_ci if (lseek(dosfs, boot->bpbFSInfo * boot->bpbBytesPerSec, SEEK_SET) 356f9f848faSopenharmony_ci != boot->bpbFSInfo * boot->bpbBytesPerSec 357f9f848faSopenharmony_ci || write(dosfs, fsinfo, sizeof fsinfo) 358f9f848faSopenharmony_ci != sizeof fsinfo) { 359f9f848faSopenharmony_ci perr("Unable to write bpbFSInfo"); 360f9f848faSopenharmony_ci return FSFATAL; 361f9f848faSopenharmony_ci } 362f9f848faSopenharmony_ci /* 363f9f848faSopenharmony_ci * Technically, we should return FSBOOTMOD here. 364f9f848faSopenharmony_ci * 365f9f848faSopenharmony_ci * However, since Win95 OSR2 (the first M$ OS that has 366f9f848faSopenharmony_ci * support for FAT32) doesn't maintain the FSINFO block 367f9f848faSopenharmony_ci * correctly, it has to be fixed pretty often. 368f9f848faSopenharmony_ci * 369f9f848faSopenharmony_ci * Therefore, we handle the FSINFO block only informally, 370f9f848faSopenharmony_ci * fixing it if necessary, but otherwise ignoring the 371f9f848faSopenharmony_ci * fact that it was incorrect. 372f9f848faSopenharmony_ci */ 373f9f848faSopenharmony_ci return 0; 374f9f848faSopenharmony_ci} 375