[syslinux:pathbased] Implement !GPT protocol in Syslinux core; handle offset > 2 TB

syslinux-bot for H. Peter Anvin hpa at linux.intel.com
Mon Jun 14 15:42:17 PDT 2010


Commit-ID:  441798c66ea1b7d065d819c1af6a8c799d38036e
Gitweb:     http://syslinux.zytor.com/commit/441798c66ea1b7d065d819c1af6a8c799d38036e
Author:     H. Peter Anvin <hpa at linux.intel.com>
AuthorDate: Mon, 14 Jun 2010 15:38:35 -0700
Committer:  H. Peter Anvin <hpa at linux.intel.com>
CommitDate: Mon, 14 Jun 2010 15:41:37 -0700

Implement !GPT protocol in Syslinux core; handle offset > 2 TB

Implement the !GPT handover protocol in the Syslinux core, and handle
partition offsets above 2 TB.  We do not yet handle filesystem sizes
above 2 TB, but that should be a reasonably straightforward extension
at this time (need to switch to 8-byte block pointers).

This finally meant moving getlinsec out of the boot sector, since it
no longer fits.  Instead have a very simple getonesec implementation
in the boot sector.  getlinsec still fits in Sector 1, although it
doesn't leave space for very many block pointers.  That's still better
than adding yet another boot loader stage, however.

Signed-off-by: H. Peter Anvin <hpa at linux.intel.com>


---
 core/diskstart.inc      |  467 +++++++++++++++++++++++++++++------------------
 extlinux/main.c         |    7 +-
 libinstaller/syslxint.h |    6 +-
 libinstaller/syslxmod.c |   15 +-
 4 files changed, 301 insertions(+), 194 deletions(-)

diff --git a/core/diskstart.inc b/core/diskstart.inc
index f249d7c..b4086c5 100644
--- a/core/diskstart.inc
+++ b/core/diskstart.inc
@@ -17,11 +17,13 @@
 ; Common early-bootstrap code for harddisk-based Syslinux derivatives.
 ;
 
-		; Expanded superblock
 		section .earlybss
-		alignb 8
-SuperInfo	resq 16			; The first 16 bytes expanded 8 times
-DriveNumber	resb 1
+		alignb 16
+PartInfo:				; Partition table info
+.mbr:		resb 16			; MBR partition info
+.gptlen:	resd 1
+.gpt:		resb 92
+FloppyTable	resb 16			; Floppy info table (must follow PartInfo)
 
 		section .init
 ;
@@ -29,12 +31,12 @@ DriveNumber	resb 1
 ; "close" to the initial stack pointer offset, in order to
 ; reduce the code size...
 ;
-StackBuf	equ STACK_TOP-44-32	; Start the stack here (grow down - 4K)
-PartInfo	equ StackBuf		; Saved partition table entry
-FloppyTable	equ PartInfo+16		; Floppy info table (must follow PartInfo)
-OrigFDCTabPtr	equ StackBuf-8		; The 2nd high dword on the stack
-OrigESDI	equ StackBuf-4		; The high dword on the stack
-StackHome	equ OrigFDCTabPtr	; The start of the canonical stack
+StackBuf	equ STACK_TOP-44	; Start the stack here (grow down - 4K)
+Hidden		equ StackBuf-20		; Partition offset
+OrigFDCTabPtr	equ StackBuf-12		; The 2nd high dword on the stack
+OrigESDI	equ StackBuf-8		; The high dword on the stack
+DriveNumber	equ StackBuf-4		; Drive number
+StackHome	equ Hidden		; The start of the canonical stack
 
 ;
 ; Primary entry point.  Tempting as though it may be, we can't put the
@@ -98,6 +100,7 @@ superblock_max	equ $-superblock
 
 		global SecPerClust
 SecPerClust	equ bxSecPerClust
+
 ;
 ; Note we don't check the constraints above now; we did that at install
 ; time (we hope!)
@@ -108,20 +111,24 @@ start:
 ;
 ; Set up the stack
 ;
-		xor ax,ax
-		mov ss,ax
-		mov sp,StackBuf		; Just below BSS
+		xor cx,cx
+		mov ss,cx
+		mov sp,StackBuf-2	; Just below BSS (-2 for alignment)
+		push dx			; Save drive number (in DL)
 		push es			; Save initial ES:DI -> $PnP pointer
 		push di
