[syslinux:pathbased] core: rewrite loadhigh in C

syslinux-bot for H. Peter Anvin hpa at zytor.com
Sun Feb 21 17:54:10 PST 2010


Commit-ID:  741ed6fa8609b0a8ce1fa9b1abc27916326b95f9
Gitweb:     http://syslinux.zytor.com/commit/741ed6fa8609b0a8ce1fa9b1abc27916326b95f9
Author:     H. Peter Anvin <hpa at zytor.com>
AuthorDate: Sun, 21 Feb 2010 17:53:23 -0800
Committer:  H. Peter Anvin <hpa at zytor.com>
CommitDate: Sun, 21 Feb 2010 17:53:23 -0800

core: rewrite loadhigh in C

Rewrite the loadhight function in C, and eliminate double usage of
xfer_buf_seg.

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


---
 core/fs/loadhigh.c |  113 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 core/loadhigh.inc  |   70 ++++----------------------------
 2 files changed, 121 insertions(+), 62 deletions(-)

diff --git a/core/fs/loadhigh.c b/core/fs/loadhigh.c
new file mode 100644
index 0000000..e365b1a
--- /dev/null
+++ b/core/fs/loadhigh.c
@@ -0,0 +1,113 @@
+/*
+ * -----------------------------------------------------------------------
+ *
+ *   Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
+ *   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
+ *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ *   Boston MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * loadhigh.c
+ *
+ * An alternate interface to getfssec.
+ *
+ * Inputs:	SI  = file handle/cluster pointer
+ *		EDI = target address in high memory
+ *		EAX = maximum number of bytes to load
+ *		DX  = zero-padding mask (e.g. 0003h for pad to dword)
+ *		BX  = 16-bit subroutine to call at the top of each loop
+ *                    (to print status and check for abort)
+ *		EBP = maximum load address
+ *
+ * Outputs:	SI  = file handle/cluster pointer
+ *		EBX = first untouched address (not including padding)
+ *		EDI = first untouched address (including padding)
+ *		CF  = reached EOF
+ *		OF  = ran out of high memory
+ */
+
+#include <com32.h>
+#include <minmax.h>
+#include "core.h"
+#include "fs.h"
+
+#define MAX_CHUNK	(1 << 20) /* 1 MB */
+
+void pm_load_high(com32sys_t *regs)
+{
+    struct fs_info *fs;
+    uint32_t bytes;
+    uint32_t zero_mask;
+    bool have_more;
+    uint32_t bytes_read;
+    char *buf, *limit;
+    struct file *file;
+    uint32_t sector_mask;
+    size_t pad;
+
+    bytes     = regs->eax.l;
+    zero_mask = regs->edx.w[0];
+    buf       = (char *)regs->edi.l;
+    limit     = (char *)(regs->ebp.l & ~zero_mask);
+    file      = handle_to_file(regs->esi.w[0]);
+    fs        = file->fs;
+
+    regs->eflags.l &= ~(EFLAGS_CF|EFLAGS_OF|EFLAGS_AF|
+			EFLAGS_PF|EFLAGS_ZF|EFLAGS_SF);
+
+    sector_mask = SECTOR_SIZE(fs) - 1;
+
+    while (bytes) {
+	uint32_t sectors;
+	uint32_t chunk;
+
+	if (buf + SECTOR_SIZE(fs) > limit) {
+	    /* Can't fit even one more sector in... */
+	    regs->eflags.l |= EFLAGS_OF;
+	    break;
+	}
+
+	chunk = bytes;
+
+	if (regs->ebx.w[0]) {
+	    call16((void (*)(void))(size_t)regs->ebx.w[0], &zero_regs, NULL);
+	    chunk = min(chunk, MAX_CHUNK);
+	}
+
+	if (chunk > (((char *)limit - buf) & ~sector_mask))
+	    chunk = ((char *)limit - buf) & ~sector_mask;
+
+	sectors = (chunk + sector_mask) >> SECTOR_SHIFT(fs);
+	bytes_read = fs->fs_ops->getfssec(file, buf, sectors, &have_more);
+
+	if (bytes_read > chunk)
+	    bytes_read = chunk;
+
+	buf += bytes_read;
+	bytes -= bytes_read;
+
+	if (!have_more) {
+	    /*
+	     * If we reach EOF, the filesystem driver will have already closed
+	     * the underlying file... this really should be cleaner.
+	     */
+	    _close_file(file);
+	    regs->esi.w[0] = 0;
+	    regs->eflags.l |= EFLAGS_CF;
+	    break;
+	}
+    }
+
+    pad = (size_t)buf & zero_mask;
+    if (pad)
+	memset(buf, 0, pad);
+
+    regs->ebx.l = (size_t)buf;
+    regs->edi.l = (size_t)buf + pad;
+}
diff --git a/core/loadhigh.inc b/core/loadhigh.inc
index 205c3e6..89de5e8 100644
--- a/core/loadhigh.inc
+++ b/core/loadhigh.inc
@@ -1,7 +1,7 @@
 ;; -----------------------------------------------------------------------
 ;;
 ;;   Copyright 1994-2009 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
