summaryrefslogtreecommitdiffstats
path: root/sys/boot/i386
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2012-08-05 12:57:38 +0000
committerae <ae@FreeBSD.org>2012-08-05 12:57:38 +0000
commit7d0b9e919063866ecf0618822070b8cb60af52c0 (patch)
treeb47c5e1de4eedbfcc806f72495c98f82b6cf98c8 /sys/boot/i386
parent53f13e0527cdd085c670d34e5ad0b018a4ce648e (diff)
downloadFreeBSD-src-7d0b9e919063866ecf0618822070b8cb60af52c0.zip
FreeBSD-src-7d0b9e919063866ecf0618822070b8cb60af52c0.tar.gz
When GPT signature is invalid in the primary GPT header, then try to
read backup GPT header. Submitted by: hrs (previous version)
Diffstat (limited to 'sys/boot/i386')
-rw-r--r--sys/boot/i386/pmbr/pmbr.s43
1 files changed, 36 insertions, 7 deletions
diff --git a/sys/boot/i386/pmbr/pmbr.s b/sys/boot/i386/pmbr/pmbr.s
index 8acdef2..1a75881 100644
--- a/sys/boot/i386/pmbr/pmbr.s
+++ b/sys/boot/i386/pmbr/pmbr.s
@@ -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
OpenPOWER on IntegriCloud