libpayload: Add liblzma, libcbfs

Add cbfs core from coreboot into libpayload, and to support lzma decode,
add coreboot's lzma code, too. Carl-Daniel agreed to relicense the
lzmadecode wrapper as BSD-l, solving licensing problems.

Change-Id: Id28990fe7e951d99447e265a4880d70a8f208dd2
Signed-off-by: Patrick Georgi <patrick.georgi@secunet.com>
Reviewed-on: http://review.coreboot.org/115
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Reviewed-by: Marc Jones <marcj303@gmail.com>
This commit is contained in:
Patrick Georgi 2011-07-21 15:43:14 +02:00 committed by Stefan Reinauer
parent b88351537b
commit 6de1ee4a30
14 changed files with 1065 additions and 4 deletions

View File

@ -129,7 +129,14 @@ config CBFS
bool "CBFS support"
default y
help
CBFS is the archive format of (obsolete) coreboot v3
CBFS is the archive format of coreboot
config LZMA
bool "LZMA decoder"
default y
help
LZMA decoder implementation, usable eg. by CBFS,
but also externally.
endmenu
menu "Console Options"

View File

@ -41,6 +41,8 @@ classes-$(CONFIG_PCI) += libpci
classes-$(CONFIG_LIBC) += libc
classes-$(CONFIG_CURSES) += libcurses
classes-$(CONFIG_PDCURSES) += libmenu libform libpanel
classes-$(CONFIG_CBFS) += libcbfs
classes-$(CONFIG_LZMA) += liblzma
libraries := $(classes-y)
classes-y += head.o
@ -52,6 +54,8 @@ head.o-S-deps = $(obj)/libpayload-config.h
subdirs-y := arch/$(ARCHDIR-y)
subdirs-y += crypto libc drivers libpci
subdirs-$(CONFIG_CURSES) += curses
subdirs-$(CONFIG_CBFS) += libcbfs
subdirs-$(CONFIG_LZMA) += liblzma
INCLUDES := -Iinclude -Iinclude/$(ARCHDIR-y) -I$(obj)
CFLAGS = $(INCLUDES) -O2 -pipe -g

View File

@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# libpayload version: 0.2.0
# Tue Jul 12 15:54:09 2011
# Thu Jul 21 15:45:38 2011
#
#
@ -23,8 +23,11 @@ CONFIG_TARGET_I386=y
# Standard Libraries
#
CONFIG_LIBC=y
CONFIG_CURSES=y
# CONFIG_TINYCURSES is not set
CONFIG_PDCURSES=y
# CONFIG_CBFS is not set
CONFIG_CBFS=y
CONFIG_LZMA=y
#
# Console Options

View File

@ -0,0 +1,2 @@
#include <arch/types.h>
#include "cbfs_core.h"

View File

