diff options
author | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-15 21:04:28 +0100 |
---|---|---|
committer | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-24 18:05:53 +0100 |
commit | c876d3bbefe0dc00c27ca0c12d29da5874946962 (patch) | |
tree | 69f468a185a369b01998314bc3ecc19b70f4fcaa /rbutil/ipodpatcher/fat32format.c | |
parent | 6c6f0757d7a902feb293be165d1490c42bc8e7ad (diff) | |
download | rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.tar.gz rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.zip |
rbutil: Merge rbutil with utils folder.
rbutil uses several components from the utils folder, and can be
considered part of utils too. Having it in a separate folder is an
arbitrary split that doesn't help anymore these days, so merge them.
This also allows other utils to easily use libtools.make without the
need to navigate to a different folder.
Change-Id: I3fc2f4de19e3e776553efb5dea5f779dfec0dc21
Diffstat (limited to 'rbutil/ipodpatcher/fat32format.c')
-rw-r--r-- | rbutil/ipodpatcher/fat32format.c | 530 |
1 files changed, 0 insertions, 530 deletions
diff --git a/rbutil/ipodpatcher/fat32format.c b/rbutil/ipodpatcher/fat32format.c deleted file mode 100644 index 7ee8021cbf..0000000000 --- a/rbutil/ipodpatcher/fat32format.c +++ /dev/null @@ -1,530 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * - * FAT32 formatting functions. Based on: - * - * Fat32 formatter version 1.03 - * (c) Tom Thornhill 2005 - * This software is covered by the GPL. - * By using this tool, you agree to absolve Ridgecrop of an liabilities for - * lost data. - * Please backup any data you value before using this tool. - * - * - * Modified June 2007 by Dave Chapman for use in ipodpatcher - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdbool.h> -#include <stdint.h> -#include <inttypes.h> - -#include "ipodio.h" - -static inline uint16_t swap16(uint16_t value) -{ - return (value >> 8) | (value << 8); -} - -static inline uint32_t swap32(uint32_t value) -{ - uint32_t hi = swap16(value >> 16); - uint32_t lo = swap16(value & 0xffff); - return (lo << 16) | hi; -} - -/* The following functions are not the most efficient, but are - self-contained and don't require needing to know endianness of CPU - at compile-time. - - Note that htole16/htole32 exist on some platforms, so for - simplicity we use different names. - -*/ - -static uint16_t rb_htole16(uint16_t x) -{ - uint16_t test = 0x1234; - unsigned char* p = (unsigned char*)&test; - - if (p[0]==0x12) { - /* Big-endian */ - return swap16(x); - } else { - return x; - } -} - -static uint32_t rb_htole32(uint32_t x) -{ - uint32_t test = 0x12345678; - unsigned char* p = (unsigned char*)&test; - - if (p[0]==0x12) { - /* Big-endian */ - return swap32(x); - } else { - return x; - } -} - - -/* TODO: Pass these as parameters to the various create_ functions */ - -/* can be zero for default or 1,2,4,8,16,32 or 64 */ -static int sectors_per_cluster = 0; - -/* Recommended values */ -static uint32_t ReservedSectCount = 32; -static uint32_t NumFATs = 2; -static uint32_t BackupBootSect = 6; -static uint32_t VolumeId=0; /* calculated before format */ - -/* Calculated later */ -static uint32_t FatSize=0; -static uint32_t BytesPerSect=0; -static uint32_t SectorsPerCluster=0; -static uint32_t TotalSectors=0; -static uint32_t SystemAreaSize=0; -static uint32_t UserAreaSize=0; -static uint8_t VolId[12] = "NO NAME "; - - -struct FAT_BOOTSECTOR32 -{ - /* Common fields. */ - uint8_t sJmpBoot[3]; - char sOEMName[8]; - uint16_t wBytsPerSec; - uint8_t bSecPerClus; - uint16_t wRsvdSecCnt; - uint8_t bNumFATs; - uint16_t wRootEntCnt; - uint16_t wTotSec16; /* if zero, use dTotSec32 instead */ - uint8_t bMedia; - uint16_t wFATSz16; - uint16_t wSecPerTrk; - uint16_t wNumHeads; - uint32_t dHiddSec; - uint32_t dTotSec32; - - /* Fat 32/16 only */ - uint32_t dFATSz32; - uint16_t wExtFlags; - uint16_t wFSVer; - uint32_t dRootClus; - uint16_t wFSInfo; - uint16_t wBkBootSec; - uint8_t Reserved[12]; - uint8_t bDrvNum; - uint8_t Reserved1; - uint8_t bBootSig; /* == 0x29 if next three fields are ok */ - uint32_t dBS_VolID; - uint8_t sVolLab[11]; - uint8_t sBS_FilSysType[8]; -} __attribute__((packed)); - -struct FAT_FSINFO { - uint32_t dLeadSig; // 0x41615252 - uint8_t sReserved1[480]; // zeros - uint32_t dStrucSig; // 0x61417272 - uint32_t dFree_Count; // 0xFFFFFFFF - uint32_t dNxt_Free; // 0xFFFFFFFF - uint8_t sReserved2[12]; // zeros - uint32_t dTrailSig; // 0xAA550000 -} __attribute__((packed)); - - -/* Write "count" zero sectors, starting at sector "sector" */ -static int zero_sectors(struct ipod_t* ipod, uint64_t sector, int count) -{ - int n; - - if (ipod_seek(ipod, sector * ipod->sector_size) < 0) { - fprintf(stderr,"[ERR] Seek failed\n"); - return -1; - } - - memset(ipod->sectorbuf, 0, 128 * ipod->sector_size); - - /* Write 128 sectors at a time */ - while (count) { - if (count >= 128) - n = 128; - else - n = count; - - if (ipod_write(ipod,n * ipod->sector_size) < 0) { - perror("[ERR] Write failed in zero_sectors\n"); - return -1; - } - - count -= n; - } - - return 0; -} - - -/* -28.2 CALCULATING THE VOLUME SERIAL NUMBER - -For example, say a disk was formatted on 26 Dec 95 at 9:55 PM and 41.94 -seconds. DOS takes the date and time just before it writes it to the -disk. - -Low order word is calculated: Volume Serial Number is: - Month & Day 12/26 0c1ah - Sec & Hundrenths 41:94 295eh 3578:1d02 - ----- - 3578h - -High order word is calculated: - Hours & Minutes 21:55 1537h - Year 1995 07cbh - ----- - 1d02h -*/ -static uint32_t get_volume_id ( ) -{ - /* TODO */ -#if 0 - SYSTEMTIME s; - uint32_t d; - uint16_t lo,hi,tmp; - - GetLocalTime( &s ); - - lo = s.wDay + ( s.wMonth << 8 ); - tmp = (s.wMilliseconds/10) + (s.wSecond << 8 ); - lo += tmp; - - hi = s.wMinute + ( s.wHour << 8 ); - hi += s.wYear; - - d = lo + (hi << 16); - return(d); -#endif - return(0); -} - -/* -This is the Microsoft calculation from FATGEN - - uint32_t RootDirSectors = 0; - uint32_t TmpVal1, TmpVal2, FATSz; - - TmpVal1 = DskSize - ( ReservedSecCnt + RootDirSectors); - TmpVal2 = (256 * SecPerClus) + NumFATs; - TmpVal2 = TmpVal2 / 2; - FATSz = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2; - - return( FatSz ); -*/ - - -static uint32_t get_fat_size_sectors(uint32_t DskSize, uint32_t ReservedSecCnt, - uint32_t SecPerClus, uint32_t NumFATs, - uint32_t BytesPerSect) -{ - uint64_t Numerator, Denominator; - uint64_t FatElementSize = 4; - uint64_t FatSz; - - /* This is based on - http://hjem.get2net.dk/rune_moeller_barnkob/filesystems/fat.html - I've made the obvious changes for FAT32 - */ - - Numerator = FatElementSize * ( DskSize - ReservedSecCnt ); - Denominator = ( SecPerClus * BytesPerSect ) + ( FatElementSize * NumFATs ); - FatSz = Numerator / Denominator; - - /* round up */ - FatSz += 1; - - return((uint32_t)FatSz); -} - -static uint8_t get_spc(uint32_t ClusterSizeKB, uint32_t BytesPerSect) -{ - uint32_t spc = ( ClusterSizeKB * 1024 ) / BytesPerSect; - return( (uint8_t) spc ); -} - -static uint8_t get_sectors_per_cluster(uint32_t DiskSizeSectors, - uint32_t BytesPerSect) -{ - uint8_t ret = 0x01; /* 1 sector per cluster */ - uint64_t DiskSizeBytes = (uint64_t)DiskSizeSectors * (uint64_t)BytesPerSect; - int64_t DiskSizeMB = DiskSizeBytes / ( 1024*1024 ); - - /* 512 MB to 8,191 MB 4 KB */ - if ( DiskSizeMB > 512 ) - ret = get_spc( 4, BytesPerSect ); /* ret = 0x8; */ - - /* 8,192 MB to 16,383 MB 8 KB */ - if ( DiskSizeMB > 8192 ) - ret = get_spc( 8, BytesPerSect ); /* ret = 0x10; */ - - /* 16,384 MB to 32,767 MB 16 KB */ - if ( DiskSizeMB > 16384 ) - ret = get_spc( 16, BytesPerSect ); /* ret = 0x20; */ - - /* Larger than 32,768 MB 32 KB */ - if ( DiskSizeMB > 32768 ) - ret = get_spc( 32, BytesPerSect ); /* ret = 0x40; */ - - return( ret ); - -} - -static void create_boot_sector(unsigned char* buf, - struct ipod_t* ipod, int partition) -{ - struct FAT_BOOTSECTOR32* pFAT32BootSect = (struct FAT_BOOTSECTOR32*)buf; - - /* fill out the boot sector and fs info */ - pFAT32BootSect->sJmpBoot[0]=0xEB; - pFAT32BootSect->sJmpBoot[1]=0x5A; - pFAT32BootSect->sJmpBoot[2]=0x90; - memcpy(pFAT32BootSect->sOEMName, "MSWIN4.1", 8 ); - pFAT32BootSect->wBytsPerSec = rb_htole16(BytesPerSect); - pFAT32BootSect->bSecPerClus = SectorsPerCluster ; - pFAT32BootSect->wRsvdSecCnt = rb_htole16(ReservedSectCount); - pFAT32BootSect->bNumFATs = NumFATs; - pFAT32BootSect->wRootEntCnt = rb_htole16(0); - pFAT32BootSect->wTotSec16 = rb_htole16(0); - pFAT32BootSect->bMedia = 0xF8; - pFAT32BootSect->wFATSz16 = rb_htole16(0); - pFAT32BootSect->wSecPerTrk = rb_htole16(ipod->sectors_per_track); - pFAT32BootSect->wNumHeads = rb_htole16(ipod->num_heads); - pFAT32BootSect->dHiddSec = rb_htole16(ipod->pinfo[partition].start); - pFAT32BootSect->dTotSec32 = rb_htole32(TotalSectors); - pFAT32BootSect->dFATSz32 = rb_htole32(FatSize); - pFAT32BootSect->wExtFlags = rb_htole16(0); - pFAT32BootSect->wFSVer = rb_htole16(0); - pFAT32BootSect->dRootClus = rb_htole32(2); - pFAT32BootSect->wFSInfo = rb_htole16(1); - pFAT32BootSect->wBkBootSec = rb_htole16(BackupBootSect); - pFAT32BootSect->bDrvNum = 0x80; - pFAT32BootSect->Reserved1 = 0; - pFAT32BootSect->bBootSig = 0x29; - pFAT32BootSect->dBS_VolID = rb_htole32(VolumeId); - memcpy(pFAT32BootSect->sVolLab, VolId, 11); - memcpy(pFAT32BootSect->sBS_FilSysType, "FAT32 ", 8 ); - - buf[510] = 0x55; - buf[511] = 0xaa; -} - -static void create_fsinfo(unsigned char* buf) -{ - struct FAT_FSINFO* pFAT32FsInfo = (struct FAT_FSINFO*)buf; - - /* FSInfo sect */ - pFAT32FsInfo->dLeadSig = rb_htole32(0x41615252); - pFAT32FsInfo->dStrucSig = rb_htole32(0x61417272); - pFAT32FsInfo->dFree_Count = rb_htole32((uint32_t) -1); - pFAT32FsInfo->dNxt_Free = rb_htole32((uint32_t) -1); - pFAT32FsInfo->dTrailSig = rb_htole32(0xaa550000); - pFAT32FsInfo->dFree_Count = rb_htole32((UserAreaSize/SectorsPerCluster)-1); - - /* clusters 0-1 reserved, we used cluster 2 for the root dir */ - pFAT32FsInfo->dNxt_Free = rb_htole32(3); -} - -static void create_firstfatsector(unsigned char* buf) -{ - uint32_t* p = (uint32_t*)buf; /* We know the buffer is aligned */ - - /* First FAT Sector */ - p[0] = rb_htole32(0x0ffffff8); /* Reserved cluster 1 media id in low byte */ - p[1] = rb_htole32(0x0fffffff); /* Reserved cluster 2 EOC */ - p[2] = rb_htole32(0x0fffffff); /* end of cluster chain for root dir */ -} - -int format_partition(struct ipod_t* ipod, int partition) -{ - uint32_t i; - uint64_t qTotalSectors=0; - uint64_t FatNeeded; - - VolumeId = get_volume_id( ); - - /* Only support hard disks at the moment */ - if ( ipod->sector_size != 512 ) - { - fprintf(stderr,"[ERR] Only disks with 512 bytes per sector are supported.\n"); - return -1; - } - BytesPerSect = ipod->sector_size; - - /* Checks on Disk Size */ - qTotalSectors = ipod->pinfo[partition].size; - - /* low end limit - 65536 sectors */ - if ( qTotalSectors < 65536 ) - { - /* I suspect that most FAT32 implementations would mount this - volume just fine, but the spec says that we shouldn't do - this, so we won't */ - - fprintf(stderr,"[ERR] This drive is too small for FAT32 - there must be at least 64K clusters\n" ); - return -1; - } - - if ( qTotalSectors >= 0xffffffff ) - { - /* This is a more fundamental limitation on FAT32 - the total - sector count in the root dir is 32bit. With a bit of - creativity, FAT32 could be extended to handle at least 2^28 - clusters There would need to be an extra field in the - FSInfo sector, and the old sector count could be set to - 0xffffffff. This is non standard though, the Windows FAT - driver FASTFAT.SYS won't understand this. Perhaps a future - version of FAT32 and FASTFAT will handle this. */ - - fprintf(stderr,"[ERR] This drive is too big for FAT32 - max 2TB supported\n"); - } - - if ( sectors_per_cluster ) { - SectorsPerCluster = sectors_per_cluster; - } else { - SectorsPerCluster = get_sectors_per_cluster(ipod->pinfo[partition].size, - BytesPerSect ); - } - - TotalSectors = (uint32_t) qTotalSectors; - - FatSize = get_fat_size_sectors(TotalSectors, ReservedSectCount, - SectorsPerCluster, NumFATs, BytesPerSect ); - - UserAreaSize = TotalSectors - ReservedSectCount - (NumFATs*FatSize); - - /* First zero out ReservedSect + FatSize * NumFats + SectorsPerCluster */ - SystemAreaSize = (ReservedSectCount+(NumFATs*FatSize) + SectorsPerCluster); - - /* Work out the Cluster count */ - FatNeeded = UserAreaSize/SectorsPerCluster; - - /* check for a cluster count of >2^28, since the upper 4 bits of - the cluster values in the FAT are reserved. */ - if (FatNeeded > 0x0FFFFFFF) { - fprintf(stderr,"[ERR] This drive has more than 2^28 clusters, try to specify a larger cluster size\n" ); - return -1; - } - - /* Sanity check, make sure the fat is big enough. - Convert the cluster count into a Fat sector count, and check - the fat size value we calculated earlier is OK. */ - - FatNeeded *=4; - FatNeeded += (BytesPerSect-1); - FatNeeded /= BytesPerSect; - - if ( FatNeeded > FatSize ) { - fprintf(stderr,"[ERR] Drive too big to format\n"); - return -1; - } - - /* - Write boot sector, fats - Sector 0 Boot Sector - Sector 1 FSInfo - Sector 2 More boot code - we write zeros here - Sector 3 unused - Sector 4 unused - Sector 5 unused - Sector 6 Backup boot sector - Sector 7 Backup FSInfo sector - Sector 8 Backup 'more boot code' - zero'd sectors upto ReservedSectCount - FAT1 ReservedSectCount to ReservedSectCount + FatSize - ... - FATn ReservedSectCount to ReservedSectCount + FatSize - RootDir - allocated to cluster2 - */ - - fprintf(stderr,"[INFO] Heads - %d, sectors/track = %d\n",ipod->num_heads,ipod->sectors_per_track); - fprintf(stderr,"[INFO] Size : %" PRIu64 "GB %u sectors\n", - ((uint64_t)ipod->pinfo[partition].size * (uint64_t)ipod->sector_size) / (1000*1000*1000), TotalSectors ); - fprintf(stderr,"[INFO] %d Bytes Per Sector, Cluster size %d bytes\n", BytesPerSect, SectorsPerCluster*BytesPerSect ); - fprintf(stderr,"[INFO] Volume ID is %x:%x\n", VolumeId>>16, VolumeId&0xffff ); - fprintf(stderr,"[INFO] %d Reserved Sectors, %d Sectors per FAT, %d fats\n", ReservedSectCount, FatSize, NumFATs ); - fprintf (stderr,"[INFO] %d Total clusters\n", UserAreaSize/SectorsPerCluster ); - - fprintf(stderr,"[INFO] Formatting partition %d:...\n",partition); - - /* Once zero_sectors has run, any data on the drive is basically lost... */ - fprintf(stderr,"[INFO] Clearing out %d sectors for Reserved sectors, fats and root cluster...\n", SystemAreaSize ); - - zero_sectors(ipod, ipod->pinfo[partition].start, SystemAreaSize); - - fprintf(stderr,"[INFO] Initialising reserved sectors and FATs...\n" ); - - /* Create the boot sector structure */ - create_boot_sector(ipod->sectorbuf, ipod, partition); - create_fsinfo(ipod->sectorbuf + 512); - - /* Write boot sector and fsinfo at start of partition */ - if (ipod_seek(ipod, ipod->pinfo[partition].start * ipod->sector_size) < 0) { - fprintf(stderr,"[ERR] Seek failed\n"); - return -1; - } - if (ipod_write(ipod,512 * 2) < 0) { - perror("[ERR] Write failed (first copy of bootsect/fsinfo)\n"); - return -1; - } - - /* Write backup copy of boot sector and fsinfo */ - if (ipod_seek(ipod, (ipod->pinfo[partition].start + BackupBootSect) * ipod->sector_size) < 0) { - fprintf(stderr,"[ERR] Seek failed\n"); - return -1; - } - if (ipod_write(ipod,512 * 2) < 0) { - perror("[ERR] Write failed (first copy of bootsect/fsinfo)\n"); - return -1; - } - - /* Create the first FAT sector */ - create_firstfatsector(ipod->sectorbuf); - - /* Write the first fat sector in the right places */ - for ( i=0; i<NumFATs; i++ ) { - int SectorStart = ReservedSectCount + (i * FatSize ); - - if (ipod_seek(ipod, (ipod->pinfo[partition].start + SectorStart) * ipod->sector_size) < 0) { - fprintf(stderr,"[ERR] Seek failed\n"); - return -1; - } - - if (ipod_write(ipod,512) < 0) { - perror("[ERR] Write failed (first copy of bootsect/fsinfo)\n"); - return -1; - } - } - - fprintf(stderr,"[INFO] Format successful\n"); - - return 0; -} |