diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2013-01-17 21:02:18 -0800 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2013-01-17 21:03:53 -0800 |
commit | 02b09a09186a36381b3cbceb484d836745cd2b63 (patch) | |
tree | 43f820200e6b4628900dce98bd4d71353ef9dbc3 | |
parent | 238ca24e867c74aabe97544b35b8dabb3dc26594 (diff) | |
download | syslinux-02b09a09186a36381b3cbceb484d836745cd2b63.tar.gz syslinux-02b09a09186a36381b3cbceb484d836745cd2b63.tar.xz syslinux-02b09a09186a36381b3cbceb484d836745cd2b63.zip |
slzm: Syslinux compressed modules
Use ELF compressed into a custom lzo container. The reason for not
using the standard lzop container is that we are doing one-shot
decompression anyway, and by having the appropriate information in the
header we can manage memory better.
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | com32/cmenu/Makefile | 2 | ||||
-rw-r--r-- | com32/hdt/Makefile | 2 | ||||
-rw-r--r-- | com32/include/sys/module.h | 5 | ||||
-rw-r--r-- | com32/include/syslinux/slzm.h | 57 | ||||
-rw-r--r-- | com32/lib/Makefile | 4 | ||||
-rw-r--r-- | com32/lib/sys/module/common.c | 123 | ||||
-rw-r--r-- | com32/lib/sys/module/elf_module.c | 31 | ||||
-rw-r--r-- | com32/lua/src/Makefile | 6 | ||||
-rw-r--r-- | com32/rosh/Makefile | 2 | ||||
-rw-r--r-- | com32/samples/Makefile | 2 | ||||
-rw-r--r-- | core/lzo/lzoif.c | 46 | ||||
-rw-r--r-- | lzo/.gitignore | 1 | ||||
-rw-r--r-- | lzo/Makefile | 5 | ||||
-rw-r--r-- | lzo/mkmodule.c | 370 | ||||
-rw-r--r-- | mk/devel.mk | 2 | ||||
-rw-r--r-- | mk/elf.mk | 11 | ||||
-rw-r--r-- | mk/lib.mk | 4 | ||||
-rw-r--r-- | mk/syslinux.mk | 2 |
19 files changed, 602 insertions, 75 deletions
@@ -57,7 +57,7 @@ BOBJECTS = $(BTARGET) \ # Note: libinstaller is both a BSUBDIR and an ISUBDIR. It contains # files that depend only on the B phase, but may have to be regenerated # for "make installer". -BSUBDIRS = codepage com32 lzo core memdisk mbr memdump gpxe sample \ +BSUBDIRS = lzo codepage com32 core memdisk mbr memdump gpxe sample \ diag libinstaller dos win32 win64 dosutil ITARGET = IOBJECTS = $(ITARGET) \ diff --git a/com32/cmenu/Makefile b/com32/cmenu/Makefile index d51b2e84..7b9e72c8 100644 --- a/com32/cmenu/Makefile +++ b/com32/cmenu/Makefile @@ -29,7 +29,7 @@ CFLAGS += -I./libmenu LIBMENU = libmenu/syslnx.o libmenu/com32io.o libmenu/tui.o \ libmenu/menu.o libmenu/passwords.o libmenu/des.o libmenu/help.o \ - $(com32)/libutil/libutil.c32 $(com32)/lib/libcom32.c32 + $(com32)/libutil/libutil.elf $(com32)/lib/libcom32.elf CMENUS = $(patsubst %.c,%.c32,$(wildcard *.c)) IMENUS = $(patsubst %.menu,%.c32,$(wildcard *.menu)) diff --git a/com32/hdt/Makefile b/com32/hdt/Makefile index 42f5c0d1..b4df63a9 100644 --- a/com32/hdt/Makefile +++ b/com32/hdt/Makefile @@ -20,7 +20,7 @@ MAKEDIR = $(topdir)/mk include $(MAKEDIR)/elf.mk LIBS = ../libupload/libcom32upload.a -C_LIBS += $(com32)/cmenu/libmenu/libmenu.c32 +C_LIBS += $(com32)/cmenu/libmenu/libmenu.elf CFLAGS += -I$(com32)/cmenu/libmenu -I$(com32) MODULES = hdt.c32 diff --git a/com32/include/sys/module.h b/com32/include/sys/module.h index a18561a9..095f3948 100644 --- a/com32/include/sys/module.h +++ b/com32/include/sys/module.h @@ -109,8 +109,9 @@ struct elf_module { union { // Transient - Data available while the module is loading struct { - FILE *_file; // The file object of the open file - Elf32_Off _cr_offset; // The current offset in the open file + void *buf; // Buffer to data + size_t len; // Length of data + size_t cr_offset; // The current offset } l; // Process execution data diff --git a/com32/include/syslinux/slzm.h b/com32/include/syslinux/slzm.h new file mode 100644 index 00000000..9f069833 --- /dev/null +++ b/com32/include/syslinux/slzm.h @@ -0,0 +1,57 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2013 Intel Corporation; author: H. Peter Anvin + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * slzm.h + * + * Syslinux compressed header format + */ +#ifndef _SYSLINUX_SLZM_H +#define _SYSLINUX_SLZM_H + +#include <inttypes.h> + +#define SLZM_MAGIC1 0xcd4cfdb8 +#define SLZM_MAGIC2 0x464c4521 +/* Need to be smarter about these... */ +#define SLZM_PLATFORM 1 /* PC-BIOS */ +#define SLZM_ARCH 3 /* EM_386 */ +#define SLZM_MINVER 0x501 +#define SLZM_MAXVER 0x5ff + +struct slzm_header { + uint32_t magic[2]; + uint16_t platform; + uint16_t arch; + uint16_t minversion; + uint16_t maxversion; + uint32_t zsize; + uint32_t usize; + uint32_t resv[6]; +}; + +#endif /* _SYSLINUX_SLZM_H */ diff --git a/com32/lib/Makefile b/com32/lib/Makefile index d979ab43..7bedc22e 100644 --- a/com32/lib/Makefile +++ b/com32/lib/Makefile @@ -60,7 +60,7 @@ LIBLOAD_OBJS = \ syslinux/run_default.o syslinux/run_command.o \ syslinux/cleanup.o syslinux/localboot.o syslinux/runimage.o \ \ - syslinux/loadfile.o syslinux/floadfile.o syslinux/zloadfile.o \ + syslinux/loadfile.o syslinux/zloadfile.o \ \ syslinux/load_linux.o syslinux/initramfs.o \ syslinux/initramfs_file.o syslinux/initramfs_loadfile.o \ @@ -81,10 +81,10 @@ LIBENTRY_OBJS = \ dprintf.o vdprintf.o \ \ syslinux/idle.o \ - \ exit.o LIBMODULE_OBJS = \ + syslinux/floadfile.o \ sys/module/common.o sys/module/elf_module.o \ sys/module/elfutils.o \ sys/module/exec.o diff --git a/com32/lib/sys/module/common.c b/com32/lib/sys/module/common.c index deb2bcc8..1daa533e 100644 --- a/com32/lib/sys/module/common.c +++ b/com32/lib/sys/module/common.c @@ -9,6 +9,8 @@ #include <elf.h> #include <string.h> #include <fs.h> +#include <syslinux/loadfile.h> +#include <syslinux/slzm.h> #include <linux/list.h> #include <sys/module.h> @@ -16,6 +18,10 @@ #include "elfutils.h" #include "common.h" +__extern int lzo1x_decompress_fast_safe(const void *src, unsigned int src_len, + void *dst, unsigned int *dst_len, + void *wrkmem); + /** * The one and only list of loaded modules */ @@ -103,71 +109,120 @@ again: int image_load(struct elf_module *module) { - module->u.l._file = findpath(module->name); + void *zdata, *mdata; + size_t zlen, mlen; + const struct slzm_header *hdr; + FILE *f; + int zr; + int rv = -1; + + zdata = mdata = NULL; + f = NULL; + + memset(&module->u.l, 0, sizeof module->u.l); + + f = findpath(module->name); - if (module->u.l._file == NULL) { - DBG_PRINT("Could not open object file '%s'\n", module->name); + if (!f) { + DBG_PRINT("Could not open module file '%s'\n", module->name); goto error; } - module->u.l._cr_offset = 0; + if (floadfile(f, &zdata, &zlen, NULL, 0)) { + DBG_PRINT("Could not read module file '%s'\n", module->name); + goto error; + } - return 0; + fclose(f); + f = NULL; -error: - if (module->u.l._file != NULL) { - fclose(module->u.l._file); - module->u.l._file = NULL; + hdr = zdata; + if (zlen < sizeof *hdr) { + dprintf("%s: file too short\n", module->name); + goto error; } - return -1; -} + zlen -= sizeof *hdr; + if (hdr->magic[0] != SLZM_MAGIC1 || hdr->magic[1] != SLZM_MAGIC2 || + hdr->platform != SLZM_PLATFORM || hdr->arch != SLZM_ARCH || + zlen < hdr->zsize) { + dprintf("%s: bad header\n", module->name); + goto error; + } -int image_unload(struct elf_module *module) { - if (module->u.l._file != NULL) { - fclose(module->u.l._file); - module->u.l._file = NULL; + mlen = hdr->usize + 15; + mdata = malloc(mlen); + if (!mdata) { + dprintf("%s: failed to allocate mdata buffer\n", + module->name); + goto error; + } + + zr = lzo1x_decompress_fast_safe((const char *)zdata + sizeof *hdr, + hdr->zsize, mdata, &mlen, NULL); + if (zr) { + dprintf("%s: decompression returned error %d\n", + module->name, zr); + goto error; + } + if (mlen != hdr->usize) { + dprintf("%s: decompression returned %zu bytes expected %u\n", + module->name, mlen, hdr->usize); + goto error; } - module->u.l._cr_offset = 0; + module->u.l.buf = mdata; + module->u.l.len = mlen; + mdata = NULL; /* Don't free */ + rv = 0; + +error: + if (mdata) + free(mdata); + if (zdata) + free(zdata); + if (f) + fclose(f); + + return rv; +} + + +int image_unload(struct elf_module *module) { + if (module->u.l.buf) { + free(module->u.l.buf); + memset(&module->u.l, 0, sizeof module->u.l); + } return 0; } int image_read(void *buff, size_t size, struct elf_module *module) { - size_t result = fread(buff, size, 1, module->u.l._file); - - if (result < 1) + if (size > module->u.l.len - module->u.l.cr_offset) return -1; - module->u.l._cr_offset += size; + memcpy(buff, (const char *)module->u.l.buf + module->u.l.cr_offset, + size); + + module->u.l.cr_offset += size; return 0; } int image_skip(size_t size, struct elf_module *module) { - void *skip_buff = NULL; - size_t result; - - if (size == 0) - return 0; - - skip_buff = malloc(size); - result = fread(skip_buff, size, 1, module->u.l._file); - free(skip_buff); - - if (result < 1) + if (size > module->u.l.len - module->u.l.cr_offset) return -1; - module->u.l._cr_offset += size; + module->u.l.cr_offset += size; return 0; } int image_seek(Elf32_Off offset, struct elf_module *module) { - if (offset < module->u.l._cr_offset) // Cannot seek backwards + if (offset >= module->u.l.len) // Cannot seek backwards return -1; - return image_skip(offset - module->u.l._cr_offset, module); + module->u.l.cr_offset = offset; + return 0; } diff --git a/com32/lib/sys/module/elf_module.c b/com32/lib/sys/module/elf_module.c index 24da2209..391be484 100644 --- a/com32/lib/sys/module/elf_module.c +++ b/com32/lib/sys/module/elf_module.c @@ -132,28 +132,15 @@ static int load_segments(struct elf_module *module, Elf32_Ehdr *elf_hdr) { if (cr_pht->p_type == PT_LOAD) { // Copy the segment at its destination - if (cr_pht->p_offset < module->u.l._cr_offset) { - // The segment contains data before the current offset - // It can be discarded without worry - it would contain only - // headers - Elf32_Off aux_off = module->u.l._cr_offset - cr_pht->p_offset; - - if (image_read((char *)module_get_absolute(cr_pht->p_vaddr, module) + aux_off, - cr_pht->p_filesz - aux_off, module) < 0) { - res = -1; - goto out; - } - } else { - if (image_seek(cr_pht->p_offset, module) < 0) { - res = -1; - goto out; - } - - if (image_read(module_get_absolute(cr_pht->p_vaddr, module), - cr_pht->p_filesz, module) < 0) { - res = -1; - goto out; - } + if (image_seek(cr_pht->p_offset, module) < 0) { + res = -1; + goto out; + } + + if (image_read(module_get_absolute(cr_pht->p_vaddr, module), + cr_pht->p_filesz, module) < 0) { + res = -1; + goto out; } /* diff --git a/com32/lua/src/Makefile b/com32/lua/src/Makefile index d70d23ea..b412af1d 100644 --- a/com32/lua/src/Makefile +++ b/com32/lua/src/Makefile @@ -25,12 +25,12 @@ LNXLIBS = #GCCWARN += -Wno-error CFLAGS += -DSYSLINUX -MODULES = lua.c32 +MODULES = lua.c32 liblua.c32 TESTFILES = OBJS = lua.o -LIBLUA = liblua.c32 +LIBLUA = liblua.elf LIBLUA_OBJS := lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o LIBLUA_OBJS += lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o @@ -50,7 +50,7 @@ CFLAGS += -DLUA_ANSI all: $(MODULES) $(TESTFILES) -liblua.elf : $(LIBLUA_OBJS) +$(LIBLUA) : $(LIBLUA_OBJS) $(LD) $(LDFLAGS) -shared -soname $(patsubst %.elf,%.c32,$(@F)) \ -o $@ $^ diff --git a/com32/rosh/Makefile b/com32/rosh/Makefile index 5b54225b..f0aa9136 100644 --- a/com32/rosh/Makefile +++ b/com32/rosh/Makefile @@ -16,7 +16,7 @@ ## ROSH Read Only Shell ## -LIBS = $(com32)/libutil/libutil.c32 $(com32)/lib/libcom32.c32 +LIBS = $(com32)/libutil/libutil.elf $(com32)/lib/libcom32.elf topdir = ../.. MAKEDIR = $(topdir)/mk diff --git a/com32/samples/Makefile b/com32/samples/Makefile index f6ae00ab..781c1f91 100644 --- a/com32/samples/Makefile +++ b/com32/samples/Makefile @@ -14,7 +14,7 @@ ## samples for syslinux users ## -LIBS = $(com32)/libutil/libutil.c32 +LIBS = $(com32)/libutil/libutil.elf topdir = ../.. MAKEDIR = $(topdir)/mk diff --git a/core/lzo/lzoif.c b/core/lzo/lzoif.c new file mode 100644 index 00000000..187dd205 --- /dev/null +++ b/core/lzo/lzoif.c @@ -0,0 +1,46 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2013 Intel Corporation; author: H. Peter Anvin + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * core/lzo/lzoif.c + * + * This only applies to i386 platforms... + */ + +#include "core.h" + +extern int __attribute__((regparm(0))) +_lzo1x_decompress_asm_fast_safe(const void *src, unsigned int src_len, + void *dst, unsigned int *dst_len, + void *wrkmem); + +__export int lzo1x_decompress_fast_safe(const void *src, unsigned int src_len, + void *dst, unsigned int *dst_len, + void *wrkmem) +{ + return _lzo1x_decompress_asm_fast_safe(src, src_len, dst, dst_len, wrkmem); +} diff --git a/lzo/.gitignore b/lzo/.gitignore index 04202daf..910ffde2 100644 --- a/lzo/.gitignore +++ b/lzo/.gitignore @@ -1 +1,2 @@ /prepcore +/mkmodule diff --git a/lzo/Makefile b/lzo/Makefile index cf8f985a..fe4311d3 100644 --- a/lzo/Makefile +++ b/lzo/Makefile @@ -18,7 +18,7 @@ INCLUDES += -I./include LIBOBJS = $(patsubst %.c,%.o,$(wildcard src/*.c)) LIB = lzo.a -BINS = prepcore +BINS = prepcore mkmodule all : $(BINS) @@ -30,6 +30,9 @@ $(LIB) : $(LIBOBJS) prepcore : prepcore.o $(LIB) $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) +mkmodule : mkmodule.o $(LIB) + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + tidy dist clean spotless: rm -f $(BINS) rm -f *.o *.a .*.d diff --git a/lzo/mkmodule.c b/lzo/mkmodule.c new file mode 100644 index 00000000..9524b32d --- /dev/null +++ b/lzo/mkmodule.c @@ -0,0 +1,370 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009-2013 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., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + This file is based in part on: + + precomp2.c -- example program: how to generate pre-compressed data + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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; either version 2 of + the License, or (at your option) any later version. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + <markus@oberhumer.com> + http://www.oberhumer.com/opensource/lzo/ + */ + +#include "lzo/lzoconf.h" +#include "lzo/lzo1x.h" +#include "../com32/include/syslinux/slzm.h" + +LZO_EXTERN(int) +lzo1x_999_compress_internal(const lzo_bytep in, lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem, + const lzo_bytep dict, lzo_uint dict_len, + lzo_callback_p cb, + int try_lazy, + lzo_uint good_length, + lzo_uint max_lazy, + lzo_uint nice_length, + lzo_uint max_chain, lzo_uint32 flags); + +LZO_EXTERN(int) +lzo1y_999_compress_internal(const lzo_bytep in, lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem, + const lzo_bytep dict, lzo_uint dict_len, + lzo_callback_p cb, + int try_lazy, + lzo_uint good_length, + lzo_uint max_lazy, + lzo_uint nice_length, + lzo_uint max_chain, lzo_uint32 flags); + +#define PARANOID 1 + +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <inttypes.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <time.h> + +#ifdef __GNUC__ +# define noreturn void __attribute__((noreturn)) +#else +# define noreturn void +#endif + +static inline uint16_t get_16(const uint16_t * p) +{ +#if defined(__i386__) || defined(__x86_64__) + /* Littleendian and unaligned-capable */ + return *p; +#else + const uint8_t *pp = (const uint8_t *)p; + return (uint16_t) pp[0] + ((uint16_t) pp[1] << 8); +#endif +} + +static inline void set_16(uint16_t * p, uint16_t v) +{ +#if defined(__i386__) || defined(__x86_64__) + /* Littleendian and unaligned-capable */ + *p = v; +#else + uint8_t *pp = (uint8_t *) p; + pp[0] = (v & 0xff); + pp[1] = ((v >> 8) & 0xff); +#endif +} + +static inline uint32_t get_32(const uint32_t * p) +{ +#if defined(__i386__) || defined(__x86_64__) + /* Littleendian and unaligned-capable */ + return *p; +#else + const uint8_t *pp = (const uint8_t *)p; + return (uint32_t) pp[0] + ((uint32_t) pp[1] << 8) + + ((uint32_t) pp[2] << 16) + ((uint32_t) pp[3] << 24); +#endif +} + +static inline void set_32(uint32_t * p, uint32_t v) +{ +#if defined(__i386__) || defined(__x86_64__) + /* Littleendian and unaligned-capable */ + *p = v; +#else + uint8_t *pp = (uint8_t *) p; + pp[0] = (v & 0xff); + pp[1] = ((v >> 8) & 0xff); + pp[2] = ((v >> 16) & 0xff); + pp[3] = ((v >> 24) & 0xff); +#endif +} + +const char *progname = NULL; +const char *in_name = NULL; +const char *out_name = NULL; + +static noreturn error(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + fprintf(stderr, "%s: ", progname); + if (in_name) + fprintf(stderr, "%s: ", in_name); + vfprintf(stderr, fmt, ap); + fputc('\n', stderr); + va_end(ap); + + exit(1); +} + +static void *xzalloc(size_t n) +{ + void *p = calloc(n, 1); + if (!p) + error("out of memory"); + return p; +} + +/************************************************************************* +// +**************************************************************************/ + +int main(int argc, char *argv[]) +{ + int r; + int lazy; + const int max_try_lazy = 5; + const lzo_uint big = 65536L; /* can result in very slow compression */ + const lzo_uint32 flags = 0x1; + + lzo_bytep infile; + lzo_uint infile_len; + + lzo_bytep out; + lzo_uint out_bufsize; + lzo_uint best_len, out_len = 0; + + lzo_bytep test; + + lzo_byte wrkmem[LZO1X_999_MEM_COMPRESS]; + + int best_lazy = -1; + + lzo_uint orig_len; + lzo_uint32 uncompressed_checksum; + lzo_uint32 compressed_checksum; + + FILE *f; + long l; + + struct slzm_header header; + + progname = argv[0]; + if (argc != 3) { + fprintf(stderr, "Usage: %s file output-file\n", progname); + exit(1); + } + in_name = argv[1]; + if (argc > 2) + out_name = argv[2]; + +/* + * Step 0: prepare the fixed part of the header + */ + memset(&header, 0, sizeof header); + set_32(&header.magic[0], SLZM_MAGIC1); + set_32(&header.magic[1], SLZM_MAGIC2); + set_16(&header.platform, SLZM_PLATFORM); + set_16(&header.arch, SLZM_ARCH); + set_16(&header.minversion, SLZM_MINVER); + set_16(&header.maxversion, SLZM_MAXVER); + +/* + * Step 1: initialize the LZO library + */ + if (lzo_init() != LZO_E_OK) + error("internal error - lzo_init() failed!"); + +/* + * Step 3: open the input file + */ + f = fopen(in_name, "rb"); + if (!f) + error("cannot open file: %s", strerror(errno)); + + fseek(f, 0, SEEK_END); + l = ftell(f); + fseek(f, 0, SEEK_SET); + if (l <= 0) { + error("empty file", progname, in_name); + fclose(f); + exit(1); + } + infile_len = (lzo_uint) l; + out_bufsize = infile_len + infile_len / 16 + 64 + 3 + 2048; + +/* + * Step 4: allocate compression buffers and read the file + */ + infile = xzalloc(infile_len); + out = xzalloc(out_bufsize); + infile_len = fread(infile, 1, infile_len, f); + fclose(f); + + set_32(&header.usize, infile_len); + +/* + * Step 5: compute a checksum of the uncompressed data + */ + uncompressed_checksum = lzo_adler32(0, NULL, 0); + uncompressed_checksum = lzo_adler32(uncompressed_checksum, + infile, infile_len); + +/* + * Step 6a: compress from `in' to `out' with LZO1X-999 + */ + best_len = infile_len; + for (lazy = 0; lazy <= max_try_lazy; lazy++) { + out_len = out_bufsize; + r = lzo1x_999_compress_internal(infile, infile_len, + out, &out_len, wrkmem, + NULL, 0, 0, + lazy, big, big, big, big, flags); + if (r != LZO_E_OK) + /* this should NEVER happen */ + error("internal error - compression failed: %d", r); + + if (out_len < best_len) { + best_len = out_len; + best_lazy = lazy; + } + } + +/* + * Step 7: check if compressible + */ + if (best_len >= infile_len) { + fprintf(stderr, "%s: %s: this file contains incompressible data.", + progname, in_name); + /* do it anyway */ + } + +/* + * Step 8: compress data again using the best compressor found + */ + out_len = out_bufsize; + r = lzo1x_999_compress_internal(infile, infile_len, out, &out_len, wrkmem, + NULL, 0, 0, + best_lazy, big, big, big, big, flags); + assert(r == LZO_E_OK); + assert(out_len == best_len); + set_32(&header.zsize, out_len); + +/* + * Step 9: optimize compressed data (compressed data is in `out' buffer) + */ + orig_len = infile_len; + r = lzo1x_optimize(out, out_len, infile, &orig_len, NULL); + if (r != LZO_E_OK || orig_len != infile_len) { + /* this should NEVER happen */ + error("internal error - optimization failed: %d", r); + } + +/* + * Step 10: compute a checksum of the compressed data + */ + compressed_checksum = lzo_adler32(0, NULL, 0); + compressed_checksum = lzo_adler32(compressed_checksum, out, out_len); + +/* + * Step 11: write compressed data to a file + */ + f = fopen(out_name, "wb"); + if (!f) + error("cannot open output file %s: %s", out_name, strerror(errno)); + + if (fwrite(&header, 1, sizeof header, f) != sizeof header || + fwrite(out, 1, out_len, f) != out_len || + fclose(f)) + error("write error"); + +/* + * Step 12: verify decompression + */ +#ifdef PARANOID + orig_len = infile_len * 2; + test = xzalloc(orig_len); + r = lzo1x_decompress_safe(out, out_len, test, &orig_len, NULL); + + if (r != LZO_E_OK || orig_len != infile_len) { + /* this should NEVER happen */ + error("internal error - decompression failed: %d", r); + } + + if (memcmp(test, infile, infile_len)) { + /* this should NEVER happen */ + error("internal error - decompression data error"); + } + + /* Now you could also verify decompression under similar conditions as in + * your application, e.g. overlapping assembler decompression etc. + */ + + free(test); +#endif + + free(infile); + free(out); + + return 0; +} diff --git a/mk/devel.mk b/mk/devel.mk index 8184c30f..15b2ea64 100644 --- a/mk/devel.mk +++ b/mk/devel.mk @@ -1,3 +1,3 @@ # Useful while doing development, but not for production. GCCWARN += -Wno-clobbered -# GCCWARN += -DDEBUG_PORT=0x3f8 -DDEBUG=1 +GCCWARN += -DDEBUG_PORT=0x3f8 -DDEBUG=1 @@ -35,7 +35,7 @@ com32 = $(topdir)/com32 core = $(topdir)/core ifneq ($(NOGPL),1) -GPLLIB = $(com32)/gpllib/libgpl.c32 +GPLLIB = $(com32)/gpllib/libgpl.elf GPLINCLUDE = -I$(com32)/gplinclude else GPLLIB = @@ -54,8 +54,8 @@ LNXCFLAGS = -I$(com32)/libutil/include -W -Wall -O -g -D_GNU_SOURCE LNXSFLAGS = -g LNXLDFLAGS = -g -C_LIBS = $(com32)/libutil/libutil.c32 $(GPLLIB) \ - $(com32)/lib/libcom32.c32 +C_LIBS = $(com32)/libutil/libutil.elf $(GPLLIB) \ + $(com32)/lib/libcom32.elf C_LNXLIBS = $(com32)/libutil/libutil_lnx.a \ $(com32)/elflink/ldlinux/ldlinux_lnx.a @@ -86,4 +86,7 @@ C_LNXLIBS = $(com32)/libutil/libutil_lnx.a \ $(LD) $(LDFLAGS) -o $@ $^ %.c32: %.elf - $(OBJCOPY) --strip-debug --strip-unneeded $< $@ + $(OBJCOPY) --strip-debug --strip-unneeded $< $*.tmp + $(MKMODULE) $*.tmp $@ + rm -f $*.tmp + @@ -81,4 +81,6 @@ LDFLAGS = -m elf_i386 --hash-style=gnu -T $(com32)/lib/elf32.ld $(CC) $(MAKEDEPS) $(CFLAGS) $(SOFLAGS) -S -o $@ $< %.c32: %.elf - $(OBJCOPY) --strip-debug --strip-unneeded $< $@ + $(OBJCOPY) --strip-debug --strip-unneeded $< $*.tmp + $(MKMODULE) $*.tmp $@ + rm -f $*.tmp diff --git a/mk/syslinux.mk b/mk/syslinux.mk index 1378b6d5..6205ebcf 100644 --- a/mk/syslinux.mk +++ b/mk/syslinux.mk @@ -65,6 +65,8 @@ MKISOFS = mkisofs SED = sed WGET = wget +MKMODULE = $(topdir)/lzo/mkmodule + com32 = $(topdir)/com32 # Common warnings we want for all gcc-generated code |