Package: dosfstools Version: 3.0.6-1ubuntu1~ppa2 Severity: normal Tags: patch
After reformatting a usb-stick syslinux is now failing with an error message of "Boot error" whereas it had been booting ok. This message means that the syslinux ldlinux.sys program is not loading properly--the first sector, which resides in the boot sector is loading but is not finding the rest of the ldlinux program where it expects it. See Ubuntu LP #398241. I narrowed the problem down to the drop of 14-bootcode.dpatch. My BIOS only recognizes a FAT hard disk file system if the drive number is 0x80 and hidden sectors is non-zero. The patch was applied per Debian bug report #303442 and was removed due to #489292. According to the bug reporter for the latter bug the problem was in the setting of the hidden sectors field in the DOS superblock (first sector). The first fix set this so that the boot load program would think that it was located in the first sector of the second track--a common case but certainly not a universal one. This change broke booting from floppies. The drive number should match the contents of DL for the INT 13 BIOS call. The hidden sectors is used by some boot sector programs to find where it is located on the drive, and therefore at what sectors the rest of the contents of the file system can be found. (With hard disks the combination of the MBR and a boot sector program can use the partition table for the bootable partition rather than the hidden sectors field, making the file system relocatable). I suggest that the fix be restored but that the hidden sectors field be so set only in the hard disk code section--and that it should be set from the start field from the hard disk geometry ioctl result. It is my understanding that this is what this field is for. The hidden sectors field should remain zero for floppies, floppy images, and for any file systems starting at the first sector of the device. The FAT superblock settings I propose match what I observed in these fields in dumping a partition formatted by a reference operating system. I have coded a patch for the above, adding printing of these fields when in verbose mode, and adding options to override the drive number and FAT media byte. The patch does not include the original function to insert bootcode. >From the patch I have built a new version in my launchpad ppa (http://ppa.launchpad.net/~jsjgruber/ppa/ubuntu karmic main) In testing my version I found that test code included in Debian #489292 works. -- System Information: Debian Release: squeeze/sid APT prefers karmic-updates APT policy: (500, 'karmic-updates'), (500, 'karmic-security'), (500, 'karmic') Architecture: i386 (i686) Kernel: Linux 2.6.31-14-generic (SMP w/2 CPU cores) Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Versions of packages dosfstools depends on: ii libc6 2.10.1-0ubuntu15 GNU C Library: Shared libraries dosfstools recommends no packages. dosfstools suggests no packages. -- no debconf information
diff --git a/debian/changelog b/debian/changelog index d4c0675..44b2460 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +dosfstools (3.0.6-1ubuntu1~ppa2) karmic; urgency=low + + * Unless overridden by the user sets the DOS boot sector's + hidden-sectors field to match the start of a hard disk's + partition. + * Initialize DOS boot sector device_number according to device media type + Addresses LP: #398241 + * Adds options to override the DOS boot sector device_number and + the FAT media type. + + -- John S Gruber <[email protected]> Sun, 18 Oct 2009 21:10:45 -0400 + dosfstools (3.0.6-1) unstable; urgency=low * Updating maintainer field. diff --git a/man/mkdosfs.8 b/man/mkdosfs.8 index bb87ce6..8c0f138 100644 --- a/man/mkdosfs.8 +++ b/man/mkdosfs.8 @@ -64,6 +64,14 @@ .I logical-sector-size ] [ +.B \-D +.I drive-number +] +[ +.B \-M +.I FAT-media-type +] +[ .B \-v ] .I device @@ -118,6 +126,11 @@ be stored on the disk, but the file nevertheless will have the correct size. The resulting file can be copied later to a floppy disk or other device, or mounted through a loop device. .TP +.BI \-D " drive-number" +Specify the BIOS drive number to be stored in the FAT boot sector. +This value is usually 0x80 for hard disks and 0x00 for floppy devices +or partitions to be used for floppy emulation. +.TP .BI \-f " number-of-FATs" Specify the number of file allocation tables in the file system. The default is 2. Currently the Linux MS-DOS file system does not support @@ -164,6 +177,11 @@ file must not exceed 418 bytes once line feeds have been converted to carriage return-line feed combinations, and tabs have been expanded. If the filename is a hyphen (-), the text is taken from standard input. .TP +.BI \-M " FAT-media-type" +Specify the BIOS drive number to be stored in the FAT boot sector. +This value is usually 0xF8 for hard disks and has a value from 0xF9 +to 0xFF for floppies or partitions to be used for floppy emulation. +.TP .BI \-n " volume-name" Sets the volume name (label) of the file system. The volume name can be up to 11 characters long. The default is no label. diff --git a/src/mkdosfs.c b/src/mkdosfs.c index 89c5600..7c6773b 100644 --- a/src/mkdosfs.c +++ b/src/mkdosfs.c @@ -310,6 +310,10 @@ static int sectors_per_cluster = 0; /* Number of sectors per disk cluster */ static int root_dir_entries = 0; /* Number of root directory entries */ static char *blank_sector; /* Blank sector - all zeros */ static int hidden_sectors = 0; /* Number of hidden sectors */ +static int hidden_sectors_by_user = 0; /* -h option invoked */ +static int drive_number_option = 0; /* drive number */ +static int drive_number_by_user = 0; /* drive number option invoked */ +static int fat_media_byte = 0; /* media byte in header and starting FAT */ static int malloc_entire_fat = FALSE; /* Whether we should malloc() the entire FAT or not */ /* Function prototype definitions */ @@ -753,6 +757,8 @@ establish_params (int device_num,int size) else { bs.secs_track = CT_LE_W(geometry.sectors); /* Set up the geometry information */ bs.heads = CT_LE_W(geometry.heads); + if (!hidden_sectors_by_user) + hidden_sectors = CT_LE_L(geometry.start); } def_hd_params: bs.media = (char) 0xf8; /* Set up the media descriptor for a hard drive */ @@ -805,6 +811,18 @@ setup_tables (void) strcpy (bs.system_id, "mkdosfs"); if (sectors_per_cluster) bs.cluster_size = (char) sectors_per_cluster; + + if (fat_media_byte) + bs.media = (char) fat_media_byte; + + if (bs.media == 0xf8) + vi->drive_number=0x80; + else + vi->drive_number=0x00; + + if (drive_number_by_user) + vi->drive_number= (char) drive_number_option; + if (size_fat == 32) { /* Under FAT32, the root dir is in a cluster chain, and this is @@ -1198,9 +1216,11 @@ setup_tables (void) printf("%s has %d head%s and %d sector%s per track,\n", device_name, CF_LE_W(bs.heads), (CF_LE_W(bs.heads) != 1) ? "s" : "", CF_LE_W(bs.secs_track), (CF_LE_W(bs.secs_track) != 1) ? "s" : ""); + printf("hidden sectors 0x%04x;\n", hidden_sectors); printf("logical sector size is %d,\n",sector_size); printf("using 0x%02x media descriptor, with %d sectors;\n", (int) (bs.media), num_sectors); + printf("drive number 0x%02x;\n", (int) (vi->drive_number)); printf("file system has %d %d-bit FAT%s and %d sector%s per cluster.\n", (int) (bs.fats), size_fat, (bs.fats != 1) ? "s" : "", (int) (bs.cluster_size), (bs.cluster_size != 1) ? "s" : ""); @@ -1386,6 +1406,7 @@ Usage: mkdosfs [-A] [-c] [-C] [-v] [-I] [-l bad-block-file] [-b backup-boot-sect [-m boot-msg-file] [-n volume-name] [-i volume-id]\n\ [-s sectors-per-cluster] [-S logical-sector-size] [-f number-of-FATs]\n\ [-h hidden-sectors] [-F fat-size] [-r root-dir-entries] [-R reserved-sectors]\n\ + [-M FAT-media-byte] [-D drive_number]\n\ /dev/name [blocks]\n"); } @@ -1448,7 +1469,7 @@ main (int argc, char **argv) printf ("%s " VERSION " (" VERSION_DATE ")\n", program_name); - while ((c = getopt (argc, argv, "Ab:cCf:F:Ii:l:m:n:r:R:s:S:h:v")) != EOF) + while ((c = getopt (argc, argv, "Ab:cCf:F:Ii:l:m:n:r:R:s:S:h:M:D:v")) != EOF) /* Scan the command line for options */ switch (c) { @@ -1473,6 +1494,16 @@ main (int argc, char **argv) case 'C': /* C : Create a new file */ create = TRUE; break; + + case 'D': /* D : Choose Drive Number */ + drive_number_option = (int) strtol (optarg, &tmp, 0); + if (*tmp || (drive_number_option != 0 && drive_number_option != 0x80)) + { + printf ("Drive number must be 0 or 0x80: %s\n", optarg); + usage (); + } + drive_number_by_user=1; + break; case 'f': /* f : Choose number of FATs */ nr_fats = (int) strtol (optarg, &tmp, 0); @@ -1500,6 +1531,7 @@ main (int argc, char **argv) printf("Bad number of hidden sectors : %s\n", optarg); usage (); } + hidden_sectors_by_user = 1; break; case 'I': @@ -1587,6 +1619,15 @@ main (int argc, char **argv) } break; + case 'M': /* M : FAT Media byte */ + fat_media_byte = (int) strtol (optarg, &tmp, 0); + if (*tmp || fat_media_byte < 248 || fat_media_byte > 255) + { + printf ("FAT Media byte must be between 0xF8 and 0xFF : %s\n", optarg); + usage (); + } + break; + case 'n': /* n : Volume name */ sprintf(volume_name, "%-11.11s", optarg); break;

