aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/cbfs.c75
-rw-r--r--src/lib/lzma.c3
-rw-r--r--src/lib/rmodule.c22
-rw-r--r--src/lib/selfboot.c13
4 files changed, 69 insertions, 44 deletions
diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c
index 55a8536a36..82bfa2d8ad 100644
--- a/src/lib/cbfs.c
+++ b/src/lib/cbfs.c
@@ -19,9 +19,11 @@
#include <stdlib.h>
#include <boot_device.h>
#include <cbfs.h>
+#include <commonlib/compression.h>
#include <endian.h>
#include <lib.h>
#include <symbols.h>
+#include <timestamp.h>
#define ERROR(x...) printk(BIOS_ERR, "CBFS: " x)
#define LOG(x...) printk(BIOS_INFO, "CBFS: " x)
@@ -68,13 +70,57 @@ void *cbfs_boot_map_with_leak(const char *name, uint32_t type, size_t *size)
return rdev_mmap(&fh.data, 0, fsize);
}
-static size_t inflate(void *src, void *dst)
+size_t cbfs_load_and_decompress(const struct region_device *rdev, size_t offset,
+ size_t in_size, void *buffer, size_t buffer_size, uint32_t compression)
{
- if (ENV_BOOTBLOCK || ENV_VERSTAGE)
- return 0;
- if (ENV_ROMSTAGE && !IS_ENABLED(CONFIG_COMPRESS_RAMSTAGE))
+ size_t out_size;
+
+ switch (compression) {
+ case CBFS_COMPRESS_NONE:
+ if (rdev_readat(rdev, buffer, offset, in_size) != in_size)
+ return 0;
+ return in_size;
+
+ case CBFS_COMPRESS_LZ4:
+ if ((ENV_BOOTBLOCK || ENV_VERSTAGE) &&
+ !IS_ENABLED(CONFIG_COMPRESS_PRERAM_STAGES))
+ return 0;
+
+ /* Load the compressed image to the end of the available memory
+ * area for in-place decompression. It is the responsibility of
+ * the caller to ensure that buffer_size is large enough
+ * (see compression.h, guaranteed by cbfstool for stages). */
+ void *compr_start = buffer + buffer_size - in_size;
+ if (rdev_readat(rdev, compr_start, offset, in_size) != in_size)
+ return 0;
+
+ timestamp_add_now(TS_START_ULZ4F);
+ out_size = ulz4fn(compr_start, in_size, buffer, buffer_size);
+ timestamp_add_now(TS_END_ULZ4F);
+ return out_size;
+
+ case CBFS_COMPRESS_LZMA:
+ if (ENV_BOOTBLOCK || ENV_VERSTAGE)
+ return 0;
+ if (ENV_ROMSTAGE && !IS_ENABLED(CONFIG_COMPRESS_RAMSTAGE))
+ return 0;
+
+ void *map = rdev_mmap(rdev, offset, in_size);
+ if (map == NULL)
+ return 0;
+
+ /* Note: timestamp not useful for memory-mapped media (x86) */
+ timestamp_add_now(TS_START_ULZMA);
+ out_size = ulzman(map, in_size, buffer, buffer_size);
+ timestamp_add_now(TS_END_ULZMA);
+
+ rdev_munmap(rdev, map);
+
+ return out_size;
+
+ default:
return 0;
- return ulzma(src, dst);
+ }
}
static inline int tohex4(unsigned int c)
@@ -152,22 +198,9 @@ int cbfs_prog_stage_load(struct prog *pstage)
goto out;
}
- if (stage.compression == CBFS_COMPRESS_NONE) {
- if (rdev_readat(fh, load, foffset, fsize) != fsize)
- return -1;
- } else if (stage.compression == CBFS_COMPRESS_LZMA) {
- void *map = rdev_mmap(fh, foffset, fsize);
-
- if (map == NULL)
- return -1;
-
- fsize = inflate(map, load);
-
- rdev_munmap(fh, map);
-
- if (!fsize)
- return -1;
- } else
+ fsize = cbfs_load_and_decompress(fh, foffset, fsize, load,
+ stage.memlen, stage.compression);
+ if (!fsize)
return -1;
/* Clear area not covered by file. */
diff --git a/src/lib/lzma.c b/src/lib/lzma.c
index 5566cd5dfc..d0b4c355b1 100644
--- a/src/lib/lzma.c
+++ b/src/lib/lzma.c
@@ -29,8 +29,6 @@ size_t ulzman(const void *src, size_t srcn, void *dst, size_t dstn)
MAYBE_STATIC unsigned char scratchpad[15980];
const unsigned char *cp;
- /* Note: these timestamps aren't useful for memory-mapped media (x86) */
- timestamp_add_now(TS_START_ULZMA);
memcpy(properties, src, LZMA_PROPERTIES_SIZE);
/* The outSize in LZMA stream is a 64bit integer stored in little-endian
* (ref: lzma.cc@LZMACompress: put_64). To prevent accessing by
@@ -55,7 +53,6 @@ size_t ulzman(const void *src, size_t srcn, void *dst, size_t dstn)
printk(BIOS_WARNING, "lzma: Decoding error = %d\n", res);
return 0;
}
- timestamp_add_now(TS_END_ULZMA);
return outProcessed;
}
diff --git a/src/lib/rmodule.c b/src/lib/rmodule.c
index 628195cafa..585fb5f2ef 100644
--- a/src/lib/rmodule.c
+++ b/src/lib/rmodule.c
@@ -259,8 +259,6 @@ int rmodule_stage_load(struct rmod_stage_load *rsl)
struct cbfs_stage stage;
void *rmod_loc;
struct region_device *fh;
- const int use_lzma = ENV_RAMSTAGE
- || (ENV_ROMSTAGE && IS_ENABLED(CONFIG_COMPRESS_RAMSTAGE));
if (rsl->prog == NULL || prog_name(rsl->prog) == NULL)
return -1;
@@ -284,24 +282,8 @@ int rmodule_stage_load(struct rmod_stage_load *rsl)
printk(BIOS_INFO, "Decompressing stage %s @ 0x%p (%d bytes)\n",
prog_name(rsl->prog), rmod_loc, stage.memlen);
- if (stage.compression == CBFS_COMPRESS_NONE) {
- if (rdev_readat(fh, rmod_loc, sizeof(stage), stage.len) !=
- stage.len)
- return -1;
- } else if (use_lzma && (stage.compression == CBFS_COMPRESS_LZMA)) {
- size_t fsize;
- void *map = rdev_mmap(fh, sizeof(stage), stage.len);
-
- if (map == NULL)
- return -1;
-
- fsize = ulzman(map, stage.len, rmod_loc, stage.memlen);
-
- rdev_munmap(fh, map);
-
- if (!fsize)
- return -1;
- } else
+ if (!cbfs_load_and_decompress(fh, sizeof(stage), stage.len, rmod_loc,
+ stage.memlen, stage.compression))
return -1;
if (rmodule_parse(rmod_loc, &rmod_stage))
diff --git a/src/lib/selfboot.c b/src/lib/selfboot.c
index f3a1e52728..7d3e2dd5f6 100644
--- a/src/lib/selfboot.c
+++ b/src/lib/selfboot.c
@@ -14,6 +14,7 @@
* GNU General Public License for more details.
*/
+#include <commonlib/compression.h>
#include <console/console.h>
#include <cpu/cpu.h>
#include <endian.h>
@@ -25,6 +26,7 @@
#include <lib.h>
#include <bootmem.h>
#include <program_loading.h>
+#include <timestamp.h>
static const unsigned long lb_start = (unsigned long)&_program;
static const unsigned long lb_end = (unsigned long)&_eprogram;
@@ -386,7 +388,18 @@ static int load_self_segments(
switch(ptr->compression) {
case CBFS_COMPRESS_LZMA: {
printk(BIOS_DEBUG, "using LZMA\n");
+ timestamp_add_now(TS_START_ULZMA);
len = ulzman(src, len, dest, memsz);
+ timestamp_add_now(TS_END_ULZMA);
+ if (!len) /* Decompression Error. */
+ return 0;
+ break;
+ }
+ case CBFS_COMPRESS_LZ4: {
+ printk(BIOS_DEBUG, "using LZ4\n");
+ timestamp_add_now(TS_START_ULZ4F);
+ len = ulz4fn(src, len, dest, memsz);
+ timestamp_add_now(TS_END_ULZ4F);
if (!len) /* Decompression Error. */
return 0;
break;