* Avoid flicker on the TRAB's VFD by synchronizing the enable with

the HSYNC/VSYNC. Requires new CPLD code (Version 101 for Rev. 100
  boards, version 153 for Rev. 200 boards).

* Patch by Vladimir Gurevich, 12 Mar 2003:
  Fix relocation problem of statically initialized string pointers
  in common/cmd_pci.c

* Patch by Kai-Uwe Blm, 12 Mar 2003:
  Cleanup & bug fixes for JFFS2 code:
  - the memory mangement was broken. It caused havoc on malloc by
    writing beyond the block boundaries.
  - the length calculation for files was wrong, sometimes resulting
    in short file reads.
  - data copying now optionally takes fragment version numbers into
    account, to avoid copying from older data.
  See doc/README.JFFS2 for details.
This commit is contained in:
wdenk 2003-03-14 20:47:52 +00:00
parent 09127c6096
commit 06d01dbe00
22 changed files with 846 additions and 618 deletions

View File

@ -2,6 +2,24 @@
Changes since U-Boot 0.2.2:
======================================================================
* Avoid flicker on the TRAB's VFD by synchronizing the enable with
the HSYNC/VSYNC. Requires new CPLD code (Version 101 for Rev. 100
boards, version 153 for Rev. 200 boards).
* Patch by Vladimir Gurevich, 12 Mar 2003:
Fix relocation problem of statically initialized string pointers
in common/cmd_pci.c
* Patch by Kai-Uwe Blöm, 12 Mar 2003:
Cleanup & bug fixes for JFFS2 code:
- the memory mangement was broken. It caused havoc on malloc by
writing beyond the block boundaries.
- the length calculation for files was wrong, sometimes resulting
in short file reads.
- data copying now optionally takes fragment version numbers into
account, to avoid copying from older data.
See doc/README.JFFS2 for details.
* Patch by Josef Wagner, 12 Mar 2003:
- 16/32 MB and 50/80 MHz support with auto-detection for IP860
- ETH05 and BEDBUG support for CU824

View File

