From: Michal Simek Date: Tue, 25 Sep 2012 07:09:02 +0000 (+0200) Subject: romfs: Add ROMFS implementation X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=546270e8a1b2295af4b41b930a17646e3c392daf;p=thirdparty%2Fu-boot.git romfs: Add ROMFS implementation Some changes to have support on v2012.10 Signed-off-by: Michal Simek --- diff --git a/Makefile b/Makefile index e3a27c62493..9036bee5086 100755 --- 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 diff --git a/common/Makefile b/common/Makefile index 22e8a6fb35d..f64ea88bc2c 100644 --- a/common/Makefile +++ b/common/Makefile @@ -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 index 00000000000..6c58c3e82b7 --- /dev/null +++ b/common/cmd_romfs.c @@ -0,0 +1,221 @@ +/* + * (C) Copyright 2008-2009 Michal Simek + * + * Michal SIMEK + * + * 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 +#include + +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 /)", + " [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" +); +/***************************************************/ diff --git a/fs/Makefile b/fs/Makefile index 901e1894b6a..b5bbad67177 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -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 index 00000000000..150b2428850 --- /dev/null +++ b/fs/romfs/Makefile @@ -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 index 00000000000..ef7d8dfe0b6 --- /dev/null +++ b/fs/romfs/romfs.c @@ -0,0 +1,294 @@ +/* + * (C) Copyright 2007 Michal Simek + * + * Michal SIMEK + * + * 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 +#include + +/* 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; +} diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h index f434cd08910..4d7e322525a 100644 --- a/include/config_cmd_all.h +++ b/include/config_cmd_all.h @@ -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 */ diff --git a/include/configs/microblaze-generic.h b/include/configs/microblaze-generic.h index 721cd906adb..7244789c1a6 100644 --- a/include/configs/microblaze-generic.h +++ b/include/configs/microblaze-generic.h @@ -305,6 +305,8 @@ #define CONFIG_CMD_MFSL #define CONFIG_CMD_ECHO +#define CONFIG_CMD_ROMFS + #if defined(CONFIG_DCACHE) || defined(CONFIG_ICACHE) # define CONFIG_CMD_CACHE #else