@ -0,0 +1,180 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net>
*
* This file is dual-licensed. You can choose between:
* - The GNU GPL, version 2, as published by the Free Software Foundation
* - The revised BSD license (without advertising clause)
*
* ---------------------------------------------------------------------------
* 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; version 2 of the License.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
* ---------------------------------------------------------------------------
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ---------------------------------------------------------------------------
*/
#ifndef _CBFS_CORE_H_
#define _CBFS_CORE_H_
/** These are standard values for the known compression
alogrithms that coreboot knows about for stages and
payloads. Of course, other CBFS users can use whatever
values they want, as long as they understand them. */
#define CBFS_COMPRESS_NONE 0
#define CBFS_COMPRESS_LZMA 1
/** These are standard component types for well known
components (i.e - those that coreboot needs to consume.
Users are welcome to use any other value for their
components */
#define CBFS_TYPE_STAGE 0x10
#define CBFS_TYPE_PAYLOAD 0x20
#define CBFS_TYPE_OPTIONROM 0x30
#define CBFS_TYPE_BOOTSPLASH 0x40
#define CBFS_TYPE_RAW 0x50
#define CBFS_TYPE_VSA 0x51
#define CBFS_TYPE_MBI 0x52
#define CBFS_TYPE_MICROCODE 0x53
#define CBFS_COMPONENT_CMOS_DEFAULT 0xaa
#define CBFS_COMPONENT_CMOS_LAYOUT 0x01aa
/** this is the master cbfs header - it need to be
located somewhere in the bootblock. Where it
actually lives is up to coreboot. A pointer to
this header will live at 0xFFFFFFFc, so we can
easily find it. */
#define CBFS_HEADER_MAGIC 0x4F524243
#define CBFS_HEADPTR_ADDR 0xFFFFFFFc
#define VERSION1 0x31313131
struct cbfs_header {
uint32_t magic;
uint32_t version;
uint32_t romsize;
uint32_t bootblocksize;
uint32_t align;
uint32_t offset;
uint32_t pad[2];
} __attribute__((packed));
/** This is a component header - every entry in the CBFS
will have this header.
This is how the component is arranged in the ROM:
-------------- <- 0
component header
-------------- <- sizeof(struct component)
component name
-------------- <- offset
data
...
-------------- <- offset + len
*/
#define CBFS_FILE_MAGIC "LARCHIVE"
struct cbfs_file {
char magic[8];
uint32_t len;
uint32_t type;
uint32_t checksum;
uint32_t offset;
} __attribute__((packed));
/*** Component sub-headers ***/
/* Following are component sub-headers for the "standard"
component types */
/** This is the sub-header for stage components. Stages are
loaded by coreboot during the normal boot process */
struct cbfs_stage {
uint32_t compression; /** Compression type */
uint64_t entry; /** entry point */
uint64_t load; /** Where to load in memory */
uint32_t len; /** length of data to load */
uint32_t memlen; /** total length of object in memory */
} __attribute__((packed));
/** this is the sub-header for payload components. Payloads
are loaded by coreboot at the end of the boot process */
struct cbfs_payload_segment {
uint32_t type;
uint32_t compression;
uint32_t offset;
uint64_t load_addr;
uint32_t len;
uint32_t mem_len;
} __attribute__((packed));
struct cbfs_payload {
struct cbfs_payload_segment segments;
};
#define PAYLOAD_SEGMENT_CODE 0x45444F43
#define PAYLOAD_SEGMENT_DATA 0x41544144
#define PAYLOAD_SEGMENT_BSS 0x20535342
#define PAYLOAD_SEGMENT_PARAMS 0x41524150
#define PAYLOAD_SEGMENT_ENTRY 0x52544E45
struct cbfs_optionrom {
uint32_t compression;
uint32_t len;
} __attribute__((packed));
#define CBFS_NAME(_c) (((char *) (_c)) + sizeof(struct cbfs_file))
#define CBFS_SUBHEADER(_p) ( (void *) ((((uint8_t *) (_p)) + ntohl((_p)->offset))) )
/* returns pointer to file inside CBFS or NULL */
struct cbfs_file *cbfs_find(const char *name);
/* returns pointer to file data inside CBFS */
void *cbfs_get_file(const char *name);
/* returns pointer to file data inside CBFS after if type is correct */
void *cbfs_find_file(const char *name, int type);
/* returns 0 on success, -1 on failure */
int cbfs_decompress(int algo, void *src, void *dst, int len);
#endif

View File

@ -0,0 +1,40 @@
/*
* This file is part of the libpayload project.
*
* Copyright (C) 2011 secunet Security Networks AG
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _LZMA_H
#define _LZMA_H
/* decompresses the data stream at src to dst, determining its length from
* the data stream itself.
*
* returns the decompressed size, or 0 on error
*/
unsigned long ulzma(unsigned char *src, unsigned char *dst);
#endif

View File

@ -38,4 +38,3 @@ libc-$(CONFIG_LIBC) += qsort.c
# should be moved to coreboot directory
libc-$(CONFIG_LAR) += lar.c
#libc-$(CONFIG_CBFS) += cbfs.c

View File

@ -0,0 +1,31 @@
##
## This file is part of the libpayload project.
##
## Copyright (C) 2011 secunet Security Networks AG
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## 1. Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## 2. Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## 3. The name of the author may not be used to endorse or promote products
## derived from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
## ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
## LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
## OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
## SUCH DAMAGE.
##
libcbfs-$(CONFIG_CBFS) += cbfs.c

View File

