bin/183234: [patch] can't boot BeagleBone Black when newfs_msdos is trimming to a multiple of sectors per track

Guy Yur guyyur at gmail.com
Wed Oct 23 10:20:00 UTC 2013


>Number:         183234
>Category:       bin
>Synopsis:       [patch] can't boot BeagleBone Black when newfs_msdos is trimming to a multiple of sectors per track
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Oct 23 10:20:00 UTC 2013
>Closed-Date:
>Last-Modified:
>Originator:     Guy Yur
>Release:        FreeBSD 11.0-CURRENT arm
>Organization:
>Environment:
System: FreeBSD bbb.localdomain 11.0-CURRENT FreeBSD 11.0-CURRENT #1 r256722M: Fri Oct 18 17:40:09 IDT 2013     root at vm9.localdomain:/usr/obj/arm.armv6/usr/src/sys/BBB  arm


>Description:
I am booting the BeagleBone Black from a 4 GB microSD card with a
31 MB FAT16 slice aligned on 1 MB and a FreeBSD slice.
The BeagleBone Black firmware ignores the FAT16 filesystem and
doesn't even try to load the MLO file ('CCCC' on ttyU0).
If the FAT16 bpbSectors field is adjusted to be the full sector count
of the slice the boot succeeds.


# gpart show
=>     63  7744449  mmcsd0  MBR  (3.7G)
       63     1985          - free -  (993K)
     2048    63488       1  !4  [active]  (31M)
    65536  7677952       2  freebsd  (3.7G)
  7743488     1024          - free -  (512K)

=>      0  7677952  mmcsd0s2  BSD  (3.7G)
        0  7677952         1  freebsd-ufs  (3.7G)

=>      0  7677952  ufsid/52617ff06c9a983b  BSD  (3.7G)
        0  7677952                       1  freebsd-ufs  (3.7G)


# newfs_msdos -F 16 -c 8 -r 2 -o 2048 -m 0xF8 -L BOOT /dev/md0s1
newfs_msdos: trim 47 sectors to adjust to a multiple of 63
/dev/md0s1: 63344 sectors in 7918 FAT16 clusters (4096 bytes/cluster)
BytesPerSec=512 SecPerClust=8 ResSectors=2 FATs=2 RootDirEnts=512 Sectors=63441 Media=0xf8 FATsecs=31 SecPerTrack=63 Heads=255 HiddenSecs=2048


Didn't work with "newfs_msdos -F 16 -c 8 -L BOOT /dev/md0s1" either.
I added -r, -o and -m based on Windows format which booted succesfully.
The boot only succeeded after changing bpbSectors from 63441 to 63488
in the FAT16 Boot Record.


>How-To-Repeat:
Create a FAT16 slices and a FreeBSD slice on a microSD card.
The FAT16 slice should be aligned on 1 MB and have a size that is
not divisible by the sectors per track of the media.
Use newfs_msdos to create the filesystem.
Try to boot the BeagleBone Black from the microSD card.


>Fix:
You can specify -h, -u, -S, -s and -o flags to bypass the delta check
in newfs_msdos.

1a. NetBSD removed the check in newfs_msdos.c cvs rev 1.40
    http://cvsweb.netbsd.org/bsdweb.cgi/src/sbin/newfs_msdos/newfs_msdos.c.diff?r1=1.39&r2=1.40
    Attached patch (remove_delta.patch)

1b. If the trimming is still needed for older BIOSes,
    maybe an option can be added to skip the delta check.
    Attached patch (add_opt_G.patch) that adds a "-G" option.

2. I noticed the code only converts from bpbHugeSectors to bpbSectors if
   the sum of the hidden and huge sectors is less than or equal MAXU16.
   When formatting in Windows bpbSectors is still used for 63488 sectors
   and 2048 hidden (sum > MAXU16).
   The hidden sectors count is the number of sectors before the
   FAT16 Boot Record so it shouldn't affect the sector count.
   Attached patch (huge_sec_conversion.patch) to only check for
   bpb.bpbHugeSectors <= MAXU16 when converting to bpbSectors.


