summaryrefslogtreecommitdiffstats
path: root/rbutil/ipodpatcher/fat32format.c
diff options
context:
space:
mode:
authorDominik Riebeling <Dominik.Riebeling@gmail.com>2021-12-15 21:04:28 +0100
committerDominik Riebeling <Dominik.Riebeling@gmail.com>2021-12-24 18:05:53 +0100
commitc876d3bbefe0dc00c27ca0c12d29da5874946962 (patch)
tree69f468a185a369b01998314bc3ecc19b70f4fcaa /rbutil/ipodpatcher/fat32format.c
parent6c6f0757d7a902feb293be165d1490c42bc8e7ad (diff)
downloadrockbox-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.c530
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;
-}