Patchwork Add CBFS support to FILO

login
register
about
Submitter Patrick Georgi
Date 2009-08-20 14:33:21
Message ID <4A8D5EB1.10504@georgi-clan.de>
Download mbox | patch
Permalink /patch/150/
State Accepted
Headers show

Comments

Patrick Georgi - 2009-08-20 14:33:21
Hi,

attached patch adds CBFS to FILO. Use mem:/path/to/file for access.
Tested with
configfile mem:/menu.lst
after I added with
cbfstool coreboot.rom add menu.lst menu.lst 84

The filetype ID (84 in this case) can be freely chosen as long as it's not 0

Signed-off-by: Patrick Georgi <patrick.georgi@coresystems.de>

Regards,
Patrick
Harrison, Jon (SELEX GALILEO, UK) - 2009-08-20 15:32:32
Nice !! 

> -----Original Message-----
> From: Patrick Georgi [mailto:patrick@georgi-clan.de] 
> Sent: 20 August 2009 15:33
> To: coreboot; Harrison, Jon (SELEX GALILEO, UK)
> Subject: [PATCH] Add CBFS support to FILO
> 
>                     *** WARNING ***
> 
>  This message has originated outside your organisation,
>   either from an external partner or the Global Internet. 
>       Keep this in mind if you answer this message.
> 
> 
> Hi,
> 
> attached patch adds CBFS to FILO. Use mem:/path/to/file for access.
> Tested with
> configfile mem:/menu.lst
> after I added with
> cbfstool coreboot.rom add menu.lst menu.lst 84
> 
> The filetype ID (84 in this case) can be freely chosen as 
> long as it's not 0
> 
> Signed-off-by: Patrick Georgi <patrick.georgi@coresystems.de>
> 
> Regards,
> Patrick
> 
SELEX Sensors and Airborne Systems Limited
Registered Office: Sigma House, Christopher Martin Road, Basildon, Essex SS14 3EL
A company registered in England & Wales.  Company no. 02426132
********************************************************************
This email and any attachments are confidential to the intended
recipient and may also be privileged. If you are not the intended
recipient please delete it from your system and notify the sender.
You should not copy it or use it for any purpose nor disclose or
distribute its contents to any other person.
********************************************************************
Myles Watson - 2009-08-27 20:19:25
On Thu, Aug 27, 2009 at 11:46 AM, Harrison, Jon (SELEX GALILEO,
UK)<jon.harrison@selexgalileo.com> wrote:
> Hi,
>
> Attached is an update to Patrick's filo patch, with a small patch to
> libpayload too.
Probably the best way to do this would be for you to Ack Patrick's
patch, then send your small patch to the list.

> In addition to basic CBFS file system support, which should allow
> configfile and linux boot from CBFS, I have also added initial SELF boot
> support that allows simple libpayload based payloads to be launched from
> filo.

The libpayload patch looks pretty good, but it looks like all of the
changes could have been made in coreboot_tables.h and coreboot.c or
options.c.

> I know a lot of you guys think that this is all a bit of a waste of time
> / broken way of doing things, but for me it does now mean that I have
> the full equivalent functionality of SeaBIOS with USB keyboard support
> all for only the cost of a compressed filo image.

It's great to have more than one way to skin the proverbial cat.  I
think it's close.

Thanks,
Myles
Harrison, Jon (SELEX GALILEO, UK) - 2009-08-28 07:14:06
Looks good to me.

Acked-by: Jon Harrison <bothlyn@blueyonder.co.uk> 

> -----Original Message-----
> From: Patrick Georgi [mailto:patrick@georgi-clan.de] 
> Sent: 20 August 2009 15:33
> To: coreboot; Harrison, Jon (SELEX GALILEO, UK)
> Subject: [PATCH] Add CBFS support to FILO
> 
>                     *** WARNING ***
> 
>  This message has originated outside your organisation,
>   either from an external partner or the Global Internet. 
>       Keep this in mind if you answer this message.
> 
> 
> Hi,
> 
> attached patch adds CBFS to FILO. Use mem:/path/to/file for access.
> Tested with
> configfile mem:/menu.lst
> after I added with
> cbfstool coreboot.rom add menu.lst menu.lst 84
> 
> The filetype ID (84 in this case) can be freely chosen as 
> long as it's not 0
> 
> Signed-off-by: Patrick Georgi <patrick.georgi@coresystems.de>
> 
> Regards,
> Patrick
> 
SELEX Sensors and Airborne Systems Limited
Registered Office: Sigma House, Christopher Martin Road, Basildon, Essex SS14 3EL
A company registered in England & Wales.  Company no. 02426132
********************************************************************
This email and any attachments are confidential to the intended
recipient and may also be privileged. If you are not the intended
recipient please delete it from your system and notify the sender.
You should not copy it or use it for any purpose nor disclose or
distribute its contents to any other person.
********************************************************************

Patch

Index: include/cbfs.h
===================================================================
--- include/cbfs.h	(Revision 0)
+++ include/cbfs.h	(Revision 0)
@@ -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
+
Index: fs/vfs.c
===================================================================
--- fs/vfs.c	(Revision 104)
+++ fs/vfs.c	(Arbeitskopie)
@@ -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
Index: fs/lzma.c
===================================================================
--- fs/lzma.c	(Revision 0)
+++ fs/lzma.c	(Revision 0)
@@ -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;
+}
Index: fs/Makefile.inc
===================================================================
--- fs/Makefile.inc	(Revision 104)
+++ fs/Makefile.inc	(Arbeitskopie)
@@ -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
Index: fs/lzmadecode.c
===================================================================
--- fs/lzmadecode.c	(Revision 0)
+++ fs/lzmadecode.c	(Revision 0)
@@ -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;
+}
Index: fs/lzmadecode.h
===================================================================
--- fs/lzmadecode.h	(Revision 0)
+++ fs/lzmadecode.h	(Revision 0)
@@ -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
Index: fs/cbfs.c
===================================================================
--- fs/cbfs.c	(Revision 0)
+++ fs/cbfs.c	(Revision 0)
@@ -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();
+}
+
Index: fs/fsys_cbfs.c
===================================================================
--- fs/fsys_cbfs.c	(Revision 0)
+++ fs/fsys_cbfs.c	(Revision 0)
@@ -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;
+}
+
Index: fs/filesys.h
===================================================================
--- fs/filesys.h	(Revision 104)
+++ fs/filesys.h	(Arbeitskopie)
@@ -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);
Index: Config.in
===================================================================
--- Config.in	(Revision 104)
+++ Config.in	(Arbeitskopie)
@@ -213,6 +213,10 @@ 
 	bool "Squash filesystem"
 	default n
 
+config FSYS_CBFS
+	bool "CBFS ROM Image"
+	default y
+
 endmenu
 
 menu "Loaders"