Module Name:    src
Committed By:   jakllsch
Date:           Thu Jan  6 01:08:49 UTC 2011

Modified Files:
        src/distrib/sets/lists/base: md.amd64 md.i386
        src/sbin/gpt: Makefile gpt.c gpt.h
        src/sys/arch/i386/stand/bootxx: boot1.c bootxx.S pbr.S
        src/sys/arch/i386/stand/mbr: Makefile
        src/sys/sys: bootblock.h
Added Files:
        src/sbin/gpt: biosboot.c
        src/sys/arch/i386/stand/mbr: gpt.S
        src/sys/arch/i386/stand/mbr/mbr_gpt: Makefile
        src/sys/arch/i386/stand/mbr/mbr_gpt_com0: Makefile

Log Message:
Support booting from GPT-partioned disks on PC-BIOS-compatible systems.

Much of the work in this commit was done by Mike Volokhov during GSoC 2009.


To generate a diff of this commit:
cvs rdiff -u -r1.106 -r1.107 src/distrib/sets/lists/base/md.amd64
cvs rdiff -u -r1.137 -r1.138 src/distrib/sets/lists/base/md.i386
cvs rdiff -u -r1.3 -r1.4 src/sbin/gpt/Makefile
cvs rdiff -u -r0 -r1.1 src/sbin/gpt/biosboot.c
cvs rdiff -u -r1.12 -r1.13 src/sbin/gpt/gpt.c
cvs rdiff -u -r1.4 -r1.5 src/sbin/gpt/gpt.h
cvs rdiff -u -r1.19 -r1.20 src/sys/arch/i386/stand/bootxx/boot1.c
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/i386/stand/bootxx/bootxx.S
cvs rdiff -u -r1.18 -r1.19 src/sys/arch/i386/stand/bootxx/pbr.S
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/i386/stand/mbr/Makefile
cvs rdiff -u -r0 -r1.1 src/sys/arch/i386/stand/mbr/gpt.S
cvs rdiff -u -r0 -r1.1 src/sys/arch/i386/stand/mbr/mbr_gpt/Makefile
cvs rdiff -u -r0 -r1.1 src/sys/arch/i386/stand/mbr/mbr_gpt_com0/Makefile
cvs rdiff -u -r1.51 -r1.52 src/sys/sys/bootblock.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/base/md.amd64
diff -u src/distrib/sets/lists/base/md.amd64:1.106 src/distrib/sets/lists/base/md.amd64:1.107
--- src/distrib/sets/lists/base/md.amd64:1.106	Thu Dec 16 18:42:49 2010
+++ src/distrib/sets/lists/base/md.amd64	Thu Jan  6 01:08:48 2011
@@ -1,4 +1,4 @@
-# $NetBSD: md.amd64,v 1.106 2010/12/16 18:42:49 christos Exp $
+# $NetBSD: md.amd64,v 1.107 2011/01/06 01:08:48 jakllsch Exp $
 ./dev/lms0					base-obsolete		obsolete
 ./dev/mms0					base-obsolete		obsolete
 ./libexec/ld.elf_so-i386			base-sys-shlib		compat,pic
@@ -298,6 +298,8 @@
 ./usr/mdec/mbr_com0				base-sysutil-bin
 ./usr/mdec/mbr_com0_9600			base-sysutil-bin
 ./usr/mdec/mbr_ext				base-sysutil-bin
+./usr/mdec/mbr_gpt				base-sysutil-bin
+./usr/mdec/mbr_gpt_com0				base-sysutil-bin
 ./usr/mdec/netboot_3c509.rom			base-sysutil-bin
 ./usr/mdec/netboot_3c590.rom			base-sysutil-bin
 ./usr/mdec/netboot_3c90xb.rom			base-sysutil-bin

Index: src/distrib/sets/lists/base/md.i386
diff -u src/distrib/sets/lists/base/md.i386:1.137 src/distrib/sets/lists/base/md.i386:1.138
--- src/distrib/sets/lists/base/md.i386:1.137	Sat Sep 11 13:06:36 2010
+++ src/distrib/sets/lists/base/md.i386	Thu Jan  6 01:08:48 2011
@@ -1,4 +1,4 @@
-# $NetBSD: md.i386,v 1.137 2010/09/11 13:06:36 tsutsui Exp $
+# $NetBSD: md.i386,v 1.138 2011/01/06 01:08:48 jakllsch Exp $
 ./dev/lms0					base-obsolete		obsolete
 ./dev/mms0					base-obsolete		obsolete
 ./dev/pms0					base-obsolete		obsolete
@@ -79,6 +79,8 @@
 ./usr/mdec/mbr_com0				base-sysutil-bin
 ./usr/mdec/mbr_com0_9600			base-sysutil-bin
 ./usr/mdec/mbr_ext				base-sysutil-bin
+./usr/mdec/mbr_gpt				base-sysutil-bin
+./usr/mdec/mbr_gpt_com0				base-sysutil-bin
 ./usr/mdec/netboot_3c509.rom			base-sysutil-bin
 ./usr/mdec/netboot_3c590.rom			base-sysutil-bin
 ./usr/mdec/netboot_3c90xb.rom			base-sysutil-bin

Index: src/sbin/gpt/Makefile
diff -u src/sbin/gpt/Makefile:1.3 src/sbin/gpt/Makefile:1.4
--- src/sbin/gpt/Makefile:1.3	Sat Apr 11 07:58:12 2009
+++ src/sbin/gpt/Makefile	Thu Jan  6 01:08:48 2011
@@ -1,9 +1,9 @@
-# $NetBSD: Makefile,v 1.3 2009/04/11 07:58:12 lukem Exp $
+# $NetBSD: Makefile,v 1.4 2011/01/06 01:08:48 jakllsch Exp $
 # $FreeBSD: src/sbin/gpt/Makefile,v 1.7 2005/09/01 02:49:20 marcel Exp $
 
 PROG=	gpt
-SRCS=	add.c create.c destroy.c gpt.c label.c map.c migrate.c recover.c \
-	remove.c show.c
+SRCS=	add.c biosboot.c create.c destroy.c gpt.c label.c map.c migrate.c \
+	recover.c remove.c show.c
 MAN=	gpt.8
 
 LDADD+=	-lprop -lutil

