[U-Boot-Users] Question about CFG_ENV_ADDR during RAMBOOT
Ulf Samuelsson
ulf at atmel.com
Wed May 30 00:13:45 CEST 2007
This patch is obviously not going to be accepted in the main tree...
Here is my patch to allow
* cp.b from SDRAM to dataflash with CRC calculation and storage
* cp.b from dataflash to SDRAM with CRC calculation and check
* compare dataflash to SDRAM.
Looks like it disappeared from the 1.1.2-atmel version by mistake.
The reason for adding the CRC is that the CRC check used
when booting the kernel does not really trigger the user to think
along the right lines.
If you write the kernel after the root fs, you overwrite the beginning of the root fs
if the kernel does not fit.
If you write the kernel before you write the root fs, you will overwrite
the last part of the kernel if the kernel does not fit.
By doing the crc check when copying from the dataflash to SDRAM
you immediately pinpoint the problem.
If U-Boot contained a command to write the kernel to dataflash,
then this command could check that the image fits into the partition
allocated for the kernel, and would report a "kernel too large"
warning message.
diff -urN u-boot-1.1.4-0rig/common/cmd_mem.c u-boot-1.1.4/common/cmd_mem.c
--- u-boot-1.1.4-0rig/common/cmd_mem.c 2006-08-18 18:35:32.000000000 +0200
+++ u-boot-1.1.4/common/cmd_mem.c 2006-08-18 19:32:33.000000000 +0200
@@ -64,6 +64,7 @@
}
#endif
+
#if (CONFIG_COMMANDS & CFG_CMD_MEMORY)
#ifdef CMD_MEM_DEBUG
@@ -71,6 +72,63 @@
#else
#define PRINTF(fmt,args...)
#endif
+#ifdef CONFIG_HAS_DATAFLASH
+#define DF_PAGE_VALID 0x01
+typedef unsigned char dfpagebuf[CFG_DATAFLASH_PAGE_SIZE];
+dfpagebuf dfcache[3]; // Cache buffers for dataflash
+unsigned char dfvalid[3]; // if DF_PAGE_VALID is set, then the, cache buffer contents are valid
+unsigned char dflru[3]; // Least recently used algorithm to determine which buffer to reuse
+unsigned int dfpage[3]; // TLB for cache, tells which page is loaded into dfcache
+
+void flush_dfcache(void)
+{
+ dfvalid[0] = dfvalid[1] = dfvalid[2] = 0;
+ dflru[0] = 0;
+ dflru[1] = 1;
+ dflru[2] = 2;
+}
+
+ulong translate(unsigned int addr)
+{
+ unsigned int page = (addr) / CFG_DATAFLASH_PAGE_SIZE;
+ unsigned int index = (addr) - (page * CFG_DATAFLASH_PAGE_SIZE);
+ unsigned int i,rc;
+ for(i = 0; i < 2; i++) {
+ if((page == dfpage[i]) && (dfvalid[i] & DF_PAGE_VALID)) {
+ if(dflru[0] == i) {
+ // nothing
+ } else if(dflru[1] == i) {
+ // swap with 0
+ dflru[1] = dflru[0];
+ dflru[0] = i;
+ } else {
+ // shift down
+ dflru[2] = dflru[1];
+ dflru[1] = dflru[0];
+ dflru[0] = i;
+ }
+ return (unsigned int) &dfcache[i][index];
+ }
+ }
+ // not found
+ // use buffer found in dflru[2]
+ i = dflru[2];
+ if ((rc = read_dataflash(addr, CFG_DATAFLASH_PAGE_SIZE, dfcache[i])) == DATAFLASH_OK){
+ dflru[2] = dflru[1];
+ dflru[1] = dflru[0];
+ dflru[0] = i;
+ dfvalid[i] |= DF_PAGE_VALID;
+ return (unsigned int) &dfcache[i][index];
+ }
+ return 0;
+}
+void df_writed(unsigned char *ldest, ulong laddr)
+{
+
+}
+void df_writew(unsigned char *ldest,ushort laddr) {}
+void df_writeb(unsigned char *ldest, u_char laddr) {}
+#endif
static int mod_mem(cmd_tbl_t *, int, int, int, char *[]);
@@ -316,6 +374,7 @@
int do_mem_cmp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
ulong addr1, addr2, count, ngood;
+ ulong laddr1, laddr2;
int size;
int rcode = 0;
@@ -338,12 +397,57 @@
count = simple_strtoul(argv[3], NULL, 16);
#ifdef CONFIG_HAS_DATAFLASH
+/*
if (addr_dataflash(addr1) | addr_dataflash(addr2)){
puts ("Comparison with DataFlash space not supported.\n\r");
return 0;
}
+*/
+ if (addr_dataflash(addr1) | addr_dataflash(addr2)){
+ flush_dfcache();
+ ngood = 0;
+ while (count-- > 0) {
+ laddr1 = translate((unsigned int) addr1);
+ laddr2 = translate((unsigned int) addr2);
+ if (size == 4) {
+ ulong word1 = *(ulong *)laddr1;
+ ulong word2 = *(ulong *)laddr2;
+ if (word1 != word2) {
+ printf("word at 0x%08lx (0x%08lx) "
+ "!= word at 0x%08lx (0x%08lx)\n",
+ laddr1, word1, laddr2, word2);
+ rcode = 1;
+ break;
+ }
+ }
+ else if (size == 2) {
+ ushort hword1 = *(ushort *)laddr1;
+ ushort hword2 = *(ushort *)laddr2;
+ if (hword1 != hword2) {
+ printf("halfword at 0x%08lx (0x%04x) "
+ "!= halfword at 0x%08lx (0x%04x)\n",
+ laddr1, hword1, laddr2, hword2);
+ rcode = 1;
+ break;
+ }
+ }
+ else {
+ u_char byte1 = *(u_char *)laddr1;
+ u_char byte2 = *(u_char *)laddr2;
+ if (byte1 != byte2) {
+ printf("byte at 0x%08lx (0x%02x) "
+ "!= byte at 0x%08lx (0x%02x)\n",
+ laddr1, byte1, laddr2, byte2);
+ rcode = 1;
+ break;
+ }
+ }
+ ngood++;
+ addr1 += size;
+ addr2 += size;
+ }
+ } else {
#endif
-
ngood = 0;
while (count-- > 0) {
@@ -384,6 +488,10 @@
addr1 += size;
addr2 += size;
}
+#ifdef CONFIG_HAS_DATAFLASH
+ }
+#endif
+
printf("Total of %ld %s%s were the same\n",
ngood, size == 4 ? "word" : size == 2 ? "halfword" : "byte",
@@ -484,11 +592,30 @@
/* Check if we are copying from RAM or Flash to DataFlash */
if (addr_dataflash(dest) && !addr_dataflash(addr)){
int rc;
+#ifdef CONFIG_DATAFLASH_CRC
+ unsigned int crc;
+ unsigned char *p;
+ puts ("Copy to DataFlash with CRC... ");
+ crc = crc32 (0, (const uchar *) addr, count*size);
+ // Save CRC in small endian format
+ printf("0x%08x written to [%08x] ... ",crc,(unsigned int) (dest + count * size));
+ p = (unsigned char *) addr+(count*size);
+ *p++ = (unsigned char) crc & 0xff;
+ crc >>= 8;
+
+ *p++ = (unsigned char) crc & 0xff;
+ crc >>= 8;
- puts ("Copy to DataFlash... ");
+ *p++ = (unsigned char) crc & 0xff;
+ crc >>= 8;
- rc = write_dataflash (dest, addr, count*size);
+ *p = (unsigned char) crc & 0xff;
+ rc = write_dataflash (dest, addr, count*size+4);
+#else
+ puts ("Copy to DataFlash... ");
+ rc = write_dataflash (dest, addr, count*size);
+#endif
if (rc != 1) {
dataflash_perror (rc);
return (1);
@@ -504,17 +631,70 @@
#endif
){
int rc;
+#ifdef CONFIG_DATAFLASH_CRC
+ unsigned char *p;
+ unsigned int crc,oldcrc;
+ puts ("Copy from DataFlash with CRC...");
+ rc = read_dataflash(addr, (count * size)+4, (char *) dest);
+ if (rc != 1) {
+ dataflash_perror (rc);
+ return (1);
+ }
+ // Read CRC in small endian format, MSB first
+
+ p = (unsigned char *) dest + (count * size) + 3;
+ oldcrc = *p--;
+ oldcrc = (oldcrc << 8) | *p--;
+ oldcrc = (oldcrc << 8) | *p--;
+ oldcrc = (oldcrc << 8) | *p;
+ crc = crc32 (0, (const uchar *) dest, count*size);
+ if(crc != oldcrc) {
+ printf("\n\rBad CRC, %x expected, found %x... \n\r",oldcrc,crc);
+ return 1;
+ } else {
+ printf("[0x%x]",crc);
+ }
+#else
+ puts ("Copy from DataFlash...");
rc = read_dataflash(addr, count * size, (char *) dest);
if (rc != 1) {
dataflash_perror (rc);
return (1);
}
+#endif
+ if (rc != 1) {
+ dataflash_perror (rc);
+ return (1);
+ }
+ puts ("done\n\r");
return 0;
}
if (addr_dataflash(addr) && addr_dataflash(dest)){
- puts ("Unsupported combination of source/destination.\n\r");
+ puts ("Cannot copy between two dataflash areas\n\r");
return 1;
+#if 0
+ unsigned int addr_page = (unsigned int) addr / CFG_DATAFLASH_PAGE_SIZE ;
+ unsigned int dest_page = (unsigned int) dest / CFG_DATAFLASH_PAGE_SIZE;
+ unsigned char *ldest,*laddr; if(addr_page == dest_page)
+ puts ("Cannot copy within same page\n\r");
+ return 1;
+ }
+ flush_dfcache();
+ // Read into buffer 0
+ while (count-- > 0) {
+ laddr = translate(addr); // Read source page if not inside
+ ldest = translate(dest); // Read dest page if not inside
+ if (size == 4)
+ df_writed(ldest, *((ulong *)laddr);
+ else if (size == 2)
+ df_writew(ldest,*((ushort *)laddr);
+ else
+ df_writeb(ldest, *((u_char *)laddr);
+ addr += size;
+ dest += size;
+ }
+#endif
}
#endif
--
Best Regards,
Ulf Samuelsson ulf at atmel.com
Atmel Nordic AB
Mail: Box 2033, 174 02 Sundbyberg, Sweden
Visit: Kavallerivägen 24, 174 58 Sundbyberg, Sweden
Phone +46 (8) 441 54 22 Fax +46 (8) 441 54 29
GSM +46 (706) 22 44 57
Technical support when I am not available:
AT90 AVR Applications Group: mailto:avr at atmel.com
AT91 ARM Applications Group: mailto:at91support at atmel.com
links: www.avrfreaks.net; www.at91.com; avr32linux.org
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ulf.vcf
Type: text/x-vcard
Size: 301 bytes
Desc: not available
Url : http://lists.denx.de/pipermail/u-boot/attachments/20070530/7eaf41d0/attachment.vcf
More information about the U-Boot
mailing list