Author: oxygene Date: 2009-08-28 00:52:37 +0200 (Fri, 28 Aug 2009) New Revision: 105
Added: trunk/filo/fs/cbfs.c trunk/filo/fs/fsys_cbfs.c trunk/filo/fs/lzma.c trunk/filo/fs/lzmadecode.c trunk/filo/fs/lzmadecode.h trunk/filo/include/cbfs.h Modified: trunk/filo/Config.in trunk/filo/configs/defconfig trunk/filo/fs/Makefile.inc trunk/filo/fs/filesys.h trunk/filo/fs/vfs.c Log: add CBFS support
Modified: trunk/filo/Config.in =================================================================== --- trunk/filo/Config.in 2009-08-06 10:21:41 UTC (rev 104) +++ trunk/filo/Config.in 2009-08-27 22:52:37 UTC (rev 105) @@ -213,6 +213,10 @@ bool "Squash filesystem" default n
+config FSYS_CBFS + bool "CBFS ROM Image filesystem" + default y + endmenu
menu "Loaders"
Modified: trunk/filo/configs/defconfig =================================================================== --- trunk/filo/configs/defconfig 2009-08-06 10:21:41 UTC (rev 104) +++ trunk/filo/configs/defconfig 2009-08-27 22:52:37 UTC (rev 105) @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # FILO version: 0.6.0 -# Wed Apr 29 21:18:12 2009 +# Fri Aug 28 00:51:59 2009 # CONFIG_TARGET_I386=y # CONFIG_REVIEW is not set @@ -39,6 +39,7 @@ CONFIG_ELTORITO=y # CONFIG_FSYS_CRAMFS is not set # CONFIG_FSYS_SQUASHFS is not set +CONFIG_FSYS_CBFS=y
# # Loaders
Modified: trunk/filo/fs/Makefile.inc =================================================================== --- trunk/filo/fs/Makefile.inc 2009-08-06 10:21:41 UTC (rev 104) +++ trunk/filo/fs/Makefile.inc 2009-08-27 22:52:37 UTC (rev 105) @@ -30,4 +30,6 @@ TARGETS-$(CONFIG_FSYS_SQUASHFS) += fs/fsys_squashfs.o TARGETS-$(CONFIG_FSYS_SQUASHFS) += fs/squashfs_zlib.o TARGETS-$(CONFIG_ARTEC_BOOT) += fs/fsys_aboot.o - +TARGETS-$(CONFIG_FSYS_CBFS) += fs/fsys_cbfs.o +TARGETS-$(CONFIG_FSYS_CBFS) += fs/cbfs.o +TARGETS-$(CONFIG_FSYS_CBFS) += fs/lzma.o
Added: trunk/filo/fs/cbfs.c =================================================================== --- trunk/filo/fs/cbfs.c (rev 0) +++ trunk/filo/fs/cbfs.c 2009-08-27 22:52:37 UTC (rev 105) @@ -0,0 +1,236 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008, Jordan Crouse jordan@cosmicpenguin.net + * + * 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 + */ + +#include <arch/types.h> +#include <arch/virtual.h> +#include <cbfs.h> + +#define ALIGN(val,by) ((val+by-1)&~(by-1)) +#define cbfs_printf(...) /* printf(__VA_ARGS__) */ +#define printk_spew cbfs_printf +#define printk_debug cbfs_printf +#define printk_info cbfs_printf +#define printk_err cbfs_printf + +#ifndef CONFIG_BIG_ENDIAN +#define ntohl(x) ( ((x&0xff)<<24) | ((x&0xff00)<<8) | \ + ((x&0xff0000) >> 8) | ((x&0xff000000) >> 24) ) +#else +#define ntohl(x) (x) +#endif + +int cbfs_decompress(int algo, void *src, void *dst, int len) +{ + switch(algo) { + case CBFS_COMPRESS_NONE: + memcpy(dst, src, len); + return 0; + + case CBFS_COMPRESS_LZMA: { + unsigned long ulzma(unsigned char *src, unsigned char *dst); + ulzma(src, dst); + } + return 0; + + default: + printk_info( "CBFS: Unknown compression type %d\n", + algo); + return -1; + } +} + +int cbfs_check_magic(struct cbfs_file *file) +{ + return !strcmp(file->magic, CBFS_FILE_MAGIC) ? 1 : 0; +} + +struct cbfs_header *cbfs_master_header(void) +{ + struct cbfs_header *header; + + void *ptr = phys_to_virt((void *)*((unsigned long *) phys_to_virt(CBFS_HEADPTR_ADDR))); + printk_spew("Check CBFS header at %p\n", ptr); + header = (struct cbfs_header *) ptr; + + printk_spew("magic is %08x\n", ntohl(header->magic)); + if (ntohl(header->magic) != CBFS_HEADER_MAGIC) { + printk_err("ERROR: No valid CBFS header found!\n"); + return NULL; + } + + printk_spew("Found CBFS header at %p\n", ptr); + return header; +} + +struct cbfs_file *cbfs_find(const char *name) +{ + struct cbfs_header *header = cbfs_master_header(); + unsigned long offset; + + if (header == NULL) + return NULL; + offset = phys_to_virt(0 - ntohl(header->romsize) + ntohl(header->offset)); + + int align= ntohl(header->align); + + while(1) { + struct cbfs_file *file = (struct cbfs_file *) offset; + if (!cbfs_check_magic(file)) return NULL; + printk_debug("Check %s\n", CBFS_NAME(file)); + if (!strcmp(CBFS_NAME(file), name)) + return file; + + int flen = ntohl(file->len); + int foffset = ntohl(file->offset); + printk_spew("CBFS: follow chain: %p + %x + %x + align -> ", (void *)offset, foffset, flen); + + unsigned long oldoffset = offset; + offset = ALIGN(offset + foffset + flen, align); + printk_spew("%p\n", (void *)offset); + if (virt_to_phys(offset) <= virt_to_phys(oldoffset)) return NULL; + + if (offset < phys_to_virt(0xFFFFFFFF - ntohl(header->romsize))) + return NULL; + } +} + +struct cbfs_stage *cbfs_find_file(const char *name, int type) +{ + struct cbfs_file *file = cbfs_find(name); + + if (file == NULL) { + printk_info( "CBFS: Could not find file %s\n", + name); + return NULL; + } + + if (ntohl(file->type) != type) { + printk_info( "CBFS: File %s is of type %x instead of" + "type %x\n", name, file->type, type); + + return NULL; + } + + return (void *) CBFS_SUBHEADER(file); +} + +void *cbfs_load_optionrom(u16 vendor, u16 device, void * dest) +{ + char name[17]; + struct cbfs_optionrom *orom; + u8 *src; + + sprintf(name,"pci%04x,%04x.rom", vendor, device); + + orom = (struct cbfs_optionrom *) + cbfs_find_file(name, CBFS_TYPE_OPTIONROM); + + if (orom == NULL) + return NULL; + + /* They might have specified a dest address. If so, we can decompress. + * If not, there's not much hope of decompressing or relocating the rom. + * in the common case, the expansion rom is uncompressed, we + * pass 0 in for the dest, and all we have to do is find the rom and + * return a pointer to it. + */ + + /* BUG: the cbfstool is (not yet) including a cbfs_optionrom header */ + src = ((unsigned char *) orom); // + sizeof(struct cbfs_optionrom); + + if (! dest) + return src; + + if (cbfs_decompress(ntohl(orom->compression), + src, + dest, + ntohl(orom->len))) + return NULL; + + return dest; +} + +void * cbfs_load_stage(const char *name) +{ + struct cbfs_stage *stage = (struct cbfs_stage *) + cbfs_find_file(name, CBFS_TYPE_STAGE); + /* this is a mess. There is no ntohll. */ + /* for now, assume compatible byte order until we solve this. */ + u32 entry; + + if (stage == NULL) + return (void *) -1; + + printk_info("Stage: load %s @ %d/%d bytes, enter @ %llx\n", + name, + (u32) stage->load, stage->memlen, + stage->entry); + memset((void *) (u32) stage->load, 0, stage->memlen); + + if (cbfs_decompress(stage->compression, + ((unsigned char *) stage) + + sizeof(struct cbfs_stage), + (void *) (u32) stage->load, + stage->len)) + return (void *) -1; + printk_info("Stage: done loading.\n"); + + entry = stage->entry; +// return (void *) ntohl((u32) stage->entry); + return (void *) entry; +} + +void * cbfs_get_file(const char *name) +{ + return cbfs_find(name); +} + +int cbfs_execute_stage(const char *name) +{ + struct cbfs_stage *stage = (struct cbfs_stage *) + cbfs_find_file(name, CBFS_TYPE_STAGE); + + if (stage == NULL) + return 1; + + if (ntohl(stage->compression) != CBFS_COMPRESS_NONE) { + printk_info( "CBFS: Unable to run %s: Compressed file" + "Not supported for in-place execution\n", name); + return 1; + } + + /* FIXME: This isn't right */ + printk_info( "CBFS: run @ %p\n", (void *) ntohl((u32) stage->entry)); + return run_address((void *) ntohl((u32) stage->entry)); +} + +/** + * run_address is passed the address of a function taking no parameters and + * jumps to it, returning the result. + * @param f the address to call as a function. + * returns value returned by the function. + */ + +int run_address(void *f) +{ + int (*v) (void); + v = f; + return v(); +} +
Modified: trunk/filo/fs/filesys.h =================================================================== --- trunk/filo/fs/filesys.h 2009-08-06 10:21:41 UTC (rev 104) +++ trunk/filo/fs/filesys.h 2009-08-27 22:52:37 UTC (rev 105) @@ -162,6 +162,12 @@ int fat_dir (char *dirname); #endif
+#ifdef CONFIG_FSYS_CBFS +int cbfs_mount (void); +int cbfs_read (char *buf, int len); +int cbfs_dir (char *dirname); +#endif + #ifdef CONFIG_FSYS_EXT2FS int ext2fs_mount (void); int ext2fs_read (char *buf, int len);
Added: trunk/filo/fs/fsys_cbfs.c =================================================================== --- trunk/filo/fs/fsys_cbfs.c (rev 0) +++ trunk/filo/fs/fsys_cbfs.c 2009-08-27 22:52:37 UTC (rev 105) @@ -0,0 +1,66 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000,2001,2005 Free Software Foundation, Inc. + * Copyright (C) 2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, + * as published by the Free Software Foundation. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "filesys.h" +#include <cbfs.h> + +struct cbfs_file *file; +void* fileptr; + +int +cbfs_mount (void) +{ + /* Check if it's a 4GB device (ie. RAM) */ + if (part_length != (1<<(32-9))) + return 0; + + /* CBFS? */ + if (!cbfs_master_header()) + return 0; + + return 1; +} + +int +cbfs_read (char *buf, int len) +{ + if (filepos + len > filemax) { + len = filemax - filepos; + } + memcpy(buf, fileptr+filepos, len); + filepos+=len; + return len; +} + +int +cbfs_dir (char *dirname) +{ + if (dirname[0]=='/') dirname++; + file = cbfs_find(dirname); + if (!file) { + errnum = ERR_FILE_NOT_FOUND; + return 0; + } + + filepos = 0; + filemax = ntohl(file->len); + fileptr = (void*)file+ntohl(file->offset); + return 1; +} +
Added: trunk/filo/fs/lzma.c =================================================================== --- trunk/filo/fs/lzma.c (rev 0) +++ trunk/filo/fs/lzma.c 2009-08-27 22:52:37 UTC (rev 105) @@ -0,0 +1,47 @@ +/* + +Coreboot interface to memory-saving variant of LZMA decoder + +(C)opyright 2006 Carl-Daniel Hailfinger +Released under the GNU GPL v2 or later + +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 "lzmadecode.c" +#define printk_warning printf + + +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) { + printk_warning("lzma: Incorrect stream properties.\n"); + return 0; + } + mallocneeds = (LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); + if (mallocneeds > 15980) { + printk_warning("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) { + printk_warning("lzma: Decoding error = %d\n", res); + return 0; + } + return outSize; +}
Added: trunk/filo/fs/lzmadecode.c =================================================================== --- trunk/filo/fs/lzmadecode.c (rev 0) +++ trunk/filo/fs/lzmadecode.c 2009-08-27 22:52:37 UTC (rev 105) @@ -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; +}
Added: trunk/filo/fs/lzmadecode.h =================================================================== --- trunk/filo/fs/lzmadecode.h (rev 0) +++ trunk/filo/fs/lzmadecode.h 2009-08-27 22:52:37 UTC (rev 105) @@ -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
Modified: trunk/filo/fs/vfs.c =================================================================== --- trunk/filo/fs/vfs.c 2009-08-06 10:21:41 UTC (rev 104) +++ trunk/filo/fs/vfs.c 2009-08-27 22:52:37 UTC (rev 105) @@ -47,6 +47,9 @@ };
struct fsys_entry fsys_table[] = { +# ifdef CONFIG_FSYS_CBFS + {"CBFS ROM Image", cbfs_mount, cbfs_read, cbfs_dir, 0, 0}, +# endif # ifdef CONFIG_FSYS_FAT {"FAT filesystem", fat_mount, fat_read, fat_dir, 0, 0}, # endif
Added: trunk/filo/include/cbfs.h =================================================================== --- trunk/filo/include/cbfs.h (rev 0) +++ trunk/filo/include/cbfs.h 2009-08-27 22:52:37 UTC (rev 105) @@ -0,0 +1,174 @@ +/* + * 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_H_ +#define _CBFS_H_ + +/** These are standard values for the known compression + alogrithms that coreboot knows about for stages and + payloads. Of course, other LAR 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 + +/** 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 { + u32 magic; + u32 version; + u32 romsize; + u32 bootblocksize; + u32 align; + u32 offset; + u32 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]; + u32 len; + u32 type; + u32 checksum; + u32 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 { + u32 compression; /** Compression type */ + u64 entry; /** entry point */ + u64 load; /** Where to load in memory */ + u32 len; /** length of data to load */ + u32 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 { + u32 type; + u32 compression; + u32 offset; + u64 load_addr; + u32 len; + u32 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 { + u32 compression; + u32 len; +} __attribute__((packed)); + +#define CBFS_NAME(_c) (((char *) (_c)) + sizeof(struct cbfs_file)) +#define CBFS_SUBHEADER(_p) ( (void *) ((((u8 *) (_p)) + ntohl((_p)->offset))) ) + +void * cbfs_load_payload(struct lb_memory *lb_mem, const char *name); +void * cbfs_load_stage(const char *name); +int cbfs_execute_stage(const char *name); +void * cbfs_get_file(const char *name); +void *cbfs_load_optionrom(u16 vendor, u16 device, void * dest); +int run_address(void *f); +int cbfs_decompress(int algo, void *src, void *dst, int len); +struct cbfs_stage *cbfs_find_file(const char *name, int type); +int cbfs_check_magic(struct cbfs_file *file); +struct cbfs_header *cbfs_master_header(void); +struct cbfs_file *cbfs_find(const char *name); +void cbfs_and_run_core(char* filename, unsigned int ebp); + +#endif +