Index: src/sbin/gpt/gpt.c
diff -u src/sbin/gpt/gpt.c:1.12 src/sbin/gpt/gpt.c:1.13
--- src/sbin/gpt/gpt.c:1.12	Fri Apr  2 19:33:09 2010
+++ src/sbin/gpt/gpt.c	Thu Jan  6 01:08:48 2011
@@ -31,7 +31,7 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/gpt.c,v 1.16 2006/07/07 02:44:23 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: gpt.c,v 1.12 2010/04/02 19:33:09 christos Exp $");
+__RCSID("$NetBSD: gpt.c,v 1.13 2011/01/06 01:08:48 jakllsch Exp $");
 #endif
 
 #include <sys/param.h>
@@ -756,6 +756,7 @@
 	const char *name;
 } cmdsw[] = {
 	{ cmd_add, "add" },
+	{ cmd_biosboot, "biosboot" },
 	{ cmd_create, "create" },
 	{ cmd_destroy, "destroy" },
 	{ NULL, "help" },
@@ -772,7 +773,7 @@
 static void
 usage(void)
 {
-	extern const char addmsg[], createmsg[], destroymsg[];
+	extern const char addmsg[], biosbootmsg[], createmsg[], destroymsg[];
 	extern const char labelmsg1[], labelmsg2[], labelmsg3[];
 	extern const char migratemsg[], recovermsg[], removemsg1[];
 	extern const char removemsg2[], showmsg[];
@@ -783,6 +784,7 @@
 	    "       %s %s\n"
 	    "       %s %s\n"
 	    "       %s %s\n"
+	    "       %s %s\n"
 	    "       %*s %s\n"
 	    "       %s %s\n"
 	    "       %s %s\n"
@@ -790,6 +792,7 @@
 	    "       %s %s\n"
 	    "       %s %s\n",
 	    getprogname(), addmsg,
+	    getprogname(), biosbootmsg,
 	    getprogname(), createmsg,
 	    getprogname(), destroymsg,
 	    getprogname(), labelmsg1,

Index: src/sbin/gpt/gpt.h
diff -u src/sbin/gpt/gpt.h:1.4 src/sbin/gpt/gpt.h:1.5
--- src/sbin/gpt/gpt.h:1.4	Sat Feb  7 18:12:22 2009
+++ src/sbin/gpt/gpt.h	Thu Jan  6 01:08:48 2011
@@ -67,7 +67,7 @@
 };
 
 struct mbr {
-	uint16_t	mbr_code[223];
+	uint8_t		mbr_code[446];
 	struct mbr_part	mbr_part[4];
 	uint16_t	mbr_sig;
 #define	MBR_SIG		0xAA55
@@ -90,6 +90,7 @@
 void	utf8_to_utf16(const uint8_t *, uint16_t *, size_t);
 
 int	cmd_add(int, char *[]);
+int	cmd_biosboot(int, char *[]);
 int	cmd_create(int, char *[]);
 int	cmd_destroy(int, char *[]);
 int	cmd_label(int, char *[]);

Index: src/sys/arch/i386/stand/bootxx/boot1.c
diff -u src/sys/arch/i386/stand/bootxx/boot1.c:1.19 src/sys/arch/i386/stand/bootxx/boot1.c:1.20
--- src/sys/arch/i386/stand/bootxx/boot1.c:1.19	Fri Jan  1 03:18:27 2010
+++ src/sys/arch/i386/stand/bootxx/boot1.c	Thu Jan  6 01:08:48 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: boot1.c,v 1.19 2010/01/01 03:18:27 christos Exp $	*/
+/*	$NetBSD: boot1.c,v 1.20 2011/01/06 01:08:48 jakllsch Exp $	*/
 
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: boot1.c,v 1.19 2010/01/01 03:18:27 christos Exp $");
+__RCSID("$NetBSD: boot1.c,v 1.20 2011/01/06 01:08:48 jakllsch Exp $");
 
 #include <lib/libsa/stand.h>
 #include <lib/libkern/libkern.h>
@@ -44,11 +44,11 @@
 #define XSTR(x) #x
 #define STR(x) XSTR(x)
 
-static uint32_t bios_sector;
+static daddr_t bios_sector;
 
 static struct biosdisk_ll d;
 
-const char *boot1(uint32_t, uint32_t *);
+const char *boot1(uint32_t, uint64_t *);
 extern void putstr(const char *);
 
 extern struct disklabel ptn_disklabel;
@@ -60,7 +60,7 @@
 }
 
 const char *
-boot1(uint32_t biosdev, uint32_t *sector)
+boot1(uint32_t biosdev, uint64_t *sector)
 {
 	struct stat sb;
 	int fd;

Index: src/sys/arch/i386/stand/bootxx/bootxx.S
diff -u src/sys/arch/i386/stand/bootxx/bootxx.S:1.9 src/sys/arch/i386/stand/bootxx/bootxx.S:1.10
--- src/sys/arch/i386/stand/bootxx/bootxx.S:1.9	Mon Apr 28 20:23:25 2008
+++ src/sys/arch/i386/stand/bootxx/bootxx.S	Thu Jan  6 01:08:48 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: bootxx.S,v 1.9 2008/04/28 20:23:25 martin Exp $	*/
+/*	$NetBSD: bootxx.S,v 1.10 2011/01/06 01:08:48 jakllsch Exp $	*/
 
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -39,7 +39,7 @@
  *
  * On entry:
  * 	%dl			BIOS drive number
- *	%esi			Sector number of netbsd partition
+ *	%edi:%esi		Sector number of NetBSD partition
  *	%cs, %ds, %es, %ss	All zero
  *	%sp			near 0xfffc
  */
@@ -60,6 +60,7 @@
 	calll	real_to_prot
 	.code32
 
+	push	%edi
 	movl	$_end, %ecx		/* zero bss */
 	movl	$__bss_start, %edi
 	subl	%edi, %ecx
@@ -67,9 +68,11 @@
 	xor	%eax, %eax
 	rep
 	stosl
+	pop	%edi
 
-	and	$0xff, %edx
-	push	%esi			/* save args for secondary bootstrap */
+	movzbl	%dl, %edx
+	push	%edi			/* save args for secondary bootstrap */
+	push	%esi
 	movl	%esp, %esi		/* address of sector number */
 	push	%edx
 	push	%esi			/* args for boot1 */
@@ -84,7 +87,9 @@
 
 	pop	%edx			/* bios disk number */
 	pop	%ebx			/* expected partition start sector */
+	pop	%ecx
 	movl	$boot_params, %esi
+	orb	$X86_BP_FLAGS_LBA64VALID, 4(%esi)
 	lcall	$SECONDARY_LOAD_ADDRESS/16, $0
 
 boot_fail:

Index: src/sys/arch/i386/stand/bootxx/pbr.S
diff -u src/sys/arch/i386/stand/bootxx/pbr.S:1.18 src/sys/arch/i386/stand/bootxx/pbr.S:1.19
--- src/sys/arch/i386/stand/bootxx/pbr.S:1.18	Sun Jan  2 02:01:58 2011
+++ src/sys/arch/i386/stand/bootxx/pbr.S	Thu Jan  6 01:08:48 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: pbr.S,v 1.18 2011/01/02 02:01:58 jakllsch Exp $	*/
+/*	$NetBSD: pbr.S,v 1.19 2011/01/06 01:08:48 jakllsch Exp $	*/
 
 /*-
  * Copyright (c) 2003,2004 The NetBSD Foundation, Inc.
@@ -97,6 +97,8 @@
  * sector we were loaded from (if we were loaded by NetBSD mbr code).
  * In any case we have to re-read sector zero of the disk and hunt
  * through the BIOS partition table for the NetBSD partition.
+ * However, if there's a magic number in %eax, then %ecx:%ebx
+ * contains the sector we were loaded from.
  */
 
 	.text
@@ -119,12 +121,20 @@
 
 	. = start + MBR_AFTERBPB	/* skip BPB */
 start0:
+#ifndef BOOT_FROM_FAT
+	movl	%eax, %edi		/* move %eax magic out of the way */
+#endif
 	xor	%ax, %ax		/* don't trust values of ds, es or ss */
 	mov	%ax, %ds
 	mov	%ax, %es
 	mov	%ax, %ss
 	mov	$0xfffc, %sp
 
+#ifndef BOOT_FROM_FAT
+	cmpl	$X86_MBR_GPT_MAGIC, %edi /* did mbr_gpt leave us a LBA? */
+	je	boot_gpt
+#endif
+
 	/* A 'reset disk system' request is traditional here... */
 	push	%dx			/* some BIOS zap %dl here :-( */
 	int	$0x13			/* ah == 0 from code above */
@@ -332,6 +342,7 @@
 	jnz	error
 
 	movl	%ebp, %esi			/* %esi ptn base, %dl disk id */
+	movl	lba_sector + 4, %edi		/* %edi ptn base high */
 	jmp	$0, $bootxx			/* our %cs may not be zero */
 
 /* Read disk using int13-extension parameter block */
@@ -355,17 +366,26 @@
 	movw	$0x200 + BOOTXX_SECTORS, %ax	/* command 2, xx sectors */
 	jmp	do_read
 
+#ifndef BOOT_FROM_FAT
+boot_gpt:
+	/* 64-bit LBA in %ecx:%ebx */
+	movl	%ebx, lba_sector
+	movl	%ecx, lba_sector + 4
+	movl	%ebx, %ebp
+	jmp	boot_lba
+#endif
+
 _errtxt: .ascii	"Error "			/* runs into newline... */
 _errcod: .byte	0				/* ... if errcod set */
 _newline:
 	.asciz	"\r\n"
 
 #ifndef TERSE_ERROR
-ERR_READ:	.asciz	"Disk read"
-ERR_NO_BOOTXX:	.asciz	"Not a bootxx image"
-ERR_PTN:	.asciz	"No NetBSD partition"
+ERR_READ:	.asciz	"read"
+ERR_NO_BOOTXX:	.asciz	"no magic"
+ERR_PTN:	.asciz	"no slice"
 #ifndef NO_LBA_CHECK
-ERR_NO_LBA:	.asciz	"Invalid CHS read"
+ERR_NO_LBA:	.asciz	"need LBA"
 #endif
 #endif
 
@@ -387,8 +407,7 @@
 	.word	BOOTADDR			/* offset in segment */
 	.word	0				/* segment */
 _lba_sector:
-	.long	0x0000				/* sector # goes here... */
-	.long	0x0000
+	.quad	0				/* sector # goes here... */
 
 /* Drive Serial Number */
 	. = _C_LABEL(start) + MBR_DSN_OFFSET

Index: src/sys/arch/i386/stand/mbr/Makefile
diff -u src/sys/arch/i386/stand/mbr/Makefile:1.2 src/sys/arch/i386/stand/mbr/Makefile:1.3
--- src/sys/arch/i386/stand/mbr/Makefile:1.2	Sat Jan 19 21:01:34 2008
+++ src/sys/arch/i386/stand/mbr/Makefile	Thu Jan  6 01:08:49 2011
@@ -1,5 +1,6 @@
-#	$NetBSD: Makefile,v 1.2 2008/01/19 21:01:34 dsl Exp $
+#	$NetBSD: Makefile,v 1.3 2011/01/06 01:08:49 jakllsch Exp $
 
 SUBDIR=		mbr mbr_bootsel mbr_ext mbr_com0 mbr_com0_9600
+SUBDIR+=	mbr_gpt mbr_gpt_com0
 
 .include <bsd.subdir.mk>

Index: src/sys/sys/bootblock.h
diff -u src/sys/sys/bootblock.h:1.51 src/sys/sys/bootblock.h:1.52
--- src/sys/sys/bootblock.h:1.51	Wed Jan  5 23:13:01 2011
+++ src/sys/sys/bootblock.h	Thu Jan  6 01:08:48 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: bootblock.h,v 1.51 2011/01/05 23:13:01 jakllsch Exp $	*/
+/*	$NetBSD: bootblock.h,v 1.52 2011/01/06 01:08:48 jakllsch Exp $	*/
 
 /*-
  * Copyright (c) 2002-2004 The NetBSD Foundation, Inc.
@@ -168,6 +168,8 @@
  *
  *	400 - 439	MP	NetBSD: mbr_bootsel
  *
+ *	424 - 439	M	NetBSD: bootptn_guid (in GPT PMBR only)
+ *
  *	440 - 443	M	WinNT/2K/XP Drive Serial Number (NT DSN)
  *		http://www.geocities.com/thestarman3/asm/mbr/Win2kmbr.htm
  *
@@ -194,6 +196,9 @@
 #define	MBR_BOOTCODE_OFFSET	90	/* offsetof(mbr_sector, mbr_bootcode) */
 #define	MBR_BS_OFFSET		400	/* offsetof(mbr_sector, mbr_bootsel) */
 #define	MBR_BS_OLD_OFFSET	404	/* where mbr_bootsel used to be */
+#define	MBR_GPT_GUID_OFFSET	424	/* location of partition GUID to boot */
+#define	MBR_GPT_GUID_DEFAULT		/* default uninitialized GUID */ \
+	{0xeee69d04,0x02f4,0x11e0,0x8f,0x5d,{0x00,0xe0,0x81,0x52,0x9a,0x6b}}
 #define	MBR_DSN_OFFSET		440	/* offsetof(mbr_sector, mbr_dsn) */
 #define	MBR_BS_MAGIC_OFFSET	444	/* offsetof(mbr_sector, mbr_bootsel_magic) */
 #define	MBR_PART_OFFSET		446	/* offsetof(mbr_sector, mbr_part[0]) */
@@ -1064,6 +1069,7 @@
 #define	X86_BOOT_MAGIC_2	X86_BOOT_MAGIC(2)	/* bootxx.S */
 #define	X86_BOOT_MAGIC_PXE	X86_BOOT_MAGIC(3)	/* start_pxe.S */
 #define	X86_BOOT_MAGIC_FAT	X86_BOOT_MAGIC(4)	/* fatboot.S */
+#define	X86_MBR_GPT_MAGIC	0xedb88320		/* gpt.S */
 
 		/* values for bp_flags */
 #define	X86_BP_FLAGS_RESET_VIDEO	1

Added files:

Index: src/sbin/gpt/biosboot.c
diff -u /dev/null src/sbin/gpt/biosboot.c:1.1
--- /dev/null	Thu Jan  6 01:08:49 2011
+++ src/sbin/gpt/biosboot.c	Thu Jan  6 01:08:48 2011
@@ -0,0 +1,326 @@
+/*	$NetBSD: biosboot.c,v 1.1 2011/01/06 01:08:48 jakllsch Exp $ */
+
+/*
+ * Copyright (c) 2009 The NetBSD Foundation, Inc. 
+ * All rights reserved.
+ *     
+ * This code is derived from software contributed to the NetBSD Foundation
+ * by Mike M. Volokhov. Development of this software was supported by the
+ * Google Summer of Code program.
+ * The GSoC project was mentored by Allen Briggs and Joerg Sonnenberger.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifdef __RCSID
+__RCSID("$NetBSD: biosboot.c,v 1.1 2011/01/06 01:08:48 jakllsch Exp $");
+#endif
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/disk.h>
+#include <sys/param.h>
+#include <sys/bootblock.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <paths.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <util.h>
+
+#include "map.h"
+#include "gpt.h"
+
+#define DEFAULT_BOOTDIR		"/usr/mdec"
+#define DEFAULT_BOOTCODE	"mbr_gpt"
+
+static daddr_t start;
+static uint64_t size;
+
+static char *bootpath;
+static unsigned int entry;
+
+const uuid_t uuid_mbr_guid_default = MBR_GPT_GUID_DEFAULT;
+
+const char biosbootmsg[] = "biosboot [-c bootcode] [-i index] device ...";
+
+static void
+usage_biosboot(void)
+{
+	fprintf(stderr, "usage: %s %s\n", getprogname(), biosbootmsg);
+	exit(1);
+}
+
+static struct mbr*
+read_boot(void)
+{
+	int bfd, ret = 0;
+	struct mbr *buf;
+	struct stat st;
+	uuid_t uuid_patch_magic;
+
+	/* XXX how to do the following better? */
+	if (bootpath == NULL) {
+		bootpath = strdup(DEFAULT_BOOTDIR "/" DEFAULT_BOOTCODE);
+	} else {
+		if (strchr(bootpath, '/') == 0) {
+			char *p;
+			if ((p = strdup(bootpath)) == NULL)
+				err(1, "Malloc failed");
+			free(bootpath);
+			(void)asprintf(&bootpath, "%s/%s", DEFAULT_BOOTDIR, p);
+			free(p);
+		}
+	}
+	if (bootpath == NULL)
+		err(1, "Malloc failed");
+
+	if ((buf = malloc((size_t)secsz)) == NULL)
+		err(1, "Malloc failed");
+
+	if ((bfd = open(bootpath, O_RDONLY)) < 0 || fstat(bfd, &st) == -1) {
+		warn("%s", bootpath);
+		goto fail;
+	}
+
+	if (st.st_size != secsz) {
+		warnx("%s: the bootcode does not match '%s' sector size",
+			bootpath, device_name);
+		goto fail;
+	}
+
+	if (read(bfd, buf, secsz) != st.st_size) {
+		warn("%s", bootpath);
+		goto fail;
+	}
+
+	if (le32toh(buf->mbr_sig) != MBR_SIG) {
+		warnx("%s: invalid MBR magic", bootpath);
+		goto fail;
+	}
+
+	uuid_dec_le(&buf->mbr_code[MBR_GPT_GUID_OFFSET], &uuid_patch_magic);
+
+	/*
+	 * The loader have to contain some magic in patchable area,
+	 * such we can be sure that we won't trash something important
+	 */
+	if (!uuid_equal(&uuid_patch_magic, &uuid_mbr_guid_default, NULL)) {
+		warnx("%s: the bootcode does not support required options",
+			bootpath);
+		goto fail;
+	}
+
+	ret++;
+
+    fail:
+	if (bfd >= 0)
+		close(bfd);
+	if (ret == 0) {
+		free(buf);
+		buf = NULL;
+	}
+	return buf;
+}
+
+static void
+biosboot(int fd)
+{
+	map_t *gpt, *tpg;
+	map_t *tbl, *lbt;
+	map_t *mbrmap, *m;
+	struct mbr *mbr, *bootcode;
+	struct gpt_ent *pp;
+	uuid_t buuid;
+
+	/*
+	 * Parse and validate partition maps
+	 */
+	gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
+	if (gpt == NULL) {
+		warnx("%s: error: no primary GPT header; run create or recover",
+		    device_name);
+		return;
+	}
+
+	tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
+	if (tpg == NULL) {
+		warnx("%s: error: no secondary GPT header; run recover",
+		    device_name);
+		return;
+	}
+
+	tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
+	lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
+	if (tbl == NULL || lbt == NULL) {
+		warnx("%s: error: run recover -- trust me", device_name);
+		return;
+	}
+
+	mbrmap = map_find(MAP_TYPE_PMBR);
+	if (mbrmap == NULL || mbrmap->map_start != 0) {
+		warnx("%s: error: no valid Protective MBR found", device_name);
+		return;
+	}
+
+	mbr = mbrmap->map_data;
+
+	/*
+	 * Update the boot code
+	 */
+	if ((bootcode = read_boot()) == NULL) {
+		warnx("error reading bootcode");
+		return;
+	}
+	(void)memcpy(&mbr->mbr_code, &bootcode->mbr_code,
+		sizeof(mbr->mbr_code));
+	free(bootcode);
+
+	/*
+	 * Walk through the GPT and see where we can boot from
+	 */
+	for (m = map_first(); m != NULL; m = m->map_next) {
+		if (m->map_type != MAP_TYPE_GPT_PART || m->map_index < 1)
+			continue;
+
+		pp = m->map_data;
+
+		/* first, prefer user selection */
+		if (entry > 0 && m->map_index == entry)
+			break;
+
+		/* next, partition as could be specified by wedge */
+		if (entry < 1 && size > 0 &&
+		    m->map_start == start && m->map_size == (off_t)size)
+			break;
+	}
+
+	if (m == NULL) {
+		warnx("error: no bootable partition");
+		return;
+	} else
+		uuid_dec_le(pp->ent_guid, &buuid);
+
+#if 1
+	{
+		char *p;
+
+		uuid_to_string(&buuid, &p, NULL);
+		printf("Boot device:     %s\n", device_name);
+		printf("Partition GUID:  %s\n", p);
+		printf("Boot code:       %s\n", bootpath);
+
+		free(p);
+	}
+#endif
+
+	uuid_enc_le(&mbr->mbr_code[MBR_GPT_GUID_OFFSET], &buuid);
+	if (gpt_write(fd, mbrmap) == -1) {
+		warnx("error: cannot update Protective MBR");
+		return;
+	}
+}
+
+int
+cmd_biosboot(int argc, char *argv[])
+{
+	struct dkwedge_info dkw;
+	struct stat sb;
+	char devpath[MAXPATHLEN];
+	char *dev, *p;
+	int ch, fd;
+
+	while ((ch = getopt(argc, argv, "c:i:")) != -1) {
+		switch(ch) {
+		case 'c':
+			if (bootpath != NULL)
+				usage_biosboot();
+			if ((bootpath = strdup(optarg)) == NULL)
+				err(1, "Malloc failed");
+			break;
+		case 'i':
+			if (entry > 0)
+				usage_biosboot();
+			entry = strtoul(optarg, &p, 10);
+			if (*p != 0 || entry < 1)
+				usage_biosboot();
+			break;
+		default:
+			usage_biosboot();
+		}
+	}
+
+	if (argc == optind)
+		usage_biosboot();
+
+	while (optind < argc) {
+		dev = argv[optind++];
+		start = 0;
+		size = 0;
+
+#ifdef __NetBSD__
+		/*
+		 * If a dk wedge was specified, loader should be
+		 * installed onto parent device
+		 */
+		if ((fd = opendisk(dev, O_RDONLY, devpath, sizeof(devpath), 0))
+				== -1)
+			goto next;
+		if (fstat(fd, &sb) == -1)
+			goto close;
+
+#ifdef DIOCGWEDGEINFO
+		if ((sb.st_mode & S_IFMT) != S_IFREG &&
+		    ioctl(fd, DIOCGWEDGEINFO, &dkw) != -1) {
+			if (entry > 0)
+				/* wedges and indexes are mutually exclusive */
+				usage_biosboot();
+			dev = dkw.dkw_parent;
+			start = dkw.dkw_offset;
+			size = dkw.dkw_size;
+		}
+#endif
+	close:
+		close(fd);
+#endif	/* __NetBSD__*/
+
+		fd = gpt_open(dev);
+	next:
+		if (fd == -1) {
+			warn("unable to open device '%s'", device_name);
+			continue;
+		}
+
+		biosboot(fd);
+
+		gpt_close(fd);
+	}
+
+	return (0);
+}

Index: src/sys/arch/i386/stand/mbr/gpt.S
diff -u /dev/null src/sys/arch/i386/stand/mbr/gpt.S:1.1
--- /dev/null	Thu Jan  6 01:08:49 2011
+++ src/sys/arch/i386/stand/mbr/gpt.S	Thu Jan  6 01:08:49 2011
@@ -0,0 +1,552 @@
+/*	$NetBSD: gpt.S,v 1.1 2011/01/06 01:08:49 jakllsch Exp $ */
+
+/*
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to the NetBSD Foundation
+ * by Mike M. Volokhov, based on the mbr.S code by Wolfgang Solfrank,
+ * Frank van der Linden, and David Laight.
+ * Development of this software was supported by the
+ * Google Summer of Code program.
+ * The GSoC project was mentored by Allen Briggs and Joerg Sonnenberger.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * x86 PC BIOS master boot code - GUID partition table format
+ */
+
+/* Compile options:
+ * COM_PORT	- do serial io to specified port number
+ *		  0..3 => bios port, otherwise actual io_addr
+ * COM_BAUD	- initialise serial port baud rate
+ *
+ * NO_LBA_CHECK	- no check if bios supports LBA reads
+ * NO_CRC_CHECK	- disable crc checks for GPT
+ * NO_BANNER    - do not output title line 'banner'
+ */
+
+#ifdef COM_PORT
+#if COM_PORT < 4
+/* The first 4 items in the 40:xx segment are the serial port base addresses */
+#define COM_PORT_VAL (0x400 + (COM_PORT * 2))
+#else
+#define COM_PORT_VAL $COM_PORT
+#endif
+
+#if !defined(COM_FREQ)
+#define COM_FREQ 1843200
+#endif
+#endif
+
+#include <machine/asm.h>
+#include <sys/bootblock.h>
+
+#define BOOTADDR	0x7c00
+#define GPTBUFADDR	0xa000		/* GPT buffer (both header & array) */
+
+/*
+ * GPT header structure, offsets
+ */
+#define GPTHDR_SIG_O	0		/* header signature, 8 b */
+#define GPTHDR_REV_O	8		/* GPT revision, 4 b */
+#define GPTHDR_SIZE_O	12		/* header size, 4 b */
+#define GPTHDR_CRC_O	16		/* header CRC32, 4 b */
+#define GPTHDR_RSVD_O	20		/* reserved, 4 b */
+#define GPTHDR_MYLBA_O	24		/* this header LBA, 8 b */
+#define GPTHDR_ALTLBA_O	32		/* alternate header LBA, 8 b */
+#define GPTHDR_SLBA_O	40		/* first usable LBA, 8 b */
+#define GPTHDR_ELBA_O	48		/* last usable LBA, 8 b */
+#define GPTHDR_GUID_O	56		/* disk GUID, 16 b */
+#define GPTHDR_PTNLBA_O	72		/* ptn. entry LBA, 8 b */
+#define GPTHDR_PTNN_O	80		/* number of ptns, 4 b */
+#define GPTHDR_PTNSZ_O	84		/* partition size, 4 b */
+#define GPTHDR_PTNCRC_O	88		/* ptn. array CRC32, 4 b */
+
+/*
+ * GPT partition entry structure, offsets
+ */
+#define GPTPTN_TYPE_O	0		/* ptn. type GUID, 16 b */
+#define GPTPTN_GUID_O	16		/* ptn. unique GUID, 16 b */
+#define GPTPTN_SLBA_O	32		/* ptn. starting LBA, 8 b */
+#define GPTPTN_ELBA_O	40		/* ptn. ending LBA, 8 b */
+#define GPTPTN_ATTR_O	48		/* ptn. attributes, 8 b */
+#define GPTPTN_NAME_O	56		/* ptn. name, UTF-16, 72 b */
+
+/*
+ * Default values of generic disk partitioning
+ */
+#ifndef SECTOR_SIZE
+#define SECTOR_SIZE		512		/* 8192 bytes max */
+#endif
+#define GPTHDR_BLKNO		1
+#define GPTHDR_SIZE		92		/* size of GPT header */
+#define GPTHDR_LBASZ		1		/* default LBAs for header */
+#define GPTHDR_PTNSZ		128		/* size of a partition entry */
+#define GPTHDR_PTNN_MIN		128		/* minimum number of ptns */
+#define GPTPTN_SIZE		(GPTHDR_PTNSZ * GPTHDR_PTNN_MIN)
+#if GPTPTN_SIZE % SECTOR_SIZE == 0
+#define GPTPTN_LBASZ		(GPTPTN_SIZE / SECTOR_SIZE)
+#else
+#define GPTPTN_LBASZ		(GPTPTN_SIZE / SECTOR_SIZE + 1)
+#endif
+#define GPT_LBASZ		(GPTHDR_LBASZ + GPTPTN_LBASZ)
+
+/*
+ * Minimum and maximum drive number that is considered to be valid.
+ */
+#define MINDRV		0x80
+#define MAXDRV		0x8f
+
+/*
+ * Error codes. Done this way to save space.
+ */
+#define ERR_INVPART	'P'		/* Invalid partition table */
+#define ERR_READ	'R'		/* Read error */
+#define ERR_NOOS	'S'		/* Magic no. check failed for part. */
+#define ERR_NO_LBA	'L'		/* Sector above chs limit */
+
+#define set_err(err)	movb	$err, %al
+
+	.text
+	.code16
+/*
+ * Move ourselves out of the way first.
+ * (to the address we are linked at)
+ * and zero our bss
+ */
+ENTRY(start)
+	xor	%ax, %ax
+	mov	%ax, %ss
+	movw	$BOOTADDR, %sp
+	mov	%ax, %es
+	mov	%ax, %ds
+	movw	$mbr, %di
+	mov     $BOOTADDR + (mbr - start), %si
+	push	%ax			/* zero for %cs of lret */
+	push	%di
+	movw	$(bss_start - mbr), %cx
+	rep
+	movsb				/* relocate code (zero %cx on exit) */
+	mov	$(bss_end - bss_start + 511)/512, %ch
+	rep
+	stosw				/* zero bss */
+	lret				/* Ensures %cs == 0 */
+
+/*
+ * Sanity check the drive number passed by the BIOS. Some BIOSs may not
+ * do this and pass garbage.
+ */
+mbr:
+	cmpb	$MAXDRV, %dl		/* relies on MINDRV being 0x80 */
+	jle	1f
+	movb	$MINDRV, %dl		/* garbage in, boot disk 0 */
+1:
+	push	%dx			/* save drive number */
+	push	%dx			/* twice - for err_msg loop */
+
+#if defined(COM_PORT) && defined(COM_BAUD)
+	mov	$com_args, %si
+	mov	$num_com_args, %cl	/* %ch is zero from above */
+	mov	COM_PORT_VAL, %dx
+1:	lodsw
+	add	%ah, %dl
+	outb	%dx
+	loop	1b
+#endif
+
+#ifndef NO_BANNER
+	mov	$banner, %si
+	call	message
+#endif
+
+/*
+ * Read and validate GUID partition tables
+ *
+ * Register use:
+ * %ax		temp
+ * %bx		temp
+ * %cx		counters (%ch was preset to zero via %cx before)
+ * %dx		disk pointer (inherited from BIOS or the check above)
+ * %bp		GPT header pointer
+ */
+#ifndef NO_LBA_CHECK
+/*
+ * Determine whether we have int13-extensions, by calling int 13, function 41.
+ * Check for the magic number returned, and the disk packet capability.
+ * On entry %dx should contain BIOS disk number.
+ */
+lba_check:
+	movw	$0x55aa, %bx
+	movb	$0x41, %ah
+	int	$0x13
+	set_err(ERR_NO_LBA)
+	jc	1f			/* no int13 extensions */
+	cmpw	$0xaa55, %bx
+	jnz	1f
+	testb	$1, %cl
+	jnz	gpt
+1:	jmp	err_msg
+#endif
+
+gpt:
+	/*
+	 * Read GPT header
+	 */
+	movw	$GPTBUFADDR, %bp	/* start from primary GPT layout */
+read_gpt:
+	call	do_lba_read		/* read GPT header */
+	jc	try_gpt2
+
+	/*
+	 * Verify GPT header
+	 */
+	movw	$efihdr_sign, %si	/* verify GPT signature... */
+	movw	%bp, %di		/* ptn signature is at offset 0 */
+	movb	$sizeof_efihdr_sign, %cl /* signature length */
+	repe
+	cmpsb				/* compare */
+	jne	try_gpt2		/* if not equal - try GPT2 */
+
+#ifndef NO_CRC_CHECK
+	mov	%bp, %si		/* verify CRC32 of the header... */
+	mov	$GPTHDR_SIZE, %di	/* header boundary */
+	add	%bp, %di
+	xor	%eax, %eax
+	xchgl	%eax, GPTHDR_CRC_O(%bp)	/* save and reset header CRC */
+	call	crc32
+	cmp	%eax, %ebx		/* is CRC correct? */
+	jne	try_gpt2
+#endif
+
+#if 0	/* XXX: weak check - safely disabled due to space constraints */
+	movw	$lba_sector, %si	/* verify GPT location... */
+	mov	$GPTHDR_MYLBA_O, %di
+	add	%bp, %di
+	movb	$8, %cl			/* LBA size */
+	repe
+	cmpsb				/* compare */
+	jne	try_gpt2		/* if not equal - try GPT2 */
+#endif
+
+	/*
+	 * All header checks passed - now verify GPT partitions array
+	 */
+#ifndef NO_CRC_CHECK
+	movl	GPTHDR_PTNCRC_O(%bp), %eax	/* original array checksum */
+	push	%bp			/* save header pointer for try_gpt2 */
+#endif
+
+	/*
+	 * point %bp to GPT partitions array location
+	 */
+	cmp	$GPTBUFADDR, %bp
+	je	1f
+	mov	$GPTBUFADDR, %bp
+	jmp	2f
+1:	mov	$GPTBUFADDR + GPTPTN_LBASZ * SECTOR_SIZE, %bp
+2:
+
+#ifndef NO_CRC_CHECK
+	mov	%bp, %si		/* array location for CRC32 check */
+	mov	$GPTPTN_SIZE, %di	/* array boundary */
+	add	%bp, %di
+	call	crc32
+	cmp	%eax, %ebx		/* is CRC correct? */
+	jne	1f			/* if no - try GPT2 */
+	pop	%ax			/* restore stack consistency */
+#endif
+	jmp	gpt_parse
+
+#ifndef NO_CRC_CHECK
+1:	pop	%bp			/* restore after unsucc. array check */
+#endif
+try_gpt2:
+	cmp	$GPTBUFADDR, %bp	/* is this GPT1? */
+	set_err(ERR_INVPART)		
+	jne	err_msg			/* if no - we just tried GPT2. Stop. */
+
+	mov	%bp, %si		/* use [%bp] as tmp buffer */
+	movb	$0x1a, (%si)		/* init buffer size (per v.1.0) */
+	movb	$0x48, %ah		/* request extended LBA status */
+	int	$0x13			/* ... to get GPT2 location */
+	set_err(ERR_NO_LBA)
+	jc	err_msg			/* on error - stop */
+#define LBA_DKINFO_OFFSET 16		/* interested offset in out buffer */
+	addw	$LBA_DKINFO_OFFSET, %si	/* ... contains number of disk LBAs */
+#undef LBA_DKINFO_OFFSET
+	movw	$lba_sector, %di
+	movb	$8, %cl			/* LBA size */
+	rep
+	movsb				/* do get */
+	subl	$GPT_LBASZ, lba_sector	/* calculate location of GPT2 */
+	sbbl	$0, lba_sector + 4	/* 64-bit LBA correction */
+
+	movw	$GPTBUFADDR + GPTPTN_LBASZ * SECTOR_SIZE, %bp
+					/* the GPT2 header location */
+	jmp	read_gpt		/* try once again */
+
+/*
+ * GPT header validation done.
+ * Now parse GPT partitions and try to boot from appropriate.
+ * Register use:
+ * %bx		partition counter
+ * %bp		partition entry pointer (already initialized on entry)
+ * %di		partition entry moving pointer
+ * %si		variables pointer
+ * %cx		counter
+ */
+
+gpt_parse:
+	movw	$BOOTADDR, lba_rbuff	/* from now we will read boot code */
+	movb	$1, lba_count		/* read PBR only */
+	mov	$GPTHDR_PTNN_MIN, %bx	/* number of GUID partitions to parse */
+do_gpt_parse:
+	movw	$bootptn_guid, %si	/* lookup the boot partition GUID */
+	movb	$0x10, %cl		/* sizeof GUID */
+	movw	%bp, %di		/* set pointer to partition entry */
+	add	%cx, %di		/* partition GUID at offset 16 */
+	repe
+	cmpsb				/* do compare */
+	jne	try_nextptn		/* doesn't seem appropriate ptn */
+
+	/*
+	 * Read partition boot record
+	 */
+	mov	$GPTPTN_SLBA_O, %si	/* point %si to partition LBA */
+	add	%bp, %si
+	movw	$lba_sector, %di
+	movb	$8, %cl			/* LBA size */
+	rep
+	movsb				/* set read pointer to LBA of PBR */
+	call	do_lba_read		/* read PBR */
+	jz	try_nextptn
+
+	/*
+	 * Check signature for valid bootcode and try to boot
+	 */
+	movb	BOOTADDR, %al		/* first byte non-zero */
+	testb	%al, %al
+	jz	1f
+	movw	BOOTADDR + MBR_MAGIC_OFFSET, %ax
+1:	cmp	$MBR_MAGIC, %ax
+	jne	try_nextptn
+do_boot:
+	pop	%dx			/* ... %dx - drive # */
+	movw	$lba_sector, %sp	/* ... %ecx:%ebx - boot partition LBA */
+	pop	%ebx
+	pop	%ecx
+	movl 	crc32_poly, %eax	/* X86_MBR_GPT_MAGIC */
+	jmp	BOOTADDR
+					/* THE END */
+
+try_nextptn:
+	addw	$GPTHDR_PTNSZ, %bp	/* move to next partition */
+	dec	%bx			/* ptncounter-- */
+	jnz	do_gpt_parse
+	set_err(ERR_NOOS)		/* no bootable partitions were found */
+	/* jmp	err_msg */		/* stop */
+
+/* Something went wrong...
+ * Output error code,
+ * reset disk subsystem - needed after read failure,
+ * and wait for user key
+ */
+err_msg:
+	movb	%al, errcod
+	movw	$errtxt, %si
+	call	message
+	pop	%dx			/* drive we errored on */
+	xor	%ax,%ax			/* only need %ah = 0 */
+	int	$0x13			/* reset disk subsystem */
+	int	$0x18			/* BIOS might ask for a key */
+					/* press and retry boot seq. */
+1:	sti
+	hlt
+	jmp	1b
+
+/*
+ * I hate #including source files, but the stuff below has to be at
+ * the correct absolute address.
+ * Clearly this could be done with a linker script.
+ */
+
+#if defined(COM_PORT) && defined(COM_BAUD)
+message:
+	pusha
+message_1:
+	lodsb
+	test	%al, %al
+	jz	3f
+	mov	COM_PORT_VAL, %dx
+	outb	%al, %dx
+	add	$5, %dl
+2:	inb	%dx
+	test	$0x40, %al
+	jz	2b
+	jmp	message_1
+3:	popa
+	ret
+#else
+#include <message.S>
+#endif
+
+#if 0
+#include <dump_eax.S>
+#endif
+
+#ifndef NO_CRC_CHECK
+/*
+ * The CRC32 calculation
+ *
+ * %si		address of block to hash
+ * %di		stop address
+ * %ax		scratch (but restored after exit)
+ * %dx		scratch (but restored after exit)
+ * %cx		counter
+ * %ebx		crc (returned)
+ */
+crc32:
+	push	%dx			/* preserve drive number */
+	push	%ax			/* preserve original CRC */
+
+	xorl	%ebx, %ebx
+	decl	%ebx			/* init value */
+1:
+	lodsb				/* load next message byte to %al */
+	movb	$8, %cl			/* set bit counter */
+2:
+	movb	%al, %dl
+	xorb	%bl, %dl		/* xoring with previous result */
+	shrl	$1, %ebx
+	shrb	$1, %al
+	testb	$1, %dl
+	jz	3f
+crc32_poly = . + 3			/* gross, but saves a few bytes */
+	xorl	$0xedb88320, %ebx	/* EFI CRC32 Polynomial */
+3:
+	loop	2b			/* loop over bits */
+	cmp	%di, %si		/* do we reached end of message? */
+	jne	1b
+	notl	%ebx			/* result correction */
+
+	pop	%ax
+	pop	%dx
+	ret
+#endif
+
+do_lba_read:
+	movw	$lba_dap, %si
+	movb	$0x42, %ah
+	int	$0x13			/* read */
+	ret
+
+/*
+ * Data definition block
+ */
+
+errtxt: .ascii	"Error "		/* runs into crlf if errcod set */
+errcod: .byte	0
+crlf:	.asciz	"\r\n"
+
+#ifndef NO_BANNER
+banner:	.asciz	"NetBSD GPT\r\n"
+#endif
+
+#if defined(COM_PORT) && defined(COM_BAUD)
+#define COM_DIVISOR (((COM_FREQ / COM_BAUD) + 8) / 16)
+com_args:
+	.byte	0x80			/* divisor latch enable */
+	.byte	+3			/* io_port + 3 */
+	.byte	COM_DIVISOR & 0xff
+	.byte	-3			/* io_port */
+	.byte	COM_DIVISOR >> 8	/* high baud */
+	.byte	+1			/* io_port + 1 */
+	.byte	0x03			/* 8 bit no parity */
+	.byte	+2			/* io_port + 3 */
+num_com_args = (. - com_args)/2
+#endif
+
+/*
+ * Control block for int-13 LBA read - Disk Address Packet
+ */
+lba_dap:
+	.byte	0x10			/* control block length */
+	.byte	0			/* reserved */
+lba_count:
+	.word	GPT_LBASZ		/* sector count */
+lba_rbuff:
+	.word	GPTBUFADDR		/* offset in segment */
+	.word	0			/* segment */
+lba_sector:
+	.quad	GPTHDR_BLKNO		/* sector # goes here... */
+
+efihdr_sign:
+	.ascii	"EFI PART"		/* GPT header signature */
+	.long	0x00010000		/* GPT header revision */
+sizeof_efihdr_sign = . - efihdr_sign
+
+/*
+ * Stuff from here on is overwritten by gpt/fdisk - the offset must not change
+ *
+ * Get amount of space to makefile can report it.
+ * (Unfortunately I can't seem to get the value reported when it is -ve)
+ */
+mbr_space = bootptn_guid - .
+
+/*
+ * GUID of the bootable partition. Patchable area.
+ * Default GUID used by installer for safety checks.
+ */
+	. = start + MBR_GPT_GUID_OFFSET
+bootptn_guid:
+	/* MBR_GPT_GUID_DEFAULT */
+	.long 0xeee69d04
+	.word 0x02f4
+	.word 0x11e0
+	.byte 0x8f,0x5d
+	.byte 0x00,0xe0,0x81,0x52,0x9a,0x6b
+
+/* space for mbr_dsn */
+	. = start + MBR_DSN_OFFSET
+	.long	0
+
+/* mbr_bootsel_magic */
+	. = start + MBR_BS_MAGIC_OFFSET
+	.word	0
+
+/* mbr partition table */
+	. = start + MBR_PART_OFFSET
+parttab:
+	.fill	0x40, 0x01, 0x00
+
+	. = start + MBR_MAGIC_OFFSET
+	.word	MBR_MAGIC
+
+/* zeroed data space */
+bss_off = 0
+bss_start = .
+#define BSS(name, size) name = bss_start + bss_off; bss_off = bss_off + size
+	BSS(dump_eax_buff, 16)
+	BSS(bss_end, 0)

Index: src/sys/arch/i386/stand/mbr/mbr_gpt/Makefile
diff -u /dev/null src/sys/arch/i386/stand/mbr/mbr_gpt/Makefile:1.1
--- /dev/null	Thu Jan  6 01:08:49 2011
+++ src/sys/arch/i386/stand/mbr/mbr_gpt/Makefile	Thu Jan  6 01:08:49 2011
@@ -0,0 +1,6 @@
+#	$NetBSD: Makefile,v 1.1 2011/01/06 01:08:49 jakllsch Exp $
+
+PROG=		mbr_gpt
+SRCS=		gpt.S
+
+.include <../Makefile.mbr>

Index: src/sys/arch/i386/stand/mbr/mbr_gpt_com0/Makefile
diff -u /dev/null src/sys/arch/i386/stand/mbr/mbr_gpt_com0/Makefile:1.1
--- /dev/null	Thu Jan  6 01:08:49 2011
+++ src/sys/arch/i386/stand/mbr/mbr_gpt_com0/Makefile	Thu Jan  6 01:08:49 2011
@@ -0,0 +1,7 @@
+#	$NetBSD: Makefile,v 1.1 2011/01/06 01:08:49 jakllsch Exp $
+
+PROG=		mbr_gpt_com0
+SRCS=		gpt.S
+AFLAGS+=	-DCOM_PORT=0
+
+.include <../Makefile.mbr>

Reply via email to