bin/127764: Patch to preserve NT disk UID data for boot0cfg

Daniel J. O'Connor darius at midget.dons.net.au
Wed Oct 1 06:30:02 UTC 2008


>Number:         127764
>Category:       bin
>Synopsis:       Patch to preserve NT disk UID data for boot0cfg
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Oct 01 06:30:01 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator:     Daniel J. O'Connor
>Release:        FreeBSD 8.0-CURRENT i386
>Organization:
>Environment:
-current as of 1/Oct/08.

>Description:
boot0/boot0cfg currently overwrite the NT UID in the MBR which causes MS
Windows Vista to fail to boot (unless you follow instructions here
http://www.clearchain.com/wiki/FreeBSD_&_Windows_Vista), it can also confuse
MS Windows XP.

Eugene Grosbein wrote patches and posted them here..
http://groups.google.ru/group/fido7.ru.unix.bsd/browse_thread/thread/dbb7ee5ebc159f73/8dab84b83e46ab84?hl=ru&fwc=2
I'd like them committed as they do work and I expect more people to dual boot
Vista these days..

>How-To-Repeat:
>Fix:

Index: lib/libdisk/write_i386_disk.c
===================================================================
RCS file: /usr/CVS-Repository/src/lib/libdisk/write_i386_disk.c,v
retrieving revision 1.9
diff -u -r1.9 write_i386_disk.c
--- lib/libdisk/write_i386_disk.c	4 Jun 2004 11:49:11 -0000	1.9
+++ lib/libdisk/write_i386_disk.c	25 Jul 2007 02:04:25 -0000
@@ -75,9 +75,9 @@
 
 	if (mbrblk[0x1b0] == 0x66 && mbrblk[0x1b1] == 0xbb) {
 		if (edd)
-			mbrblk[0x1bb] |= 0x80;	/* Packet mode on */
+			mbrblk[0x1af] |= 0x80;	/* Packet mode on */
 		else
-			mbrblk[0x1bb] &= 0x7f;	/* Packet mode off */
+			mbrblk[0x1af] &= 0x7f;	/* Packet mode off */
 	}
 }
 
@@ -94,6 +94,11 @@
 	int s[4];
 	int need_edd = 0;	/* Need EDD (packet interface) */
 
+#ifndef OFF_NTSERNUM
+#define OFF_NTSERNUM 0x1b8
+#endif
+	unsigned char ntsernum[4];
+
 	strcpy(device, _PATH_DEV);
         strcat(device, d1->name);
 
@@ -108,6 +113,7 @@
 	}
 	dp = (struct dos_partition *)(mbrblk + DOSPARTOFF);
 	memcpy(work, dp, sizeof work);
+	memcpy(ntsernum, mbrblk + OFF_NTSERNUM, sizeof(ntsernum));
 	dp = work;
 	free(mbrblk);
 	for (c1 = d1->chunks->part; c1; c1 = c1->next) {
@@ -188,6 +194,7 @@
 	}
 	if (d1->bootmgr) {
 		memcpy(mbrblk, d1->bootmgr, DOSPARTOFF);
+		memcpy(mbrblk + OFF_NTSERNUM, ntsernum, sizeof(ntsernum));
 		Cfg_Boot_Mgr(mbrblk, need_edd);
         }
 	memcpy(mbrblk + DOSPARTOFF, dp, sizeof *dp * NDOSPART);
Index: usr.sbin/boot0cfg/boot0cfg.c
===================================================================
RCS file: /usr/CVS-Repository/src/usr.sbin/boot0cfg/boot0cfg.c,v
retrieving revision 1.20
diff -u -r1.20 boot0cfg.c
--- usr.sbin/boot0cfg/boot0cfg.c	15 Jul 2005 08:04:32 -0000	1.20
+++ usr.sbin/boot0cfg/boot0cfg.c	25 Jul 2007 02:08:04 -0000
@@ -44,10 +44,11 @@
 
 #define MBRSIZE         512     /* master boot record size */
 
+#define OFF_OPT		0x1ad	/* offset: default boot option */
+#define OFF_DRIVE	0x1ae	/* offset: setdrv drive */
+#define OFF_FLAGS       0x1af   /* offset: option flags */
 #define OFF_VERSION	0x1b0	/* offset: version number */
-#define OFF_OPT		0x1b9	/* offset: default boot option */
-#define OFF_DRIVE	0x1ba	/* offset: setdrv drive */
-#define OFF_FLAGS       0x1bb   /* offset: option flags */
+#define OFF_NTSERNUM	0x1b8	/* offset: NT Drive Serial Number */
 #define OFF_TICKS       0x1bc   /* offset: clock ticks */
 #define OFF_PTBL        0x1be   /* offset: partition table */
 #define OFF_MAGIC       0x1fe   /* offset: magic number */
