Skip to content

Commit 6642011

Browse files
committed
Small changes/fixes.
Added some unfinished exFAT structs.
1 parent 8f91cb9 commit 6642011

10 files changed

Lines changed: 129 additions & 64 deletions

File tree

Makefile

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ DEFINES :=
1010

1111
# Compiler settings
1212
ARCH :=
13-
CFLAGS := $(ARCH) -std=c17 -O2 -g -fstrict-aliasing -ffunction-sections \
14-
-fdata-sections -Wall -Wextra -Wstrict-aliasing=2
15-
CXXFLAGS := $(ARCH) -std=c++20 -O2 -g -fstrict-aliasing -ffunction-sections \
16-
-fdata-sections -Wall -Wextra -Wstrict-aliasing=2
13+
CFLAGS := $(ARCH) -std=c17 -O2 -g -fstrict-aliasing \
14+
-ffunction-sections -fdata-sections -Wall -Wextra \
15+
-Wstrict-aliasing=2
16+
CXXFLAGS := $(ARCH) -std=c++20 -O2 -g -fstrict-aliasing \
17+
-ffunction-sections -fdata-sections -Wall -Wextra \
18+
-Wstrict-aliasing=2
1719
ASFLAGS := $(ARCH) -O2 -g -x assembler-with-cpp
1820
ARFLAGS := -rcs
1921
LDFLAGS := $(ARCH) -O2 -g -Wl,--gc-sections

include/exfat.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#pragma once
2+
3+
#include <cstddef>
4+
#include "types.h"
5+
6+
// References:
7+
// exFAT: https://learn.microsoft.com/en-us/windows/win32/fileio/exfat-specification
8+
9+
10+
// Boot Sector.
11+
typedef struct
12+
{
13+
u8 jumpBoot[3]; // {0xEB, 0x76, 0x90}.
14+
char fileSystemName[8]; // "EXFAT ".
15+
u8 mustBeZero[53];
16+
u64 partitionOffset; // Arbitrary value or 0 = ignore this field.
17+
u64 volumeLength; // Minimum "2^20 / 2^BytesPerSectorShift", maximum "2^64 - 1". If excess space sub-region size = 0 then max. is "ClusterHeapOffset + (2^32 - 11) * 2^SectorsPerClusterShift".
18+
u32 fatOffset; // Minimum "24", maximum "ClusterHeapOffset - (FatLength * NumberOfFats)".
19+
u32 fatLength; // Minimum "(ClusterCount + 2) * 2^2 / 2^BytesPerSectorShift" rounded up to nearest integer, maximum "(ClusterHeapOffset - FatOffset) / NumberOfFats" rounded down to nearest integer.
20+
u32 clusterHeapOffset; // Minimum "FatOffset + FatLength * NumberOfFats", maximum "2^32 - 1" or "VolumeLength - (ClusterCount * 2^SectorsPerClusterShift)" whichever is smaller.
21+
u32 clusterCount; // Shall be the lesser of "(VolumeLength - ClusterHeapOffset) / 2^SectorsPerClusterShiftrounded down to the nearest integer" or "2^32 - 11". Recommended no more than "2^24 - 2".
22+
u32 firstClusterOfRootDirectory; // Minimum "2", maximum "ClusterCount + 1".
23+
u32 volumeSerialNumber; // Volume serial number generated from date and time.
24+
u16 fileSystemRevision; // versionHigh<<8 | (u8)versionLow. Version high 1-99, versionLow 0-99. Usually 1.00.
25+
u16 volumeFlags; // Bit 0 = activeFat, bit 1 = volumeDirty, bit 2 = mediaFailure, bit 3 = clearToZero, bits 4-15 reserved.
26+
u8 bytesPerSectorShift; // Minimum "9" (512 bytes), maximum "12" (4 KiB).
27+
u8 sectorsPerClusterShift; // Minimum "0" (1 sector), maximum "25 - BytesPerSectorShift" (32 MiB).
28+
u8 numberOfFats; // "1" or "2" (TexFAT only).
29+
u8 driveSelect; // Arbitrary value. Recommended 0x80.
30+
u8 percentInUse; // 0-100 "percentage of allocated clusters in the Cluster Heap, rounded down to the nearest integer" or 0xFF if unknown.
31+
u8 reserved[7];
32+
u8 bootCode[390]; // Bootstrapping code or 0xF4 filled (x86 halt).
33+
u16 bootSignature; // 0xAA55.
34+
//u8 excessSpace[(1u<<bytesPerSectorShift) - 512];
35+
} BootSector;
36+
static_assert(offsetof(BootSector, bootSignature) == 510, "Member bootSignature of BootSector not at offsetof 510.");
37+
38+
// Extended Boot Sector.
39+
/*typedef struct
40+
{
41+
u8 extendedBootCode[(1u<<bytesPerSectorShift) - 4];
42+
u32 extendedBootSignature; // 0xAA550000.
43+
} ExtendedBootSector;*/
Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
#pragma once
22

