From 76adb3c3574e7451137604b62e41fc0ed48b021b Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Wed, 11 Feb 2009 01:53:52 -0800 Subject: [PATCH] Fix long-standing bug in boot1 code - can read junk from fake partition table boot1 reads the MBR to locate the BSD partition type (0xA5). However, to reduce the size of the boot1 code the 32 bit LBA for the MBR was being loaded via the fake partition table at label 'part4', which was assumed to contain a LBA of 0. Unfortunately this portion of the boot1 code is not usually written by the disklabel program and may contain garbage. For the last few years we have worked around the issue by zeroing out the label area before installing a new label. We still have to do this to avoid disklabel32/disklabel64 confusion, but with this fix forgetting to zero the area should not cause a properly installed disklabel to fail to boot properly. To fix the problem, add the necessary instructions to generate a 32 bit LBA of 0 directly for reading the MBR. They barely fit. --- sys/boot/pc32/boot2/boot1.S | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/sys/boot/pc32/boot2/boot1.S b/sys/boot/pc32/boot2/boot1.S index f7194f752d..39cfcdfa0c 100644 --- a/sys/boot/pc32/boot2/boot1.S +++ b/sys/boot/pc32/boot2/boot1.S @@ -143,6 +143,9 @@ xread.1: // Starting // Setup the segment registers to flat addressing (segment 0) and setup the // stack to end just below the start of our code. // +// XXX note - our origin (start) points to the MEM_BIOS_LADDR. We run +// from there but boot2 later on calls xread at BOOT1_ORIGIN. +// main: cld // String ops inc xor %cx,%cx // Zero mov %cx,%es // Address @@ -160,16 +163,18 @@ main: cld // String ops inc movsw // code // // If we are on a hard drive, then load the MBR and look for the first -// FreeBSD slice. We use the fake partition entry below that points to -// the MBR when we call nread. The first pass looks for the first active -// FreeBSD slice. The second pass looks for the first non-active FreeBSD -// slice if the first one fails. +// FreeBSD slice. +// +// Note, we can't use the fake partition entry (part4), as it may contain +// garbage if this is a normal boot1 on a slice, verses a dangerously +// dedicated disk. Hardwire sector 0 to acquire the MBR // - mov $part4,%si // Partition + xor %ax,%ax + xor %cx,%cx cmpb $0x80,%dl // Hard drive? jb main.4 // No movb $0x1,%dh // Block count - callw nread // Read MBR + callw nread_alt // Read MBR mov $0x1,%cx // Two passes main.1: mov $BOOT2_LOAD_BUF+PRT_OFF,%si // Partition table movb $0x1,%dh // Partition @@ -273,9 +278,11 @@ seta20.2: inb $0x64,%al // Get status // // Trampoline used to call read from within boot1. // -nread: mov $BOOT2_LOAD_BUF,%bx // Transfer buffer +nread: mov 0x8(%si),%ax // Get mov 0xa(%si),%cx // LBA +nread_alt: + mov $BOOT2_LOAD_BUF,%bx // Transfer buffer push %cs // Read from callw xread.1 // disk jnc return // If success, return @@ -430,6 +437,10 @@ flags: .byte FLAGS // Flags .org PRT_OFF,0x90 // Partition table +// +// THIS MAY NOT BE WRITTEN OUT TO THE BOOT1 AREA OF THE DISKLABEL. This +// section is only written out when the disklabel is placed on the raw +// disk instead of in a slice, when creating a dangerously dedicated disk. .fill 0x30,0x1,0x0 part4: .byte 0x80, 0x00, 0x01, 0x00 -- 2.41.0