tools: create a new tool for more efficient jffs2 padding
authorGabor Juhos <juhosg@openwrt.org>
Sat, 2 Jul 2011 08:37:56 +0000 (08:37 +0000)
committerGabor Juhos <juhosg@openwrt.org>
Sat, 2 Jul 2011 08:37:56 +0000 (08:37 +0000)
SVN-Revision: 27355

tools/Makefile
tools/padjffs2/Makefile [new file with mode: 0644]
tools/padjffs2/src/Makefile [new file with mode: 0644]
tools/padjffs2/src/padjffs2.c [new file with mode: 0644]

index 486734b..aff6ea8 100644 (file)
@@ -16,7 +16,7 @@ tools-$(CONFIG_GCC_VERSION_4_5) += mpc libelf
 endif
 tools-y += m4 libtool autoconf automake flex bison pkg-config sed mklibs
 tools-y += sstrip ipkg-utils genext2fs e2fsprogs mtd-utils mkimage
-tools-y += firmware-utils patch-cmdline quilt yaffs2 flock
+tools-y += firmware-utils patch-cmdline quilt yaffs2 flock padjffs2
 tools-y += mm-macros xorg-macros xfce-macros missing-macros xz cmake
 tools-$(CONFIG_TARGET_orion_generic) += wrt350nv2-builder upslug2
 tools-$(CONFIG_TARGET_x86) += qemu
diff --git a/tools/padjffs2/Makefile b/tools/padjffs2/Makefile
new file mode 100644 (file)
index 0000000..a057ddd
--- /dev/null
@@ -0,0 +1,36 @@
+#
+# Copyright (C) 2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=padjffs2
+PKG_VERSION:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Prepare
+       mkdir -p $(HOST_BUILD_DIR)
+       $(CP) ./src/* $(HOST_BUILD_DIR)/
+       find $(HOST_BUILD_DIR) -name .svn | $(XARGS) rm -rf
+endef
+
+define Host/Configure
+endef
+
+define Host/Compile
+       $(MAKE) CC="$(HOSTCC)" -C $(HOST_BUILD_DIR)
+endef
+
+define Host/Install
+       $(CP) $(HOST_BUILD_DIR)/padjffs2 $(STAGING_DIR_HOST)/bin/
+endef
+
+define Host/Clean
+       rm -f $(STAGING_DIR_HOST)/bin/padjffs2
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/padjffs2/src/Makefile b/tools/padjffs2/src/Makefile
new file mode 100644 (file)
index 0000000..fe1a7aa
--- /dev/null
@@ -0,0 +1,15 @@
+CC = gcc
+CFLAGS =
+WFLAGS = -Wall -Werror
+padjffs2-objs = padjffs2.o
+
+all: padjffs2
+
+%.o: %.c
+       $(CC) $(CFLAGS) $(WFLAGS) -c -o $@ $<
+
+padjffs2: $(padjffs2-objs)
+       $(CC) -o $@ $(padjffs2-objs)
+
+clean:
+       rm -f padjffs2 *.o
diff --git a/tools/padjffs2/src/padjffs2.c b/tools/padjffs2/src/padjffs2.c
new file mode 100644 (file)
index 0000000..679992d
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+static char *progname;
+static unsigned char eof_mark[4] = {0xde, 0xad, 0xc0, 0xde};
+
+#define ERR(fmt, ...) do { \
+       fflush(0); \
+       fprintf(stderr, "[%s] *** error: " fmt "\n", \
+                       progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define ERRS(fmt, ...) do { \
+       int save = errno; \
+       fflush(0); \
+       fprintf(stderr, "[%s] *** error: " fmt ", %s\n", \
+                       progname, ## __VA_ARGS__, strerror(save)); \
+} while (0)
+
+#define BUF_SIZE       (64 * 1024)
+#define ALIGN(_x,_y)   (((_x) + ((_y) - 1)) & ~((_y) - 1))
+
+static int pad_image(char *name, uint32_t pad_mask)
+{
+       char *buf;
+       int fd;
+       ssize_t in_len;
+       ssize_t out_len;
+       int ret = -1;
+
+       buf = malloc(BUF_SIZE);
+       if (!buf) {
+               ERR("No memory for buffer");
+               goto out;
+       }
+
+       fd = open(name, O_RDWR);
+       if (fd < 0) {
+               ERRS("Unable to open %s", name);
+               goto free_buf;
+       }
+
+       in_len = lseek(fd, 0, SEEK_END);
+       if (in_len < 0)
+               goto close;
+
+       memset(buf, '\xff', BUF_SIZE);
+
+       out_len = in_len;
+       while (pad_mask) {
+               uint32_t mask;
+               ssize_t t;
+               int i;
+
+               for (i = 10; i < 32; i++) {
+                       mask = 1UL << i;
+                       if (pad_mask & mask)
+                               break;
+               }
+
+               in_len = ALIGN(in_len, mask);
+
+               for (i = 10; i < 32; i++) {
+                       mask = 1UL << i;
+                       if ((in_len & (mask - 1)) == 0)
+                               pad_mask &= ~mask;
+               }
+
+               printf("padding image to %08x\n", in_len);
+
+               while (out_len < in_len) {
+                       ssize_t len;
+
+                       len = in_len - out_len;
+                       if (len > BUF_SIZE)
+                               len = BUF_SIZE;
+
+                       t = write(fd, buf, len);
+                       if (t != len) {
+                               ERRS("Unable to write to %s", name);
+                               goto close;
+                       }
+
+                       out_len += len;
+               }
+
+               /* write out the JFFS end-of-filesystem marker */
+               t = write(fd, eof_mark, 4);
+               if (t != 4) {
+                       ERRS("Unable to write to %s", name);
+                       goto close;
+               }
+               out_len += 4;
+       }
+
+       ret = 0;
+
+close:
+       close(fd);
+free_buf:
+       free(buf);
+out:
+       return ret;
+}
+
+int main(int argc, char* argv[])
+{
+       uint32_t pad_mask;
+       int ret = EXIT_FAILURE;
+       int err;
+       int i;
+
+       progname = basename(argv[0]);
+
+       if (argc < 2) {
+               fprintf(stderr,
+                       "Usage: %s file [pad0] [pad1] [padN]\n",
+                       progname);
+               goto out;
+       }
+
+       pad_mask = 0;
+       for (i = 2; i < argc; i++)
+               pad_mask |= strtoul(argv[i], NULL, 0) * 1024;
+
+       if (pad_mask == 0)
+               pad_mask = (4 * 1024) | (8 * 1024) | (64 * 1024) |
+                          (128 * 1024);
+
+       err = pad_image(argv[1], pad_mask);
+       if (err)
+               goto out;
+
+       ret = EXIT_SUCCESS;
+
+out:
+       return ret;
+}