-		mov es,ax
+		mov es,cx
+
 ;
-; DS:SI may contain a partition table entry.  Preserve it for us.
+; DS:SI may contain a partition table entry and possibly a GPT entry.
+; Preserve it for us.  This saves 92 bytes of the GPT entry, which is
+; currently the maximum we care about.
 ;
-		mov cx,8		; Save partition info
+		mov cl,(16+4+92)/2	; Save partition info
 		mov di,PartInfo
-		rep movsw
+		rep movsw		; This puts CX back to zero
 
-		mov ds,ax		; Now we can initialize DS...
+		mov ds,cx		; Now we can initialize DS...
 
 ;
 ; Now sautee the BIOS floppy info block to that it will support decent-
@@ -138,12 +145,12 @@ start:
 
 		; Save the old fdctab even if hard disk so the stack layout
 		; is the same.  The instructions above do not change the flags
-		mov [DriveNumber],dl	; Save drive number in DL
 		and dl,dl		; If floppy disk (00-7F), assume no
 					; partition table
 		js harddisk
 
 floppy:
+		xor ax,ax
 		mov cl,6		; 12 bytes (CX == 0)
 		; es:di -> FloppyTable already
 		; This should be safe to do now, interrupts are off...
@@ -151,25 +158,34 @@ floppy:
 		mov [bx+2],ax		; Segment 0
 		fs rep movsw		; Faster to move words
 		mov cl,[bsSecPerTrack]  ; Patch the sector count
-		mov [di-8],cl
-		; AX == 0 here
+		mov [di-112+8],cl
 		int 13h			; Some BIOSes need this
 
+		push cx			; Partition offset == 0
+		push cx
+		push cx
+		push cx
 		jmp short not_harddisk
 ;
 ; The drive number and possibly partition information was passed to us
 ; by the BIOS or previous boot loader (MBR).  Current "best practice" is to
 ; trust that rather than what the superblock contains.
 ;
-; Would it be better to zero out bsHidden if we don't have a partition table?
-;
 ; Note: di points to beyond the end of PartInfo
 ;
 harddisk:
-		test byte [di-16],7Fh	; Sanity check: "active flag" should
+		test byte [di-112],7Fh	; Sanity check: "active flag" should
 		jnz no_partition	; be 00 or 80