@@ -21,83 +21,29 @@
 
 ;
 ; load_high:	loads (the remainder of) a file into high memory.
-;		This routine prints dots for each 64K transferred, and
-;		calls abort_check periodically.
-;
-;		The xfer_buf_seg is used as a bounce buffer.
 ;
 ;		Assumes CS == DS.
 ;
-;		The input address (EDI) should be dword aligned, and the final
-;		stretch is padded with zeroes if necessary.
-;
 ; Inputs:	SI  = file handle/cluster pointer
 ;		EDI = target address in high memory
 ;		EAX = maximum number of bytes to load
 ;		DX  = zero-padding mask (e.g. 0003h for pad to dword)
 ;		BX  = subroutine to call at the top of each loop
 ;                     (to print status and check for abort)
-;		MyHighMemSize = maximum load address
+;		[MyHighMemSize] = maximum load address
 ;
 ; Outputs:	SI  = file handle/cluster pointer
 ;		EBX = first untouched address (not including padding)
 ;		EDI = first untouched address (including padding)
 ;		CF  = reached EOF
 ;
+		extern pm_load_high
 load_high:
-		push es				; <AAA> ES
-
-		mov cx,xfer_buf_seg
-		mov es,cx
-		mov [PauseBird],bx
-
-.read_loop:
-		and si,si			; If SI == 0 then we have end of file
-		jz .eof
-		call [PauseBird]
-
-		push eax			; <A> Total bytes to transfer
-		cmp eax,(1 << 16)		; Max 64K in one transfer
-		jna .size_ok
-		mov eax,(1 << 16)
-.size_ok:
-		push eax			; <B> Bytes transferred this chunk
-		add eax,SECTOR_SIZE-1
-		shr eax,SECTOR_SHIFT		; Convert to sectors
-
-		; Now (e)ax contains the number of sectors to get
-		push edi			; <C> Target buffer
-		mov cx,ax
-		xor bx,bx			; ES:0
-		pm_call getfssec			; Load the data into xfer_buf_seg
-		pop edi				; <C> Target buffer
-		pushf				; <C> EOF status
-		lea ebx,[edi+ecx]		; End of data
-.fix_slop:
-		test cx,dx
-		jz .noslop
-		; The last dword fractional - pad with zeroes
-		; Zero-padding is critical for multi-file initramfs.
-		mov byte [es:ecx],0
-		inc cx
-		jmp short .fix_slop
-.noslop:
-		lea eax,[edi+ecx]
-		cmp eax,[MyHighMemSize]
-		ja .overflow
-
-		push esi			; <D> File handle/cluster pointer
-		mov esi,core_xfer_buf		; Source address
-		call bcopy			; Copy to high memory
-		pop esi				; <D> File handle/cluster pointer
-		popf				; <C> EOF status
-		pop ecx				; <B> Byte count this round
-		pop eax				; <A> Total bytes to transfer
-		jc .eof
-		sub eax,ecx
-		jnz .read_loop			; More to read... (if ZF=1 then CF=0)
-.eof:
-		pop es				; <AAA> ES
+		push ebp
+		mov ebp,[MyHighMemSize]
+		pm_call pm_load_high
+		pop ebp
+		jo .overflow
 		ret
 
 .overflow:	mov si,err_nohighmem



More information about the Syslinux-commits mailing list