@ -38,10 +38,10 @@
int misc_init_r(void)
{
#if 0
uchar *str;
/* determine if the software update key is pressed during startup */
#if 0
/* not ported yet... */
if (GPLR0 & 0x00000800) {
printf("using bootcmd_normal (sw-update button not pressed)\n");

View File

@ -21,4 +21,8 @@
# MA 02111-1307 USA
#
#
# TOP860 board
#
TEXT_BASE = 0x80000000

View File

@ -39,7 +39,7 @@
* The Innokom board has GPIO70 connected to SCLK which can be toggled
* until all chips think that their current cycles are finished.
*/
int i2c_init_board(void)
void i2c_init_board(void)
{
int i;
@ -53,8 +53,6 @@ int i2c_init_board(void)
}
/* set gpio pin to input */
GPDR(70) &= ~GPIO_bit(70);
return 0;
}

View File

@ -65,10 +65,8 @@ unsigned long flash_init (void)
int i;
ulong size = 0;
for (i = 0; i < CFG_MAX_FLASH_BANKS; i++)
{
switch (i)
{
for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
switch (i) {
case 0:
flash_get_size ((FPW *) PHYS_FLASH_1, &flash_info[i]);
flash_get_offsets (PHYS_FLASH_1, &flash_info[i]);
@ -93,8 +91,7 @@ unsigned long flash_init (void)
flash_protect ( FLAG_PROTECT_SET,
CFG_ENV_ADDR,
CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
&flash_info[0]);
CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0] );
return size;
}
@ -129,14 +126,21 @@ void flash_print_info (flash_info_t *info)
}
switch (info->flash_id & FLASH_VENDMASK) {
case FLASH_MAN_INTEL: printf ("INTEL "); break;
default: printf ("Unknown Vendor "); break;
case FLASH_MAN_INTEL:
printf ("INTEL ");
break;
default:
printf ("Unknown Vendor ");
break;
}
switch (info->flash_id & FLASH_TYPEMASK) {
case FLASH_28F128J3A:
printf ("28F128J3A\n"); break;
default: printf ("Unknown Chip Type\n"); break;
printf ("28F128J3A\n");
break;
default:
printf ("Unknown Chip Type\n");
break;
}
printf (" Size: %ld MB in %d Sectors\n",
@ -148,8 +152,7 @@ void flash_print_info (flash_info_t *info)
printf ("\n ");
printf (" %08lX%s",
info->start[i],
info->protect[i] ? " (RO)" : " "
);
info->protect[i] ? " (RO)" : " ");
}
printf ("\n");
return;
@ -218,7 +221,7 @@ static ulong flash_get_size (FPW *addr, flash_info_t *info)
int flash_erase (flash_info_t *info, int s_first, int s_last)
{
int flag, prot, sect;
ulong type, start, now, last;
ulong type, start, last;
int rcode = 0;
if ((s_first < 0) || (s_first > s_last)) {
@ -354,8 +357,7 @@ int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
}
wp += port_width;
cnt -= port_width;
if (count++ > 0x800)
{
if (count++ > 0x800) {
spin_wheel ();
count = 0;
}
@ -390,12 +392,11 @@ static int write_data (flash_info_t *info, ulong dest, FPW data)
{
FPWV *addr = (FPWV *) dest;
ulong status;
ulong start;
int flag;
/* Check if Flash is (sufficiently) erased */
if ((*addr & data) != data) {
printf("not erased at %08lx (%x)\n",(ulong)addr,*addr);
printf ("not erased at %08lx (%lx)\n", (ulong) addr, *addr);
return (2);
}
/* Disable interrupts which might cause a timeout here */
@ -420,13 +421,11 @@ static int write_data (flash_info_t *info, ulong dest, FPW data)
return (0);
}
void inline
spin_wheel(void)
void inline spin_wheel (void)
{
static int r=0,p=0;
static int p = 0;
static char w[] = "\\/-";
printf ("\010%c", w[p]);
(++p == 3) ? (p = 0) : 0;
}

View File

@ -49,7 +49,9 @@ int mpl_prg(unsigned long src,unsigned long size)
unsigned long start;
flash_info_t *info;
int i,rc;
#if defined(CONFIG_PIP405) || defined(CONFIG_MIP405)
unsigned long *magic = (unsigned long *)src;
#endif
info = &flash_info[0];

View File

@ -102,7 +102,7 @@ int do_vcma9(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
printf("\nplease defined 'ethaddr'\n");
}
} else if (strcmp(argv[2], "dump") == 0) {
uchar addr, endaddr, csum; ushort data;
uchar addr = 0, endaddr, csum; ushort data;
printf("Dump of CS8900 config device: ");
cs8900_e2prom_read(addr, &data);

View File

@ -183,7 +183,6 @@ static uchar Get_Board_PCB(void)
int checkboard(void)
{
unsigned char s[50];
unsigned char bc, var, rc;
int i;
backup_t *b = (backup_t *) s;

View File

@ -59,10 +59,24 @@
#define FRAME_BUF_SIZE ((256*4*56)/8)
#define frame_buf_offs 4
/* defines for starting Timer3 as CPLD-Clk */
#define START3 (1 << 16)
#define UPDATE3 (1 << 17)
#define INVERT3 (1 << 18)
#define RELOAD3 (1 << 19)
/* CPLD-Register for controlling vfd-blank-signal */
#define VFD_DISABLE (*(volatile uchar *)0x04038000=0x0000)
#define VFD_ENABLE (*(volatile uchar *)0x04038000=0x0001)
/* Supported VFD Types */
#define VFD_TYPE_T119C 1 /* Noritake T119C VFD */
#define VFD_TYPE_MN11236 2
/*#define NEW_CPLD_CLK*/
int vfd_board_id;
/* taken from armboot/common/vfd.c */
unsigned long adr_vfd_table[112][18][2][4][2];
unsigned char bit_vfd_table[112][18][2][4][2];
@ -80,9 +94,7 @@ void init_grid_ctrl(void)
/*
* clear frame buffer (logical clear => set to "black")
*/
memset ((void *)(gd->fb_base),
gd->vfd_inv_data ? 0xFF : 0,
FRAME_BUF_SIZE);
memset ((void *)(gd->fb_base), 0, FRAME_BUF_SIZE);
switch (gd->vfd_type) {
case VFD_TYPE_T119C:
@ -98,9 +110,6 @@ void init_grid_ctrl(void)
bit_nr = bit % 8;
bit_nr = (bit_nr > 3) ? bit_nr-4 : bit_nr+4;
temp=(*(volatile unsigned char*)(adr));
if (gd->vfd_inv_data)
temp &= ~(1<<bit_nr);
else
temp |= (1<<bit_nr);
(*(volatile unsigned char*)(adr))=temp;
@ -115,9 +124,6 @@ void init_grid_ctrl(void)
bit_nr = bit%8;
bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;
temp=(*(volatile unsigned char*)(adr));
if (gd->vfd_inv_data)
temp &= ~(1<<bit_nr);
else
temp |= (1<<bit_nr);
(*(volatile unsigned char*)(adr))=temp;
}
@ -136,9 +142,6 @@ void init_grid_ctrl(void)
bit_nr = bit % 8;
bit_nr = (bit_nr > 3) ? bit_nr-4 : bit_nr+4;
temp=(*(volatile unsigned char*)(adr));
if (gd->vfd_inv_data)
temp &= ~(1<<bit_nr);
else
temp |= (1<<bit_nr);
(*(volatile unsigned char*)(adr))=temp;
@ -152,9 +155,6 @@ void init_grid_ctrl(void)
bit_nr = bit%8;
bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;
temp=(*(volatile unsigned char*)(adr));
if (gd->vfd_inv_data)
temp &= ~(1<<bit_nr);
else
temp |= (1<<bit_nr);
(*(volatile unsigned char*)(adr))=temp;
}
@ -295,17 +295,10 @@ void set_vfd_pixel(unsigned char x, unsigned char y,
bit_nr = bit_vfd_table[x][y][color][display][0];
temp=(*(volatile unsigned char*)(adr));
if (gd->vfd_inv_data) {
if (value)
temp &= ~(1<<bit_nr);
else
temp |= (1<<bit_nr);
} else {
if (value)
temp |= (1<<bit_nr);
else
temp &= ~(1<<bit_nr);
}
(*(volatile unsigned char*)(adr))=temp;
}
@ -365,20 +358,57 @@ void transfer_pic(int display, unsigned char *adr, int height, int width)
*/
int vfd_init_clocks (void)
{
/* Port-Pins als LCD-Ausgang */
rPCCON = (rPCCON & 0xFFFFFF00)| 0x000000AA;
/* Port-Pins als LCD-Ausgang */
rPDCON = (rPDCON & 0xFFFFFF03)| 0x000000A8;
#ifdef CFG_WITH_VFRAME
/* mit VFRAME zum Messen */
rPDCON = (rPDCON & 0xFFFFFF00)| 0x000000AA;
#endif
rLCDCON2 = 0x000DC000;
rLCDCON3 = 0x0051000A;
rLCDCON4 = 0x00000001;
rLCDCON5 = 0x00000440;
/* try to determine display type from the value
* defined by pull-ups
*/
rPCUP = (rPCUP & 0xFFF0); /* activate GPC0...GPC3 pullups */
rPCCON = (rPCCON & 0xFFFFFF00); /* configure GPC0...GPC3 as inputs */
udelay (10); /* allow signals to settle */
vfd_board_id = (~rPCDAT) & 0x000F; /* read GPC0...GPC3 port pins */
VFD_DISABLE; /* activate blank for the vfd */
#define NEW_CPLD_CLK
#ifdef NEW_CPLD_CLK
if (vfd_board_id) {
/* If new board revision, then use PWM 3 as cpld-clock */
/* Enable 500 Hz timer for fill level sensor to operate properly */
/* Configure TOUT3 as functional pin, disable pull-up */
rPDCON &= ~0x30000;
rPDCON |= 0x20000;
rPDUP |= (1 << 8);
/* Configure the prescaler */
rTCFG0 &= ~0xff00;
rTCFG0 |= 0x0f00;
/* Select MUX input (divider) for timer3 (1/16) */
rTCFG1 &= ~0xf000;
rTCFG1 |= 0x3000;
/* Enable autoreload and set the counter and compare
* registers to values for the 500 Hz clock
* (for a given prescaler (15) and divider (16)):
* counter = (66000000 / 500) >> 9;
*/
rTCNTB3 = 0x101;
rTCMPB3 = 0x101 / 2;
/* Start timer */
rTCON = (rTCON | UPDATE3 | RELOAD3) & ~INVERT3;
rTCON = (rTCON | START3) & ~UPDATE3;
}
#endif
/* If old board revision, then use vm-signal as cpld-clock */
rLCDCON2 = 0x00FFC000;
rLCDCON3 = 0x0007FF00;
rLCDCON4 = 0x00000000;
rLCDCON5 = 0x00000400;
rLCDCON1 = 0x00000B75;
/* VM (GPD1) is used as clock for the CPLD */
rPDCON = (rPDCON & 0xFFFFFFF3) | 0x00000008;
return 0;
}
@ -397,7 +427,7 @@ int drv_vfd_init(void)
char *tmp;
ulong palette;
static int vfd_init_done = 0;
int vfd_id;
int vfd_inv_data = 0;
DECLARE_GLOBAL_DATA_PTR;
@ -405,17 +435,9 @@ int drv_vfd_init(void)
return (0);
vfd_init_done = 1;
/* try to determine display type from the value
* defined by pull-ups
*/
rPCUP = (rPCUP & 0xFFF0); /* activate GPC0...GPC3 pullups */
rPCCON = (rPCCON & 0xFFFFFF00); /* configure GPC0...GPC3 as inputs */
udelay(10); /* allow signals to settle */
debug("Detecting Revison of WA4-VFD: ID=0x%X\n", vfd_board_id);
vfd_id = (~rPCDAT) & 0x000F; /* read GPC0...GPC3 port pins */
debug("Detecting Revison of WA4-VFD: ID=0x%X\n", vfd_id);
switch (vfd_id) {
switch (vfd_board_id) {
case 0: /* board revision < Rev.200 */
if ((tmp = getenv ("vfd_type")) == NULL) {
break;
@ -428,19 +450,18 @@ int drv_vfd_init(void)
/* cannot use printf for a warning here */
gd->vfd_type = 0; /* unknown */
}
gd->vfd_inv_data = 0;
break;
default: /* default to MN11236, data inverted */
gd->vfd_type = VFD_TYPE_MN11236;
gd->vfd_inv_data = 1;
vfd_inv_data = 1;
setenv ("vfd_type", "MN11236");
}
debug ("VFD type: %s%s\n",
(gd->vfd_type == VFD_TYPE_T119C) ? "T119C" :
(gd->vfd_type == VFD_TYPE_MN11236) ? "MN11236" :
"unknown",
gd->vfd_inv_data ? ", inverted data" : "");
vfd_inv_data ? ", inverted data" : "");
gd->fb_base = gd->fb_base;
create_vfd_table();
@ -458,11 +479,33 @@ int drv_vfd_init(void)
* (wrap around)
* see manual S3C2400
*/
/* Stopp LCD-Controller */
rLCDCON1 = 0x00000000;
/* frame buffer startadr */
rLCDSADDR1 = gd->fb_base >> 1;
/* frame buffer endadr */
rLCDSADDR2 = (gd->fb_base + FRAME_BUF_SIZE) >> 1;
rLCDSADDR3 = ((256/4));
rLCDCON2 = 0x000DC000;
rLCDCON3 = 0x0051000A;
rLCDCON4 = 0x00000001;
if (gd->vfd_type && vfd_inv_data)
rLCDCON5 = 0x000004C0;
else
rLCDCON5 = 0x00000440;
/* Port pins as LCD output */
rPCCON = (rPCCON & 0xFFFFFF00)| 0x000000AA;
rPDCON = (rPDCON & 0xFFFFFF03)| 0x000000A8;
/* Synchronize VFD enable with LCD controller to avoid flicker */
rLCDCON1 = 0x00000B75; /* Start LCD-Controller */
while((rLCDCON5 & 0x180000)!=0x100000); /* Wait for end of VSYNC */
while((rLCDCON5 & 0x060000)!=0x040000); /* Wait for next HSYNC */
while((rLCDCON5 & 0x060000)==0x040000);
while((rLCDCON5 & 0x060000)!=0x000000);
if(gd->vfd_type)
VFD_ENABLE;
debug ("LCDSADDR1: %lX\n", rLCDSADDR1);
debug ("LCDSADDR2: %lX\n", rLCDSADDR2);
@ -471,6 +514,17 @@ int drv_vfd_init(void)
return 0;
}
/*
* Disable VFD: should be run before resetting the system:
* disable VM, enable pull-up
*/
void disable_vfd (void)
{
VFD_DISABLE;
rPDCON &= ~0xC;
rPDUP &= ~0x2;
}
/************************************************************************/
/* ** ROM capable initialization part - needed to reserve FB memory */
/************************************************************************/

View File

@ -115,28 +115,65 @@ void pciinfo(int BusNum, int ShortPCIListing)
char* pci_classes_str(u8 class)
{
static char *pci_classes[] = {
"Build before PCI Rev2.0",
"Mass storage controller",
"Network controller ",
"Display controller ",
"Multimedia device ",
"Memory controller ",
"Bridge device ",
"Simple comm. controller",
"Base system peripheral ",
"Input device ",
"Docking station ",
"Processor ",
"Serial bus controller ",
"Reserved entry ",
"Does not fit any class "
};
if (class < (sizeof pci_classes / sizeof *pci_classes))
return pci_classes[(int) class];
switch (class) {
case PCI_CLASS_NOT_DEFINED:
return "Build before PCI Rev2.0";
break;
case PCI_BASE_CLASS_STORAGE:
return "Mass storage controller";
break;
case PCI_BASE_CLASS_NETWORK:
return "Network controller ";
break;
case PCI_BASE_CLASS_DISPLAY:
return "Display controller ";
break;
case PCI_BASE_CLASS_MULTIMEDIA:
return "Multimedia device ";
break;
case PCI_BASE_CLASS_MEMORY:
return "Memory controller ";
break;
case PCI_BASE_CLASS_BRIDGE:
return "Bridge device ";
break;
case PCI_BASE_CLASS_COMMUNICATION:
return "Simple comm. controller";
break;
case PCI_BASE_CLASS_SYSTEM:
return "Base system peripheral ";
break;
case PCI_BASE_CLASS_INPUT:
return "Input device ";
break;
case PCI_BASE_CLASS_DOCKING:
return "Docking station ";
break;
case PCI_BASE_CLASS_PROCESSOR:
return "Processor ";
break;
case PCI_BASE_CLASS_SERIAL:
return "Serial bus controller ";
break;
case PCI_BASE_CLASS_INTELLIGENT:
return "Intelligent controller ";
break;
case PCI_BASE_CLASS_SATELLITE:
return "Satellite controller ";
break;
case PCI_BASE_CLASS_CRYPT:
return "Cryptographic device ";
break;
case PCI_BASE_CLASS_SIGNAL_PROCESSING:
return "DSP ";
break;
case PCI_CLASS_OTHERS:
return "Does not fit any class ";
break;
default:
return "??? ";
break;
};
}
/*

View File

@ -199,9 +199,9 @@ int interrupt_init (void)
/* load value for 10 ms timeout */
lastdec = rTCNTB4 = timer_load_val;
/* auto load, manual update of Timer 4 */
rTCON = 0x600000;
rTCON = (rTCON & ~0x0700000) | 0x600000;
/* auto load, start Timer 4 */
rTCON = 0x500000;
rTCON = (rTCON & ~0x0700000) | 0x500000;
timestamp = 0;
return (0);
@ -296,8 +296,10 @@ ulong get_tbclk (void)
#if defined(CONFIG_SMDK2400) || defined(CONFIG_TRAB)
tbclk = timer_load_val * 100;
#elif defined(CONFIG_SMDK2410)
#elif defined(CONFIG_SMDK2410) || defined(CONFIG_VCMA9)
tbclk = CFG_HZ;
#else
# error "tbclk not configured"
#endif
return tbclk;

View File

@ -446,6 +446,9 @@ fiq:
reset_cpu:
#ifdef CONFIG_S3C2400
bl disable_interrupts
# ifdef CONFIG_TRAB
bl disable_vfd
# endif
ldr r1, _rWTCON
ldr r2, _rWTCNT
/* Disable watchdog */

View File

@ -9,6 +9,14 @@ fsload - load binary file from a file system image
fsinfo - print information about file systems
ls - list files in a directory
If you boot from a partition which is mounted writable, and you
update your boot environment by replacing single files on that
partition, you should also define CFG_JFFS2_SORT_FRAGMENTS. Scanning
the JFFS2 filesystem takes *much* longer with this feature, though.
Sorting is done while inserting into the fragment list, which is
more or less a bubble sort. That algorithm is known to be O(n^2),
thus you should really consider if you can avoid it!
There is two ways for JFFS2 to find the disk. The default way uses
the flash_info structure to find the start of a JFFS2 disk (called

View File

@ -296,7 +296,7 @@ int cs8900_e2prom_read(unsigned char addr, unsigned short *value)
/* write a 16-bit word into the EEPROM */
/***********************************************************/
void cs8900_e2prom_write(unsigned char addr, unsigned short value)
int cs8900_e2prom_write(unsigned char addr, unsigned short value)
{
cs8900_e2prom_ready();
put_reg(PP_EECMD, EEPROM_WRITE_EN);
@ -307,7 +307,7 @@ void cs8900_e2prom_write(unsigned char addr, unsigned short value)
put_reg(PP_EECMD, EEPROM_WRITE_DIS);
cs8900_e2prom_ready();
return;
return 0;
}
#endif /* COMMANDS & CFG_NET */

View File

@ -253,6 +253,6 @@
#define EEPROM_ERASE_CMD 0x0300
extern int cs8900_e2prom_read(uchar, ushort *);
extern void cs8900_e2prom_write(uchar, ushort);
extern int cs8900_e2prom_write(uchar, ushort);
#endif /* CONFIG_DRIVER_CS8900 */

View File

@ -64,10 +64,12 @@ static int GetIICSDA(void)
return (rGPEDAT & 0x8000) >> 15;
}
#if 0
static void SetIICSDA(int x)
{
rGPEDAT = (rGPEDAT & ~0x8000) | (x&1) << 15;
}
#endif
static void SetIICSCL(int x)
{

View File

@ -1,3 +1,4 @@
/* vi: set sw=4 ts=4: */
/*
-------------------------------------------------------------------------
* Filename: jffs2.c
@ -75,6 +76,42 @@
*
*/
/*
* Bugfixing by Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de>, (C) Mar/2003
*
* - overhaul of the memory management. Removed much of the "paper-bagging"
* in that part of the code, fixed several bugs, now frees memory when
* partition is changed.
* It's still ugly :-(
* - fixed a bug in jffs2_1pass_read_inode where the file length calculation
* was incorrect. Removed a bit of the paper-bagging as well.
* - removed double crc calculation for fragment headers in jffs2_private.h
* for speedup.
* - scan_empty rewritten in a more "standard" manner (non-paperbag, that is).
* - spinning wheel now spins depending on how much memory has been scanned
* - lots of small changes all over the place to "improve" readability.
* - implemented fragment sorting to ensure that the newest data is copied
* if there are multiple copies of fragments for a certain file offset.
*
* The fragment sorting feature must be enabled by CFG_JFFS2_SORT_FRAGMENTS.
* Sorting is done while adding fragments to the lists, which is more or less a
* bubble sort. This takes a lot of time, and is most probably not an issue if
* the boot filesystem is always mounted readonly.
*
* You should define it if the boot filesystem is mounted writable, and updates
* to the boot files are done by copying files to that filesystem.
*
*
* There's a big issue left: endianess is completely ignored in this code. Duh!
*
*
* You still should have paper bags at hand :-(. The code lacks more or less
* any comment, and is still arcane and difficult to read in places. As this
* is incompatible with any new code from the jffs2 maintainers anyway, it
* should probably be dumped and replaced by something like jffs2reader!
*/
#include <common.h>
#include <config.h>
#include <malloc.h>
@ -88,6 +125,23 @@
#include "jffs2_private.h"
#define NODE_CHUNK 1024 /* size of memory allocation chunk in b_nodes */
#define SPIN_BLKSIZE 18 /* spin after having scanned 1<<BLKSIZE bytes */
/* Debugging switches */
#undef DEBUG_DIRENTS /* print directory entry list after scan */
#undef DEBUG_FRAGMENTS /* print fragment list after scan */
#undef DEBUG /* enable debugging messages */
#ifdef DEBUG
# define DEBUGF(fmt,args...) printf(fmt ,##args)
#else
# define DEBUGF(fmt,args...)
#endif
/* Compression names */
static char *compr_names[] = {
"NONE",
@ -96,116 +150,172 @@ static char *compr_names[] = {
"RUBINMIPS",
"COPY",
"DYNRUBIN",
"ZLIB" };
"ZLIB"
};
static char spinner[] = { '|', '\\', '-', '/' };
/* Spinning wheel */
static char spinner[] = { '|', '/', '-', '\\' };
#define DEBUG
#ifdef DEBUG
# define DEBUGF(fmt,args...) printf(fmt ,##args)
#else
# define DEBUGF(fmt,args...)
#endif
/* Memory management */
struct mem_block {
u32 index;
struct mem_block *next;
struct b_node nodes[NODE_CHUNK];
};
#define MALLOC_CHUNK (10*1024)
static void
free_nodes(struct b_list *list)
{
while (list->listMemBase != NULL) {
struct mem_block *next = list->listMemBase->next;
free( list->listMemBase );
list->listMemBase = next;
}
}
static struct b_node *
add_node(struct b_node *tail, u32 * count, u32 * memBase)
add_node(struct b_list *list)
{
u32 index;
u32 memLimit;
u32 index = 0;
struct mem_block *memBase;
struct b_node *b;
index = (*count) * sizeof(struct b_node) % MALLOC_CHUNK;
memLimit = MALLOC_CHUNK;
memBase = list->listMemBase;
if (memBase != NULL)
index = memBase->index;
#if 0
putLabeledWord("add_node: index = ", index);
putLabeledWord("add_node: memLimit = ", memLimit);
putLabeledWord("add_node: memBase = ", *memBase);
putLabeledWord("add_node: memBase = ", list->listMemBase);
#endif
/* we need not keep a list of bases since we'll never free the */
/* memory, just jump the the kernel */
if ((index == 0) || (index > memLimit)) { /* we need mode space before we continue */
if ((*memBase = (u32) mmalloc(MALLOC_CHUNK)) == (u32) NULL) {
if (memBase == NULL || index >= NODE_CHUNK) {
/* we need more space before we continue */
memBase = mmalloc(sizeof(struct mem_block));
if (memBase == NULL) {
putstr("add_node: malloc failed\n");
return NULL;
}
memBase->next = list->listMemBase;
index = 0;
#if 0
putLabeledWord("add_node: alloced a new membase at ", *memBase);
#endif
}
/* now we have room to add it. */
b = (struct b_node *) (*memBase + index);
b = &memBase->nodes[index];
index ++;
/* null on first call */
if (tail)
tail->next = b;
#if 0
putLabeledWord("add_node: tail = ", (u32) tail);
if (tail)
putLabeledWord("add_node: tail->next = ", (u32) tail->next);
#endif
#if 0
putLabeledWord("add_node: mb+i = ", (u32) (*memBase + index));
putLabeledWord("add_node: b = ", (u32) b);
#endif
(*count)++;
b->next = (struct b_node *) NULL;
memBase->index = index;
list->listMemBase = memBase;
list->listCount++;
return b;
}
/* we know we have empties at the start offset so we will hop */
/* t points that would be non F if there were a node here to speed this up. */
struct jffs2_empty_node {
u32 first;
u32 second;
};
static struct b_node *
insert_node(struct b_list *list, u32 offset)
{
struct b_node *new;
#ifdef CFG_JFFS2_SORT_FRAGMENTS
struct b_node *b, *prev;
#endif
if (!(new = add_node(list))) {
putstr("add_node failed!\r\n");
return NULL;
}
new->offset = offset;
#ifdef CFG_JFFS2_SORT_FRAGMENTS
if (list->listTail != NULL && list->listCompare(new, list->listTail))
prev = list->listTail;
else if (list->listLast != NULL && list->listCompare(new, list->listLast))
prev = list->listLast;
else
prev = NULL;
for (b = (prev ? prev->next : list->listHead);
b != NULL && list->listCompare(new, b);
prev = b, b = b->next) {
list->listLoops++;
}
if (b != NULL)
list->listLast = prev;
if (b != NULL) {
new->next = b;
if (prev != NULL)
prev->next = new;
else
list->listHead = new;
} else
#endif
{
new->next = (struct b_node *) NULL;
if (list->listTail != NULL) {
list->listTail->next = new;
list->listTail = new;
} else {
list->listTail = list->listHead = new;
}
}
return new;
}
#ifdef CFG_JFFS2_SORT_FRAGMENTS
static int compare_inodes(struct b_node *new, struct b_node *old)
{
struct jffs2_raw_inode *jNew = (struct jffs2_raw_inode *)new->offset;
struct jffs2_raw_inode *jOld = (struct jffs2_raw_inode *)old->offset;
return jNew->version < jOld->version;
}
static int compare_dirents(struct b_node *new, struct b_node *old)
{
struct jffs2_raw_dirent *jNew = (struct jffs2_raw_dirent *)new->offset;
struct jffs2_raw_dirent *jOld = (struct jffs2_raw_dirent *)old->offset;
return jNew->version > jOld->version;
}
#endif
static u32
jffs2_scan_empty(u32 start_offset, struct part_info *part)
{
u32 max = part->size - sizeof(struct jffs2_raw_inode);
char *max = part->offset + part->size - sizeof(struct jffs2_raw_inode);
char *offset = part->offset + start_offset;
/* this would be either dir node_crc or frag isize */
u32 offset = start_offset + 32;
struct jffs2_empty_node *node;
while (offset < max && *(u32 *)offset == 0xFFFFFFFF) {
offset += sizeof(u32);
/* return if spinning is due */
if (((u32)offset & ((1 << SPIN_BLKSIZE)-1)) == 0) break;
}
start_offset += 4;
while (offset < max) {
node = (struct jffs2_empty_node *) (part->offset + offset);
if ((node->first == 0xFFFFFFFF) && (node->second == 0xFFFFFFFF)) {
/* we presume that there were no nodes in between and advance in a hop */
/* putLabeledWord("\t\tjffs2_scan_empty: empty at offset=",offset); */
start_offset = offset + 4;
offset = start_offset + 32; /* orig 32 + 4 bytes for the second==0xfffff */
} else {
return start_offset;
}
}
return start_offset;
return offset - part->offset;
}
static u32
jffs_init_1pass_list(struct part_info *part)
{
if ( 0 != ( part->jffs2_priv=malloc(sizeof(struct b_lists)))){
struct b_lists *pL =(struct b_lists *)part->jffs2_priv;
struct b_lists *pL;
pL->dirListHead = pL->dirListTail = NULL;
pL->fragListHead = pL->fragListTail = NULL;
pL->dirListCount = 0;
pL->dirListMemBase = 0;
pL->fragListCount = 0;
pL->fragListMemBase = 0;
pL->partOffset = 0x0;
if (part->jffs2_priv != NULL) {
pL = (struct b_lists *)part->jffs2_priv;
free_nodes(&pL->frag);
free_nodes(&pL->dir);
free(pL);
}
if (NULL != (part->jffs2_priv = malloc(sizeof(struct b_lists)))) {
pL = (struct b_lists *)part->jffs2_priv;
memset(pL, 0, sizeof(*pL));
#ifdef CFG_JFFS2_SORT_FRAGMENTS
pL->dir.listCompare = compare_dirents;
pL->frag.listCompare = compare_inodes;
#endif
}
return 0;
}
@ -216,21 +326,18 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest)
{
struct b_node *b;
struct jffs2_raw_inode *jNode;
u32 totalSize = 1;
u32 oldTotalSize = 0;
u32 size = 0;
char *lDest = (char *) dest;
u32 totalSize = 0;
u16 latestVersion = 0;
char *lDest;
char *src;
long ret;
int i;
u32 counter = 0;
char totalSizeSet = 0;
#if 0
b = pL->fragListHead;
while (b) {
for (b = pL->frag.listHead; b != NULL; b = b->next) {
jNode = (struct jffs2_raw_inode *) (b->offset);
if ((inode == jNode->ino)) {
#if 0
putLabeledWord("\r\n\r\nread_inode: totlen = ", jNode->totlen);
putLabeledWord("read_inode: inode = ", jNode->ino);
putLabeledWord("read_inode: version = ", jNode->version);
@ -241,58 +348,26 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest)
putLabeledWord("read_inode: compr = ", jNode->compr);
putLabeledWord("read_inode: usercompr = ", jNode->usercompr);
putLabeledWord("read_inode: flags = ", jNode->flags);
}
b = b->next;
}
#endif
#if 1
b = pL->fragListHead;
while (b && (size < totalSize)) {
jNode = (struct jffs2_raw_inode *) (b->offset);
if ((inode == jNode->ino)) {
if ((jNode->isize == oldTotalSize) && (jNode->isize > totalSize)) {
/* 2 consecutive isizes indicate file length */
/* get actual file length from the newest node */
if (jNode->version >= latestVersion) {
totalSize = jNode->isize;
totalSizeSet = 1;
} else if (!totalSizeSet) {
totalSize = size + jNode->dsize + 1;
latestVersion = jNode->version;
}
oldTotalSize = jNode->isize;
if(dest) {
src = ((char *) jNode) + sizeof(struct jffs2_raw_inode);
/* lDest = (char *) (dest + (jNode->offset & ~3)); */
/* ignore data behind latest known EOF */
if (jNode->offset > totalSize)
continue;
lDest = (char *) (dest + jNode->offset);
#if 0
putLabeledWord("\r\n\r\nread_inode: src = ", src);
putLabeledWord("read_inode: src = ", src);
putLabeledWord("read_inode: dest = ", lDest);
putLabeledWord("read_inode: dsize = ", jNode->dsize);
putLabeledWord("read_inode: csize = ", jNode->csize);
putLabeledWord("read_inode: version = ", jNode->version);
putLabeledWord("read_inode: isize = ", jNode->isize);
putLabeledWord("read_inode: offset = ", jNode->offset);
putLabeledWord("read_inode: compr = ", jNode->compr);
putLabeledWord("read_inode: flags = ", jNode->flags);
#endif
switch (jNode->compr) {
case JFFS2_COMPR_NONE:
#if 0
{
int i;
if ((dest > 0xc0092ff0) && (dest < 0xc0093000))
for (i = 0; i < first->length; i++) {
putLabeledWord("\tCOMPR_NONE: src =", src + i);
putLabeledWord("\tCOMPR_NONE: length =", first->length);
putLabeledWord("\tCOMPR_NONE: dest =", dest + i);
putLabeledWord("\tCOMPR_NONE: data =", (unsigned char) *(src + i));
}
}
#endif
ret = (unsigned long) ldr_memcpy(lDest, src, jNode->dsize);
break;
case JFFS2_COMPR_ZERO:
@ -320,22 +395,18 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest)
}
}
size += jNode->dsize;
#if 0
putLabeledWord("read_inode: size = ", size);
putLabeledWord("read_inode: totalSize = ", totalSize);
putLabeledWord("read_inode: compr ret = ", ret);
#endif
}
b = b->next;
counter++;
}
#endif
#if 0
putLabeledWord("read_inode: returning = ", size);
putLabeledWord("read_inode: returning = ", totalSize);
#endif
return size;
return totalSize;
}
/* find the inode from the slashless name given a parent */
@ -354,9 +425,10 @@ jffs2_1pass_find_inode(struct b_lists * pL, const char *name, u32 pino)
counter = 0;
/* we need to search all and return the inode with the highest version */
for(b = pL->dirListHead;b;b=b->next,counter++) {
for(b = pL->dir.listHead; b; b = b->next, counter++) {
jDir = (struct jffs2_raw_dirent *) (b->offset);
if ((pino == jDir->pino) && (len == jDir->nsize) && (jDir->ino) && /* 0 for unlink */
if ((pino == jDir->pino) && (len == jDir->nsize) &&
(jDir->ino) && /* 0 for unlink */
(!strncmp(jDir->name, name, len))) { /* a match */
if (jDir->version < version) continue;
@ -477,12 +549,12 @@ jffs2_1pass_list_inodes(struct b_lists * pL, u32 pino)
struct b_node *b;
struct jffs2_raw_dirent *jDir;
for(b = pL->dirListHead;b;b=b->next) {
for (b = pL->dir.listHead; b; b = b->next) {
jDir = (struct jffs2_raw_dirent *) (b->offset);
if ((pino == jDir->pino) && (jDir->ino)) { /* 0 inode for unlink */
if ((pino == jDir->pino) && (jDir->ino)) { /* ino=0 -> unlink */
u32 i_version = 0;
struct jffs2_raw_inode *jNode, *i = NULL;
struct b_node *b2 = pL->fragListHead;
struct b_node *b2 = pL->frag.listHead;
while (b2) {
jNode = (struct jffs2_raw_inode *) (b2->offset);
@ -568,7 +640,7 @@ jffs2_1pass_resolve_inode(struct b_lists * pL, u32 ino)
unsigned char *src;
/* we need to search all and return the inode with the highest version */
for(b = pL->dirListHead; b; b=b->next) {
for(b = pL->dir.listHead; b; b = b->next) {
jDir = (struct jffs2_raw_dirent *) (b->offset);
if (ino == jDir->ino) {
if(jDir->version < version) continue;
@ -593,8 +665,9 @@ jffs2_1pass_resolve_inode(struct b_lists * pL, u32 ino)
/* now we found the right entry again. (shoulda returned inode*) */
if (jDirFound->type != DT_LNK)
return jDirFound->ino;
/* so its a soft link so we follow it again. */
b2 = pL->fragListHead;
/* it's a soft link so we follow it again. */
b2 = pL->frag.listHead;
while (b2) {
jNode = (struct jffs2_raw_inode *) (b2->offset);
if (jNode->ino == jDirFound->ino) {
@ -644,7 +717,8 @@ jffs2_1pass_search_list_inodes(struct b_lists * pL, const char *fname, u32 pino)
tmp[i] = c[i + 1];
tmp[i] = '\0';
/* only a failure if we arent looking at top level */
if (!(pino = jffs2_1pass_find_inode(pL, working_tmp, pino)) && (working_tmp[0])) {
if (!(pino = jffs2_1pass_find_inode(pL, working_tmp, pino)) &&
(working_tmp[0])) {
putstr("find_inode failed for name=");
putstr(working_tmp);
putstr("\r\n");
@ -681,7 +755,7 @@ jffs2_1pass_rescan_needed(struct part_info *part)
return 1;
}
/* if we have no list, we need to rescan */
if (pL->fragListCount == 0) {
if (pL->frag.listCount == 0) {
DEBUGF ("rescan: fraglist zero\n");
return 1;
}
@ -691,12 +765,13 @@ jffs2_1pass_rescan_needed(struct part_info *part)
DEBUGF ("rescan: different partition\n");
return 1;
}
/* but suppose someone reflashed the root partition at the same offset... */
b = pL->dirListHead;
/* but suppose someone reflashed a partition at the same offset... */
b = pL->dir.listHead;
while (b) {
node = (struct jffs2_unknown_node *) (b->offset);
if (node->nodetype != JFFS2_NODETYPE_DIRENT) {
DEBUGF ("rescan: fs changed beneath me? (%lx)\n", (unsigned long) b->offset);
DEBUGF ("rescan: fs changed beneath me? (%lx)\n",
(unsigned long) b->offset);
return 1;
}
b = b->next;
@ -704,120 +779,44 @@ jffs2_1pass_rescan_needed(struct part_info *part)
return 0;
}
static u32
jffs2_1pass_build_lists(struct part_info * part)
{
struct b_lists *pL;
struct jffs2_unknown_node *node;
u32 offset;
u32 max = part->size - sizeof(struct jffs2_raw_inode);
u32 counter = 0;
u32 counter4 = 0;
u32 counterF = 0;
u32 counterN = 0;
/* turn off the lcd. Refreshing the lcd adds 50% overhead to the */
/* jffs2 list building enterprise nope. in newer versions the overhead is */
/* only about 5 %. not enough to inconvenience people for. */
/* lcd_off(); */
/* if we are building a list we need to refresh the cache. */
/* note that since we don't free our memory, eventually this will be bad. */
/* but we're a bootldr so what the hell. */
jffs_init_1pass_list(part);
pL=(struct b_lists *)part->jffs2_priv;
pL->partOffset = part->offset;
offset = 0;
printf("Scanning JFFS2 FS: ");
/* start at the beginning of the partition */
while (offset < max) {
if (! (++counter%10000))
printf("\b\b%c ", spinner[(counter / 10000) % 4]);
node = (struct jffs2_unknown_node *) (part->offset + offset);
if (node->magic == JFFS2_MAGIC_BITMASK && hdr_crc(node)) {
/* if its a fragment add it */
if (node->nodetype == JFFS2_NODETYPE_INODE && inode_crc((struct jffs2_raw_inode *) node)) {
if (!(pL->fragListTail = add_node(pL->fragListTail, &(pL->fragListCount),
&(pL->fragListMemBase)))) {
putstr("add_node failed!\r\n");
return 0;
}
pL->fragListTail->offset = (u32) (part->offset + offset);
if (!pL->fragListHead)
pL->fragListHead = pL->fragListTail;
} else if (node->nodetype == JFFS2_NODETYPE_DIRENT &&
dirent_crc((struct jffs2_raw_dirent *) node) &&
dirent_name_crc((struct jffs2_raw_dirent *) node)) {
if (! (counterN%100))
printf("\b\b. ");
#if 0
printf("Found DIRENT @ 0x%lx\n", offset);
putstr("\r\nbuild_lists:p&l ->");
putnstr(((struct jffs2_raw_dirent *) node)->name, ((struct jffs2_raw_dirent *) node)->nsize);
putstr("\r\n");
putLabeledWord("\tpino = ", ((struct jffs2_raw_dirent *) node)->pino);
putLabeledWord("\tnsize = ", ((struct jffs2_raw_dirent *) node)->nsize);
#endif
if (!(pL->dirListTail = add_node(pL->dirListTail, &(pL->dirListCount), &(pL->dirListMemBase)))) {
putstr("add_node failed!\r\n");
return 0;
}
pL->dirListTail->offset = (u32) (part->offset + offset);
#if 0
putLabeledWord("\ttail = ", (u32) pL->dirListTail);
putstr("\ttailName ->");
putnstr(((struct jffs2_raw_dirent *) (pL->dirListTail->offset))->name,
((struct jffs2_raw_dirent *) (pL->dirListTail->offset))->nsize);
putstr("\r\n");
#endif
if (!pL->dirListHead)
pL->dirListHead = pL->dirListTail;
counterN++;
} else if (node->nodetype == JFFS2_NODETYPE_CLEANMARKER) {
if (node->totlen != sizeof(struct jffs2_unknown_node))
printf("OOPS Cleanmarker has bad size %d != %d\n", node->totlen, sizeof(struct jffs2_unknown_node));
} else {
printf("Unknown node type: %x len %d offset 0x%x\n", node->nodetype, node->totlen, offset);
}
offset += ((node->totlen + 3) & ~3);
counterF++;
} else if (node->magic == JFFS2_EMPTY_BITMASK && node->nodetype == JFFS2_EMPTY_BITMASK) {
offset = jffs2_scan_empty(offset, part);
} else { /* if we know nothing of the filesystem, we just step and look. */
offset += 4;
counter4++;
}
/* printf("unknown node magic %4.4x %4.4x @ %lx\n", node->magic, node->nodetype, (unsigned long)node); */
}
putstr("\b\b done.\r\n"); /* close off the dots */
/* turn the lcd back on. */
/* splash(); */
#if 0
putLabeledWord("dir entries = ", pL->dirListCount);
putLabeledWord("frag entries = ", pL->fragListCount);
putLabeledWord("+4 increments = ", counter4);
putLabeledWord("+file_offset increments = ", counterF);
#endif
#undef SHOW_ALL
#undef SHOW_ALL_FRAGMENTS
#ifdef SHOW_ALL
#ifdef DEBUG_FRAGMENTS
static void
dump_fragments(struct b_lists *pL)
{
struct b_node *b;
struct b_node *b2;
struct jffs2_raw_dirent *jDir;
struct jffs2_raw_inode *jNode;
putstr("\r\n\r\n******The fragment Entries******\r\n");
b = pL->frag.listHead;
while (b) {
jNode = (struct jffs2_raw_inode *) (b->offset);
putLabeledWord("\r\n\tbuild_list: FLASH_OFFSET = ", b->offset);
putLabeledWord("\tbuild_list: totlen = ", jNode->totlen);
putLabeledWord("\tbuild_list: inode = ", jNode->ino);
putLabeledWord("\tbuild_list: version = ", jNode->version);
putLabeledWord("\tbuild_list: isize = ", jNode->isize);
putLabeledWord("\tbuild_list: atime = ", jNode->atime);
putLabeledWord("\tbuild_list: offset = ", jNode->offset);
putLabeledWord("\tbuild_list: csize = ", jNode->csize);
putLabeledWord("\tbuild_list: dsize = ", jNode->dsize);
putLabeledWord("\tbuild_list: compr = ", jNode->compr);
putLabeledWord("\tbuild_list: usercompr = ", jNode->usercompr);
putLabeledWord("\tbuild_list: flags = ", jNode->flags);
putLabeledWord("\tbuild_list: offset = ", b->offset); // FIXME: ? [RS]
b = b->next;
}
}
#endif
#ifdef DEBUG_DIRENTS
static void
dump_dirents(struct b_lists *pL)
{
struct b_node *b;
struct jffs2_raw_dirent *jDir;
putstr("\r\n\r\n******The directory Entries******\r\n");
b = pL->dirListHead;
b = pL->dir.listHead;
while (b) {
jDir = (struct jffs2_raw_dirent *) (b->offset);
putstr("\r\n");
@ -833,32 +832,103 @@ jffs2_1pass_build_lists(struct part_info * part)
putLabeledWord("\tbuild_list: type = ", jDir->type);
putLabeledWord("\tbuild_list: node_crc = ", jDir->node_crc);
putLabeledWord("\tbuild_list: name_crc = ", jDir->name_crc);
putLabeledWord("\tbuild_list: offset = ", b->offset); // FIXME: ? [RS]
b = b->next;
}
#ifdef SHOW_ALL_FRAGMENTS
putstr("\r\n\r\n******The fragment Entries******\r\n");
b = pL->fragListHead;
while (b) {
jNode = (struct jffs2_raw_inode *) (b->offset);
putLabeledWord("\r\n\tbuild_list: FLASH_OFFSET = ", b->offset);
putLabeledWord("\tbuild_list: totlen = ", jNode->totlen);
putLabeledWord("\tbuild_list: inode = ", jNode->ino);
putLabeledWord("\tbuild_list: version = ", jNode->version);
putLabeledWord("\tbuild_list: isize = ", jNode->isize);
putLabeledWord("\tbuild_list: atime = ", jNode->atime);
putLabeledWord("\tbuild_list: offset = ", jNode->offset);
putLabeledWord("\tbuild_list: csize = ", jNode->csize);
putLabeledWord("\tbuild_list: dsize = ", jNode->dsize);
putLabeledWord("\tbuild_list: compr = ", jNode->compr);
putLabeledWord("\tbuild_list: usercompr = ", jNode->usercompr);
putLabeledWord("\tbuild_list: flags = ", jNode->flags);
b = b->next;
}
#endif /* SHOW_ALL_FRAGMENTS */
#endif
static u32
jffs2_1pass_build_lists(struct part_info * part)
{
struct b_lists *pL;
struct jffs2_unknown_node *node;
u32 offset, oldoffset = 0;
u32 max = part->size - sizeof(struct jffs2_raw_inode);
u32 counter = 0;
u32 counter4 = 0;
u32 counterF = 0;
u32 counterN = 0;
/* turn off the lcd. Refreshing the lcd adds 50% overhead to the */
/* jffs2 list building enterprise nope. in newer versions the overhead is */
/* only about 5 %. not enough to inconvenience people for. */
/* lcd_off(); */
/* if we are building a list we need to refresh the cache. */
jffs_init_1pass_list(part);
pL = (struct b_lists *)part->jffs2_priv;
pL->partOffset = part->offset;
offset = 0;
printf("Scanning JFFS2 FS: ");
/* start at the beginning of the partition */
while (offset < max) {
if ((oldoffset >> SPIN_BLKSIZE) != (offset >> SPIN_BLKSIZE)) {
printf("\b\b%c ", spinner[counter++ % sizeof(spinner)]);
oldoffset = offset;
}
#endif /* SHOW_ALL */
node = (struct jffs2_unknown_node *) (part->offset + offset);
if (node->magic == JFFS2_MAGIC_BITMASK && hdr_crc(node)) {
/* if its a fragment add it */
if (node->nodetype == JFFS2_NODETYPE_INODE &&
inode_crc((struct jffs2_raw_inode *) node)) {
if (insert_node(&pL->frag, (u32) part->offset +
offset) == NULL)
return 0;
} else if (node->nodetype == JFFS2_NODETYPE_DIRENT &&
dirent_crc((struct jffs2_raw_dirent *) node) &&
dirent_name_crc((struct jffs2_raw_dirent *) node)) {
if (! (counterN%100))
printf("\b\b. ");
if (insert_node(&pL->dir, (u32) part->offset +
offset) == NULL)
return 0;
counterN++;
} else if (node->nodetype == JFFS2_NODETYPE_CLEANMARKER) {
if (node->totlen != sizeof(struct jffs2_unknown_node))
printf("OOPS Cleanmarker has bad size "
"%d != %d\n", node->totlen,
sizeof(struct jffs2_unknown_node));
} else {
printf("Unknown node type: %x len %d "
"offset 0x%x\n", node->nodetype,
node->totlen, offset);
}
offset += ((node->totlen + 3) & ~3);
counterF++;
} else if (node->magic == JFFS2_EMPTY_BITMASK &&
node->nodetype == JFFS2_EMPTY_BITMASK) {
offset = jffs2_scan_empty(offset, part);
} else { /* if we know nothing, we just step and look. */
offset += 4;
counter4++;
}
/* printf("unknown node magic %4.4x %4.4x @ %lx\n", node->magic, node->nodetype, (unsigned long)node); */
}
putstr("\b\b done.\r\n"); /* close off the dots */
/* turn the lcd back on. */
/* splash(); */
#if 0
putLabeledWord("dir entries = ", pL->dir.listCount);
putLabeledWord("frag entries = ", pL->frag.listCount);
putLabeledWord("+4 increments = ", counter4);
putLabeledWord("+file_offset increments = ", counterF);
#endif
#ifdef DEBUG_DIRENTS
dump_dirents(pL);
#endif
#ifdef DEBUG_FRAGMENTS
dump_fragments(pL);
#endif
/* give visual feedback that we are done scanning the flash */
led_blink(0x0, 0x0, 0x1, 0x1); /* off, forever, on 100ms, off 100ms */
return 1;
@ -875,13 +945,13 @@ jffs2_1pass_fill_info(struct b_lists * pL, struct b_jffs2_info * piL)
struct jffs2_raw_inode *jNode;
int i;
b = pL->fragListHead;
for (i = 0; i < JFFS2_NUM_COMPR; i++) {
piL->compr_info[i].num_frags = 0;
piL->compr_info[i].compr_sum = 0;
piL->compr_info[i].decompr_sum = 0;
}
b = pL->frag.listHead;
while (b) {
jNode = (struct jffs2_raw_inode *) (b->offset);
if (jNode->compr < JFFS2_NUM_COMPR) {

View File

@ -3,23 +3,31 @@
#include <jffs2/jffs2.h>
struct b_node {
u32 offset;
struct b_node *next;
};
struct b_list {
struct b_node *listTail;
struct b_node *listHead;
#ifdef CFG_JFFS2_SORT_FRAGMENTS
struct b_node *listLast;
int (*listCompare)(struct b_node *new, struct b_node *node);
u32 listLoops;
#endif
u32 listCount;
struct mem_block *listMemBase;
};
struct b_lists {
char *partOffset;
struct b_node *dirListTail;
struct b_node *dirListHead;
u32 dirListCount;
u32 dirListMemBase;
struct b_node *fragListTail;
struct b_node *fragListHead;
u32 fragListCount;
u32 fragListMemBase;
struct b_list dir;
struct b_list frag;
};
struct b_compr_info {
u32 num_frags;
u32 compr_sum;
@ -33,11 +41,14 @@ struct b_jffs2_info {
static inline int
hdr_crc(struct jffs2_unknown_node *node)
{
#if 1
u32 crc = crc32_no_comp(0, (unsigned char *)node, sizeof(struct jffs2_unknown_node) - 4);
u32 crc_blah = crc32_no_comp(~0, (unsigned char *)node, sizeof(struct jffs2_unknown_node) - 4);
crc_blah ^= ~0;
#else
/* what's the semantics of this? why is this here? */
u32 crc = crc32_no_comp(~0, (unsigned char *)node, sizeof(struct jffs2_unknown_node) - 4);
crc ^= ~0;
#endif
if (node->hdr_crc != crc) {
return 0;
} else {

View File

@ -44,7 +44,6 @@ typedef struct global_data {
#ifdef CONFIG_VFD
unsigned long fb_base; /* base address of frame buffer */
unsigned char vfd_type; /* display type */
unsigned char vfd_inv_data; /* inverted data lines ? */
#endif
#if 0
unsigned long cpu_clk; /* CPU clock in Hz! */

View File

@ -71,22 +71,37 @@ extern void __raw_readsl(unsigned int addr, void *data, int longlen);
#include <asm/arch/io.h>
/*
* IO definitions. We define {out,in,outs,ins}[bwl] if __io is defined
* by the machine. Otherwise, these definitions are left for the machine
* specific header files to pick up.
* IO port access primitives
* -------------------------
*
* The ARM doesn't have special IO access instructions; all IO is memory
* mapped. Note that these are defined to perform little endian accesses
* only. Their primary purpose is to access PCI and ISA peripherals.
*
* Note that for a big endian machine, this implies that the following
* big endian mode connectivity is in place, as described by numerious
* ARM documents:
*
* PCI: D0-D7 D8-D15 D16-D23 D24-D31
* ARM: D24-D31 D16-D23 D8-D15 D0-D7
*
* The machine specific io.h include defines __io to translate an "IO"
* address to a memory address.
*
* Note that we prevent GCC re-ordering or caching values in expressions
* by introducing sequence points into the in*() definitions. Note that
* __raw_* do not guarantee this behaviour.
*
* The {in,out}[bwl] macros are for emulating x86-style PCI/ISA IO space.
*/
#ifdef __io
#define outb(v,p) __raw_writeb(v,__io(p))
#define outw(v,p) __raw_writew(v,__io(p))
#define outl(v,p) __raw_writel(v,__io(p))
#define outw(v,p) __raw_writew(cpu_to_le16(v),__io(p))
#define outl(v,p) __raw_writel(cpu_to_le32(v),__io(p))
#define inb(p) ({ unsigned int __v = __raw_readb(__io(p)); __v; })
#define inw(p) ({ unsigned int __v = __raw_readw(__io(p)); __v; })
#define inl(p) ({ unsigned int __v = __raw_readl(__io(p)); __v; })
#define inw(p) ({ unsigned int __v = le16_to_cpu(__raw_readw(__io(p))); __v; })
#define inl(p) ({ unsigned int __v = le32_to_cpu(__raw_readl(__io(p))); __v; })
#define outsb(p,d,l) __raw_writesb(__io(p),d,l)
#define outsw(p,d,l) __raw_writesw(__io(p),d,l)
@ -171,20 +186,20 @@ extern void __readwrite_bug(const char *fn);
*/
#ifdef __mem_pci
#define readb(addr) ({ unsigned int __v = __raw_readb(__mem_pci(addr)); __v; })
#define readw(addr) ({ unsigned int __v = __raw_readw(__mem_pci(addr)); __v; })
#define readl(addr) ({ unsigned int __v = __raw_readl(__mem_pci(addr)); __v; })
#define readb(c) ({ unsigned int __v = __raw_readb(__mem_pci(c)); __v; })
#define readw(c) ({ unsigned int __v = le16_to_cpu(__raw_readw(__mem_pci(c))); __v; })
#define readl(c) ({ unsigned int __v = le32_to_cpu(__raw_readl(__mem_pci(c))); __v; })
#define writeb(val,addr) __raw_writeb(val,__mem_pci(addr))
#define writew(val,addr) __raw_writew(val,__mem_pci(addr))
#define writel(val,addr) __raw_writel(val,__mem_pci(addr))
#define writeb(v,c) __raw_writeb(v,__mem_pci(c))
#define writew(v,c) __raw_writew(cpu_to_le16(v),__mem_pci(c))
#define writel(v,c) __raw_writel(cpu_to_le32(v),__mem_pci(c))
#define memset_io(a,b,c) _memset_io(__mem_pci(a),(b),(c))
#define memcpy_fromio(a,b,c) _memcpy_fromio((a),__mem_pci(b),(c))
#define memcpy_toio(a,b,c) _memcpy_toio(__mem_pci(a),(b),(c))
#define memset_io(c,v,l) _memset_io(__mem_pci(c),(v),(l))
#define memcpy_fromio(a,c,l) _memcpy_fromio((a),__mem_pci(c),(l))
#define memcpy_toio(c,a,l) _memcpy_toio(__mem_pci(c),(a),(l))
#define eth_io_copy_and_sum(a,b,c,d) \
eth_copy_and_sum((a),__mem_pci(b),(c),(d))
#define eth_io_copy_and_sum(s,c,l,b) \
eth_copy_and_sum((s),__mem_pci(c),(l),(b))
static inline int
check_signature(unsigned long io_addr, const unsigned char *signature,
@ -218,14 +233,6 @@ out:
#endif /* __mem_pci */
/*
* remap a physical address `phys' of size `size' with page protection `prot'
* into virtual address `from'
*/
#define io_remap_page_range(from,phys,size,prot) \
remap_page_range(from,phys,size,prot)
/*
* If this architecture has ISA IO, then define the isa_read/isa_write
* macros.
@ -245,6 +252,10 @@ out:
#define isa_eth_io_copy_and_sum(a,b,c,d) \
eth_copy_and_sum((a),__mem_isa(b),(c),(d))
#ifndef PCI_MEMORY_VADDR /* XXX problem not understood -- wd */
#define PCI_MEMORY_VADDR 0
#endif /* XXX */
static inline int
isa_check_signature(unsigned long io_addr, const unsigned char *signature,
int length)

View File

@ -60,9 +60,9 @@
#define CONFIG_ENV_OVERWRITE
#define CONFIG_BAUDRATE 19200
#define CONFIG_MISC_INIT_R 1 /* we have a misc_init_r() function */
#define CONFIG_COMMANDS ((CONFIG_CMD_DFL | CFG_CMD_I2C | CFG_CMD_EEPROM) & ~CFG_CMD_NET)
#define CONFIG_COMMANDS (CONFIG_CMD_DFL|CFG_CMD_I2C|CFG_CMD_EEPROM|CFG_CMD_NET|CFG_CMD_JFFS2|CFG_CMD_DHCP)
/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include <cmd_confdefs.h>
@ -90,13 +90,13 @@
/*
* Size of malloc() pool; this lives below the uppermost 128 KiB which are
* used for the RAM copy of the uboot code
*
*/
/* #define CFG_MALLOC_LEN (CFG_ENV_SIZE + 128*1024) */
#define CFG_MALLOC_LEN (128*1024)
#define CFG_MALLOC_LEN (256*1024)
#define CFG_LONGHELP /* undef to save memory */
#define CFG_PROMPT "uboot> " /* Monitor Command Prompt */
#define CFG_CBSIZE 128 /* Console I/O Buffer Size */
#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
#define CFG_MAXARGS 16 /* max number of command args */
#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */
@ -106,10 +106,7 @@
#undef CFG_CLKS_IN_HZ /* everything, incl board info, in Hz */
#define CFG_LOAD_ADDR 0xa7fe0000 /* default load address */
/* RS: where is this documented? */
/* RS: is this where U-Boot is */
/* RS: relocated to in RAM? */
#define CFG_LOAD_ADDR 0xa3000000 /* load kernel to this address */
#define CFG_HZ 3686400 /* incrementer freq: 3.6864 MHz */
/* RS: the oscillator is actually 3680130?? */
@ -138,9 +135,20 @@
#define CFG_ENV_SIZE 1024 /* 1 KiB */
#define CFG_I2C_EEPROM_ADDR 0x50 /* A0 = 0 (hardwired) */
#define CFG_EEPROM_PAGE_WRITE_BITS 5 /* 5 bits = 32 octets */
#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10 /* between stop and start */
#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 15 /* between stop and start */
#define CFG_I2C_EEPROM_ADDR_LEN 2 /* length of address */
#define CFG_EEPROM_SIZE 4096 /* size in bytes */
#define CFG_I2C_INIT_BOARD 1 /* board has it's own init */
/*
* SMSC91C111 Network Card
*/
#define CONFIG_DRIVER_SMC91111 1
#define CONFIG_SMC91111_BASE 0x14000000 /* chip select 5 */
#undef CONFIG_SMC_USE_32_BIT /* 16 bit bus access */
#undef CONFIG_SMC_91111_EXT_PHY /* we use internal phy */
#undef CONFIG_SHOW_ACTIVITY
#define CONFIG_NET_RETRY_COUNT 10 /* # of retries */
/*
* Stack sizes
@ -168,11 +176,19 @@
#define CFG_FLASH_BASE PHYS_FLASH_1
/*
* GPIO settings;
*/
/* GP15 == nCS1 is 1
/*
* JFFS2 Partitions
*/
#define CFG_JFFS_CUSTOM_PART 1 /* see board/innokom/flash.c */
#define CONFIG_MTD_INNOKOM_16MB 1 /* development flash */
#undef CONFIG_MTD_INNOKOM_64MB /* production flash */
/*
* GPIO settings; see BDI2000 config file for details
*
* GP15 == nCS1 is 1
* GP24 == SFRM is 1
* GP25 == TXD is 1
* GP33 == nCS5 is 1
@ -273,6 +289,7 @@
#define CFG_GAFR2_L_VAL 0xA0000000
#define CFG_GAFR2_U_VAL 0x00000002
/* FIXME: set GPIO_RER/FER */
/* RDH = 1
@ -285,9 +302,8 @@
/*
* Memory settings
*/
/* This is the configuration for nCS0/1 -> flash banks
*
* This is the configuration for nCS0/1 -> flash banks
* configuration for nCS1:
* [31] 0 - Slower Device
* [30:28] 010 - CS deselect to CS time: 2*(2*MemClk) = 40 ns
@ -321,7 +337,7 @@
* [03] 1 - 16 Bit bus width
* [02:00] 100 - variable latency I/O
*/
#define CFG_MSC1_VAL 0x132C593C /* TDM switch, DSP */
#define CFG_MSC1_VAL 0x123C593C /* TDM switch, DSP */
/* This is the configuration for nCS4/5 -> ExtBus, LAN Controller
*
@ -340,7 +356,7 @@
* [03] 1 - 16 Bit bus width
* [02:00] 100 - variable latency I/O
*/
#define CFG_MSC2_VAL 0x132C6CDC /* extra bus, LAN controller */
#define CFG_MSC2_VAL 0x123C6CDC /* extra bus, LAN controller */
/* MDCNFG: SDRAM Configuration Register
*
@ -359,16 +375,15 @@
* [12] 1 - SA1111 compatiblity mode
* [11] 1 - latch return data with return clock
* [10] 0 - no alternate addressing for pair 0/1
* [09:08] 01 - tRP=2*MemClk; CL=2; tRCD=2*MemClk; tRAS=5*MemClk; tRC=8*MemClk
* [09:08] 01 - tRP=2*MemClk CL=2 tRCD=2*MemClk tRAS=5*MemClk tRC=8*MemClk
* [7] 1 - 4 internal banks in lower partition pair
* [06:05] 10 - 13 row address bits for partition 0/1
* [04:03] 01 - 9 column address bits for partition 0/1
* [02] 0 - SDRAM partition 0/1 width is 32 bit
* [01] 0 - disable SDRAM partition 1
* [00] 1 - enable SDRAM partition 0
*
* use the configuration above but disable partition 0
*/
/* use the configuration above but disable partition 0 */
#define CFG_MDCNFG_VAL 0x000019c8
/* MDREFR: SDRAM Refresh Control Register
@ -434,11 +449,4 @@
#define CFG_FLASH_ERASE_TOUT (2*CFG_HZ) /* Timeout for Flash Erase */
#define CFG_FLASH_WRITE_TOUT (2*CFG_HZ) /* Timeout for Flash Write */
#if 0
#define CFG_ENV_IS_IN_FLASH 1
#define CFG_ENV_ADDR (PHYS_FLASH_1 + 0x1C000)
/* Addr of Environment Sector */
#define CFG_ENV_SIZE 0x4000 /* Total Size of Environment Sector */
#endif
#endif /* __CONFIG_H */

View File

@ -51,6 +51,9 @@
* repeatedly to change the speed and slave addresses.
*/
void i2c_init(int speed, int slaveaddr);
#ifdef CFG_I2C_INIT_BOARD
void i2c_init_board(void);
#endif
/*
* Probe the given I2C chip address. Returns 0 if a chip responded,