-		mov eax,[di-8]		; Partition offset (dword)
-		mov [bsHidden],eax
+		cmp eax,'!GPT'		; !GPT signature?
+		jne .not_gpt
+		push dword [di-112+20+36]
+		push dword [di-112+20+32]
+		jmp .gotoffs
+.not_gpt:
+		push cx			; Upper half partition offset == 0
+		push cx
+		push dword [di-112+8]	; Partition offset (dword)
+.gotoffs:
 no_partition:
 ;
 ; Get disk drive parameters (don't trust the superblock.)  Don't do this for
@@ -211,7 +227,7 @@ eddcheck:
 		;
 		; We have EDD support...
 		;
-		mov byte [getlinsec.jmp+1],(getlinsec_ebios-(getlinsec.jmp+2))
+		mov byte [getonesec.jmp+1],(getonesec_ebios-(getonesec.jmp+2))
 .noedd:
 
 ;
@@ -228,79 +244,45 @@ eddcheck:
 		jne kaboom
 
 		; Go for it...
-		jmp ldlinux_ent
+		jmp 0:ldlinux_ent
 
-;
-; getonesec: get one disk sector
-;
-getonesec:
-		mov bp,1		; One sector
-		; Fall through
 
 ;
-; getlinsec: load a sequence of BP floppy sector given by the linear sector
-;	     number in EAX into the buffer at ES:BX.  We try to optimize
-;	     by loading up to a whole track at a time, but the user
-;	     is responsible for not crossing a 64K boundary.
-;	     (Yes, BP is weird for a count, but it was available...)
+; getonesec: load a single disk linear sector EDX:EAX into the buffer
+;	     at ES:BX.
 ;
-;	     On return, BX points to the first byte after the transferred
-;	     block.
-;
-;            This routine assumes CS == DS, and trashes most registers.
+;            This routine assumes CS == DS == SS, and trashes most registers.
 ;
 ; Stylistic note: use "xchg" instead of "mov" when the source is a register
 ; that is dead from that point; this saves space.  However, please keep
 ; the order to dst,src to keep things sane.
 ;
-		global getlinsec
-getlinsec:
-		add eax,[bsHidden]		; Add partition offset
-		xor edx,edx			; Zero-extend LBA (eventually allow 64 bits)
-
-.jmp:		jmp strict short getlinsec_cbios
+getonesec:
+		xor edx,edx			; Assume 32-bit partition size
+		add eax,[Hidden]		; Add partition offset
+		adc edx,[Hidden+4]
+		mov cx,retry_count
+.jmp:		jmp strict short getonesec_cbios
 
 ;
-; getlinsec_ebios:
+; getonesec_ebios:
 ;
-; getlinsec implementation for EBIOS (EDD)
+; getonesec implementation for EBIOS (EDD)
 ;
-getlinsec_ebios:
-.loop:
-                push bp                         ; Sectors left
-.retry2:
-		call maxtrans			; Enforce maximum transfer size
-		movzx edi,bp			; Sectors we are about to read
-		mov cx,retry_count
+getonesec_ebios:
 .retry:
-
 		; Form DAPA on stack
 		push edx
 		push eax
 		push es
 		push bx
-		push di
+		push word 1
 		push word 16
 		mov si,sp
-		pushad
-                mov dl,[DriveNumber]
-		push ds
-		push ss
-		pop ds				; DS <- SS
                 mov ah,42h                      ; Extended Read
-		int 13h
-		pop ds
-		popad
+		call xint13
 		lea sp,[si+16]			; Remove DAPA
 		jc .error
-		pop bp
-		add eax,edi			; Advance sector pointer
-		sub bp,di			; Sectors left
-                shl di,SECTOR_SHIFT		; 512-byte sectors
-                add bx,di			; Advance buffer pointer
-                and bp,bp
-                jnz .loop
-
                 ret
 
 .error:
@@ -311,32 +293,21 @@ getlinsec_ebios:
 
 		pushad				; Try resetting the device
 		xor ax,ax
-		mov dl,[DriveNumber]
 		int 13h
 		popad
 		loop .retry			; CX-- and jump if not zero
 
-		;shr word [MaxTransfer],1	; Reduce the transfer size
-		;jnz .retry2
-
 		; Total failure.  Try falling back to CBIOS.
-		mov byte [getlinsec.jmp+1],(getlinsec_cbios-(getlinsec.jmp+2))
-		;mov byte [MaxTransfer],63	; Max possibe CBIOS transfer
-
-		pop bp
-		; ... fall through ...
+		mov byte [getonesec.jmp+1],(getonesec_cbios-(getonesec.jmp+2))
 
 ;
-; getlinsec_cbios:
+; getonesec_cbios:
 ;
 ; getlinsec implementation for legacy CBIOS
 ;
-getlinsec_cbios:
-.loop:
-		push edx
-		push eax
-		push bp
-		push bx
+getonesec_cbios:
+.retry:
+		pushad
 
 		movzx esi,word [bsSecPerTrack]
 		movzx edi,word [bsHeads]
@@ -357,19 +328,8 @@ getlinsec_cbios:
 
 		;
 		; Now we have AX = cyl, DX = head, CX = sector (0-based),
-		; BP = sectors to transfer, SI = bsSecPerTrack,
-		; ES:BX = data target
+		; SI = bsSecPerTrack, ES:BX = data target
 		;
-
-		call maxtrans			; Enforce maximum transfer size
-
-		; Must not cross track boundaries, so BP <= SI-CX
-		sub si,cx
-		cmp bp,si
-		jna .bp_ok
-		mov bp,si
-.bp_ok:
-
 		shl ah,6		; Because IBM was STOOPID
 					; and thought 8 bits were enough
 					; then thought 10 bits were enough...
@@ -377,35 +337,14 @@ getlinsec_cbios:
 		or cl,ah
 		mov ch,al
 		mov dh,dl
-		mov dl,[DriveNumber]
-		xchg ax,bp		; Sector to transfer count
-		mov ah,02h		; Read sectors
-		mov bp,retry_count
-.retry:
-		pushad
-		int 13h
-		popad
+		mov ax,0201h		; Read one sector
+		call xint13
 		jc .error
-.resume:
-		movzx ecx,al		; ECX <- sectors transferred
-		shl ax,SECTOR_SHIFT	; Convert sectors in AL to bytes in AX
-		pop bx
-		add bx,ax
-		pop bp
-		pop eax
-		pop edx
-		add eax,ecx
-		sub bp,cx
-		jnz .loop
 		ret
 
 .error:
-		dec bp
-		jnz .retry
-
-		xchg ax,bp		; Sectors transferred <- 0
-		shr word [MaxTransfer],1
-		jnz .resume
+		popad
+		loop .retry
 		; Fall through to disk_error
 
 ;
@@ -421,42 +360,51 @@ kaboom:
 		pop dword [fdctab]	; Restore FDC table
 .patch:					; When we have full code, intercept here
 		mov si,bailmsg
+		call writestr_early
+
+		xor ax,ax
+.again:		int 16h			; Wait for keypress
+					; NB: replaced by int 18h if
+					; chosen at install time..
+		int 19h			; And try once more to boot...
+.norge:		jmp short .norge	; If int 19h returned; this is the end
 
-		; Write error message, this assumes screen page 0
+;
+;
+; writestr_early: write a null-terminated string to the console
+;	    This assumes we're on page 0.  This is only used for early
+;           messages, so it should be OK.
+;
+writestr_early:
+		pushad
 .loop:		lodsb
 		and al,al
-                jz .done
+                jz .return
 		mov ah,0Eh		; Write to screen as TTY
 		mov bx,0007h		; Attribute
 		int 10h
 		jmp short .loop
-.done:
-		cbw			; AH <- 0
-.again:		int 16h			; Wait for keypress
-					; NB: replaced by int 18h if
-					; chosen at install time..
-		int 19h			; And try once more to boot...
-.norge:		jmp short .norge	; If int 19h returned; this is the end
+.return:	popad
+		ret
 
 ;
-; Truncate BP to MaxTransfer
+; INT 13h wrapper function
 ;
-maxtrans:
-		cmp bp,[MaxTransfer]
-		jna .ok
-		mov bp,[MaxTransfer]
-.ok:		ret
+xint13:
+                mov dl,[DriveNumber]
+		pushad
+		int 13h
+		popad
+		ret
 
 ;
 ; Error message on failure
 ;
 bailmsg:	db 'Boot error', 0Dh, 0Ah, 0
 
-		; This fails if the boot sector overflows
-		zb 1F8h-($-$$)
-
+		; This fails if the boot sector overflowsg
+		zb 1FAh-($-$$)
 FirstSector	dd 0xDEADBEEF			; Location of sector 1
-MaxTransfer	dw 0x007F			; Max transfer size
 
 ; This field will be filled in 0xAA55 by the installer, but we abuse it
 ; to house a pointer to the INT 16h instruction at
@@ -493,6 +441,7 @@ ADVSectors	dw 0		; Additional sectors for ADVs
 LDLDwords	dd 0		; Total dwords starting at ldlinux_sys,
 CheckSum	dd 0		; Checksum starting at ldlinux_sys
 				; value = LDLINUX_MAGIC - [sum of dwords]
+MaxTransfer	dw 127		; Max sectors to transfer
 CurrentDirPtr	dw CurrentDirName-LDLINUX_SYS	; Current directory name string
 CurrentDirLen	dw CURRENTDIR_MAX
 SubvolPtr	dw SubvolName-LDLINUX_SYS
@@ -519,8 +468,6 @@ ldlinux_ent:
 ; value in CS, but we don't want to deal with that anymore from now
 ; on.
 ;
-		jmp 0:.next
-.next:
 		sti		; In case of broken INT 13h BIOSes
 
 ;
@@ -530,13 +477,26 @@ ldlinux_ent:
 		call writestr_early
 
 ;
+; Checksum data thus far
+;
+		mov si,ldlinux_sys
+		mov cx,SECTOR_SIZE >> 2
+		mov edx,-LDLINUX_MAGIC
+.checksum:
+		lodsd
+		add edx,eax
+		loop .checksum
+		mov [CheckSum],edx		; Save intermediate result
+
+;
 ; Tell the user if we're using EBIOS or CBIOS
 ;
 print_bios:
 		mov si,cbios_name
-		cmp byte [getlinsec.jmp+1],(getlinsec_ebios-(getlinsec.jmp+2))
+		cmp byte [getonesec.jmp+1],(getonesec_ebios-(getonesec.jmp+2))
 		jne .cbios
 		mov si,ebios_name
+		mov byte [getlinsec.jmp+1],(getlinsec_ebios-(getlinsec.jmp+2))
 .cbios:
 		mov [BIOSName],si
 		call writestr_early
@@ -547,8 +507,7 @@ BIOSName	resw 1
 
 		section .init
 ;
-; Now we read the rest of LDLINUX.SYS.	Don't bother loading the first
-; sector again, though.
+; Now we read the rest of LDLINUX.SYS.
 ;
 load_rest:
 		lea esi,[SectorPtrs]
@@ -568,7 +527,7 @@ load_rest:
 		inc bp
 		dec cx
 		jz .chunk_ready
-		cmp ebx,esi			; Pointer we don't have yet?
+		cmp esi,ebx			; Pointer we don't have yet?
 		jae .chunk_ready
 		inc edx				; Next linear sector
 		cmp [si],edx			; Does it match
@@ -584,7 +543,7 @@ load_rest:
 		mov es,bx
 		xor bx,bx
 		xor edx,edx			; Zero-extend LBA
-		call getlinsecsr
+		call getlinsec
 		pop es
 		pop ebx
 		shl ebp,SECTOR_SHIFT
@@ -599,9 +558,10 @@ load_rest:
 ; by the time we get to the end it should all cancel out.
 ;
 verify_checksum:
-		mov si,ldlinux_sys
+		mov si,ldlinux_sys + SECTOR_SIZE
 		mov ecx,[LDLDwords]
-		mov eax,-LDLINUX_MAGIC
+		sub ecx,SECTOR_SIZE >> 2
+		mov eax,[CheckSum]
 		push ds
 .checksum:
 		add eax,[si]
@@ -631,37 +591,179 @@ verify_checksum:
 ; Subroutines that have to be in the first sector
 ; -----------------------------------------------------------------------------
 
+
+
 ;
+; getlinsec: load a sequence of BP floppy sector given by the linear sector
+;	     number in EAX into the buffer at ES:BX.  We try to optimize
+;	     by loading up to a whole track at a time, but the user
+;	     is responsible for not crossing a 64K boundary.
+;	     (Yes, BP is weird for a count, but it was available...)
 ;
-; writestr_early: write a null-terminated string to the console
-;	    This assumes we're on page 0.  This is only used for early
-;           messages, so it should be OK.
+;	     On return, BX points to the first byte after the transferred
+;	     block.
 ;
-writestr_early:
+;            This routine assumes CS == DS.
+;
+		global getlinsec
+getlinsec:
 		pushad
-.loop:		lodsb
-		and al,al
-                jz .return
-		mov ah,0Eh		; Write to screen as TTY
-		mov bx,0007h		; Attribute
-		int 10h
-		jmp short .loop
-.return:	popad
-		ret
+		xor edx,edx			; For now only 32-bit internal
+		add eax,[Hidden]		; Add partition offset
+		adc edx,[Hidden+4]
+.jmp:		jmp strict short getlinsec_cbios
 
+;
+; getlinsec_ebios:
+;
+; getlinsec implementation for EBIOS (EDD)
+;
+getlinsec_ebios:
+.loop:
+                push bp                         ; Sectors left
+.retry2:
+		call maxtrans			; Enforce maximum transfer size
+		movzx edi,bp			; Sectors we are about to read
+		mov cx,retry_count
+.retry:
+
+		; Form DAPA on stack
+		push edx
+		push eax
+		push es
+		push bx
+		push di
+		push word 16
+		mov si,sp
+                mov ah,42h                      ; Extended Read
+		push ds
+		push ss
+		pop ds
+		call xint13
+		pop ds
+		lea sp,[si+16]			; Remove DAPA
+		jc .error
+		pop bp
+		add eax,edi			; Advance sector pointer
+		adc edx,0
+		sub bp,di			; Sectors left
+                shl di,SECTOR_SHIFT		; 512-byte sectors
+                add bx,di			; Advance buffer pointer
+                and bp,bp
+                jnz .loop
+
+		popad
+                ret
+
+.error:
+		; Some systems seem to get "stuck" in an error state when
+		; using EBIOS.  Doesn't happen when using CBIOS, which is
+		; good, since some other systems get timeout failures
+		; waiting for the floppy disk to spin up.
+
+		pushad				; Try resetting the device
+		xor ax,ax
+		mov dl,[DriveNumber]
+		int 13h
+		popad
+		loop .retry			; CX-- and jump if not zero
+
+		;shr word [MaxTransfer],1	; Reduce the transfer size
+		;jnz .retry2
+
+		; Total failure.  Try falling back to CBIOS.
+		mov byte [getlinsec.jmp+1],(getlinsec_cbios-(getlinsec.jmp+2))
+		;mov byte [MaxTransfer],63	; Max possibe CBIOS transfer
+
+		pop bp
+		; ... fall through ...
 
 ;
-; getlinsecsr: save registers, call getlinsec, restore registers
-;	       Save/restore the flags, too, especially IF.
+; getlinsec_cbios:
 ;
-getlinsecsr:	
-		pushfd
-		pushad
-		call getlinsec
+; getlinsec implementation for legacy CBIOS
+;
+getlinsec_cbios:
+.loop:
+		push edx
+		push eax
+		push bp
+		push bx
+
+		movzx esi,word [bsSecPerTrack]
+		movzx edi,word [bsHeads]
+		;
+		; Dividing by sectors to get (track,sector): we may have
+		; up to 2^18 tracks, so we need to use 32-bit arithmetric.
+		;
+		div esi
+		xor cx,cx
+		xchg cx,dx		; CX <- sector index (0-based)
+					; EDX <- 0
+		; eax = track #
+		div edi			; Convert track to head/cyl
+
+		; We should test this, but it doesn't fit...
+		; cmp eax,1023
+		; ja .error
+
+		;
+		; Now we have AX = cyl, DX = head, CX = sector (0-based),
+		; BP = sectors to transfer, SI = bsSecPerTrack,
+		; ES:BX = data target
+		;
+
+		call maxtrans			; Enforce maximum transfer size
+
+		; Must not cross track boundaries, so BP <= SI-CX
+		sub si,cx
+		cmp bp,si
+		jna .bp_ok
+		mov bp,si
+.bp_ok:
+
+		shl ah,6		; Because IBM was STOOPID
+					; and thought 8 bits were enough
+					; then thought 10 bits were enough...
+		inc cx			; Sector numbers are 1-based, sigh
+		or cl,ah
+		mov ch,al
+		mov dh,dl
+		xchg ax,bp		; Sector to transfer count
+		mov ah,02h		; Read sectors
+		mov bp,retry_count
+.retry:
+		call xint13
+		jc .error
+.resume:
+		movzx ecx,al		; ECX <- sectors transferred
+		shl ax,SECTOR_SHIFT	; Convert sectors in AL to bytes in AX
+		pop bx
+		add bx,ax
+		pop bp
+		pop eax
+		pop edx
+		add eax,ecx
+		sub bp,cx
+		jnz .loop
 		popad
-		popfd
 		ret
 
+.error:
+		dec bp
+		jnz .retry
+
+		xchg ax,bp		; Sectors transferred <- 0
+		shr word [MaxTransfer],1
+		jnz .resume
+		jmp kaboom
+
+maxtrans:
+		cmp bp,[MaxTransfer]
+		jna .ok
+		mov bp,[MaxTransfer]
+.ok:		ret
+
 ;
 ; Checksum error message
 ;
@@ -739,12 +841,15 @@ expand_super:
 		mov eax,ROOT_FS_OPS
 		movzx dx,byte [DriveNumber]
 		; DH = 0: we are boot from disk not CDROM
-		mov ecx,[bsHidden]
-		; Reserved for upper 32 bits of partition offset...
-		; mov ebx,[bsHidden+4]
-		xor ebx,ebx
+		mov ecx,[Hidden]
+		mov ebx,[Hidden+4]
 		mov si,[bsHeads]
 		mov di,[bsSecPerTrack]
 		movzx ebp,word [MaxTransfer]
 		pm_call fs_init
 		popad
+
+		section .bss16
+SuperInfo	resq 16			; The first 16 bytes expanded 8 times
+
+		section .text16
diff --git a/extlinux/main.c b/extlinux/main.c
index c76add4..0a55692 100644
--- a/extlinux/main.c
+++ b/extlinux/main.c
@@ -314,9 +314,6 @@ int patch_file_and_bootblock(int fd, const char *dir, int devfd)
 
     /* First sector need pointer in boot sector */
     set_32(&bs->NextSector, *sectp++);
-    /* Stupid mode? */
-    if (opt.stupid_mode)
-	set_16(&bs->MaxTransfer, 1);
 
     /* Search for LDLINUX_MAGIC to find the patch area */
     for (wp = (uint32_t *) boot_image; get_32(wp) != LDLINUX_MAGIC; wp++) ;
@@ -328,6 +325,10 @@ int patch_file_and_bootblock(int fd, const char *dir, int devfd)
     set_16(&patcharea->adv_sectors, 2);
     set_32(&patcharea->dwords, dw);
 
+    /* Stupid mode? */
+    if (opt.stupid_mode)
+	set_16(&patcharea->maxtransfer, 1);
+
     /* Set the sector pointers */
     secptroffset = get_16(&patcharea->secptroffset);
     wp = (uint32_t *) ((char *)boot_image + secptroffset);
diff --git a/libinstaller/syslxint.h b/libinstaller/syslxint.h
index 2276bfe..bc818df 100644
--- a/libinstaller/syslxint.h
+++ b/libinstaller/syslxint.h
@@ -87,6 +87,7 @@ struct patch_area {
     uint16_t adv_sectors;
     uint32_t dwords;
     uint32_t checksum;
+    uint16_t maxtransfer;
     uint16_t diroffset;
     uint16_t dirlen;
     uint16_t subvoloffset;
@@ -120,7 +121,7 @@ struct boot_sector {
 	    uint32_t VolumeID;
 	    char VolumeLabel[11];
 	    char FileSysType[8];
-	    uint8_t Code[442];
+	    uint8_t Code[444];
 	} __attribute__ ((packed)) bs16;
 	struct {
 	    uint32_t FATSz32;
@@ -136,12 +137,11 @@ struct boot_sector {
 	    uint32_t VolumeID;
 	    char VolumeLabel[11];
 	    char FileSysType[8];
-	    uint8_t Code[414];
+	    uint8_t Code[416];
 	} __attribute__ ((packed)) bs32;
     } __attribute__ ((packed));
 
     uint32_t NextSector;	/* Pointer to the first unused sector */
-    uint16_t MaxTransfer;	/* Max sectors per transfer */
     uint16_t bsSignature;
 } __attribute__ ((packed));
 
diff --git a/libinstaller/syslxmod.c b/libinstaller/syslxmod.c
index 96f155f..c600a81 100644
--- a/libinstaller/syslxmod.c
+++ b/libinstaller/syslxmod.c
@@ -1,7 +1,7 @@
 /* ----------------------------------------------------------------------- *
  *
  *   Copyright 1998-2008 H. Peter Anvin - All Rights Reserved
- *   Copyright 2009 Intel Corporation; author H. Peter Anvin
+ *   Copyright 2009-2010 Intel Corporation; author H. Peter Anvin
  *
  *   This program is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -241,12 +241,7 @@ int syslinux_patch(const uint32_t * sectors, int nsectors,
     if (nsectors < nsect)
 	return -1;
 
-    /* Patch in options, as appropriate */
-    if (stupid) {
-	/* Access only one sector at a time */
-	set_16(&sbs->MaxTransfer, 1);
-    }
-
+    /* Handle RAID mode, write proper bsSignature */
     i = get_16(&sbs->bsSignature);
     if (raid_mode)
 	set_16((uint16_t *) ((char *)sbs + i), 0x18CD);	/* INT 18h */
@@ -277,6 +272,12 @@ int syslinux_patch(const uint32_t * sectors, int nsectors,
 	memcpy((char *)boot_image + diroffset, subdir, strlen(subdir) + 1);
     }
 
+    /* Handle Stupid mode */
+    if (stupid) {
+	/* Access only one sector at a time */
+	set_16(&patcharea->maxtransfer, 1);
+    }
+
     /* Set the sector pointers */
     wp = (uint32_t *) ((char *)boot_image +
 		       get_16_sl(&patcharea->secptroffset));



More information about the Syslinux-commits mailing list