[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