aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2009-05-21 15:36:50 -0700
committerH. Peter Anvin <hpa@zytor.com>2009-05-21 15:36:50 -0700
commite462c28ffaca0132c1761736bc93cb06a41dc7a6 (patch)
tree24edb9f85175bdd6cc30bf270f3e59571bca71ae
parentd4d9f190900d31b5e9428401a0175012957d7cb7 (diff)
downloadsyslinux-e462c28ffaca0132c1761736bc93cb06a41dc7a6.tar.gz
syslinux-e462c28ffaca0132c1761736bc93cb06a41dc7a6.tar.xz
syslinux-e462c28ffaca0132c1761736bc93cb06a41dc7a6.zip
isohybrid: support booting from partition; fix CBIOS booting
Fix CBIOS in isohybrid mode. Also allow an isohybrid image to be booted from a partition. Unfortunately this breaks compatibility between differing versions of isohybrid and isolinux.bin. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--core/isolinux.asm29
-rw-r--r--mbr/Makefile9
-rwxr-xr-xmbr/checksize.pl2
-rw-r--r--mbr/isohdpfx.S69
-rw-r--r--utils/Makefile3
-rw-r--r--utils/isohybrid.in13
6 files changed, 86 insertions, 39 deletions
diff --git a/core/isolinux.asm b/core/isolinux.asm
index cc97f479..b85ecd36 100644
--- a/core/isolinux.asm
+++ b/core/isolinux.asm
@@ -112,6 +112,8 @@ DiskError resb 1 ; Error code for disk I/O
DriveNumber resb 1 ; CD-ROM BIOS drive number
ISOFlags resb 1 ; Flags for ISO directory search
RetryCount resb 1 ; Used for disk access retries
+ alignb 8
+bsHidden resq 1 ; Used in hybrid mode
bsSecPerTrack resw 1 ; Used in hybrid mode
bsHeads resw 1 ; Used in hybrid mode
@@ -222,26 +224,31 @@ bi_end:
; Custom entry point for the hybrid-mode disk.
; The following values will have been pushed onto the
; entry stack:
- ; - CBIOS Heads
- ; - CBIOS Sectors
- ; - EBIOS flag
- ; - DX (including drive number)
- ; - DI
; - ES
+ ; - DI
+ ; - DX (including drive number)
+ ; - partition offset (qword)
+ ; - EBIOS flag
+ ; - CBIOS Sectors
+ ; - CBIOS Heads
; (top of stack)
+ ;
%ifndef DEBUG_MESSAGES
_hybrid_signature:
- dd 0x7078c0fb ; An arbitrary number...
-
+ dd 0x0defe3f7
_start_hybrid:
+ pop word [cs:bsHeads]
+ pop word [cs:bsSecPerTrack]
+
pop ax
mov si,bios_cbios
and ax,ax
jz .cbios
mov si,bios_ebios
.cbios:
- pop word [cs:bsSecPerTrack]
- pop word [cs:bsHeads]
+
+ pop dword [cs:bsHidden]
+ pop dword [cs:bsHidden+4]
pop dx
pop di
@@ -745,6 +752,8 @@ getlinsec_ebios:
xor edx,edx
shld edx,eax,2
shl eax,2 ; Convert to HDD sectors
+ add eax,[bsHidden]
+ adc edx,[bsHidden+4]
shl bp,2
.loop:
@@ -814,7 +823,9 @@ getlinsec_ebios:
; getlinsec implementation for legacy CBIOS
;
getlinsec_cbios:
+ xor edx,edx
shl eax,2 ; Convert to HDD sectors
+ add eax,[bsHidden]
shl bp,2
.loop:
diff --git a/mbr/Makefile b/mbr/Makefile
index 3140132a..c3eb97a7 100644
--- a/mbr/Makefile
+++ b/mbr/Makefile
@@ -18,11 +18,10 @@
topdir = ..
include $(topdir)/MCONFIG.embedded
-all: mbr.bin altmbr.bin gptmbr.bin isohdpfx.bin \
- mbr_c.bin altmbr_c.bin gptmbr_c.bin isohdpfx_c.bin \
- mbr_f.bin altmbr_f.bin gptmbr_f.bin isohdpfx_f.bin
+all: mbr.bin altmbr.bin gptmbr.bin isohdpfx.bin isohdppx.bin \
+ mbr_c.bin altmbr_c.bin gptmbr_c.bin isohdpfx_c.bin isohdppx_c.bin \
+ mbr_f.bin altmbr_f.bin gptmbr_f.bin isohdpfx_f.bin isohdppx_f.bin
-.PRECIOUS: %.o
%.o: %.S
$(CC) $(MAKEDEPS) $(SFLAGS) -Wa,-a=$*.lst -c -o $@ $<
@@ -50,3 +49,5 @@ clean: tidy
spotless: clean
rm -f *.bin
+
+-include .*.d
diff --git a/mbr/checksize.pl b/mbr/checksize.pl
index 4648c95c..7d61bdfd 100755
--- a/mbr/checksize.pl
+++ b/mbr/checksize.pl
@@ -27,7 +27,7 @@ if (!defined($maxsize)) {
$maxsize = $padsize = 440;
} elsif ($file =~ /^gptmbr[^0-9a-z]/) {
$maxsize = $padsize = 424;
- } elsif ($file =~ /^isohdpfx[^0-9a-z]/) {
+ } elsif ($file =~ /^isohdp[fp]x[^0-9a-z]/) {
$maxsize = $padsize = 432;
} elsif ($file =~ /^altmbr[^0-9a-z]/) {
$maxsize = 439; $padsize = 440;
diff --git a/mbr/isohdpfx.S b/mbr/isohdpfx.S
index f42b4b5b..53e1ed6b 100644
--- a/mbr/isohdpfx.S
+++ b/mbr/isohdpfx.S
@@ -39,7 +39,7 @@
.code16
.text
-HYBRID_MAGIC = 0x7078c0fb
+HYBRID_MAGIC = 0x0defe3f7
isolinux_hybrid_signature = 0x7c00+64
isolinux_start_hybrid = 0x7c00+64+4
@@ -47,10 +47,11 @@ isolinux_start_hybrid = 0x7c00+64+4
/* Important: the top 6 words on the stack are passed to isolinux.bin */
stack = 0x7c00
driveno = (stack-6)
-ebios_flag = (stack-8)
-sectors = (stack-10)
-heads = (stack-12)
-secpercyl = (stack-16)
+partoffset = (stack-14)
+ebios_flag = (stack-16)
+sectors = (stack-18)
+heads = (stack-20)
+secpercyl = (stack-24)
BIOS_kbdflags = 0x417
BIOS_page = 0x462
@@ -66,18 +67,47 @@ bootsec:
_start:
cli
- xorw %ax, %ax
- movw %ax, %ds
- movw %ax, %ss
+ xorw %bx, %bx
+ movw %bx, %ds
+ movw %bx, %ss
movw $stack, %sp
- movw %sp, %si
- pushw %es /* es:di -> $PnP header */
+ pushw %es /* -4: es:di -> $PnP header */
pushw %di
- movw %ax, %es
+ movw %bx, %es
sti
cld
+ ADJUST_DRIVE
+ pushw %dx /* -6: dl -> drive number */
+
+ /* Check to see if we have a partition table entry */
+#ifdef PARTITION_SUPPORT
+ andw %si, %si /* %si == 0 -> no partition data */
+ jz 1f
+ testb $0x7f, (%si) /* Invalid active flag field? */
+ jnz 1f
+ cmpl $0x58504721, %eax /* !GPT signature in EAX? */
+ jne 2f
+ cmpb $0xee, 4(%si) /* EFI partition type? */
+ jne 2f
+ /* We have GPT partition information */
+ pushl (36+16)(%si) /* -10: partoffset_hi */
+ pushl (32+16)(%si) /* -14: partoffset_lo */
+ jmp 3f
+2:
+ /* We have non-GPT partition information */
+ pushl $0 /* -10: partoffset_hi */
+ pushl 8(%si) /* -14: partoffset_lo */
+ jmp 3f
+#endif
+1:
+ /* We have no partition information */
+ pushl $0 /* -10: partoffset_hi */
+ pushl $0 /* -14: partoffset_lo */
+3:
+
/* Copy down to 0:0x600 */
+ movw $0x7c00, %si
movw $_start, %di
movw $(512/2), %cx
rep; movsw
@@ -85,9 +115,6 @@ _start:
ljmpw $0, $next
next:
- ADJUST_DRIVE
- pushw %dx /* dl -> drive number */
-
/* Check to see if we have EBIOS */
pushw %dx /* drive number */
movb $0x41, %ah /* %al == 0 already */
@@ -106,24 +133,24 @@ next:
read_sector_cbios: movb $0x42, %ah ; jmp read_common */
movl $0xeb42b4+((read_common-read_sector_cbios-4) << 24), \
(read_sector_cbios)
-
+ jmp 1f
1:
popw %dx
- pushw %cx /* Save EBIOS flag */
+ pushw %cx /* -16: Save EBIOS flag */
/* Get (C)HS geometry */
movb $0x08, %ah
int $0x13
andw $0x3f, %cx /* Sector count */
- pushw %cx /* Save sectors on the stack */
+ pushw %cx /* -18: Save sectors on the stack */
movzbw %dh, %ax /* dh = max head */
incw %ax /* From 0-based max to count */
- pushw %ax /* Save heads on the stack */
+ pushw %ax /* -20: Save heads on the stack */
mulw %cx /* Heads*sectors -> sectors per cylinder */
/* Save sectors/cylinder on the stack */
- pushw %dx /* High word */
- pushw %ax /* Low word */
+ pushw %dx /* -22: High word */
+ pushw %ax /* -24: Low word */
/*
* Load sectors. We do this one at a time mostly to avoid
@@ -169,6 +196,8 @@ bad_signature:
read_sector:
pushal
xorl %edx, %edx
+ addl (partoffset), %eax
+ adcl (partoffset+4), %edx
pushl %edx /* MSW of LBA */
pushl %eax /* LSW of LBA */
pushw %es /* Buffer segment */
diff --git a/utils/Makefile b/utils/Makefile
index 7670bef6..9df9595a 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -23,7 +23,8 @@ LDFLAGS = -O2 -s
TARGETS = mkdiskimage isohybrid gethostip
ASIS = keytab-lilo lss16toppm md5pass ppmtolss16 sha1pass syslinux2ansi
-ISOHDPFX = ../mbr/isohdpfx.bin ../mbr/isohdpfx_f.bin ../mbr/isohdpfx_c.bin
+ISOHDPFX = ../mbr/isohdpfx.bin ../mbr/isohdpfx_f.bin ../mbr/isohdpfx_c.bin \
+ ../mbr/isohdppx.bin ../mbr/isohdppx_f.bin ../mbr/isohdppx_c.bin
all: $(TARGETS)
diff --git a/utils/isohybrid.in b/utils/isohybrid.in
index 2bbaada4..b3a502bc 100644
--- a/utils/isohybrid.in
+++ b/utils/isohybrid.in
@@ -43,6 +43,7 @@ use Fcntl;
'type' => [0, 255],
'id' => [0, 0xffffffff],
'hd0' => [0, 2],
+ 'partok' => [0, 1],
);
# Boolean options just set other options
@@ -50,6 +51,8 @@ use Fcntl;
'nohd0' => ['hd0', 0],
'forcehd0' => ['hd0', 1],
'ctrlhd0' => ['hd0', 2],
+ 'nopartok' => ['partok', 0],
+ 'partok' => ['partok', 1],
);
sub usage() {
@@ -63,6 +66,7 @@ sub usage() {
" -id Specify MBR ID (default random)\n",
" -forcehd0 Always assume we are loaded as disk ID 0\n",
" -ctrlhd0 Assume disk ID 0 if the Ctrl key is pressed\n",
+ " -partok Allow booting from within a partition\n";
exit 1;
}
@@ -161,9 +165,10 @@ if ($de_boot != 0x88 || $de_media != 0 ||
# Now $de_lba should contain the CD sector number for isolinux.bin
seek(FILE, $de_lba*2048+0x40, SEEK_SET) or die "$0: $file: $!\n";
read(FILE, $ibsig, 4);
-if ($ibsig ne "\xfb\xc0\x78\x70") {
- die "$0: $file: bootloader is missing isolinux.bin hybrid signature\n".
- "Note: isolinux-debug.bin does not support hybrid booting\n";
+if ($ibsig ne "\xf7\xe3\xef\x0d") {
+ die "$0: $file: bootloader is missing current (3.81+) isolinux.bin\n".
+ " hybrid signature; Note that isolinux-debug.bin does not\n".
+ " support hybrid booting.\n";
}
# Get the total size of the image
@@ -202,7 +207,7 @@ if (defined($opt{'id'})) {
# Print the MBR and partition table
seek(FILE, 0, SEEK_SET) or die "$0: $file: $!\n";
-for ($i = 0; $i <= $opt{'hd0'}; $i++) {
+for ($i = 0; $i <= $opt{'hd0'}+3*$opt{'partok'}; $i++) {
$mbr = get_hex_data();
}
if ( length($mbr) > 432 ) {