From ead73689db79fecc3e17215d100ab52ce4377657 Mon Sep 17 00:00:00 2001 From: Stefan Reinauer Date: Tue, 2 May 2006 12:05:13 +0000 Subject: add automatic payload compression method to LinuxBIOS git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2288 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/arch/i386/Config.lb | 17 ++++++++- src/config/Options.lb | 5 +++ src/cpu/amd/car/copy_and_run.c | 69 ++-------------------------------- src/cpu/x86/car/copy_and_run.c | 69 +++------------------------------- src/lib/nrv2b.c | 61 ++++++++++++++++++++++++++++++ src/stream/Config.lb | 5 +++ src/stream/rom_stream.c | 4 +- src/stream/zrom_stream.c | 84 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 181 insertions(+), 133 deletions(-) create mode 100644 src/lib/nrv2b.c create mode 100644 src/stream/zrom_stream.c (limited to 'src') diff --git a/src/arch/i386/Config.lb b/src/arch/i386/Config.lb index ebb014f525..e1722bed42 100644 --- a/src/arch/i386/Config.lb +++ b/src/arch/i386/Config.lb @@ -18,9 +18,22 @@ makerule nrv2b action "$(HOSTCC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -DNDEBUG -DBITSIZE=32 -DENDIAN=0 $< -o $@" end +makerule payload + depends "$(PAYLOAD)" + action "cp $< $@" +end + +makerule payload.nrv2b + depends "$(PAYLOAD) nrv2b" + action "./nrv2b e $(PAYLOAD) $@" +end + +makedefine PAYLOAD-1:=payload +makedefine PAYLOAD-$(CONFIG_COMPRESSED_ROM_STREAM):=payload.nrv2b + makerule linuxbios.rom - depends "linuxbios.strip buildrom" - action "./buildrom $< $@ $(PAYLOAD) $(ROM_IMAGE_SIZE) $(ROM_SECTION_SIZE)" + depends "linuxbios.strip buildrom $(PAYLOAD-1)" + action "./buildrom $< $@ $(PAYLOAD-1) $(ROM_IMAGE_SIZE) $(ROM_SECTION_SIZE)" end makerule crt0.S diff --git a/src/config/Options.lb b/src/config/Options.lb index 2f3d8dd1c0..3dfa80110f 100644 --- a/src/config/Options.lb +++ b/src/config/Options.lb @@ -564,6 +564,11 @@ define CONFIG_ROM_STREAM_START export always comment "ROM stream start location" end +define CONFIG_COMPRESSED_ROM_STREAM + default 0 + export always + comment "compressed boot image is located in ROM" +end define CONFIG_FS_STREAM default 0 export always diff --git a/src/cpu/amd/car/copy_and_run.c b/src/cpu/amd/car/copy_and_run.c index 68e9e35482..44c3bf24fc 100644 --- a/src/cpu/amd/car/copy_and_run.c +++ b/src/cpu/amd/car/copy_and_run.c @@ -1,31 +1,10 @@ /* by yhlu 6.2005 moved from nrv2v.c and some lines from crt0.S + 2006/05/02 - stepan: move nrv2b to an extra file. */ -#ifndef ENDIAN -#define ENDIAN 0 -#endif -#ifndef BITSIZE -#define BITSIZE 32 -#endif - -#define GETBIT_8(bb, src, ilen) \ - (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1) - -#define GETBIT_LE16(bb, src, ilen) \ - (bb*=2,bb&0xffff ? (bb>>16)&1 : (ilen+=2,((bb=(src[ilen-2]+src[ilen-1]*256u)*2+1)>>16)&1)) -#define GETBIT_LE32(bb, src, ilen) \ - (bc > 0 ? ((bb>>--bc)&1) : (bc=31,\ - bb=*(const uint32_t *)((src)+ilen),ilen+=4,(bb>>31)&1)) - -#if ENDIAN == 0 && BITSIZE == 8 -#define GETBIT(bb, src, ilen) GETBIT_8(bb, src, ilen) -#endif -#if ENDIAN == 0 && BITSIZE == 16 -#define GETBIT(bb, src, ilen) GETBIT_LE16(bb, src, ilen) -#endif -#if ENDIAN == 0 && BITSIZE == 32 -#define GETBIT(bb, src, ilen) GETBIT_LE32(bb, src, ilen) +#if CONFIG_COMPRESS +#include "lib/nrv2b.c" #endif static inline void print_debug_cp_run(const char *strval, uint32_t val) @@ -66,47 +45,7 @@ static void copy_and_run(void) print_debug_cp_run("src=",(uint32_t)src); print_debug_cp_run("dst=",(uint32_t)dst); - for(;;) { - unsigned int m_off, m_len; - while(GETBIT(bb, src, ilen)) { - dst[olen++] = src[ilen++]; - } - - m_off = 1; - do { - m_off = m_off*2 + GETBIT(bb, src, ilen); - } while (!GETBIT(bb, src, ilen)); - if (m_off == 2) - { - m_off = last_m_off; - } - else - { - m_off = (m_off - 3)*256 + src[ilen++]; - if(m_off == 0xffffffffU) - break; - last_m_off = ++m_off; - } - m_len = GETBIT(bb, src, ilen); - m_len = m_len*2 + GETBIT(bb, src, ilen); - if (m_len == 0) - { - m_len++; - do { - m_len = m_len*2 + GETBIT(bb, src, ilen); - } while(!GETBIT(bb, src, ilen)); - m_len += 2; - } - m_len += (m_off > 0xd00); - { - const uint8_t *m_pos; - m_pos = dst + olen - m_off; - dst[olen++] = *m_pos++; - do { - dst[olen++] = *m_pos++; - } while(--m_len > 0); - } - } + unrv2b(src, dst); #endif print_debug_cp_run("linxbios_ram.bin length = ", olen); diff --git a/src/cpu/x86/car/copy_and_run.c b/src/cpu/x86/car/copy_and_run.c index ae77e50956..4954e43841 100644 --- a/src/cpu/x86/car/copy_and_run.c +++ b/src/cpu/x86/car/copy_and_run.c @@ -1,31 +1,10 @@ /* by yhlu 6.2005 moved from nrv2v.c and some lines from crt0.S + 2006/05/02 - stepan: move nrv2b to an extra file. */ -#ifndef ENDIAN -#define ENDIAN 0 -#endif -#ifndef BITSIZE -#define BITSIZE 32 -#endif - -#define GETBIT_8(bb, src, ilen) \ - (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1) - -#define GETBIT_LE16(bb, src, ilen) \ - (bb*=2,bb&0xffff ? (bb>>16)&1 : (ilen+=2,((bb=(src[ilen-2]+src[ilen-1]*256u)*2+1)>>16)&1)) -#define GETBIT_LE32(bb, src, ilen) \ - (bc > 0 ? ((bb>>--bc)&1) : (bc=31,\ - bb=*(const uint32_t *)((src)+ilen),ilen+=4,(bb>>31)&1)) - -#if ENDIAN == 0 && BITSIZE == 8 -#define GETBIT(bb, src, ilen) GETBIT_8(bb, src, ilen) -#endif -#if ENDIAN == 0 && BITSIZE == 16 -#define GETBIT(bb, src, ilen) GETBIT_LE16(bb, src, ilen) -#endif -#if ENDIAN == 0 && BITSIZE == 32 -#define GETBIT(bb, src, ilen) GETBIT_LE32(bb, src, ilen) +#if CONFIG_COMPRESS +#include "lib/nrv2b.c" #endif static void copy_and_run(unsigned cpu_reset) @@ -65,46 +44,8 @@ static void copy_and_run(unsigned cpu_reset) // dump_mem(src, src+0x100); - for(;;) { - unsigned int m_off, m_len; - while(GETBIT(bb, src, ilen)) { - dst[olen++] = src[ilen++]; - } - m_off = 1; - do { - m_off = m_off*2 + GETBIT(bb, src, ilen); - } while (!GETBIT(bb, src, ilen)); - if (m_off == 2) - { - m_off = last_m_off; - } - else - { - m_off = (m_off - 3)*256 + src[ilen++]; - if(m_off == 0xffffffffU) - break; - last_m_off = ++m_off; - } - m_len = GETBIT(bb, src, ilen); - m_len = m_len*2 + GETBIT(bb, src, ilen); - if (m_len == 0) - { - m_len++; - do { - m_len = m_len*2 + GETBIT(bb, src, ilen); - } while(!GETBIT(bb, src, ilen)); - m_len += 2; - } - m_len += (m_off > 0xd00); - { - const uint8_t *m_pos; - m_pos = dst + olen - m_off; - dst[olen++] = *m_pos++; - do { - dst[olen++] = *m_pos++; - } while(--m_len > 0); - } - } + unrv2b(src, dst); + #endif // dump_mem(dst, dst+0x100); #if CONFIG_USE_INIT diff --git a/src/lib/nrv2b.c b/src/lib/nrv2b.c new file mode 100644 index 0000000000..f912347e3a --- /dev/null +++ b/src/lib/nrv2b.c @@ -0,0 +1,61 @@ +#include +#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 +// a problem since the nrv2b binary behaves the same.. + +#define GETBIT(bb, src, ilen) \ + (bc > 0 ? ((bb>>--bc)&1) : (bc=31,\ + bb=*(const uint32_t *)((src)+ilen),ilen+=4,(bb>>31)&1)) + +static void unrv2b(uint8_t * src, uint8_t * dst) +{ + unsigned long ilen = 0, olen = 0, last_m_off = 1; + uint32_t bb = 0; + unsigned bc = 0; + const uint8_t *m_pos; + + // skip length + src += 4; + + for (;;) { + unsigned int m_off, m_len; + while (GETBIT(bb, src, ilen)) { + dst[olen++] = src[ilen++]; + } + + m_off = 1; + do { + m_off = m_off * 2 + GETBIT(bb, src, ilen); + } while (!GETBIT(bb, src, ilen)); + if (m_off == 2) { + m_off = last_m_off; + } else { + m_off = (m_off - 3) * 256 + src[ilen++]; + if (m_off == 0xffffffffU) + break; + last_m_off = ++m_off; + } + + m_len = GETBIT(bb, src, ilen); + m_len = m_len * 2 + GETBIT(bb, src, ilen); + if (m_len == 0) { + m_len++; + do { + m_len = m_len * 2 + GETBIT(bb, src, ilen); + } while (!GETBIT(bb, src, ilen)); + m_len += 2; + } + m_len += (m_off > 0xd00); + + m_pos = dst + olen - m_off; + dst[olen++] = *m_pos++; + do { + dst[olen++] = *m_pos++; + } while (--m_len > 0); + } + +} + diff --git a/src/stream/Config.lb b/src/stream/Config.lb index b146c0451e..46c2dc7f08 100644 --- a/src/stream/Config.lb +++ b/src/stream/Config.lb @@ -1,3 +1,4 @@ +uses CONFIG_COMPRESSED_ROM_STREAM uses CONFIG_ROM_STREAM uses CONFIG_IDE_STREAM uses CONFIG_FS_STREAM @@ -7,6 +8,10 @@ if CONFIG_ROM_STREAM object rom_stream.o end +if CONFIG_COMPRESSED_ROM_STREAM + object zrom_stream.o +end + if CONFIG_IDE_STREAM default CONFIG_IDE=1 object ide_stream.o diff --git a/src/stream/rom_stream.c b/src/stream/rom_stream.c index 7a662d019e..1127be0b8a 100644 --- a/src/stream/rom_stream.c +++ b/src/stream/rom_stream.c @@ -18,8 +18,8 @@ */ /*XXXXXXXXXXXXXX */ -/*static const */unsigned char *rom_start = (void *)CONFIG_ROM_STREAM_START; -/*static const */unsigned char *rom_end = (void *)(CONFIG_ROM_STREAM_START + PAYLOAD_SIZE - 1); +/*static const */unsigned char *rom_start = (unsigned char *)CONFIG_ROM_STREAM_START; +/*static const */unsigned char *rom_end = (unsigned char *)(CONFIG_ROM_STREAM_START + PAYLOAD_SIZE - 1); /*XXXXXXXXXXXXXX */ static const unsigned char *rom; diff --git a/src/stream/zrom_stream.c b/src/stream/zrom_stream.c new file mode 100644 index 0000000000..39da619a04 --- /dev/null +++ b/src/stream/zrom_stream.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include + +// include generic nrv2b +#include "../lib/nrv2b.c" + +#ifndef CONFIG_ROM_STREAM_START +#define CONFIG_ROM_STREAM_START 0xffff0000UL +#endif + +unsigned char *rom_start = (unsigned char *)CONFIG_ROM_STREAM_START; +unsigned char *rom_end = (unsigned char *)(CONFIG_ROM_STREAM_START + PAYLOAD_SIZE - 1);; + +extern unsigned char _heap, _eheap; + +static const unsigned char *rom; + +int stream_init(void) +{ + unsigned long compressed_rom_start=rom_start; + unsigned long compressed_rom_end=rom_end; + unsigned int len; + + len=*(unsigned int *)compressed_rom_start; // LE only for now + + printk_debug (" compressed rom stream: 0x%08lx - 0x%08lx\n", + compressed_rom_start, compressed_rom_end); + + rom_start = &_eheap; + rom_end = rom_start + len; // LE only for now +#if 0 + { + int i; + for (i=0; i<512; i++) { + if( i%16==0) printk_spew("\n%04x :", i); + printk_spew(" %02x", *(unsigned char *)(compressed_rom_start+i)); + } + } +#endif + printk_debug(" rom stream: 0x%08lx - 0x%08lx\n", (unsigned long) + rom_start, (unsigned long) rom_end); + + printk_debug("Uncompressing..."); + unrv2b((uint8_t *) compressed_rom_start, (uint8_t *)rom_start); + printk_debug(" done.\n"); + + rom = rom_start; + + return 0; +} + +void stream_fini(void) +{ + return; +} + +byte_offset_t stream_skip(byte_offset_t count) +{ + byte_offset_t bytes; + bytes = count; + if ((rom + bytes) > rom_end) { + printk_warning(" overflowed source buffer\n"); + bytes = 0; + if (rom <= rom_end) { + bytes = (rom_end - rom) + 1; + } + } + rom += bytes; + return bytes; +} + +byte_offset_t stream_read(void *vdest, byte_offset_t count) +{ + unsigned char *dest = vdest; + const unsigned char *src = rom; + byte_offset_t bytes; + + bytes = stream_skip(count); + memcpy(dest, src, bytes); + return bytes; +} -- cgit v1.2.3