Skip to content

Commit 2952644

Browse files
committed
Turns out the head 254 bug was not a bug in SDFormatter but how it's supposed to be.
Set the offset for the jmp instruction in the boot sector and mention this difference in the README.
1 parent f0cba8b commit 2952644

File tree

3 files changed

+21
-25
lines changed

3 files changed

+21
-25
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Unfortunately SDFormatter isn't available for Linux so i made this. It is a tool to format your SD card the way the SD Association intended but under Linux.
33

44
Multiple SD cards with different capacities have been tested and this tool formats them 1:1 the same as SDFormatter with the following exceptions:
5-
* SDFormatter sets end head in the MBR to 254 for a card with 31074304 sectors (16 GB) which is a bug i believe. sdFormatLinux uses 255.
5+
* SDFormatter does not set the jmp instruction offset in the boot sector. sdFormatLinux does.
66
* sdFormatLinux does not support exFAT right now.
77

88
## Examples

source/fat.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,13 +139,14 @@ int makeFsFat(const FormatParams &params, BufferedFsWriter &dev, const std::stri
139139

140140
// Boot sector.
141141
BootSec bs{};
142-
memcpy(bs.jmpBoot, "\xEB\x00\x90", 3); // Doesn't jump to bootCode but it's what SDFormatter uses.
142+
const u8 fatBits = params.fatBits;
143+
const u8 jmpBoot[3] = {0xEB, (u8)(fatBits < 32 ? 0x3C : 0x58), 0x90}; // Note: SDFormatter hardcodes 0xEB 0x00 0x90.
144+
memcpy(bs.jmpBoot, jmpBoot, 3);
143145
memcpy(bs.oemName, BS_DEFAULT_OEM_NAME, 8);
144146

145147
// BIOS Parameter Block (BPB).
146148
const u32 secPerClus = params.secPerClus;
147149
const u32 rsvdSecCnt = params.rsvdSecCnt;
148-
const u8 fatBits = params.fatBits;
149150
const u32 partSectors = static_cast<u32>(params.totSec - partStart);
150151
const u32 secPerFat = params.secPerFat;
151152
bs.bytesPerSec = bytesPerSec;

source/mbr.cpp

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,23 @@
1111

1212

1313
// Converts LBA to MBR CHS format.
14-
// TODO: SDFormatter uses end head 254 for a 16 GB card. Bug?
1514
static u32 lba2chs(u64 lba, const u32 heads, const u32 secPerTrk)
1615
{
17-
// We can't encode this even with 255 heads and 63 sectors per track.
18-
// Returning the maximum in this case is ok.
19-
if(lba >= 16450560)
20-
return 0x00FFFFFF; // Cylinder 1023, head 255, sector 63.
21-
2216
const u32 spc = heads * secPerTrk;
23-
const u32 c = lba / spc;
17+
u32 c = lba / spc;
2418
lba %= spc;
25-
const u32 h = lba / secPerTrk;
26-
const u32 s = lba % secPerTrk + 1;
19+
u32 h = lba / secPerTrk;
20+
u32 s = lba % secPerTrk + 1;
2721

28-
// Return the maximum if we can't encode this
29-
// and also set the uppermost byte to maximum to indicate an error.
30-
if(c > 1023 || h > 255 || s > 63)
31-
return 0xFFFFFFFF;
22+
// Return the maximum if we can't encode this.
23+
if(c >= 1024 || h >= heads || s > secPerTrk)
24+
{
25+
c = 1023;
26+
h = 254;
27+
s = 63;
28+
}
3229

33-
//printf("lba2chs(%" PRIu64 ", %" PRIu32 ", %" PRIu32 "): c: %" PRIu32 ", h: %" PRIu32 ", s: %" PRIu32 "\n",
34-
// lba, heads, secPerTrk, c, h, s);
35-
return (c & 0xFF)<<16 | (c & 0x300)<<6 | s<<8 | h;
30+
return (c & 0xFFu)<<16 | (c & 0x300u)<<6 | s<<8 | h;
3631
}
3732

3833
// TODO: Rewrite this function to use partSize to determine the fs type.
@@ -62,18 +57,18 @@ int createMbrAndPartition(const FormatParams &params, BufferedFsWriter &dev)
6257
const u64 totSec = params.totSec * (bytesPerSec>>9); // Convert back to physical sectors.
6358
const u64 partSize = totSec - partStart; // TODO: Is this correct or should we align the end?
6459
u8 type;
65-
if(fatBits == 12) type = 0x01; // FAT12 (16/32 MiB).
60+
if(fatBits == 12) type = 0x01; // FAT12 (16/32 MiB).
6661
else if(fatBits == 16)
6762
{
68-
if(partSize < 65536) type = 0x04; // FAT16 (<32 MiB). TODO: Is this actually "<" or "<="?
69-
else type = 0x06; // FAT16 (>=32 MiB).
63+
if(partSize < 65536) type = 0x04; // FAT16 (<32 MiB).
64+
else type = 0x06; // FAT16 (>=32 MiB).
7065
}
7166
else if(fatBits == 32)
7267
{
73-
if((totSec - 1) < 16450560) type = 0x0B; // FAT32 CHS.
74-
else type = 0x0C; // FAT32 LBA.
68+
if(totSec <= 16450560) type = 0x0B; // FAT32 CHS.
69+
else type = 0x0C; // FAT32 LBA.
7570
}
76-
else type = 0x07; // exFAT.
71+
else type = 0x07; // exFAT.
7772
entry.type = type;
7873
verbosePrintf("Partition type: 0x%02" PRIX8 "\n", type);
7974

0 commit comments

Comments
 (0)