summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--com32/include/syslinux/loadfile.h2
-rw-r--r--com32/lib/sys/fileread.c2
-rw-r--r--com32/lib/sys/vesa/background.c14
-rw-r--r--com32/lib/syslinux/loadfile.c91
-rw-r--r--comboot.inc1
-rw-r--r--doc/comboot.doc4
6 files changed, 77 insertions, 37 deletions
diff --git a/com32/include/syslinux/loadfile.h b/com32/include/syslinux/loadfile.h
index fbda589d..c565cc9a 100644
--- a/com32/include/syslinux/loadfile.h
+++ b/com32/include/syslinux/loadfile.h
@@ -2,11 +2,13 @@
#define LIBUTIL_LOADFILE_H
#include <stddef.h>
+#include <stdio.h>
/* loadfile() returns the true size of the file, but will guarantee valid,
zero-padded memory out to this boundary. */
#define LOADFILE_ZERO_PAD 64
int loadfile(const char *, void **, size_t *);
+int floadfile(FILE *, void **, size_t *, const void *, size_t);
#endif
diff --git a/com32/lib/sys/fileread.c b/com32/lib/sys/fileread.c
index fe20e64b..5e528b19 100644
--- a/com32/lib/sys/fileread.c
+++ b/com32/lib/sys/fileread.c
@@ -65,7 +65,7 @@ ssize_t __file_read(struct file_info *fp, void *buf, size_t count)
}
fp->i.filedes = oreg.esi.w[0];
- fp->i.nbytes = min(fp->i.length-fp->i.offset, (unsigned)MAXBLOCK);
+ fp->i.nbytes = oreg.ecx.l;
fp->i.datap = fp->i.buf;
memcpy(fp->i.buf, __com32.cs_bounce, fp->i.nbytes);
}
diff --git a/com32/lib/sys/vesa/background.c b/com32/lib/sys/vesa/background.c
index 3bdda208..f141a6ae 100644
--- a/com32/lib/sys/vesa/background.c
+++ b/com32/lib/sys/vesa/background.c
@@ -33,6 +33,7 @@
#include <stdlib.h>
#include <sys/stat.h>
#include <minmax.h>
+#include <syslinux/loadfile.h>
#include "vesa.h"
#include "video.h"
@@ -172,19 +173,16 @@ static int jpeg_sig_cmp(uint8_t *bytes, int len)
static int read_jpeg_file(FILE *fp, uint8_t *header, int len)
{
struct jdec_private *jdec = NULL;
- unsigned char *jpeg_file = NULL;
- size_t length_of_file = filesize(fp);
+ void *jpeg_file = NULL;
+ size_t length_of_file;
unsigned int width, height;
int rv = -1;
unsigned char *components[1];
unsigned int bytes_per_row[1];
- jpeg_file = malloc(length_of_file);
- if (!jpeg_file)
- goto err;
-
- memcpy(jpeg_file, header, len);
- if (fread(jpeg_file+len, 1, length_of_file-len, fp) != length_of_file-len)
+ rv = floadfile(fp, &jpeg_file, &length_of_file, header, len);
+ fclose(fp);
+ if (rv)
goto err;
jdec = tinyjpeg_init();
diff --git a/com32/lib/syslinux/loadfile.c b/com32/lib/syslinux/loadfile.c
index ec7a6039..f5479dab 100644
--- a/com32/lib/syslinux/loadfile.c
+++ b/com32/lib/syslinux/loadfile.c
@@ -25,45 +25,84 @@
#include <syslinux/loadfile.h>
+#define INCREMENTAL_CHUNK 1024*1024
+
int loadfile(const char *filename, void **ptr, size_t *len)
{
- int fd;
- struct stat st;
- void *data;
FILE *f;
- size_t xlen;
+ int rv;
- fd = open(filename, O_RDONLY);
- if ( fd < 0 )
+ f = fopen(filename, "r");
+ if ( !f )
return -1;
- f = fdopen(fd, "rb");
- if ( !f ) {
- close(fd);
- return -1;
- }
+ rv = floadfile(f, ptr, len, NULL, 0);
+ fclose(f);
- if ( fstat(fd, &st) )
- goto err_fclose;
+ return rv;
+}
- *len = st.st_size;
- xlen = (st.st_size + LOADFILE_ZERO_PAD-1) & ~(LOADFILE_ZERO_PAD-1);
+int floadfile(FILE *f, void **ptr, size_t *len, const void *prefix,
+ size_t prefix_len)
+{
+ struct stat st;
+ void *data, *dp;
+ size_t alen, clen, rlen, xlen;
- *ptr = data = malloc(xlen);
- if ( !data )
- goto err_fclose;
+ clen = alen = 0;
+ data = NULL;
- if ( (off_t)fread(data, 1, st.st_size, f) != st.st_size )
- goto err_free;
+ if ( fstat(fileno(f), &st) )
+ goto err;
- memset((char *)data + st.st_size, 0, xlen-st.st_size);
+ if (!S_ISREG(st.st_mode)) {
+ /* Not a regular file, we can't assume we know the file size */
+ if (prefix_len) {
+ clen = alen = prefix_len;
+ data = malloc(prefix_len);
+ if (!data)
+ goto err;
- fclose(f);
+ memcpy(data, prefix, prefix_len);
+ }
+
+ do {
+ alen += INCREMENTAL_CHUNK;
+ dp = realloc(data, alen);
+ if (!dp)
+ goto err;
+ data = dp;
+
+ rlen = fread((char *)data+clen, 1, alen-clen, f);
+ clen += rlen;
+ } while (clen == alen);
+
+ *len = clen;
+ xlen = (clen + LOADFILE_ZERO_PAD-1) & ~(LOADFILE_ZERO_PAD-1);
+ dp = realloc(data, xlen);
+ if (dp)
+ data = dp;
+ *ptr = data;
+ } else {
+ *len = clen = st.st_size + prefix_len - ftell(f);
+ xlen = (clen + LOADFILE_ZERO_PAD-1) & ~(LOADFILE_ZERO_PAD-1);
+
+ *ptr = data = malloc(xlen);
+ if ( !data )
+ return -1;
+
+ memcpy(data, prefix, prefix_len);
+
+ if ( (off_t)fread((char *)data+prefix_len, 1, clen-prefix_len, f)
+ != clen-prefix_len )
+ goto err;
+ }
+
+ memset((char *)data + clen, 0, xlen-clen);
return 0;
- err_free:
- free(data);
- err_fclose:
- fclose(f);
+ err:
+ if (data)
+ free(data);
return -1;
}
diff --git a/comboot.inc b/comboot.inc
index 7c0f40f7..646f44d6 100644
--- a/comboot.inc
+++ b/comboot.inc
@@ -425,6 +425,7 @@ comapi_read:
jnc .noteof
xor si,si ; SI <- 0 on EOF, CF <- 0
.noteof: mov P_SI,si
+ mov P_ECX,ecx
ret
;
diff --git a/doc/comboot.doc b/doc/comboot.doc
index c4e303af..41dfb9fe 100644
--- a/doc/comboot.doc
+++ b/doc/comboot.doc
@@ -315,7 +315,7 @@ AX=0007h [2.08] Read file
ES:BX buffer
CX number of blocks to read
Output: SI file handle, or 0 if EOF was reached
- EAX number of bytes read [3.70]
+ ECX number of bytes read [3.70]
Read blocks from a file. Note that the file handle that is
returned in SI may not be the same value that was passed in.
@@ -323,7 +323,7 @@ AX=0007h [2.08] Read file
If end of file was reached (SI=0), the file was automatically
closed.
- In 3.70 or later, EAX returns the number of bytes read. This
+ In 3.70 or later, ECX returns the number of bytes read. This
will always be a multiple of the block size unless EOF is
reached.