The WRT1900AC among other Linksys routers uses a dual-firmware layout. The bootloader passes the active rootfs in bootargs and also sets the rootfstype to jffs2 - which is clearly something we don't want. Rename both root= and rootfstype= variables to avoid issues and also use the former to dynamically rename the active partition to "ubi". Signed-off-by: Imre Kaloz --- a/arch/arm/boot/compressed/atags_to_fdt.c +++ b/arch/arm/boot/compressed/atags_to_fdt.c @@ -66,6 +66,18 @@ static uint32_t get_cell_size(const void return cell_size; } +static void mangle_bootargs(void *fdt, const char *fdt_cmdline) +{ + char *rootdev; + char *rootfs; + + rootdev = strstr(fdt_cmdline, "root=/dev/mtdblock"); + strncpy(rootdev, "uboot_active_root=", 18); + + rootfs = strstr(fdt_cmdline, "rootfstype"); + strncpy(rootfs, "origfstype", 10); +} + static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline) { char cmdline[COMMAND_LINE_SIZE]; @@ -135,6 +147,9 @@ int atags_to_fdt(void *atag_list, void * for_each_tag(atag, atag_list) { if (atag->hdr.tag == ATAG_CMDLINE) { + /* Rename the original root= and rootfstype= options */ + mangle_bootargs(fdt, + atag->u.cmdline.cmdline); /* Append the ATAGS command line to the device tree * command line. * NB: This means that if the same parameter is set in --- a/arch/arm/boot/compressed/string.c +++ b/arch/arm/boot/compressed/string.c @@ -111,6 +111,53 @@ char *strchr(const char *s, int c) return (char *)s; } +/** + * strncpy - Copy a length-limited, %NUL-terminated string + * @dest: Where to copy the string to + * @src: Where to copy the string from + * @count: The maximum number of bytes to copy + * + * The result is not %NUL-terminated if the source exceeds + * @count bytes. + * + * In the case where the length of @src is less than that of + * count, the remainder of @dest will be padded with %NUL. + * + */ +char *strncpy(char *dest, const char *src, size_t count) +{ + char *tmp = dest; + + while (count) { + if ((*tmp = *src) != 0) + src++; + tmp++; + count--; + } + return dest; +} + +/** + * strstr - Find the first substring in a %NUL terminated string + * @s1: The string to be searched + * @s2: The string to search for + */ +char *strstr(const char *s1, const char *s2) +{ + size_t l1, l2; + + l2 = strlen(s2); + if (!l2) + return (char *)s1; + l1 = strlen(s1); + while (l1 >= l2) { + l1--; + if (!memcmp(s1, s2, l2)) + return (char *)s1; + s1++; + } + return NULL; +} #undef memset void *memset(void *s, int c, size_t count) --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c @@ -25,12 +25,15 @@ static bool node_has_compatible(struct d return of_get_property(pp, "compatible", NULL); } +static int uboot_active_root; + static int parse_ofpart_partitions(struct mtd_info *master, struct mtd_partition **pparts, struct mtd_part_parser_data *data) { struct device_node *node; const char *partname; + const char *owrtpart = "ubi"; struct device_node *pp; int nr_parts, i; @@ -78,9 +81,15 @@ static int parse_ofpart_partitions(struc (*pparts)[i].offset = of_read_number(reg, a_cells); (*pparts)[i].size = of_read_number(reg + a_cells, s_cells); - partname = of_get_property(pp, "label", &len); - if (!partname) - partname = of_get_property(pp, "name", &len); + if (uboot_active_root && (i == uboot_active_root)) { + partname = owrtpart; + } else { + partname = of_get_property(pp, "label", &len); + + if (!partname) + partname = of_get_property(pp, "name", &len); + } + (*pparts)[i].name = partname; if (of_get_property(pp, "read-only", &len)) @@ -178,6 +187,18 @@ static int __init ofpart_parser_init(voi return 0; } +static int __init active_root(char *str) +{ + get_option(&str, &uboot_active_root); + + if (!uboot_active_root) + return 1; + + return 1; +} + +__setup("uboot_active_root=", active_root); + static void __exit ofpart_parser_exit(void) { deregister_mtd_parser(&ofpart_parser);