@ -0,0 +1,78 @@
/*
* This file is part of the libpayload project.
*
* Copyright (C) 2011 secunet Security Networks AG
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <arch/endian.h>
#include <stdio.h>
#include <string.h>
#include <cbfs.h>
#ifdef CONFIG_LZMA
#define CBFS_CORE_WITH_LZMA
#include <lzma.h>
#endif
#define ERROR(x...) printf(x)
#define LOG(x...)
uint32_t host_virt_to_phys(void *addr);
void *host_phys_to_virt(uint32_t addr);
uint32_t romstart(void);
uint32_t romend(void);
#include <arch/virtual.h>
uint32_t host_virt_to_phys(void *addr) {
return virt_to_phys(addr);
}
void *host_phys_to_virt(uint32_t addr) {
return phys_to_virt(addr);
}
#undef virt_to_phys
#undef phys_to_virt
uint32_t (*virt_to_phys)(void *) = host_virt_to_phys;
void* (*phys_to_virt)(uint32_t) = host_phys_to_virt;
uint32_t _romstart = 0xffffffff;
uint32_t _romend = 0;
uint32_t romstart(void)
{
return _romstart;
}
uint32_t romend(void)
{
return _romend;
}
#include "cbfs_core.c"

View File

@ -0,0 +1,174 @@
/*
* This file is part of the libpayload project.
*
* Copyright (C) 2011 secunet Security Networks AG
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* The CBFS core requires a couple of #defines or functions to adapt it to the target environment:
*
* CBFS_CORE_WITH_LZMA (must be #define)
* if defined, ulzma() must exist for decompression of data streams
*
* phys_to_virt(x), virt_to_phys(x)
* translate physical addresses to virtual and vice versa
* can be idempotent if no mapping is necessary.
*
* ERROR(x...)
* print an error message x (in printf format)
*
* LOG(x...)
* print a debug message x (in printf format)
*
* romstart()
* returns the start address of the ROM image, or 0xffffffff if ROM is
* top-aligned. This is a physical address.
*
* romend()
* returns the highest address of the ROM image + 1, for use if
* romstart() == 0xffffffff. This is a physical address.
*/
#include <cbfs_core.h>
/* returns pointer to master header or 0xffffffff if not found */
static struct cbfs_header *get_cbfs_header(void)
{
struct cbfs_header *header;
/* find header */
if (romstart() == 0xffffffff) {
header = (struct cbfs_header*)phys_to_virt(*(uint32_t*)phys_to_virt(romend() + CBFS_HEADPTR_ADDR));
} else {
// FIXME: where's the master header on ARM (our current bottom-aligned platform)?
header = NULL;
}
if (CBFS_HEADER_MAGIC != ntohl(header->magic)) {
ERROR("Could not find valid CBFS master header at %p: %x vs %x.\n", header, CBFS_HEADER_MAGIC, ntohl(header->magic));
if (header->magic == 0xffffffff) {
ERROR("Maybe ROM is not mapped properly?\n");
}
return (void*)0xffffffff;
}
return header;
}
// by must be power-of-two
#define CBFS_ALIGN(val, by) (typeof(val))((uint32_t)(val + by - 1) & (uint32_t)~(by - 1))
#define CBFS_ALIGN_UP(val, by) CBFS_ALIGN(val + 1, by)
/* public API starts here*/
struct cbfs_file *cbfs_find(const char *name)
{
struct cbfs_header *header = get_cbfs_header();
if (header == (void*)0xffffffff) return NULL;
LOG("Searching for %s\n", name);
void *data, *dataend, *origdata;
/* find first entry */
if (romstart() == 0xffffffff) {
data = (void*)phys_to_virt(romend()) - ntohl(header->romsize) + ntohl(header->offset);
dataend = (void*)phys_to_virt(romend());
} else {
data = (void*)phys_to_virt(romstart()) + ntohl(header->offset);
dataend = (void*)phys_to_virt(romstart()) + ntohl(header->romsize);
}
int align = ntohl(header->align);
origdata = data;
while ((data < (dataend - 1)) && (data >= origdata)) {
struct cbfs_file *file = data;
if (memcmp(CBFS_FILE_MAGIC, file->magic, strlen(CBFS_FILE_MAGIC)) != 0) {
// no file header found. corruption?
// proceed in aligned steps to resynchronize
LOG("No file header found at %p, searching for header\n", data);
data = phys_to_virt(CBFS_ALIGN_UP(virt_to_phys(data), align));
continue;
}
LOG("Check %s\n", CBFS_NAME(file));
if (strcmp(CBFS_NAME(file), name) == 0) {
return file;
}
void *olddata = data;
data = phys_to_virt(CBFS_ALIGN(virt_to_phys(data) + ntohl(file->len) + ntohl(file->offset), align));
if (olddata > data) {
LOG("Something is wrong here. File chain moved from %p to %p\n", olddata, data);
return NULL;
}
}
return NULL;
}
void *cbfs_get_file(const char *name)
{
struct cbfs_file *file = cbfs_find(name);
if (file == NULL) {
ERROR("Could not find file '%s'.\n", name);
return NULL;
}
return (void*)CBFS_SUBHEADER(file);
}
void *cbfs_find_file(const char *name, int type)
{
struct cbfs_file *file = cbfs_find(name);
if (file == NULL) {
ERROR("Could not find file '%s'.\n", name);
return NULL;
}
if (ntohl(file->type) != type) {
ERROR("File '%s' is of type %x, but we requested %x.\n", name, ntohl(file->type), type);
return NULL;
}
return (void*)CBFS_SUBHEADER(file);
}
int cbfs_decompress(int algo, void *src, void *dst, int len)
{
switch (algo) {
case CBFS_COMPRESS_NONE:
memcpy(dst, src, len);
return 0;
#ifdef CBFS_CORE_WITH_LZMA
case CBFS_COMPRESS_LZMA:
if (ulzma(src, dst) != 0) {
return 0;
}
return -1;
#endif
default:
ERROR("tried to decompress %d bytes with algorithm #%x, but that algorithm id is unsupported.\n", len, algo);
return -1;
}
}

