From 015aed13171ff6201459286e15fc5e0686a46907 Mon Sep 17 00:00:00 2001 From: juhosg Date: Wed, 11 Jul 2007 13:00:27 +0000 Subject: [adm5120] refactor kernel code (part 1), mark it as broken now git-svn-id: svn://svn.openwrt.org/openwrt/trunk@7916 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../adm5120-2.6/files/arch/mips/adm5120/trxsplit.c | 219 +++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 target/linux/adm5120-2.6/files/arch/mips/adm5120/trxsplit.c (limited to 'target/linux/adm5120-2.6/files/arch/mips/adm5120/trxsplit.c') diff --git a/target/linux/adm5120-2.6/files/arch/mips/adm5120/trxsplit.c b/target/linux/adm5120-2.6/files/arch/mips/adm5120/trxsplit.c new file mode 100644 index 0000000000..0377892d3f --- /dev/null +++ b/target/linux/adm5120-2.6/files/arch/mips/adm5120/trxsplit.c @@ -0,0 +1,219 @@ +/* + * $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_master = NULL; +static struct mtd_info *trx_mtds[TRX_MAX_OFFSET]; +static struct mtd_partition trx_parts[TRX_MAX_OFFSET]; +static struct trx_header trx_hdr; +static int trx_nr_parts = 0; +static int trx_rootfs_part = -1; + +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) + goto err_out; + + if (retlen != sizeof(trx_hdr)) + 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 1; + +err_out: + return 0; +} + +static void __init trxsplit_create_partitions(struct mtd_info *mtd, + unsigned long offset) +{ + struct mtd_partition *part = trx_parts; + int i; + + for (i=0;ioffset = offset + trx_hdr.offsets[i]; + part->mtdp = &trx_mtds[trx_nr_parts]; + 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 = "trx_loader"; + i++; + } + + part = &trx_parts[i]; + part->name = "trx_kernel"; + i++; + + part = &trx_parts[i]; + part->name = "trx_rootfs"; + trx_rootfs_part = i; +} + +static void __init trxsplit_add_mtd(struct mtd_info *mtd) +{ + unsigned long offset; + unsigned long blocklen; + int found; + + if (trx_mtd_master) + 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); + + found = 0; + for (offset=0; offset < mtd->size; offset+=blocklen) { + found = trxsplit_checktrx(mtd, offset); + if (found) + break; + } + + if (found == 0) { + printk(KERN_ALERT PFX "no TRX header found\n"); + return; + } + + printk(KERN_INFO PFX "TRX header found at 0x%lX\n", offset); + + trxsplit_create_partitions(mtd, offset); + + trx_mtd_master = mtd; +} + +static void trxsplit_remove_mtd(struct mtd_info *mtd) +{ +} + +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 err; + int i; + + trxsplit_find_trx(); + + if (trx_mtd_master == NULL) + goto err; + + printk(KERN_INFO PFX "creating TRX partitions in '%s'\n", + trx_mtd_master->name); + + err = add_mtd_partitions(trx_mtd_master, trx_parts, trx_nr_parts); + if (err) { + printk(KERN_ALERT PFX "creating TRX partitions failed\n"); + goto err; + } + + for (i=0; i= 0) { + printk(KERN_INFO PFX "set '%s' to be root filesystem\n", + trx_mtds[trx_rootfs_part]->name); + ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, trx_mtds[trx_rootfs_part]->index); + } + + return 0; + +err: + return -1; +} + +late_initcall(trxsplit_init); -- cgit v1.2.3