[syslinux] isohybrid boot from logical partition

Martin Str|mberg ams at ludd.ltu.se
Sat Mar 18 00:20:31 PDT 2017


Thomas Schmitt said:
> I am wondering about the meaning or reason of "+20" in this assembler line:
> 
>   movl    (32+20)(%si), %ecx
> 
> Why that extra offset 20 on the byte offset 32 which is specified by
> GPT specs (UEFI 2.4, 5.3.3) ? (Do i get the language wrong ?)

Well I've been looking at this. It seems gptmbr.S
(<http://git.zytor.com/syslinux/syslinux.git/tree/mbr/gptmbr.S>)
builds up a fake MBR GPT protective entry in memory at offset
0x1be (lines 196-212) and then puts the bootable GPT entry directly
after (lines 191, 217). The comments says so. The comments aren't
clear about also adding the GPT entry length between the MBR and GPT
entries. That's four more bytes. So 16+4=20.

I think si points at the fake MBR entry at the insruction you ask
about.


But isohdpfx.S is buggy:
	/* Check to see if we have a partition table entry */
	xorl	%ebx, %ebx
	xorl	%ecx, %ecx
#ifdef PARTITION_SUPPORT
	andw	%si, %si		/* %si == 0 -> no partition data */
	jz	1f
	testb	$0x7f, (%si)		/* Invalid active flag field? */
	jnz	1f
	cmpb	%cl, 4(%si)		/* Partition type zero == invalid? */
	je	1f
	cmpl	$0x58504721, %eax	/* !GPT signature in EAX? */
	jne	2f
	cmpb	$0xed, 4(%si)		/* EFI partition type? */
	jne	2f
	
	/* We have GPT partition information */
	movl	(32+20)(%si), %ecx
	movl	(36+20)(%si), %ebx
	jmp	1f

	/* We have non-GPT partition information */
2:
	movl	8(%si), %ecx
#endif
1:
	/* We have no partition information */
	pushl	%ebx			/*  -4: partoffset_hi */
	pushl	%ecx			/*  -8: partoffset_lo */
	pushw	%es			/* -10: es:di -> $PnP header */
	pushw	%di			/* -12: es:di -> $PnP header */

	movw	%bp, %ds
	movw	%bp, %es
	
	ADJUST_DRIVE
	pushw	%dx			/* -14: dl -> drive number */

	/* Copy down to 0:0x600 */
	movw	$0x7c00, %si
	movw	$_start, %di
	movw	$(512/2), %cx
	rep; movsw

	ljmpw	$0, $next
next:

	/* Check to see if we have EBIOS */
	pushw	%dx		/* drive number */
	movb	$0x41, %ah	/* %al == 0 already */

Here it claims that al is zero. This is not true. Especially if you
look at the line that says "cmpl    $0x58504721, %eax" earlier. That
code is looking for a signature in eax! ADJUST_DRIVE marco doesn't
touch al.

So "movb    $0x41, %ah" should be "movw    $0x4100, %ax".


Also besides the 16/32 confusion in gptmbr.S there's more weirdness
that looks like a bug:

	/* Check to see if we have EBIOS */
	pushw	%dx		/* drive number */
	movb	$0x41, %ah	/* %al == 0 already */
	movw	$0x55aa, %bx
	xorw	%cx, %cx
	xorb	%dh, %dh
	stc
	int	$0x13
	popw	%dx		/* restore drive */
	movb	$0x08, %ah	/* get CHS geometry */
	jc	1f
	cmpw	$0xaa55, %bx
	jne	1f
	shrw	%cx		/* Bit 0 = fixed disk subset */
	jnc	1f

	/* We have EBIOS; patch in the following code at
	   read_sector_cbios: movb $0x42, %ah ;  jmp read_common */
	movl	$0xeb42b4+((read_common-read_sector_cbios-4) << 24), \
		(read_sector_cbios)

	/*
	 * read sector size.
	 * Should not fail but if it does I assume that at least
	 * previous 512 value is not overridden
	 */
	movb	$0x48, %ah
	movw	%sp, %si

1:
	/* Get (C)HS geometry */
	int	$0x13


Assuming the check EBIOS call failed and returned carry, ah will be 1
(according to RBIL) so this last int 0x13 will execute "INT 13 - DISK
- GET STATUS OF LAST OPERATION" not "INT 13 - DISK - GET DRIVE
PARAMETERS" which is called with ah=8, which I think was the
intention.

Similarly if any other condition that are checked for a successful
EBIOS check fails, this int 0x13 will be called with rubbish.


I'd change the last lines to:

	movw	%sp, %si
	jmp	2f
	
1:
	mov	$8, %ah

2:
	/* Get (C)HS geometry */
	int	$0x13


-- 
MartinS


More information about the Syslinux mailing list