View File

@ -0,0 +1,31 @@
##
## This file is part of the libpayload project.
##
## Copyright (C) 2011 secunet Security Networks AG
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## 1. Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## 2. Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## 3. The name of the author may not be used to endorse or promote products
## derived from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
## ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
## LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
## OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
## SUCH DAMAGE.
##
liblzma-$(CONFIG_LZMA) += lzma.c

View File

@ -0,0 +1,47 @@
/*
* coreboot interface to memory-saving variant of LZMA decoder
*
* Copyright (C) 2006 Carl-Daniel Hailfinger
* Released under the BSD license
*
* Parts of this file are based on C/7zip/Compress/LZMA_C/LzmaTest.c from the LZMA
* SDK 4.42, which is written and distributed to public domain by Igor Pavlov.
*
*/
#include <lzma.h>
#include <stdio.h>
#include <string.h>
#include "lzmadecode.c"
unsigned long ulzma(unsigned char * src, unsigned char * dst)
{
unsigned char properties[LZMA_PROPERTIES_SIZE];
UInt32 outSize;
SizeT inProcessed;
SizeT outProcessed;
int res;
CLzmaDecoderState state;
SizeT mallocneeds;
unsigned char scratchpad[15980];
memcpy(properties, src, LZMA_PROPERTIES_SIZE);
outSize = *(UInt32 *)(src + LZMA_PROPERTIES_SIZE);
if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) {
printf("lzma: Incorrect stream properties.\n");
return 0;
}
mallocneeds = (LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
if (mallocneeds > 15980) {
printf("lzma: Decoder scratchpad too small!\n");
return 0;
}
state.Probs = (CProb *)scratchpad;
res = LzmaDecode(&state, src + LZMA_PROPERTIES_SIZE + 8, (SizeT)0xffffffff, &inProcessed,
dst, outSize, &outProcessed);
if (res != 0) {
printf("lzma: Decoding error = %d\n", res);
return 0;
}
return outSize;
}

View File

