From: Gabor Juhos Date: Mon, 1 Oct 2007 09:51:32 +0000 (+0000) Subject: [adm5120] prepare trxsplit to support sysupgrade X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=8d1c94836c2d9d2564d8d12cdf5d5778d4920394;p=openwrt%2Fsvn-archive%2Farchive.git [adm5120] prepare trxsplit to support sysupgrade SVN-Revision: 9085 --- diff --git a/target/linux/adm5120/files/arch/mips/adm5120/Makefile b/target/linux/adm5120/files/arch/mips/adm5120/Makefile index 583d1d12c1..2a5f391f25 100644 --- a/target/linux/adm5120/files/arch/mips/adm5120/Makefile +++ b/target/linux/adm5120/files/arch/mips/adm5120/Makefile @@ -9,5 +9,3 @@ obj-y += gpio.o obj-y += platform.o obj-y += reset.o obj-y += time.o - -obj-y += trxsplit.o diff --git a/target/linux/adm5120/files/arch/mips/adm5120/trxsplit.c b/target/linux/adm5120/files/arch/mips/adm5120/trxsplit.c deleted file mode 100644 index 941f306950..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/trxsplit.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * $Id$ - * - * Copyright (C) 2007 OpenWrt.org - * Copyright (C) Gabor Juhos - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#define PFX "trxsplit: " - -#define TRX_MAGIC 0x30524448 /* "HDR0" */ -#define TRX_VERSION 1 -#define TRX_MAX_LEN 0x3A0000 -#define TRX_NO_HEADER 1 /* Do not write TRX header */ -#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */ -#define TRX_MAX_OFFSET 3 -#define TRX_MIN_KERNEL_SIZE 256*1024 - -struct trx_header { - u32 magic; /* "HDR0" */ - u32 len; /* Length of file including header */ - u32 crc32; /* 32-bit CRC from flag_version to end of file */ - u32 flag_version; /* 0:15 flags, 16:31 version */ - u32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */ -}; - -#define BLOCK_LEN_MIN 0x10000 - -static struct mtd_info *trx_mtd = NULL; -static unsigned long trx_offset = 0; -static int trx_nr_parts = 0; -static struct mtd_partition trx_parts[TRX_MAX_OFFSET]; -static struct trx_header trx_hdr; - -static int __init trxsplit_checktrx(struct mtd_info *mtd, unsigned long offset) -{ - size_t retlen; - int err; - - err = mtd->read(mtd, offset, sizeof(trx_hdr), &retlen, (void *)&trx_hdr); - if (err) { - printk(KERN_ALERT PFX "unable to read from '%s'\n", mtd->name); - goto err_out; - } - - if (retlen != sizeof(trx_hdr)) { - printk(KERN_ALERT PFX "reading failed on '%s'\n", mtd->name); - goto err_out; - } - - trx_hdr.magic = le32_to_cpu(trx_hdr.magic); - trx_hdr.len = le32_to_cpu(trx_hdr.len); - trx_hdr.crc32 = le32_to_cpu(trx_hdr.crc32); - trx_hdr.flag_version = le32_to_cpu(trx_hdr.flag_version); - trx_hdr.offsets[0] = le32_to_cpu(trx_hdr.offsets[0]); - trx_hdr.offsets[1] = le32_to_cpu(trx_hdr.offsets[1]); - trx_hdr.offsets[2] = le32_to_cpu(trx_hdr.offsets[2]); - - /* sanity checks */ - if (trx_hdr.magic != TRX_MAGIC) - goto err_out; - - if (trx_hdr.len > mtd->size - offset) - goto err_out; - - /* TODO: add crc32 checking too? */ - - return 0; - -err_out: - return -1; -} - -static int __init trxsplit_create_partitions(void) -{ - struct mtd_partition *part = trx_parts; - int ret = 0; - int i; - - if (trx_mtd == NULL) - goto out; - - printk(KERN_INFO PFX "creating TRX partitions in '%s' (%d,%d)\n", - trx_mtd->name, MTD_BLOCK_MAJOR, trx_mtd->index); - - for (i=0; ioffset = trx_offset + trx_hdr.offsets[i]; - trx_nr_parts++; - } - - for (i=0; isize - trx_parts[i].offset; - - i=0; - part = &trx_parts[i]; - if (part->size < TRX_MIN_KERNEL_SIZE) { - part->name = "loader"; - i++; - } - - part = &trx_parts[i]; - part->name = "kernel"; - i++; - - part = &trx_parts[i]; - part->name = "rootfs"; - - ret = add_mtd_partitions(trx_mtd, trx_parts, trx_nr_parts); - if (ret) { - printk(KERN_ALERT PFX "creating TRX partitions failed\n"); - } - -out: - return ret; -} - -static void __init trxsplit_add_mtd(struct mtd_info *mtd) -{ - unsigned long offset; - unsigned long blocklen; - int err; - - if (trx_mtd) - return; - - blocklen = mtd->erasesize; - if (blocklen < BLOCK_LEN_MIN) - blocklen = BLOCK_LEN_MIN; - - printk(KERN_INFO PFX "searching TRX header in '%s'\n", mtd->name); - - err = 0; - for (offset=0; offset < mtd->size; offset+=blocklen) { - err = trxsplit_checktrx(mtd, offset); - if (err == 0) - break; - } - - if (err) { - printk(KERN_ALERT PFX "no TRX header found\n"); - return; - } - - printk(KERN_INFO PFX "TRX header found at 0x%lX\n", offset); - - trx_mtd = mtd; - trx_offset = offset; -} - -static void __init trxsplit_remove_mtd(struct mtd_info *mtd) -{ - /* nothing to do */ -} - -static struct mtd_notifier trxsplit_notifier __initdata = { - .add = trxsplit_add_mtd, - .remove = trxsplit_remove_mtd, -}; - -static void __init trxsplit_find_trx(void) -{ - register_mtd_user(&trxsplit_notifier); - unregister_mtd_user(&trxsplit_notifier); -} - -static int __init trxsplit_init(void) -{ - int ret; - - trxsplit_find_trx(); - - ret = trxsplit_create_partitions(); - return ret; -} - -late_initcall(trxsplit_init); diff --git a/target/linux/adm5120/files/drivers/mtd/trxsplit.c b/target/linux/adm5120/files/drivers/mtd/trxsplit.c new file mode 100644 index 0000000000..ad0e25a113 --- /dev/null +++ b/target/linux/adm5120/files/drivers/mtd/trxsplit.c @@ -0,0 +1,227 @@ +/* + * $Id$ + * + * Copyright (C) 2007 OpenWrt.org + * Copyright (C) Gabor Juhos + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define PFX "trxsplit: " + +#define TRX_MAGIC 0x30524448 /* "HDR0" */ +#define TRX_VERSION 1 +#define TRX_MAX_LEN 0x3A0000 +#define TRX_NO_HEADER 1 /* Do not write TRX header */ +#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */ +#define TRX_MAX_OFFSET 3 +#define TRX_MIN_KERNEL_SIZE 256*1024 + +struct trx_header { + u32 magic; /* "HDR0" */ + u32 len; /* Length of file including header */ + u32 crc32; /* 32-bit CRC from flag_version to end of file */ + u32 flag_version; /* 0:15 flags, 16:31 version */ + u32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */ +}; + +#define BLOCK_LEN_MIN 0x10000 + +static struct mtd_info *trx_mtd = NULL; +static unsigned long trx_offset = 0; +static int trx_nr_parts = 0; +static struct mtd_partition trx_parts[TRX_MAX_OFFSET]; +static struct trx_header trx_hdr; + +static int trxsplit_refresh_partitions(struct mtd_info *mtd); + +static int trxsplit_checktrx(struct mtd_info *mtd, unsigned long offset) +{ + size_t retlen; + int err; + + err = mtd->read(mtd, offset, sizeof(trx_hdr), &retlen, (void *)&trx_hdr); + if (err) { + printk(KERN_ALERT PFX "unable to read from '%s'\n", mtd->name); + goto err_out; + } + + if (retlen != sizeof(trx_hdr)) { + printk(KERN_ALERT PFX "reading failed on '%s'\n", mtd->name); + goto err_out; + } + + trx_hdr.magic = le32_to_cpu(trx_hdr.magic); + trx_hdr.len = le32_to_cpu(trx_hdr.len); + trx_hdr.crc32 = le32_to_cpu(trx_hdr.crc32); + trx_hdr.flag_version = le32_to_cpu(trx_hdr.flag_version); + trx_hdr.offsets[0] = le32_to_cpu(trx_hdr.offsets[0]); + trx_hdr.offsets[1] = le32_to_cpu(trx_hdr.offsets[1]); + trx_hdr.offsets[2] = le32_to_cpu(trx_hdr.offsets[2]); + + /* sanity checks */ + if (trx_hdr.magic != TRX_MAGIC) + goto err_out; + + if (trx_hdr.len > mtd->size - offset) + goto err_out; + + /* TODO: add crc32 checking too? */ + + return 0; + +err_out: + return -1; +} + +static void trxsplit_findtrx(struct mtd_info *mtd) +{ + unsigned long offset; + unsigned long blocklen; + int err; + + blocklen = mtd->erasesize; + if (blocklen < BLOCK_LEN_MIN) + blocklen = BLOCK_LEN_MIN; + + printk(KERN_INFO PFX "searching TRX header in '%s'\n", mtd->name); + + err = 0; + for (offset=0; offset < mtd->size; offset+=blocklen) { + err = trxsplit_checktrx(mtd, offset); + if (err == 0) + break; + } + + if (err) + return; + + printk(KERN_INFO PFX "TRX header found at 0x%lX\n", offset); + + trx_mtd = mtd; + trx_offset = offset; +} + +static void trxsplit_create_partitions(struct mtd_info *mtd) +{ + struct mtd_partition *part = trx_parts; + int err; + int i; + + for (i=0; ioffset = trx_offset + trx_hdr.offsets[i]; + trx_nr_parts++; + } + + for (i=0; isize - trx_parts[i].offset; + + i=0; + part = &trx_parts[i]; + if (part->size < TRX_MIN_KERNEL_SIZE) { + part->name = "loader"; + i++; + } + + part = &trx_parts[i]; + part->name = "kernel"; + i++; + + part = &trx_parts[i]; + part->name = "rootfs"; + + err = add_mtd_partitions(mtd, trx_parts, trx_nr_parts); + if (err) { + printk(KERN_ALERT PFX "adding TRX partitions failed\n"); + return; + } + + mtd->refresh_device = trxsplit_refresh_partitions; +} + +static int trxsplit_refresh_partitions(struct mtd_info *mtd) +{ + printk(KERN_INFO PFX "refreshing TRX partitions in '%s' (%d,%d)\n", + mtd->name, MTD_BLOCK_MAJOR, mtd->index); + + /* remove old partitions */ + del_mtd_partitions(mtd); + + trxsplit_findtrx(mtd); + if (!trx_mtd) + goto err; + + trxsplit_create_partitions(trx_mtd); + return 1; + +err: + return 0; +} + +static void __init trxsplit_add_mtd(struct mtd_info *mtd) +{ + if (!trx_mtd) + trxsplit_findtrx(mtd); +} + +static void __init trxsplit_remove_mtd(struct mtd_info *mtd) +{ + /* nothing to do */ +} + +static struct mtd_notifier trxsplit_notifier __initdata = { + .add = trxsplit_add_mtd, + .remove = trxsplit_remove_mtd, +}; + +static void __init trxsplit_scan(void) +{ + register_mtd_user(&trxsplit_notifier); + unregister_mtd_user(&trxsplit_notifier); +} + +static int __init trxsplit_init(void) +{ + trxsplit_scan(); + + if (trx_mtd) { + printk(KERN_INFO PFX "creating TRX partitions in '%s' (%d,%d)\n", + trx_mtd->name, MTD_BLOCK_MAJOR, trx_mtd->index); + trxsplit_create_partitions(trx_mtd); + } + + return 0; +} + +late_initcall(trxsplit_init); diff --git a/target/linux/adm5120/patches-2.6.22/103-mtd_trxsplit.patch b/target/linux/adm5120/patches-2.6.22/103-mtd_trxsplit.patch new file mode 100644 index 0000000000..c623bc42e4 --- /dev/null +++ b/target/linux/adm5120/patches-2.6.22/103-mtd_trxsplit.patch @@ -0,0 +1,28 @@ +Index: linux-2.6.22.4/drivers/mtd/Kconfig +=================================================================== +--- linux-2.6.22.4.orig/drivers/mtd/Kconfig ++++ linux-2.6.22.4/drivers/mtd/Kconfig +@@ -57,6 +57,11 @@ config MTD_ROOTFS_SPLIT + depends on MTD_PARTITIONS + default y + ++config MTD_TRXSPLIT ++ bool "Automatically find and split TRX partitions" ++ depends on MTD_PARTITIONS ++ default n ++ + config MTD_REDBOOT_PARTS + tristate "RedBoot partition table parsing" + depends on MTD_PARTITIONS +Index: linux-2.6.22.4/drivers/mtd/Makefile +=================================================================== +--- linux-2.6.22.4.orig/drivers/mtd/Makefile ++++ linux-2.6.22.4/drivers/mtd/Makefile +@@ -8,6 +8,7 @@ mtd-$(CONFIG_MTD_PARTITIONS) += mtdpart. + obj-$(CONFIG_MTD) += $(mtd-y) + + obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o ++obj-$(CONFIG_MTD_TRXSPLIT) += trxsplit.o + obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o + obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o + obj-$(CONFIG_MTD_AFS_PARTS) += afs.o diff --git a/target/linux/adm5120/router_be/config-2.6.22 b/target/linux/adm5120/router_be/config-2.6.22 index 85aad4ea71..43476e2321 100644 --- a/target/linux/adm5120/router_be/config-2.6.22 +++ b/target/linux/adm5120/router_be/config-2.6.22 @@ -164,6 +164,7 @@ CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_REDBOOT_PARTS is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_SLRAM is not set +CONFIG_MTD_TRXSPLIT=y CONFIG_NETDEV_1000=y CONFIG_NET_KEY=y # CONFIG_NET_PCI is not set diff --git a/target/linux/adm5120/router_le/config-2.6.22 b/target/linux/adm5120/router_le/config-2.6.22 index c67e1404c6..a331c2a134 100644 --- a/target/linux/adm5120/router_le/config-2.6.22 +++ b/target/linux/adm5120/router_le/config-2.6.22 @@ -123,7 +123,7 @@ CONFIG_MTD=y CONFIG_MTD_ADM5120=y CONFIG_MTD_BLKDEVS=y CONFIG_MTD_BLOCK=y -CONFIG_MTD_BLOCK2MTD=y +# CONFIG_MTD_BLOCK2MTD is not set CONFIG_MTD_CFI=y # CONFIG_MTD_CFI_ADV_OPTIONS is not set CONFIG_MTD_CFI_AMDSTD=y @@ -174,6 +174,7 @@ CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_REDBOOT_PARTS is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_SLRAM is not set +CONFIG_MTD_TRXSPLIT=y # CONFIG_NETDEV_1000 is not set CONFIG_NET_KEY=y # CONFIG_NET_PCI is not set