Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 14 Jun 2012 16:11:11 +0400
From:      "Andrey V. Elsukov" <ae@FreeBSD.org>
To:        Hiroki Sato <hrs@FreeBSD.org>
Cc:        Warren Block <wblock@wonkity.com>, Andriy Gapon <avg@FreeBSD.org>, Pawel Jakub Dawidek <pjd@FreeBSD.org>, current@FreeBSD.org, jhb@FreeBSD.org
Subject:   Re: CFR: backup GPT header support in pmbr and loader(8) (Re: Handbook mirroring section)
Message-ID:  <4FD9D4DF.9090609@FreeBSD.org>
In-Reply-To: <20120610.224813.710171778841273502.hrs@allbsd.org>
References:  <4FCF3021.5070802@FreeBSD.org> <20120606.200735.1551208261335301113.hrs@allbsd.org> <4FD05573.70801@FreeBSD.org> <20120610.224813.710171778841273502.hrs@allbsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------000000090006070106000802
Content-Type: text/plain; charset=KOI8-R
Content-Transfer-Encoding: 7bit

On 10.06.2012 17:48, Hiroki Sato wrote:
> ae> Yes, i also have thought about this and this should work for most GEOM classes,
> ae> but i revised again PMBR code and it seems that it will not work anyway :)
> ae> Our PMBR doesn't use backup GPT header and table, and it doesn't verify
> ae> correctness of primary GPT.
> ae>
> ae> From the other side, there are three situations when we use GPT:
> ae> 1. FreeBSD is only one system on the disk and we use PMBR and gptboot to boot it.
> ae>
> ae> In case if we will fix PMBR your patch will help.
> 
>  I created the attached patchset for the loader and pmbr to support
>  backup GPT header when the primary one is corrupted.  Can anyone test
>  and/or review it?
> 
>  The pmbr program now checks the GPT signature, and if failed it tries
>  to search the backup header from the last LBA.  When GEOM metadata is
>  found at the last LBA, the second last will be checked.  The
>  loader(8) program also supports the same algorithm to search the
>  backup header.

Hi,

I have tested your patch and discovered yet another problem.
Actually the loader(8) doesn't read backup GPT header and table and
this stops booting when primary header or table damaged
(pmbr and gptboot works as expected in this case).
The libi386/biosdisk.c should be modified to add this support.

Also, our PMBR image doesn't contain any partition entries and
writing it to the disk with dd(1) makes the system unbootable.
What you think if we will add one partition entry to the PMBR image?
I modified your patch (the last hunk added) and it is attached.

-- 
WBR, Andrey V. Elsukov

--------------000000090006070106000802
Content-Type: text/plain; charset=windows-1251;
 name="pmbr.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="pmbr.diff"

Index: head/sys/boot/i386/pmbr/pmbr.s
===================================================================
--- head/sys/boot/i386/pmbr/pmbr.s	(revision 237056)
+++ head/sys/boot/i386/pmbr/pmbr.s	(working copy)
@@ -42,8 +42,9 @@
 		.set STACK,EXEC+SECSIZE*4	# Stack address
 		.set GPT_ADDR,STACK		# GPT header address
 		.set GPT_SIG,0
-		.set GPT_SIG_0,0x20494645
-		.set GPT_SIG_1,0x54524150
+		.set GPT_SIG_0,0x20494645	# "EFI "
+		.set GPT_SIG_1,0x54524150	# "PART"
+		.set GEOM_MAGIC,0x4d4f4547	# "GEOM"
 		.set GPT_MYLBA,24
 		.set GPT_PART_LBA,72
 		.set GPT_NPART,80
@@ -52,6 +53,8 @@
 		.set PART_TYPE,0
 		.set PART_START_LBA,32
 		.set PART_END_LBA,40
+		.set DPBUF,PART_ADDR+SECSIZE
+		.set DPBUF_SEC,0x10		# Number of sectors
 
 		.set NHRDRV,0x475		# Number of hard drives
 
@@ -91,16 +94,40 @@ main:	 	cmpb $0x80,%dl			# Drive valid?
 		jb main.2			# Yes
 main.1: 	movb $0x80,%dl			# Assume drive 0x80
 #
-# Load the primary GPT header from LBA 1 and verify signature.
+# Load the GPT header and verify signature.  Try LBA 1 for the primary one and
+# the last LBA for the backup if it is broken.  Skip the LBAs if GEOM
+# metadata found at the backup location.
 #
-main.2:		movw $GPT_ADDR,%bx
+main.2:		call getdrvparams		# Read drive parameters
+		movb $1,%dh			# %dh := 1 (reading primary)
+main.2a:	movw $GPT_ADDR,%bx
 		movw $lba,%si
-		call read
+		call read			# Read header and check GPT sig
 		cmpl $GPT_SIG_0,GPT_ADDR+GPT_SIG
-		jnz err_pt
+		jnz main.2b
 		cmpl $GPT_SIG_1,GPT_ADDR+GPT_SIG+4
-		jnz err_pt
+		jnz main.2b
+		jmp load_part
+main.2b:	cmpb $1,%dh			# Reading primary?
+		je main.3			# Try backup if yes
+		cmpl $GEOM_MAGIC,GPT_ADDR	# GEOM sig at backup location?
+		jz main.3			# Skip GEOM metadata
+		jmp err_pt			# Invalid table found
 #
+# Try alternative LBAs from the last sector for the GPT header.
+#
+main.3:		movb $0,%dh			# %dh := 0 (reading backup)
+		movw $DPBUF+DPBUF_SEC,%si	# %si = last sector + 1
+		movw $lba,%di			# %di = $lba
+		cmpl $0,(%si)			#
+		jnz main.3a			#
+		decl 0x4(%si)			# 0x4(%si) = last sec (32-64)
+main.3a:	decl (%si)			# 0x0(%si) = last sec (0-31)
+		movw $2,%cx
+		rep
+		movsw				# $lastsec--, copy it to $lba
+		jmp main.2a			# Read the next sector
+#
 # Load a partition table sector from disk and look for a FreeBSD boot
 # partition.
 #
@@ -172,6 +199,16 @@ read:		pushl 0x4(%si)			# Set the LBA
 		jc err_rd			# If error
 		ret
 #
+# Check the number of LBAs on the drive index %dx.  Trashes %ax and %si.
+#
+getdrvparams:
+		movw $DPBUF,%si			# Set the address of result buf
+		movw $0x001e,(%si)		# len
+		movw $0x4800,%ax		# BIOS: Read Drive Parameters
+		int $0x13			# Call the BIOS
+		jc err_rd			# "I/O error" if error
+		ret
+#
 # Various error message entry points.
 #
 err_big: 	movw $msg_big,%si		# "Boot loader too
@@ -219,5 +256,15 @@ boot_uuid:	.long 0x83bd6b9d
 sig:		.long 0				# OS Disk Signature
 		.word 0				# "Unknown" in PMBR
 
-partbl: 	.fill 0x10,0x4,0x0		# Partition table
+partbl: 	.byte 0x80
+		.byte 0x00
+		.byte 0x02
+		.byte 0x00
+		.byte 0xee
+		.byte 0xff
+		.byte 0xff
+		.byte 0xff
+		.long 1
+		.long 0xffffffff
+		.fill 0x10,0x3,0x0		# Partition table
 		.word MAGIC			# Magic number

--------------000000090006070106000802--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4FD9D4DF.9090609>