[coreboot] r48 - in trunk/filo-0.5: . drivers drivers/flash fs i386 include main

svn at coreboot.org svn at coreboot.org
Sat May 3 17:03:46 CEST 2008


Author: stepan
Date: 2008-05-03 17:03:45 +0200 (Sat, 03 May 2008)
New Revision: 48

Added:
   trunk/filo-0.5/drivers/flash/
   trunk/filo-0.5/drivers/flash/Makefile
   trunk/filo-0.5/drivers/flash/lxflash.c
   trunk/filo-0.5/drivers/flash/lxflash.h
   trunk/filo-0.5/fs/fsys_aboot.c
   trunk/filo-0.5/i386/artecboot.c
   trunk/filo-0.5/include/artecboot.h
Modified:
   trunk/filo-0.5/Makefile
   trunk/filo-0.5/defconfig
   trunk/filo-0.5/fs/Makefile
   trunk/filo-0.5/fs/blockdev.c
   trunk/filo-0.5/fs/filesys.h
   trunk/filo-0.5/fs/vfs.c
   trunk/filo-0.5/i386/Makefile
   trunk/filo-0.5/i386/defconfig
   trunk/filo-0.5/i386/linux_load.c
   trunk/filo-0.5/include/fs.h
   trunk/filo-0.5/include/lib.h
   trunk/filo-0.5/main/console.c
   trunk/filo-0.5/main/filo.c
Log:
trying to merge most of ARTECs tree. 


Modified: trunk/filo-0.5/Makefile
===================================================================
--- trunk/filo-0.5/Makefile	2008-05-03 14:48:04 UTC (rev 47)
+++ trunk/filo-0.5/Makefile	2008-05-03 15:03:45 UTC (rev 48)
@@ -13,7 +13,8 @@
 endif
 
 PROGRAM_NAME = FILO
-PROGRAM_VERSION = 0.5
+PROGRAM_VERSION = 0.5.5
+
 BUILD_INFO = ($(shell whoami)@$(shell hostname)) $(shell LANG=C date)
 
 # for now:
@@ -21,7 +22,7 @@
 
 LIBGCC = $(shell $(CC) -print-libgcc-file-name)
 
-SUBDIRS = main main/grub fs drivers drivers/usb $(ARCH)
+SUBDIRS = main main/grub fs drivers drivers/usb drivers/flash $(ARCH)
 
 OBJS = $(addsuffix /builtin.o,$(SUBDIRS))
 
@@ -60,7 +61,7 @@
 	+$(MAKE) -C $(patsubst _clean_%,%,$@) clean
 
 clean: $(SUBDIRS_CLEAN)
-	rm -f filo.elf filo config.h filo.iso null.o builtin.o
+	rm -f filo.elf filo config.h filo.iso
 
 distclean: clean
 	rm -f Config Config.bak include/arch

Modified: trunk/filo-0.5/defconfig
===================================================================
--- trunk/filo-0.5/defconfig	2008-05-03 14:48:04 UTC (rev 47)
+++ trunk/filo-0.5/defconfig	2008-05-03 15:03:45 UTC (rev 48)
@@ -18,6 +18,7 @@
 #AUTOBOOT_FILE = "mem at 0xfff80000"
 #AUTOBOOT_FILE = "hde1 at 0"
 #AUTOBOOT_FILE = "uda1:/vmlinuz.elf"
+#AUTOBOOT_FILE = "flashb at 0x00400000,0x154a00 console=tty0 console=ttyS0,115200"
 
 # Time in second before booting AUTOBOOT_FILE
 AUTOBOOT_DELAY = 2
@@ -45,6 +46,9 @@
 # Driver for USB Storage
 USB_DISK = 1
 
+# Driver for NAND flash storage
+#FLASH_DISK = 1
+
 # VGA text console
 VGA_CONSOLE = 1
 PC_KEYBOARD = 1
@@ -99,4 +103,7 @@
 #DEBUG_IDE = 1
 #DEBUG_USB = 1
 #DEBUG_ELTORITO = 1
+#DEBUG_FLASH = 1
+#DEBUG_ARTECBOOT = 1
 
+

Added: trunk/filo-0.5/drivers/flash/Makefile
===================================================================
--- trunk/filo-0.5/drivers/flash/Makefile	                        (rev 0)
+++ trunk/filo-0.5/drivers/flash/Makefile	2008-05-03 15:03:45 UTC (rev 48)
@@ -0,0 +1,7 @@
+TOPDIR = ../..
+-include $(TOPDIR)/Config
+
+OBJS-1 :=
+OBJS-$(FLASH_DISK) += lxflash.o
+
+include $(TOPDIR)/makerules

