From 5d01ec0f80cc8379df17ed9a922de37b487770b4 Mon Sep 17 00:00:00 2001 From: "Ronald G. Minnich" Date: Tue, 31 Mar 2009 11:57:36 +0000 Subject: This patch adds Jordan's romtool support for v2. There are a few changes. The 20K bootblock size restriction is gone. ROMFS has been tested and works on v2 with qemu and kontron. Once this patch is in, those patches will follow. Signed-off-by: Ronald G. Minnich Acked-by: Patrick Georgi git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4032 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- util/romtool/tools/lzma/minilzma.cc | 318 ++++++++++++++++++++++++++++++++++++ 1 file changed, 318 insertions(+) create mode 100644 util/romtool/tools/lzma/minilzma.cc (limited to 'util/romtool/tools/lzma/minilzma.cc') diff --git a/util/romtool/tools/lzma/minilzma.cc b/util/romtool/tools/lzma/minilzma.cc new file mode 100644 index 0000000000..7610910a19 --- /dev/null +++ b/util/romtool/tools/lzma/minilzma.cc @@ -0,0 +1,318 @@ +/* + * minimal lzma implementation + * + * Copyright (C) 2002 Eric Biederman + * Copyright (C) 2005 Joel Yliluoma + * Copyright (C) 2007 coresystems GmbH + * (Adapted by Stefan Reinauer for coresystems GmbH) + * Copyright (C) 2007 Patrick Georgi + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 + */ + +#include "C/Common/MyInitGuid.h" +#include "C/7zip/Compress/LZMA/LZMAEncoder.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +const std::vector LZMACompress + (const std::vector& buf); + +const std::vector LZMADeCompress + (const std::vector& buf); + +static inline uint16_t R16(const void* p) +{ + const unsigned char* data = (const unsigned char*)p; + return (data[0] << 0) | (data[1] << 8); +} +static inline uint32_t R32(const void* p) +{ + const unsigned char* data = (const unsigned char*)p; + return R16(data) | (R16(data+2) << 16); +} + +#define L (uint64_t) + +static inline uint64_t R64(const void* p) +{ + const unsigned char* data = (const unsigned char*)p; + return (L R32(data)) | ((L R32(data+4)) << 32); +} + +#undef L + +static UInt32 SelectDictionarySizeFor(unsigned datasize) +{ + #if 1 + return datasize; + #else +#ifdef __GNUC__ + /* gnu c can optimize this switch statement into a fast binary + * search, but it cannot do so for the list of the if statements. + */ + switch(datasize) + { + case 0 ... 512 : return 512; + case 513 ... 1024: return 2048; + case 1025 ... 4096: return 8192; + case 4097 ... 16384: return 32768; + case 16385 ... 65536: return 528288; + case 65537 ... 528288: return 1048576*4; + case 528289 ... 786432: return 1048576*16; + default: return 1048576*32; + } +#else + if(datasize <= 512) return 512; + if(datasize <= 1024) return 1024; + if(datasize <= 4096) return 4096; + if(datasize <= 16384) return 32768; + if(datasize <= 65536) return 528288; + if(datasize <= 528288) return 1048576*4; + if(datasize <= 786432) reutrn 1048576*16; + return 32*1048576; +#endif + #endif +} + + +class CInStreamRam: public ISequentialInStream, public CMyUnknownImp +{ + const std::vector& input; + size_t Pos; +public: + MY_UNKNOWN_IMP + + CInStreamRam(const std::vector& buf) : input(buf), Pos(0) + { + } + virtual ~CInStreamRam() {} + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CInStreamRam::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 remain = input.size() - Pos; + if (size > remain) size = remain; + + std::memcpy(data, &input[Pos], size); + Pos += size; + + if(processedSize != NULL) *processedSize = size; + + return S_OK; +} + +class COutStreamRam: public ISequentialOutStream, public CMyUnknownImp +{ + std::vector result; + size_t Pos; +public: + MY_UNKNOWN_IMP + + COutStreamRam(): result(), Pos(0) { } + virtual ~COutStreamRam() { } + + void Reserve(unsigned n) { result.reserve(n); } + const std::vector& Get() const { return result; } + + HRESULT WriteByte(Byte b) + { + if(Pos >= result.size()) result.resize(Pos+1); + result[Pos++] = b; + return S_OK; + } + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP COutStreamRam::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if(Pos+size > result.size()) result.resize(Pos+size); + + std::memcpy(&result[Pos], data, size); + if(processedSize != NULL) *processedSize = size; + Pos += size; + return S_OK; +} + +const std::vector LZMACompress(const std::vector& buf) +{ + if(buf.empty()) return buf; + + const UInt32 dictionarysize = SelectDictionarySizeFor(buf.size()); + + NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; + CMyComPtr encoder = encoderSpec; + const PROPID propIDs[] = + { + NCoderPropID::kAlgorithm, + NCoderPropID::kDictionarySize, + NCoderPropID::kNumFastBytes, + }; + const unsigned kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); + PROPVARIANT properties[kNumProps]; + properties[0].vt = VT_UI4; properties[0].ulVal = (UInt32)2; + properties[1].vt = VT_UI4; properties[1].ulVal = (UInt32)dictionarysize; + properties[2].vt = VT_UI4; properties[2].ulVal = (UInt32)64; + + if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) + { + Error: + return std::vector (); + } + + COutStreamRam *const outStreamSpec = new COutStreamRam; + CMyComPtr outStream = outStreamSpec; + CInStreamRam *const inStreamSpec = new CInStreamRam(buf); + CMyComPtr inStream = inStreamSpec; + + outStreamSpec->Reserve(buf.size()); + + if (encoderSpec->WriteCoderProperties(outStream) != S_OK) goto Error; + + for (unsigned i = 0; i < 8; i++) + { + UInt64 t = (UInt64)buf.size(); + outStreamSpec->WriteByte((Byte)((t) >> (8 * i))); + } + + HRESULT lzmaResult = encoder->Code(inStream, outStream, 0, 0, 0); + if (lzmaResult != S_OK) goto Error; + + return outStreamSpec->Get(); +} + +#undef RC_NORMALIZE + +#include "C/7zip/Decompress/LzmaDecode.h" +#include "C/7zip/Decompress/LzmaDecode.c" + +const std::vector LZMADeCompress + (const std::vector& buf) +{ + if(buf.size() <= 5+8) return std::vector (); + + uint_least64_t out_sizemax = R64(&buf[5]); + + std::vector result(out_sizemax); + + CLzmaDecoderState state; + LzmaDecodeProperties(&state.Properties, &buf[0], LZMA_PROPERTIES_SIZE); + state.Probs = new CProb[LzmaGetNumProbs(&state.Properties)]; + + SizeT in_done; + SizeT out_done; + LzmaDecode(&state, &buf[13], buf.size()-13, &in_done, + &result[0], result.size(), &out_done); + + delete[] state.Probs; + + result.resize(out_done); + return result; +} + +#ifndef COMPACT +int main(int argc, char *argv[]) +{ + char *s; + FILE *f, *infile, *outfile; + int c; + + if (argc != 4) { + std::fprintf(stderr, "'lzma e file1 file2' encodes file1 into file2.\n" + "'lzma d file2 file1' decodes file2 into file1.\n"); + + return EXIT_FAILURE; + } + if (argc == 4) { + if ((s = argv[1], s[1] || strpbrk(s, "DEde") == NULL) + || (s = argv[2], (infile = fopen(s, "rb")) == NULL) + || (s = argv[3], (outfile = fopen(s, "wb")) == NULL)) { + std::fprintf(stderr, "??? %s\n", s); + return EXIT_FAILURE; + } + } + + struct stat fs; + int si; + if (fstat(fileno(infile), &fs)) { + std::perror(strerror(errno)); + return EXIT_FAILURE; + } + si=fs.st_size; + + char *Buf=(char *)malloc(si); + fread(Buf,si, 1, infile); + + std::vector result; + if (toupper(*argv[1]) == 'E') + result = LZMACompress(std::vector(Buf,Buf+si)); + else + result = LZMADeCompress(std::vector(Buf,Buf+si)); + + fwrite(&result[0], result.size(), 1, outfile); + fclose(infile); + fclose(outfile); + return EXIT_SUCCESS; +} +#else +extern "C" { + +/** + * Compress a buffer with lzma + * Don't copy the result back if it is too large. + * @param in a pointer to the buffer + * @param in_len the length in bytes + * @param out a pointer to a buffer of at least size in_len + * @param out_len a pointer to the compressed length of in + */ + +void do_lzma_compress(char *in, int in_len, char *out, int *out_len) { + std::vector result; + result = LZMACompress(std::vector(in, in + in_len)); + *out_len = result.size(); + if (*out_len < in_len) + std::memcpy(out, &result[0], *out_len); +} + +void do_lzma_uncompress(char *dst, int dst_len, char *src, int src_len) { + std::vector result; + result = LZMADeCompress(std::vector(src, src + src_len)); + if (result.size() <= dst_len) + std::memcpy(dst, &result[0], result.size()); + else + { + fprintf(stderr, "Not copying %d bytes to %d-byte buffer!\n", + result.size(), dst_len); + exit(1); + } +} + +} +#endif + -- cgit v1.2.3