diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 211f261126..fa99467ccb 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -37,6 +37,27 @@ SILENT := >/dev/null 2>&1 ROM_SIZE := $(shell expr $(CONFIG_LINUXBIOS_ROMSIZE_KB) \* 1024) +LARFILES := nocompress:normal/initram normal/stage2 nocompress:normal/option_table +ifneq ($(CONFIG_PAYLOAD_NONE),y) +LARFILES += normal/payload +endif + +DECOMPRESSORS := +ifeq ($(CONFIG_COMPRESSION_LZMA),y) +DECOMPRESSORS += lzma.o +endif +ifeq ($(CONFIG_COMPRESSION_NRV2B),y) +DECOMPRESSORS += nrv2b.o +endif + +COMPRESSFLAG := +ifeq ($(CONFIG_DEFAULT_COMPRESSION_LZMA),y) +COMPRESSFLAG := -C lzma +endif +ifeq ($(CONFIG_DEFAULT_COMPRESSION_NRV2B),y) +COMPRESSFLAG := -C nrv2b +endif + $(obj)/linuxbios.rom: $(obj)/linuxbios.bootblock $(obj)/util/lar/lar lzma nrv2b $(obj)/linuxbios.initram $(obj)/linuxbios.stage2 $(obj)/option_table $(Q)rm -rf $(obj)/lar.tmp $(Q)mkdir $(obj)/lar.tmp @@ -57,7 +78,9 @@ else fi endif $(Q)printf " LAR $(subst $(shell pwd)/,,$(@))\n" - $(Q)cd $(obj)/lar.tmp && ../util/lar/lar -c ../linuxbios.rom . \ + $(Q)cd $(obj)/lar.tmp && ../util/lar/lar $(COMPRESSFLAG) -c \ + ../linuxbios.rom \ + $(LARFILES) \ -s $(ROM_SIZE) -b $(obj)/linuxbios.bootblock $(Q)# QEMU wants bios.bin: $(Q)# Run "qemu -L build/ -serial stdio -hda /dev/zero". @@ -75,7 +98,7 @@ $(obj)/linuxbios.bootblock: $(obj)/linuxbios.vpd $(obj)/stage0.init # STAGE0_LIB_OBJ = uart8250.o mem.o elfboot.o lar.o delay.o vtxprintf.o \ - vsprintf.o console.o + vsprintf.o console.o $(DECOMPRESSORS) STAGE0_ARCH_X86_OBJ = stage1.o serial.o archelfboot.o speaker.o \ udelay_io.o mc146818rtc.o diff --git a/arch/x86/stage1.c b/arch/x86/stage1.c index 542dbd11ee..2c455898bb 100644 --- a/arch/x86/stage1.c +++ b/arch/x86/stage1.c @@ -25,6 +25,8 @@ #include #include +#define UNCOMPRESS_AREA 0x60000 + /* these prototypes should go into headers */ void uart_init(void); void die(const char *msg); @@ -230,13 +232,18 @@ void __attribute__((stdcall)) stage1_main(u32 bist) ret = find_file(&archive, "normal/payload", &result); if (ret) { - printk(BIOS_WARNING, "No such file '%s'.\n", "normal/payload"); + printk(BIOS_ERR, "No such file '%s'.\n", "normal/payload"); die("FATAL: No payload found.\n"); } + ret = copy_file(&archive, "normal/payload", (void *)UNCOMPRESS_AREA); + if (ret) { + printk(BIOS_ERR, "'%s' found, but could not load it.\n", "normal/payload"); + die("FATAL: No usable payload found.\n"); + } - ret = elfboot_mem(mem, result.start, result.len); + ret = elfboot_mem(mem, (void *)UNCOMPRESS_AREA, result.reallen); - printk(BIOS_DEBUG, "elfboot_mem returns %d\n", ret); + printk(BIOS_ERR, "elfboot_mem returns %d\n", ret); die ("FATAL: Last stage returned to LinuxBIOS.\n"); } diff --git a/include/lar.h b/include/lar.h index 082fb4834f..a6dc0af7a3 100644 --- a/include/lar.h +++ b/include/lar.h @@ -68,6 +68,8 @@ struct lar_header { struct mem_file { void *start; int len; + u32 reallen; + u32 compression; }; /* Prototypes. */ diff --git a/lib/elfboot.c b/lib/elfboot.c index faec2ecf44..f49a729568 100644 --- a/lib/elfboot.c +++ b/lib/elfboot.c @@ -185,6 +185,8 @@ int elfboot_mem(struct lb_memory *mem, void *where, int size) continue; } printk(BIOS_DEBUG, "Found ELF candidate at offset %d\n", i); + header_offset = i; + break; /* Sanity check the elf header */ if ((ehdr->e_type == ET_EXEC) && elf_check_arch(ehdr) && diff --git a/lib/lar.c b/lib/lar.c index 108482b6ad..459373abf7 100644 --- a/lib/lar.c +++ b/lib/lar.c @@ -53,6 +53,8 @@ int find_file(struct mem_file *archive, char *filename, struct mem_file *result) if (strcmp(fullname, filename) == 0) { result->start = walk + ntohl(header->offset); result->len = ntohl(header->len); + result->reallen = ntohl(header->reallen); + result->compression = ntohl(header->compression); return 0; } // skip file @@ -74,9 +76,31 @@ int copy_file(struct mem_file *archive, char *filename, void *where) return 1; } - memcpy(where, result.start, result.len); - - return 0; + printk(BIOS_SPEW, "LAR: Compression algorithm #%i used\n", result.compression); + /* no compression */ + if (result.compression == 0) { + memcpy(where, result.start, result.len); + return 0; + } +#ifdef CONFIG_COMPRESSION_LZMA + /* lzma */ + unsigned long ulzma(unsigned char * src, unsigned char * dst); + if (result.compression == 1) { + ulzma(result.start, where); + return 0; + } +#endif +#ifdef CONFIG_COMPRESSION_NRV2B + /* nrv2b */ + unsigned long unrv2b(u8 * src, u8 * dst, unsigned long *ilen_p); + if (result.compression == 2) { + int tmp; + unrv2b(result.start, where, &tmp); + return 0; + } +#endif + printk(BIOS_INFO, "LAR: Compression algorithm #%i not supported!\n", result.compression); + return 1; } int run_file(struct mem_file *archive, char *filename, void *where) diff --git a/lib/lzma.c b/lib/lzma.c index b47afe5f43..c79ebe3649 100644 --- a/lib/lzma.c +++ b/lib/lzma.c @@ -7,9 +7,11 @@ Released under the GNU GPL */ #include "lzmadecode.c" +#include "string.h" +#include "console.h" -static unsigned long ulzma(unsigned char * src, unsigned char * dst) +unsigned long ulzma(u8 *src, u8 *dst) { unsigned char properties[LZMA_PROPERTIES_SIZE]; UInt32 outSize; diff --git a/lib/nrv2b.c b/lib/nrv2b.c index a094ad4b60..bca6618b97 100644 --- a/lib/nrv2b.c +++ b/lib/nrv2b.c @@ -1,3 +1,4 @@ +#include // This GETBIT is supposed to work on little endian // 32bit systems. The algorithm will definitely need // some fixing on other systems, but it might not be @@ -28,7 +29,8 @@ #if ENDIAN == 0 && BITSIZE == 32 #define GETBIT(bb, src, ilen) GETBIT_LE32(bb, src, ilen) #endif -static unsigned long unrv2b(u8 * src, u8 * dst, unsigned long *ilen_p) + +unsigned long unrv2b(u8 *src, u8 *dst, unsigned long *ilen_p) { unsigned long ilen = 0, olen = 0, last_m_off = 1; u32 bb = 0;