Added: trunk/filo-0.5/drivers/flash/lxflash.c
===================================================================
--- trunk/filo-0.5/drivers/flash/lxflash.c	                        (rev 0)
+++ trunk/filo-0.5/drivers/flash/lxflash.c	2008-05-03 15:03:45 UTC (rev 48)
@@ -0,0 +1,824 @@
+/*******************************************************************************
+ *
+ *	Geode LX CS5536 flash driver
+ *
+ *	Copyright 2006 Andrei Birjukov <andrei.birjukov at artecdesign.ee> and
+ *	Artec Design LLC http://www.artecdesign.ee
+ *
+ *	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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ******************************************************************************/
+
+#include <lib.h>
+#include <fs.h>
+#include <arch/io.h>
+#include "lxflash.h"
+
+#define DEBUG_THIS DEBUG_FLASH
+#include <debug.h>
+
+////////////////////////////////////////////////////////////////////////////////
+// driver globals
+
+static FLASH_INFO g_flashInfo;		// flash info structure
+static uint32_t	g_deviceID = 0;		// flash memory ID
+static uint32_t	g_chipID = 0;		// chip ID
+static uint16_t	g_baseAddr = 0;		// port mapped controller IO base address
+
+static uint8_t g_eccTest[MAX_ECC_SIZE];	// used to retrieve/store ECC
+static uint8_t g_eccCalc[MAX_ECC_SIZE];
+
+static uint32_t g_currentPage = (uint32_t)-1;
+static uint8_t g_pageBuf[MAX_PAGE_SIZE];
+static uint8_t *g_pBBT=NULL;
+
+////////////////////////////////////////////////////////////////////////////////
+// ECC structs and routines
+
+/*
+ * Pre-calculated 256-way 1 byte column parity
+ */
+static const uint8_t nand_ecc_precalc_table[] = {
+	0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
+	0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
+	0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
+	0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
+	0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
+	0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
+	0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
+	0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
+	0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
+	0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
+	0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
+	0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
+	0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
+	0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
+	0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
+	0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
+};
+
+
+/**
+ * nand_trans_result - [GENERIC] create non-inverted ECC
+ * @reg2:	line parity reg 2
+ * @reg3:	line parity reg 3
+ * @ecc_code:	ecc
+ *
+ * Creates non-inverted ECC code from line parity
+ */
+static void NAND_transResult(uint8_t reg2, uint8_t reg3,
+	uint8_t *ecc_code)
+{
+	uint8_t a, b, i, tmp1, tmp2;
+
+	/* Initialize variables */
+	a = b = 0x80;
+	tmp1 = tmp2 = 0;
+
+	/* Calculate first ECC byte */
+	for (i = 0; i < 4; i++) {
+		if (reg3 & a)		/* LP15,13,11,9 --> ecc_code[0] */
+			tmp1 |= b;
+		b >>= 1;
+		if (reg2 & a)		/* LP14,12,10,8 --> ecc_code[0] */
+			tmp1 |= b;
+		b >>= 1;
+		a >>= 1;
+	}
+
+	/* Calculate second ECC byte */
+	b = 0x80;
+	for (i = 0; i < 4; i++) {
+		if (reg3 & a)		/* LP7,5,3,1 --> ecc_code[1] */
+			tmp2 |= b;
+		b >>= 1;
+		if (reg2 & a)		/* LP6,4,2,0 --> ecc_code[1] */
+			tmp2 |= b;
+		b >>= 1;
+		a >>= 1;
+	}
+
+	/* Store two of the ECC bytes */
+	ecc_code[0] = tmp1;
+	ecc_code[1] = tmp2;
+}
+
+/**
+ * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code for 256 byte block
+ * @dat:	raw data
+ * @ecc_code:	buffer for ECC
+ */
+int NAND_calculateECC(const uint8_t *dat, uint8_t *ecc_code)
+{
+	uint8_t idx, reg1, reg2, reg3;
+	int j;
+
+	/* Initialize variables */
+	reg1 = reg2 = reg3 = 0;
+	ecc_code[0] = ecc_code[1] = ecc_code[2] = 0;
+
+	/* Build up column parity */
+	for(j = 0; j < 256; j++) {
+
+		/* Get CP0 - CP5 from table */
+		idx = nand_ecc_precalc_table[dat[j]];
+		reg1 ^= (idx & 0x3f);
+
+		/* All bit XOR = 1 ? */
+		if (idx & 0x40) {
+			reg3 ^= (uint8_t) j;
+			reg2 ^= ~((uint8_t) j);
+		}
+	}
+
+	/* Create non-inverted ECC code from line parity */
+	NAND_transResult(reg2, reg3, ecc_code);
+
+	/* Calculate final ECC code */
+	ecc_code[0] = ~ecc_code[0];
+	ecc_code[1] = ~ecc_code[1];
+	ecc_code[2] = ((~reg1) << 2) | 0x03;
+	return 0;
+}
+
+/**
+ * nand_correct_data - [NAND Interface] Detect and correct bit error(s)
+ * @dat:	raw data read from the chip
+ * @read_ecc:	ECC from the chip
+ * @calc_ecc:	the ECC calculated from raw data
+ *
+ * Detect and correct a 1 bit error for 256 byte block
+ */
+int NAND_correctData(uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc)
+{
+	uint8_t a, b, c, d1, d2, d3, add, bit, i;
+
+	/* Do error detection */
+	d1 = calc_ecc[0] ^ read_ecc[0];
+	d2 = calc_ecc[1] ^ read_ecc[1];
+	d3 = calc_ecc[2] ^ read_ecc[2];
+
+	if ((d1 | d2 | d3) == 0) {
+		/* No errors */
+		return 0;
+	}
+	else {
+		a = (d1 ^ (d1 >> 1)) & 0x55;
+		b = (d2 ^ (d2 >> 1)) & 0x55;
+		c = (d3 ^ (d3 >> 1)) & 0x54;
+
+		/* Found and will correct single bit error in the data */
+		if ((a == 0x55) && (b == 0x55) && (c == 0x54)) {
+			c = 0x80;
+			add = 0;
+			a = 0x80;
+			for (i=0; i<4; i++) {
+				if (d1 & c)
+					add |= a;
+				c >>= 2;
+				a >>= 1;
+			}
+			c = 0x80;
+			for (i=0; i<4; i++) {
+				if (d2 & c)
+					add |= a;
+				c >>= 2;
+				a >>= 1;
+			}
+			bit = 0;
+			b = 0x04;
+			c = 0x80;
+			for (i=0; i<3; i++) {
+				if (d3 & c)
+					bit |= b;
+				c >>= 2;
+				b >>= 1;
+			}
+			b = 0x01;
+			a = dat[add];
+			a ^= (b << bit);
+			dat[add] = a;
+			return 1;
+		}
+		else {
+			i = 0;
+			while (d1) {
+				if (d1 & 0x01)
+					++i;
+				d1 >>= 1;
+			}
+			while (d2) {
+				if (d2 & 0x01)
+					++i;
+				d2 >>= 1;
+			}
+			while (d3) {
+				if (d3 & 0x01)
+					++i;
+				d3 >>= 1;
+			}
+			if (i == 1) {
+				/* ECC Code Error Correction */
+				read_ecc[0] = calc_ecc[0];
+				read_ecc[1] = calc_ecc[1];
+				read_ecc[2] = calc_ecc[2];
+				return 2;
+			}
+			else {
+				/* Uncorrectable Error */
+				return -1;
+			}
+		}
+	}
+
+	/* Should never happen */
+	return -1;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NAND flash helper functions go here, ported from Windows CE FMD
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// NAND_checkStatus()
+//
+// Retrieve the status of the Chip. This function accept a loop number, which
+// is used to do the loop if chip is not ready.
+//
+// dwLoops:
+//
+// 0: no loop
+// 0xffffffff: loop forever
+
+uint8_t NAND_checkStatus(uint32_t dwLoops)
+{
+	int	bStop = (dwLoops != (uint32_t) -1);
+	uint8_t	ucStatus;
+	int i;
+
+	// There is a 200ns delay (Twb) between the time that the !write-enable line
+	// (!WE) is asserted and the time the ready (R/!B) line is de-asserted. Generate a
+	// delay before querrying the status.
+	for (i=0; i<10; i++)
+		inb(g_baseAddr + IO_NAND_STS);
+
+	while(TRUE)
+	{
+		ucStatus = inb(g_baseAddr + IO_NAND_STS);
+
+		if(((ucStatus & CS_NAND_STS_FLASH_RDY) &&	// status ready
+				!(ucStatus & CS_NAND_CTLR_BUSY)) ||		// controller not busy
+				(bStop && !dwLoops))					// non-infinite loop and
+
+			break;									// we already pay our due
+
+		dwLoops --;
+	}
+
+	return ucStatus;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NAND command helpers
+
+static __inline void NAND_enableHwECC(int enable)
+{
+	if(enable) outb(0x07, g_baseAddr + IO_NAND_ECC_CTL);
+	else outb(0x02, g_baseAddr + IO_NAND_ECC_CTL);
+}
+
+static void NAND_readHwECC(uint8_t *pData)
+{
+	// read ECC data from status register
+	pData[0] = inb(g_baseAddr + IO_NAND_ECC_MSB);
+	pData[1] = inb(g_baseAddr + IO_NAND_ECC_LSB);
+	pData[2] = inb(g_baseAddr + IO_NAND_ECC_COL);
+}
+
+static __inline void NAND_writeIO(uint8_t b)
+{
+	outb(b, g_baseAddr + IO_NAND_IO);
+}
+
+static __inline void NAND_writeCTL(uint8_t b)
+{
+	outb(b, g_baseAddr + IO_NAND_CTL);
+}
+
+static __inline uint8_t NAND_readDataByte()
+{
+	return inb(g_baseAddr + IO_NAND_DATA);
+}
+
+static void NAND_readData(uint8_t *pData, int nSize)
+{
+	int i, nDwords = nSize/4;	// number of double words
+	int nBytes = nSize % 4;		// leftover stuff
+
+	if(nSize > 528) return;		// oversized buffer?
+
+	// read from port mapped registers, 
+	for(i=0; i<nDwords; i++)
+		((uint32_t*)pData)[i] = inl(g_baseAddr + IO_NAND_DATA);
+
+	for(i=0; i<nBytes; i++)
+		pData[i] = inb(g_baseAddr + IO_NAND_DATA);
+}
+
+static __inline void NAND_writeByte(uint8_t b)
+{
+	outb(b, g_baseAddr + IO_NAND_DATA);
+}
+
+static void NAND_writeData(uint8_t *pData, int nSize)
+{
+	int i;
+	if(nSize > 528) return;	// oversized buffer?
+
+	// write byte by byte, pedestrian way
+	for(i=0; i<nSize; i++)
+		NAND_writeByte(pData[i]);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// NAND_getStatus()
+//
+// Retrieve the status of the Chip. This function accept a loop number, which
+// is used to do the loop if chip is not ready.
+//
+// dwLoops:
+//
+// 0: no loop
+// 0xffffffff: loop forever
+
+uint8_t NAND_getStatus(uint32_t dwLoops)
+{
+	int	bStop = (dwLoops != (uint32_t) -1);
+	uint8_t	ucStatus;
+
+	NAND_checkStatus(dwLoops);		// wait until ready
+
+	NAND_writeCTL(CS_NAND_CTL_CLE);	// latch command
+	NAND_writeIO(CMD_STATUS);		// issue read status command
+	NAND_writeCTL(0x00);			// enable chip
+
+	while(1)
+	{
+		ucStatus = inb(g_baseAddr + IO_NAND_DATA);
+
+		if((ucStatus & STATUS_READY) ||		// status ready
+				(bStop && !dwLoops))			// non-infinite loop and
+
+			break;							// we already pay our due
+
+		dwLoops--;
+	}
+
+	return ucStatus;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// NAND_readFlashID
+//
+// Retrieve the flash chip manufacturer and ID
+
+
+uint32_t NAND_readFlashID()
+{
+	uint32_t dwID=0;
+
+	NAND_writeCTL(0x00);			// enable chip
+
+	NAND_checkStatus((uint32_t) -1);	// check ready
+
+	NAND_writeCTL(CS_NAND_CTL_CLE);	// latch command
+	NAND_writeIO(CMD_READID);		// send command
+	NAND_writeCTL(CS_NAND_CTL_ALE);	// latch address
+	NAND_writeIO(0x00);				// send address
+	NAND_writeCTL(0x00);			// enable chip
+
+	NAND_checkStatus((uint32_t) -1);
+
+	dwID = inl(g_baseAddr + IO_NAND_DATA);
+
+	NAND_writeCTL(CS_NAND_CTL_CE);	// disable chip
+
+	return dwID;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// NAND_isBlockBad
+//
+// Check to see if the given block is bad. A block is bad if the 517th uint8_t on
+// the first or second page is not 0xff.
+//
+// blockID: The block address. We need to convert this to page address
+//
+
+int NAND_isBlockBad(uint32_t blockID)
+{
+	uint8_t pa1, pa2, pa3, ca1, ca2, bData;
+
+	// Get the first page of the block
+	uint32_t dwPageID = blockID * g_flashInfo.pagesPerBlock;
+	
+	// for 512-byte page size, use the original addressing scheme
+	if(g_flashInfo.dataBytesPerPage == PAGE_SIZE_512)
+	{
+		// three page address bytes
+		pa1 = (uint8_t) (dwPageID & 0xff);
+		pa2 = (uint8_t) ((dwPageID >> 8) & 0xff);
+		pa3 = (uint8_t) ((dwPageID >> 16) & 0xff);
+		// just one column address byte
+		ca1 = VALIDADDR;
+	}
+	// for 2048-byte page size, we need to add some stuff
+	else if(g_flashInfo.dataBytesPerPage == PAGE_SIZE_2048)
+	{
+		// three page address bytes
+		pa1 = (uint8_t) (dwPageID & 0xff);
+		pa2 = (uint8_t) ((dwPageID >> 8) & 0xff);
+		pa3 = (uint8_t) ((dwPageID >> 16) & 0xff);
+		// two column address bytes
+		ca1 = 0x0000;
+		ca2 = 0x0008;	// point to the 2048-th byte
+	}
+	// unsupported page size
+	else return TRUE;
+
+	// For our NAND flash, we don't have to issue two read command. We just need
+	// to issue one read command and do contiquous read
+
+	NAND_writeCTL(0x00);				// enable chip
+	NAND_checkStatus((uint32_t) -1);	// check ready
+
+	// Check the first page.
+	NAND_writeCTL(CS_NAND_CTL_CLE);		// latch command
+	
+	if(g_flashInfo.dataBytesPerPage == PAGE_SIZE_2048)
+		NAND_writeIO(CMD_READ);			// send read command
+	else NAND_writeIO(CMD_READ2);		// send read command 2
+	NAND_writeCTL(CS_NAND_CTL_ALE);		// latch address
+	NAND_writeIO(ca1);					// send Column Address 1
+
+	if(g_flashInfo.dataBytesPerPage == PAGE_SIZE_2048)
+		NAND_writeIO(ca2);				// send Column Address 2
+
+	NAND_writeIO(pa1);					// send Page Address 1
+	NAND_writeIO(pa2);					// send Page Address 2
+	NAND_writeIO(pa3);					// send Page Address 3
+	NAND_writeCTL(0x00);				// select chip
+	
+	if(g_flashInfo.dataBytesPerPage == PAGE_SIZE_2048)
+	{
+		NAND_writeCTL(CS_NAND_CTL_CLE);	// latch command
+		NAND_writeIO(CMD_READ_2K);		// send read command
+		NAND_writeCTL(0x00);			// select chip
+	}
+
+	NAND_checkStatus((uint32_t) -1);	// check ready
+
+	bData = NAND_readDataByte();		// read out the bad block marker
+	if(bData != 0xff)					// no bits may be zeroed
+	{
+		debug("bad block found at address 0x%x\n", blockID);
+		NAND_writeCTL(CS_NAND_CTL_CE);	// disable chip
+		return TRUE;
+	}
+
+	NAND_writeCTL(CS_NAND_CTL_CE);		// disable chip
+	return FALSE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+
+__inline int IsECCWritten(uint8_t *pECC)
+{
+	// FIXME: check only 6 first bytes
+	static uint8_t abNoECC[] = {0xff,0xff,0xff,0xff,0xff,0xff};
+	return (memcmp(pECC, abNoECC, sizeof(abNoECC)) != 0);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// 
+
+int NAND_initChip(int chipNum)
+{
+	msr_t msr;
+
+	memset(&g_flashInfo, 0, sizeof(g_flashInfo));
+
+	g_chipID = chipNum;
+
+	///////////////////////////////////////////////////////////////////////////////////
+	// init the MSR_DIVIL_BALL_OPTS register, enable flash mode
+	
+	msr = rdmsr(MSR_DIVIL_BALL_OPTS);
+	msr.lo &= ~PIN_OPT_IDE;
+	wrmsr(MSR_DIVIL_BALL_OPTS, msr);
+	msr = rdmsr(MSR_DIVIL_BALL_OPTS);
+	debug("MSR_DIVIL_BALL_OPTS = 0x%08x 0x%08x\n", msr.hi, msr.lo);
+
+	///////////////////////////////////////////////////////////////////////////////////
+	// init the MSR_DIVIL_LBAR_FLSHx register, I/O mapped mode, set base address
+	
+	msr.hi = SET_FLSH_HIGH;
+	msr.lo = SET_FLSH_LOW;
+	wrmsr(MSR_DIVIL_LBAR_FLSH0 + g_chipID, msr);
+	g_baseAddr = SET_FLSH_LOW;	// set the IO base address
+
+	// read the register back
+	msr = rdmsr(MSR_DIVIL_LBAR_FLSH0 + g_chipID);
+	debug("MSR_DIVIL_LBAR_FLSH%d = 0x%08x 0x%08x\n", (int)g_chipID, msr.hi, msr.lo);
+
+	///////////////////////////////////////////////////////////////////////////////////
+	// init the MSR_NANDF_DATA NAND timing register
+
+	msr.hi = 0;
+	msr.lo = SET_NANDF_DATA_LOW;
+	wrmsr(MSR_NANDF_DATA, msr);
+
+	msr = rdmsr(MSR_NANDF_DATA);
+	debug("MSR_NANDF_DATA = 0x%08x 0x%08x\n", msr.hi, msr.lo);
+
+	///////////////////////////////////////////////////////////////////////////////////
+	// init the MSR_NANDF_CTL NAND timing register
+
+	msr.hi = 0;
+	msr.lo = SET_NANDF_CTL_LOW;
+	wrmsr(MSR_NANDF_CTL, msr);
+
+	msr = rdmsr(MSR_NANDF_CTL);
+	debug("MSR_NANDF_CTL = 0x%08x 0x%08x\n", msr.hi, msr.lo);
+
+	// read out flash chip ID
+	g_deviceID = NAND_readFlashID();
+	
+	switch(g_deviceID)	// allow only known flash chips
+	{
+	case SAMSUNG_NAND_64MB:
+	case SST_NAND_64MB:
+
+		g_flashInfo.numBlocks = 4096;
+		g_flashInfo.pagesPerBlock = 32;
+		g_flashInfo.dataBytesPerPage = 512;
+		g_flashInfo.flashType = FLASH_NAND;
+
+		break;
+		
+	case SST_NAND_512MB:
+
+		g_flashInfo.numBlocks = 4096;
+		g_flashInfo.pagesPerBlock = 64;
+		g_flashInfo.dataBytesPerPage = 2048;
+		g_flashInfo.flashType = FLASH_NAND;
+		
+		break;
+
+	default:
+		printf("Unsupported flash chip ID: %x\n", g_deviceID);
+		return -1;
+	}
+
+	g_flashInfo.bytesPerBlock = g_flashInfo.dataBytesPerPage * g_flashInfo.pagesPerBlock;
+
+	if(!g_pBBT) g_pBBT = malloc(g_flashInfo.numBlocks);
+	if(!g_pBBT)
+	{
+		printf("Could not allocate bad block table\n");
+		return -1;
+	}
+
+	debug("bad block table allocated, size %d\n", g_flashInfo.numBlocks);
+	memset(g_pBBT, BLOCK_UNKNOWN, g_flashInfo.numBlocks);
+
+	printf("Geode LX flash driver initialized, device ID 0x%x\n", g_deviceID);
+	debug("FlashChip = 0x%x\n", g_chipID);
+	debug("NumBlocks = 0x%x\n", g_flashInfo.numBlocks);
+	debug("PagesPerBlock = 0x%x\n", g_flashInfo.pagesPerBlock);
+	debug("BytesPerPage = 0x%x\n", g_flashInfo.dataBytesPerPage);
+	debug("FlashType = %s\n", g_flashInfo.flashType == FLASH_NAND ? "NAND" : "NOR");
+	return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// NAND_readPage
+//
+// Read the content of the sector.
+//
+// startSectorAddr: Starting page address
+// pSectorBuff : Buffer for the data portion
+
+int NAND_readPage(uint32_t pageAddr, uint8_t *pPageBuff)
+{
+	if (!pPageBuff)
+	{
+		debug("Invalid parameters!\n");
+		return ERROR_BAD_PARAMS;
+	}
+
+	// sanity check
+	if (pageAddr < (g_flashInfo.numBlocks * g_flashInfo.pagesPerBlock))
+	{
+		uint8_t bData = 0, bBadBlock = 0, bReserved = 0;
+
+		uint8_t addr1 = (uint8_t)(pageAddr & 0xff);
+		uint8_t addr2 = (uint8_t)((pageAddr >> 8) & 0xff);
+		uint8_t addr3 = (uint8_t)((pageAddr >> 16) & 0xff);
+		
+		uint16_t eccSize = 0;				// total ECC size
+		uint32_t pageSize = 0;
+		
+		NAND_writeCTL(0x00);				// enable chip
+		NAND_checkStatus((uint32_t)-1);		// check ready
+
+		NAND_writeCTL(CS_NAND_CTL_CLE);		// latch command
+		NAND_writeIO(CMD_READ);				// send read command
+		NAND_writeCTL(CS_NAND_CTL_ALE);		// latch address
+		NAND_writeIO(0x00);					// send Column Address 1
+		
+		if(g_flashInfo.dataBytesPerPage == PAGE_SIZE_2048)
+			NAND_writeIO(0x00);				// send Column Address 2
+		
+		NAND_writeIO(addr1);				// send Page Address 1
+		NAND_writeIO(addr2);				// send Page Address 2
+		NAND_writeIO(addr3);				// send Page Address 3
+		NAND_writeCTL(0x00);				// select chip
+		
+		if(g_flashInfo.dataBytesPerPage == PAGE_SIZE_2048)
+		{
+			NAND_writeCTL(CS_NAND_CTL_CLE);	// latch command
+			NAND_writeIO(CMD_READ_2K);		// send read command
+			NAND_writeCTL(0x00);			// select chip
+		}
+
+		NAND_checkStatus((uint32_t) -1);	// check ready
+
+		while(pageSize < g_flashInfo.dataBytesPerPage)
+		{
+			// read out the first half of page data
+			NAND_enableHwECC(1);			// enable HW ECC calculation
+			NAND_readData(&pPageBuff[pageSize], READ_BLOCK_SIZE);
+			NAND_readHwECC(&g_eccCalc[pageSize / READ_BLOCK_SIZE * 3]);
+			// update counters too
+			pageSize += READ_BLOCK_SIZE;
+			eccSize += 3;
+		}
+
+		debug("read %d bytes from page address %x\n", pageSize, pageAddr);
+		NAND_enableHwECC(0);				// disable HW ECC
+
+		// Now read the spare area data
+
+		if(g_flashInfo.dataBytesPerPage == PAGE_SIZE_512)
+		{
+			// Read the ECC info according to Linux MTD format, first part
+			NAND_readData(g_eccTest, 4);
+	
+			bBadBlock = NAND_readDataByte();	// bad block byte
+			bReserved = NAND_readDataByte();	// reserved byte
+			// Read the ECC info according to Linux MTD format, second part
+			NAND_readData(&g_eccTest[4], 2);
+
+			// calculate the first part of ECC, use software method
+			//NAND_calculateECC(&pPageBuff[0], &g_eccCalc[0]);
+			// calculate the second part of ECC, use software method
+			//NAND_calculateECC(&pPageBuff[256], &g_eccCalc[3]);
+		}
+		else if(g_flashInfo.dataBytesPerPage == PAGE_SIZE_2048)
+		{
+			int i;
+			for(i=0; i<40; i++) NAND_readDataByte();	// skip stuff 
+			// Read the ECC info according to Linux MTD format (2048 byte page)
+			NAND_readData(g_eccTest, eccSize); 
+		}
+		
+		// test the data integrity; if the data is invalid, attempt to fix it using ECC
+		if(memcmp(g_eccCalc, g_eccTest, eccSize))
+		{
+			int nRet = 0;
+
+			// If the ECC is all 0xff, then it probably hasn't been written out yet
+			// because the data hasn't been written, so ignore the invalid ECC.
+			if(!IsECCWritten(g_eccTest))
+			{
+				debug("No ECC detected at page 0x%x\n", pageAddr);
+				NAND_writeCTL(CS_NAND_CTL_CE);	// disable chip
+				return ERROR_NO_ECC;
+			}
+			
+			debug("Page data (page 0x%x) is invalid. Attempting ECC to fix it.\n", pageAddr);
+			nRet = NAND_correctData(&pPageBuff[0], &g_eccTest[0], &g_eccCalc[0]);
+			if(nRet == -1)
+			{
+				debug("ERROR - page data (page 0x%x, first part) Unable to correct invalid data!\n", pageAddr);
+				NAND_writeCTL(CS_NAND_CTL_CE);	// disable chip
+				return ERROR_ECC_ERROR1;
+			}
+			else if(nRet == 0) debug("No errors detected (page 0x%x, first part)\n", pageAddr);
+			else debug("Invalid data (page 0x%x, first part) was corrected using ECC!\n", pageAddr);
+
+			// now do the second part
+			nRet = NAND_correctData(&pPageBuff[256], &g_eccTest[3], &g_eccCalc[3]);
+			if(nRet == -1)
+			{
+				debug("ERROR - page data (page 0x%x, second part) Unable to correct invalid data!\n", pageAddr);
+				NAND_writeCTL(CS_NAND_CTL_CE);	// disable chip
+				return ERROR_ECC_ERROR2;
+			}
+			else if(nRet == 0) debug("No errors detected (page 0x%x, second part)\n", pageAddr);
+			else debug("Invalid data (page 0x%x, second part) was corrected using ECC!\n", pageAddr);
+		}
+	} 
+	else 
+	{
+		debug("Page address [%d] is too large\n", pageAddr);
+		return ERROR_BAD_ADDRESS;
+	}
+
+	NAND_writeCTL(CS_NAND_CTL_CE);	// disable chip
+	return ERROR_SUCCESS;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// FILO interface functions
+
+int flash_probe(int drive)
+{
+	debug("drive %d\n", drive);
+	return NAND_initChip(drive);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+int flash_read(int drive, sector_t sector, void *buffer)
+{
+	int block, nRet;
+	uint32_t pageAddress = sector * DEV_SECTOR_SIZE / g_flashInfo.dataBytesPerPage;
+	uint32_t pageOffset = sector * DEV_SECTOR_SIZE % g_flashInfo.dataBytesPerPage;
+	
+	// sanity check
+	if(!g_pBBT || !g_flashInfo.pagesPerBlock)
+	{
+		debug("error: NAND not initialized\n");
+		return -1;
+	}
+	
+	// check that the page ID is valid
+	if(pageAddress >= (g_flashInfo.numBlocks * g_flashInfo.pagesPerBlock))
+	{
+		debug("error: sector offset %x out of range\n", sector);
+		return -2;
+	}
+
+	// get block address
+	block = pageAddress / g_flashInfo.pagesPerBlock;
+
+	debug("drive %d, sector %d -> page %d + %d, buffer 0x%08x\n", 
+		drive, (unsigned int)sector, pageAddress, pageOffset, (unsigned int)buffer);
+
+	// get the block status first
+	if(g_pBBT[block] == BLOCK_UNKNOWN)
+	{
+		debug("checking block 0x%x status for BBT\n", block);
+		g_pBBT[block] = NAND_isBlockBad(block) ? BLOCK_BAD : BLOCK_GOOD;
+	}
+
+	// return failure immediately if the block is bad
+	if(g_pBBT[block] == BLOCK_BAD) 
+	{
+		debug("error: block %x is bad\n", block);
+		return -3;
+	}
+	
+	// check if we have just read that page
+	if(g_currentPage == pageAddress)
+	{
+		// should use cache instead
+		memcpy(buffer, g_pageBuf + pageOffset, DEV_SECTOR_SIZE);
+		return ERROR_SUCCESS;
+	}
+	
+	// otherwise proceed with normal reading
+	nRet = NAND_readPage(pageAddress, g_pageBuf);
+	memcpy(buffer, g_pageBuf + pageOffset, DEV_SECTOR_SIZE);
+	
+	return nRet;
+}

Added: trunk/filo-0.5/drivers/flash/lxflash.h
===================================================================
--- trunk/filo-0.5/drivers/flash/lxflash.h	                        (rev 0)
+++ trunk/filo-0.5/drivers/flash/lxflash.h	2008-05-03 15:03:45 UTC (rev 48)
@@ -0,0 +1,155 @@
+#ifndef LXFLASH_H
+#define LXFLASH_H
+
+#define TRUE	1	// hmm that's quite obvious :)
+#define FALSE	0
+
+typedef struct msr_struct 
+{
+	unsigned lo;
+	unsigned hi;
+} msr_t;
+
+static inline msr_t rdmsr(unsigned index)
+{
+	msr_t result;
+	__asm__ __volatile__ (
+		"rdmsr"
+		: "=a" (result.lo), "=d" (result.hi)
+		: "c" (index)
+		);
+	return result;
+}
+
+static inline void wrmsr(unsigned index, msr_t msr)
+{
+	__asm__ __volatile__ (
+		"wrmsr"
+		: /* No outputs */
+		: "c" (index), "a" (msr.lo), "d" (msr.hi)
+		);
+}
+
+typedef struct _FLASH_INFO
+{
+    unsigned long	numBlocks;
+    unsigned long	bytesPerBlock;
+    unsigned short	pagesPerBlock;
+    unsigned short	dataBytesPerPage;
+	unsigned short	flashType;
+} FLASH_INFO;
+
+// NAND flash controller MSR registers
+
+#define MSR_DIVIL_LBAR_FLSH0	0x51400010	// Flash Chip Select 0
+#define MSR_DIVIL_LBAR_FLSH1	0x51400011	// Flash Chip Select 1
+#define MSR_DIVIL_LBAR_FLSH2	0x51400012	// Flash Chip Select 2
+#define MSR_DIVIL_LBAR_FLSH3	0x51400013	// Flash Chip Select 3
+
+#define MSR_DIVIL_BALL_OPTS		0x51400015
+#define PIN_OPT_IDE				(1UL<<0)	// 0 for flash, 1 for IDE
+
+#define MSR_NANDF_DATA			0x5140001B
+#define MSR_NANDF_CTL			0x5140001C
+
+// Intended value for LBAR_FLSHx: enabled, PIO, NAND, @0xC000
+
+#define SET_FLSH_HIGH			0x0000FFF3
+#define SET_FLSH_LOW			0x0000C000
+#define SET_NANDF_DATA_LOW		0x01200120
+#define SET_NANDF_CTL_LOW		0x00000120
+
+// ThinCan defaults
+
+#define PAGE_SIZE_512			512
+#define PAGE_SIZE_2048			2048
+#define MAX_PAGE_SIZE			2048
+#define MAX_ECC_SIZE			24
+#define READ_BLOCK_SIZE			256
+
+//  VALIDADDR is 5 << 8
+//
+//  Explain:    5 means the 6th byte in spare area (517 byte in the page)
+//              Shift 8 bit to the left to form the correct address for 16bit port
+//
+#define VALIDADDR				0x05
+#define OEMADDR					0x04		// 5th byte in spare area 
+
+//  NAND Flash Command. This appears to be generic across all NAND flash chips
+
+#define CMD_READ                0x00        //  Read
+#define CMD_READ1               0x01        //  Read1
+#define CMD_READ2               0x50        //  Read2
+#define CMD_READID              0x90        //  ReadID
+#define CMD_READID2             0x91        //  Read extended ID
+#define CMD_WRITE               0x80        //  Write phase 1
+#define CMD_WRITE2              0x10        //  Write phase 2
+#define CMD_ERASE               0x60        //  Erase phase 1
+#define CMD_ERASE2              0xd0        //  Erase phase 2
+#define CMD_STATUS              0x70        //  Status read
+#define CMD_RESET               0xff        //  Reset
+#define CMD_READ_2K             0x30        //  Second cycle read cmd for 2KB flash 
+
+// Registers within the NAND flash controller BAR -- memory mapped
+
+#define MM_NAND_DATA			0x00		// 0 to 0x7ff, in fact
+#define MM_NAND_CTL				0x800		// Any even address 0x800-0x80e
+#define MM_NAND_IO				0x801		// Any odd address 0x801-0x80f
+#define MM_NAND_STS				0x810
+#define MM_NAND_ECC_LSB			0x811
+#define MM_NAND_ECC_MSB			0x812
+#define MM_NAND_ECC_COL			0x813
+#define MM_NAND_LAC				0x814
+#define MM_NAND_ECC_CTL			0x815
+
+// Registers within the NAND flash controller BAR -- I/O mapped 
+
+#define IO_NAND_DATA			0x00		// 0 to 3, in fact
+#define IO_NAND_CTL				0x04
+#define IO_NAND_IO				0x05
+#define IO_NAND_STS				0x06
+#define IO_NAND_ECC_CTL			0x08
+#define IO_NAND_ECC_LSB			0x09
+#define IO_NAND_ECC_MSB			0x0a
+#define IO_NAND_ECC_COL			0x0b
+#define IO_NAND_LAC				0x0c
+
+#define CS_NAND_CTL_DIST_EN			(1<<4)	// Enable NAND Distract interrupt
+#define CS_NAND_CTL_RDY_INT_MASK	(1<<3)	// Enable RDY/BUSY# interrupt
+#define CS_NAND_CTL_ALE				(1<<2)
+#define CS_NAND_CTL_CLE				(1<<1)
+#define CS_NAND_CTL_CE				(1<<0)	// Keep low; 1 to reset
+
+#define CS_NAND_STS_FLASH_RDY		(1<<3)
+#define CS_NAND_CTLR_BUSY			(1<<2)
+#define CS_NAND_CMD_COMP			(1<<1)
+#define CS_NAND_DIST_ST				(1<<0)
+
+#define CS_NAND_ECC_PARITY			(1<<2)
+#define CS_NAND_ECC_CLRECC			(1<<1)
+#define CS_NAND_ECC_ENECC			(1<<0)
+
+//  Status bit pattern, read from chip register
+
+#define STATUS_READY				0x40	//  Ready
+#define STATUS_ERROR				0x01	//  Error
+
+#define FLASH_NOR					0
+#define FLASH_NAND					1
+
+#define SAMSUNG_NAND_64MB			0xc0a576ec
+#define SST_NAND_64MB				0x76207620
+#define SST_NAND_512MB				0x9580dc20
+
+#define ERROR_SUCCESS				0
+#define ERROR_BAD_PARAMS			-1
+#define ERROR_ECC_ERROR1			1
+#define ERROR_ECC_ERROR2			2
+#define ERROR_BAD_ADDRESS			3
+#define ERROR_NO_ECC				4
+
+#define BLOCK_UNKNOWN				0
+#define BLOCK_BAD					2
+#define BLOCK_GOOD					1
+
+#endif

Modified: trunk/filo-0.5/fs/Makefile
===================================================================
--- trunk/filo-0.5/fs/Makefile	2008-05-03 14:48:04 UTC (rev 47)
+++ trunk/filo-0.5/fs/Makefile	2008-05-03 15:03:45 UTC (rev 48)
@@ -14,5 +14,6 @@
 OBJS-$(FSYS_CRAMFS) += mini_inflate.o
 OBJS-$(FSYS_SQUASHFS) += fsys_squashfs.o
 OBJS-$(FSYS_SQUASHFS) += squashfs_zlib.o
+OBJS-$(ARTEC_BOOT) += fsys_aboot.o
 
 include $(TOPDIR)/makerules

Modified: trunk/filo-0.5/fs/blockdev.c
===================================================================
--- trunk/filo-0.5/fs/blockdev.c	2008-05-03 14:48:04 UTC (rev 47)
+++ trunk/filo-0.5/fs/blockdev.c	2008-05-03 15:03:45 UTC (rev 48)
@@ -5,8 +5,9 @@
 #define DEBUG_THIS DEBUG_BLOCKDEV
 #include <debug.h>
 
-#define NUM_CACHE 64
-static unsigned char buf_cache[NUM_CACHE][512];
+#define NUM_CACHE		64
+
+static unsigned char buf_cache[NUM_CACHE][DEV_SECTOR_SIZE];
 static unsigned long cache_sect[NUM_CACHE];
 
 static char dev_name[256];
@@ -44,7 +45,7 @@
 	unsigned char start_sect[4]; /* unaligned little endian */
 	unsigned char nr_sects[4]; /* ditto */
     } *p;
-    unsigned char buf[512];
+    unsigned char buf[DEV_SECTOR_SIZE];
 
     /* PC partition probe */
     if (!devread(0, 0, sizeof(buf), buf)) {
@@ -53,7 +54,7 @@
     }
     if (!has_pc_part_magic(buf)) {
 	debug("pc partition magic number not found\n");
-	//debug_hexdump(buf, 512);
+	//debug_hexdump(buf, DEV_SECTOR_SIZE);
 	return PARTITION_UNKNOWN;
     }
     p = (struct pc_partition *) (buf + 0x1be);
@@ -151,6 +152,16 @@
 	}
 	*drive = *name - 'a';
 	name++;
+    } 
+	else if (memcmp(name, "flash", 5) == 0) {
+	*type = DISK_FLASH;
+	name += 5;
+        if (*name < 'a' || *name > 'z') {
+	    printf("Invalid flash chip\n");
+	    return 0;
+	}
+	*drive = *name - 'a';
+	name++;
     } else if (memcmp(name, "mem", 3) == 0) {
 	*type = DISK_MEM;
 	name += 3;
@@ -198,13 +209,13 @@
     }
 
     /* Do simple sanity check first */
-    if (offset & 0x1ff) {
-	printf("Device offset must be multiple of 512\n");
+    if (offset & DEV_SECTOR_MASK) {
+	printf("Device offset must be multiple of %d\n", DEV_SECTOR_SIZE);
 	return 0;
     }
-    if (length & 0x1ff) {
-	printf("WARNING: length is rounded up to multiple of 512\n");
-	length = (length + 0x1ff) & ~0x1ff;
+    if (length & DEV_SECTOR_MASK) {
+	printf("WARNING: length is rounded up to multiple of %d\n", DEV_SECTOR_SIZE);
+	length = (length + DEV_SECTOR_MASK) & ~DEV_SECTOR_MASK;
     }
 
     switch (type) {
@@ -226,11 +237,24 @@
         disk_size = (uint32_t) -1; /* FIXME */
         break;
 #endif
-    case DISK_MEM:
-	disk_size = 1 << (32 - 9); /* 4GB/512-byte */
+
+#ifdef FLASH_DISK
+	case DISK_FLASH:
+		if(flash_probe(drive) != 0)
+		{
+			debug("failed to open flash\n");
+			return 0;
+		}
+		disk_size = (uint32_t) -1; /* FIXME */
+		break;
+#endif
+
+	case DISK_MEM:
+	disk_size = 1 << (32 - DEV_SECTOR_BITS); /* 4GB/512-byte */
 	break;
-    default:
-	printf("Unknown device type %d\n", type);
+
+	default:
+		printf("Unknown device type %d\n", type);
 	return 0;
     }
 
@@ -265,21 +289,21 @@
     }
 
     if (offset) {
-	if (offset >= (uint64_t) part_length << 9) {
+	if (offset >= (uint64_t) part_length << DEV_SECTOR_BITS) {
 	    printf("Device offset is too high\n");
 	    return 0;
 	}
-	part_start += offset >> 9;
-	part_length -= offset >> 9;
+	part_start += offset >> DEV_SECTOR_BITS;
+	part_length -= offset >> DEV_SECTOR_BITS;
 	debug("after offset: start %lu, length %lu\n", part_start, part_length);
     }
 
     if (length) {
-	if (length > (uint64_t) part_length << 9) {
+	if (length > (uint64_t) part_length << DEV_SECTOR_BITS) {
 	    printf("Specified length exceeds the size of device\n");
 	    return 0;
 	}
-	part_length = length >> 9;
+	part_length = length >> DEV_SECTOR_BITS;
 	debug("after length: length %lu\n", part_length);
 	using_devsize = 0;
     }
@@ -297,7 +321,7 @@
 
     /* If reading memory, just return the memory as the buffer */
     if (dev_type == DISK_MEM) {
-	unsigned long phys = sector << 9;
+	unsigned long phys = sector << DEV_SECTOR_BITS;
 	//debug("mem: %#lx\n", phys);
 	return phys_to_virt(phys);
     }
@@ -315,11 +339,19 @@
 	    break;
 #endif
 #ifdef USB_DISK
-        case DISK_USB:
-            if (usb_read(dev_drive, sector, buf) != 0)
-                goto readerr;
-            break;
+	case DISK_USB:
+		if (usb_read(dev_drive, sector, buf) != 0)
+		goto readerr;
+		break;
 #endif
+
+#ifdef FLASH_DISK
+	case DISK_FLASH:
+		if (flash_read(dev_drive, sector, buf) != 0)
+			return 0;
+		break;
+#endif
+
 	default:
 	    printf("read_sector: device not open\n");
 	    return 0;

Modified: trunk/filo-0.5/fs/filesys.h
===================================================================
--- trunk/filo-0.5/fs/filesys.h	2008-05-03 14:48:04 UTC (rev 47)
+++ trunk/filo-0.5/fs/filesys.h	2008-05-03 15:03:45 UTC (rev 48)
@@ -182,6 +182,12 @@
 int squashfs_dir (char *dirname);
 #endif
 
+#ifdef ARTEC_BOOT
+int aboot_mount (void);
+int aboot_read (char *buf, int len);
+int aboot_dir (char *dirname);
+#endif
+
 /* This is not a flag actually, but used as if it were a flag.  */
 #define PC_SLICE_TYPE_HIDDEN_FLAG	0x10
 

Added: trunk/filo-0.5/fs/fsys_aboot.c
===================================================================
--- trunk/filo-0.5/fs/fsys_aboot.c	                        (rev 0)
+++ trunk/filo-0.5/fs/fsys_aboot.c	2008-05-03 15:03:45 UTC (rev 48)
@@ -0,0 +1,184 @@
+#ifdef ARTEC_BOOT
+
+/*******************************************************************************
+ *
+ *	FILO Artecboot Virtual File System
+ *
+ *	Copyright 2006 Andrei Birjukov <andrei.birjukov at artecdesign.ee> and
+ *	Artec Design LLC http://www.artecdesign.ee
+ *
+ *	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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ******************************************************************************/
+
+#include <lib.h>
+#include <fs.h>
+#include <sys_info.h>
+
+#include "artecboot.h"
+#include "shared.h"
+#include "filesys.h"
+
+#define DEBUG_THIS DEBUG_ARTECBOOT
+#include <debug.h>
+
+static ARTECBOOT_HEADER bootHdr;
+static uint32_t fileStart = 0;
+
+// device read helper, calls the block device read function
+// returns number of bytes parsed fthe stream 
+
+int aboot_devread(char* pData, int nSize)
+{
+	char sectorBuf[DEV_SECTOR_SIZE];
+	uint32_t len, total=0;
+	int failCount = 128;
+
+	uint32_t sector = (fileStart + filepos) >> DEV_SECTOR_BITS;
+	uint32_t byteOffset = (fileStart + filepos) & DEV_SECTOR_MASK;
+	
+	debug("file start %x, sector %x, offset %d\n", fileStart, sector, byteOffset);
+
+	if (sector + ((nSize + DEV_SECTOR_MASK) >> DEV_SECTOR_BITS) > part_length)
+	{
+		printf("Error: read outside of device device/partition\n");
+		debug("sector=%lu, partition size=%lu, read length=%lu\n",
+			(unsigned long)sector, 	(unsigned long)part_length, (unsigned long)nSize);
+		return 0;
+    }
+
+    while (nSize > 0)
+	{
+		if (!devread(sector, 0, DEV_SECTOR_SIZE, sectorBuf))
+		{
+			debug("sector 0x%x read failed\n", sector);
+			// do not abort immediately, try some more
+			if((failCount --) == 0) return 0;
+			
+			sector ++;	// try the next sector
+			total += DEV_SECTOR_SIZE;
+			continue;
+		}
+
+		len = SECTOR_SIZE - byteOffset;
+		if (len > nSize)
+			len = nSize;
+		memcpy(pData, sectorBuf + byteOffset, len);
+		
+		sector ++;
+		byteOffset = 0;
+		
+		nSize -= len;
+		pData += len;
+		total += len;
+    }
+
+	// return number of bytes read from the stream
+    return total;
+}
+
+int aboot_mount(void)
+{
+	debug("Mounting Artecboot VFS...\n");
+	// clear the boot header
+	memset(&bootHdr, 0, sizeof(bootHdr));
+	
+	fileStart = 0;
+	filepos = 0;
+	
+	// now read out the boot header
+	if(aboot_devread((char*)&bootHdr, sizeof(ARTECBOOT_HEADER)) < sizeof(ARTECBOOT_HEADER))
+	{
+		debug("Boot error: failed reading the boot image header\n");
+		return 0;
+	}
+
+	// check whether the flash data is valid at all
+	if(bootHdr.magicHeader != ARTECBOOT_HEADER_MAGIC)
+	{
+		debug("No Artecboot signature found, aborting\n");
+		return 0;
+	}
+
+	// check the version number
+	if(bootHdr.bootVersion > CURRENT_VERSION)
+	{
+		debug("Boot error: incompatible version number: %x\n", bootHdr.bootVersion);
+		return 0;
+	}
+
+	// align the partition length to the sector size
+	part_length = ((bootHdr.imageSize - 1) >> DEV_SECTOR_BITS) + 1;
+	return 1;
+}
+
+int aboot_read(char *buf, int len)
+{
+	int read;
+	// sanity check
+	if(bootHdr.magicHeader != ARTECBOOT_HEADER_MAGIC) return 0;
+	debug("reading %d bytes to %x...\n", len, (unsigned int)buf);
+
+	read = aboot_devread(buf, len);
+	filepos += read;	// advance current position
+	
+	debug("read %d bytes, pos %x\n", read, filepos);
+	
+	// returned length may be greater than requested size because of skipped bad blocks
+	if(read >= len) return len;
+	return 0;
+}
+
+int aboot_dir(char *dirname)
+{
+	int nRet = 0;
+	// sanity check
+	if(bootHdr.magicHeader != ARTECBOOT_HEADER_MAGIC) return 0;
+	
+	// we can only recognize certain hardcoded filenames
+	if(!strcmp(dirname, ABOOT_FILE_HEADER))
+	{
+		filepos = 0;
+		fileStart = 0;
+		filemax = sizeof(ARTECBOOT_HEADER);
+		nRet = 1;
+	}
+	else if(!strcmp(dirname, ABOOT_FILE_KERNEL))
+	{
+		filepos = 0;
+		fileStart = bootHdr.kernelStart;
+		filemax = bootHdr.kernelSize;
+		nRet = 1;
+	}
+	else if(!strcmp(dirname, ABOOT_FILE_INITRD))
+	{
+		filepos = 0;
+		fileStart = bootHdr.initrdStart;
+		filemax = bootHdr.initrdSize;
+		nRet = 1;
+	}
+	else
+	{
+		// unknown file
+		filepos = 0;
+		filemax = 0;
+		nRet = 0;
+	}
+	
+	debug("open file: %s, size %d, dev start %x\n", dirname, filemax, fileStart);
+	return nRet;
+}
+
+#endif

Modified: trunk/filo-0.5/fs/vfs.c
===================================================================
--- trunk/filo-0.5/fs/vfs.c	2008-05-03 14:48:04 UTC (rev 47)
+++ trunk/filo-0.5/fs/vfs.c	2008-05-03 15:03:45 UTC (rev 48)
@@ -25,33 +25,37 @@
 
 struct fsys_entry fsys_table[] = {
 # ifdef FSYS_FAT
-    {"fat", fat_mount, fat_read, fat_dir, 0, 0},
+    {"FAT filesystem", fat_mount, fat_read, fat_dir, 0, 0},
 # endif
 # ifdef FSYS_EXT2FS
-    {"ext2fs", ext2fs_mount, ext2fs_read, ext2fs_dir, 0, 0},
+    {"EXT2 filesystem", ext2fs_mount, ext2fs_read, ext2fs_dir, 0, 0},
 # endif
 # ifdef FSYS_MINIX
-    {"minix", minix_mount, minix_read, minix_dir, 0, 0},
+    {"MINIX filesystem", minix_mount, minix_read, minix_dir, 0, 0},
 # endif
 # ifdef FSYS_REISERFS
-    {"reiserfs", reiserfs_mount, reiserfs_read, reiserfs_dir, 0,
+    {"REISERFS filesystem", reiserfs_mount, reiserfs_read, reiserfs_dir, 0,
      reiserfs_embed},
 # endif
 # ifdef FSYS_JFS
-    {"jfs", jfs_mount, jfs_read, jfs_dir, 0, jfs_embed},
+    {"JFS filesystem", jfs_mount, jfs_read, jfs_dir, 0, jfs_embed},
 # endif
 # ifdef FSYS_XFS
-    {"xfs", xfs_mount, xfs_read, xfs_dir, 0, 0},
+    {"XFS filesystem", xfs_mount, xfs_read, xfs_dir, 0, 0},
 # endif
 # ifdef FSYS_ISO9660
-    {"iso9660", iso9660_mount, iso9660_read, iso9660_dir, 0, 0},
+    {"ISO9660 filesystem", iso9660_mount, iso9660_read, iso9660_dir, 0, 0},
 # endif
 # ifdef FSYS_CRAMFS
-    {"cramfs", cramfs_mount, cramfs_read, cramfs_dir, 0, 0},
+    {"CRAM filesystem", cramfs_mount, cramfs_read, cramfs_dir, 0, 0},
 # endif
 # ifdef FSYS_SQUASHFS
-    {"squashfs", squashfs_mount, squashfs_read, squashfs_dir, 0, 0},
+    {"SQUASH filesystem", squashfs_mount, squashfs_read, squashfs_dir, 0, 0},
 # endif
+# ifdef ARTEC_BOOT
+    {"Artecboot Virtual Filesystem", aboot_mount, aboot_read, aboot_dir, 0, 0},
+# endif
+
 };
 
 /* NULLFS is used to read images from raw device */
@@ -172,11 +176,14 @@
     if (len < 0 || len > filemax-filepos)
 	len = filemax - filepos;
     errnum = 0;
-    return fsys->read_func(buf, len);
+
+	debug("reading %d bytes, offset 0x%x\n", len, filepos);
+	return fsys->read_func(buf, len);
 }
 
 int file_seek(unsigned long offset)
 {
+	debug("seeking to 0x%x\n", offset);
     filepos = offset;
     return filepos;
 }
@@ -186,6 +193,13 @@
     return filemax;
 }
 
+void file_set_size(unsigned long size)
+{
+	debug("updating file size to %d bytes\n", size);
+    filemax = size;
+	using_devsize = 0;
+}
+
 void file_close(void)
 {
 }

Modified: trunk/filo-0.5/i386/Makefile
===================================================================
--- trunk/filo-0.5/i386/Makefile	2008-05-03 14:48:04 UTC (rev 47)
+++ trunk/filo-0.5/i386/Makefile	2008-05-03 15:03:45 UTC (rev 48)
@@ -4,5 +4,6 @@
 OBJS-1 := context.o switch.o segment.o timer.o sys_info.o
 OBJS-$(LINUX_LOADER) += linux_load.o
 OBJS-$(MULTIBOOT_IMAGE) += multiboot.o
+OBJS-$(ARTEC_BOOT) += artecboot.o
 
 include $(TOPDIR)/makerules

Added: trunk/filo-0.5/i386/artecboot.c
===================================================================
--- trunk/filo-0.5/i386/artecboot.c	                        (rev 0)
+++ trunk/filo-0.5/i386/artecboot.c	2008-05-03 15:03:45 UTC (rev 48)
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ *
+ *	FILO Artecboot loader, enables multiboot through custom header 
+ *
+ *	Copyright 2006 Andrei Birjukov <andrei.birjukov at artecdesign.ee> and
+ *	Artec Design LLC http://www.artecdesign.ee
+ *
+ *	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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ******************************************************************************/
+
+#include <lib.h>
+#include <fs.h>
+#include <sys_info.h>
+#include "artecboot.h"
+#include "../fs/filesys.h"
+
+#define DEBUG_THIS DEBUG_ARTECBOOT
+#include <debug.h>
+
+static ARTECBOOT_HEADER bootHdr;
+
+int artecboot_load(struct sys_info *info, const char *file, const char *cmdline)
+{
+	int i;
+
+	printf("Starting the Artecboot loader...\n");
+	// clear the boot header
+	memset(&bootHdr, 0, sizeof(bootHdr));
+	
+	// try opening the boot parameter file
+	if (!file_open(file))
+	{
+		printf("Boot error: failed to open image file: %s\n", file);
+		return LOADER_NOT_SUPPORT;
+	}
+
+	file_seek(0);	// seek to the beginning of the parameter file
+	
+	// now read out the boot header
+	if(file_read(&bootHdr, sizeof(ARTECBOOT_HEADER)) != sizeof(ARTECBOOT_HEADER))
+	{
+		printf("Boot error: failed reading the boot image header\n");
+		return LOADER_NOT_SUPPORT;
+	}
+	
+	// check whether the parameter data is valid at all
+	if(bootHdr.magicHeader != ARTECBOOT_HEADER_MAGIC)
+	{
+		debug("No Artecboot signature found, aborting\n");
+		return LOADER_NOT_SUPPORT;
+	}
+
+	// check the version number
+	if(bootHdr.bootVersion > CURRENT_VERSION)
+	{
+		printf("Boot error: incompatible version number: %x\n", bootHdr.bootVersion);
+		return LOADER_NOT_SUPPORT;
+	}
+	
+	// shall we replace the command line?
+	if(bootHdr.bitFlags & FLAG_CMDLINE)
+	{
+		// check the command line and wipe out all junk
+		for(i=0; bootHdr.cmdLine[i] != 0; i++)
+			switch(bootHdr.cmdLine[i])
+			{
+			case '\n':
+			case '\r':
+				bootHdr.cmdLine[i] = ' ';
+				break;
+			default:
+				// do nothing
+				break;
+			}
+	}
+	else if(cmdline) 
+		strncpy(bootHdr.cmdLine, cmdline, sizeof(bootHdr.cmdLine));
+	
+	// proceed basing on the specified OS type
+	switch(bootHdr.osType)
+	{
+	case OS_LINUX:
+		if(bootHdr.bitFlags & FLAG_INITRD)
+		{
+			char initrdParam[100];
+			if(bootHdr.bitFlags & FLAG_FILESYSTEM)
+			{
+				// we are using a real filesystem, so format the initrd file as usually
+				sprintf(initrdParam, " initrd=%s", bootHdr.initrdFile); 
+			}
+			else
+			{
+				// we are using a 'fake' filesystem, so use the image offset
+				sprintf(initrdParam, " initrd=flashb at 0x%x,0x%x", 
+						bootHdr.initrdStart, bootHdr.initrdSize);
+			}			
+
+			debug("adding initrd parameter: %s\n", initrdParam); 
+			strncat(bootHdr.cmdLine, initrdParam, sizeof(bootHdr.cmdLine));
+		}
+	
+		printf("Starting Linux loader...\n");
+
+		// if using a real filesystem, load the kernel image from a specified file		
+		if(bootHdr.bitFlags & FLAG_FILESYSTEM)
+			linux_load(info, bootHdr.kernelFile, bootHdr.cmdLine);
+		// if using a 'fake' filesystem, consider reading from the same image
+		else
+		{
+			part_start = bootHdr.kernelStart >> DEV_SECTOR_BITS;	
+			part_length = ((bootHdr.kernelSize-1) >> DEV_SECTOR_BITS) + 1;
+			filemax = bootHdr.kernelSize;
+			linux_load(info, file, bootHdr.cmdLine);
+		}
+	
+		break;
+		
+	case OS_WINCE:
+
+		printf("Starting Windows CE loader...\n");
+		// if using a real filesystem, load the kernel image from a specified file		
+		if(bootHdr.bitFlags & FLAG_FILESYSTEM)
+			wince_load(info, bootHdr.kernelFile, bootHdr.cmdLine);
+		// if using a 'fake' filesystem, consider reading from the same image
+		else
+		{
+			part_start = bootHdr.kernelStart >> DEV_SECTOR_BITS;	
+			part_length = ((bootHdr.kernelSize-1) >> DEV_SECTOR_BITS) + 1;
+			filemax = bootHdr.kernelSize;	
+			wince_load(info, file, bootHdr.cmdLine);
+		}
+
+		break;	
+		
+	default:
+		printf("Boot error: unknown OS type, aborting: %d\n", bootHdr.osType);
+		return LOADER_NOT_SUPPORT;
+	}
+	
+	return 0;
+}

Modified: trunk/filo-0.5/i386/defconfig
===================================================================
--- trunk/filo-0.5/i386/defconfig	2008-05-03 14:48:04 UTC (rev 47)
+++ trunk/filo-0.5/i386/defconfig	2008-05-03 15:03:45 UTC (rev 48)
@@ -3,6 +3,13 @@
 # Loader for standard Linux kernel image, a.k.a. /vmlinuz
 LINUX_LOADER = 1
 
+# Loader for Windows CE image
+# Leave disabled for now. Not supported.
+#WINCE_LOADER = 1
+
+# Artecboot loader support
+#ARTEC_BOOT = 1
+
 # Boot FILO from Multiboot loader (eg. GRUB)
 #MULTIBOOT_IMAGE = 1
 

Modified: trunk/filo-0.5/i386/linux_load.c
===================================================================
--- trunk/filo-0.5/i386/linux_load.c	2008-05-03 14:48:04 UTC (rev 47)
+++ trunk/filo-0.5/i386/linux_load.c	2008-05-03 15:03:45 UTC (rev 48)
@@ -164,11 +164,11 @@
     uint32_t kern_addr;
 
     if (file_read(hdr, sizeof *hdr) != sizeof *hdr) {
-	debug("Can't read Linux header\n");
+	printf("Can't read Linux header\n");
 	return 0;
     }
     if (hdr->boot_sector_magic != 0xaa55) {
-	debug("Not a Linux kernel image\n");
+	printf("Not a Linux kernel image\n");
 	return 0;
     }
 
@@ -178,7 +178,7 @@
 	 * Perform a simple (incomplete) sanity check. */
 	if (hdr->setup_sects >= 16
 		|| file_size() - (hdr->setup_sects<<9) >= 512<<10) {
-	    debug("This looks like a bootdisk image but not like Linux...\n");
+	    printf("This looks like a bootdisk image but not like Linux...\n");
 	    return 0;
 	}
 

Added: trunk/filo-0.5/include/artecboot.h
===================================================================
--- trunk/filo-0.5/include/artecboot.h	                        (rev 0)
+++ trunk/filo-0.5/include/artecboot.h	2008-05-03 15:03:45 UTC (rev 48)
@@ -0,0 +1,34 @@
+// Artecboot header, gives information to loader
+
+#define ARTECBOOT_HEADER_MAGIC		0x10ADFACE
+#define CURRENT_VERSION				0x0102
+
+#define OS_UNKNOWN					0x00
+#define OS_LINUX					0x01
+#define OS_WINCE					0x02
+
+#define FLAG_INITRD					0x0001		// if set, the loader will provide initrd to kernel
+#define FLAG_FILESYSTEM				0x0002		// if set, the loader will use specified file names
+#define FLAG_CMDLINE				0x0004		// if set, the loader will pass the new command line
+
+typedef struct __attribute__ ((packed))
+{
+	unsigned long	magicHeader;
+	unsigned short	bootVersion;
+	unsigned short	headerSize;		// also kernel image start
+	unsigned long	imageSize;		// NB! since 1.02 is the total image/partition size
+	unsigned long	bitFlags;
+	unsigned short	osType;
+	char			cmdLine[256];
+	unsigned long	kernelStart;	// used with Artecboot VFS / NULLFS
+	unsigned long	kernelSize;		// used with Artecboot VFS / NULLFS
+	unsigned long	initrdStart;	// used with Artecboot VFS / NULLFS
+	unsigned long	initrdSize;		// used with Artecboot VFS / NULLFS
+	char			kernelFile[100];	// valid only with FLAG_FILESYSTEM
+	char			initrdFile[100];	// valid only with FLAG_FILESYSTEM
+
+} ARTECBOOT_HEADER;
+
+#define ABOOT_FILE_KERNEL	"/kernel"
+#define ABOOT_FILE_INITRD	"/initrd"
+#define ABOOT_FILE_HEADER	"/header"

Modified: trunk/filo-0.5/include/fs.h
===================================================================
--- trunk/filo-0.5/include/fs.h	2008-05-03 14:48:04 UTC (rev 47)
+++ trunk/filo-0.5/include/fs.h	2008-05-03 15:03:45 UTC (rev 48)
@@ -5,6 +5,10 @@
 
 typedef uint64_t sector_t;
 
+#define DEV_SECTOR_BITS		9
+#define DEV_SECTOR_SIZE		(1<<9)
+#define DEV_SECTOR_MASK		(DEV_SECTOR_SIZE-1)
+
 #ifdef IDE_DISK
 int ide_probe(int drive);
 int ide_read(int drive, sector_t sector, void *buffer);
@@ -15,20 +19,29 @@
 int usb_read(int drive, sector_t sector, void *buffer);
 #endif
 
+#ifdef FLASH_DISK
+int flash_probe(int drive);
+int flash_read(int drive, sector_t sector, void *buffer);
+#endif
+
 #define DISK_IDE 1
 #define DISK_MEM 2
 #define DISK_USB 3
+#define DISK_FLASH 4
 
 int devopen(const char *name, int *reopen);
 int devread(unsigned long sector, unsigned long byte_offset,
 	unsigned long byte_len, void *buf);
+void dev_set_partition(unsigned long start, unsigned long size);
+void dev_get_partition(unsigned long *start, unsigned long *size);
 
 int file_open(const char *filename);
 int file_read(void *buf, unsigned long len);
 int file_seek(unsigned long offset);
 unsigned long file_size(void);
+void file_set_size(unsigned long size);
 
-#define PARTITION_UNKNOWN 0xbad6a7
+#define PARTITION_UNKNOWN	0xbad6a7
 
 #ifdef ELTORITO
 int open_eltorito_image(int part, unsigned long *start, unsigned long *length);

Modified: trunk/filo-0.5/include/lib.h
===================================================================
--- trunk/filo-0.5/include/lib.h	2008-05-03 14:48:04 UTC (rev 47)
+++ trunk/filo-0.5/include/lib.h	2008-05-03 15:03:45 UTC (rev 48)
@@ -58,6 +58,8 @@
 char *strncpy(char *to, const char *from, int count);
 char * strcpy (char *dest, const char *src);
 char * strstr (const char *s1, const char *s2);
+int strncat (char *s1, const char *s2, int n);
+int sprintf(char * buf, const char *fmt, ...);
 
 unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base);
 unsigned long long strtoull_with_suffix(const char *cp,char **endp,unsigned int base);
@@ -83,4 +85,16 @@
 #define linux_load(x,y,z) LOADER_NOT_SUPPORT /* nop */
 #endif
 
+#if WINCE_LOADER
+int wince_load(struct sys_info *, const char *filename, const char *cmdline);
+#else
+#define wince_load(x,y,z) LOADER_NOT_SUPPORT /* nop */
+#endif
+
+#if ARTEC_BOOT
+int artecboot_load(struct sys_info *, const char *filename, const char *cmdline);
+#else
+#define artecboot_load(x,y,z) LOADER_NOT_SUPPORT /* nop */
+#endif
+
 #endif /* LIB_H */

Modified: trunk/filo-0.5/main/console.c
===================================================================
--- trunk/filo-0.5/main/console.c	2008-05-03 14:48:04 UTC (rev 47)
+++ trunk/filo-0.5/main/console.c	2008-05-03 15:03:45 UTC (rev 48)
@@ -1,10 +1,13 @@
 #include <arch/stdint.h>
 #include <lib.h>
 
+void video_cls();
+
 void console_init(void)
 {
 #ifdef VGA_CONSOLE
-    vga_init();
+	vga_init();
+	video_cls();
 #endif
 #ifdef SERIAL_CONSOLE
     serial_init();

Modified: trunk/filo-0.5/main/filo.c
===================================================================
--- trunk/filo-0.5/main/filo.c	2008-05-03 14:48:04 UTC (rev 47)
+++ trunk/filo-0.5/main/filo.c	2008-05-03 15:03:45 UTC (rev 48)
@@ -49,8 +49,10 @@
 	param++;
     }
 
+	if (artecboot_load(&sys_info, file, param) == LOADER_NOT_SUPPORT)
     if (elf_load(&sys_info, file, param) == LOADER_NOT_SUPPORT)
 	if (linux_load(&sys_info, file, param) == LOADER_NOT_SUPPORT)
+	if (wince_load(&sys_info, file, param) == LOADER_NOT_SUPPORT)
 	    printf("Unsupported image format\n");
     free(file);
 }





More information about the coreboot mailing list