]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
romfs: Add ROMFS implementation
authorMichal Simek <monstr@monstr.eu>
Tue, 25 Sep 2012 07:09:02 +0000 (09:09 +0200)
committerMichal Simek <monstr@monstr.eu>
Tue, 25 Sep 2012 09:02:44 +0000 (11:02 +0200)
Some changes to have support on v2012.10

Signed-off-by: Michal Simek <monstr@monstr.eu>
Makefile
common/Makefile
common/cmd_romfs.c [new file with mode: 0644]
fs/Makefile
fs/romfs/Makefile [new file with mode: 0644]
fs/romfs/romfs.c [new file with mode: 0644]
include/config_cmd_all.h
include/configs/microblaze-generic.h

index e3a27c624939d10c584781582e83749378cfa594..9036bee50865687fa13e221e8a838c66ce8fc2f4 100755 (executable)
--- a/Makefile
+++ b/Makefile
@@ -248,6 +248,7 @@ LIBS-y += fs/cramfs/libcramfs.o \
        fs/fdos/libfdos.o \
        fs/jffs2/libjffs2.o \
        fs/reiserfs/libreiserfs.o \
+       fs/romfs/libromfs.o \
        fs/ubifs/libubifs.o \
        fs/yaffs2/libyaffs2.o \
        fs/zfs/libzfs.o
index 22e8a6fb35d2b83a37027085742240efc5fee40e..f64ea88bc2ca356199528b5f0fd44053e6142f06 100644 (file)
@@ -143,6 +143,7 @@ COBJS-$(CONFIG_CMD_PORTIO) += cmd_portio.o
 COBJS-$(CONFIG_CMD_PXE) += cmd_pxe.o
 COBJS-$(CONFIG_CMD_REGINFO) += cmd_reginfo.o
 COBJS-$(CONFIG_CMD_REISER) += cmd_reiser.o
+COBJS-$(CONFIG_CMD_ROMFS) += cmd_romfs.o
 COBJS-$(CONFIG_CMD_SATA) += cmd_sata.o
 COBJS-$(CONFIG_CMD_SF) += cmd_sf.o
 COBJS-$(CONFIG_CMD_SCSI) += cmd_scsi.o
