From cf52f51b85f1366f0124dda81e75b87badb13c50 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 7 Dec 2006 00:26:26 +0000 Subject: [PATCH] remove custom partition table hack, add ptgen utility for generating partition tables SVN-Revision: 5704 --- target/linux/rb532-2.6/config | 1 - target/linux/rb532-2.6/image/Makefile | 16 +- target/linux/rb532-2.6/image/gen_image.sh | 17 + .../patches/130-custom_partitions.patch | 311 ------------------ tools/firmware-utils/Makefile | 1 + tools/firmware-utils/src/ptgen.c | 219 ++++++++++++ 6 files changed, 238 insertions(+), 327 deletions(-) create mode 100755 target/linux/rb532-2.6/image/gen_image.sh delete mode 100644 target/linux/rb532-2.6/patches/130-custom_partitions.patch create mode 100644 tools/firmware-utils/src/ptgen.c diff --git a/target/linux/rb532-2.6/config b/target/linux/rb532-2.6/config index 2d2138261a..98474ad71a 100644 --- a/target/linux/rb532-2.6/config +++ b/target/linux/rb532-2.6/config @@ -1180,7 +1180,6 @@ CONFIG_CIFS=m # Partition Types # CONFIG_PARTITION_ADVANCED=y -CONFIG_OPENWRT_PARTITION=y # CONFIG_ACORN_PARTITION is not set # CONFIG_OSF_PARTITION is not set # CONFIG_AMIGA_PARTITION is not set diff --git a/target/linux/rb532-2.6/image/Makefile b/target/linux/rb532-2.6/image/Makefile index 4907214469..1f3a88ba40 100644 --- a/target/linux/rb532-2.6/image/Makefile +++ b/target/linux/rb532-2.6/image/Makefile @@ -39,9 +39,6 @@ define Image/BuildKernel $(CP) $(KDIR)/loader.elf $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-vmlinux endef -PARTITION1=\x80\x01\x01\x00\x27\x01\x20\x7b\x20\x00\x00\x00\xe0\x1e\x00\x00# 4 MB (kernel part) -PARTITION2=\x00\x00\x01\x7c\x83\x01\xa0\x64\x00\x1f\x00\x00\x40\x7a\x00\x00# 16 MB (rootfs part) - define Image/cmdline/jffs2-64k block2mtd.block2mtd=/dev/cfa2,65536 root=/dev/mtdblock0 rootfstype=jffs2 endef @@ -56,18 +53,7 @@ endef define Image/Build $(STAGING_DIR)/bin/patch-cmdline $(LINUX_DIR)/vmlinux '$(strip $(call Image/cmdline/$(1))) ' - ( \ - echo -ne OWRT | dd bs=$$$$((0x1be)) conv=sync; \ - ( \ - echo -ne '$(strip $(PARTITION1))'; \ - echo -ne '$(strip $(PARTITION2))'; \ - ) | dd bs=$$$$((0x40)) conv=sync; \ - echo -ne '\x55\xaa'; \ - dd if=/dev/zero bs=$$$$((0x3e00)) conv=sync count=1; \ - dd if=$(LINUX_DIR)/vmlinux bs=$$$$((0x3dc000)) conv=sync; \ - cat $(KDIR)/root.$(1); \ - echo -ne '\xde\xad\xc0\xde'; \ - ) > $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).bin + ./gen_image.sh $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).bin 4 $(LINUX_DIR)/vmlinux 16 $(KDIR)/root.$(1) endef $(eval $(call BuildImage)) diff --git a/target/linux/rb532-2.6/image/gen_image.sh b/target/linux/rb532-2.6/image/gen_image.sh new file mode 100755 index 0000000000..e812859797 --- /dev/null +++ b/target/linux/rb532-2.6/image/gen_image.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +OUTPUT="$1" +KERNELSIZE="$2" +KERNELIMAGE="$3" +ROOTFSSIZE="$4" +ROOTFSIMAGE="$5" + +rm -f "$OUTPUT" + +# create partition table +set `ptgen -o "$OUTPUT" -h 16 -s 32 -t 0x27 -p ${KERNELSIZE}m -t 0x83 -p ${ROOTFSSIZE}m` + +KERNELOFFSET="$(($1 / 512))" +ROOTFSOFFSET="$(($2 / 512))" + +dd if="$KERNELIMAGE" of="$OUTPUT" bs=512 conv=notrunc seek="$KERNELOFFSET" +dd if="$ROOTFSIMAGE" of="$OUTPUT" bs=512 conv=notrunc seek="$ROOTFSOFFSET" diff --git a/target/linux/rb532-2.6/patches/130-custom_partitions.patch b/target/linux/rb532-2.6/patches/130-custom_partitions.patch deleted file mode 100644 index e4b332703a..0000000000 --- a/target/linux/rb532-2.6/patches/130-custom_partitions.patch +++ /dev/null @@ -1,311 +0,0 @@ -diff -urN linux.old/fs/partitions/check.c linux.dev/fs/partitions/check.c ---- linux.old/fs/partitions/check.c 2006-05-31 02:31:44.000000000 +0200 -+++ linux.dev/fs/partitions/check.c 2006-06-15 01:27:17.000000000 +0200 -@@ -29,6 +29,7 @@ - #include "ldm.h" - #include "mac.h" - #include "msdos.h" -+#include "openwrt.h" - #include "osf.h" - #include "sgi.h" - #include "sun.h" -@@ -48,6 +49,9 @@ - * Probe partition formats with tables at disk address 0 - * that also have an ADFS boot block at 0xdc0. - */ -+#ifdef CONFIG_OPENWRT_PARTITION -+ openwrt_partition, -+#endif - #ifdef CONFIG_ACORN_PARTITION_ICS - adfspart_check_ICS, - #endif -diff -urN linux.old/fs/partitions/Kconfig linux.dev/fs/partitions/Kconfig ---- linux.old/fs/partitions/Kconfig 2006-05-31 02:31:44.000000000 +0200 -+++ linux.dev/fs/partitions/Kconfig 2006-06-15 01:27:17.000000000 +0200 -@@ -14,6 +14,12 @@ - - If unsure, say N. - -+config OPENWRT_PARTITION -+ bool "OpenWrt partition support" if PARTITION_ADVANCED -+ default y -+ help -+ Support the custom OpenWrt partition map -+ - config ACORN_PARTITION - bool "Acorn partition support" if PARTITION_ADVANCED - default y if ARCH_ACORN -diff -urN linux.old/fs/partitions/Makefile linux.dev/fs/partitions/Makefile ---- linux.old/fs/partitions/Makefile 2006-05-31 02:31:44.000000000 +0200 -+++ linux.dev/fs/partitions/Makefile 2006-06-15 01:27:17.000000000 +0200 -@@ -11,6 +11,7 @@ - obj-$(CONFIG_MAC_PARTITION) += mac.o - obj-$(CONFIG_LDM_PARTITION) += ldm.o - obj-$(CONFIG_MSDOS_PARTITION) += msdos.o -+obj-$(CONFIG_OPENWRT_PARTITION) += openwrt.o - obj-$(CONFIG_OSF_PARTITION) += osf.o - obj-$(CONFIG_SGI_PARTITION) += sgi.o - obj-$(CONFIG_SUN_PARTITION) += sun.o -diff -urN linux.old/fs/partitions/openwrt.c linux.dev/fs/partitions/openwrt.c ---- linux.old/fs/partitions/openwrt.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/fs/partitions/openwrt.c 2006-06-15 01:27:17.000000000 +0200 -@@ -0,0 +1,249 @@ -+/* -+ * fs/partitions/openwrt.c -+ * -+ * Code extracted from drivers/block/genhd.c -+ * and fs/partitions/msdos.c -+ * -+ * Copyright (C) 2006 Felix Fietkau -+ * Copyright (C) 1991-1998 Linus Torvalds -+ * -+ * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug -+ * in the early extended-partition checks and added DM partitions -+ * -+ * Support for DiskManager v6.0x added by Mark Lord, -+ * with information provided by OnTrack. This now works for linux fdisk -+ * and LILO, as well as loadlin and bootln. Note that disks other than -+ * /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1). -+ * -+ * More flexible handling of extended partitions - aeb, 950831 -+ * -+ * Check partition table on IDE disks for common CHS translations -+ * -+ * Re-organised Feb 1998 Russell King -+ */ -+ -+#include -+ -+#include "check.h" -+#include "openwrt.h" -+ -+/* -+ * Many architectures don't like unaligned accesses, while -+ * the nr_sects and start_sect partition table entries are -+ * at a 2 (mod 4) address. -+ */ -+#include -+ -+#define SYS_IND(p) (get_unaligned(&p->sys_ind)) -+#define NR_SECTS(p) ({ __typeof__(p->nr_sects) __a = \ -+ get_unaligned(&p->nr_sects); \ -+ le32_to_cpu(__a); \ -+ }) -+ -+#define START_SECT(p) ({ __typeof__(p->start_sect) __a = \ -+ get_unaligned(&p->start_sect); \ -+ le32_to_cpu(__a); \ -+ }) -+ -+static inline int is_extended_partition(struct partition *p) -+{ -+ return (SYS_IND(p) == DOS_EXTENDED_PARTITION || -+ SYS_IND(p) == WIN98_EXTENDED_PARTITION || -+ SYS_IND(p) == LINUX_EXTENDED_PARTITION); -+} -+ -+#define MSDOS_LABEL_MAGIC1 0x55 -+#define MSDOS_LABEL_MAGIC2 0xAA -+ -+static inline int -+msdos_magic_present(unsigned char *p) -+{ -+ return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2); -+} -+ -+static inline int -+openwrt_magic_present(unsigned char *p) -+{ -+ return (p[0] == 'O' && -+ p[1] == 'W' && -+ p[2] == 'R' && -+ p[3] == 'T'); -+} -+ -+/* -+ * Create devices for each logical partition in an extended partition. -+ * The logical partitions form a linked list, with each entry being -+ * a partition table with two entries. The first entry -+ * is the real data partition (with a start relative to the partition -+ * table start). The second is a pointer to the next logical partition -+ * (with a start relative to the entire extended partition). -+ * We do not create a Linux partition for the partition tables, but -+ * only for the actual data partitions. -+ */ -+ -+static void -+parse_extended(struct parsed_partitions *state, struct block_device *bdev, -+ u32 first_sector, u32 first_size) -+{ -+ struct partition *p; -+ Sector sect; -+ unsigned char *data; -+ u32 this_sector, this_size; -+ int sector_size = bdev_hardsect_size(bdev) / 512; -+ int loopct = 0; /* number of links followed -+ without finding a data partition */ -+ int i; -+ -+ this_sector = first_sector; -+ this_size = first_size; -+ -+ while (1) { -+ if (++loopct > 100) -+ return; -+ if (state->next == state->limit) -+ return; -+ data = read_dev_sector(bdev, this_sector, §); -+ if (!data) -+ return; -+ -+ if (!msdos_magic_present(data + 510)) -+ goto done; -+ -+ p = (struct partition *) (data + 0x1be); -+ -+ /* -+ * Usually, the first entry is the real data partition, -+ * the 2nd entry is the next extended partition, or empty, -+ * and the 3rd and 4th entries are unused. -+ * However, DRDOS sometimes has the extended partition as -+ * the first entry (when the data partition is empty), -+ * and OS/2 seems to use all four entries. -+ */ -+ -+ /* -+ * First process the data partition(s) -+ */ -+ for (i=0; i<4; i++, p++) { -+ u32 offs, size, next; -+ if (!NR_SECTS(p) || is_extended_partition(p)) -+ continue; -+ -+ /* Check the 3rd and 4th entries - -+ these sometimes contain random garbage */ -+ offs = START_SECT(p)*sector_size; -+ size = NR_SECTS(p)*sector_size; -+ next = this_sector + offs; -+ if (i >= 2) { -+ if (offs + size > this_size) -+ continue; -+ if (next < first_sector) -+ continue; -+ if (next + size > first_sector + first_size) -+ continue; -+ } -+ -+ put_partition(state, state->next, next, size); -+ if (SYS_IND(p) == LINUX_RAID_PARTITION) -+ state->parts[state->next].flags = 1; -+ loopct = 0; -+ if (++state->next == state->limit) -+ goto done; -+ } -+ /* -+ * Next, process the (first) extended partition, if present. -+ * (So far, there seems to be no reason to make -+ * parse_extended() recursive and allow a tree -+ * of extended partitions.) -+ * It should be a link to the next logical partition. -+ */ -+ p -= 4; -+ for (i=0; i<4; i++, p++) -+ if (NR_SECTS(p) && is_extended_partition(p)) -+ break; -+ if (i == 4) -+ goto done; /* nothing left to do */ -+ -+ this_sector = first_sector + START_SECT(p) * sector_size; -+ this_size = NR_SECTS(p) * sector_size; -+ put_dev_sector(sect); -+ } -+done: -+ put_dev_sector(sect); -+} -+ -+ -+int openwrt_partition(struct parsed_partitions *state, struct block_device *bdev) -+{ -+ int sector_size = bdev_hardsect_size(bdev) / 512; -+ Sector sect; -+ unsigned char *data; -+ struct partition *p; -+ int slot; -+ u32 last_block = 0; -+ u32 size = 0; -+ int firstfree = 5; -+ -+ data = read_dev_sector(bdev, 0, §); -+ if (!data) -+ return -1; -+ if (!openwrt_magic_present(data)) { -+ printk("No OpenWrt partition table detected\n"); -+ put_dev_sector(sect); -+ return 0; -+ } -+ -+ /* -+ * Now that the 55aa signature is present, this is probably -+ * either the boot sector of a FAT filesystem or a DOS-type -+ * partition table. Reject this in case the boot indicator -+ * is not 0 or 0x80. -+ */ -+ p = (struct partition *) (data + 0x1be); -+ for (slot = 1; slot <= 4; slot++, p++) { -+ if (p->boot_ind != 0 && p->boot_ind != 0x80) { -+ put_dev_sector(sect); -+ return 0; -+ } -+ } -+ -+ p = (struct partition *) (data + 0x1be); -+ -+ /* -+ * Look for partitions in two passes: -+ * First find the primary and DOS-type extended partitions. -+ */ -+ -+ state->next = 6; -+ for (slot = 1 ; slot <= 4 ; slot++, p++) { -+ u32 start = START_SECT(p)*sector_size; -+ size = NR_SECTS(p)*sector_size; -+ if (!size) { -+ if (firstfree > slot) -+ firstfree = slot; -+ -+ continue; -+ } -+ if (is_extended_partition(p)) { -+ /* prevent someone doing mkfs or mkswap on an -+ extended partition, but leave room for LILO */ -+ last_block = start + size; -+ put_partition(state, slot, start, size == 1 ? 1 : 2); -+ printk(" <"); -+ parse_extended(state, bdev, start, size); -+ printk(" >"); -+ continue; -+ } -+ if ((start + size) > get_capacity(bdev->bd_disk)) -+ size = get_capacity(bdev->bd_disk) - start; -+ last_block = start + size; -+ put_partition(state, slot, start, size); -+ } -+ if (last_block + 1024 < (size = get_capacity(bdev->bd_disk))) -+ put_partition(state, firstfree, last_block, size - last_block); -+ -+ printk("\n"); -+ -+ put_dev_sector(sect); -+ return 1; -+} -+ -diff -urN linux.old/fs/partitions/openwrt.h linux.dev/fs/partitions/openwrt.h ---- linux.old/fs/partitions/openwrt.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/fs/partitions/openwrt.h 2006-06-15 01:27:17.000000000 +0200 -@@ -0,0 +1,6 @@ -+/* -+ * fs/partitions/openwrt.h -+ */ -+ -+int openwrt_partition(struct parsed_partitions *state, struct block_device *bdev); -+ diff --git a/tools/firmware-utils/Makefile b/tools/firmware-utils/Makefile index 7b612aeac1..e600e90592 100644 --- a/tools/firmware-utils/Makefile +++ b/tools/firmware-utils/Makefile @@ -23,6 +23,7 @@ define Build/Compile $(call cc,motorola-bin) $(call cc,dgfirmware) $(call cc,trx2usr) + $(call cc,ptgen) endef define Build/Install diff --git a/tools/firmware-utils/src/ptgen.c b/tools/firmware-utils/src/ptgen.c new file mode 100644 index 0000000000..2d78eae535 --- /dev/null +++ b/tools/firmware-utils/src/ptgen.c @@ -0,0 +1,219 @@ +/* + * ptgen - partition table generator + * Copyright (C) 2006 by Felix Fietkau + * + * uses parts of afdisk + * Copyright (C) 2002 by David Roetzel + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if __BYTE_ORDER == __BIG_ENDIAN +#define cpu_to_le16(x) bswap_16(x) +#elif __BYTE_ORDER == __LITTLE_ENDIAN +#define cpu_to_le16(x) (x) +#else +#error unknown endianness! +#endif + +/* Partition table entry */ +struct pte { + unsigned char active; + unsigned char chs_start[3]; + unsigned char type; + unsigned char chs_end[3]; + unsigned int start; + unsigned int length; +}; + +struct partinfo { + unsigned long size; + int type; +}; + +int verbose = 0; +int active = 1; +int heads = -1; +int sectors = -1; +struct partinfo parts[4]; +char *filename = NULL; + + +/* + * parse the size argument, which is either + * a simple number (K assumed) or + * K, M or G + * + * returns the size in KByte + */ +static long to_kbytes(const char *string) { + int exp = 0; + long result; + char *end; + + result = strtoul(string, &end, 0); + switch (tolower(*end)) { + case 'k' : + case '\0' : exp = 0; break; + case 'm' : exp = 1; break; + case 'g' : exp = 2; break; + default: return 0; + } + + if (*end) + end++; + + if (*end) { + fprintf(stderr, "garbage after end of number\n"); + return 0; + } + + /* result: number + 1024^(exp) */ + return result * ((2 << ((10 * exp) - 1)) ?: 1); +} + +/* convert the sector number into a CHS value for the partition table */ +static void to_chs(long sect, unsigned char chs[3]) { + int c,h,s; + + s = (sect % sectors) + 1; + sect = sect / sectors; + h = sect % heads; + sect = sect / heads; + c = sect; + + chs[0] = h; + chs[1] = s | ((c >> 2) & 0xC0); + chs[2] = c & 0xFF; + + return; +} + +/* round the sector number up to the next cylinder */ +static inline unsigned long round_to_cyl(long sect) { + int cyl_size = heads * sectors; + + return sect + cyl_size - ((sect % cyl_size) ?: cyl_size); +} + +/* check the partition sizes and write the partition table */ +static int gen_ptable(int nr) +{ + struct pte pte[4]; + unsigned long sect = 0; + int i, fd, ret = -1, start, len; + + memset(pte, 0, sizeof(struct pte) * 4); + for (i = 0; i < nr; i++) { + if (!parts[i].size) { + fprintf(stderr, "Invalid size in partition %d!\n", i); + return -1; + } + pte[i].active = ((i + 1) == active) ? 0x80 : 0; + pte[i].type = parts[i].type; + pte[i].start = cpu_to_le16(start = sect + sectors); + sect = round_to_cyl(start + parts[i].size * 2); + pte[i].length = cpu_to_le16(len = sect - start); + to_chs(start, pte[i].chs_start); + to_chs(start + len - 1, pte[i].chs_end); + if (verbose) + fprintf(stderr, "Partition %d: start=%ld, end=%ld, size=%ld\n", i, (long) start * 512, ((long) start + (long) len) * 512, (long) len * 512); + printf("%ld\n", ((long) start * 512)); + } + + if ((fd = open(filename, O_WRONLY|O_CREAT, 0644)) < 0) { + fprintf(stderr, "Can't open output file '%s'\n",filename); + return -1; + } + + lseek(fd, 446, SEEK_SET); + if (write(fd, pte, sizeof(struct pte) * 4) != sizeof(struct pte) * 4) { + fprintf(stderr, "write failed.\n"); + goto fail; + } + lseek(fd, 510, SEEK_SET); + if (write(fd, "\x55\xaa", 2) != 2) { + fprintf(stderr, "write failed.\n"); + goto fail; + } + + ret = 0; +fail: + close(fd); + return ret; +} + +static void usage(char *prog) +{ + fprintf(stderr, "Usage: %s [-v] -h -s -o [-a 0..4] [[-t ] -p ...] \n", prog); + exit(1); +} + +int main (int argc, char **argv) +{ + char type = 0x83; + int ch; + int part = 0; + + while ((ch = getopt(argc, argv, "h:s:p:a:t:o:v")) != -1) { + switch (ch) { + case 'o': + filename = optarg; + break; + case 'v': + verbose++; + break; + case 'h': + heads = (int) strtoul(optarg, NULL, 0); + break; + case 's': + sectors = (int) strtoul(optarg, NULL, 0); + break; + case 'p': + if (part > 3) { + fprintf(stderr, "Too many partitions\n"); + exit(1); + } + parts[part].size = to_kbytes(optarg); + parts[part++].type = type; + break; + case 't': + type = (char) strtoul(optarg, NULL, 16); + break; + case 'a': + active = (int) strtoul(optarg, NULL, 0); + if ((active < 0) || (active > 4)) + active = 0; + break; + case '?': + default: + usage(argv[0]); + } + } + argc -= optind; + if (argc || (heads <= 0) || (sectors <= 0) || !filename) + usage(argv[0]); + + return gen_ptable(part); +}