Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 5 Aug 2012 12:57:38 +0000 (UTC)
From:      "Andrey V. Elsukov" <ae@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r239060 - head/sys/boot/i386/pmbr
Message-ID:  <201208051257.q75CvcqA085421@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ae
Date: Sun Aug  5 12:57:38 2012
New Revision: 239060
URL: http://svn.freebsd.org/changeset/base/239060

Log:
  When GPT signature is invalid in the primary GPT header, then try to
  read backup GPT header.
  
  Submitted by:	hrs (previous version)

Modified:
  head/sys/boot/i386/pmbr/pmbr.s

Modified: head/sys/boot/i386/pmbr/pmbr.s
==============================================================================
--- head/sys/boot/i386/pmbr/pmbr.s	Sun Aug  5 12:16:11 2012	(r239059)
+++ head/sys/boot/i386/pmbr/pmbr.s	Sun Aug  5 12:57:38 2012	(r239060)
@@ -42,8 +42,8 @@
 		.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 GPT_MYLBA,24
 		.set GPT_PART_LBA,72
 		.set GPT_NPART,80
@@ -52,6 +52,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,15 +93,32 @@ 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.
 #
-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?
+		jne err_pt			# If no - 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
+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 +191,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



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