grub4dos
grub4dos copied to clipboard
Query about partnew and exFAT
See https://github.com/a1ive/grub2-filemanager/issues/145 Does grub4dos add Partition Offset? Does it corrupt 0x1c-0x1f in VBR? Does it recalculate checksum in Sector 11 of VBR? Partition Offset at 0x40-0x47 in VBR and Sector 11 checksum should be updated.
exfat image file:


Bytes 0x1c-0x1f are overwritten (illegal) Bytes 0x40-0x47 not updated with new Partition offset (presumably checksum not updated in sector 11???)
Image file - sector 11
After partnew

Checksum sector not updated.
FAT32 BPB: struct grub_fat_bpb { grub_uint8_t jmp_boot[3]; grub_uint8_t oem_name[8]; grub_uint16_t bytes_per_sector; grub_uint8_t sectors_per_cluster; grub_uint16_t num_reserved_sectors; grub_uint8_t num_fats; grub_uint16_t num_root_entries; grub_uint16_t num_total_sectors_16; grub_uint8_t media; grub_uint16_t sectors_per_fat_16; grub_uint16_t sectors_per_track; grub_uint16_t num_heads; grub_uint32_t num_hidden_sectors; /* 0x1C */ grub_uint32_t num_total_sectors_32; ...
exFAT BPB: struct grub_exfat_bpb { grub_uint8_t jmp_boot[3]; grub_uint8_t oem_name[8]; grub_uint8_t mbz[53]; grub_uint64_t num_hidden_sectors; grub_uint64_t num_total_sectors; grub_uint32_t num_reserved_sectors; grub_uint32_t sectors_per_fat; grub_uint32_t cluster_offset; grub_uint32_t cluster_count; grub_uint32_t root_cluster; grub_uint32_t num_serial; grub_uint16_t fs_revision; grub_uint16_t volume_flags; grub_uint8_t bytes_per_sector_shift; grub_uint8_t sectors_per_cluster_shift; grub_uint8_t num_fats; grub_uint8_t num_ph_drive; grub_uint8_t reserved[8]; } GRUB_PACKED;
offset 好像是不一样的。
New partition is not recognised by Windows.
I made (hd0,0) type 0 so only (hd0,1) is present.
Partition 1 SIZE=3826.988MiB Type: 00 *ACTIVE*
START POS = CYL:0 HD:32 SEC:33 END POS = CYL:487 HD:254 SEC:63
START (LBA) = 2,048 (00000800) SIZE (LBA) = 7,837,672 (007797E8) [End=7,839,719]
Partition 2 SIZE=297.081MiB Type: 07 NTFS\exFAT
START POS = CYL:2 HD:55 SEC:48 END POS = CYL:77 HD:113 SEC:15
START (LBA) = 19,640 (00004CB8) SIZE (LBA) = 608,422 (000948A6) [End=628,061]
https://github.com/a1ive/grub/blob/0debea8e30bfc4e496fc6aab8dc9ed359f745daa/grub-core/lib/fatfs/ff.c#L6094
/* Create two set of the exFAT VBR blocks */
sect = b_vol;
for (n = 0; n < 2; n++) {
/* Main record (+0) */
mem_set(buf, 0, ss);
mem_cpy(buf + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11); /* Boot jump code (x86), OEM name */
st_qword(buf + BPB_VolOfsEx, b_vol); /* Volume offset in the physical drive [sector] */
st_qword(buf + BPB_TotSecEx, sz_vol); /* Volume size [sector] */
st_dword(buf + BPB_FatOfsEx, (DWORD)(b_fat - b_vol)); /* FAT offset [sector] */
st_dword(buf + BPB_FatSzEx, sz_fat); /* FAT size [sector] */
st_dword(buf + BPB_DataOfsEx, (DWORD)(b_data - b_vol)); /* Data offset [sector] */
st_dword(buf + BPB_NumClusEx, n_clst); /* Number of clusters */
st_dword(buf + BPB_RootClusEx, 2 + tbl[0] + tbl[1]); /* Root dir cluster # */
st_dword(buf + BPB_VolIDEx, GET_FATTIME()); /* VSN */
st_word(buf + BPB_FSVerEx, 0x100); /* Filesystem version (1.00) */
for (buf[BPB_BytsPerSecEx] = 0, i = ss; i >>= 1; buf[BPB_BytsPerSecEx]++) ; /* Log2 of sector size [byte] */
for (buf[BPB_SecPerClusEx] = 0, i = sz_au; i >>= 1; buf[BPB_SecPerClusEx]++) ; /* Log2 of cluster size [sector] */
buf[BPB_NumFATsEx] = 1; /* Number of FATs */
buf[BPB_DrvNumEx] = 0x80; /* Drive number (for int13) */
st_word(buf + BS_BootCodeEx, 0xFEEB); /* Boot code (x86) */
st_word(buf + BS_55AA, 0xAA55); /* Signature (placed here regardless of sector size) */
for (i = sum = 0; i < ss; i++) { /* VBR checksum */
if (i != BPB_VolFlagEx && i != BPB_VolFlagEx + 1 && i != BPB_PercInUseEx) sum = xsum32(buf[i], sum);
}
if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
/* Extended bootstrap record (+1..+8) */
mem_set(buf, 0, ss);
st_word(buf + ss - 2, 0xAA55); /* Signature (placed at end of sector) */
for (j = 1; j < 9; j++) {
for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */
if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
}
/* OEM/Reserved record (+9..+10) */
mem_set(buf, 0, ss);
for ( ; j < 11; j++) {
for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */
if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
}
/* Sum record (+11) */
for (i = 0; i < ss; i += 4) st_dword(buf + i, sum); /* Fill with checksum value */
if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
}
static DWORD xsum32 ( /* Returns 32-bit checksum */
BYTE dat, /* Byte to be calculated (byte-by-byte processing) */
DWORD sum /* Previous sum value */
)
{
sum = ((sum & 1) ? 0x80000000 : 0) + (sum >> 1) + dat;
return sum;
}
EXFAT300A.zip Here is partition image of exFAT 300MB that can be used to test with partnew re. exFAT xsum - locations at 106 107 112 should not be checksummed because they are changed by filesystem.
UINT32 VBRChecksum(const unsigned char octets[], long NumberOfBytes)
{
UINT32 Checksum = 0;
long Index;
for (Index = 0; Index < NumberOfBytes; Index++)
{
if (Index == 106 || Index == 107 || Index == 112)
{
continue;
}
Checksum = ((Checksum <<31) | (Checksum>> 1)) + (UINT32) octets[Index];
}
return Checksum;
Figure 19 Code snippet
If VBR bytes 0x1c-0x1f >> 00 after partnew - then Windows can read exFAT partition

- CANNOT ACCESS
- now repair bytes

If change 0x40 then get Bad volume

The partnew function is not applicable to the exFAT file system . In other words, partnew failed to consider the exFAT file system. After all, the exFAT file system is post - developed .
OK - simplest fix is to remove the hidden sectors update to VBR for exFAT. Then, at least, the exFAT partition will be accessible to Windows (but not bootable).