diff --git a/common/cmd_romfs.c b/common/cmd_romfs.c
new file mode 100644 (file)
index 0000000..6c58c3e
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * (C) Copyright 2008-2009 Michal Simek
+ *
+ * Michal SIMEK <monstr@monstr.eu>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+
+int romfs_check (int info);
+int romfs_load (int *loadoffset, int info, char *filename);
+int romfs_ls (int info, char *filename);
+int romfs_info (int info);
+int romfs_cat (int info, char *filename);
+
+u32 address; /* physical address of fs */
+
+/**
+ * Routine implementing fsload u-boot command. This routine tries to load
+ * a requested file from jffs2/cramfs filesystem on a current partition.
+ *
+ * @param cmdtp command internal data
+ * @param flag command flag
+ * @param argc number of arguments supplied to the command
+ * @param argv arguments list
+ * @return 0 on success, 1 otherwise
+ */
+/* FIXME here is not clean handling with load_addr */
+int do_romfs_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       char *fsname = NULL;
+       char *filename = NULL;
+       int size = 0;
+
+       ulong offset = 0;
+
+       switch (argc) {
+       case 4:
+               address = simple_strtoul(argv[3], NULL, 16);
+       case 3:
+               filename = argv[2];
+               offset = simple_strtoul(argv[1], NULL, 16);
+               break;
+       default:
+               cmd_usage(cmdtp);
+               return 1;
+       }
+
+       /* check partition type for romfs */
+       if (romfs_check(address))
+               fsname = "ROMFS";
+       else
+               puts ("error\n");
+
+       printf("### %s loading '%s' to 0x%lx\n", fsname, filename, offset);
+
+       if (romfs_check(address))
+               size = romfs_load ((int *) offset, address, filename);
+
+       if (size > 0) {
+               char buf[10];
+               printf("### %s load complete: %d bytes loaded to 0x%lx\n",
+                       fsname, size, offset);
+               sprintf(buf, "%x", size);
+               setenv("filesize", buf);
+       } else
+               printf("### %s LOAD ERROR<%x> for %s!\n",
+                                       fsname, size, filename);
+
+       return !(size > 0);
+}
+
+/**
+ * Routine implementing u-boot ls command which lists content of a given
+ * directory on a current partition.
+ *
+ * @param cmdtp command internal data
+ * @param flag command flag
+ * @param argc number of arguments supplied to the command
+ * @param argv arguments list
+ * @return 0 on success, 1 otherwise
+ */
+int do_romfs_ls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       char *filename = "/";
+       int loc_addr = 0;
+
+       if (argc >= 2)
+               filename = argv[1];
+
+       if (argc > 2)
+               loc_addr = simple_strtoul (argv[2], NULL, 16);
+       else
+               loc_addr = address;
+
+       /* check partition type for cramfs */
+       if (romfs_check (loc_addr)) {
+               address = loc_addr;
+               return (romfs_ls (loc_addr, filename) ? 0 : 1);
+       }
+       return 1;
+}
+
+
+
+/**
+ * Routine implementing u-boot cat command which lists content of a given
+ * directory on a current partition.
+ *
+ * @param cmdtp command internal data
+ * @param flag command flag
+ * @param argc number of arguments supplied to the command
+ * @param argv arguments list
+ * @return 0 on success, 1 otherwise
+ */
+int do_romfs_cat (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       char *filename = "/";
+       int loc_addr = 0;
+
+       if (argc >= 2)
+               filename = argv[1];
+
+       if (argc > 2)
+               loc_addr = simple_strtoul (argv[2], NULL, 16);
+       else
+               loc_addr = address;
+
+       /* check partition type for cramfs */
+       if (romfs_check (loc_addr)) {
+               address = loc_addr;
+               return (romfs_cat (loc_addr, filename) ? 0 : 1);
+       }
+       return 1;
+}
+
+
+/**
+ * Routine implementing u-boot fsinfo command. This routine prints out
+ * miscellaneous filesystem informations/statistics.
+ *
+ * @param cmdtp command internal data
+ * @param flag command flag
+ * @param argc number of arguments supplied to the command
+ * @param argv arguments list
+ * @return 0 on success, 1 otherwise
+ */
+int do_romfs_fsinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       int loc_addr;
+
+       if (argc == 2)
+               loc_addr = simple_strtoul(argv[1], NULL, 16);
+       else
+               loc_addr = address;
+
+       /* check partition type for romfs */
+       if (romfs_check(loc_addr))
+               if (romfs_info (loc_addr)) {
+                       address = loc_addr;
+                       return 1;
+               }
+       return 0;
+}
+
+/*
+U_BOOT_CMD(
+       ext2ls, 4,      1,      do_ext2ls,
+       "list files in a directory (default /)",
+       "<interface> <dev[:part]> [directory]\n"
+       "    - list files from 'dev' on 'interface' in a 'directory'"
+);
+*/
+
+/***************************************************/
+U_BOOT_CMD(
+       rload,  4,      0,      do_romfs_fsload,
+       "ROMFS: load binary file from a filesystem image",
+       "[ off filename [fs_addr]]\n"
+       "    - ROMFS: load binary file from flash bank\n"
+       "      with offset 'off'"
+);
+U_BOOT_CMD(
+       rls,    3,      1,      do_romfs_ls,
+       "ROMFS: list files in a directory (default /)",
+       "[directory [fs_addr]]\n"
+       "    - ROMFS: list files in a directory"
+);
+
+U_BOOT_CMD(
+       rcat,   3,      1,      do_romfs_cat,
+       "ROMFS: cat text file (default /)",
+       "[directory [fs_addr]]\n"
+       "    - ROMFS: list files in a directory"
+);
+
+U_BOOT_CMD(
+       rinfo,  2,      1,      do_romfs_fsinfo,
+       "ROMFS: print information about filesystems",
+       "[fs_addr]\n"
+       "    - ROMFS: print information about filesystems"
+);
+/***************************************************/
index 901e1894b6a6b5a1fc26e4fe800f75b42db0dae4..b5bbad671770a75d29aaeccb5b508dc72480730a 100644 (file)
@@ -31,6 +31,7 @@ subdirs-$(CONFIG_CMD_FAT) += fat
 subdirs-$(CONFIG_CMD_FDOS) += fdos
 subdirs-$(CONFIG_CMD_JFFS2) += jffs2
 subdirs-$(CONFIG_CMD_REISER) += reiserfs