@ -0,0 +1,398 @@
/*
LzmaDecode.c
LZMA Decoder (optimized for Speed version)
LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
http://www.7-zip.org/
LZMA SDK is licensed under two licenses:
1) GNU Lesser General Public License (GNU LGPL)
2) Common Public License (CPL)
It means that you can select one of these two licenses and
follow rules of that license.
SPECIAL EXCEPTION:
Igor Pavlov, as the author of this Code, expressly permits you to
statically or dynamically link your Code (or bind by name) to the
interfaces of this file without subjecting your linked Code to the
terms of the CPL or GNU LGPL. Any modifications or additions
to this file, however, are subject to the LGPL or CPL terms.
*/
#include "lzmadecode.h"
#define kNumTopBits 24
#define kTopValue ((UInt32)1 << kNumTopBits)
#define kNumBitModelTotalBits 11
#define kBitModelTotal (1 << kNumBitModelTotalBits)
#define kNumMoveBits 5
#define RC_READ_BYTE (*Buffer++)
#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
{ int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
{ UpdateBit0(p); mi <<= 1; A0; } else \
{ UpdateBit1(p); mi = (mi + mi) + 1; A1; }
#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
{ int i = numLevels; res = 1; \
do { CProb *cp = probs + res; RC_GET_BIT(cp, res) } while(--i != 0); \
res -= (1 << numLevels); }
#define kNumPosBitsMax 4
#define kNumPosStatesMax (1 << kNumPosBitsMax)
#define kLenNumLowBits 3
#define kLenNumLowSymbols (1 << kLenNumLowBits)
#define kLenNumMidBits 3
#define kLenNumMidSymbols (1 << kLenNumMidBits)
#define kLenNumHighBits 8
#define kLenNumHighSymbols (1 << kLenNumHighBits)
#define LenChoice 0
#define LenChoice2 (LenChoice + 1)
#define LenLow (LenChoice2 + 1)
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
#define kNumStates 12
#define kNumLitStates 7
#define kStartPosModelIndex 4
#define kEndPosModelIndex 14
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
#define kNumPosSlotBits 6
#define kNumLenToPosStates 4
#define kNumAlignBits 4
#define kAlignTableSize (1 << kNumAlignBits)
#define kMatchMinLen 2
#define IsMatch 0
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
#define IsRepG0 (IsRep + kNumStates)
#define IsRepG1 (IsRepG0 + kNumStates)
#define IsRepG2 (IsRepG1 + kNumStates)
#define IsRep0Long (IsRepG2 + kNumStates)
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
#define LenCoder (Align + kAlignTableSize)
#define RepLenCoder (LenCoder + kNumLenProbs)
#define Literal (RepLenCoder + kNumLenProbs)
#if Literal != LZMA_BASE_SIZE
StopCompilingDueBUG
#endif
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
{
unsigned char prop0;
if (size < LZMA_PROPERTIES_SIZE)
return LZMA_RESULT_DATA_ERROR;
prop0 = propsData[0];
if (prop0 >= (9 * 5 * 5))
return LZMA_RESULT_DATA_ERROR;
{
for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
propsRes->lc = prop0;
/*
unsigned char remainder = (unsigned char)(prop0 / 9);
propsRes->lc = prop0 % 9;
propsRes->pb = remainder / 5;
propsRes->lp = remainder % 5;
*/
}
return LZMA_RESULT_OK;
}
#define kLzmaStreamWasFinishedId (-1)
int LzmaDecode(CLzmaDecoderState *vs,
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
{
CProb *p = vs->Probs;
SizeT nowPos = 0;
Byte previousByte = 0;
UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
int lc = vs->Properties.lc;
int state = 0;
UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
int len = 0;
const Byte *Buffer;
const Byte *BufferLim;
UInt32 Range;
UInt32 Code;
*inSizeProcessed = 0;
*outSizeProcessed = 0;
{
UInt32 i;
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
for (i = 0; i < numProbs; i++)
p[i] = kBitModelTotal >> 1;
}
RC_INIT(inStream, inSize);
while(nowPos < outSize)
{
CProb *prob;
UInt32 bound;
int posState = (int)(
(nowPos
)
& posStateMask);
prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
IfBit0(prob)
{
int symbol = 1;
UpdateBit0(prob)
prob = p + Literal + (LZMA_LIT_SIZE *
(((
(nowPos
)
& literalPosMask) << lc) + (previousByte >> (8 - lc))));
if (state >= kNumLitStates)
{
int matchByte;
matchByte = outStream[nowPos - rep0];
do
{
int bit;
CProb *probLit;
matchByte <<= 1;
bit = (matchByte & 0x100);
probLit = prob + 0x100 + bit + symbol;
RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
}
while (symbol < 0x100);
}
while (symbol < 0x100)
{
CProb *probLit = prob + symbol;
RC_GET_BIT(probLit, symbol)
}
previousByte = (Byte)symbol;
outStream[nowPos++] = previousByte;
if (state < 4) state = 0;
else if (state < 10) state -= 3;
else state -= 6;
}
else
{
UpdateBit1(prob);
prob = p + IsRep + state;
IfBit0(prob)
{
UpdateBit0(prob);
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
state = state < kNumLitStates ? 0 : 3;
prob = p + LenCoder;
}
else
{
UpdateBit1(prob);
prob = p + IsRepG0 + state;
IfBit0(prob)
{
UpdateBit0(prob);
prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
IfBit0(prob)
{
UpdateBit0(prob);
if (nowPos == 0)
return LZMA_RESULT_DATA_ERROR;
state = state < kNumLitStates ? 9 : 11;
previousByte = outStream[nowPos - rep0];
outStream[nowPos++] = previousByte;
continue;
}
else
{
UpdateBit1(prob);
}
}
else
{
UInt32 distance;
UpdateBit1(prob);
prob = p + IsRepG1 + state;
IfBit0(prob)
{
UpdateBit0(prob);
distance = rep1;
}
else
{
UpdateBit1(prob);
prob = p + IsRepG2 + state;
IfBit0(prob)
{
UpdateBit0(prob);
distance = rep2;
}
else
{
UpdateBit1(prob);
distance = rep3;
rep3 = rep2;
}
rep2 = rep1;
}
rep1 = rep0;
rep0 = distance;
}
state = state < kNumLitStates ? 8 : 11;
prob = p + RepLenCoder;
}
{
int numBits, offset;
CProb *probLen = prob + LenChoice;
IfBit0(probLen)
{
UpdateBit0(probLen);
probLen = prob + LenLow + (posState << kLenNumLowBits);
offset = 0;
numBits = kLenNumLowBits;
}
else
{
UpdateBit1(probLen);
probLen = prob + LenChoice2;
IfBit0(probLen)
{
UpdateBit0(probLen);
probLen = prob + LenMid + (posState << kLenNumMidBits);
offset = kLenNumLowSymbols;
numBits = kLenNumMidBits;
}
else
{
UpdateBit1(probLen);
probLen = prob + LenHigh;
offset = kLenNumLowSymbols + kLenNumMidSymbols;
numBits = kLenNumHighBits;
}
}
RangeDecoderBitTreeDecode(probLen, numBits, len);
len += offset;
}
if (state < 4)
{
int posSlot;
state += kNumLitStates;
prob = p + PosSlot +
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
kNumPosSlotBits);
RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
if (posSlot >= kStartPosModelIndex)
{
int numDirectBits = ((posSlot >> 1) - 1);
rep0 = (2 | ((UInt32)posSlot & 1));
if (posSlot < kEndPosModelIndex)
{
rep0 <<= numDirectBits;
prob = p + SpecPos + rep0 - posSlot - 1;
}
else
{
numDirectBits -= kNumAlignBits;
do
{
RC_NORMALIZE
Range >>= 1;
rep0 <<= 1;
if (Code >= Range)
{
Code -= Range;
rep0 |= 1;
}
}
while (--numDirectBits != 0);
prob = p + Align;
rep0 <<= kNumAlignBits;
numDirectBits = kNumAlignBits;
}
{
int i = 1;
int mi = 1;
do
{
CProb *prob3 = prob + mi;
RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
i <<= 1;
}
while(--numDirectBits != 0);
}
}
else
rep0 = posSlot;
if (++rep0 == (UInt32)(0))
{
/* it's for stream version */
len = kLzmaStreamWasFinishedId;
break;
}
}
len += kMatchMinLen;
if (rep0 > nowPos)
return LZMA_RESULT_DATA_ERROR;
do
{
previousByte = outStream[nowPos - rep0];
len--;
outStream[nowPos++] = previousByte;
}
while(len != 0 && nowPos < outSize);
}
}
RC_NORMALIZE;
*inSizeProcessed = (SizeT)(Buffer - inStream);
*outSizeProcessed = nowPos;
return LZMA_RESULT_OK;
}

View File

@ -0,0 +1,67 @@
/*
LzmaDecode.h
LZMA Decoder interface
LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
http://www.7-zip.org/
LZMA SDK is licensed under two licenses:
1) GNU Lesser General Public License (GNU LGPL)
2) Common Public License (CPL)
It means that you can select one of these two licenses and
follow rules of that license.
SPECIAL EXCEPTION:
Igor Pavlov, as the author of this code, expressly permits you to
statically or dynamically link your code (or bind by name) to the
interfaces of this file without subjecting your linked code to the
terms of the CPL or GNU LGPL. Any modifications or additions
to this file, however, are subject to the LGPL or CPL terms.
*/
#ifndef __LZMADECODE_H
#define __LZMADECODE_H
typedef unsigned char Byte;
typedef unsigned short UInt16;
typedef unsigned int UInt32;
typedef UInt32 SizeT;
#define CProb UInt16
#define LZMA_RESULT_OK 0
#define LZMA_RESULT_DATA_ERROR 1
#define LZMA_BASE_SIZE 1846
#define LZMA_LIT_SIZE 768
#define LZMA_PROPERTIES_SIZE 5
typedef struct _CLzmaProperties
{
int lc;
int lp;
int pb;
}CLzmaProperties;
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
#define kLzmaNeedInitId (-2)
typedef struct _CLzmaDecoderState
{
CLzmaProperties Properties;
CProb *Probs;
} CLzmaDecoderState;
int LzmaDecode(CLzmaDecoderState *vs,
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
#endif