[PATCH 4/5] add-partition-support.patch

Andy Green andy at openmoko.com
Fri Aug 22 01:17:43 CEST 2008


We have to minimally support DOS partition scheme.
Partitions are counted from 1+ now, and 0 means no
partition table instead of -1.

Signed-off-by: Andy Green <andy at openmoko.com>
---

 include/qi.h                      |    7 ++-
 src/drivers/glamo-mmc.c           |   15 +++++--
 src/drivers/i2c-bitbang-s3c24xx.c |    2 -
 src/gta02/gta02.c                 |   24 +++++++----
 src/gta03/gta03.c                 |    3 -
 src/nand_read.c                   |   44 ++++++++++----------
 src/phase2.c                      |   82 ++++++++++++++++++++++++-------------
 src/start_qi.c                    |    2 -
 src/utils.c                       |    5 ++
 9 files changed, 114 insertions(+), 70 deletions(-)

diff --git a/include/qi.h b/include/qi.h
index ea0382b..01cf2fa 100644
--- a/include/qi.h
+++ b/include/qi.h
@@ -42,8 +42,8 @@ enum filesystem {
 struct kernel_source {
 	const char *name; /* NULL name means invalid */
 	int (*block_init)(void);
-	int (*block_read)(unsigned char * buf, unsigned long byte_start,
-							       int count_bytes);
+	int (*block_read)(unsigned char * buf, unsigned long start512,
+							       int blocks512);
 	int partition_index; /* -1 means no partition table */
 	int offset_if_no_partition; /* used if partition_index is -1 */
 	enum filesystem filesystem;
@@ -85,9 +85,10 @@ void print32(unsigned int u);
 void printdec(int n);
 void hexdump(unsigned char *start, int len);
 unsigned int _ntohl(unsigned int n);
+unsigned int _letocpu(unsigned int n);
 unsigned long crc32(unsigned long crc, const unsigned char *buf,
 							      unsigned int len);
-int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size);
+int nand_read_ll(unsigned char *buf, unsigned long start512, int blocks512);
 
 #endif
 
diff --git a/src/drivers/glamo-mmc.c b/src/drivers/glamo-mmc.c
index 035bc07..4f383dd 100644
--- a/src/drivers/glamo-mmc.c
+++ b/src/drivers/glamo-mmc.c
@@ -316,8 +316,14 @@ static int mmc_cmd(int opcode, int arg, int flags,
 		return 0;
 
 	if (error) {
-//		printf("cmd 0x%x, arg 0x%x flags 0x%x\n", opcode, arg, flags);
-#if 0
+		puts("cmd 0x");
+		print8(opcode);
+		puts(", arg 0x");
+		print8(arg);
+		puts(", flags 0x");
+		print32(flags);
+		puts("\n");
+#if 1
 		puts("Error after cmd: 0x");
 		print32(error);
 		puts("\n");
@@ -360,7 +366,7 @@ static int mmc_cmd(int opcode, int arg, int flags,
 		error = -5;
 	if (error) {
 //		printf("cmd 0x%x, arg 0x%x flags 0x%x\n", opcode, arg, flags);
-#if 0
+#if 1
 		puts("Error after resp: 0x");
 		print32(status);
 		puts("\n");
@@ -573,7 +579,7 @@ static void print_sd_cid(const struct sd_cid *cid)
 
 int mmc_init(int verbose)
 {
-	int retries = 14, rc = -1;
+	int retries = 16, rc = -1;
 	int resp;
 	u8 response[16];
 //	mmc_cid_t *mmc_cid = (mmc_cid_t *)response;
@@ -641,6 +647,7 @@ int mmc_init(int verbose)
 
 		udelay(100000);
 		udelay(100000);
+		udelay(100000);
 
 		resp = mmc_cmd(MMC_APP_CMD, 0x00000000,
 			MMC_CMD_AC | MMC_RSP_R1, 0, 0, 0,
diff --git a/src/drivers/i2c-bitbang-s3c24xx.c b/src/drivers/i2c-bitbang-s3c24xx.c
index f71dfc4..c2d46ed 100644
--- a/src/drivers/i2c-bitbang-s3c24xx.c
+++ b/src/drivers/i2c-bitbang-s3c24xx.c
@@ -56,7 +56,7 @@ static void i2c_spin_s3c24xx(void)
 {
 	int n;
 
-	for (n = 0; n < 700; n++)
+	for (n = 0; n < 1000; n++)
 		rGPJDAT |= (1 << 5);
 }
 
diff --git a/src/gta02/gta02.c b/src/gta02/gta02.c
index 5023180..cda7a2b 100644
--- a/src/gta02/gta02.c
+++ b/src/gta02/gta02.c
@@ -263,6 +263,15 @@ int sd_card_init_gta02(void)
 	return mmc_init(1);
 }
 
+int sd_card_block_read_gta02(unsigned char * buf, unsigned long start512,
+							       int blocks512)
+{
+unsigned long mmc_bread(int dev_num, unsigned long blknr, unsigned long blkcnt,
+								     void *dst);
+
+	return mmc_bread(0, start512, blocks512, buf);
+}
+
 /* return nonzero if we believe we run on GTA02 */
 
 int is_this_board_gta02(void)
@@ -303,9 +312,9 @@ const struct board_api board_api_gta02 = {
 		[0] = {
 			.name = "SD Card FAT Kernel",
 			.block_init = sd_card_init_gta02,
-			.block_read = nand_read_ll,
-			.partition_index = 0,
-			.filesystem = FS_FAT,
+			.block_read = sd_card_block_read_gta02,
+			.partition_index = 1,
+			.filesystem = FS_EXT2,
 			.commandline = "mtdparts=physmap-flash:-(nor);" \
 					"neo1973-nand:" \
 					 "0x00040000(qi)," \
@@ -314,18 +323,17 @@ const struct board_api board_api_gta02 = {
 					 "0x000a0000(extra)," \
 					 "0x00040000(identity)," \
 					 "0x0f6a0000(backuprootfs) " \
-				       "rootfstype=jffs2 " \
-				       "root=/dev/mtdblock6 " \
+				       "rootfstype=ext2 " \
+				       "root=/dev/mmcblk0p1 " \
 				       "console=ttySAC2,115200 " \
-				       "loglevel=8 " \
+				       "loglevel=4 " \
 				       "init=/sbin/init "\
 				       "ro"
 		},
 		[1] = {
 			.name = "NAND Kernel",
 			.block_read = nand_read_ll,
-			.partition_index = -1,
-			.offset_if_no_partition = 0x80000,
+			.offset_if_no_partition = 0x80000 / 512,
 			.filesystem = FS_RAW,
 			.commandline = "mtdparts=physmap-flash:-(nor);" \
 					"neo1973-nand:" \
diff --git a/src/gta03/gta03.c b/src/gta03/gta03.c
index f99ecae..90f5908 100644
--- a/src/gta03/gta03.c
+++ b/src/gta03/gta03.c
@@ -234,8 +234,7 @@ const struct board_api board_api_gta03 = {
 		[0] = {
 			.name = "NAND Kernel",
 			.block_read = nand_read_ll,
-			.partition_index = -1,
-			.offset_if_no_partition = 0x80000,
+			.offset_if_no_partition = 0x80000 / 512,
 			.filesystem = FS_RAW,
 			.commandline = 	"neo1973-nand:" \
 					 "0x00040000(qi)," \
diff --git a/src/nand_read.c b/src/nand_read.c
index 94bf839..cb2a2de 100644
--- a/src/nand_read.c
+++ b/src/nand_read.c
@@ -17,6 +17,7 @@
 
 /* NOTE this stuff runs in steppingstone context! */
 
+/* the API refers to 512-byte blocks */
 
 #include <qi.h>
 #include "nand_read.h"
@@ -55,13 +56,13 @@ static inline void nand_wait(void)
 #define	NAND_BLOCK_MASK		(NAND_PAGE_SIZE - 1)
 #define NAND_BLOCK_SIZE		(NAND_PAGE_SIZE * 64)
 
-static int is_bad_block(unsigned long i)
+static int is_bad_block(unsigned long block_index)
 {
 	unsigned char data;
 	unsigned long page_num;
 
 	nand_clear_RnB();
-	page_num = i >> 11; /* addr / 2048 */
+	page_num = block_index >> 2; /* addr / 2048 */
 	NFCMD = NAND_CMD_READ0;
 	NFADDR = BAD_BLOCK_OFFSET & 0xff;
 	NFADDR = (BAD_BLOCK_OFFSET >> 8) & 0xff;
@@ -78,7 +79,7 @@ static int is_bad_block(unsigned long i)
 	return 0;
 }
 
-static int nand_read_page_ll(unsigned char *buf, unsigned long addr)
+static int nand_read_page_ll(unsigned char *buf, unsigned long block512)
 {
 	unsigned short *ptr16 = (unsigned short *)buf;
 	unsigned int i, page_num;
@@ -91,7 +92,7 @@ static int nand_read_page_ll(unsigned char *buf, unsigned long addr)
 
 	NFCMD = NAND_CMD_READ0;
 
-	page_num = addr >> 11; /* addr / 2048 */
+	page_num = block512 >> 2; /* 512 block -> 2048 block */
 	/* Write Address */
 	NFADDR = 0;
 	NFADDR = 0;
@@ -108,17 +109,18 @@ static int nand_read_page_ll(unsigned char *buf, unsigned long addr)
 		*p16++ = NFDATA16;
 	}
 #endif
-	return NAND_PAGE_SIZE;
+	return 4;
 }
 
 /* low level nand read function */
-int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
+int nand_read_ll(unsigned char *buf, unsigned long start_block512,
+								  int blocks512)
 {
 	int i, j;
 	int bad_count = 0;
 
-	if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK))
-		return -1;	/* invalid alignment */
+	if (start_block512 & 3) /* inside 2048-byte block */
+		return -1;
 
 	/* chip Enable */
 	nand_select();
@@ -127,22 +129,20 @@ int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
 	for (i = 0; i < 10; i++)
 		;
 
-	for (i = start_addr; i < (start_addr + size);) {
-		if ((i & (NAND_BLOCK_SIZE - 1)) == 0) {
-			if (is_bad_block(i) ||
-					is_bad_block(i + NAND_PAGE_SIZE)) {
-				i += NAND_BLOCK_SIZE;
-				size += NAND_BLOCK_SIZE;
-				if (bad_count++ == 4)
-					return -1;
-
-				continue;
-			}
+	while (blocks512 > 0) {
+		if (is_bad_block(start_block512) ||
+				is_bad_block(start_block512 + 4)) {
+			start_block512 += 4;
+			blocks512 += 4;
+			if (bad_count++ == 4)
+				return -1;
+			continue;
 		}
 
-		j = nand_read_page_ll(buf, i);
-		i += j;
-		buf += j;
+		j = nand_read_page_ll(buf, start_block512);
+		start_block512 += j;
+		buf += j << 9;
+		blocks512 -= j;
 	}
 
 	/* chip Disable */
diff --git a/src/phase2.c b/src/phase2.c
index b2ad6a9..7543e49 100644
--- a/src/phase2.c
+++ b/src/phase2.c
@@ -48,6 +48,8 @@ void bootloader_second_phase(void)
 		void * kernel_dram = (void *)(TEXT_BASE - (8 * 1024 * 1024));
 		unsigned long crc;
 		image_header_t	*hdr;
+		unsigned long partition_offset_blocks = 0;
+		unsigned long partition_length_blocks = 0;
 
 		/* eat leading white space */
 		for (p = cmdline; *p == ' '; p++);
@@ -67,45 +69,67 @@ void bootloader_second_phase(void)
 		/* if there's a partition table implied, parse it, otherwise
 		 * just use a fixed offset
 		 */
-		if (this_board->kernel_source[kernel].partition_index != -1) {
+		if (this_board->kernel_source[kernel].partition_index) {
+			unsigned char *p = kernel_dram;
 
-			puts("partitions not supported yet\n");
-			kernel++;
-			continue;
-
-		} else {
 			if (this_board->kernel_source[kernel].block_read(
-				kernel_dram, this_board->kernel_source[kernel].
-					    offset_if_no_partition, 4096) < 0) {
-				puts ("Bad kernel header\n");
+						       kernel_dram, 0, 4) < 0) {
+				puts("Bad partition read\n");
 				kernel++;
 				continue;
 			}
 
-			hdr = (image_header_t *)kernel_dram;
-
-			if (_ntohl(hdr->ih_magic) != IH_MAGIC) {
-				puts("bad magic ");
-				print32(hdr->ih_magic);
+			if ((p[0x1fe] != 0x55) || (p[0x1ff] != 0xaa)) {
+				puts("partition signature missing\n");
 				kernel++;
 				continue;
 			}
 
-			puts("        Found: ");
-			puts((const char *)hdr->ih_name);
-			puts("\n         Size: ");
-			printdec(_ntohl(hdr->ih_size) >> 10);
-			puts(" KiB\n");
-
-			if (nand_read_ll(kernel_dram,
-				this_board->kernel_source[kernel].
-				offset_if_no_partition, (_ntohl(hdr->ih_size) +
-						sizeof(image_header_t) + 2048) &
-							     ~(2048 - 1)) < 0) {
-				puts ("Bad kernel read\n");
-				kernel++;
-				continue;
-			}
+			p += 0x1be + 8 + (0x10 * (this_board->
+				    kernel_source[kernel].partition_index - 1));
+
+			partition_offset_blocks = (((u32)p[3]) << 24) |
+						  (((u32)p[2]) << 16) |
+						  (((u32)p[1]) << 8) |
+						  p[0];
+			partition_length_blocks = (((u32)p[7]) << 24) |
+						  (((u32)p[6]) << 16) |
+						  (((u32)p[5]) << 8) |
+						  p[4];
+
+		} else
+			partition_offset_blocks = this_board->
+				   kernel_source[kernel].offset_if_no_partition;
+
+		if (this_board->kernel_source[kernel].block_read(
+				 kernel_dram, partition_offset_blocks, 8) < 0) {
+			puts ("Bad kernel header\n");
+			kernel++;
+			continue;
+		}
+
+		hdr = (image_header_t *)kernel_dram;
+
+		if (_ntohl(hdr->ih_magic) != IH_MAGIC) {
+			puts("bad magic ");
+			print32(hdr->ih_magic);
+			kernel++;
+			continue;
+		}
+
+		puts("        Found: ");
+		puts((const char *)hdr->ih_name);
+		puts("\n         Size: ");
+		printdec(_ntohl(hdr->ih_size) >> 10);
+		puts(" KiB\n");
+
+		if ((this_board->kernel_source[kernel].block_read)(
+			kernel_dram, partition_offset_blocks,
+			((_ntohl(hdr->ih_size) + sizeof(image_header_t) +
+					       2048) & ~(2048 - 1)) >> 9) < 0) {
+			puts ("Bad kernel read\n");
+			kernel++;
+			continue;
 		}
 
 		puts("      Cmdline: ");
diff --git a/src/start_qi.c b/src/start_qi.c
index f5c0223..3d993fd 100644
--- a/src/start_qi.c
+++ b/src/start_qi.c
@@ -60,7 +60,7 @@ void start_qi(void)
 	 */
 
 	/* We randomly pull 24KBytes of bootloader */
-	if (nand_read_ll((unsigned char *)TEXT_BASE, 0, 24 * 1024) < 0)
+	if (nand_read_ll((unsigned char *)TEXT_BASE, 0, 24 * 1024 / 512) < 0)
 		goto unhappy;
 
 	/* ask all the boards we support in turn if they recognize this
diff --git a/src/utils.c b/src/utils.c
index 11b1675..62f7c17 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -54,6 +54,11 @@ unsigned int _ntohl(unsigned int n) {
 			       ((n & 0xff0000) >> 8) | ((n & 0xff000000) >> 24);
 }
 
+unsigned int _letocpu(unsigned int n) {
+	return n;
+}
+
+
 int puts(const char *string)
 {
 	while (*string)




More information about the openmoko-kernel mailing list