From: H. Peter Anvin Date: Thu, 21 May 2009 22:36:50 +0000 (-0700) Subject: isohybrid: support booting from partition; fix CBIOS booting X-Git-Tag: syslinux-3.81-pre10~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e462c28ffaca0132c1761736bc93cb06a41dc7a6;p=platform%2Fupstream%2Fsyslinux.git 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 --- diff --git a/core/isolinux.asm b/core/isolinux.asm index cc97f47..b85ecd3 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 3140132..c3eb97a 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 4648c95..7d61bdf 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 f42b4b5..53e1ed6 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 7670bef..9df9595 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 2bbaada..b3a502b 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 ) {