3-
#include <assert.h>
4-
#include <stdalign.h>
5-
#include <stddef.h>
3+
#include <cstddef>
64
#include "types.h"
75

86
// References:
97
// FAT12/16/32: http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/fatgen103.doc
10-
// exFAT: https://learn.microsoft.com/en-us/windows/win32/fileio/exfat-specification
118

129

1310
typedef struct
@@ -20,8 +17,8 @@ typedef struct
2017
u16 endSC;
2118
u32 startLba;
2219
u32 sectorsLba;
23-
} PartInfo;
24-
static_assert(offsetof(PartInfo, sectorsLba) == 12, "Error.");
20+
} __attribute__((packed)) PartInfo;
21+
static_assert(offsetof(PartInfo, sectorsLba) == 12, "Member sectorsLba of PartInfonfo not at offsetof 12.");
2522

2623
typedef struct
2724
{
@@ -31,7 +28,7 @@ typedef struct
3128
PartInfo partTable[4];
3229
u16 magic;
3330
} __attribute__((packed)) Mbr;
34-
static_assert(offsetof(Mbr, magic) == 510, "Error.");
31+
static_assert(offsetof(Mbr, magic) == 510, "Member magic of Mbr not at offsetof 510.");
3532

3633
// Volume Boot Record.
3734
typedef struct
@@ -86,9 +83,9 @@ typedef struct
8683
};
8784
u16 sigWord; // 0xAA55.
8885
} __attribute__((packed)) Vbr;
89-
static_assert(offsetof(Vbr, fat16.bootCode) == 62, "Error.");
90-
static_assert(offsetof(Vbr, fat32.bootCode) == 90, "Error.");
91-
static_assert(offsetof(Vbr, sigWord) == 510, "Error.");
86+
static_assert(offsetof(Vbr, fat16.bootCode) == 62, "Member fat16.bootCode of Vbr not at offsetof 62.");
87+
static_assert(offsetof(Vbr, fat32.bootCode) == 90, "Member fat32.bootCode of Vbr not at offsetof 90.");
88+
static_assert(offsetof(Vbr, sigWord) == 510, "Member sigWord of Vbr not at offsetof 510.");
9289

9390
typedef struct
9491
{
@@ -100,7 +97,7 @@ typedef struct
10097
u8 reserved2[12]; // Must be 0.
10198
u32 trailSig; // Must be 0xAA550000.
10299
} FsInfo;
103-
static_assert(offsetof(FsInfo, trailSig) == 508, "Error.");
100+
static_assert(offsetof(FsInfo, trailSig) == 508, "Member trailSig of FsInfo not at offsetof 508.");
104101

105102
typedef struct
106103
{
@@ -117,6 +114,4 @@ typedef struct
117114
u16 fstClusLo; // Low u16 of first data cluster.
118115
u32 fileSize; // File/directory size in bytes.
119116
} FatDir;
120-
static_assert(offsetof(FatDir, fileSize) == 28, "Error.");
121-
122-
// TODO: exFAT.
117+
static_assert(offsetof(FatDir, fileSize) == 28, "Member fileSize of FatDir not at offsetof 28.");

include/format.h

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
#pragma once
22

3-
#include <stdbool.h>
43
#include "types.h"
54

65

7-
#define FLAGS_DRY_RUN (1u)
8-
#define FLAGS_ERASE (1u<<1)
9-
#define FLAGS_SECURE_ERASE (1u<<2)
10-
#define FLAGS_FORCE_FAT32 (1u<<3)
11-
#define FLAGS_PRINT_FS (1u<<4)
12-
#define FLAGS_VERBOSE (1u<<5)
6+
union ArgFlags
7+
{
8+
struct
9+
{
10+
u8 dryRun : 1;
11+
u8 erase : 1;
12+
u8 secErase : 1;
13+
u8 forceFat32 : 1;
14+
u8 printFs : 1;
15+
u8 verbose : 1;
16+
};
17+
u8 allFlags;
18+
};
1319

1420

1521