@@ -154,15 +155,17 @@
 	write_mbr(fpath, O_CREAT | O_TRUNC, mbr, mbr_size);
 
     /*
-     * If we are installing the boot loader, read it from disk and copy the
-     * slice table over from the existing MBR.  If not, then point boot0
-     * back at the MBR we just read in.  After this, boot0 is the data to
-     * write back to disk if we are going to do a write.
+     * If we are installing the boot loader, read it from disk and
+     * copy the slice table and NT Drive Serial Number over from the
+     * existing MBR.  If not, then point boot0 back at the MBR we just
+     * read in.  After this, boot0 is the data to write back to disk
+     * if we are going to do a write.
      */
     if (B_flag) {
 	boot0_size = read_mbr(bpath, &boot0, 1);
         memcpy(boot0 + OFF_PTBL, mbr + OFF_PTBL,
 	    sizeof(struct dos_partition) * NDOSPART);
+        memcpy(boot0 + OFF_NTSERNUM, mbr + OFF_NTSERNUM, 4);
     } else {
 	boot0 = mbr;
 	boot0_size = mbr_size;
@@ -374,6 +377,7 @@
     static u_int8_t id0[] = {0xfc, 0x31, 0xc0, 0x8e, 0xc0, 0x8e, 0xd8,
 			     0x8e, 0xd0, 0xbc, 0x00, 0x7c };
     static u_int8_t id1[] = {'D', 'r', 'i', 'v', 'e', ' '};
+    static u_int8_t id1_alt[] = {'D', 'i', 's', 'k', ' '};
     static struct {
 	unsigned off;
 	unsigned len;
@@ -381,11 +385,16 @@
     } ident[2] = {
         {0x0,   sizeof(id0), id0},
         {0x1b2, sizeof(id1), id1}
+    }, ident_alt[2] = {
+        {0x0,   sizeof(id0), id0},
+        {0x1b2, sizeof(id1_alt), id1_alt}
     };
+
     unsigned int i;
 
     for (i = 0; i < sizeof(ident) / sizeof(ident[0]); i++)
-        if (memcmp(bs + ident[i].off, ident[i].key, ident[i].len))
+        if (memcmp(bs + ident[i].off, ident[i].key, ident[i].len) &&
+	    memcmp(bs + ident_alt[i].off, ident_alt[i].key, ident_alt[i].len)) 
 	    return 0;
     return 1;
 }
Index: sys/boot/i386/boot0/boot0.S
===================================================================
RCS file: /usr/CVS-Repository/src/sys/boot/i386/boot0/boot0.S,v
retrieving revision 1.16
diff -u -r1.16 boot0.S
--- sys/boot/i386/boot0/boot0.S	26 Mar 2007 21:56:13 -0000	1.16
+++ sys/boot/i386/boot0/boot0.S	25 Jul 2007 01:58:13 -0000
@@ -45,10 +45,10 @@
  * Addresses in the sector of embedded data values.
  * Accessed with negative offsets from the end of the relocated sector (%ebp).
  */
-		.set _NXTDRV,-0x48		# Next drive
-		.set _OPT,-0x47 		# Default option
-		.set _SETDRV,-0x46		# Drive to force
-		.set _FLAGS,-0x45		# Flags
+		.set _NXTDRV,-0x49		# Next drive
+		.set _OPT,-0x53 		# Default option
+		.set _SETDRV,-0x52		# Drive to force
+		.set _FLAGS,-0x51		# Flags
 		.set _TICKS,-0x44		# Timeout ticks
 		.set _FAKE,0x0			# Fake partition entry
 		.set _MNUOPT,0xc		# Menu options
@@ -427,7 +427,7 @@
 		.byte os_dos-.			# Windows
 		.byte os_dos-.			# Windows
 		.byte os_linux-.		# Linux
-		.byte os_freebsd-.		# FreeBSD
+		.byte os_bsd-.			# FreeBSD
 		.byte os_bsd-.			# OpenBSD
 		.byte os_bsd-.			# NetBSD
 		.byte os_misc-. 		# Unknown
@@ -438,9 +438,13 @@
 os_misc:	.ascii "?";    .byte '?'|0x80
 os_dos:		.ascii "DO";   .byte 'S'|0x80
 os_linux:	.ascii "Linu"; .byte 'x'|0x80
-os_freebsd:	.ascii "Free"
 os_bsd:		.ascii "BS";   .byte 'D'|0x80
 
+		.byte 0x90			# free space
+opt:		.byte 0x0			# Option
+setdrv:		.byte 0x80			# Drive to force
+flags:		.byte FLAGS			# Flags
+
 		.org PRT_OFF-0xe,0x90
 
 		.word B0MAGIC			# Magic number
@@ -450,11 +454,9 @@
  * Be especially careful that nxtdrv: must come after drive:, as it
  * is part of the same string.
  */
-drive:		.ascii "Drive "
+drive:		.ascii "Disk "
 nxtdrv:		.byte 0x0			# Next drive number
-opt:		.byte 0x0			# Option
-setdrv:		.byte 0x80			# Drive to force
-flags:		.byte FLAGS			# Flags
+		.byte 0xa8,0xa8,0xa8,0xa8	# NT Drive Serial Number
 ticks:		.word TICKS			# Delay
 
 /*

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


More information about the freebsd-bugs mailing list