14 static constexpr
char PARTAB_HEADER[11] = {
15 '\353',
'\376',
'\220',
'M',
'S',
'X',
'_',
'I',
'D',
'E',
' '
17 [[nodiscard]]
static bool isPartitionTableSector(
const PartitionTable& pt)
19 return memcmp(pt.
header, PARTAB_HEADER,
sizeof(PARTAB_HEADER)) == 0;
26 return isPartitionTableSector(buf.
pt);
34 if (partition < 1 || partition > 31) {
36 "Invalid partition number specified (must be 1-31).");
40 if (!isPartitionTableSector(buf.
pt)) {
41 throw CommandException(
42 "No (or invalid) partition table.");
47 throw CommandException(
"No partition number ",
partition);
80 memcpy(&boot, &defaultBootBlock,
sizeof(boot));
84 byte nbReservedSectors = 1;
85 byte nbHiddenSectors = 1;
91 byte nbSectorsPerCluster;
97 if (nbSectors > 32732) {
102 nbSectorsPerFat = 12;
103 nbSectorsPerCluster = 16;
106 nbHiddenSectors = 16;
107 }
else if (nbSectors > 16388) {
111 nbSectorsPerFat = 12;
112 nbSectorsPerCluster = 8;
115 }
else if (nbSectors > 8212) {
119 nbSectorsPerFat = 12;
120 nbSectorsPerCluster = 4;
123 }
else if (nbSectors > 4126) {
127 nbSectorsPerFat = 12;
128 nbSectorsPerCluster = 2;
131 }
else if (nbSectors > 2880) {
136 nbSectorsPerCluster = 2;
139 }
else if (nbSectors > 1440) {
144 nbSectorsPerCluster = 2;
147 }
else if (nbSectors > 720) {
153 nbSectorsPerCluster = 2;
163 nbSectorsPerCluster = 2;
183 unsigned nbRootDirSectors = nbDirEntry / 16;
184 unsigned rootDirStart = 1 + nbFats * nbSectorsPerFat;
185 unsigned firstDataSector = rootDirStart + nbRootDirSectors;
186 return {firstDataSector, descriptor};
194 auto [firstDataSector, descriptor] = setBootSector(buf.
bootSector, nbSectors, dos1);
198 memset(&buf, 0,
sizeof(buf));
199 for (
auto i :
xrange(2u, firstDataSector)) {
205 buf.
raw[0] = descriptor;
211 memset(&buf, 0xE5,
sizeof(buf));
212 for (
auto i :
xrange(firstDataSector, nbSectors)) {
222 [[nodiscard]]
static constexpr
CHS logicalToCHS(
unsigned logical)
226 unsigned tmp = logical + 1;
227 unsigned sector = tmp % 32;
228 if (sector == 0) sector = 32;
229 tmp = (tmp - sector) / 32;
230 unsigned head = tmp % 16;
231 unsigned cylinder = tmp / 16;
232 return {cylinder, head, sector};
237 assert(sizes.size() <= 31);
240 memset(&buf, 0,
sizeof(buf));
241 memcpy(buf.
pt.
header, PARTAB_HEADER,
sizeof(PARTAB_HEADER));
244 unsigned partitionOffset = 1;
245 for (
auto i :
xrange(sizes.size())) {
246 unsigned partitionNbSectors = sizes[i];
247 auto& p = buf.
pt.
part[30 - i];
248 auto [startCylinder, startHead, startSector] =
249 logicalToCHS(partitionOffset);
250 auto [endCylinder, endHead, endSector] =
251 logicalToCHS(partitionOffset + partitionNbSectors - 1);
252 p.boot_ind = (i == 0) ? 0x80 : 0x00;
254 p.sector = startSector;
255 p.cyl = startCylinder;
257 p.end_head = endHead;
258 p.end_sector = endSector;
259 p.end_cyl = endCylinder;
260 p.start = partitionOffset;
262 DiskPartition diskPartition(disk, partitionOffset, partitionNbSectors);
264 partitionOffset += partitionNbSectors;
static const SectorBuffer dos2BootBlock
static const SectorBuffer dos1BootBlock
void readSector(size_t sector, SectorBuffer &buf)
size_t getNbSectors() const
void writeSector(size_t sector, const SectorBuffer &buf)
bool hasPartitionTable(SectorAccessibleDisk &disk)
Check whether the given disk is partitioned.
void format(SectorAccessibleDisk &disk, bool dos1)
Format the given disk (= a single partition).
void checkValidPartition(SectorAccessibleDisk &disk, unsigned partition)
Checks whether the disk is partitioned the specified partition exists throws a CommandException if on...
void partition(SectorAccessibleDisk &disk, const std::vector< unsigned > &sizes)
Write a partition table to the given disk and format each partition.
void checkFAT12Partition(SectorAccessibleDisk &disk, unsigned partition)
Like above, but also check whether partition is of type FAT12.
uint16_t word
16 bit unsigned integer
uint32_t random_32bit()
Return a random 32-bit value.
Endian::L16 hiddenSectors
Endian::UA_L16 dirEntries
constexpr auto xrange(T e)