1622
void setVerboseMode(const bool verbose);
17-
u32 formatSd(const char *const path, const char *const label, const u32 flags, const u64 overrTotSec);
23+
u32 formatSd(const char *const path, const char *const label, const ArgFlags flags, const u64 overrTotSec);

include/types.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#pragma once
22

3-
#include <stdint.h>
4-
#include <inttypes.h>
3+
#include <cstdint>
4+
#include <cinttypes>
55

66

77
typedef uint8_t u8;

source/blockdev.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ int BlockDev::open(const char *const path, const bool rw) noexcept
7676
return res;
7777
}
7878

79+
// TODO: Use pread()?
7980
int BlockDev::read(u8 *buf, const u64 sector, const u64 count) const noexcept
8081
{
8182
int res = 0;
@@ -104,6 +105,7 @@ int BlockDev::read(u8 *buf, const u64 sector, const u64 count) const noexcept
104105
return res;
105106
}
106107

108+
// TODO: Use pwrite()?
107109
int BlockDev::write(const u8 *buf, const u64 sector, const u64 count) noexcept
108110
{
109111
int res = 0;

source/exfat.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include "types.h"
2+
#include "exfat.h"
3+
4+
5+
6+
u32 calcExFatBootChecksum(const u8 *data, const u16 bytesPerSector)
7+
{
8+
u32 checksum = 0;
9+
for(u32 i = 0; i < (bytesPerSector * 11); i++)
10+
{
11+
if(i == 106 || i == 107 || i == 112) continue;
12+
13+
checksum = (checksum & 1u ? 0x80000000 : 0) + (checksum>>1) + data[i];
14+
}
15+
16+
return checksum;
17+
}

source/format.cpp

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
#include <sys/random.h> // getrandom()...
99
#include "types.h"
1010
#include "format.h"
11-
#include "fs_structs.h"
11+
#include "exfat.h"
12+
#include "fat.h"
1213
#include "blockdev.h"
1314

1415

@@ -79,9 +80,8 @@ static void calcFormatFat(const u32 totSec, FormatParams *const params)
7980
u32 tmpSecPerFat;
8081
while(1)
8182
{
82-
// TODO: We probably don't need double here.
83-
maxClus = (double)(totSec - partStart - fsAreaSize) / secPerClus /*+ 1*/; // TODO: We should probably remove the + 1.
84-
tmpSecPerFat = ceil((double)((2 + (maxClus /*- 1*/)) * fatBits) / (bytesPerSec * 8)); // TODO: We should probably remove the - 1.
83+
maxClus = (totSec - partStart - fsAreaSize) / secPerClus;
84+
tmpSecPerFat = ceil((double)((2 + maxClus) * fatBits) / (bytesPerSec * 8));
8585

8686
if(tmpSecPerFat <= secPerFat) break;
8787

@@ -129,9 +129,8 @@ static void calcFormatFat32(const u32 totSec, FormatParams *const params)
129129
u32 tmpSecPerFat;
130130
while(1)
131131
{
132-
// TODO: We probably don't need double here.
133-
maxClus = (double)(totSec - partStart - fsAreaSize) / secPerClus /*+ 1*/; // TODO: We should probably remove the + 1.
134-
tmpSecPerFat = ceil((double)((2 + (maxClus /*- 1*/)) * fatBits) / (bytesPerSec * 8)); // TODO: We should probably remove the - 1.
132+
maxClus = (totSec - partStart - fsAreaSize) / secPerClus;
133+
tmpSecPerFat = ceil((double)((2 + maxClus) * fatBits) / (bytesPerSec * 8));
135134

136135
if(tmpSecPerFat <= secPerFat) break;
137136

@@ -274,7 +273,7 @@ static u32 makeVolId(void)
274273

275274
static u32 lba2chs(u64 lba, const u32 heads, const u32 secPerTrk)
276275
{
277-
if(lba < 16450560)
276+
if(lba <= 16450560)
278277
{
279278
const u32 spc = heads * secPerTrk;
280279

@@ -320,10 +319,10 @@ static void makeMbrPartition(const FormatParams *const params, const bool bootab
320319
}
321320
else if(fatBits == 32)
322321
{
323-
if((totSec - 1) < 16450560) partType = 0x0B; // FAT32 CHS.
324-
else partType = 0x0C; // FAT32 LBA.
322+
if((totSec - 1) <= 16450560) partType = 0x0B; // FAT32 CHS.
323+
else partType = 0x0C; // FAT32 LBA.
325324
}
326-
else partType = 0x07; // exFAT.
325+
else partType = 0x07; // exFAT.
327326
mbr->partTable[0].id = partType;
328327
verbosePrintf("Partition type: 0x%02" PRIX8 "\n", partType);
329328

@@ -379,7 +378,7 @@ static void makeFsFat(const FormatParams *const params, Vbr *const vbr, const ch
379378
vbr->fat16.bootSig = 0x29;
380379
vbr->fat16.volId = makeVolId();
381380
memcpy(vbr->fat16.volLab, labelBuf, 11);
382-
memcpy(vbr->fat16.filSysType, "FAT16 ", 8);
381+
memcpy(vbr->fat16.filSysType, "FAT16 ", 8); // Bug: What about FAT12?
383382
memset(vbr->fat16.bootCode, 0xF4, sizeof(vbr->fat16.bootCode));
384383

385384
// Reserve first 2 FAT entries of both FATs.
@@ -394,7 +393,7 @@ static void makeFsFat(const FormatParams *const params, Vbr *const vbr, const ch
394393
vbr->fat32.fatSz32 = secPerFat;
395394
vbr->fat32.extFlags = 0; // TODO: Allow disabling mirroring?
396395
vbr->fat32.fsVer = 0; // 0.0.
397-
vbr->fat32.rootClus = 2; // Or the first cluster not marked as defective.
396+
vbr->fat32.rootClus = 2; // 2 or the first cluster not marked as defective.
398397
vbr->fat32.fsInfoSector = 1;
399398
vbr->fat32.bkBootSec = 6;
400399
vbr->fat32.drvNum = 0x80;
@@ -446,7 +445,7 @@ static void makeFsFat(const FormatParams *const params, Vbr *const vbr, const ch
446445
// TODO
447446
}*/
448447

449-
u32 formatSd(const char *const path, const char *const label, const u32 flags, const u64 overrTotSec)
448+
u32 formatSd(const char *const path, const char *const label, const ArgFlags flags, const u64 overrTotSec)
450449
{
451450
BlockDev dev;
452451
if(dev.open(path, true) != 0) return 2;
@@ -464,25 +463,26 @@ u32 formatSd(const char *const path, const char *const label, const u32 flags, c
464463
}
465464
verbosePrintf("SD card contains %" PRIu64 " sectors.\n", totSec);
466465

467-
if((flags & (FLAGS_ERASE | FLAGS_SECURE_ERASE)) != 0)
466+
if(flags.erase || flags.secErase)
468467
{
469468
verbosePuts("Erasing SD card...");
470469

471470
// TODO: Apparently not all cards support secure erase.
472-
const int discardRes = dev.discardAll((flags & FLAGS_SECURE_ERASE) != 0);
471+
const int discardRes = dev.discardAll(flags.secErase);
473472
if(discardRes == EOPNOTSUPP)
474473
{
475474
fputs("SD card can't be erased. Ignoring.\n", stderr);
476475
}
477476
else if(discardRes != 0) return 3;
478477
}
479478

480-
FormatParams params = {};
481-
getFormatParams(totSec, (flags & FLAGS_FORCE_FAT32) != 0, &params);
479+
FormatParams params{};
480+
getFormatParams(totSec, flags.forceFat32, &params);
482481

483482
// For FAT32 we also need to clear the root directory cluster.
484-
const size_t bufSize = 512 * (params.partStart + params.fsAreaSize + (params.fatBits == 32 ? params.secPerClus : 0));
485-
const std::unique_ptr<u8[]> buf(new(std::nothrow) u8[bufSize]);
483+
const u32 partStart = params.partStart;
484+
const size_t bufSize = 512 * (partStart + params.fsAreaSize + (params.fatBits == 32 ? params.secPerClus : 0));
485+
const std::unique_ptr<u8[]> buf(new(std::nothrow) u8[bufSize]{});
486486
if(!buf)
487487
{
488488
fputs("Not enough memory.", stderr);
@@ -498,7 +498,6 @@ u32 formatSd(const char *const path, const char *const label, const u32 flags, c
498498
// TODO: Label should be upper case and some chars are not allowed. Implement conversion + checks.
499499
// mkfs.fat allows lower case but warns about it.
500500
verbosePuts("Formatting the partition...");
501-
const u32 partStart = params.partStart;
502501
makeFsFat(&params, (Vbr*)(buf.get() + (512 * partStart)), label);
503502

504503
if(dev.write(buf.get(), 0, bufSize / 512) != 0)

source/fs_printer.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <cstdio>
2-
#include "fs_structs.h"
2+
#include "exfat.h"
3+
#include "fat.h"
34

45

56

0 commit comments

Comments
 (0)