From: H. Peter Anvin Date: Wed, 27 Feb 2008 20:40:31 +0000 (-0800) Subject: Comboot/Com32 changes for unspecified file lengths X-Git-Tag: syslinux-3.70-pre1~6 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=48722c47bbdcfe51e905e87ec0d34415506393c5;p=profile%2Fivi%2Fsyslinux.git Comboot/Com32 changes for unspecified file lengths Handle unspecified file length for comboot/com32 modules; do changes to the appropriate part of libcom32 to handle this properly. --- diff --git a/com32/include/syslinux/loadfile.h b/com32/include/syslinux/loadfile.h index fbda589..c565cc9 100644 --- a/com32/include/syslinux/loadfile.h +++ b/com32/include/syslinux/loadfile.h @@ -2,11 +2,13 @@ #define LIBUTIL_LOADFILE_H #include +#include /* 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 fe20e64..5e528b1 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 3bdda20..f141a6a 100644 --- a/com32/lib/sys/vesa/background.c +++ b/com32/lib/sys/vesa/background.c @@ -33,6 +33,7 @@ #include #include #include +#include #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 ec7a603..f5479da 100644 --- a/com32/lib/syslinux/loadfile.c +++ b/com32/lib/syslinux/loadfile.c @@ -25,45 +25,84 @@ #include +#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 7c0f40f..646f44d 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 c4e303a..41dfb9f 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.