ae2a274518
The definition of bpb's num_total_sectors_16 and num_total_sectors_32 is that either the 16-bit field is non-zero and is used (in which case eg mkfs.fat sets the 32-bit field to zero), or it is zero and the 32-bit field is used. Therefore, a BPB is invalid only if *both* fields are zero; having one field as zero and the other as non-zero is the case to be expected. (Indeed, according to Microsoft's specification one of the fields *must* be zero, and the other non-zero.) This affects all users of grub_chainloader_patch_bpb which are in chainloader.c, freedos.c, and ntldr.c Some descriptions of the semantics of these two fields: https://www.win.tue.nl/~aeb/linux/fs/fat/fat-1.html The old 2-byte fields "total number of sectors" and "number of sectors per FAT" are now zero; this information is now found in the new 4-byte fields. (Here given in the FAT32 EBPB section but the total sectors 16/32 bit fields semantic is true of FAT12 and FAT16 too.) https://wiki.osdev.org/FAT#BPB_.28BIOS_Parameter_Block.29 19 | 2 | The total sectors in the logical volume. If this value is 0, it means there are more than 65535 sectors in the volume, and the actual count is stored in "Large Sectors (bytes 32-35). 32 | 4 | Large amount of sector on media. This field is set if there are more than 65535 sectors in the volume. (Doesn't specify what the "large" field is set to when unused, but as mentioned mkfs.fat sets it to zero then.) https://technet.microsoft.com/en-us/library/cc976796.aspx 0x13 | WORD | 0x0000 | Small Sectors . The number of sectors on the volume represented in 16 bits (< 65,536). For volumes larger than 65,536 sectors, this field has a value of zero and the Large Sectors field is used instead. 0x20 | DWORD | 0x01F03E00 | Large Sectors . If the value of the Small Sectors field is zero, this field contains the total number of sectors in the FAT16 volume. If the value of the Small Sectors field is not zero, the value of this field is zero. https://staff.washington.edu/dittrich/misc/fatgen103.pdf page 10 BPB_TotSec16 | 19 | 2 | This field is the old 16-bit total count of sectors on the volume. This count includes the count of all sectors in all four regions of the volume. This field can be 0; if it is 0, then BPB_TotSec32 must be non-zero. For FAT32 volumes, this field must be 0. For FAT12 and FAT16 volumes, this field contains the sector count, and BPB_TotSec32 is 0 if the total sector count “fits” (is less than 0x10000). BPB_TotSec32 | 32 | 4 | This field is the new 32-bit total count of sectors on the volume. This count includes the count of all sectors in all four regions of the volume. This field can be 0; if it is 0, then BPB_TotSec16 must be non-zero. For FAT32 volumes, this field must be non-zero. For FAT12/FAT16 volumes, this field contains the sector count if BPB_TotSec16 is 0 (count is greater than or equal to 0x10000). (This specifies that an unused BPB_TotSec32 field is set to zero.) By the way fix offsets in include/grub/fat.h. Tested with lDebug booted in qemu via grub2's FreeDOS direct loading support, refer to https://bitbucket.org/ecm/ldosboot + https://bitbucket.org/ecm/ldebug Signed-off-by: C. Masloch <pushbx@38.de> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
77 lines
2.3 KiB
C
77 lines
2.3 KiB
C
/*
|
|
* GRUB -- GRand Unified Bootloader
|
|
* Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
|
|
*
|
|
* GRUB 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 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* GRUB is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef GRUB_FAT_H
|
|
#define GRUB_FAT_H 1
|
|
|
|
#include <grub/types.h>
|
|
|
|
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; /* 0x10 */
|
|
grub_uint16_t num_root_entries;
|
|
grub_uint16_t num_total_sectors_16;
|
|
grub_uint8_t media; /* 0x15 */
|
|
grub_uint16_t sectors_per_fat_16;
|
|
grub_uint16_t sectors_per_track; /* 0x18 */
|
|
grub_uint16_t num_heads; /* 0x1A */
|
|
grub_uint32_t num_hidden_sectors; /* 0x1C */
|
|
grub_uint32_t num_total_sectors_32; /* 0x20 */
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
grub_uint8_t num_ph_drive;
|
|
grub_uint8_t reserved;
|
|
grub_uint8_t boot_sig;
|
|
grub_uint32_t num_serial;
|
|
grub_uint8_t label[11];
|
|
grub_uint8_t fstype[8];
|
|
} GRUB_PACKED fat12_or_fat16;
|
|
struct
|
|
{
|
|
grub_uint32_t sectors_per_fat_32;
|
|
grub_uint16_t extended_flags;
|
|
grub_uint16_t fs_version;
|
|
grub_uint32_t root_cluster;
|
|
grub_uint16_t fs_info;
|
|
grub_uint16_t backup_boot_sector;
|
|
grub_uint8_t reserved[12];
|
|
grub_uint8_t num_ph_drive;
|
|
grub_uint8_t reserved1;
|
|
grub_uint8_t boot_sig;
|
|
grub_uint32_t num_serial;
|
|
grub_uint8_t label[11];
|
|
grub_uint8_t fstype[8];
|
|
} GRUB_PACKED fat32;
|
|
} GRUB_PACKED version_specific;
|
|
} GRUB_PACKED;
|
|
|
|
#ifdef GRUB_UTIL
|
|
#include <grub/disk.h>
|
|
|
|
grub_disk_addr_t
|
|
grub_fat_get_cluster_sector (grub_disk_t disk, grub_uint64_t *sec_per_lcn);
|
|
#endif
|
|
|
|
#endif
|