+subdirs-$(CONFIG_CMD_ROMFS) += romfs
 subdirs-$(CONFIG_YAFFS2) += yaffs2
 subdirs-$(CONFIG_CMD_UBIFS) += ubifs
 subdirs-$(CONFIG_CMD_ZFS) += zfs
diff --git a/fs/romfs/Makefile b/fs/romfs/Makefile
new file mode 100644 (file)
index 0000000..150b242
--- /dev/null
@@ -0,0 +1,47 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB    = $(obj)libromfs.o
+
+AOBJS  =
+COBJS-$(CONFIG_CMD_ROMFS) := romfs.o
+
+SRCS   := $(AOBJS:.o=.S) $(COBJS-y:.o=.c)
+OBJS   := $(addprefix $(obj),$(AOBJS) $(COBJS-y))
+
+
+all:   $(LIB) $(AOBJS)
+
+$(LIB):        $(obj).depend $(OBJS)
+       $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/fs/romfs/romfs.c b/fs/romfs/romfs.c
new file mode 100644 (file)
index 0000000..ef7d8df
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * (C) Copyright 2007 Michal Simek
+ *
+ * Michal SIMEK <monstr@monstr.eu>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/byteorder.h>
+
+/* ROMFS superblock */
+struct romfs_super {
+       u32 word0;
+       u32 word1;
+       u32 size;
+       u32 checksum;
+       char name[0];
+};
+
+struct romfs_inode {
+       u32 next;
+       u32 spec;
+       u32 size;
+       u32 checksum;
+       char name[0];
+};
+
+#undef DEBUG_ROMFS
+
+#define ROMFS_ALIGN(x) (((x) & 0xfffffff0))
+#define HEADERSIZE(name)       (0x20 + ROMFS_ALIGN(strlen(name)))
+
+/* find romfs inode */
+static unsigned long romfs_resolve (unsigned long begin, unsigned long offset,
+                               unsigned long size, int raw, char *filename)
+{
+       unsigned long inodeoffset = 0, nextoffset;
+       struct romfs_inode *inode;
+#ifdef DEBUG_ROMFS
+       printf ("ROMFS_resolve: begin 0x%lx, offset 0x%lx, size 0x%lx, "
+               "raw 0x%x, filename %s\n\n",
+                                       begin, offset, size, raw, filename);
+#endif
+
+       while (inodeoffset < size) {
+               inode = (struct romfs_inode *)(begin + offset + inodeoffset);
+               nextoffset = ROMFS_ALIGN(inode->next);
+#ifdef DEBUG_ROMFS
+               printf("inode 0x%x, name %s - len 0x%x, next inode 0x%lx,"
+                       "compare names 0x%x\n", (u32)inode, inode->name,
+                       strlen (inode->name), nextoffset,
+                       strncmp (filename, inode->name, strlen (filename)));
+#endif
+               if (!strncmp (filename, inode->name, strlen (inode->name))) {
+                       char *p = strtok (NULL, "/");
+
+                       if (raw && (p == NULL || *p == '\0'))
+                               return offset + inodeoffset;
+
+                       return romfs_resolve (begin,
+                                       inodeoffset + HEADERSIZE (inode->name),
+                                       size, raw, p);
+               }
+               inodeoffset = nextoffset;
+               offset = 0; /* clear offset at the end because first label */
+       }
+
+       printf ("Can't find corresponding entry\n");
+       return 0;
+}
+
+int romfs_load (char *loadoffset, int info, char *filename)
+{
+       struct romfs_inode *inode;
+       struct romfs_super *sb;
+       char *data;
+       int pocet;
+       unsigned long offset;
+
+       sb = (struct romfs_super *) info;
+
+       offset = romfs_resolve (info, HEADERSIZE (sb->name),
+                               sb->size, 1, strtok (filename, "/"));
+       if (offset <= 0)
+               return offset;
+
+       inode = (struct romfs_inode *)(info + offset);
+       data = (char *)((int)inode + HEADERSIZE (inode->name));
+       pocet = inode->size;
+       while (pocet--)
+               *loadoffset++ = *data++;
+
+       return inode->size;
+}
+
+static int romfs_list_inode (int info, unsigned long offset)
+{
+       struct romfs_inode *inode =
+                       (struct romfs_inode *)(info + offset);
+       struct romfs_inode *hardlink = NULL;
+       char str[3], *data;
+
+/*     mapping         spec.info means
+ 0     hard link       link destination [file header]
+ 1     directory       first file's header
+ 2     regular file    unused, must be zero [MBZ]
+ 3     symbolic link   unused, MBZ (file data is the link content)
+ 4     block device    16/16 bits major/minor number
+ 5     char device             - " -
+ 6     socket          unused, MBZ
+ 7     fifo            unused, MBZ */
+
+       switch (inode->next & 0x7) {
+       case 0:
+               str[0] = 'h';
+               break;
+       case 1:
+               str[0] = 'd';
+               break;
+       case 2:
+               str[0] = 'f';
+               break;
+       case 3:
+               str[0] = 'l';
+               break;
+       case 4:
+               str[0] = 'b';
+               break;
+       case 5:
+               str[0] = 'c';
+               break;
+       case 6:
+               str[0] = 's';
+               break;
+       case 7:
+               str[0] = 'p';
+               break;
+       default:
+               str[0] = '?';
+       }
+
+       if (inode->next & 0x8) {
+               str[1] = 'x';
+       } else {
+               str[1] = '-';
+       }
+       str[2] = '\0';
+
+       if ((str[0] == 'b') || (str[0] == 'c')) {
+#ifdef DEBUG_ROMFS
+               printf (" %s  %3d,%3d %12s 0x%08x 0x%08x", str,
+                       (inode->spec & 0xffff0000) >> 16,
+                       inode->spec & 0x0000ffff, inode->name, (u32)inode,
+                       inode->spec);
+#else
+               printf (" %s  %3d,%3d %12s", str,
+                       (inode->spec & 0xffff0000) >> 16,
+                       inode->spec & 0x0000ffff, inode->name);
+
+#endif
+       } else {
+#ifdef DEBUG_ROMFS
+               printf (" %s  %7d %12s 0x%08x 0x%08x", str, inode->size,
+                       inode->name, (u32)inode, inode->spec);
+#else
+               printf (" %s  %7d %12s", str, inode->size, inode->name);
+#endif
+               if (str[0] == 'l') {
+                       data = (char *)((int)inode + HEADERSIZE (inode->name));
+                       puts (" -> ");
+                       puts (data);
+               }
+               if (str[0] == 'h') {
+                       hardlink = (struct romfs_inode *)(info + inode->spec);
+                       puts (" -> ");
+                       puts (hardlink->name);
+               }
+       }
+       puts ("\n");
+       return ROMFS_ALIGN(inode->next);
+}
+
+/* listing directory */
+int romfs_ls (int info, char *filename)
+{
+       struct romfs_inode *inode;
+       struct romfs_super *sb;
+       unsigned long inodeoffset = 0, nextoffset;
+       unsigned long size;
+
+       sb = (struct romfs_super *) info;
+       inode = (struct romfs_inode *) info;
+
+       if ((strlen (filename) != 0) && strcmp (filename, "/")) {
+               inodeoffset = romfs_resolve (info,
+                       HEADERSIZE (sb->name), sb->size, 1,
+                       strtok (filename, "/"));
+
+               /* inode not found */
+               if (inodeoffset == 0)
+                       return 0;
+
+               /* look at what is it */
+               inode = (struct romfs_inode *)(info + inodeoffset);
+               if ((inode->next & 0x7) != 1)
+                       return (romfs_list_inode (info, inodeoffset) > 0);
+       }
+
+       /* print directory */
+       size = sb->size;
+       inodeoffset = inodeoffset + HEADERSIZE (inode->name);
+
+       while (inodeoffset < size) {
+               nextoffset = romfs_list_inode (info, inodeoffset);
+               if (nextoffset == 0)
+                       break;
+               inodeoffset = nextoffset;
+       }
+       return 1;
+}
+
+/* cat file */
+int romfs_cat (int info, char *filename)
+{
+       struct romfs_inode *inode;
+       struct romfs_super *sb;
+       unsigned long inodeoffset = 0;
+       char *data;
+
+       sb = (struct romfs_super *) info;
+       inode = (struct romfs_inode *) info;
+
+       if ((strlen (filename) != 0) && strcmp (filename, "/")) {
+               inodeoffset = romfs_resolve (info,
+                       HEADERSIZE (sb->name), sb->size, 1,
+                       strtok (filename, "/"));
+
+               /* inode not found */
+               if (inodeoffset == 0)
+                       return 0;
+
+               /* look at what it is */
+               inode = (struct romfs_inode *)(info + inodeoffset);
+               if ((inode->next & 0x7) == 2) {
+                       data =(char *) (info + inodeoffset +
+                                       (u32)HEADERSIZE (inode->name));
+                       printf("%s\n", data);
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+int romfs_info (int info)
+{
+       struct romfs_super *sb;
+       sb = (struct romfs_super *)info;
+
+       printf ("name: \t\t%s, len %d B\n", sb->name, strlen (sb->name));
+       printf ("size of SB:\t%d B\n", HEADERSIZE (sb->name));
+       printf ("full size:\t%d B\n", sb->size);
+       printf ("checksum:\t0x%x\n", sb->checksum);
+       printf ("fs address:\t0x%x\n", (u32)sb);
+       return 1;
+}
+
+int romfs_check (int info)
+{
+       struct romfs_super *sb;
+
+       sb = (struct romfs_super *) info;
+
+       if ((sb->word0 != 0x2D726F6D) || (sb->word1 != 0x3166732D))
+               return 0;
+
+       return 1;
+}
index f434cd08910e5f71ffaaa07ae512681b6117788b..4d7e322525a2cd627395ce1ecd1ebbd01665e702 100644 (file)
@@ -70,6 +70,7 @@
 #define CONFIG_CMD_REGINFO     /* Register dump                */
 #define CONFIG_CMD_REISER      /* Reiserfs support             */
 #define CONFIG_CMD_RARP                /* rarpboot support             */
+#define CONFIG_CMD_ROMFS       /* ROMFS support                */
 #define CONFIG_CMD_RUN         /* run command in env variable  */
 #define CONFIG_CMD_SAVEENV     /* saveenv                      */
 #define CONFIG_CMD_SAVES       /* save S record dump           */
index 721cd906adb151ae5214c1bd4f9a7082b38aa5cb..7244789c1a6cbf121d0e95ad3dec9691227f8730 100644 (file)
 #define CONFIG_CMD_MFSL
 #define CONFIG_CMD_ECHO
 
+#define CONFIG_CMD_ROMFS
+
 #if defined(CONFIG_DCACHE) || defined(CONFIG_ICACHE)
 # define CONFIG_CMD_CACHE
 #else