--- remove_delta.patch begins here ---
Index: sbin/newfs_msdos/newfs_msdos.c
===================================================================
--- sbin/newfs_msdos/newfs_msdos.c	(revision 256722)
+++ sbin/newfs_msdos/newfs_msdos.c	(working copy)
@@ -402,15 +402,8 @@
     if (oflag)
 	bpb.bpbHiddenSecs = opt_o;
     if (!(opt_f || (opt_h && opt_u && opt_S && opt_s && oflag))) {
-	off_t delta;
 	getdiskinfo(fd, fname, dtype, oflag, &bpb);
 	bpb.bpbHugeSectors -= (opt_ofs / bpb.bpbBytesPerSec);
-	delta = bpb.bpbHugeSectors % bpb.bpbSecPerTrack;
-	if (delta != 0) {
-	    warnx("trim %d sectors to adjust to a multiple of %d",
-		(int)delta, bpb.bpbSecPerTrack);
-	    bpb.bpbHugeSectors -= delta;
-	}
 	if (bpb.bpbSecPerClust == 0) {	/* set defaults */
 	    if (bpb.bpbHugeSectors <= 6000)	/* about 3MB -> 512 bytes */
 		bpb.bpbSecPerClust = 1;
--- remove_delta.patch ends here ---

--- add_opt_G.patch begins here ---
Index: sbin/newfs_msdos/newfs_msdos.8
===================================================================
--- sbin/newfs_msdos/newfs_msdos.8	(revision 256722)
+++ sbin/newfs_msdos/newfs_msdos.8	(working copy)
@@ -38,6 +38,7 @@
 .Op Fl B Ar boot
 .Op Fl C Ar create-size
 .Op Fl F Ar FAT-type
+.Op Fl G
 .Op Fl I Ar VolumeId
 .Op Fl L Ar label
 .Op Fl O Ar OEM
@@ -103,6 +104,8 @@
 smaller than the size specified as parameter.
 .It Fl F Ar FAT-type
 FAT type (one of 12, 16, or 32).
+.It Fl G
+Ignore geometry in sector count calculation.
 .It Fl I Ar VolumeID
 Volume ID, a 32 bit number in decimal or hexadecimal (0x...) format.
 .It Fl L Ar label
Index: sbin/newfs_msdos/newfs_msdos.c
===================================================================
--- sbin/newfs_msdos/newfs_msdos.c	(revision 256722)
+++ sbin/newfs_msdos/newfs_msdos.c	(working copy)
@@ -236,11 +236,11 @@
 int
 main(int argc, char *argv[])
 {
-    static const char opts[] = "@:NB:C:F:I:L:O:S:a:b:c:e:f:h:i:k:m:n:o:r:s:u:";
+    static const char opts[] = "@:NB:C:F:GI:L:O:S:a:b:c:e:f:h:i:k:m:n:o:r:s:u:";
     const char *opt_B = NULL, *opt_L = NULL, *opt_O = NULL, *opt_f = NULL;
-    u_int opt_F = 0, opt_I = 0, opt_S = 0, opt_a = 0, opt_b = 0, opt_c = 0;
-    u_int opt_e = 0, opt_h = 0, opt_i = 0, opt_k = 0, opt_m = 0, opt_n = 0;
-    u_int opt_o = 0, opt_r = 0, opt_s = 0, opt_u = 0;
+    u_int opt_F = 0, opt_G = 0, opt_I = 0, opt_S = 0, opt_a = 0, opt_b = 0;
+    u_int opt_c = 0, opt_e = 0, opt_h = 0, opt_i = 0, opt_k = 0, opt_m = 0;
+    u_int opt_n = 0, opt_o = 0, opt_r = 0, opt_s = 0, opt_u = 0;
     int opt_N = 0;
     int Iflag = 0, mflag = 0, oflag = 0;
     char buf[MAXPATHLEN];
@@ -283,6 +283,9 @@
 		errx(1, "%s: bad FAT type", optarg);
 	    opt_F = atoi(optarg);
 	    break;
+	case 'G':
+	    opt_G = 1;
+	    break;
 	case 'I':
 	    opt_I = argto4(optarg, 0, "volume ID");
 	    Iflag = 1;
@@ -406,7 +409,7 @@
 	getdiskinfo(fd, fname, dtype, oflag, &bpb);
 	bpb.bpbHugeSectors -= (opt_ofs / bpb.bpbBytesPerSec);
 	delta = bpb.bpbHugeSectors % bpb.bpbSecPerTrack;
-	if (delta != 0) {
+	if (delta != 0 && !opt_G) {
 	    warnx("trim %d sectors to adjust to a multiple of %d",
 		(int)delta, bpb.bpbSecPerTrack);
 	    bpb.bpbHugeSectors -= delta;
@@ -1033,6 +1036,7 @@
 	    "\t-B get bootstrap from file\n"
 	    "\t-C create image file with specified size\n"
 	    "\t-F FAT type (12, 16, or 32)\n"
+	    "\t-G ignore geometry in sector count calculation\n"
 	    "\t-I volume ID\n"
 	    "\t-L volume label\n"
 	    "\t-N don't create file system: just print out parameters\n"
--- add_opt_G.patch ends here ---

--- huge_sec_conversion.patch begins here ---
Index: sbin/newfs_msdos/newfs_msdos.c
===================================================================
--- sbin/newfs_msdos/newfs_msdos.c	(revision 256722)
+++ sbin/newfs_msdos/newfs_msdos.c	(working copy)
@@ -603,7 +603,7 @@
 	bpb.bpbMedia = !bpb.bpbHiddenSecs ? 0xf0 : 0xf8;
     if (fat == 32)
 	bpb.bpbRootClust = RESFTE;
-    if (bpb.bpbHiddenSecs + bpb.bpbHugeSectors <= MAXU16) {
+    if (bpb.bpbHugeSectors <= MAXU16) {
 	bpb.bpbSectors = bpb.bpbHugeSectors;
 	bpb.bpbHugeSectors = 0;
     }
--- huge_sec_conversion.patch ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list