--- zzzz-none-000/linux-2.4.17/drivers/mtd/bootldr.c 2001-10-04 22:14:44.000000000 +0000 +++ sangam-fb-322/linux-2.4.17/drivers/mtd/bootldr.c 2004-11-24 13:22:49.000000000 +0000 @@ -3,7 +3,7 @@ * * Copyright 2001 Compaq Computer Corporation. * - * $Id: bootldr.c,v 1.6 2001/10/02 15:05:11 dwmw2 Exp $ + * $Id: bootldr.c,v 1.1.1.1 2003/06/23 22:18:28 jharrell Exp $ * * Use consistent with the GNU GPL is permitted, * provided that this copyright notice is @@ -27,48 +27,149 @@ #include #include -#define FLASH_PARTITION_NAMELEN 32 enum LFR_FLAGS { - LFR_SIZE_PREFIX = 1, /* prefix data with 4-byte size */ - LFR_PATCH_BOOTLDR = 2, /* patch bootloader's 0th instruction */ - LFR_KERNEL = 4, /* add BOOTIMG_MAGIC, imgsize and VKERNEL_BASE to head of programmed region (see bootldr.c) */ - LFR_EXPAND = 8 /* expand partition size to fit rest of flash */ + LFR_SIZE_PREFIX = 1, /* prefix data with 4-byte size */ + LFR_PATCH_BOOTLDR = 2, /* patch bootloader's 0th instruction */ + LFR_KERNEL = 4, /* add BOOTIMG_MAGIC, imgsize and VKERNEL_BASE to head of programmed region (see bootldr.c) */ + LFR_EXPAND = 8 /* expand partition size to fit rest of flash */ }; // the tags are parsed too early to malloc or alloc_bootmem so we'll fix it // for now -#define MAX_NUM_PARTITIONS 8 -typedef struct FlashRegion { - char name[FLASH_PARTITION_NAMELEN]; - unsigned long base; - unsigned long size; - enum LFR_FLAGS flags; -} FlashRegion; - -typedef struct BootldrFlashPartitionTable { - int magic; /* should be filled with 0x646c7470 (btlp) BOOTLDR_PARTITION_MAGIC */ - int npartitions; - struct FlashRegion partition[8]; -} BootldrFlashPartitionTable; - -#define BOOTLDR_MAGIC 0x646c7462 /* btld: marks a valid bootldr image */ -#define BOOTLDR_PARTITION_MAGIC 0x646c7470 /* btlp: marks a valid bootldr partition table in params sector */ - -#define BOOTLDR_MAGIC_OFFSET 0x20 /* offset 0x20 into the bootldr */ -#define BOOTCAP_OFFSET 0X30 /* offset 0x30 into the bootldr */ - -#define BOOTCAP_WAKEUP (1<<0) -#define BOOTCAP_PARTITIONS (1<<1) /* partition table stored in params sector */ -#define BOOTCAP_PARAMS_AFTER_BOOTLDR (1<<2) /* params sector right after bootldr sector(s), else in last sector */ -static struct BootldrFlashPartitionTable Table; -static struct BootldrFlashPartitionTable *partition_table = NULL; +static struct tag_ptable Table; +static struct tag_ptable *partition_table = NULL; +static char cmdline[1024]; +/* + * Format suggested by Nicolas Pitre: mtdpart=@:[,@:[,...]] + */ +static int parse_mtdpart(char *cmdline, struct mtd_info *master, struct mtd_partition **pparts) +{ + int npartitions = 0; + int i; + int base; + int size; + int last_base = 0; + int last_size = 0; + char *start = cmdline; + + struct mtd_partition *parts; + int namelen = 0; + char *names; + int ret = 0; + + // printk(__FUNCTION__ "{%s}\n", cmdline); + while (1) { + char *comma_pos = strchr(start, ','); + char *at_pos; + char *colon_pos; + npartitions++; + + if (comma_pos) + *comma_pos = 0; + + at_pos = strchr(start, '@'); + colon_pos = strchr(start, ':'); + if (at_pos) *at_pos = 0; + if (colon_pos) *at_pos = 0; + + if (*start) { + namelen += strlen(start); + } else { + // mtdpartNNN + namelen += 12; + } + + /* restore the separators */ + if (at_pos) *at_pos = '@'; + if (colon_pos) *at_pos = ':'; + if (comma_pos) { + start = comma_pos + 1; + *comma_pos = ','; + } else { + break; + } + } + + if (npartitions == 0) + return 0; + + start = cmdline; + + // printk("npartitions=%d\n", npartitions); + + parts = kmalloc(sizeof(*parts)*npartitions + namelen, GFP_KERNEL); + if (!parts) { + ret = -ENOMEM; + goto out; + } + names = (char *)&parts[npartitions]; + memset(parts, 0, sizeof(*parts)*npartitions + namelen); + + // now fill in the partition info + for (i = 0; i < npartitions; i++) { + char *comma_pos = strchr(start, ','); + char *at_pos; + char *colon_pos; + char *name = start; + char defaultname[32] = "mtdpartXXX"; + + if (comma_pos) + *comma_pos = 0; + + at_pos = strchr(start, '@'); + // printk(" at_pos=%s\n", at_pos); + colon_pos = strchr(start, ':'); + // printk(" colon_pos=%s\n", colon_pos); + + if (at_pos) *at_pos = 0; + if (colon_pos) *colon_pos = 0; + if (at_pos == start || colon_pos == start) { + // use default name + sprintf(defaultname, "mtdpart%d", i); + name = defaultname; + } + if (at_pos) + base = simple_strtoul(at_pos+1, NULL, 0); + else + base = last_base + last_size; + if (colon_pos) + size = simple_strtoul(colon_pos+1, NULL, 0); + else + size = 0; + + parts[i].name = names; + names += strlen(name) + 1; + strcpy(parts[i].name, name); + + parts[i].size = size; + parts[i].offset = base; + parts[i].mask_flags = 0; + + // printk(" partition %s o=%x s=%x\n", + // parts[i].name, parts[i].offset, parts[i].size); + + last_base = base; + last_size = size; + if (comma_pos) { + start = comma_pos + 1; + } + } + + ret = npartitions; + *pparts = parts; + + out: + + return ret; +} int parse_bootldr_partitions(struct mtd_info *master, struct mtd_partition **pparts) { struct mtd_partition *parts; - int ret, retlen, i; + int ret = 0; + int retlen, i; int npartitions = 0; long partition_table_offset; long bootmagic = 0; @@ -77,53 +178,52 @@ char *names; -#if 0 - /* verify bootldr magic */ - ret = master->read(master, BOOTLDR_MAGIC_OFFSET, sizeof(long), &retlen, (void *)&bootmagic); - if (ret) - goto out; - if (bootmagic != BOOTLDR_MAGIC) - goto out; - /* see if bootldr supports partition tables and where to find the partition table */ - ret = master->read(master, BOOTCAP_OFFSET, sizeof(long), &retlen, (void *)&bootcap); - if (ret) - goto out; - - if (!(bootcap & BOOTCAP_PARTITIONS)) - goto out; - if (bootcap & BOOTCAP_PARAMS_AFTER_BOOTLDR) - partition_table_offset = master->erasesize; - else - partition_table_offset = master->size - master->erasesize; - - printk(__FUNCTION__ ": partition_table_offset=%#lx\n", partition_table_offset); - printk(__FUNCTION__ ": ptable_addr=%#lx\n", ptable_addr); + if (cmdline[0] != 0) { + return parse_mtdpart(cmdline, master, pparts); + } + + /* if we did not receive a partition table from the bootldr, then try to read one from flash */ + if (!partition_table) { + /* verify bootldr magic */ + ret = master->read(master, BOOTLDR_MAGIC_OFFSET, sizeof(long), &retlen, (void *)&bootmagic); + if (ret) + goto out; + if (bootmagic != BOOTLDR_MAGIC) + goto out; + /* see if bootldr supports partition tables and where to find the partition table */ + ret = master->read(master, BOOTCAP_OFFSET, sizeof(long), &retlen, (void *)&bootcap); + if (ret) + goto out; + + if (!(bootcap & BOOTCAP_PARTITIONS)) + goto out; + if (bootcap & BOOTCAP_PARAMS_AFTER_BOOTLDR) + partition_table_offset = master->erasesize; + else + partition_table_offset = master->size - master->erasesize; + /* Read the partition table */ + partition_table = (struct tag_ptable *)kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!partition_table) + return -ENOMEM; + + ret = master->read(master, partition_table_offset, + PAGE_SIZE, &retlen, (void *)partition_table); + if (ret) + goto out; + } - /* Read the partition table */ - partition_table = (struct BootldrFlashPartitionTable *)kmalloc(PAGE_SIZE, GFP_KERNEL); if (!partition_table) - return -ENOMEM; - - ret = master->read(master, partition_table_offset, - PAGE_SIZE, &retlen, (void *)partition_table); - if (ret) - goto out; - -#endif - if (!partition_table) - return -ENOMEM; - + return -ENOMEM; printk(__FUNCTION__ ": magic=%#x\n", partition_table->magic); printk(__FUNCTION__ ": numPartitions=%#x\n", partition_table->npartitions); - /* check for partition table magic number */ if (partition_table->magic != BOOTLDR_PARTITION_MAGIC) goto out; npartitions = (partition_table->npartitions > MAX_NUM_PARTITIONS)? - MAX_NUM_PARTITIONS:partition_table->npartitions; + MAX_NUM_PARTITIONS:partition_table->npartitions; printk(__FUNCTION__ ": npartitions=%#x\n", npartitions); @@ -140,19 +240,16 @@ memset(parts, 0, sizeof(*parts)*npartitions + namelen); - // from here we use the partition table for (i = 0; i < npartitions; i++) { - struct FlashRegion *partition = &partition_table->partition[i]; + struct bootldr_flash_region *partition = &partition_table->partition[i]; const char *name = partition->name; parts[i].name = names; names += strlen(name) + 1; - strcpy(parts[i].name, name); + strncpy(parts[i].name, name, BOOTLDR_PARTITION_NAMELEN); - if (partition->flags & LFR_EXPAND) - parts[i].size = MTDPART_SIZ_FULL; - else - parts[i].size = partition->size; + // We rely on the bootloader to do partition expansion + parts[i].size = partition->size; parts[i].offset = partition->base; parts[i].mask_flags = 0; @@ -174,40 +271,77 @@ } +#if 1 static int __init parse_tag_ptable(const struct tag *tag) { - char buf[128]; - int i; - int j; - - partition_table = &Table; +#ifdef CONFIG_DEBUG_LL + int i; +#endif + struct tag_ptable *ptable = (struct tag_ptable *)(&tag->u); + int npartitions = ptable->npartitions; + + partition_table = &Table; #ifdef CONFIG_DEBUG_LL - sprintf(buf,"ptable: magic = = 0x%lx npartitions= %d \n", - tag->u.ptable.magic,tag->u.ptable.npartitions); - printascii(buf); + printk("ptable: magic = 0x%x npartitions= %d \n", + ptable->magic,ptable->npartitions); - for (i=0; iu.ptable.npartitions; i++){ - sprintf(buf,"ptable: partition name = %s base= 0x%lx size= 0x%lx flags= 0x%lx\n", - (char *) (&tag->u.ptable.partition[i].name[0]), - tag->u.ptable.partition[i].base, - tag->u.ptable.partition[i].size, - tag->u.ptable.partition[i].flags); - printascii(buf); - } + for (i=0; inpartitions; i++){ + printk("ptable: partition name = %s base= 0x%x size= 0x%x flags= 0x%x\n", + (char *) (&ptable->partition[i].name[0]), + ptable->partition[i].base, + ptable->partition[i].size, + ptable->partition[i].flags); + + } #endif - memcpy((void *)partition_table,(void *) (&(tag->u.ptable)),sizeof(partition_table) + - sizeof(struct FlashRegion)*tag->u.ptable.npartitions); + if ( npartitions > MAX_NUM_PARTITIONS ) { + printk(__FUNCTION__ ": Too many partitions (%d), trimming to %d\n", + npartitions, MAX_NUM_PARTITIONS); + npartitions = MAX_NUM_PARTITIONS; + } + memcpy((void *)partition_table,(void *) ptable, + (sizeof(partition_table) + sizeof(struct bootldr_flash_region)*npartitions)); - return 0; + return 0; } -__tagtable(ATAG_PTABLE, parse_tag_ptable); +__tagtable(ATAG_PTABLE_COMPAT, parse_tag_ptable); +#endif -EXPORT_SYMBOL(parse_bootldr_partitions); +/* + * Format suggested by Nicolas Pitre: mtdpart=@:[,@:[,...]] + */ +static int handle_mtdpart(char *mtdpart) +{ + strcpy(cmdline, mtdpart); + return 1; +} +#if 0 +__setup("mtdpart=", handle_mtdpart); +#endif + +static int handle_test(char *mtdpart) +{ + // kmalloc(size, GFP_KERNEL); does not work at this point during boot process + char *foo; + +#ifdef CONFIG_DEBUG_LL + printascii("calling alloc_pages\n"); +#endif + // foo = alloc_pages(GFP_KERNEL, 0); +#ifdef CONFIG_DEBUG_LL + printascii("done \n"); +#endif + return 1; +} + +__setup("test=", handle_test); + +EXPORT_SYMBOL(parse_bootldr_partitions); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Compaq Computer Corporation");