aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/cmd_ace.c31
-rw-r--r--common/cmd_bdinfo.c14
-rw-r--r--common/cmd_bootm.c4
-rw-r--r--common/cmd_dcr.c2
-rw-r--r--common/cmd_elf.c4
-rw-r--r--common/cmd_flash.c201
-rw-r--r--common/cmd_fpga.c97
-rw-r--r--common/cmd_jffs2.c2012
-rw-r--r--common/cmd_mii.c2
-rw-r--r--common/cmd_scsi.c19
-rw-r--r--common/cmd_usb.c36
-rw-r--r--common/environment.c5
-rw-r--r--common/hush.c18
-rw-r--r--common/lcd.c33
-rw-r--r--common/lynxkdi.c2
-rw-r--r--common/miiphybb.c328
-rw-r--r--common/miiphyutil.c8
-rw-r--r--common/usb.c271
-rw-r--r--common/usb_storage.c134
19 files changed, 2757 insertions, 464 deletions
diff --git a/common/cmd_ace.c b/common/cmd_ace.c
index c5b08bf772..fb4d3584b5 100644
--- a/common/cmd_ace.c
+++ b/common/cmd_ace.c
@@ -31,6 +31,12 @@
* available to cmd_fat.c:get_dev and filling in a block device
* description that has all the bits needed for FAT support to
* read sectors.
+ *
+ * According to Xilinx technical support, before accessing the
+ * SystemACE CF you need to set the following control bits:
+ * FORCECFGMODE : 1
+ * CFGMODE : 0
+ * CFGSTART : 0
*/
# include <common.h>
@@ -95,7 +101,9 @@ static int get_cf_lock(void)
int retry = 10;
/* CONTROLREG = LOCKREG */
- ace_writew(0x0002, 0x18);
+ unsigned val=ace_readw(0x18);
+ val|=0x0002;
+ ace_writew((val&0xffff), 0x18);
/* Wait for MPULOCK in STATUSREG[15:0] */
while (! (ace_readw(0x04) & 0x0002)) {
@@ -112,8 +120,9 @@ static int get_cf_lock(void)
static void release_cf_lock(void)
{
- /* CONTROLREG = none */
- ace_writew(0x0000, 0x18);
+ unsigned val=ace_readw(0x18);
+ val&=~(0x0002);
+ ace_writew((val&0xffff), 0x18);
}
block_dev_desc_t * systemace_get_dev(int dev)
@@ -127,6 +136,9 @@ block_dev_desc_t * systemace_get_dev(int dev)
systemace_dev.blksz = 512;
systemace_dev.removable = 1;
systemace_dev.block_read = systemace_read;
+
+ init_part(&systemace_dev);
+
}
return &systemace_dev;
@@ -145,6 +157,7 @@ static unsigned long systemace_read(int dev,
int retry;
unsigned blk_countdown;
unsigned char*dp = (unsigned char*)buffer;
+ unsigned val;
if (get_cf_lock() < 0) {
unsigned status = ace_readw(0x04);
@@ -165,7 +178,7 @@ static unsigned long systemace_read(int dev,
retry = 2000;
for (;;) {
- unsigned val = ace_readw(0x04);
+ val = ace_readw(0x04);
/* If CFDETECT is false, card is missing. */
if (! (val & 0x0010)) {
@@ -212,6 +225,11 @@ static unsigned long systemace_read(int dev,
/* Write sector count | ReadMemCardData. */
ace_writew((trans&0xff) | 0x0300, 0x14);
+ /* Reset the configruation controller */
+ val = ace_readw(0x18);
+ val|=0x0080;
+ ace_writew(val, 0x18);
+
retry = trans * 16;
while (retry > 0) {
int idx;
@@ -231,6 +249,11 @@ static unsigned long systemace_read(int dev,
retry -= 1;
}
+ /* Clear the configruation controller reset */
+ val = ace_readw(0x18);
+ val&=~0x0080;
+ ace_writew(val, 0x18);
+
/* Count the blocks we transfer this time. */
start += trans;
blk_countdown -= trans;
diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
index ca834732b8..40e28dd9d2 100644
--- a/common/cmd_bdinfo.c
+++ b/common/cmd_bdinfo.c
@@ -61,24 +61,26 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
#endif
print_num ("bootflags", bd->bi_bootflags );
#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
- defined(CONFIG_405EP) || defined(CONFIG_XILINX_ML300)
+ defined(CONFIG_405EP) || defined(CONFIG_XILINX_ML300) || \
+ defined(CONFIG_440EP) || defined(CONFIG_440GR)
print_str ("procfreq", strmhz(buf, bd->bi_procfreq));
print_str ("plb_busfreq", strmhz(buf, bd->bi_plb_busfreq));
-#if defined(CONFIG_405GP) || defined(CONFIG_405EP) || defined(CONFIG_XILINX_ML300)
+#if defined(CONFIG_405GP) || defined(CONFIG_405EP) || defined(CONFIG_XILINX_ML300) || \
+ defined(CONFIG_440EP) || defined(CONFIG_440GR)
print_str ("pci_busfreq", strmhz(buf, bd->bi_pci_busfreq));
#endif
-#else /* ! CONFIG_405GP, CONFIG_405CR, CONFIG_405EP, CONFIG_XILINX_ML300 */
-#if defined(CONFIG_8260) || defined(CONFIG_MPC8560)
+#else /* ! CONFIG_405GP, CONFIG_405CR, CONFIG_405EP, CONFIG_XILINX_ML300, CONFIG_440EP CONFIG_440GR */
+#if defined(CONFIG_CPM2)
print_str ("vco", strmhz(buf, bd->bi_vco));
print_str ("sccfreq", strmhz(buf, bd->bi_sccfreq));
print_str ("brgfreq", strmhz(buf, bd->bi_brgfreq));
#endif
print_str ("intfreq", strmhz(buf, bd->bi_intfreq));
-#if defined(CONFIG_8260) || defined(CONFIG_MPC8560)
+#if defined(CONFIG_CPM2)
print_str ("cpmfreq", strmhz(buf, bd->bi_cpmfreq));
#endif
print_str ("busfreq", strmhz(buf, bd->bi_busfreq));
-#endif /* CONFIG_405GP, CONFIG_405CR, CONFIG_405EP, CONFIG_XILINX_ML300 */
+#endif /* CONFIG_405GP, CONFIG_405CR, CONFIG_405EP, CONFIG_XILINX_ML300, CONFIG_440EP CONFIG_440GR */
#if defined(CONFIG_MPC8220)
print_str ("inpfreq", strmhz(buf, bd->bi_inpfreq));
print_str ("flbfreq", strmhz(buf, bd->bi_flbfreq));
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index a90735f3f2..c200fd8b86 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -580,12 +580,12 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
kbd->bi_flbfreq /= 1000000L;
kbd->bi_vcofreq /= 1000000L;
#endif
-#if defined(CONFIG_8260) || defined(CONFIG_MPC8560)
+#if defined(CONFIG_CPM2)
kbd->bi_cpmfreq /= 1000000L;
kbd->bi_brgfreq /= 1000000L;
kbd->bi_sccfreq /= 1000000L;
kbd->bi_vco /= 1000000L;
-#endif /* CONFIG_8260 */
+#endif
#if defined(CONFIG_MPC5xxx)
kbd->bi_ipbfreq /= 1000000L;
kbd->bi_pcifreq /= 1000000L;
diff --git a/common/cmd_dcr.c b/common/cmd_dcr.c
index a91db66e02..3e4e08f95b 100644
--- a/common/cmd_dcr.c
+++ b/common/cmd_dcr.c
@@ -29,7 +29,7 @@
#include <config.h>
#include <command.h>
-#if defined(CONFIG_4xx) && defined(CFG_CMD_SETGETDCR)
+#if defined(CONFIG_4xx) && (CONFIG_COMMANDS & CFG_CMD_SETGETDCR)
/* ======================================================================
* Interpreter command to retrieve an IBM PPC 4xx Device Control Register
diff --git a/common/cmd_elf.c b/common/cmd_elf.c
index 37286e86a8..eccf2e9e7b 100644
--- a/common/cmd_elf.c
+++ b/common/cmd_elf.c
@@ -78,7 +78,7 @@ int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
* ====================================================================== */
int do_bootvx ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
-#if defined(CONFIG_WALNUT405) || \
+#if defined(CONFIG_WALNUT) || \
defined(CFG_VXWORKS_MAC_PTR)
DECLARE_GLOBAL_DATA_PTR;
#endif
@@ -121,7 +121,7 @@ int do_bootvx ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
* This will vary from board to board
*/
-#if defined(CONFIG_WALNUT405)
+#if defined(CONFIG_WALNUT)
tmp = (char *) CFG_NVRAM_BASE_ADDR + 0x500;
memcpy ((char *) tmp, (char *) &gd->bd->bi_enetaddr[3], 3);
#elif defined(CFG_VXWORKS_MAC_PTR)
diff --git a/common/cmd_flash.c b/common/cmd_flash.c
index b2728ab1d3..d5be30c54d 100644
--- a/common/cmd_flash.c
+++ b/common/cmd_flash.c
@@ -27,13 +27,22 @@
#include <common.h>
#include <command.h>
-
#ifdef CONFIG_HAS_DATAFLASH
#include <dataflash.h>
#endif
#if (CONFIG_COMMANDS & CFG_CMD_FLASH)
+#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
+#include <jffs2/jffs2.h>
+
+/* parition handling routines */
+int mtdparts_init(void);
+int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num);
+int find_dev_and_part(const char *id, struct mtd_device **dev,
+ u8 *part_num, struct part_info **part);
+#endif
+
extern flash_info_t flash_info[]; /* info for FLASH chips */
/*
@@ -96,6 +105,95 @@ abbrev_spec (char *str, flash_info_t ** pinfo, int *psf, int *psl)
return 1;
}
+/*
+ * This function computes the start and end addresses for both
+ * erase and protect commands. The range of the addresses on which
+ * either of the commands is to operate can be given in two forms:
+ * 1. <cmd> start end - operate on <'start', 'end')
+ * 2. <cmd> start +length - operate on <'start', start + length)
+ * If the second form is used and the end address doesn't fall on the
+ * sector boundary, than it will be adjusted to the next sector boundary.
+ * If it isn't in the flash, the function will fail (return -1).
+ * Input:
+ * arg1, arg2: address specification (i.e. both command arguments)
+ * Output:
+ * addr_first, addr_last: computed address range
+ * Return:
+ * 1: success
+ * -1: failure (bad format, bad address).
+*/
+static int
+addr_spec(char *arg1, char *arg2, ulong *addr_first, ulong *addr_last)
+{
+ char len_used = 0; /* indicates if the "start +length" form used */
+ char *ep;
+
+ *addr_first = simple_strtoul(arg1, &ep, 16);
+ if (ep == arg1 || *ep != '\0')
+ return -1;
+
+ if (arg2 && *arg2 == '+'){
+ len_used = 1;
+ ++arg2;
+ }
+
+ *addr_last = simple_strtoul(arg2, &ep, 16);
+ if (ep == arg2 || *ep != '\0')
+ return -1;
+
+ if (len_used){
+ char found = 0;
+ ulong bank;
+
+ /*
+ * *addr_last has the length, compute correct *addr_last
+ * XXX watch out for the integer overflow! Right now it is
+ * checked for in both the callers.
+ */
+ *addr_last = *addr_first + *addr_last - 1;
+
+ /*
+ * It may happen that *addr_last doesn't fall on the sector
+ * boundary. We want to round such an address to the next
+ * sector boundary, so that the commands don't fail later on.
+ */
+
+ /* find the end addr of the sector where the *addr_last is */
+ for (bank = 0; bank < CFG_MAX_FLASH_BANKS && !found; ++bank){
+ int i;
+ flash_info_t *info = &flash_info[bank];
+ for (i = 0; i < info->sector_count && !found; ++i){
+ /* get the end address of the sector */
+ ulong sector_end_addr;
+ if (i == info->sector_count - 1){
+ sector_end_addr =
+ info->start[0] + info->size - 1;
+ } else {
+ sector_end_addr =
+ info->start[i+1] - 1;
+ }
+ if (*addr_last <= sector_end_addr &&
+ *addr_last >= info->start[i]){
+ /* sector found */
+ found = 1;
+ /* adjust *addr_last if necessary */
+ if (*addr_last < sector_end_addr){
+ *addr_last = sector_end_addr;
+ }
+ }
+ } /* sector */
+ } /* bank */
+ if (!found){
+ /* error, addres not in flash */
+ printf("Error: end address (0x%08lx) not in flash!\n",
+ *addr_last);
+ return -1;
+ }
+ } /* "start +length" from used */
+
+ return 1;
+}
+
static int
flash_fill_sect_ranges (ulong addr_first, ulong addr_last,
int *s_first, int *s_last,
@@ -206,11 +304,17 @@ int do_flinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
flash_print_info (&flash_info[bank-1]);
return 0;
}
+
int do_flerase (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
flash_info_t *info;
ulong bank, addr_first, addr_last;
int n, sect_first, sect_last;
+#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
+ struct mtd_device *dev;
+ struct part_info *part;
+ u8 dev_type, dev_num, pnum;
+#endif
int rcode = 0;
if (argc < 2) {
@@ -238,6 +342,32 @@ int do_flerase (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
return rcode;
}
+#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
+ /* erase <part-id> - erase partition */
+ if ((argc == 2) && (id_parse(argv[1], NULL, &dev_type, &dev_num) == 0)) {
+ mtdparts_init();
+ if (find_dev_and_part(argv[1], &dev, &pnum, &part) == 0) {
+ if (dev->id->type == MTD_DEV_TYPE_NOR) {
+ bank = dev->id->num;
+ info = &flash_info[bank];
+ addr_first = part->offset + info->start[0];
+ addr_last = addr_first + part->size - 1;
+
+ printf ("Erase Flash Parition %s, "
+ "bank %d, 0x%08lx - 0x%08lx ",
+ argv[1], bank, addr_first,
+ addr_last);
+
+ rcode = flash_sect_erase(addr_first, addr_last);
+ return rcode;
+ }
+
+ printf("cannot erase, not a NOR device\n");
+ return 1;
+ }
+ }
+#endif
+
if (argc != 3) {
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
@@ -256,8 +386,10 @@ int do_flerase (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
return rcode;
}
- addr_first = simple_strtoul(argv[1], NULL, 16);
- addr_last = simple_strtoul(argv[2], NULL, 16);
+ if (addr_spec(argv[1], argv[2], &addr_first, &addr_last) < 0){
+ printf ("Bad address format\n");
+ return 1;
+ }
if (addr_first >= addr_last) {
printf ("Usage:\n%s\n", cmdtp->usage);
@@ -310,6 +442,11 @@ int do_protect (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
flash_info_t *info;
ulong bank, addr_first, addr_last;
int i, p, n, sect_first, sect_last;
+#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
+ struct mtd_device *dev;
+ struct part_info *part;
+ u8 dev_type, dev_num, pnum;
+#endif
int rcode = 0;
#ifdef CONFIG_HAS_DATAFLASH
int status;
@@ -398,6 +535,33 @@ int do_protect (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
return rcode;
}
+#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
+ /* protect on/off <part-id> */
+ if ((argc == 3) && (id_parse(argv[2], NULL, &dev_type, &dev_num) == 0)) {
+ mtdparts_init();
+ if (find_dev_and_part(argv[2], &dev, &pnum, &part) == 0) {
+ if (dev->id->type == MTD_DEV_TYPE_NOR) {
+ bank = dev->id->num;
+ info = &flash_info[bank];
+ addr_first = part->offset + info->start[0];
+ addr_last = addr_first + part->size - 1;
+
+ printf ("%sProtect Flash Parition %s, "
+ "bank %d, 0x%08lx - 0x%08lx\n",
+ p ? "" : "Un", argv[1],
+ bank, addr_first, addr_last);
+
+ rcode = flash_sect_protect (p, addr_first, addr_last);
+ return rcode;
+ }
+
+ printf("cannot %sprotect, not a NOR device\n",
+ p ? "" : "un");
+ return 1;
+ }
+ }
+#endif
+
if (argc != 4) {
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
@@ -435,8 +599,10 @@ int do_protect (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
return rcode;
}
- addr_first = simple_strtoul(argv[2], NULL, 16);
- addr_last = simple_strtoul(argv[3], NULL, 16);
+ if (addr_spec(argv[2], argv[3], &addr_first, &addr_last) < 0){
+ printf("Bad address format\n");
+ return 1;
+ }
if (addr_first >= addr_last) {
printf ("Usage:\n%s\n", cmdtp->usage);
@@ -498,6 +664,15 @@ int flash_sect_protect (int p, ulong addr_first, ulong addr_last)
/**************************************************/
+#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
+# define TMP_ERASE "erase <part-id>\n - erase partition\n"
+# define TMP_PROT_ON "protect on <part-id>\n - protect partition\n"
+# define TMP_PROT_OFF "protect off <part-id>\n - make partition writable\n"
+#else
+# define TMP_ERASE /* empty */
+# define TMP_PROT_ON /* empty */
+# define TMP_PROT_OFF /* empty */
+#endif
U_BOOT_CMD(
flinfo, 2, 1, do_flinfo,
@@ -511,8 +686,12 @@ U_BOOT_CMD(
"erase - erase FLASH memory\n",
"start end\n"
" - erase FLASH from addr 'start' to addr 'end'\n"
+ "erase start +len\n"
+ " - erase FLASH from addr 'start' to the end of sect "
+ "w/addr 'start'+'len'-1\n"
"erase N:SF[-SL]\n - erase sectors SF-SL in FLASH bank # N\n"
"erase bank N\n - erase FLASH bank # N\n"
+ TMP_ERASE
"erase all\n - erase all FLASH banks\n"
);
@@ -521,16 +700,28 @@ U_BOOT_CMD(
"protect - enable or disable FLASH write protection\n",
"on start end\n"
" - protect FLASH from addr 'start' to addr 'end'\n"
+ "protect on start +len\n"
+ " - protect FLASH from addr 'start' to end of sect "
+ "w/addr 'start'+'len'-1\n"
"protect on N:SF[-SL]\n"
" - protect sectors SF-SL in FLASH bank # N\n"
"protect on bank N\n - protect FLASH bank # N\n"
+ TMP_PROT_ON
"protect on all\n - protect all FLASH banks\n"
"protect off start end\n"
" - make FLASH from addr 'start' to addr 'end' writable\n"
+ "protect off start +len\n"
+ " - make FLASH from addr 'start' to end of sect "
+ "w/addr 'start'+'len'-1 wrtable\n"
"protect off N:SF[-SL]\n"
" - make sectors SF-SL writable in FLASH bank # N\n"
"protect off bank N\n - make FLASH bank # N writable\n"
+ TMP_PROT_OFF
"protect off all\n - make all FLASH banks writable\n"
);
+#undef TMP_ERASE
+#undef TMP_PROT_ON
+#undef TMP_PROT_OFF
+
#endif /* CFG_CMD_FLASH */
diff --git a/common/cmd_fpga.c b/common/cmd_fpga.c
index 900d35aa44..c4b7392949 100644
--- a/common/cmd_fpga.c
+++ b/common/cmd_fpga.c
@@ -59,25 +59,30 @@ static int fpga_get_op (char *opstr);
/* Convert bitstream data and load into the fpga */
int fpga_loadbitstream(unsigned long dev, char* fpgadata, size_t size)
{
- int length;
- char* swapdata;
- int swapsize;
+ unsigned int length;
+ unsigned char* swapdata;
+ unsigned int swapsize;
char buffer[80];
- char *ptr;
- char *dataptr;
- int data;
- int i;
+ unsigned char *ptr;
+ unsigned char *dataptr;
+ unsigned char data;
+ unsigned int i;
int rc;
dataptr = fpgadata;
#if CFG_FPGA_XILINX
- /* skip the first 13 bytes of the bitsteam, their meaning is unknown */
- dataptr+=13;
+ /* skip the first bytes of the bitsteam, their meaning is unknown */
+ length = (*dataptr << 8) + *(dataptr+1);
+ dataptr+=2;
+ dataptr+=length;
/* get design name (identifier, length, string) */
+ length = (*dataptr << 8) + *(dataptr+1);
+ dataptr+=2;
if (*dataptr++ != 0x61) {
- PRINTF("fpga_loadbitstream: Design name identifier not recognized in bitstream.\n");
+ PRINTF ("%s: Design name identifier not recognized in bitstream\n",
+ __FUNCTION__ );
return FPGA_FAIL;
}
@@ -86,61 +91,71 @@ int fpga_loadbitstream(unsigned long dev, char* fpgadata, size_t size)
for(i=0;i<length;i++)
buffer[i]=*dataptr++;
- buffer[length-5]='\0'; /* remove filename extension */
- PRINTF("fpga_loadbitstream: design name = \"%s\".\n",buffer);
+ printf(" design filename = \"%s\"\n", buffer);
/* get part number (identifier, length, string) */
if (*dataptr++ != 0x62) {
- printf("fpga_loadbitstream: Part number identifier not recognized in bitstream.\n");
+ printf("%s: Part number identifier not recognized in bitstream\n",
+ __FUNCTION__ );
return FPGA_FAIL;
}
- length = (*dataptr << 8) + *(dataptr+1); dataptr+=2;
+ length = (*dataptr << 8) + *(dataptr+1);
+ dataptr+=2;
for(i=0;i<length;i++)
buffer[i]=*dataptr++;
- PRINTF("fpga_loadbitstream: part number = \"%s\".\n",buffer);
+ printf(" part number = \"%s\"\n", buffer);
/* get date (identifier, length, string) */
if (*dataptr++ != 0x63) {
- printf("fpga_loadbitstream: Date identifier not recognized in bitstream.\n");
+ printf("%s: Date identifier not recognized in bitstream\n",
+ __FUNCTION__);
return FPGA_FAIL;
}
- length = (*dataptr << 8) + *(dataptr+1); dataptr+=2;
+ length = (*dataptr << 8) + *(dataptr+1);
+ dataptr+=2;
for(i=0;i<length;i++)
buffer[i]=*dataptr++;
- PRINTF("fpga_loadbitstream: date = \"%s\".\n",buffer);
+ printf(" date = \"%s\"\n", buffer);
/* get time (identifier, length, string) */
if (*dataptr++ != 0x64) {
- printf("fpga_loadbitstream: Time identifier not recognized in bitstream.\n");
+ printf("%s: Time identifier not recognized in bitstream\n",__FUNCTION__);
return FPGA_FAIL;
}
- length = (*dataptr << 8) + *(dataptr+1); dataptr+=2;
+ length = (*dataptr << 8) + *(dataptr+1);
+ dataptr+=2;
for(i=0;i<length;i++)
buffer[i]=*dataptr++;
- PRINTF("fpga_loadbitstream: time = \"%s\".\n",buffer);
+ printf(" time = \"%s\"\n", buffer);
/* get fpga data length (identifier, length) */
if (*dataptr++ != 0x65) {
- printf("fpga_loadbitstream: Data length identifier not recognized in bitstream.\n");
+ printf("%s: Data length identifier not recognized in bitstream\n",
+ __FUNCTION__);
return FPGA_FAIL;
}
- swapsize = ((long)*dataptr<<24) + ((long)*(dataptr+1)<<16) + ((long)*(dataptr+2)<<8) + (long)*(dataptr+3);
+ swapsize = ((unsigned int) *dataptr <<24) +
+ ((unsigned int) *(dataptr+1) <<16) +
+ ((unsigned int) *(dataptr+2) <<8 ) +
+ ((unsigned int) *(dataptr+3) ) ;
dataptr+=4;
- PRINTF("fpga_loadbitstream: bytes in bitstream = %d.\n",swapsize);
+ printf(" bytes in bitstream = %d\n", swapsize);
/* check consistency of length obtained */
if (swapsize >= size) {
- printf("fpga_loadbitstream: Could not find right length of data in bitstream.\n");
+ printf("%s: Could not find right length of data in bitstream\n",
+ __FUNCTION__);
return FPGA_FAIL;
}
/* allocate memory */
- swapdata = (char *)malloc(swapsize);
+ swapdata = (unsigned char *)malloc(swapsize);
if (swapdata == NULL) {
- printf("fpga_loadbitstream: Could not allocate %d bytes memory !\n",swapsize);
+ printf("%s: Could not allocate %d bytes memory !\n",
+ __FUNCTION__, swapsize);
return FPGA_FAIL;
}
@@ -164,7 +179,7 @@ int fpga_loadbitstream(unsigned long dev, char* fpgadata, size_t size)
free(swapdata);
return rc;
#else
- printf("Bitstream support only for Xilinx devices.\n");
+ printf("Bitstream support only for Xilinx devices\n");
return FPGA_FAIL;
#endif
}
@@ -196,25 +211,25 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
data_size = simple_strtoul (argv[4], NULL, 16);
case 4: /* fpga <op> <dev> <data> */
fpga_data = (void *) simple_strtoul (argv[3], NULL, 16);
- PRINTF ("do_fpga: fpga_data = 0x%x\n",
- (uint) fpga_data);
+ PRINTF ("%s: fpga_data = 0x%x\n", __FUNCTION__, (uint) fpga_data);
case 3: /* fpga <op> <dev | data addr> */
dev = (int) simple_strtoul (argv[2], NULL, 16);
- PRINTF ("do_fpga: device = %d\n", dev);
+ PRINTF ("%s: device = %d\n", __FUNCTION__, dev);
/* FIXME - this is a really weak test */
if ((argc == 3) && (dev > fpga_count ())) { /* must be buffer ptr */
- PRINTF ("do_fpga: Assuming buffer pointer in arg 3\n");
+ PRINTF ("%s: Assuming buffer pointer in arg 3\n",
+ __FUNCTION__);
fpga_data = (void *) dev;
- PRINTF ("do_fpga: fpga_data = 0x%x\n",
- (uint) fpga_data);
+ PRINTF ("%s: fpga_data = 0x%x\n",
+ __FUNCTION__, (uint) fpga_data);
dev = FPGA_INVALID_DEVICE; /* reset device num */
}
case 2: /* fpga <op> */
op = (int) fpga_get_op (argv[1]);
break;
default:
- PRINTF ("do_fpga: Too many or too few args (%d)\n",
- argc);
+ PRINTF ("%s: Too many or too few args (%d)\n",
+ __FUNCTION__, argc);
op = FPGA_NONE; /* force usage display */
break;
}
@@ -241,7 +256,7 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
break;
default:
- printf ("Unknown operation.\n");
+ printf ("Unknown operation\n");
fpga_usage (cmdtp);
break;
}
@@ -281,8 +296,8 @@ U_BOOT_CMD (fpga, 6, 1, do_fpga,
"fpga - loadable FPGA image support\n",
"fpga [operation type] [device number] [image address] [image size]\n"
"fpga operations:\n"
- "\tinfo\tlist known device information.\n"
- "\tload\tLoad device from memory buffer.\n"
- "\tloadb\tLoad device from bitstream buffer (Xilinx devices only).\n"
- "\tdump\tLoad device to memory buffer.\n");
+ "\tinfo\tlist known device information\n"
+ "\tload\tLoad device from memory buffer\n"
+ "\tloadb\tLoad device from bitstream buffer (Xilinx devices only)\n"
+ "\tdump\tLoad device to memory buffer\n");
#endif /* CONFIG_FPGA && CONFIG_COMMANDS & CFG_CMD_FPGA */
diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c
index 45713a38bc..7ab6e9ca7a 100644
--- a/common/cmd_jffs2.c
+++ b/common/cmd_jffs2.c
@@ -1,11 +1,23 @@
/*
* (C) Copyright 2002
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
* (C) Copyright 2002
* Robert Schwebel, Pengutronix, <r.schwebel@pengutronix.de>
+ *
* (C) Copyright 2003
* Kai-Uwe Bloem, Auerswald GmbH & Co KG, <linux-development@auerswald.de>
*
+ * (C) Copyright 2005
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Added support for reading flash partition table from environment.
+ * Parsing routines are based on driver/mtd/cmdline.c from the linux 2.4
+ * kernel tree.
+ *
+ * $Id: cmdlinepart.c,v 1.17 2004/11/26 11:18:47 lavinen Exp $
+ * Copyright 2002 SYSGO Real-Time Solutions GmbH
+ *
* See file CREDITS for list of people who contributed to this
* project.
*
@@ -26,103 +38,1729 @@
*/
/*
- * Boot support
+ * Three environment variables are used by the parsing routines:
+ *
+ * 'partition' - keeps current partition identifier
+ *
+ * partition := <part-id>
+ * <part-id> := <dev-id>,part_num
+ *
+ *
+ * 'mtdids' - linux kernel mtd device id <-> u-boot device id mapping
+ *
+ * mtdids=<idmap>[,<idmap>,...]
+ *
+ * <idmap> := <dev-id>=<mtd-id>
+ * <dev-id> := 'nand'|'nor'<dev-num>
+ * <dev-num> := mtd device number, 0...
+ * <mtd-id> := unique device tag used by linux kernel to find mtd device (mtd->name)
+ *
+ *
+ * 'mtdparts' - partition list
+ *
+ * mtdparts=mtdparts=<mtd-def>[;<mtd-def>...]
+ *
+ * <mtd-def> := <mtd-id>:<part-def>[,<part-def>...]
+ * <mtd-id> := unique device tag used by linux kernel to find mtd device (mtd->name)
+ * <part-def> := <size>[@<offset>][<name>][<ro-flag>]
+ * <size> := standard linux memsize OR '-' to denote all remaining space
+ * <offset> := partition start offset within the device
+ * <name> := '(' NAME ')'
+ * <ro-flag> := when set to 'ro' makes partition read-only (not used, passed to kernel)
+ *
+ * Notes:
+ * - each <mtd-id> used in mtdparts must albo exist in 'mtddis' mapping
+ * - if the above variables are not set defaults for a given target are used
+ *
+ * Examples:
+ *
+ * 1 NOR Flash, with 1 single writable partition:
+ * mtdids=nor0=edb7312-nor
+ * mtdparts=mtdparts=edb7312-nor:-
+ *
+ * 1 NOR Flash with 2 partitions, 1 NAND with one
+ * mtdids=nor0=edb7312-nor,nand0=edb7312-nand
+ * mtdparts=mtdparts=edb7312-nor:256k(ARMboot)ro,-(root);edb7312-nand:-(home)
+ *
+ */
+
+/*
+ * JFFS2/CRAMFS support
*/
#include <common.h>
#include <command.h>
-#include <s_record.h>
-#include <jffs2/load_kernel.h>
-#include <net.h>
+#include <malloc.h>
+#include <jffs2/jffs2.h>
+#include <linux/mtd/nand.h>
+#include <linux/list.h>
+#include <linux/ctype.h>
#if (CONFIG_COMMANDS & CFG_CMD_JFFS2)
#include <cramfs/cramfs_fs.h>
+/* enable/disable debugging messages */
+#define DEBUG
+#undef DEBUG
+
+#ifdef DEBUG
+# define DEBUGF(fmt, args...) printf(fmt ,##args)
+#else
+# define DEBUGF(fmt, args...)
+#endif
+
+/* special size referring to all the remaining space in a partition */
+#define SIZE_REMAINING 0xFFFFFFFF
+
+/* special offset value, it is used when not provided by user
+ *
+ * this value is used temporarily during parsing, later such offests
+ * are recalculated */
+#define OFFSET_NOT_SPECIFIED 0xFFFFFFFF
+
+/* minimum partition size */
+#define MIN_PART_SIZE 4096
+
+/* this flag needs to be set in part_info struct mask_flags
+ * field for read-only partitions */
+#define MTD_WRITEABLE 1
+
+#ifdef CONFIG_JFFS2_CMDLINE
+/* default values for mtdids and mtdparts variables */
+#if defined(MTDIDS_DEFAULT)
+static const char *const mtdids_default = MTDIDS_DEFAULT;
+#else
+#warning "MTDIDS_DEFAULT not defined!"
+static const char *const mtdids_default = NULL;
+#endif
+
+#if defined(MTDPARTS_DEFAULT)
+static const char *const mtdparts_default = MTDPARTS_DEFAULT;
+#else
+#warning "MTDPARTS_DEFAULT not defined!"
+static const char *const mtdparts_default = NULL;
+#endif
+
+/* copies of last seen 'mtdids', 'mtdparts' and 'partition' env variables */
+#define MTDIDS_MAXLEN 128
+#define MTDPARTS_MAXLEN 512
+#define PARTITION_MAXLEN 16
+static char last_ids[MTDIDS_MAXLEN];
+static char last_parts[MTDPARTS_MAXLEN];
+static char last_partition[PARTITION_MAXLEN];
+
+/* low level jffs2 cache cleaning routine */
+extern void jffs2_free_cache(struct part_info *part);
+
+/* mtdids mapping list, filled by parse_ids() */
+struct list_head mtdids;
+
+/* device/partition list, parse_cmdline() parses into here */
+struct list_head devices;
+#endif /* #ifdef CONFIG_JFFS2_CMDLINE */
+
+/* current active device and partition number */
+static struct mtd_device *current_dev = NULL;
+static u8 current_partnum = 0;
+
extern int cramfs_check (struct part_info *info);
extern int cramfs_load (char *loadoffset, struct part_info *info, char *filename);
extern int cramfs_ls (struct part_info *info, char *filename);
extern int cramfs_info (struct part_info *info);
-static int part_num=0;
+static struct part_info* jffs2_part_info(struct mtd_device *dev, unsigned int part_num);
-#ifndef CFG_JFFS_CUSTOM_PART
+/* command line only routines */
+#ifdef CONFIG_JFFS2_CMDLINE
-#define CFG_JFFS_SINGLE_PART 1
+static struct mtdids* id_find_by_mtd_id(const char *mtd_id, unsigned int mtd_id_len);
+static int device_del(struct mtd_device *dev);
-static struct part_info part;
+/**
+ * Parses a string into a number. The number stored at ptr is
+ * potentially suffixed with K (for kilobytes, or 1024 bytes),
+ * M (for megabytes, or 1048576 bytes), or G (for gigabytes, or
+ * 1073741824). If the number is suffixed with K, M, or G, then
+ * the return value is the number multiplied by one kilobyte, one
+ * megabyte, or one gigabyte, respectively.
+ *
+ * @param ptr where parse begins
+ * @param retptr output pointer to next char after parse completes (output)
+ * @return resulting unsigned int
+ */
+static unsigned long memsize_parse (const char *const ptr, const char **retptr)
+{
+ unsigned long ret = simple_strtoul(ptr, (char **)retptr, 0);
-#ifndef CONFIG_JFFS2_NAND
+ switch (**retptr) {
+ case 'G':
+ case 'g':
+ ret <<= 10;
+ case 'M':
+ case 'm':
+ ret <<= 10;
+ case 'K':
+ case 'k':
+ ret <<= 10;
+ (*retptr)++;
+ default:
+ break;
+ }
-struct part_info*
-jffs2_part_info(int part_num)
+ return ret;
+}
+
+/**
+ * Format string describing supplied size. This routine does the opposite job
+ * to memsize_parse(). Size in bytes is converted to string and if possible
+ * shortened by using k (kilobytes), m (megabytes) or g (gigabytes) suffix.
+ *
+ * Note, that this routine does not check for buffer overflow, it's the caller
+ * who must assure enough space.
+ *
+ * @param buf output buffer
+ * @param size size to be converted to string
+ */
+static void memsize_format(char *buf, u32 size)
{
- extern flash_info_t flash_info[]; /* info for FLASH chips */
+#define SIZE_GB ((u32)1024*1024*1024)
+#define SIZE_MB ((u32)1024*1024)
+#define SIZE_KB ((u32)1024)
+
+ if ((size % SIZE_GB) == 0)
+ sprintf(buf, "%lug", size/SIZE_GB);
+ else if ((size % SIZE_MB) == 0)
+ sprintf(buf, "%lum", size/SIZE_MB);
+ else if (size % SIZE_KB == 0)
+ sprintf(buf, "%luk", size/SIZE_KB);
+ else
+ sprintf(buf, "%lu", size);
+}
+
+/**
+ * Save current device and partition in environment variable 'partition'.
+ */
+static void current_save(void)
+{
+ char buf[16];
+
+ DEBUGF("--- current_save ---\n");
+
+ if (current_dev) {
+ sprintf(buf, "%s%d,%d", MTD_DEV_TYPE(current_dev->id->type),
+ current_dev->id->num, current_partnum);
+
+ setenv("partition", buf);
+ strncpy(last_partition, buf, 16);
+
+ DEBUGF("=> partition %s\n", buf);
+ } else {
+ setenv("partition", NULL);
+ last_partition[0] = '\0';
+
+ DEBUGF("=> partition NULL\n");
+ }
+}
+
+/**
+ * Performs sanity check for supplied NOR flash partition. Table of existing
+ * NOR flash devices is searched and partition device is located. Alignment
+ * with the granularity of NOR flash sectors is verified.
+ *
+ * @param id of the parent device
+ * @param part partition to validate
+ * @return 0 if partition is valid, 1 otherwise
+ */
+static int part_validate_nor(struct mtdids *id, struct part_info *part)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_FLASH)
+ /* info for FLASH chips */
+ extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+ flash_info_t *flash;
+ int offset_aligned;
+ u32 end_offset;
int i;
- if(part_num==0){
+ flash = &flash_info[id->num];
+
+ offset_aligned = 0;
+ for (i = 0; i < flash->sector_count; i++) {
+ if ((flash->start[i] - flash->start[0]) == part->offset) {
+ offset_aligned = 1;
+ break;
+ }
+ }
+ if (offset_aligned == 0) {
+ printf("%s%d: partition (%s) start offset alignment incorrect\n",
+ MTD_DEV_TYPE(id->type), id->num, part->name);
+ return 1;
+ }
+
+ end_offset = part->offset + part->size;
+ for (i = 0; i < flash->sector_count; i++) {
+ if ((flash->start[i] - flash->start[0]) == end_offset)
+ return 0;
+ }
+
+ if (flash->size == end_offset)
+ return 0;
+
+ printf("%s%d: partition (%s) size alignment incorrect\n",
+ MTD_DEV_TYPE(id->type), id->num, part->name);
+#endif
+ return 1;
+}
- if(part.usr_priv==(void*)1)
- return &part;
+/**
+ * Performs sanity check for supplied NAND flash partition. Table of existing
+ * NAND flash devices is searched and partition device is located. Alignment
+ * with the granularity of nand erasesize is verified.
+ *
+ * @param id of the parent device
+ * @param part partition to validate
+ * @return 0 if partition is valid, 1 otherwise
+ */
+static int part_validate_nand(struct mtdids *id, struct part_info *part)
+{
+#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND)
+ /* info for NAND chips */
+ extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
+ struct nand_chip *nand;
- memset(&part, 0, sizeof(part));
+ nand = &nand_dev_desc[id->num];
-#if defined(CFG_JFFS2_FIRST_SECTOR)
- part.offset = (unsigned char *) flash_info[CFG_JFFS2_FIRST_BANK].start[CFG_JFFS2_FIRST_SECTOR];
+ if ((unsigned long)(part->offset) % nand->erasesize) {
+ printf("%s%d: partition (%s) start offset alignment incorrect\n",
+ MTD_DEV_TYPE(id->type), id->num, part->name);
+ return 1;
+ }
+
+ if (part->size % nand->erasesize) {
+ printf("%s%d: partition (%s) size alignment incorrect\n",
+ MTD_DEV_TYPE(id->type), id->num, part->name);
+ return 1;
+ }
+
+ return 0;
#else
- part.offset = (unsigned char *) flash_info[CFG_JFFS2_FIRST_BANK].start[0];
+ return 1;
#endif
+}
+
+/**
+ * Performs sanity check for supplied partition. Offset and size are verified
+ * to be within valid range. Partition type is checked and either
+ * parts_validate_nor() or parts_validate_nand() is called with the argument
+ * of part.
+ *
+ * @param id of the parent device
+ * @param part partition to validate
+ * @return 0 if partition is valid, 1 otherwise
+ */
+static int part_validate(struct mtdids *id, struct part_info *part)
+{
+ if (part->size == SIZE_REMAINING)
+ part->size = id->size - part->offset;
+
+ if (part->offset > id->size) {
+ printf("%s: offset %08lx beyond flash size %08lx\n",
+ id->mtd_id, part->offset, id->size);
+ return 1;
+ }
+
+ if ((part->offset + part->size) <= part->offset) {
+ printf("%s%d: partition (%s) size too big\n",
+ MTD_DEV_TYPE(id->type), id->num, part->name);
+ return 1;
+ }
+
+ if (part->offset + part->size > id->size) {
+ printf("%s: partitioning exceeds flash size\n", id->mtd_id);
+ return 1;
+ }
+
+ if (id->type == MTD_DEV_TYPE_NAND)
+ return part_validate_nand(id, part);
+ else if (id->type == MTD_DEV_TYPE_NOR)
+ return part_validate_nor(id, part);
+ else
+ DEBUGF("part_validate: invalid dev type\n");
+
+ return 1;
+}
+
+/**
+ * Delete selected partition from the partion list of the specified device.
+ *
+ * @param dev device to delete partition from
+ * @param part partition to delete
+ * @return 0 on success, 1 otherwise
+ */
+static int part_del(struct mtd_device *dev, struct part_info *part)
+{
+ /* if there is only one partition, remove whole device */
+ if (dev->num_parts == 1)
+ return device_del(dev);
+
+ /* otherwise just delete this partition */
+
+ if (dev == current_dev) {
+ /* we are modyfing partitions for the current device,
+ * update current */
+ struct part_info *curr_pi;
+ curr_pi = jffs2_part_info(current_dev, current_partnum);
+
+ if (curr_pi) {
+ if (curr_pi == part) {
+ printf("current partition deleted, resetting current to 0\n");
+ current_partnum = 0;
+ current_save();
+ } else if (part->offset <= curr_pi->offset) {
+ current_partnum--;
+ current_save();
+ }
+ }
+ }
+
+
+ jffs2_free_cache(part);
+ list_del(&part->link);
+ free(part);
+ dev->num_parts--;
+
+ return 0;
+}
+
+/**
+ * Delete all partitions from parts head list, free memory.
+ *
+ * @param head list of partitions to delete
+ */
+static void part_delall(struct list_head *head)
+{
+ struct list_head *entry, *n;
+ struct part_info *part_tmp;
+
+ /* clean tmp_list and free allocated memory */
+ list_for_each_safe(entry, n, head) {
+ part_tmp = list_entry(entry, struct part_info, link);
+
+ jffs2_free_cache(part_tmp);
+ list_del(entry);
+ free(part_tmp);
+ }
+}
+
+/**
+ * Add new partition to the supplied partition list. Make sure partitions are
+ * sorted by offset in ascending order.
+ *
+ * @param head list this partition is to be added to
+ * @param new partition to be added
+ */
+static int part_sort_add(struct mtd_device *dev, struct part_info *part)
+{
+ struct list_head *entry;
+ struct part_info *new_pi, *curr_pi;
+
+ /* link partition to parrent dev */
+ part->dev = dev;
+
+ if (list_empty(&dev->parts)) {
+ DEBUGF("part_sort_add: list empty\n");
+ list_add(&part->link, &dev->parts);
+ return 0;
+ }
+
+ new_pi = list_entry(&part->link, struct part_info, link);
+
+ /* get current partition info if we are updating current device */
+ curr_pi = NULL;
+ if (dev == current_dev)
+ curr_pi = jffs2_part_info(current_dev, current_partnum);
+
+ list_for_each(entry, &dev->parts) {
+ struct part_info *pi;
+
+ pi = list_entry(entry, struct part_info, link);
+
+ /* be compliant with kernel cmdline, allow only one partition at offset zero */
+ if ((new_pi->offset == pi->offset) && (pi->offset == 0)) {
+ printf("cannot add second partition at offset 0\n");
+ return 1;
+ }
+
+ if (new_pi->offset <= pi->offset) {
+ list_add_tail(&part->link, entry);
+
+ if (curr_pi && (pi->offset <= curr_pi->offset)) {
+ /* we are modyfing partitions for the current
+ * device, update current */
+ current_partnum++;
+ current_save();
+ }
+
+ return 0;
+ }
+ }
+ list_add_tail(&part->link, &dev->parts);
+ return 0;
+}
+
+/**
+ * Add provided partition to the partition list of a given device.
+ *
+ * @param dev device to which partition is added
+ * @param part partition to be added
+ * @return 0 on success, 1 otherwise
+ */
+static int part_add(struct mtd_device *dev, struct part_info *part)
+{
+ /* verify alignment and size */
+ if (part_validate(dev->id, part) != 0)
+ return 1;
- /* Figure out flash partition size */
- for (i = CFG_JFFS2_FIRST_BANK; i < CFG_JFFS2_NUM_BANKS+CFG_JFFS2_FIRST_BANK; i++)
- part.size += flash_info[i].size;
+ /* partition is ok, add it to the list */
+ if (part_sort_add(dev, part) != 0)
+ return 1;
-#if defined(CFG_JFFS2_FIRST_SECTOR) && (CFG_JFFS2_FIRST_SECTOR > 0)
- part.size -=
- flash_info[CFG_JFFS2_FIRST_BANK].start[CFG_JFFS2_FIRST_SECTOR] -
- flash_info[CFG_JFFS2_FIRST_BANK].start[0];
+ dev->num_parts++;
+ return 0;
+}
+
+/**
+ * Parse one partition definition, allocate memory and return pointer to this
+ * location in retpart.
+ *
+ * @param partdef pointer to the partition definition string i.e. <part-def>
+ * @param ret output pointer to next char after parse completes (output)
+ * @param retpart pointer to the allocated partition (output)
+ * @return 0 on success, 1 otherwise
+ */
+static int part_parse(const char *const partdef, const char **ret, struct part_info **retpart)
+{
+ struct part_info *part;
+ unsigned long size;
+ unsigned long offset;
+ const char *name;
+ int name_len;
+ unsigned int mask_flags;
+ const char *p;
+
+ p = partdef;
+ *retpart = NULL;
+ *ret = NULL;
+
+ /* fetch the partition size */
+ if (*p == '-') {
+ /* assign all remaining space to this partition */
+ DEBUGF("'-': remaining size assigned\n");
+ size = SIZE_REMAINING;
+ p++;
+ } else {
+ size = memsize_parse(p, &p);
+ if (size < MIN_PART_SIZE) {
+ printf("partition size too small (%lx)\n", size);
+ return 1;
+ }
+ }
+
+ /* check for offset */
+ offset = OFFSET_NOT_SPECIFIED;
+ if (*p == '@') {
+ p++;
+ offset = memsize_parse(p, &p);
+ }
+
+ /* now look for the name */
+ if (*p == '(') {
+ name = ++p;
+ if ((p = strchr(name, ')')) == NULL) {
+ printf("no closing ) found in partition name\n");
+ return 1;
+ }
+ name_len = p - name + 1;
+ if ((name_len - 1) == 0) {
+ printf("empty partition name\n");
+ return 1;
+ }
+ p++;
+ } else {
+ /* 0x00000000@0x00000000 */
+ name_len = 22;
+ name = NULL;
+ }
+
+ /* test for options */
+ mask_flags = 0;
+ if (strncmp(p, "ro", 2) == 0) {
+ mask_flags |= MTD_WRITEABLE;
+ p += 2;
+ }
+
+ /* check for next partition definition */
+ if (*p == ',') {
+ if (size == SIZE_REMAINING) {
+ *ret = NULL;
+ printf("no partitions allowed after a fill-up partition\n");
+ return 1;
+ }
+ *ret = ++p;
+ } else if ((*p == ';') || (*p == '\0')) {
+ *ret = p;
+ } else {
+ printf("unexpected character '%c' at the end of partition\n", *p);
+ *ret = NULL;
+ return 1;
+ }
+
+ /* allocate memory */
+ part = (struct part_info *)malloc(sizeof(struct part_info) + name_len);
+ if (!part) {
+ printf("out of memory\n");
+ return 1;
+ }
+ memset(part, 0, sizeof(struct part_info) + name_len);
+ part->size = size;
+ part->offset = offset;
+ part->mask_flags = mask_flags;
+ part->name = (char *)(part + 1);
+
+ if (name) {
+ /* copy user provided name */
+ strncpy(part->name, name, name_len - 1);
+ part->auto_name = 0;
+ } else {
+ /* auto generated name in form of size@offset */
+ sprintf(part->name, "0x%08lx@0x%08lx", size, offset);
+ part->auto_name = 1;
+ }
+
+ part->name[name_len - 1] = '\0';
+ INIT_LIST_HEAD(&part->link);
+
+ DEBUGF("+ partition: name %-22s size 0x%08x offset 0x%08x mask flags %d\n",
+ part->name, part->size,
+ part->offset, part->mask_flags);
+
+ *retpart = part;
+ return 0;
+}
+#endif/* #ifdef CONFIG_JFFS2_CMDLINE */
+
+/**
+ * Check device number to be within valid range for given device type.
+ *
+ * @param dev device to validate
+ * @return 0 if device is valid, 1 otherwise
+ */
+static int device_validate(u8 type, u8 num, u32 *size)
+{
+ if (type == MTD_DEV_TYPE_NOR) {
+#if (CONFIG_COMMANDS & CFG_CMD_FLASH)
+ if (num < CFG_MAX_FLASH_BANKS) {
+ extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+ *size = flash_info[num].size;
+ return 0;
+ }
+
+ printf("no such FLASH device: %s%d (valid range 0 ... %d\n",
+ MTD_DEV_TYPE(type), num, CFG_MAX_FLASH_BANKS - 1);
+#else
+ printf("support for FLASH devices not present\n");
+#endif
+ } else if (type == MTD_DEV_TYPE_NAND) {
+#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND)
+ if (num < CFG_MAX_NAND_DEVICE) {
+ extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
+ *size = nand_dev_desc[num].totlen;
+ return 0;
+ }
+
+ printf("no such NAND device: %s%d (valid range 0 ... %d)\n",
+ MTD_DEV_TYPE(type), num, CFG_MAX_NAND_DEVICE - 1);
+#else
+ printf("support for NAND devices not present\n");
#endif
+ }
+
+ return 1;
+}
+
+#ifdef CONFIG_JFFS2_CMDLINE
+/**
+ * Delete all mtd devices from a supplied devices list, free memory allocated for
+ * each device and delete all device partitions.
+ *
+ * @return 0 on success, 1 otherwise
+ */
+static int device_delall(struct list_head *head)
+{
+ struct list_head *entry, *n;
+ struct mtd_device *dev_tmp;
+
+ /* clean devices list */
+ list_for_each_safe(entry, n, head) {
+ dev_tmp = list_entry(entry, struct mtd_device, link);
+ list_del(entry);
+ part_delall(&dev_tmp->parts);
+ free(dev_tmp);
+ }
+ INIT_LIST_HEAD(&devices);
+
+ return 0;
+}
+
+/**
+ * If provided device exists it's partitions are deleted, device is removed
+ * from device list and device memory is freed.
+ *
+ * @param dev device to be deleted
+ * @return 0 on success, 1 otherwise
+ */
+static int device_del(struct mtd_device *dev)
+{
+ part_delall(&dev->parts);
+ list_del(&dev->link);
+ free(dev);
+
+ if (dev == current_dev) {
+ /* we just deleted current device */
+ if (list_empty(&devices)) {
+ current_dev = NULL;
+ } else {
+ /* reset first partition from first dev from the
+ * devices list as current */
+ current_dev = list_entry(devices.next, struct mtd_device, link);
+ current_partnum = 0;
+ }
+ current_save();
+ }
+
+
+ return 0;
+}
+
+/**
+ * Search global device list and return pointer to the device of type and num
+ * specified.
+ *
+ * @param type device type
+ * @param num device number
+ * @return NULL if requested device does not exist
+ */
+static struct mtd_device* device_find(u8 type, u8 num)
+{
+ struct list_head *entry;
+ struct mtd_device *dev_tmp;
+
+ list_for_each(entry, &devices) {
+ dev_tmp = list_entry(entry, struct mtd_device, link);
+
+ if ((dev_tmp->id->type == type) && (dev_tmp->id->num == num))
+ return dev_tmp;
+ }
+
+ return NULL;
+}
+
+/**
+ * Add specified device to the global device list.
+ *
+ * @param dev device to be added
+ */
+static void device_add(struct mtd_device *dev)
+{
+ if (list_empty(&devices)) {
+ current_dev = dev;
+ current_partnum = 0;
+ current_save();
+ }
+
+ list_add_tail(&dev->link, &devices);
+}
+
+/**
+ * Parse device type, name and mtd-id. If syntax is ok allocate memory and
+ * return pointer to the device structure.
+ *
+ * @param mtd_dev pointer to the device definition string i.e. <mtd-dev>
+ * @param ret output pointer to next char after parse completes (output)
+ * @param retdev pointer to the allocated device (output)
+ * @return 0 on success, 1 otherwise
+ */
+static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_device **retdev)
+{
+ struct mtd_device *dev;
+ struct part_info *part;
+ struct mtdids *id;
+ const char *mtd_id;
+ unsigned int mtd_id_len;
+ const char *p, *pend;
+ LIST_HEAD(tmp_list);
+ struct list_head *entry, *n;
+ u16 num_parts;
+ u32 offset;
+ int err = 1;
+
+ p = mtd_dev;
+ *retdev = NULL;
+ *ret = NULL;
+
+ DEBUGF("===device_parse===\n");
+
+ /* fetch <mtd-id> */
+ mtd_id = p;
+ if (!(p = strchr(mtd_id, ':'))) {
+ printf("no <mtd-id> identifier\n");
+ return 1;
+ }
+ mtd_id_len = p - mtd_id + 1;
+ p++;
+
+ /* verify if we have a valid device specified */
+ if ((id = id_find_by_mtd_id(mtd_id, mtd_id_len - 1)) == NULL) {
+ printf("invalid mtd device '%.*s'\n", mtd_id_len - 1, mtd_id);
+ return 1;
+ }
+
+ DEBUGF("dev type = %d (%s), dev num = %d, mtd-id = %s\n",
+ id->type, MTD_DEV_TYPE(id->type),
+ id->num, id->mtd_id);
+ pend = strchr(p, ';');
+ DEBUGF("parsing partitions %.*s\n", (pend ? pend - p : strlen(p)), p);
+
+
+ /* parse partitions */
+ num_parts = 0;
+
+ offset = 0;
+ if ((dev = device_find(id->type, id->num)) != NULL) {
+ /* if device already exists start at the end of the last partition */
+ part = list_entry(dev->parts.prev, struct part_info, link);
+ offset = part->offset + part->size;
+ }
+
+ while (p && (*p != '\0') && (*p != ';')) {
+ err = 1;
+ if ((part_parse(p, &p, &part) != 0) || (!part))
+ break;
+
+ /* calculate offset when not specified */
+ if (part->offset == OFFSET_NOT_SPECIFIED)
+ part->offset = offset;
+ else
+ offset = part->offset;
+
+ /* verify alignment and size */
+ if (part_validate(id, part) != 0)
+ break;
+
+ offset += part->size;
+
+ /* partition is ok, add it to the list */
+ list_add_tail(&part->link, &tmp_list);
+ num_parts++;
+ err = 0;
+ }
+ if (err == 1) {
+ part_delall(&tmp_list);
+ return 1;
+ }
+
+ if (num_parts == 0) {
+ printf("no partitions for device %s%d (%s)\n",
+ MTD_DEV_TYPE(id->type), id->num, id->mtd_id);
+ return 1;
+ }
+
+ DEBUGF("\ntotal partitions: %d\n", num_parts);
+
+ /* check for next device presence */
+ if (p) {
+ if (*p == ';') {
+ *ret = ++p;
+ } else if (*p == '\0') {
+ *ret = p;
+ } else {
+ printf("unexpected character '%c' at the end of device\n", *p);
+ *ret = NULL;
+ return 1;
+ }
+ }
+
+ /* allocate memory for mtd_device structure */
+ if ((dev = (struct mtd_device *)malloc(sizeof(struct mtd_device))) == NULL) {
+ printf("out of memory\n");
+ return 1;
+ }
+ memset(dev, 0, sizeof(struct mtd_device));
+ dev->id = id;
+ dev->num_parts = num_parts;
+ INIT_LIST_HEAD(&dev->parts);
+ INIT_LIST_HEAD(&dev->link);
+
+ /* move partitions from tmp_list to dev->parts */
+ list_for_each_safe(entry, n, &tmp_list) {
+ part = list_entry(entry, struct part_info, link);
+ list_del(entry);
+ if (part_sort_add(dev, part) != 0) {
+ device_del(dev);
+ return 1;
+ }
+ }
+
+ *retdev = dev;
+
+ DEBUGF("===\n\n");
+ return 0;
+}
+
+/**
+ * Initialize global device list.
+ *
+ * @return 0 on success, 1 otherwise
+ */
+static int devices_init(void)
+{
+ last_parts[0] = '\0';
+ current_dev = NULL;
+ current_save();
+
+ return device_delall(&devices);
+}
+
+/*
+ * Search global mtdids list and find id of requested type and number.
+ *
+ * @return pointer to the id if it exists, NULL otherwise
+ */
+static struct mtdids* id_find(u8 type, u8 num)
+{
+ struct list_head *entry;
+ struct mtdids *id;
+
+ list_for_each(entry, &mtdids) {
+ id = list_entry(entry, struct mtdids, link);
+
+ if ((id->type == type) && (id->num == num))
+ return id;
+ }
+
+ return NULL;
+}
+
+/**
+ * Search global mtdids list and find id of a requested mtd_id.
+ *
+ * Note: first argument is not null terminated.
+ *
+ * @param mtd_id string containing requested mtd_id
+ * @param mtd_id_len length of supplied mtd_id
+ * @return pointer to the id if it exists, NULL otherwise
+ */
+static struct mtdids* id_find_by_mtd_id(const char *mtd_id, unsigned int mtd_id_len)
+{
+ struct list_head *entry;
+ struct mtdids *id;
+
+ DEBUGF("--- id_find_by_mtd_id: '%.*s' (len = %d)\n",
+ mtd_id_len, mtd_id, mtd_id_len);
+
+ list_for_each(entry, &mtdids) {
+ id = list_entry(entry, struct mtdids, link);
+
+ DEBUGF("entry: '%s' (len = %d)\n",
+ id->mtd_id, strlen(id->mtd_id));
- /* Mark the struct as ready */
- part.usr_priv=(void*)1;
+ if (mtd_id_len != strlen(id->mtd_id))
+ continue;
+ if (strncmp(id->mtd_id, mtd_id, mtd_id_len) == 0)
+ return id;
+ }
+
+ return NULL;
+}
+#endif /* #ifdef CONFIG_JFFS2_CMDLINE */
+
+/**
+ * Parse device id string <dev-id> := 'nand'|'nor'<dev-num>, return device
+ * type and number.
+ *
+ * @param id string describing device id
+ * @param ret_id output pointer to next char after parse completes (output)
+ * @param dev_type parsed device type (output)
+ * @param dev_num parsed device number (output)
+ * @return 0 on success, 1 otherwise
+ */
+int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num)
+{
+ const char *p = id;
+
+ *dev_type = 0;
+ if (strncmp(p, "nand", 4) == 0) {
+ *dev_type = MTD_DEV_TYPE_NAND;
+ p += 4;
+ } else if (strncmp(p, "nor", 3) == 0) {
+ *dev_type = MTD_DEV_TYPE_NOR;
+ p += 3;
+ } else {
+ printf("incorrect device type in %s\n", id);
+ return 1;
+ }
+
+ if (!isdigit(*p)) {
+ printf("incorrect device number in %s\n", id);
+ return 1;
+ }
+
+ *dev_num = simple_strtoul(p, (char **)&p, 0);
+ if (ret_id)
+ *ret_id = p;
+ return 0;
+}
+
+#ifdef CONFIG_JFFS2_CMDLINE
+/**
+ * Process all devices and generate corresponding mtdparts string describing
+ * all partitions on all devices.
+ *
+ * @param buf output buffer holding generated mtdparts string (output)
+ * @param buflen buffer size
+ * @return 0 on success, 1 otherwise
+ */
+static int generate_mtdparts(char *buf, u32 buflen)
+{
+ struct list_head *pentry, *dentry;
+ struct mtd_device *dev;
+ struct part_info *part, *prev_part;
+ char *p = buf;
+ char tmpbuf[32];
+ u32 size, offset, len, part_cnt;
+ u32 maxlen = buflen - 1;
+
+ DEBUGF("--- generate_mtdparts ---\n");
+
+ if (list_empty(&devices)) {
+ buf[0] = '\0';
+ return 0;
+ }
+
+ sprintf(p, "mtdparts=");
+ p += 9;
+
+ list_for_each(dentry, &devices) {
+ dev = list_entry(dentry, struct mtd_device, link);
+
+ /* copy mtd_id */
+ len = strlen(dev->id->mtd_id) + 1;
+ if (len > maxlen)
+ goto cleanup;
+ memcpy(p, dev->id->mtd_id, len - 1);
+ p += len - 1;
+ *(p++) = ':';
+ maxlen -= len;
+
+ /* format partitions */
+ prev_part = NULL;
+ part_cnt = 0;
+ list_for_each(pentry, &dev->parts) {
+ part = list_entry(pentry, struct part_info, link);
+ size = part->size;
+ offset = part->offset;
+ part_cnt++;
+
+ /* partition size */
+ memsize_format(tmpbuf, size);
+ len = strlen(tmpbuf);
+ if (len > maxlen)
+ goto cleanup;
+ memcpy(p, tmpbuf, len);
+ p += len;
+ maxlen -= len;
+
+
+ /* add offset only when there is a gap between
+ * partitions */
+ if ((!prev_part && (offset != 0)) ||
+ (prev_part && ((prev_part->offset + prev_part->size) != part->offset))) {
+
+ memsize_format(tmpbuf, offset);
+ len = strlen(tmpbuf) + 1;
+ if (len > maxlen)
+ goto cleanup;
+ *(p++) = '@';
+ memcpy(p, tmpbuf, len - 1);
+ p += len - 1;
+ maxlen -= len;
+ }
+
+ /* copy name only if user supplied */
+ if(!part->auto_name) {
+ len = strlen(part->name) + 2;
+ if (len > maxlen)
+ goto cleanup;
+
+ *(p++) = '(';
+ memcpy(p, part->name, len - 2);
+ p += len - 2;
+ *(p++) = ')';
+ maxlen -= len;
+ }
+
+ /* ro mask flag */
+ if (part->mask_flags && MTD_WRITEABLE) {
+ len = 2;
+ if (len > maxlen)
+ goto cleanup;
+ *(p++) = 'r';
+ *(p++) = 'o';
+ maxlen -= 2;
+ }
+
+ /* print ',' separator if there are other partitions
+ * following */
+ if (dev->num_parts > part_cnt) {
+ if (1 > maxlen)
+ goto cleanup;
+ *(p++) = ',';
+ maxlen--;
+ }
+ prev_part = part;
+ }
+ /* print ';' separator if there are other devices following */
+ if (dentry->next != &devices) {
+ if (1 > maxlen)
+ goto cleanup;
+ *(p++) = ';';
+ maxlen--;
+ }
+ }
+
+ /* we still have at least one char left, as we decremented maxlen at
+ * the begining */
+ *p = '\0';
+
+ return 0;
+
+cleanup:
+ last_parts[0] = '\0';
+ return 1;
+}
+
+/**
+ * Call generate_mtdparts to process all devices and generate corresponding
+ * mtdparts string, save it in mtdparts environment variable.
+ *
+ * @param buf output buffer holding generated mtdparts string (output)
+ * @param buflen buffer size
+ * @return 0 on success, 1 otherwise
+ */
+static int generate_mtdparts_save(char *buf, u32 buflen)
+{
+ int ret;
+
+ ret = generate_mtdparts(buf, buflen);
+
+ if ((buf[0] != '\0') && (ret == 0))
+ setenv("mtdparts", buf);
+ else
+ setenv("mtdparts", NULL);
+
+ return ret;
+}
+
+/**
+ * Format and print out a partition list for each device from global device
+ * list.
+ */
+static void list_partitions(void)
+{
+ struct list_head *dentry, *pentry;
+ struct part_info *part;
+ struct mtd_device *dev;
+ int part_num;
+
+ DEBUGF("\n---list_partitions---\n");
+ list_for_each(dentry, &devices) {
+ dev = list_entry(dentry, struct mtd_device, link);
+ printf("\ndevice %s%d <%s>, # parts = %d\n",
+ MTD_DEV_TYPE(dev->id->type), dev->id->num,
+ dev->id->mtd_id, dev->num_parts);
+ printf(" #: name\t\t\tsize\t\toffset\t\tmask_flags\n");
+
+ /* list partitions for given device */
+ part_num = 0;
+ list_for_each(pentry, &dev->parts) {
+ part = list_entry(pentry, struct part_info, link);
+ printf(" %d: %-22s\t0x%08x\t0x%08x\t%d\n",
+ part_num, part->name, part->size,
+ part->offset, part->mask_flags);
+
+ part_num++;
+ }
+ }
+ if (list_empty(&devices))
+ printf("no partitions defined\n");
+
+ /* current_dev is not NULL only when we have non empty device list */
+ if (current_dev) {
+ part = jffs2_part_info(current_dev, current_partnum);
+ if (part) {
+ printf("\nactive partition: %s%d,%d - (%s) 0x%08lx @ 0x%08lx\n",
+ MTD_DEV_TYPE(current_dev->id->type),
+ current_dev->id->num, current_partnum,
+ part->name, part->size, part->offset);
+ } else {
+ printf("could not get current partition info\n\n");
+ }
+ }
+
+ printf("\ndefaults:\n");
+ printf("mtdids : %s\n", mtdids_default);
+ printf("mtdparts: %s\n", mtdparts_default);
+}
+
+/**
+ * Given partition identifier in form of <dev_type><dev_num>,<part_num> find
+ * corresponding device and verify partition number.
+ *
+ * @param id string describing device and partition
+ * @param dev pointer to the requested device (output)
+ * @param part_num verified partition number (output)
+ * @param part pointer to requested partition (output)
+ * @return 0 on success, 1 otherwise
+ */
+int find_dev_and_part(const char *id, struct mtd_device **dev,
+ u8 *part_num, struct part_info **part)
+{
+ u8 type, dnum, pnum;
+ const char *p;
+
+ DEBUGF("--- find_dev_and_part ---\nid = %s\n", id);
+
+ p = id;
+ *dev = NULL;
+ *part = NULL;
+ *part_num = 0;
+
+ if (id_parse(p, &p, &type, &dnum) != 0)
+ return 1;
+
+ if ((*p++ != ',') || (*p == '\0')) {
+ printf("no partition number specified\n");
+ return 1;
+ }
+ pnum = simple_strtoul(p, (char **)&p, 0);
+ if (*p != '\0') {
+ printf("unexpected trailing character '%c'\n", *p);
+ return 1;
+ }
- return &part;
+ if ((*dev = device_find(type, dnum)) == NULL) {
+ printf("no such device %s%d\n", MTD_DEV_TYPE(type), dnum);
+ return 1;
}
+
+ if ((*part = jffs2_part_info(*dev, pnum)) == NULL) {
+ printf("no such partition\n");
+ *dev = NULL;
+ return 1;
+ }
+
+ *part_num = pnum;
+
return 0;
}
-#else /* CONFIG_JFFS2_NAND */
+/**
+ * Find and delete partition. For partition id format see find_dev_and_part().
+ *
+ * @param id string describing device and partition
+ * @return 0 on success, 1 otherwise
+ */
+static int delete_partition(const char *id)
+{
+ u8 pnum;
+ struct mtd_device *dev;
+ struct part_info *part;
+
+ if (find_dev_and_part(id, &dev, &pnum, &part) == 0) {
+
+ DEBUGF("delete_partition: device = %s%d, partition %d = (%s) 0x%08lx@0x%08lx\n",
+ MTD_DEV_TYPE(dev->id->type), dev->id->num, pnum,
+ part->name, part->size, part->offset);
+
+ if (part_del(dev, part) != 0)
+ return 1;
+
+ if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
+ printf("generated mtdparts too long, reseting to null\n");
+ return 1;
+ }
+ return 0;
+ }
+
+ printf("partition %s not found\n", id);
+ return 1;
+}
-struct part_info*
-jffs2_part_info(int part_num)
+/**
+ * Accept character string describing mtd partitions and call device_parse()
+ * for each entry. Add created devices to the global devices list.
+ *
+ * @param mtdparts string specifing mtd partitions
+ * @return 0 on success, 1 otherwise
+ */
+static int parse_mtdparts(const char *const mtdparts)
{
- if(part_num==0){
+ const char *p = mtdparts;
+ struct mtd_device *dev;
+ int err = 1;
+
+ DEBUGF("\n---parse_mtdparts---\nmtdparts = %s\n\n", p);
+
+ /* delete all devices and partitions */
+ if (devices_init() != 0) {
+ printf("could not initialise device list\n");
+ return err;
+ }
- if(part.usr_priv==(void*)1)
- return &part;
+ /* re-read 'mtdparts' variable, devices_init may be updating env */
+ p = getenv("mtdparts");
- memset(&part, 0, sizeof(part));
+ if (strncmp(p, "mtdparts=", 9) != 0) {
+ printf("mtdparts variable doesn't start with 'mtdparts='\n");
+ return err;
+ }
+ p += 9;
+
+ while (p && (*p != '\0')) {
+ err = 1;
+ if ((device_parse(p, &p, &dev) != 0) || (!dev))
+ break;
+
+ DEBUGF("+ device: %s\t%d\t%s\n", MTD_DEV_TYPE(dev->id->type),
+ dev->id->num, dev->id->mtd_id);
+
+ /* check if parsed device is already on the list */
+ if (device_find(dev->id->type, dev->id->num) != NULL) {
+ printf("device %s%d redefined, please correct mtdparts variable\n",
+ MTD_DEV_TYPE(dev->id->type), dev->id->num);
+ break;
+ }
- part.offset = (char *)CONFIG_JFFS2_NAND_OFF;
- part.size = CONFIG_JFFS2_NAND_SIZE; /* the bigger size the slower jffs2 */
+ list_add_tail(&dev->link, &devices);
+ err = 0;
+ }
+ if (err == 1) {
+ device_delall(&devices);
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Parse provided string describing mtdids mapping (see file header for mtdids
+ * variable format). Allocate memory for each entry and add all found entries
+ * to the global mtdids list.
+ *
+ * @param ids mapping string
+ * @return 0 on success, 1 otherwise
+ */
+static int parse_mtdids(const char *const ids)
+{
+ const char *p = ids;
+ const char *mtd_id;
+ int mtd_id_len;
+ struct mtdids *id;
+ struct list_head *entry, *n;
+ struct mtdids *id_tmp;
+ u8 type, num;
+ u32 size;
+ int ret = 1;
-#ifndef CONFIG_JFFS2_NAND_DEV
-#define CONFIG_JFFS2_NAND_DEV 0
+ DEBUGF("\n---parse_mtdids---\nmtdids = %s\n\n", ids);
+
+ /* clean global mtdids list */
+ list_for_each_safe(entry, n, &mtdids) {
+ id_tmp = list_entry(entry, struct mtdids, link);
+ DEBUGF("mtdids del: %d %d\n", id_tmp->type, id_tmp->num);
+ list_del(entry);
+ free(id_tmp);
+ }
+ last_ids[0] = '\0';
+ INIT_LIST_HEAD(&mtdids);
+
+ while(p && (*p != '\0')) {
+
+ ret = 1;
+ /* parse 'nor'|'nand'<dev-num> */
+ if (id_parse(p, &p, &type, &num) != 0)
+ break;
+
+ if (*p != '=') {
+ printf("mtdids: incorrect <dev-num>\n");
+ break;
+ }
+ p++;
+
+ /* check if requested device exists */
+ if (device_validate(type, num, &size) != 0)
+ return 1;
+
+ /* locate <mtd-id> */
+ mtd_id = p;
+ if ((p = strchr(mtd_id, ',')) != NULL) {
+ mtd_id_len = p - mtd_id + 1;
+ p++;
+ } else {
+ mtd_id_len = strlen(mtd_id) + 1;
+ }
+ if (mtd_id_len == 0) {
+ printf("mtdids: no <mtd-id> identifier\n");
+ break;
+ }
+
+ /* check if this id is already on the list */
+ int double_entry = 0;
+ list_for_each(entry, &mtdids) {
+ id_tmp = list_entry(entry, struct mtdids, link);
+ if ((id_tmp->type == type) && (id_tmp->num == num)) {
+ double_entry = 1;
+ break;
+ }
+ }
+ if (double_entry) {
+ printf("device id %s%d redefined, please correct mtdids variable\n",
+ MTD_DEV_TYPE(type), num);
+ break;
+ }
+
+ /* allocate mtdids structure */
+ if (!(id = (struct mtdids *)malloc(sizeof(struct mtdids) + mtd_id_len))) {
+ printf("out of memory\n");
+ break;
+ }
+ memset(id, 0, sizeof(struct mtdids) + mtd_id_len);
+ id->num = num;
+ id->type = type;
+ id->size = size;
+ id->mtd_id = (char *)(id + 1);
+ strncpy(id->mtd_id, mtd_id, mtd_id_len - 1);
+ id->mtd_id[mtd_id_len - 1] = '\0';
+ INIT_LIST_HEAD(&id->link);
+
+ DEBUGF("+ id %s%d\t%16d bytes\t%s\n",
+ MTD_DEV_TYPE(id->type), id->num,
+ id->size, id->mtd_id);
+
+ list_add_tail(&id->link, &mtdids);
+ ret = 0;
+ }
+ if (ret == 1) {
+ /* clean mtdids list and free allocated memory */
+ list_for_each_safe(entry, n, &mtdids) {
+ id_tmp = list_entry(entry, struct mtdids, link);
+ list_del(entry);
+ free(id_tmp);
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Parse and initialize global mtdids mapping and create global
+ * device/partition list.
+ *
+ * @return 0 on success, 1 otherwise
+ */
+int mtdparts_init(void)
+{
+ static int initialized = 0;
+ const char *ids, *parts;
+ const char *current_partition;
+ int ids_changed;
+ char tmp_ep[PARTITION_MAXLEN];
+
+ DEBUGF("\n---mtdparts_init---\n");
+ if (!initialized) {
+ INIT_LIST_HEAD(&mtdids);
+ INIT_LIST_HEAD(&devices);
+ memset(last_ids, 0, MTDIDS_MAXLEN);
+ memset(last_parts, 0, MTDPARTS_MAXLEN);
+ memset(last_partition, 0, PARTITION_MAXLEN);
+ initialized = 1;
+ }
+
+ /* get variables */
+ ids = getenv("mtdids");
+ parts = getenv("mtdparts");
+ current_partition = getenv("partition");
+
+ /* save it for later parsing, cannot rely on current partition pointer
+ * as 'partition' variable may be updated during init */
+ tmp_ep[0] = '\0';
+ if (current_partition)
+ strncpy(tmp_ep, current_partition, PARTITION_MAXLEN);
+
+ DEBUGF("last_ids : %s\n", last_ids);
+ DEBUGF("env_ids : %s\n", ids);
+ DEBUGF("last_parts: %s\n", last_parts);
+ DEBUGF("env_parts : %s\n\n", parts);
+
+ DEBUGF("last_partition : %s\n", last_partition);
+ DEBUGF("env_partition : %s\n", current_partition);
+
+ /* if mtdids varible is empty try to use defaults */
+ if (!ids) {
+ if (mtdids_default) {
+ DEBUGF("mtdids variable not defined, using default\n");
+ ids = mtdids_default;
+ setenv("mtdids", (char *)ids);
+ } else {
+ printf("mtdids not defined, no default present\n");
+ return 1;
+ }
+ }
+ if (strlen(ids) > MTDIDS_MAXLEN - 1) {
+ printf("mtdids too long (> %d)\n", MTDIDS_MAXLEN);
+ return 1;
+ }
+
+ /* do no try to use defaults when mtdparts variable is not defined,
+ * just check the length */
+ if (!parts)
+ printf("mtdparts variable not set, see 'help mtdparts'\n");
+
+ if (parts && (strlen(parts) > MTDPARTS_MAXLEN - 1)) {
+ printf("mtdparts too long (> %d)\n", MTDPARTS_MAXLEN);
+ return 1;
+ }
+
+ /* check if we have already parsed those mtdids */
+ if ((last_ids[0] != '\0') && (strcmp(last_ids, ids) == 0)) {
+ ids_changed = 0;
+ } else {
+ ids_changed = 1;
+
+ if (parse_mtdids(ids) != 0) {
+ device_delall(&devices);
+ return 1;
+ }
+
+ /* ok it's good, save new ids */
+ strncpy(last_ids, ids, MTDIDS_MAXLEN);
+ }
+
+ /* parse partitions if either mtdparts or mtdids were updated */
+ if (parts && ((last_parts[0] == '\0') || ((strcmp(last_parts, parts) != 0)) || ids_changed)) {
+ if (parse_mtdparts(parts) != 0)
+ return 1;
+
+ if (list_empty(&devices)) {
+ printf("mtdparts_init: no valid partitions\n");
+ return 1;
+ }
+
+ /* ok it's good, save new parts */
+ strncpy(last_parts, parts, MTDPARTS_MAXLEN);
+
+ /* reset first partition from first dev from the list as current */
+ current_dev = list_entry(devices.next, struct mtd_device, link);
+ current_partnum = 0;
+ current_save();
+
+ DEBUGF("mtdparts_init: current_dev = %s%d, current_partnum = %d\n",
+ MTD_DEV_TYPE(current_dev->id->type),
+ current_dev->id->num, current_partnum);
+ }
+
+ /* mtdparts variable was reset to NULL, delete all devices/partitions */
+ if (!parts && (last_parts[0] != '\0'))
+ return devices_init();
+
+ /* do not process current partition if mtdparts variable is null */
+ if (!parts)
+ return 0;
+
+ /* is current partition set in environment? if so, use it */
+ if ((tmp_ep[0] != '\0') && (strcmp(tmp_ep, last_partition) != 0)) {
+ struct part_info *p;
+ struct mtd_device *cdev;
+ u8 pnum;
+
+ DEBUGF("--- getting current partition: %s\n", tmp_ep);
+
+ if (find_dev_and_part(tmp_ep, &cdev, &pnum, &p) == 0) {
+ current_dev = cdev;
+ current_partnum = pnum;
+ current_save();
+ }
+ } else if (getenv("partition") == NULL) {
+ DEBUGF("no partition variable set, setting...\n");
+ current_save();
+ }
+
+ return 0;
+}
+#else /* #ifdef CONFIG_JFFS2_CMDLINE */
+/*
+ * 'Static' version of command line mtdparts_init() routine. Single partition on
+ * a single device configuration.
+ */
+
+/**
+ * Parse and initialize global mtdids mapping and create global
+ * device/partition list.
+ *
+ * @return 0 on success, 1 otherwise
+ */
+int mtdparts_init(void)
+{
+ static int initialized = 0;
+ u32 size;
+ char *dev_name;
+
+ DEBUGF("\n---mtdparts_init---\n");
+ if (!initialized) {
+ struct mtdids *id;
+ struct part_info *part;
+
+ initialized = 1;
+ current_dev = (struct mtd_device *)
+ malloc(sizeof(struct mtd_device) +
+ sizeof(struct part_info) +
+ sizeof(struct mtdids));
+ if (!current_dev) {
+ printf("out of memory\n");
+ return 1;
+ }
+ memset(current_dev, 0, sizeof(struct mtd_device) +
+ sizeof(struct part_info) + sizeof(struct mtdids));
+
+ id = (struct mtdids *)(current_dev + 1);
+ part = (struct part_info *)(id + 1);
+
+ /* id */
+ id->mtd_id = "single part";
+
+#if defined(CONFIG_JFFS2_DEV)
+ dev_name = CONFIG_JFFS2_DEV;
+#else
+ dev_name = "nor0";
#endif
- /* nand device with the JFFS2 parition plus 1 */
- part.usr_priv = (void*)(CONFIG_JFFS2_NAND_DEV+1);
- return &part;
+
+ if ((id_parse(dev_name, NULL, &id->type, &id->num) != 0) ||
+ (device_validate(id->type, id->num, &size) != 0)) {
+ printf("incorrect device: %s%d\n", MTD_DEV_TYPE(id->type), id->num);
+ free(current_dev);
+ return 1;
+ }
+ id->size = size;
+ INIT_LIST_HEAD(&id->link);
+
+ DEBUGF("dev id: type = %d, num = %d, size = 0x%08lx, mtd_id = %s\n",
+ id->type, id->num, id->size, id->mtd_id);
+
+ /* partition */
+ part->name = "static";
+ part->auto_name = 0;
+
+#if defined(CONFIG_JFFS2_PART_SIZE)
+ part->size = CONFIG_JFFS2_PART_SIZE;
+#else
+ part->size = SIZE_REMAINING;
+#endif
+
+#if defined(CONFIG_JFFS2_PART_OFFSET)
+ part->offset = CONFIG_JFFS2_PART_OFFSET;
+#else
+ part->offset = 0x00000000;
+#endif
+
+ part->dev = current_dev;
+ INIT_LIST_HEAD(&part->link);
+
+ /* recalculate size if needed */
+ if (part->size == SIZE_REMAINING)
+ part->size = id->size - part->offset;
+
+ DEBUGF("part : name = %s, size = 0x%08lx, offset = 0x%08lx\n",
+ part->name, part->size, part->offset);
+
+ /* device */
+ current_dev->id = id;
+ INIT_LIST_HEAD(&current_dev->link);
+ current_dev->num_parts = 1;
+ INIT_LIST_HEAD(&current_dev->parts);
+ list_add(&part->link, &current_dev->parts);
}
+
return 0;
}
+#endif /* #ifdef CONFIG_JFFS2_CMDLINE */
-#endif /* CONFIG_JFFS2_NAND */
-#endif /* ifndef CFG_JFFS_CUSTOM_PART */
+/**
+ * Return pointer to the partition of a requested number from a requested
+ * device.
+ *
+ * @param dev device that is to be searched for a partition
+ * @param part_num requested partition number
+ * @return pointer to the part_info, NULL otherwise
+ */
+static struct part_info* jffs2_part_info(struct mtd_device *dev, unsigned int part_num)
+{
+ struct list_head *entry;
+ struct part_info *part;
+ int num;
+
+ if (!dev)
+ return NULL;
+
+ DEBUGF("\n--- jffs2_part_info: partition number %d for device %s%d (%s)\n",
+ part_num, MTD_DEV_TYPE(dev->id->type),
+ dev->id->num, dev->id->mtd_id);
+
+ if (part_num >= dev->num_parts) {
+ printf("invalid partition number %d for device %s%d (%s)\n",
+ part_num, MTD_DEV_TYPE(dev->id->type),
+ dev->id->num, dev->id->mtd_id);
+ return NULL;
+ }
+
+ /* locate partition number, return it */
+ num = 0;
+ list_for_each(entry, &dev->parts) {
+ part = list_entry(entry, struct part_info, link);
-int
-do_jffs2_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+ if (part_num == num++) {
+ return part;
+ }
+ }
+
+ return NULL;
+}
+
+/***************************************************/
+/* U-boot commands */
+/***************************************************/
+
+/**
+ * Routine implementing fsload u-boot command. This routine tries to load
+ * a requested file from jffs2/cramfs filesystem on a current partition.
+ *
+ * @param cmdtp command internal data
+ * @param flag command flag
+ * @param argc number of arguments supplied to the command
+ * @param argv arguments list
+ * @return 0 on success, 1 otherwise
+ */
+int do_jffs2_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
- struct part_info* jffs2_part_info(int);
- int jffs2_1pass_load(char *, struct part_info *,const char *);
char *fsname;
char *filename;
int size;
@@ -143,7 +1781,11 @@ do_jffs2_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
filename = argv[2];
}
- if (0 != (part=jffs2_part_info(part_num))){
+ /* make sure we are in sync with env variables */
+ if (mtdparts_init() !=0)
+ return 1;
+
+ if ((part = jffs2_part_info(current_dev, current_partnum))){
/* check partition type for cramfs */
fsname = (cramfs_check(part) ? "CRAMFS" : "JFFS2");
@@ -168,15 +1810,21 @@ do_jffs2_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
return !(size > 0);
}
- puts ("Active partition not valid\n");
- return 0;
+ return 1;
}
-int
-do_jffs2_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+/**
+ * Routine implementing u-boot ls command which lists content of a given
+ * directory on a current partition.
+ *
+ * @param cmdtp command internal data
+ * @param flag command flag
+ * @param argc number of arguments supplied to the command
+ * @param argv arguments list
+ * @return 0 on success, 1 otherwise
+ */
+int do_jffs2_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
- struct part_info* jffs2_part_info(int);
- int jffs2_1pass_ls(struct part_info *,char *);
char *filename = "/";
int ret;
struct part_info *part;
@@ -184,7 +1832,11 @@ do_jffs2_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
if (argc == 2)
filename = argv[1];
- if (0 != (part=jffs2_part_info(part_num))){
+ /* make sure we are in sync with env variables */
+ if (mtdparts_init() !=0)
+ return 1;
+
+ if ((part = jffs2_part_info(current_dev, current_partnum))){
/* check partition type for cramfs */
if (cramfs_check(part)) {
@@ -194,22 +1846,32 @@ do_jffs2_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
ret = jffs2_1pass_ls(part, filename);
}
- return (ret == 1);
+ return ret ? 0 : 1;
}
- puts ("Active partition not valid\n");
- return 0;
+ return 1;
}
-int
-do_jffs2_fsinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+/**
+ * Routine implementing u-boot fsinfo command. This routine prints out
+ * miscellaneous filesystem informations/statistics.
+ *
+ * @param cmdtp command internal data
+ * @param flag command flag
+ * @param argc number of arguments supplied to the command
+ * @param argv arguments list
+ * @return 0 on success, 1 otherwise
+ */
+int do_jffs2_fsinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
- struct part_info* jffs2_part_info(int);
- int jffs2_1pass_info(struct part_info *);
struct part_info *part;
char *fsname;
int ret;
- if ((part=jffs2_part_info(part_num))){
+ /* make sure we are in sync with env variables */
+ if (mtdparts_init() !=0)
+ return 1;
+
+ if ((part = jffs2_part_info(current_dev, current_partnum))){
/* check partition type for cramfs */
fsname = (cramfs_check(part) ? "CRAMFS" : "JFFS2");
@@ -222,50 +1884,161 @@ do_jffs2_fsinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
ret = jffs2_1pass_info(part);
}
- return (ret == 1);
+ return ret ? 0 : 1;
+ }
+ return 1;
+}
+
+/* command line only */
+#ifdef CONFIG_JFFS2_CMDLINE
+/**
+ * Routine implementing u-boot chpart command. Sets new current partition based
+ * on the user supplied partition id. For partition id format see find_dev_and_part().
+ *
+ * @param cmdtp command internal data
+ * @param flag command flag
+ * @param argc number of arguments supplied to the command
+ * @param argv arguments list
+ * @return 0 on success, 1 otherwise
+ */
+int do_jffs2_chpart(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+/* command line only */
+ struct mtd_device *dev;
+ struct part_info *part;
+ u8 pnum;
+
+ if (mtdparts_init() !=0)
+ return 1;
+
+ if (argc < 2) {
+ printf("no partition id specified\n");
+ return 1;
}
- puts ("Active partition not valid\n");
+
+ if (find_dev_and_part(argv[1], &dev, &pnum, &part) != 0)
+ return 1;
+
+ current_dev = dev;
+ current_partnum = pnum;
+ current_save();
+
+ printf("partition changed to %s%d,%d\n",
+ MTD_DEV_TYPE(dev->id->type), dev->id->num, pnum);
+
return 0;
}
-#ifndef CFG_JFFS_SINGLE_PART
-int
-do_jffs2_chpart(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+/**
+ * Routine implementing u-boot mtdparts command. Initialize/update default global
+ * partition list and process user partition request (list, add, del).
+ *
+ * @param cmdtp command internal data
+ * @param flag command flag
+ * @param argc number of arguments supplied to the command
+ * @param argv arguments list
+ * @return 0 on success, 1 otherwise
+ */
+int do_jffs2_mtdparts(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
- int tmp_part;
- char str_part_num[3];
- struct part_info* jffs2_part_info(int);
+ if (argc == 2) {
+ if (strcmp(argv[1], "default") == 0) {
+ setenv("mtdids", (char *)mtdids_default);
+ setenv("mtdparts", (char *)mtdparts_default);
+ setenv("partition", NULL);
- if (argc >= 2) {
- tmp_part = simple_strtoul(argv[1], NULL, 16);
- } else {
- puts ("Need partition number in argument list\n");
- return 0;
+ mtdparts_init();
+ return 0;
+ } else if (strcmp(argv[1], "delall") == 0) {
+ /* this may be the first run, initialize lists if needed */
+ mtdparts_init();
+ setenv("mtdparts", NULL);
+
+ /* devices_init() calls current_save() */
+ return devices_init();
+ }
}
- if (jffs2_part_info(tmp_part)){
- printf("Partition changed to %d\n",tmp_part);
- part_num=tmp_part;
- sprintf(str_part_num, "%d", part_num);
- setenv("partition", str_part_num);
+ /* make sure we are in sync with env variables */
+ if (mtdparts_init() != 0)
+ return 1;
+
+ if (argc == 1) {
+ list_partitions();
return 0;
}
- printf("Partition %d is not valid partiton\n",tmp_part);
- return 0;
+ /* mtdparts add <mtd-dev> <size>[@<offset>] <name> [ro] */
+ if (((argc == 5) || (argc == 6)) && (strcmp(argv[1], "add") == 0)) {
+#define PART_ADD_DESC_MAXLEN 64
+ char tmpbuf[PART_ADD_DESC_MAXLEN];
+ u8 type, num, len;
+ struct mtd_device *dev;
+ struct mtd_device *dev_tmp;
+ struct mtdids *id;
+ struct part_info *p;
-}
+ if (id_parse(argv[2], NULL, &type, &num) != 0)
+ return 1;
-U_BOOT_CMD(
- chpart, 2, 0, do_jffs2_chpart,
- "chpart\t- change active partition\n",
- " - change active partition\n"
-);
-#endif /* CFG_JFFS_SINGLE_PART */
+ if ((id = id_find(type, num)) == NULL) {
+ printf("no such device %s defined in mtdids variable\n", argv[2]);
+ return 1;
+ }
-/***************************************************/
+ len = strlen(id->mtd_id) + 1; /* 'mtd_id:' */
+ len += strlen(argv[3]); /* size@offset */
+ len += strlen(argv[4]) + 2; /* '(' name ')' */
+ if (argv[5] && (strlen(argv[5]) == 2))
+ len += 2; /* 'ro' */
+
+ if (len >= PART_ADD_DESC_MAXLEN) {
+ printf("too long partition description\n");
+ return 1;
+ }
+ sprintf(tmpbuf, "%s:%s(%s)%s",
+ id->mtd_id, argv[3], argv[4], argv[5] ? argv[5] : "");
+ DEBUGF("add tmpbuf: %s\n", tmpbuf);
+
+ if ((device_parse(tmpbuf, NULL, &dev) != 0) || (!dev))
+ return 1;
+
+ DEBUGF("+ %s\t%d\t%s\n", MTD_DEV_TYPE(dev->id->type),
+ dev->id->num, dev->id->mtd_id);
+
+ if ((dev_tmp = device_find(dev->id->type, dev->id->num)) == NULL) {
+ device_add(dev);
+ } else {
+ /* merge new partition with existing ones*/
+ p = list_entry(dev->parts.next, struct part_info, link);
+ if (part_add(dev_tmp, p) != 0) {
+ device_del(dev);
+ return 1;
+ }
+ }
+
+ if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
+ printf("generated mtdparts too long, reseting to null\n");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ /* mtdparts del part-id */
+ if ((argc == 3) && (strcmp(argv[1], "del") == 0)) {
+ DEBUGF("del: part-id = %s\n", argv[2]);
+
+ return delete_partition(argv[2]);
+ }
+
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+}
+#endif /* #ifdef CONFIG_JFFS2_CMDLINE */
+/***************************************************/
U_BOOT_CMD(
fsload, 3, 0, do_jffs2_fsload,
"fsload\t- load binary file from a filesystem image\n",
@@ -273,6 +2046,12 @@ U_BOOT_CMD(
" - load binary file from flash bank\n"
" with offset 'off'\n"
);
+U_BOOT_CMD(
+ ls, 2, 1, do_jffs2_ls,
+ "ls\t- list files in a directory (default /)\n",
+ "[ directory ]\n"
+ " - list files in a directory.\n"
+);
U_BOOT_CMD(
fsinfo, 1, 1, do_jffs2_fsinfo,
@@ -280,11 +2059,50 @@ U_BOOT_CMD(
" - print information about filesystems\n"
);
+#ifdef CONFIG_JFFS2_CMDLINE
U_BOOT_CMD(
- ls, 2, 1, do_jffs2_ls,
- "ls\t- list files in a directory (default /)\n",
- "[ directory ]\n"
- " - list files in a directory.\n"
+ chpart, 2, 0, do_jffs2_chpart,
+ "chpart\t- change active partition\n",
+ "part-id\n"
+ " - change active partition (e.g. part-id = nand0,1)\n"
);
+U_BOOT_CMD(
+ mtdparts, 6, 0, do_jffs2_mtdparts,
+ "mtdparts- define flash/nand partitions\n",
+ "\n"
+ " - list partition table\n"
+ "mtdparts delall\n"
+ " - delete all partitions\n"
+ "mtdparts del part-id\n"
+ " - delete partition (e.g. part-id = nand0,1)\n"
+ "mtdparts add <mtd-dev> <size>[@<offset>] [<name>] [ro]\n"
+ " - add partition\n"
+ "mtdparts default\n"
+ " - reset partition table to defaults\n\n"
+ "-----\n\n"
+ "this command uses three environment variables:\n\n"
+ "'partition' - keeps current partition identifier\n\n"
+ "partition := <part-id>\n"
+ "<part-id> := <dev-id>,part_num\n\n"
+ "'mtdids' - linux kernel mtd device id <-> u-boot device id mapping\n\n"
+ "mtdids=<idmap>[,<idmap>,...]\n\n"
+ "<idmap> := <dev-id>=<mtd-id>\n"
+ "<dev-id> := 'nand'|'nor'<dev-num>\n"
+ "<dev-num> := mtd device number, 0...\n"
+ "<mtd-id> := unique device tag used by linux kernel to find mtd device (mtd->name)\n\n"
+ "'mtdparts' - partition list\n\n"
+ "mtdparts=mtdparts=<mtd-def>[;<mtd-def>...]\n\n"
+ "<mtd-def> := <mtd-id>:<part-def>[,<part-def>...]\n"
+ "<mtd-id> := unique device tag used by linux kernel to find mtd device (mtd->name)\n"
+ "<part-def> := <size>[@<offset>][<name>][<ro-flag>]\n"
+ "<size> := standard linux memsize OR '-' to denote all remaining space\n"
+ "<offset> := partition start offset within the device\n"
+ "<name> := '(' NAME ')'\n"
+ "<ro-flag> := when set to 'ro' makes partition read-only (not used, passed to kernel)\n"
+);
+#endif /* #ifdef CONFIG_JFFS2_CMDLINE */
+
+/***************************************************/
+
#endif /* CFG_CMD_JFFS2 */
diff --git a/common/cmd_mii.c b/common/cmd_mii.c
index 5be4e6374d..3d260ab9bd 100644
--- a/common/cmd_mii.c
+++ b/common/cmd_mii.c
@@ -549,7 +549,7 @@ int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
U_BOOT_CMD(
mii, 5, 1, do_mii,
"mii - MII utility commands\n",
- "info <addr> - display MII PHY info\n"
+ "info <addr> - display MII PHY info\n"
"mii read <addr> <reg> - read MII PHY <addr> register <reg>\n"
"mii write <addr> <reg> <data> - write MII PHY <addr> register <reg>\n"
"mii dump <addr> <reg> - pretty-print <addr> <reg> (0-5 only)\n"
diff --git a/common/cmd_scsi.c b/common/cmd_scsi.c
index 7ee9d8efb1..ec53790f81 100644
--- a/common/cmd_scsi.c
+++ b/common/cmd_scsi.c
@@ -585,4 +585,23 @@ void scsi_setup_inquiry(ccb * pccb)
pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */
}
+
+U_BOOT_CMD(
+ scsi, 5, 1, do_scsi,
+ "scsi - SCSI sub-system\n",
+ "reset - reset SCSI controller\n"
+ "scsi info - show available SCSI devices\n"
+ "scsi scan - (re-)scan SCSI bus\n"
+ "scsi device [dev] - show or set current device\n"
+ "scsi part [dev] - print partition table of one or all SCSI devices\n"
+ "scsi read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n"
+ " to memory address `addr'\n"
+);
+
+U_BOOT_CMD(
+ scsiboot, 3, 1, do_scsiboot,
+ "scsiboot- boot from SCSI device\n",
+ "loadAddr dev:part\n"
+);
+
#endif /* #if (CONFIG_COMMANDS & CFG_CMD_SCSI) */
diff --git a/common/cmd_usb.c b/common/cmd_usb.c
index fbddb12dfd..0738f55303 100644
--- a/common/cmd_usb.c
+++ b/common/cmd_usb.c
@@ -448,11 +448,16 @@ int do_usb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
block_dev_desc_t *stor_dev;
#endif
- if ((strncmp(argv[1],"reset",5) == 0) ||
- (strncmp(argv[1],"start",5) == 0)){
+ if ((strncmp(argv[1], "reset", 5) == 0) ||
+ (strncmp(argv[1], "start", 5) == 0)){
usb_stop();
printf("(Re)start USB...\n");
- usb_init();
+ i = usb_init();
+#ifdef CONFIG_USB_STORAGE
+ /* try to recognize storage devices immediately */
+ if (i >= 0)
+ usb_stor_curr_dev = usb_stor_scan(1);
+#endif
return 0;
}
if (strncmp(argv[1],"stop",4) == 0) {
@@ -513,15 +518,18 @@ int do_usb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
return 0;
}
#ifdef CONFIG_USB_STORAGE
- if (strncmp(argv[1],"scan",4) == 0) {
- printf("Scan for storage device:\n");
- usb_stor_curr_dev=usb_stor_scan(1);
- if (usb_stor_curr_dev==-1) {
- printf("No device found. Not initialized?\n");
- return 1;
- }
+ if (strncmp(argv[1], "scan", 4) == 0) {
+ printf(" NOTE: this command is obsolete and will be phased out\n");
+ printf(" please use 'usb storage' for USB storage devices information\n\n");
+ usb_stor_info();
return 0;
}
+
+ if (strncmp(argv[1], "stor", 4) == 0) {
+ usb_stor_info();
+ return 0;
+ }
+
if (strncmp(argv[1],"part",4) == 0) {
int devno, ok;
for (ok=0, devno=0; devno<USB_MAX_STOR_DEV; ++devno) {
@@ -560,8 +568,8 @@ int do_usb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
return 1;
}
}
- if (strcmp(argv[1],"dev") == 0) {
- if (argc==3) {
+ if (strncmp(argv[1], "dev", 3) == 0) {
+ if (argc == 3) {
int dev = (int)simple_strtoul(argv[2], NULL, 10);
printf ("\nUSB device %d: ", dev);
if (dev >= USB_MAX_STOR_DEV) {
@@ -608,8 +616,8 @@ U_BOOT_CMD(
"usb stop [f] - stop USB [f]=force stop\n"
"usb tree - show USB device tree\n"
"usb info [dev] - show available USB devices\n"
- "usb scan - (re-)scan USB bus for storage devices\n"
- "usb device [dev] - show or set current USB storage device\n"
+ "usb storage - show details of USB storage devices\n"
+ "usb dev [dev] - show or set current USB storage device\n"
"usb part [dev] - print partition table of one or all USB storage devices\n"
"usb read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n"
" to memory address `addr'\n"
diff --git a/common/environment.c b/common/environment.c
index 61a8d245f9..c7f54c6bd8 100644
--- a/common/environment.c
+++ b/common/environment.c
@@ -21,7 +21,12 @@
* MA 02111-1307 USA
*/
+#ifndef __ASSEMBLY__
+#define __ASSEMBLY__ /* Dirty trick to get only #defines */
+#endif
+#define __ASM_STUB_PROCESSOR_H__ /* don't include asm/processor. */
#include <config.h>
+#undef __ASSEMBLY__
#include <environment.h>
/*
diff --git a/common/hush.c b/common/hush.c
index 47680edec3..eb7f7f1560 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -1022,12 +1022,30 @@ static void get_user_input(struct in_str *i)
int n;
static char the_command[CFG_CBSIZE];
+#ifdef CONFIG_BOOT_RETRY_TIME
+# ifdef CONFIG_RESET_TO_RETRY
+ extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+# else
+# error "This currently only works with CONFIG_RESET_TO_RETRY enabled"
+# endif
+ reset_cmd_timeout();
+#endif
i->__promptme = 1;
if (i->promptmode == 1) {
n = readline(CFG_PROMPT);
} else {
n = readline(CFG_PROMPT_HUSH_PS2);
}
+#ifdef CONFIG_BOOT_RETRY_TIME
+ if (n == -2) {
+ puts("\nTimeout waiting for command\n");
+# ifdef CONFIG_RESET_TO_RETRY
+ do_reset(NULL, 0, 0, NULL);
+# else
+# error "This currently only works with CONFIG_RESET_TO_RETRY enabled"
+# endif
+ }
+#endif
if (n == -1 ) {
flag_repeat = 0;
i->__promptme = 0;
diff --git a/common/lcd.c b/common/lcd.c
index 66506381a5..a85599dd76 100644
--- a/common/lcd.c
+++ b/common/lcd.c
@@ -58,6 +58,15 @@
/************************************************************************/
#include <video_font.h> /* Get font data, width and height */
+/************************************************************************/
+/* ** LOGO DATA */
+/************************************************************************/
+#ifdef CONFIG_LCD_LOGO
+# include <bmp_logo.h> /* Get logo data, width and height */
+# if (CONSOLE_COLOR_WHITE >= BMP_LOGO_OFFSET)
+# error Default Color Map overlaps with Logo Color Map
+# endif
+#endif
ulong lcd_setmem (ulong addr);
@@ -269,7 +278,7 @@ static void lcd_drawchars (ushort x, ushort y, uchar *str, int count)
static inline void lcd_puts_xy (ushort x, ushort y, uchar *s)
{
-#if defined(CONFIG_LCD_LOGO) && !defined(LCD_INFO_BELOW_LOGO)
+#if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO)
lcd_drawchars (x, y+BMP_LOGO_HEIGHT, s, strlen (s));
#else
lcd_drawchars (x, y, s, strlen (s));
@@ -280,7 +289,7 @@ static inline void lcd_puts_xy (ushort x, ushort y, uchar *s)
static inline void lcd_putc_xy (ushort x, ushort y, uchar c)
{
-#if defined(CONFIG_LCD_LOGO) && !defined(LCD_INFO_BELOW_LOGO)
+#if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO)
lcd_drawchars (x, y+BMP_LOGO_HEIGHT, &c, 1);
#else
lcd_drawchars (x, y, &c, 1);
@@ -420,7 +429,7 @@ static int lcd_init (void *lcdbase)
/* Initialize the console */
console_col = 0;
-#ifdef LCD_INFO_BELOW_LOGO
+#ifdef CONFIG_LCD_INFO_BELOW_LOGO
console_row = 7 + BMP_LOGO_HEIGHT / VIDEO_FONT_HEIGHT;
#else
console_row = 1; /* leave 1 blank line below logo */
@@ -673,12 +682,12 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)
static void *lcd_logo (void)
{
-#ifdef LCD_INFO
+#ifdef CONFIG_LCD_INFO
DECLARE_GLOBAL_DATA_PTR;
char info[80];
char temp[32];
-#endif /* LCD_INFO */
+#endif /* CONFIG_LCD_INFO */
#ifdef CONFIG_SPLASH_SCREEN
char *s;
@@ -700,7 +709,7 @@ static void *lcd_logo (void)
#endif /* CONFIG_LCD_LOGO */
#ifdef CONFIG_MPC823
-#ifdef LCD_INFO
+# ifdef CONFIG_LCD_INFO
sprintf (info, "%s (%s - %s) ", U_BOOT_VERSION, __DATE__, __TIME__);
lcd_drawchars (LCD_INFO_X, LCD_INFO_Y, info, strlen(info));
@@ -711,7 +720,7 @@ static void *lcd_logo (void)
sprintf (info, " Wolfgang DENK, wd@denx.de");
lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT * 2,
info, strlen(info));
-#ifdef LCD_INFO_BELOW_LOGO
+# ifdef CONFIG_LCD_INFO_BELOW_LOGO
sprintf (info, "MPC823 CPU at %s MHz",
strmhz(temp, gd->cpu_clk));
lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT * 3,
@@ -721,7 +730,7 @@ static void *lcd_logo (void)
gd->bd->bi_flashsize >> 20 );
lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT * 4,
info, strlen(info));
-#else
+# else
/* leave one blank line */
sprintf (info, "MPC823 CPU at %s MHz, %ld MB RAM, %ld MB Flash",
@@ -731,15 +740,15 @@ static void *lcd_logo (void)
lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT * 4,
info, strlen(info));
+# endif /* CONFIG_LCD_INFO_BELOW_LOGO */
+# endif /* CONFIG_LCD_INFO */
#endif /* CONFIG_MPC823 */
-#endif /* LCD_INFO_BELOW_LOGO */
-#endif /* LCD_INFO */
-#if defined(CONFIG_LCD_LOGO) && !defined(LCD_INFO_BELOW_LOGO)
+#if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO)
return ((void *)((ulong)lcd_base + BMP_LOGO_HEIGHT * lcd_line_length));
#else
return ((void *)lcd_base);
-#endif /* CONFIG_LCD_LOGO */
+#endif /* CONFIG_LCD_LOGO && !CONFIG_LCD_INFO_BELOW_LOGO */
}
/************************************************************************/
diff --git a/common/lynxkdi.c b/common/lynxkdi.c
index 14aa175b18..797d8cc880 100644
--- a/common/lynxkdi.c
+++ b/common/lynxkdi.c
@@ -20,7 +20,7 @@
#if defined(CONFIG_LYNXKDI)
#include <lynxkdi.h>
-#if defined(CONFIG_MPC8260)
+#if defined(CONFIG_MPC8260) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
void lynxkdi_boot ( image_header_t *hdr )
{
void (*lynxkdi)(void) = (void(*)(void))hdr->ih_ep;
diff --git a/common/miiphybb.c b/common/miiphybb.c
index b4cbb70305..b6af88f7d6 100644
--- a/common/miiphybb.c
+++ b/common/miiphybb.c
@@ -38,72 +38,79 @@
* Utility to send the preamble, address, and register (common to read
* and write).
*/
-static void miiphy_pre(char read,
- unsigned char addr,
- unsigned char reg)
+static void miiphy_pre (char read, unsigned char addr, unsigned char reg)
{
- int j; /* counter */
- volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, MDIO_PORT);
-
- /*
- * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure.
- * The IEEE spec says this is a PHY optional requirement. The AMD
- * 79C874 requires one after power up and one after a MII communications
- * error. This means that we are doing more preambles than we need,
- * but it is safer and will be much more robust.
- */
-
- MDIO_ACTIVE;
- MDIO(1);
- for(j = 0; j < 32; j++)
- {
- MDC(0);
- MIIDELAY;
- MDC(1);
- MIIDELAY;
- }
-
- /* send the start bit (01) and the read opcode (10) or write (10) */
- MDC(0); MDIO(0); MIIDELAY; MDC(1); MIIDELAY;
- MDC(0); MDIO(1); MIIDELAY; MDC(1); MIIDELAY;
- MDC(0); MDIO(read); MIIDELAY; MDC(1); MIIDELAY;
- MDC(0); MDIO(!read); MIIDELAY; MDC(1); MIIDELAY;
-
- /* send the PHY address */
- for(j = 0; j < 5; j++)
- {
- MDC(0);
- if((addr & 0x10) == 0)
- {
- MDIO(0);
- }
- else
- {
- MDIO(1);
- }
- MIIDELAY;
- MDC(1);
- MIIDELAY;
- addr <<= 1;
- }
-
- /* send the register address */
- for(j = 0; j < 5; j++)
- {
- MDC(0);
- if((reg & 0x10) == 0)
- {
- MDIO(0);
- }
- else
- {
- MDIO(1);
- }
- MIIDELAY;
- MDC(1);
- MIIDELAY;
- reg <<= 1;
- }
+ int j; /* counter */
+#ifndef CONFIG_EP8248
+ volatile ioport_t *iop = ioport_addr ((immap_t *) CFG_IMMR, MDIO_PORT);
+#endif
+
+ /*
+ * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure.
+ * The IEEE spec says this is a PHY optional requirement. The AMD
+ * 79C874 requires one after power up and one after a MII communications
+ * error. This means that we are doing more preambles than we need,
+ * but it is safer and will be much more robust.
+ */
+
+ MDIO_ACTIVE;
+ MDIO (1);
+ for (j = 0; j < 32; j++) {
+ MDC (0);
+ MIIDELAY;
+ MDC (1);
+ MIIDELAY;
+ }
+
+ /* send the start bit (01) and the read opcode (10) or write (10) */
+ MDC (0);
+ MDIO (0);
+ MIIDELAY;
+ MDC (1);
+ MIIDELAY;
+ MDC (0);
+ MDIO (1);
+ MIIDELAY;
+ MDC (1);
+ MIIDELAY;
+ MDC (0);
+ MDIO (read);
+ MIIDELAY;
+ MDC (1);
+ MIIDELAY;
+ MDC (0);
+ MDIO (!read);
+ MIIDELAY;
+ MDC (1);
+ MIIDELAY;
+
+ /* send the PHY address */
+ for (j = 0; j < 5; j++) {
+ MDC (0);
+ if ((addr & 0x10) == 0) {
+ MDIO (0);
+ } else {
+ MDIO (1);
+ }
+ MIIDELAY;
+ MDC (1);
+ MIIDELAY;
+ addr <<= 1;
+ }
+
+ /* send the register address */
+ for (j = 0; j < 5; j++) {
+ MDC (0);
+ if ((reg & 0x10) == 0) {
+ MDIO (0);
+ } else {
+ MDIO (1);
+ }
+ MIIDELAY;
+ MDC (1);
+ MIIDELAY;
+ reg <<= 1;
+ }
}
@@ -114,66 +121,63 @@ static void miiphy_pre(char read,
* Returns:
* 0 on success
*/
-int miiphy_read(unsigned char addr,
- unsigned char reg,
- unsigned short *value)
+int miiphy_read (unsigned char addr, unsigned char reg, unsigned short *value)
{
- short rdreg; /* register working value */
- int j; /* counter */
- volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, MDIO_PORT);
-
- miiphy_pre(1, addr, reg);
-
- /* tri-state our MDIO I/O pin so we can read */
- MDC(0);
- MDIO_TRISTATE;
- MIIDELAY;
- MDC(1);
- MIIDELAY;
-
- /* check the turnaround bit: the PHY should be driving it to zero */
- if(MDIO_READ != 0)
- {
- /* puts ("PHY didn't drive TA low\n"); */
- for(j = 0; j < 32; j++)
- {
- MDC(0);
- MIIDELAY;
- MDC(1);
- MIIDELAY;
- }
- return(-1);
- }
-
- MDC(0);
- MIIDELAY;
-
- /* read 16 bits of register data, MSB first */
- rdreg = 0;
- for(j = 0; j < 16; j++)
- {
- MDC(1);
- MIIDELAY;
- rdreg <<= 1;
- rdreg |= MDIO_READ;
- MDC(0);
- MIIDELAY;
- }
-
- MDC(1);
- MIIDELAY;
- MDC(0);
- MIIDELAY;
- MDC(1);
- MIIDELAY;
-
- *value = rdreg;
+ short rdreg; /* register working value */
+ int j; /* counter */
+#ifndef CONFIG_EP8248
+ volatile ioport_t *iop = ioport_addr ((immap_t *) CFG_IMMR, MDIO_PORT);
+#endif
+
+ miiphy_pre (1, addr, reg);
+
+ /* tri-state our MDIO I/O pin so we can read */
+ MDC (0);
+ MDIO_TRISTATE;
+ MIIDELAY;
+ MDC (1);
+ MIIDELAY;
+
+ /* check the turnaround bit: the PHY should be driving it to zero */
+ if (MDIO_READ != 0) {
+ /* puts ("PHY didn't drive TA low\n"); */
+ for (j = 0; j < 32; j++) {
+ MDC (0);
+ MIIDELAY;
+ MDC (1);
+ MIIDELAY;
+ }
+ return (-1);
+ }
+
+ MDC (0);
+ MIIDELAY;
+
+ /* read 16 bits of register data, MSB first */
+ rdreg = 0;
+ for (j = 0; j < 16; j++) {
+ MDC (1);
+ MIIDELAY;
+ rdreg <<= 1;
+ rdreg |= MDIO_READ;
+ MDC (0);
+ MIIDELAY;
+ }
+
+ MDC (1);
+ MIIDELAY;
+ MDC (0);
+ MIIDELAY;
+ MDC (1);
+ MIIDELAY;
+
+ *value = rdreg;
#ifdef DEBUG
- printf ("miiphy_read(0x%x) @ 0x%x = 0x%04x\n", reg, addr, *value);
+ printf ("miiphy_read(0x%x) @ 0x%x = 0x%04x\n", reg, addr, *value);
#endif
- return 0;
+ return 0;
}
@@ -184,47 +188,51 @@ int miiphy_read(unsigned char addr,
* Returns:
* 0 on success
*/
-int miiphy_write(unsigned char addr,
- unsigned char reg,
- unsigned short value)
+int miiphy_write (unsigned char addr, unsigned char reg, unsigned short value)
{
- int j; /* counter */
- volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, MDIO_PORT);
-
- miiphy_pre(0, addr, reg);
-
- /* send the turnaround (10) */
- MDC(0); MDIO(1); MIIDELAY; MDC(1); MIIDELAY;
- MDC(0); MDIO(0); MIIDELAY; MDC(1); MIIDELAY;
-
- /* write 16 bits of register data, MSB first */
- for(j = 0; j < 16; j++)
- {
- MDC(0);
- if((value & 0x00008000) == 0)
- {
- MDIO(0);
- }
- else
- {
- MDIO(1);
- }
- MIIDELAY;
- MDC(1);
- MIIDELAY;
- value <<= 1;
- }
-
- /*
- * Tri-state the MDIO line.
- */
- MDIO_TRISTATE;
- MDC(0);
- MIIDELAY;
- MDC(1);
- MIIDELAY;
-
- return 0;
+ int j; /* counter */
+#ifndef CONFIG_EP8248
+ volatile ioport_t *iop = ioport_addr ((immap_t *) CFG_IMMR, MDIO_PORT);
+#endif
+
+ miiphy_pre (0, addr, reg);
+
+ /* send the turnaround (10) */
+ MDC (0);
+ MDIO (1);
+ MIIDELAY;
+ MDC (1);
+ MIIDELAY;
+ MDC (0);
+ MDIO (0);
+ MIIDELAY;
+ MDC (1);
+ MIIDELAY;
+
+ /* write 16 bits of register data, MSB first */
+ for (j = 0; j < 16; j++) {
+ MDC (0);
+ if ((value & 0x00008000) == 0) {
+ MDIO (0);
+ } else {
+ MDIO (1);
+ }
+ MIIDELAY;
+ MDC (1);
+ MIIDELAY;
+ value <<= 1;
+ }
+
+ /*
+ * Tri-state the MDIO line.
+ */
+ MDIO_TRISTATE;
+ MDC (0);
+ MIIDELAY;
+ MDC (1);
+ MIIDELAY;
+
+ return 0;
}
#endif /* CONFIG_BITBANGMII */
diff --git a/common/miiphyutil.c b/common/miiphyutil.c
index 2b0dcf4f2c..13b9c65dc8 100644
--- a/common/miiphyutil.c
+++ b/common/miiphyutil.c
@@ -93,7 +93,13 @@ int miiphy_reset (unsigned char addr)
unsigned short reg;
int loop_cnt;
- if (miiphy_write (addr, PHY_BMCR, 0x8000) != 0) {
+ if (miiphy_read (addr, PHY_BMCR, &reg) != 0) {
+#ifdef DEBUG
+ printf ("PHY status read failed\n");
+#endif
+ return (-1);
+ }
+ if (miiphy_write (addr, PHY_BMCR, reg | 0x8000) != 0) {
#ifdef DEBUG
puts ("PHY reset failed\n");
#endif
diff --git a/common/usb.c b/common/usb.c
index 4136f8d776..d9515e659c 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -1,9 +1,19 @@
/*
- * (C) Copyright 2001
- * Denis Peter, MPL AG Switzerland
*
* Most of this source has been derived from the Linux USB
- * project.
+ * project:
+ * (C) Copyright Linus Torvalds 1999
+ * (C) Copyright Johannes Erdfelt 1999-2001
+ * (C) Copyright Andreas Gal 1999
+ * (C) Copyright Gregory P. Smith 1999
+ * (C) Copyright Deti Fliegl 1999 (new USB architecture)
+ * (C) Copyright Randy Dunlap 2000
+ * (C) Copyright David Brownell 2000 (kernel hotplug, usb_device_id)
+ * (C) Copyright Yggdrasil Computing, Inc. 2000
+ * (usb_device_id matching changes by Adam J. Richter)
+ *
+ * Adapted for U-Boot:
+ * (C) Copyright 2001 Denis Peter, MPL AG Switzerland
*
* See file CREDITS for list of people who contributed to this
* project.
@@ -37,6 +47,7 @@
#include <common.h>
#include <command.h>
#include <asm/processor.h>
+#include <linux/ctype.h>
#if (CONFIG_COMMANDS & CFG_CMD_USB)
@@ -45,8 +56,7 @@
#include <405gp_pci.h>
#endif
-
-/* #define USB_DEBUG */
+#undef USB_DEBUG
#ifdef USB_DEBUG
#define USB_PRINTF(fmt,args...) printf (fmt ,##args)
@@ -70,6 +80,7 @@ void usb_scan_devices(void);
int usb_hub_probe(struct usb_device *dev, int ifnum);
void usb_hub_reset(void);
+
/***********************************************************************
* wait_ms
*/
@@ -157,6 +168,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe,
{
if((timeout==0)&&(!asynch_allowed)) /* request for a asynch control pipe is not allowed */
return -1;
+
/* set setup command */
setup_packet.requesttype = requesttype;
setup_packet.request = request;
@@ -330,8 +342,7 @@ int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno)
int usb_clear_halt(struct usb_device *dev, int pipe)
{
int result;
- unsigned short status;
- int endp=usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7);
+ int endp = usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7);
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, USB_CNTL_TIMEOUT * 3);
@@ -339,15 +350,14 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
/* don't clear if failed */
if (result < 0)
return result;
- result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp,
- &status, sizeof(status), USB_CNTL_TIMEOUT * 3);
- if (result < 0)
- return result;
- USB_PRINTF("usb_clear_halt: status 0x%x\n",status);
- if (status & 1)
- return -1; /* still halted */
+
+ /*
+ * NOTE: we do not get status and verify reset was successful
+ * as some devices are reported to lock up upon this check..
+ */
+
usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
+
/* toggle is reset on clear */
usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
return 0;
@@ -423,7 +433,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
struct usb_interface_descriptor *if_face = NULL;
int ret, i;
- for (i=0; i<dev->config.bNumInterfaces; i++) {
+ for (i = 0; i < dev->config.bNumInterfaces; i++) {
if (dev->config.if_desc[i].bInterfaceNumber == interface) {
if_face = &dev->config.if_desc[i];
break;
@@ -439,8 +449,6 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
interface, NULL, 0, USB_CNTL_TIMEOUT * 5)) < 0)
return ret;
- if_face->act_altsetting = (unsigned char)alternate;
- usb_set_maxpacket(dev);
return 0;
}
@@ -511,11 +519,74 @@ int usb_get_class_descriptor(struct usb_device *dev, int ifnum,
*/
int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size)
{
- return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
- (USB_DT_STRING << 8) + index, langid, buf, size, USB_CNTL_TIMEOUT);
+ int i;
+ int result;
+
+ for (i = 0; i < 3; ++i) {
+ /* some devices are flaky */
+ result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+ (USB_DT_STRING << 8) + index, langid, buf, size,
+ USB_CNTL_TIMEOUT);
+
+ if (result > 0)
+ break;
+ }
+
+ return result;
+}
+
+
+static void usb_try_string_workarounds(unsigned char *buf, int *length)
+{
+ int newlength, oldlength = *length;
+
+ for (newlength = 2; newlength + 1 < oldlength; newlength += 2)
+ if (!isprint(buf[newlength]) || buf[newlength + 1])
+ break;
+
+ if (newlength > 2) {
+ buf[0] = newlength;
+ *length = newlength;
+ }
}
+
+static int usb_string_sub(struct usb_device *dev, unsigned int langid,
+ unsigned int index, unsigned char *buf)
+{
+ int rc;
+
+ /* Try to read the string descriptor by asking for the maximum
+ * possible number of bytes */
+ rc = usb_get_string(dev, langid, index, buf, 255);
+
+ /* If that failed try to read the descriptor length, then
+ * ask for just that many bytes */
+ if (rc < 2) {
+ rc = usb_get_string(dev, langid, index, buf, 2);
+ if (rc == 2)
+ rc = usb_get_string(dev, langid, index, buf, buf[0]);
+ }
+
+ if (rc >= 2) {
+ if (!buf[0] && !buf[1])
+ usb_try_string_workarounds(buf, &rc);
+
+ /* There might be extra junk at the end of the descriptor */
+ if (buf[0] < rc)
+ rc = buf[0];
+
+ rc = rc - (rc & 1); /* force a multiple of two */
+ }
+
+ if (rc < 2)
+ rc = -1;
+
+ return rc;
+}
+
+
/********************************************************************
* usb_string:
* Get string index and translate it to ascii.
@@ -535,7 +606,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
/* get langid for strings if it's not yet known */
if (!dev->have_langid) {
- err = usb_get_string(dev, 0, 0, tbuf, 4);
+ err = usb_string_sub(dev, 0, 0, tbuf);
if (err < 0) {
USB_PRINTF("error getting string descriptor 0 (error=%x)\n",dev->status);
return -1;
@@ -550,22 +621,11 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
dev->devnum, dev->string_langid);
}
}
- /* Just ask for a maximum length string and then take the length
- * that was returned. */
- err = usb_get_string(dev, dev->string_langid, index, tbuf, 4);
- if (err < 0)
- return err;
- u=tbuf[0];
- USB_PRINTF("Strn Len %d, index %d\n",u,index);
-
- if (u > USB_BUFSIZ) {
- USB_PRINTF("usb_string: failed to get string - too long: %d\n", u);
- return -1;
- }
- err = usb_get_string(dev, dev->string_langid, index, tbuf, u);
+ err = usb_string_sub(dev, dev->string_langid, index, tbuf);
if (err < 0)
return err;
+
size--; /* leave room for trailing NULL char in output buffer */
for (idx = 0, u = 2; u < err; u += 2) {
if (idx >= size)
@@ -641,11 +701,66 @@ int usb_new_device(struct usb_device *dev)
/* We still haven't set the Address yet */
addr = dev->devnum;
dev->devnum = 0;
+
+#undef NEW_INIT_SEQ
+#ifdef NEW_INIT_SEQ
+ /* this is a Windows scheme of initialization sequence, with double
+ * reset of the device. Some equipment is said to work only with such
+ * init sequence; this patch is based on the work by Alan Stern:
+ * http://sourceforge.net/mailarchive/forum.php?thread_id=5729457&forum_id=5398
+ */
+ int j;
+ struct usb_device_descriptor *desc;
+ int port = -1;
+ struct usb_device *parent = dev->parent;
+ unsigned short portstatus;
+
+ /* send 64-byte GET-DEVICE-DESCRIPTOR request. Since the descriptor is
+ * only 18 bytes long, this will terminate with a short packet. But if
+ * the maxpacket size is 8 or 16 the device may be waiting to transmit
+ * some more. */
+
+ desc = (struct usb_device_descriptor *)tmpbuf;
+ desc->bMaxPacketSize0 = 0;
+ for (j = 0; j < 3; ++j) {
+ err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, 64);
+ if (err < 0) {
+ USB_PRINTF("usb_new_device: 64 byte descr\n");
+ break;
+ }
+ }
+ dev->descriptor.bMaxPacketSize0 = desc->bMaxPacketSize0;
+
+ /* find the port number we're at */
+ if (parent) {
+
+ for (j = 0; j < parent->maxchild; j++) {
+ if (parent->children[j] == dev) {
+ port = j;
+ break;
+ }
+ }
+ if (port < 0) {
+ printf("usb_new_device: cannot locate device's port..\n");
+ return 1;
+ }
+
+ /* reset the port for the second time */
+ err = hub_port_reset(dev->parent, port, &portstatus);
+ if (err < 0) {
+ printf("\n Couldn't reset port %i\n", port);
+ return 1;
+ }
+ }
+#else
+ /* and this is the old and known way of initializing devices */
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8);
if (err < 8) {
printf("\n USB device not responding, giving up (status=%lX)\n",dev->status);
return 1;
}
+#endif
+
dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0;
dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
switch (dev->descriptor.bMaxPacketSize0) {
@@ -723,7 +838,7 @@ void usb_scan_devices(void)
/* device 0 is always present (root hub, so let it analyze) */
dev=usb_alloc_new_device();
usb_new_device(dev);
- printf("%d USB Devices found\n",dev_index);
+ printf("%d USB Device(s) found\n",dev_index);
/* insert "driver" if possible */
#ifdef CONFIG_USB_KEYBOARD
drv_usb_kbd_init();
@@ -821,39 +936,15 @@ struct usb_hub_device *usb_hub_allocate(void)
#define MAX_TRIES 5
-void usb_hub_port_connect_change(struct usb_device *dev, int port)
+static int hub_port_reset(struct usb_device *dev, int port,
+ unsigned short *portstat)
{
- struct usb_device *usb;
+ int tries;
struct usb_port_status portsts;
unsigned short portstatus, portchange;
- int tries;
- /* Check status */
- if (usb_get_port_status(dev, port + 1, &portsts)<0) {
- USB_HUB_PRINTF("get_port_status failed\n");
- return;
- }
-
- portstatus = swap_16(portsts.wPortStatus);
- portchange = swap_16(portsts.wPortChange);
- USB_HUB_PRINTF("portstatus %x, change %x, %s\n", portstatus, portchange,
- portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed");
-
- /* Clear the connection change status */
- usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_CONNECTION);
-
- /* Disconnect any existing devices under this port */
- if (((!(portstatus & USB_PORT_STAT_CONNECTION)) &&
- (!(portstatus & USB_PORT_STAT_ENABLE)))|| (dev->children[port])) {
- USB_HUB_PRINTF("usb_disconnect(&hub->children[port]);\n");
- /* Return now if nothing is connected */
- if (!(portstatus & USB_PORT_STAT_CONNECTION))
- return;
- }
- wait_ms(200);
-
- /* Reset the port */
+ USB_HUB_PRINTF("hub_port_reset: resetting port %d...\n", port);
for(tries=0;tries<MAX_TRIES;tries++) {
usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET);
@@ -861,7 +952,7 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
if (usb_get_port_status(dev, port + 1, &portsts)<0) {
USB_HUB_PRINTF("get_port_status failed status %lX\n",dev->status);
- return;
+ return -1;
}
portstatus = swap_16(portsts.wPortStatus);
portchange = swap_16(portsts.wPortChange);
@@ -873,10 +964,12 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
(portstatus & USB_PORT_STAT_ENABLE) ? 1 : 0);
if ((portchange & USB_PORT_STAT_C_CONNECTION) ||
!(portstatus & USB_PORT_STAT_CONNECTION))
- return;
+ return -1;
+
+ if (portstatus & USB_PORT_STAT_ENABLE) {
- if (portstatus & USB_PORT_STAT_ENABLE)
break;
+ }
wait_ms(200);
}
@@ -884,10 +977,52 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
if (tries==MAX_TRIES) {
USB_HUB_PRINTF("Cannot enable port %i after %i retries, disabling port.\n", port+1, MAX_TRIES);
USB_HUB_PRINTF("Maybe the USB cable is bad?\n");
- return;
+ return -1;
}
usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_RESET);
+ *portstat = portstatus;
+ return 0;
+
+}
+
+
+void usb_hub_port_connect_change(struct usb_device *dev, int port)
+{
+ struct usb_device *usb;
+ struct usb_port_status portsts;
+ unsigned short portstatus, portchange;
+
+ /* Check status */
+ if (usb_get_port_status(dev, port + 1, &portsts)<0) {
+ USB_HUB_PRINTF("get_port_status failed\n");
+ return;
+ }
+
+ portstatus = swap_16(portsts.wPortStatus);
+ portchange = swap_16(portsts.wPortChange);
+ USB_HUB_PRINTF("portstatus %x, change %x, %s\n", portstatus, portchange,
+ portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed");
+
+ /* Clear the connection change status */
+ usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_CONNECTION);
+
+ /* Disconnect any existing devices under this port */
+ if (((!(portstatus & USB_PORT_STAT_CONNECTION)) &&
+ (!(portstatus & USB_PORT_STAT_ENABLE)))|| (dev->children[port])) {
+ USB_HUB_PRINTF("usb_disconnect(&hub->children[port]);\n");
+ /* Return now if nothing is connected */
+ if (!(portstatus & USB_PORT_STAT_CONNECTION))
+ return;
+ }
+ wait_ms(200);
+
+ /* Reset the port */
+ if (hub_port_reset(dev, port, &portstatus) < 0) {
+ printf("cannot reset port %i!?\n", port + 1);
+ return;
+ }
+
wait_ms(200);
/* Allocate a new device struct for it */
diff --git a/common/usb_storage.c b/common/usb_storage.c
index 605a1ceb9b..69d195af60 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -1,12 +1,19 @@
/*
- * (C) Copyright 2001
- * Denis Peter, MPL AG Switzerland
+ * Most of this source has been derived from the Linux USB
+ * project:
+ * (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
+ * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
+ * (c) 1999 Michael Gee (michael@linuxspecific.com)
+ * (c) 2000 Yggdrasil Computing, Inc.
+ *
+ *
+ * Adapted for U-Boot:
+ * (C) Copyright 2001 Denis Peter, MPL AG Switzerland
*
* For BBB support (C) Copyright 2003
* Gary Jennejohn, DENX Software Engineering <gj@denx.de>
*
- * Most of this source has been derived from the Linux USB
- * project. BBB support based on /sys/dev/usb/umass.c from
+ * BBB support based on /sys/dev/usb/umass.c from
* FreeBSD.
*
* See file CREDITS for list of people who contributed to this
@@ -121,7 +128,7 @@ typedef struct {
#define UMASS_BBB_CSW_SIZE 13
#define USB_MAX_STOR_DEV 5
-static int usb_max_devs; /* number of highest available usb device */
+static int usb_max_devs = 0; /* number of highest available usb device */
static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];
@@ -177,7 +184,24 @@ void usb_show_progress(void)
}
/*********************************************************************************
- * (re)-scan the usb and reports device info
+ * show info on storage devices; 'usb start/init' must be invoked earlier
+ * as we only retrieve structures populated during devices initialization
+ */
+void usb_stor_info(void)
+{
+ int i;
+
+ if (usb_max_devs > 0)
+ for (i = 0; i < usb_max_devs; i++) {
+ printf (" Device %d: ", i);
+ dev_print(&usb_dev_desc[i]);
+ }
+ else
+ printf("No storage devices, perhaps not 'usb start'ed..?\n");
+}
+
+/*********************************************************************************
+ * scan the usb and reports device info
* to the user if mode = 1
* returns current device or -1 if no
*/
@@ -190,7 +214,7 @@ int usb_stor_scan(int mode)
memset(usb_stor_buf, 0, sizeof(usb_stor_buf));
if(mode==1) {
- printf(" scanning bus for storage devices...\n");
+ printf(" scanning bus for storage devices... ");
}
usb_disable_asynch(1); /* asynch transfer not allowed */
@@ -202,6 +226,7 @@ int usb_stor_scan(int mode)
usb_dev_desc[i].part_type=PART_TYPE_UNKNOWN;
usb_dev_desc[i].block_read=usb_stor_read;
}
+
usb_max_devs=0;
for(i=0;i<USB_MAX_DEVICE;i++) {
dev=usb_get_dev_index(i); /* get device */
@@ -211,21 +236,17 @@ int usb_stor_scan(int mode)
}
if(usb_storage_probe(dev,0,&usb_stor[usb_max_devs])) { /* ok, it is a storage devices */
/* get info and fill it in */
-
- if(usb_stor_get_info(dev, &usb_stor[usb_max_devs], &usb_dev_desc[usb_max_devs])) {
- if(mode==1) {
- printf (" Device %d: ", usb_max_devs);
- dev_print(&usb_dev_desc[usb_max_devs]);
- } /* if mode */
+ if(usb_stor_get_info(dev, &usb_stor[usb_max_devs], &usb_dev_desc[usb_max_devs]))
usb_max_devs++;
- } /* if get info ok */
} /* if storage device */
if(usb_max_devs==USB_MAX_STOR_DEV) {
printf("max USB Storage Device reached: %d stopping\n",usb_max_devs);
break;
}
} /* for */
+
usb_disable_asynch(0); /* asynch transfer allowed */
+ printf("%d Storage Device(s) found\n", usb_max_devs);
if(usb_max_devs>0)
return 0;
else
@@ -367,11 +388,13 @@ static int usb_stor_BBB_reset(struct us_data *us)
result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
US_BBB_RESET, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, us->ifnum, 0, 0, USB_CNTL_TIMEOUT*5);
+
if((result < 0) && (us->pusb_dev->status & USB_ST_STALLED))
{
USB_STOR_PRINTF("RESET:stall\n");
return -1;
}
+
/* long wait for reset */
wait_ms(150);
USB_STOR_PRINTF("BBB_reset result %d: status %X reset\n",result,us->pusb_dev->status);
@@ -640,7 +663,9 @@ int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
retry = 0;
again:
USB_STOR_PRINTF("STATUS phase\n");
- result = usb_bulk_msg(us->pusb_dev, pipein, &csw, UMASS_BBB_CSW_SIZE, &actlen, USB_CNTL_TIMEOUT*5);
+ result = usb_bulk_msg(us->pusb_dev, pipein, &csw, UMASS_BBB_CSW_SIZE,
+ &actlen, USB_CNTL_TIMEOUT*5);
+
/* special handling of STALL in STATUS phase */
if((result < 0) && (retry < 1) && (us->pusb_dev->status & USB_ST_STALLED)) {
USB_STOR_PRINTF("STATUS:stall\n");
@@ -797,7 +822,7 @@ do_retry:
static int usb_inquiry(ccb *srb,struct us_data *ss)
{
int retry,i;
- retry=3;
+ retry=5;
do {
memset(&srb->cmd[0],0,12);
srb->cmd[0]=SCSI_INQUIRY;
@@ -838,7 +863,7 @@ static int usb_request_sense(ccb *srb,struct us_data *ss)
static int usb_test_unit_ready(ccb *srb,struct us_data *ss)
{
- int retries=10;
+ int retries = 10;
do {
memset(&srb->cmd[0],0,12);
@@ -859,7 +884,7 @@ static int usb_test_unit_ready(ccb *srb,struct us_data *ss)
static int usb_read_capacity(ccb *srb,struct us_data *ss)
{
int retry;
- retry=2; /* retries */
+ retry = 3; /* retries */
do {
memset(&srb->cmd[0],0,12);
srb->cmd[0]=SCSI_RD_CAPAC;
@@ -972,9 +997,6 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data
int protocol = 0;
int subclass = 0;
-
- memset(ss, 0, sizeof(struct us_data));
-
/* let's examine the device now */
iface = &dev->config.if_desc[ifnum];
@@ -996,6 +1018,8 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data
return 0;
}
+ memset(ss, 0, sizeof(struct us_data));
+
/* At this point, we know we've got a live one */
USB_STOR_PRINTF("\n\nUSB Mass Storage device detected\n");
@@ -1103,50 +1127,62 @@ int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t
unsigned char perq,modi;
unsigned long cap[2];
unsigned long *capacity,*blksz;
- ccb *pccb=&usb_ccb;
-
- /* For some mysterious reason the 256MB flash disk of Ours Technology, Inc
- * doesn't survive this reset */
- if (dev->descriptor.idVendor != 0xea0 || dev->descriptor.idProduct != 0x6828)
+ ccb *pccb = &usb_ccb;
+
+ /* for some reasons a couple of devices would not survive this reset */
+ if (
+ /* Sony USM256E */
+ (dev->descriptor.idVendor == 0x054c &&
+ dev->descriptor.idProduct == 0x019e)
+
+ ||
+ /* USB007 Mini-USB2 Flash Drive */
+ (dev->descriptor.idVendor == 0x066f &&
+ dev->descriptor.idProduct == 0x2010)
+ )
+ USB_STOR_PRINTF("usb_stor_get_info: skipping RESET..\n");
+ else
ss->transport_reset(ss);
- pccb->pdata=usb_stor_buf;
- dev_desc->target=dev->devnum;
- pccb->lun=dev_desc->lun;
+ pccb->pdata = usb_stor_buf;
+
+ dev_desc->target = dev->devnum;
+ pccb->lun = dev_desc->lun;
USB_STOR_PRINTF(" address %d\n",dev_desc->target);
if(usb_inquiry(pccb,ss))
return -1;
- perq=usb_stor_buf[0];
- modi=usb_stor_buf[1];
- if((perq & 0x1f)==0x1f) {
+
+ perq = usb_stor_buf[0];
+ modi = usb_stor_buf[1];
+ if((perq & 0x1f) == 0x1f) {
return 0; /* skip unknown devices */
}
- if((modi&0x80)==0x80) {/* drive is removable */
- dev_desc->removable=1;
+ if((modi&0x80) == 0x80) {/* drive is removable */
+ dev_desc->removable = 1;
}
memcpy(&dev_desc->vendor[0], &usb_stor_buf[8], 8);
memcpy(&dev_desc->product[0], &usb_stor_buf[16], 16);
memcpy(&dev_desc->revision[0], &usb_stor_buf[32], 4);
- dev_desc->vendor[8]=0;
- dev_desc->product[16]=0;
- dev_desc->revision[4]=0;
+ dev_desc->vendor[8] = 0;
+ dev_desc->product[16] = 0;
+ dev_desc->revision[4] = 0;
USB_STOR_PRINTF("ISO Vers %X, Response Data %X\n",usb_stor_buf[2],usb_stor_buf[3]);
if(usb_test_unit_ready(pccb,ss)) {
printf("Device NOT ready\n Request Sense returned %02X %02X %02X\n",pccb->sense_buf[2],pccb->sense_buf[12],pccb->sense_buf[13]);
- if(dev_desc->removable==1) {
- dev_desc->type=perq;
+ if(dev_desc->removable == 1) {
+ dev_desc->type = perq;
return 1;
}
else
return 0;
}
- pccb->pdata=(unsigned char *)&cap[0];
+ pccb->pdata = (unsigned char *)&cap[0];
memset(pccb->pdata,0,8);
- if(usb_read_capacity(pccb,ss)!=0) {
+ if(usb_read_capacity(pccb,ss) != 0) {
printf("READ_CAP ERROR\n");
- cap[0]=2880;
- cap[1]=0x200;
+ cap[0] = 2880;
+ cap[1] = 0x200;
}
USB_STOR_PRINTF("Read Capacity returns: 0x%lx, 0x%lx\n",cap[0],cap[1]);
#if 0
@@ -1166,13 +1202,13 @@ int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t
(((unsigned long)(cap[1]) & (unsigned long)0xff000000UL) >> 24) ));
#endif
/* this assumes bigendian! */
- cap[0]+=1;
- capacity=&cap[0];
- blksz=&cap[1];
+ cap[0] += 1;
+ capacity = &cap[0];
+ blksz = &cap[1];
USB_STOR_PRINTF("Capacity = 0x%lx, blocksz = 0x%lx\n",*capacity,*blksz);
- dev_desc->lba=*capacity;
- dev_desc->blksz=*blksz;
- dev_desc->type=perq;
+ dev_desc->lba = *capacity;
+ dev_desc->blksz = *blksz;
+ dev_desc->type = perq;
USB_STOR_PRINTF(" address %d\n",dev_desc->target);
USB_STOR_PRINTF("partype: %d\n",dev_desc->part_type);