Move decompression further down the code flow, so that - where

possible - code is decompressed directly to the right place
(instead of copying around, as before).

The downside of this approach is that it's not possible (without API
changes to the decompressors) to put partial segments into bounce
buffers. So if a segment collides with coreboot _and_ is compressed,
it's bounced entirely.
But, as this only brings back the copy we already had before, the new
worst case is better than the average before.

It also fixes handling of compressed segments.

Signed-off-by: Patrick Georgi <patrick.georgi@coresystems.de>
Acked-by: Ronald G. Minnich <rminnich@gmail.com>


git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4207 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Patrick Georgi 2009-04-25 07:32:24 +00:00
parent 7994164a0e
commit 369bc7882a
1 changed files with 115 additions and 140 deletions

View File

@ -55,6 +55,7 @@ struct segment {
unsigned long s_srcaddr;
unsigned long s_memsz;
unsigned long s_filesz;
int compression;
};
struct verify_callback {
@ -70,54 +71,6 @@ struct ip_checksum_vcb {
unsigned short ip_checksum;
};
int cbfs_self_decompress(int algo, void *src,struct segment *new)
{
u8 *dst;
/* for uncompressed, it's easy: just point at the area in ROM */
if (algo == CBFS_COMPRESS_NONE) {
new->s_srcaddr = (u32) src;
new->s_filesz = new->s_memsz;
return 0;
}
/* for compression, let's keep it simple. We'll malloc the destination
* area and decompress to there. The compression overhead far outweighs
* any overhead for an extra copy.
*/
dst = malloc(new->s_memsz);
if (! dst)
return -1;
switch(algo) {
#if CONFIG_COMPRESSED_PAYLOAD_LZMA==1
case CBFS_COMPRESS_LZMA: {
unsigned long ulzma(unsigned char *src, unsigned char *dst);
ulzma(src, dst);
break;
}
#endif
#if CONFIG_COMPRESSED_PAYLOAD_NRV2B==1
case CBFS_COMPRESS_NRV2B: {
unsigned long unrv2b(u8 *src, u8 *dst, unsigned long *ilen_p);
unsigned long tmp;
unrv2b(src, dst, &tmp);
break;
}
#endif
default:
printk_info( "CBFS: Unknown compression type %d\n",
algo);
return -1;
}
new->s_srcaddr = (u32) dst;
new->s_filesz = new->s_memsz;
return 0;
}
/* The problem:
* Static executables all want to share the same addresses
* in memory because only a few addresses are reliably present on
@ -249,6 +202,7 @@ static void relocate_segment(unsigned long buffer, struct segment *seg)
printk_spew("segment: [0x%016lx, 0x%016lx, 0x%016lx)\n",
start, middle, end);
if (seg->compression == CBFS_COMPRESS_NONE) {
/* Slice off a piece at the beginning
* that doesn't conflict with coreboot.
*/
@ -326,6 +280,7 @@ static void relocate_segment(unsigned long buffer, struct segment *seg)
new->s_dstaddr + new->s_memsz);
}
}
/* Now retarget this segment onto the bounce buffer */
/* sort of explanation: the buffer is a 1:1 mapping to coreboot.
* so you will make the dstaddr be this buffer, and it will get copied
@ -371,15 +326,11 @@ static int build_self_segment_list(
new = malloc(sizeof(*new));
new->s_dstaddr = ntohl((u32) segment->load_addr);
new->s_memsz = ntohl(segment->mem_len);
new->compression = ntohl(segment->compression);
datasize = ntohl(segment->len);
/* figure out decompression, do it, get pointer to the area */
if (cbfs_self_decompress(ntohl(segment->compression),
((unsigned char *) first_segment) +
ntohl(segment->offset), new)) {
printk_emerg("cbfs_self_decompress failed\n");
return;
}
new->s_srcaddr = (u32) ((unsigned char *) first_segment) + ntohl(segment->offset);
new->s_filesz = ntohl(segment->len);
printk_debug("New segment dstaddr 0x%lx memsize 0x%lx srcaddr 0x%lx filesize 0x%lx\n",
new->s_dstaddr, new->s_memsz, new->s_srcaddr, new->s_filesz);
/* Clean up the values */
@ -449,23 +400,47 @@ static int load_self_segments(
/* Compute the boundaries of the segment */
dest = (unsigned char *)(ptr->s_dstaddr);
end = dest + ptr->s_memsz;
middle = dest + ptr->s_filesz;
src = ptr->s_srcaddr;
printk_spew("[ 0x%016lx, %016lx, 0x%016lx) <- %016lx\n",
(unsigned long)dest,
(unsigned long)middle,
(unsigned long)end,
(unsigned long)src);
/* Copy data from the initial buffer */
if (ptr->s_filesz) {
size_t len;
len = ptr->s_filesz;
memcpy(dest, src, len);
dest += len;
switch(ptr->compression) {
#if CONFIG_COMPRESSED_PAYLOAD_LZMA==1
case CBFS_COMPRESS_LZMA: {
printk_debug("using LZMA\n");
unsigned long ulzma(unsigned char *src, unsigned char *dst);
len = ulzma(src, dest);
break;
}
#endif
#if CONFIG_COMPRESSED_PAYLOAD_NRV2B==1
case CBFS_COMPRESS_NRV2B: {
printk_debug("using NRV2B\n");
unsigned long unrv2b(u8 *src, u8 *dst, unsigned long *ilen_p);
unsigned long tmp;
len = unrv2b(src, dest, &tmp);
break;
}
#endif
case CBFS_COMPRESS_NONE: {
printk_debug("it's not compressed!\n");
memcpy(dest, src, len);
break;
}
default:
printk_info( "CBFS: Unknown compression type %d\n", ptr->compression);
return -1;
}
end = dest + ptr->s_memsz;
middle = dest + len;
printk_spew("[ 0x%016lx, %016lx, 0x%016lx) <- %016lx\n",
(unsigned long)dest,
(unsigned long)middle,
(unsigned long)end,
(unsigned long)src);
}
/* Zero the extra bytes between middle & end */
if (middle < end) {
printk_debug("Clearing Segment: addr: 0x%016lx memsz: 0x%016lx\n",