diff options
author | Michael Gielda <mgielda@antmicro.com> | 2014-04-03 14:53:04 +0200 |
---|---|---|
committer | Michael Gielda <mgielda@antmicro.com> | 2014-04-03 14:53:04 +0200 |
commit | ae1e4e08a1005a0c487f03ba189d7536e7fdcba6 (patch) | |
tree | f1c296f8a966a9a39876b0e98e16d9c5da1776dd /ecos/packages/fs/rom | |
parent | f157da5337118d3c5cd464266796de4262ac9dbd (diff) |
Added the OS files
Diffstat (limited to 'ecos/packages/fs/rom')
-rw-r--r-- | ecos/packages/fs/rom/current/ChangeLog | 217 | ||||
-rw-r--r-- | ecos/packages/fs/rom/current/cdl/romfs.cdl | 155 | ||||
-rw-r--r-- | ecos/packages/fs/rom/current/doc/mk_romfs.txt | 111 | ||||
-rw-r--r-- | ecos/packages/fs/rom/current/doc/romfs.txt | 12 | ||||
-rw-r--r-- | ecos/packages/fs/rom/current/src/romfs.c | 1138 | ||||
-rw-r--r-- | ecos/packages/fs/rom/current/support/Makefile | 38 | ||||
-rwxr-xr-x | ecos/packages/fs/rom/current/support/file2c.tcl | 118 | ||||
-rw-r--r-- | ecos/packages/fs/rom/current/support/mk_romfs.c | 744 | ||||
-rw-r--r-- | ecos/packages/fs/rom/current/tests/romfs1.c | 408 | ||||
-rw-r--r-- | ecos/packages/fs/rom/current/tests/testromfs/etc/hosts | 0 | ||||
-rw-r--r-- | ecos/packages/fs/rom/current/tests/testromfs/etc/inetd | 0 | ||||
-rw-r--r-- | ecos/packages/fs/rom/current/tests/testromfs/etc/passwd | 32 | ||||
-rw-r--r-- | ecos/packages/fs/rom/current/tests/testromfs/mnt/thing | 1 | ||||
-rw-r--r-- | ecos/packages/fs/rom/current/tests/testromfs/var/foobar | 1 |
14 files changed, 2975 insertions, 0 deletions
diff --git a/ecos/packages/fs/rom/current/ChangeLog b/ecos/packages/fs/rom/current/ChangeLog new file mode 100644 index 0000000..dcaefd7 --- /dev/null +++ b/ecos/packages/fs/rom/current/ChangeLog @@ -0,0 +1,217 @@ +2010-11-29 John Dallaway <john@dallaway.org.uk> + + * cdl/romfs.cdl: Add CYGFUN_FS_ROM_FLASH_BLOCK_DEVICE_LOOKUP option. + * support/mk_romfs.c: Fix Win32 build. + +2010-11-13 Alexander Aganichev <aaganichev@gmail.com> + + * src/romfs.c: Added ability to mount a flash block device by name. + +2010-02-28 Øyvind Harboe <oyvind.harboe@zylin.com> + + * src/romfs.c: file name comparison was broken for two files + with the same stem. A directory/file called "foo" would not + be found if there was a file "foo*" before "foo". + +2009-10-09 John Dallaway <john@dallaway.org.uk> + + * cdl/romfs.cdl: Eliminate workarounds for file path handling + issue in obsolete Cygwin tclsh. Build the mk_romfs tool with higher + priority than the custom rules which use it. + +2009-04-28 John Dallaway <john@dallaway.org.uk> + + * cdl/romfs.cdl: Use CYGPKG_IO_FILEIO as the parent. + +2009-02-07 John Dallaway <john@dallaway.org.uk> + + * cdl/romfs.cdl: Pass file2c.tcl to tclsh directly. + +2009-01-08 John Dallaway <john@dallaway.org.uk> + + * support/file2c.tcl: Specify script interpreter via /usr/bin/env. + +2008-08-14 Klaas Gadeyne <klaas.gadeyne@fmtc.be> +2008-08-14 Jonathan Larmour <jifl@eCosCentric.com> + + * doc/mk_romfs.txt (Usage): Remove documentation about obsolete + CYGNUM_FS_ROM_BASE_ADDRESS option, and replace with better + usage description. + +2006-11-13 Xinghua Yang <yxinghua@sunnorth.com.cn> + Taiyun Wang <taiyun@sunnorth.com.cn> + + * cdl/romfs.cdl: Use CYGPKG_FS_ROM_RET_DIRENT_DTYPE to control + whether fatfs sets file type in romfs_fo_dirread. + * src/romfs.c: Set file type in romfs_fo_dirread. + * tests/romfs1.c: Test the new d_type in dirent when present. + +2006-11-13 Oyvind Harboe <oyvind.harboe@zylin.com> + + * support/file2c.tcl : align romdisk data to 4 bytes. With a bit + of bad luck, it would not be long-word aligned. + +2006-08-04 Andrew Lunn <andrew.lunn@ascom.ch> + + * src/romfs.c (romfs_getinfo): Support for block usage call. + * tests/romfs1.c (main): Add file system block usage test. + +2006-02-15 Andrew Lunn <andrew.lunn@ascom.ch> + Peter Korsgaard <jacmet@sunsite.dk> + + * support/mk_romfs.c: Use stdint.h defined types so the code is + 64 bit clean. Fix compiler warnings. + +2005-07-08 Andrew Lunn <andrew.lunn@ascom.ch> + + * cdl/romfs.cdl: Allow mk_romfs to be build even when the tests + are disabled. It is generally useful and other tests programs may + want it. + +2004-12-13 John Dallaway <jld@ecoscentric.com> + + * tests/fileio1.c: Rename to romfs1.c. eCos test names should be + unique. + * cdl/romfs.cdl: Build the romfs1 test. + +2004-10-04 Andrew Lunn <andrew.lunn@ascom.ch> + + * src/romfs.c (romfs_mount): Avoid a compiler warning about punned + types. + +2004-08-08 Bart Veer <bartv@ecoscentric.com> + + * cdl/romfs.cdl: generate both little-endian and big-endian image + files. + + * tests/fileio1.c: include either a little-endian or a big-endian + image. Totally fail the test early on if the file system cannot be + mounted. + +2004-06-14 John Dallaway <jld@ecoscentric.com> + + * cdl/romfs.cdl: Specify the test executable file name for + compatibility with the eCos Configuration Tool. + +2004-02-20 Vincent Catros <Vincent.Catros@elios-informatique.fr> + + * src/fs-ecos.c : + (jffs2_find) Policy to skip path separator is no longer + "if '/' then skip" but "while '/' then skip" allowing + multi '/' separators (i.e : /tmp////foo). + (find_entry) Policy to detect end of path is no longer + "if '\0' then end_of_path" + but "while '/' skip it and then if '\0' then end_of_path" + allowing path terminated with any number of '/' + (i.e : chdir(/tmp///)). + +2003-12-11 Sandeep Kumar <sandeep@codito.com> + + * src/romfs.c (romfs_mount) : function wrongly returns ENOENT even + if fste->data isn't NULL. + +2003-09-25 Oyvind Harboe <oyvind.harboe@zylin.com> + + * src/romfs.c (romfs_mount): If a mount fails, make sure we leave + all state information in such a way we can try again. + +2003-07-10 Andrew Lunn <andrew.lunn@ascom.ch> + + * support/mk_romfs.c: S_I[RWX]{USR|GRP|OTH} etc changed to match + the changes in sys/stat.h + +2003-02-24 Jonathan Larmour <jifl@eCosCentric.com> + + * cdl/romfs.cdl: Fix doc link. + +2003-01-30 Andrew Lunn <andrew.lunn@ascom.ch> + + * cdl/romfs.cdl: Implements the CYGINT_IO_FILEIO_FS interface. + +2003-01-29 John Dallaway <jld@ecoscentric.com> + + * support/file2c.tcl: Accommodate latest Cygwin Tcl shell + (tclsh83.exe) + +2002-04-15 Bart Veer <bartv@redhat.com> + + * support/file2c.tcl: + Do not use an alignment attribute, since it is not honoured on + all targets. + + * src/romfs.c: + Remove alignment restrictions, since they are not actually needed + yet and alignment is hard to guarantee on all targets. + +2002-01-21 Jonathan Larmour <jlarmour@redhat.com> + + * support/mk_romfs.c: Open image file in binary mode (for cygwin). + Spotted by Warren Jasper. + +2001-11-23 Jonathan Larmour <jlarmour@redhat.com> + + * cdl/romfs.cdl (CYGTST_ROMFS_BUILD_TESTS): Try gcc and cc if $HOST_CC + doesn't exist or has a problem. + +2001-11-22 Jesper Skov <jskov@redhat.com> + + * cdl/romfs.cdl: Use HOST_CC instead of 'cc'. + +2001-10-17 Drew Moseley <dmoseley@redhat.com> +2001-10-17 Jonathan Larmour <jlarmour@redhat.com> + + * support/mk_romfs.c: Open input files in binary mode (for cygwin). + * cdl/romfs.cdl: Work around cygwin path problems by copying files + into build tree. + +2001-07-20 Jonathan Larmour <jlarmour@redhat.com> + + * tests/fileio1.c (main): Get this to actually pass! Remove + kernel dependency. + * cdl/fileio.cdl: Get CDL dependencies better. Don't use + fixed base address. Make test building an option. Build mk_romfs + and use it to construct a test romfs. + * support/mk_romfs.c: fix trivial typo + * tests/testromfs: Directory hierarchy added for constructing test + ROMFS. + +2001-07-13 Richard Panton (richard.panton@3glab.com) + + * support/mk_romfs.c: Convert between host FS file modes and eCos + ones. + +2000-10-25 Richard Panton (richard.panton@3glab.com) + + * cdl/romfs.cdl: + * src/romfs.c: + * support/mk_romfs.c: + * tests/fileio1.c: + A sample ROM filesystem implementation + + + +//=========================================================================== +// ####GPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2009, 2010 Free Software Foundation, Inc. +// +// 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 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. +// ------------------------------------------- +// ####GPLCOPYRIGHTEND#### +//=========================================================================== + + diff --git a/ecos/packages/fs/rom/current/cdl/romfs.cdl b/ecos/packages/fs/rom/current/cdl/romfs.cdl new file mode 100644 index 0000000..8aa13fe --- /dev/null +++ b/ecos/packages/fs/rom/current/cdl/romfs.cdl @@ -0,0 +1,155 @@ +# ==================================================================== +# +# romfs.cdl +# +# ROM Filesystem configuration data +# +# ==================================================================== +## ####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2009, 2010 Free Software Foundation, Inc. +## +## eCos 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 or (at your option) any later +## version. +## +## eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +## +## As a special exception, if other files instantiate templates or use +## macros or inline functions from this file, or you compile this file +## and link it with other works to produce a work based on this file, +## this file does not by itself cause the resulting work to be covered by +## the GNU General Public License. However the source code for this file +## must still be made available in accordance with section (3) of the GNU +## General Public License v2. +## +## This exception does not invalidate any other reasons why a work based +## on this file might be covered by the GNU General Public License. +## ------------------------------------------- +## ####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): nickg +# Original data: nickg +# Contributors: richard.panton@3glab.com, jld +# Date: 2000-08-01 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_FS_ROM { + display "ROM filesystem" + doc ref/fileio.html + include_dir cyg/romfs + + parent CYGPKG_IO_FILEIO + requires CYGPKG_IO_FILEIO + + requires CYGPKG_ISOINFRA + requires CYGINT_ISO_ERRNO + requires CYGINT_ISO_ERRNO_CODES + + implements CYGINT_IO_FILEIO_FS + + compile -library=libextras.a romfs.c + + cdl_option CYGBLD_FS_ROMFS_MK_ROMFS { + display "Build the tool used to build filesystems" + flavor bool + default_value 1 + + make -priority 98 { + <PREFIX>/bin/file2c.tcl: <PACKAGE>/support/file2c.tcl + @mkdir -p "$(dir $@)" + @cp $< $@ + } + + # FIXME: host compiler/flags should be provided by config system + make -priority 98 { + <PREFIX>/bin/mk_romfs: <PACKAGE>/support/mk_romfs.c + @mkdir -p "$(dir $@)" + @$(HOST_CC) -g -O2 -o $@ $< || cc -g -O2 -o $@ $< || gcc -g -O2 -o $@ $< + } + + description " + When enabled this option will build a host tool which can be + used to create a rom filesystem image." + } + + cdl_option CYGPKG_FS_ROM_RET_DIRENT_DTYPE { + display "Support for fileio's struct dirent d_type field" + flavor bool + default_value 0 + active_if CYGPKG_FILEIO_DIRENT_DTYPE + + description " + This option controls whether the ROM filesystem supports + setting fileio's struct dirent d_type field. + If this option is enabled, d_type will be set. Otherwise, + nothing will be done, d_type's value will be zero because + fileio already sets it." + } + + cdl_option CYGFUN_FS_ROM_FLASH_BLOCK_DEVICE_LOOKUP { + display "Lookup flash block device names" + flavor bool + requires CYGPKG_IO_FLASH + requires CYGPKG_IO_FLASH_BLOCK_DEVICE + default_value 0 + description "Enables the location of a ROM filesystem to + be specified using a flash block device name such as + \"/dev/flash/fis/romfs\" in the call to mount()." + } + + # ---------------------------------------------------------------- + # Tests + + cdl_component CYGTST_ROMFS_BUILD_TESTS { + display "Build ROM filesystem tests" + flavor bool + no_define + default_value 0 + requires CYGINT_LIBC_STARTUP_CONTEXT + requires CYGINT_ISO_STDIO_FORMATTED_IO + requires CYGINT_ISO_STRERROR + requires CYGBLD_FS_ROMFS_MK_ROMFS + description " + This option enables the building of the ROM filesystem tests." + + make -priority 100 { + <PREFIX>/include/cyg/romfs/testromfs_le.h : <PACKAGE>/tests/testromfs <PREFIX>/bin/mk_romfs <PREFIX>/bin/file2c.tcl + $(PREFIX)/bin/mk_romfs $< testromfs_le.bin + @mkdir -p "$(dir $@)" + tclsh $(PREFIX)/bin/file2c.tcl testromfs_le.bin $@ + } + + make -priority 100 { + <PREFIX>/include/cyg/romfs/testromfs_be.h : <PACKAGE>/tests/testromfs <PREFIX>/bin/mk_romfs <PREFIX>/bin/file2c.tcl + $(PREFIX)/bin/mk_romfs -b $< testromfs_be.bin + @mkdir -p "$(dir $@)" + tclsh $(PREFIX)/bin/file2c.tcl testromfs_be.bin $@ + } + + cdl_option CYGPKG_FS_ROM_TESTS { + display "ROM filesystem tests" + flavor data + no_define + calculated { "tests/romfs1" } + description " + This option specifies the set of tests for the ROM filesystem package." + } + } +} + +# End of romfs.cdl diff --git a/ecos/packages/fs/rom/current/doc/mk_romfs.txt b/ecos/packages/fs/rom/current/doc/mk_romfs.txt new file mode 100644 index 0000000..f322513 --- /dev/null +++ b/ecos/packages/fs/rom/current/doc/mk_romfs.txt @@ -0,0 +1,111 @@ +MK_ROMFS - Make a ROMFS image +============================= + +This program creates a ROMFS image that can be read by eCos. + +mk_romfs - Create an eCos ROMFS disk image from the files + contained under a specified directory + +Usage: ../support/mk_romfs [options] <fs_root> <fs_file> + fs_root is the directory containing the files to package into the ROMFS image + fs_file is the name of the ROMFS image file to create + Options include: + -v / -q increase / decrease verbosity + -n do everything EXCEPT creating the output file + -b write a big-endian image (default is little endian) + -l collapse hard links to a single node + +----------- +How to use. +----------- + +For example, suppose you wish to access the following directories and files: + / + /etc passwd, group + /dev + /mnt + /tmp (for a RAMFS) + /var (for a RAMFS) + +1. Create the required directories and files under a suitable root, eg. under + ~/rom: + $ mkdir ~/rom + $ cd ~/rom + $ mkdir etc dev mnt tmp var + $ cp /etc/passwd /etc/group etc/ + ( remembering to edit these files....;-) + +2. Make the romfs image in a suitable place, eg /tftpboot for direct upload to + the RedBoot monitor. + $ mk_romfs -v . /tftpboot/romfs.img + mk_romfs: Verbosity 2 little endian + Phase 1 - Build file list + Phase 2 - Calculate space allocation + Phase 2a - * Directories + Phase 2b - * Regular files + Phase 2c - * Executable files + Phase 3 - Construct ROMFS image file (3 kb) + Phase 3a - * Node table + Phase 3b - * Data blocks + /tftpboot/romfs.img completed + +3. Connect to your target RedBoot monitor, and load the romfs image. You will + need to determine a suitable place in RAM to load the image into. + $ telnet xxx.xxx.xxx.xxx 1000 + Trying xxx.xxx.xxx.xxx... + Connected to xxx.xxx.xxx.xxx. + Escape character is '^]'. + RedBoot> load romfs.img -r -v -b 0x1000000 + Raw file loaded 0x01000000-0x0100093e + RedBoot> + +4. Determine where to load the romfs image in the ROM. See what's there... + RedBoot> fis list + Name FLASH addr Mem addr Length Entry point + RedBoot 0x50000000 0x50000000 0x020000 0x00000000 + RedBoot[backup] 0x50020000 0x50020000 0x020000 0x00000000 + RedBoot config 0x503C0000 0x503C0000 0x020000 0x00000000 + FIS directory 0x503E0000 0x503E0000 0x020000 0x00000000 + RedBoot> fis free + 0x50040000 .. 0x503C0000 + RedBoot> + We can see that a suitable place would be 0x50040000. + Alternatively, you can let RedBoot determine the address itself... + +5. Copy the image from RAM to ROM... + RedBoot> fis create -b 0x1000000 -l 0x940 RomFs + ... Erase from 0x50040000-0x50040940: . + ... Program from 0x01000000-0x01000940 at 0x50040000: . + ... Erase from 0x503e0000-0x50400000: . + ... Program from 0x01fd0000-0x01ff0000 at 0x503e0000: . + RedBoot> fis list + Name FLASH addr Mem addr Length Entry point + RedBoot 0x50000000 0x50000000 0x020000 0x00000000 + RedBoot[backup] 0x50020000 0x50020000 0x020000 0x00000000 + RedBoot config 0x503C0000 0x503C0000 0x020000 0x00000000 + FIS directory 0x503E0000 0x503E0000 0x020000 0x00000000 + RomFs 0x50040000 0x01000000 0x000940 0x00000000 + RedBoot> + +6. MAKE A NOTE OF THE ADDRESS IN FLASH THAT THE IMAGE IS LOADED AT. + + This address can then be used in your program in order to mount the + filesystem. + + For example, to automatically mount the new romfs created above at + /rom, you can use the following macro in your application: + + MTAB_ENTRY( romfs_mte1, + "/rom", + "romfs", + "", + (CYG_ADDRWORD) 0x50040000 ); + + See the File I/O package documentation in the eCos Reference Manual + ("Writing a New Filesystem") for more information about the MTAB_ENTRY + macro. + + Alternatively, the filesystem can be dynamically mounted with a call + to mount() such as the following: + + err = mount( "0x50040000", "/rom", "romfs" ); diff --git a/ecos/packages/fs/rom/current/doc/romfs.txt b/ecos/packages/fs/rom/current/doc/romfs.txt new file mode 100644 index 0000000..7b34a13 --- /dev/null +++ b/ecos/packages/fs/rom/current/doc/romfs.txt @@ -0,0 +1,12 @@ +ROMFS - A rom filesystem plug-in module for eCos +================================================ + +You can use this module if you have flash ROM available to install the +filesystem into. Instructions are given for creating and installing a +rom filesystem into a RedBoot monitor. + +See mk_romfs for instructions for making the filesystem. + +See romfs.c for comments about the filesystem structure. + + diff --git a/ecos/packages/fs/rom/current/src/romfs.c b/ecos/packages/fs/rom/current/src/romfs.c new file mode 100644 index 0000000..b748200 --- /dev/null +++ b/ecos/packages/fs/rom/current/src/romfs.c @@ -0,0 +1,1138 @@ +//========================================================================== +// +// romfs.c +// +// ROM file system +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos 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 or (at your option) any later +// version. +// +// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg, richard.panton@3glab.com +// Date: 2000-07-25 +// Purpose: ROM file system +// Description: This is a ROM filesystem for eCos. It attempts to +// provide full POSIX-compatible filesystem behaviour +// while at the same time being efficient in terms of +// time and space used. +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +// +// General Description +// =================== +// +// This is an implementation of a ROM filesystem for eCos. Its goal is +// to provide a working example of a filesystem that provides most of +// the required POSIX functionality. And obviously it may also be +// useful in its own right. +// +// +// Header +// ------ +// +// There is a single header that describes the overall format of the ROMFS +// disk. The address of this header is used as the base for all offsets used +// in the node and directory structures. It contains the following fields: +// +// label - A human readable label for various purposes +// fssize - The size in bytes of the entire ROMFS disk +// nodes - A count of the nodes in the disk +// +// Immediately following thisin memory is the node table, consisting of +// 'nodes' repetitions of the node object. +// +// Nodes +// ----- +// +// All files and directories are represented by node objects. Each +// romfs_node structure contains the following fields: +// +// mode - Node type, file or directory. +// nlink - Number of links to this node. Each directory entry that references +// this node is a link. +// size - Size of the data in this node in bytes. +// ctime - Creation time of the file (NOT the ROMFS) +// data - Offset of the first data byte for this node from the header +// +// Directories +// ----------- +// +// A directory is a node whose data is a list of directory entries. +// These contain the +// following fields: +// +// node - Index of the node in the romfs_disk table that is referenced by +// this entry. This is present in every directory entry fragment. +// next - Offset of the next name entry. +// name - The filename associated with this link to the node. +// +// Data Storage +// ------------ +// +// Each file has its data stored in a single contiguous memory block +// referenced by the offset in the node. +// +//========================================================================== + +#include <pkgconf/system.h> +#include <pkgconf/hal.h> +#include <pkgconf/kernel.h> +#include <pkgconf/io_fileio.h> +#include <pkgconf/fs_rom.h> + +#include <cyg/kernel/ktypes.h> // base kernel types +#include <cyg/infra/cyg_trac.h> // tracing macros +#include <cyg/infra/cyg_ass.h> // assertion macros + +#include <unistd.h> +#include <sys/types.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <errno.h> +#include <dirent.h> + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <cyg/fileio/fileio.h> + +#include <cyg/kernel/kapi.h> +#include <cyg/infra/diag.h> + +#if defined(CYGFUN_FS_ROM_FLASH_BLOCK_DEVICE_LOOKUP) +#include <cyg/io/io.h> +#include <cyg/io/config_keys.h> +#include <cyg/io/flash.h> +#endif + +//========================================================================== +// Eventually we want to eXecute In Place from the ROM in a protected +// environment, so we'll need executables to be aligned to a boundary +// suitable for MMU protection. A suitable boundary would be the 4k +// boundary in all the CPU architectures I am currently aware of. + +// Forward definitions + +// Filesystem operations +static int romfs_mount ( cyg_fstab_entry *fste, cyg_mtab_entry *mte ); +static int romfs_umount ( cyg_mtab_entry *mte ); +static int romfs_open ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, + int mode, cyg_file *fte ); +static int romfs_opendir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, + cyg_file *fte ); +static int romfs_chdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, + cyg_dir *dir_out ); +static int romfs_stat ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, + struct stat *buf); +static int romfs_getinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, + int key, void *buf, int len ); +static int romfs_setinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, + int key, void *buf, int len ); + +// File operations +static int romfs_fo_read (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio); +static int romfs_fo_lseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence ); +static int romfs_fo_ioctl (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com, + CYG_ADDRWORD data); +static int romfs_fo_fsync (struct CYG_FILE_TAG *fp, int mode ); +static int romfs_fo_close (struct CYG_FILE_TAG *fp); +static int romfs_fo_fstat (struct CYG_FILE_TAG *fp, struct stat *buf ); +static int romfs_fo_getinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len ); +static int romfs_fo_setinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len ); + +// Directory operations +static int romfs_fo_dirread (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio); +static int romfs_fo_dirlseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence ); + + +//========================================================================== +// Filesystem table entries + +// ------------------------------------------------------------------------- +// Fstab entry. +// This defines the entry in the filesystem table. +// For simplicity we use _FILESYSTEM synchronization for all accesses since +// we should never block in any filesystem operations. + +FSTAB_ENTRY( romfs_fste, "romfs", 0, + CYG_SYNCMODE_FILE_FILESYSTEM|CYG_SYNCMODE_IO_FILESYSTEM, + romfs_mount, + romfs_umount, + romfs_open, + (cyg_fsop_unlink *)cyg_fileio_erofs, + (cyg_fsop_mkdir *)cyg_fileio_erofs, + (cyg_fsop_rmdir *)cyg_fileio_erofs, + (cyg_fsop_rename *)cyg_fileio_erofs, + (cyg_fsop_link *)cyg_fileio_erofs, + romfs_opendir, + romfs_chdir, + romfs_stat, + romfs_getinfo, + romfs_setinfo); + +// ------------------------------------------------------------------------- +// mtab entry. +// This defines a single ROMFS loaded into ROM at the configured address +// +// MTAB_ENTRY( rom_mte, // structure name +// "/rom", // mount point +// "romfs", // FIlesystem type +// "", // hardware device +// (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS // Address in ROM +// ); + + +// ------------------------------------------------------------------------- +// File operations. +// This set of file operations are used for normal open files. + +static cyg_fileops romfs_fileops = +{ + romfs_fo_read, + (cyg_fileop_write *)cyg_fileio_erofs, + romfs_fo_lseek, + romfs_fo_ioctl, + cyg_fileio_seltrue, + romfs_fo_fsync, + romfs_fo_close, + romfs_fo_fstat, + romfs_fo_getinfo, + romfs_fo_setinfo +}; + +// ------------------------------------------------------------------------- +// Directory file operations. +// This set of operations are used for open directories. Most entries +// point to error-returning stub functions. Only the read, lseek and +// close entries are functional. + +static cyg_fileops romfs_dirops = +{ + romfs_fo_dirread, + (cyg_fileop_write *)cyg_fileio_enosys, + romfs_fo_dirlseek, + (cyg_fileop_ioctl *)cyg_fileio_enosys, + cyg_fileio_seltrue, + (cyg_fileop_fsync *)cyg_fileio_enosys, + romfs_fo_close, + (cyg_fileop_fstat *)cyg_fileio_enosys, + (cyg_fileop_getinfo *)cyg_fileio_enosys, + (cyg_fileop_setinfo *)cyg_fileio_enosys +}; + +//========================================================================== +// Data typedefs +// Some forward typedefs for the main data structures. + +struct romfs_disk; +typedef struct romfs_disk romfs_disk; + +struct romfs_node; +typedef struct romfs_node romfs_node; + +struct romfs_dirent; +typedef struct romfs_dirent romfs_dirent; + +//========================================================================== +// File and directory node +// This data structure represents a file or directory. + +struct romfs_node +{ + cyg_uint32 mode; // 0-3 node type + cyg_ucount32 nlink; // 4-7 number of links to this node + cyg_uint16 uid; // 8-9 Owner id + cyg_uint16 gid; // 10-11 Group id + cyg_uint32 size; // 12-15 size of file in bytes + cyg_uint32 ctime; // 16-19 creation status time + cyg_uint32 offset; // 20-23 offset of data from start of ROMFS + cyg_uint32 pad[2]; // 24-31 padding to align to 32byte boundary +}; + +//========================================================================== +// Directory entry. +// Variable sized entry containing the name and node of a directory entry + +struct romfs_dirent +{ + cyg_ucount32 node; // Index of node in romfs_disk structure + cyg_uint32 next; // Offset from start of directory of + // a) the next entry, or + // b) the end of the directory data + char name[0]; // The name, NUL terminated +}; + +//========================================================================== +// ROMFS header +// This data structure contains overall information on the ROMFS + +struct romfs_disk +{ + cyg_uint32 magic; // 0-3 Marks a valid ROMFS entry + cyg_ucount32 nodecount; // 4-7 Count of nodes in this filesystem + cyg_ucount32 disksize; // 8-11 Count of bytes in this filesystem + cyg_uint32 dev_id; // 12-15 ID of disk (put into stat.st_dev) + char name[16]; // 16-31 Name - pads to 32 bytes + romfs_node node[0]; +}; + +#define ROMFS_MAGIC 0x526f6d2e // The magic signature word for a romfs +#define ROMFS_CIGAM 0x2e6d6f52 // The byte sex is wrong if you see this + +//========================================================================== +// Directory search data +// Parameters for a directory search. The fields of this structure are +// updated as we follow a pathname through the directory tree. + +struct romfs_dirsearch +{ + romfs_disk *disk; // disk structure + romfs_node *dir; // directory to search + const char *path; // path to follow + romfs_node *node; // Node found + const char *name; // last name used + int namelen; // name fragment length + cyg_bool last; // last name in path? +}; + +typedef struct romfs_dirsearch romfs_dirsearch; + +//========================================================================== +// This seems to be the only string function referenced. Define as static +// here to avoid having to load the string library + +static bool match( const char *a, const char *b, int len ) +{ + for ( ; len > 0 && *a && *b && *a == *b ; a++, b++, len-- ) + ; + return ( len == 0 && *a == 0 ); +} + + +//========================================================================== +// SIMPLE buffer management. +// Each node has a data buffer pointer and a size. + +// ------------------------------------------------------------------------- +// findbuffer_node() +// return a pointer to the data at the indicated file position. + +static int findbuffer_node( romfs_disk *disk, // header pointer + romfs_node *node, // node pointer + off_t pos, // data position to get + cyg_uint8 **buffer, // returned buffer pointer + size_t *size) // returned buffer size +{ + if ( pos >= node->size || node->size == 0 ) + { + // Indicate end of data. + *size = 0; + } else { + + // Calculate the buffer position + *buffer = (cyg_uint8*)disk + node->offset + pos; + *size = node->size-pos; + } + + return ENOERR; +} + +//========================================================================== +// Directory operations + + +// ------------------------------------------------------------------------- +// find_direntry() +// Find a directory entry for the name and return a pointer to the first +// entry fragment. + +static romfs_dirent *find_direntry( romfs_disk *disk, romfs_node *dir, const char *name, int namelen ) +{ + off_t pos = 0; + int err; + + // Loop over all the entries until a match is found or we run out + // of data. + while( pos < dir->size ) + { + romfs_dirent *d; + cyg_uint8 *buf; + size_t size; + + err = findbuffer_node( disk, dir, pos, &buf, &size ); + if( err != ENOERR || size == 0) + return NULL; + + d = (romfs_dirent *)buf; + + // Is this the directory entry we're looking for? + if ( match( d->name, name, namelen ) ) + return d; + + // Otherwise move on to next entry in chain + pos = d->next; + } + + return NULL; +} + +//========================================================================== +// Directory search + +// ------------------------------------------------------------------------- +// init_dirsearch() +// Initialize a dirsearch object to start a search + +static void init_dirsearch( romfs_dirsearch *ds, + romfs_disk *disk, + romfs_node *dir, + const char *name) +{ + ds->disk = disk; + ds->dir = dir; + ds->path = name; + ds->node = dir; + ds->name = name; + ds->namelen = 0; + ds->last = false; +} + +// ------------------------------------------------------------------------- +// find_entry() +// Search a single directory for the next name in a path and update the +// dirsearch object appropriately. + +static int find_entry( romfs_dirsearch *ds ) +{ + romfs_node *dir = ds->dir; + const char *name = ds->path; + const char *n = name; + int namelen = 0; + romfs_dirent *d; + + // check that we really have a directory + if( !S_ISDIR(dir->mode) ) + return ENOTDIR; + + // Isolate the next element of the path name. + while( *n != '\0' && *n != '/' ) + n++, namelen++; + + // Check if this is the last path element. + while( *n == '/') n++; + if( *n == '\0' ) + ds->last = true; + + // update name in dirsearch object + ds->name = name; + ds->namelen = namelen; + + // Here we have the name and its length set up. + // Search the directory for a matching entry + + d = find_direntry( ds->disk, dir, name, namelen ); + + if( d == NULL ) + return ENOENT; + + // pass back the node we have found + ds->node = &ds->disk->node[d->node]; + + return ENOERR; + +} + +// ------------------------------------------------------------------------- +// romfs_find() +// Main interface to directory search code. This is used in all file +// level operations to locate the object named by the pathname. + +static int romfs_find( romfs_dirsearch *d ) +{ + int err; + + // Short circuit empty paths + if( *(d->path) == '\0' ) + return ENOERR; + + // iterate down directory tree until we find the object + // we want. + for(;;) + { + err = find_entry( d ); + + if( err != ENOERR ) + return err; + + if( d->last ) + return ENOERR; + + // Update dirsearch object to search next directory. + d->dir = d->node; + d->path += d->namelen; + while( *(d->path) == '/' ) d->path++; // skip dirname separators + } +} + +//========================================================================== +// Pathconf support +// This function provides support for pathconf() and fpathconf(). + +static int romfs_pathconf( romfs_node *node, struct cyg_pathconf_info *info ) +{ + int err = ENOERR; + + switch( info->name ) + { + case _PC_LINK_MAX: + info->value = LINK_MAX; + break; + + case _PC_MAX_CANON: + info->value = -1; // not supported + err = EINVAL; + break; + + case _PC_MAX_INPUT: + info->value = -1; // not supported + err = EINVAL; + break; + + case _PC_NAME_MAX: + info->value = NAME_MAX; + break; + + case _PC_PATH_MAX: + info->value = PATH_MAX; + break; + + case _PC_PIPE_BUF: + info->value = -1; // not supported + err = EINVAL; + break; + + + case _PC_ASYNC_IO: + info->value = -1; // not supported + err = EINVAL; + break; + + case _PC_CHOWN_RESTRICTED: + info->value = -1; // not supported + err = EINVAL; + break; + + case _PC_NO_TRUNC: + info->value = 0; + break; + + case _PC_PRIO_IO: + info->value = 0; + break; + + case _PC_SYNC_IO: + info->value = 0; + break; + + case _PC_VDISABLE: + info->value = -1; // not supported + err = EINVAL; + break; + + default: + err = EINVAL; + break; + } + + return err; +} + +//========================================================================== +// Filesystem operations + +// ------------------------------------------------------------------------- +// romfs_mount() +// Process a mount request. This mainly finds root for the +// filesystem. + +static int romfs_mount ( cyg_fstab_entry *fste, cyg_mtab_entry *mte ) +{ + romfs_disk *disk=NULL; + + if ( !mte->data ) { + // If the image address was not in the MTE data word, + if ( mte->devname && mte->devname[0] ) { + // If a device name specified, lookup flash block device. +#if defined(CYGFUN_FS_ROM_FLASH_BLOCK_DEVICE_LOOKUP) + if ( mte->devname[0] == '/' ) { + Cyg_ErrNo err; + cyg_io_handle_t t; + cyg_io_flash_getconfig_devaddr_t d; + int len; + err = cyg_io_lookup(mte->devname, &t); + if (err != ENOERR) { + return -err; + } + len = sizeof(d); + err = cyg_io_get_config(t, CYG_IO_GET_CONFIG_FLASH_DEVADDR, &d, &len); + if (err != ENOERR) { + return -err; + } + disk = (romfs_disk *) d.dev_addr; + } else +#endif + { + char *addr; + // And there's something in the 'hardware device' field, + // then read the address from there. + sscanf( mte->devname, "%p", &addr ); + disk = (romfs_disk *) addr; + } + } + } else { + disk = (romfs_disk *)mte->data; + } + + if ( !disk ) { + // If still no address, try the FSTAB entry data word + disk = (romfs_disk *)fste->data; + } + + if ( !disk ) { + // If still no address, give up... + return ENOENT; + } + + + + // Check the ROMFS magic number to ensure that there's really an fs. + if ( disk->magic == ROMFS_CIGAM ) { + // The disk image has the wrong byte sex!!! + return EIO; + } else if ( disk->magic != ROMFS_MAGIC || disk->nodecount == 0 ) { + // No image found + return ENOENT; + } + + mte->root = (cyg_dir)&disk->node[0]; + + mte->data = (CYG_ADDRWORD)disk; + return ENOERR; +} + +// ------------------------------------------------------------------------- +// romfs_umount() +// Unmount the filesystem. This will currently always succeed. + +static int romfs_umount ( cyg_mtab_entry *mte ) +{ + // Clear root pointer + mte->root = CYG_DIR_NULL; + + // That's all folks. + + return ENOERR; +} + +// ------------------------------------------------------------------------- +// romfs_open() +// Open a file for reading + +static int romfs_open ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, + int mode, cyg_file *file ) +{ + + romfs_dirsearch ds; + romfs_node *node = NULL; + int err; + + init_dirsearch( &ds, (romfs_disk *)mte->data, (romfs_node *)dir, name ); + + err = romfs_find( &ds ); + + if( err == ENOENT ) + { + return ENOENT; + } + else if( err == ENOERR ) + { + // The node exists. If the O_CREAT and O_EXCL bits are set, we + // must fail the open. + + if( (mode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) ) + err = EEXIST; + else node = ds.node; + } + + if( err == ENOERR && (mode & O_TRUNC ) ) + { + // If the O_TRUNC bit is set we must fail the open + + err = EPERM; + } + + if( err != ENOERR ) return err; + + // Check that we actually have a file here + if( S_ISDIR(node->mode) ) return EISDIR; + + // Initialize the file object + + file->f_flag |= mode & CYG_FILE_MODE_MASK; + file->f_type = CYG_FILE_TYPE_FILE; + file->f_ops = &romfs_fileops; + file->f_offset = 0; + file->f_data = (CYG_ADDRWORD)node; + file->f_xops = 0; + + return ENOERR; +} + +// ------------------------------------------------------------------------- +// romfs_opendir() +// Open a directory for reading. + +static int romfs_opendir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, + cyg_file *file ) +{ + romfs_dirsearch ds; + int err; + + init_dirsearch( &ds, (romfs_disk *)mte->data, (romfs_node *)dir, name ); + + err = romfs_find( &ds ); + + if( err != ENOERR ) return err; + + // check it is really a directory. + if( !S_ISDIR(ds.node->mode) ) return ENOTDIR; + + // Initialize the file object, setting the f_ops field to a + // special set of file ops. + + file->f_type = CYG_FILE_TYPE_FILE; + file->f_ops = &romfs_dirops; + file->f_offset = 0; + file->f_data = (CYG_ADDRWORD)ds.node; + file->f_xops = 0; + + return ENOERR; + +} + +// ------------------------------------------------------------------------- +// romfs_chdir() +// Change directory support. + +static int romfs_chdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, + cyg_dir *dir_out ) +{ + if( dir_out != NULL ) + { + // This is a request to get a new directory pointer in + // *dir_out. + + romfs_dirsearch ds; + int err; + + init_dirsearch( &ds, (romfs_disk *)mte->data, (romfs_node *)dir, name ); + + err = romfs_find( &ds ); + + if( err != ENOERR ) return err; + + // check it is a directory + if( !S_ISDIR(ds.node->mode) ) + return ENOTDIR; + + // Pass it out + *dir_out = (cyg_dir)ds.node; + } + // If no output dir is required, this means that the mte and + // dir arguments are the current cdir setting and we should + // forget this fact. Do nothing in ROMFS. + + return ENOERR; +} + +// ------------------------------------------------------------------------- +// romfs_stat() +// Get struct stat info for named object. + +static int romfs_stat ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, + struct stat *buf) +{ + romfs_dirsearch ds; + int err; + romfs_disk *disk = (romfs_disk *)mte->data; + + init_dirsearch( &ds, disk, (romfs_node *)dir, name ); + + err = romfs_find( &ds ); + + if( err != ENOERR ) return err; + + // Fill in the status + buf->st_mode = ds.node->mode; + buf->st_ino = (ino_t)(ds.node - &disk->node[0]); + buf->st_dev = (dev_t)disk->dev_id; + buf->st_nlink = ds.node->nlink; + buf->st_uid = ds.node->uid; + buf->st_gid = ds.node->gid; + buf->st_size = ds.node->size; + buf->st_atime = ds.node->ctime; + buf->st_mtime = ds.node->ctime; + buf->st_ctime = ds.node->ctime; + + return err; +} + +// ------------------------------------------------------------------------- +// romfs_getinfo() +// Getinfo. Currently only support pathconf() and file system block usage + +static int romfs_getinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, + int key, void *buf, int len ) +{ + romfs_dirsearch ds; + int err; + + init_dirsearch( &ds, (romfs_disk *)mte->data, (romfs_node *)dir, name ); + + err = romfs_find( &ds ); + + if( err != ENOERR ) return err; + + switch( key ) + { + case FS_INFO_CONF: + err = romfs_pathconf( ds.node, (struct cyg_pathconf_info *)buf ); + break; +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) + case FS_INFO_BLOCK_USAGE: { + struct cyg_fs_block_usage *usage = (struct cyg_fs_block_usage *) buf; + struct romfs_disk *disk = (struct romfs_disk*) mte->data; + usage->total_blocks = disk->disksize; + usage->free_blocks = 0; + usage->block_size = 1; + return ENOERR; + } +#endif + default: + err = EINVAL; + } + return err; +} + +// ------------------------------------------------------------------------- +// romfs_setinfo() +// Setinfo. Nothing to support here at present. + +static int romfs_setinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, + int key, void *buf, int len ) +{ + // No setinfo keys supported at present + + return EINVAL; +} + + +//========================================================================== +// File operations + +// ------------------------------------------------------------------------- +// romfs_fo_read() +// Read data from the file. + +static int romfs_fo_read (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio) +{ + romfs_node *node = (romfs_node *)fp->f_data; + int i; + off_t pos = fp->f_offset; + ssize_t resid = uio->uio_resid; + + // Loop over the io vectors until there are none left + for( i = 0; i < uio->uio_iovcnt; i++ ) + { + cyg_iovec *iov = &uio->uio_iov[i]; + char *buf = (char *)iov->iov_base; + off_t len = iov->iov_len; + + // Loop over each vector filling it with data from the file. + while( len > 0 && pos < node->size ) + { + cyg_uint8 *fbuf; + size_t bsize; + off_t l = len; + int err; + + // Get a pointer to the data at offset _pos_. + err = findbuffer_node( (romfs_disk *)fp->f_mte->data, node, pos, &fbuf, &bsize ); + + if( err != ENOERR ) + return err; + + // adjust size to end of file if necessary + if( l > node->size-pos ) + l = node->size-pos; + + // adjust size to the amount of contiguous data we can see + // at present. + if( l > bsize ) + l = bsize; + + // copy data out + memcpy( buf, fbuf, l ); + + // Update working vars + len -= l; + buf += l; + pos += l; + resid -= l; + } + } + + // We successfully read some data + // Update the file offset and transfer residue. + + uio->uio_resid = resid; + fp->f_offset = pos; + + return ENOERR; +} + +// ------------------------------------------------------------------------- +// romfs_fo_lseek() +// Seek to a new file position. + +static int romfs_fo_lseek (struct CYG_FILE_TAG *fp, off_t *apos, int whence ) +{ + romfs_node *node = (romfs_node *)fp->f_data; + off_t pos = *apos; + + switch( whence ) + { + case SEEK_SET: + // Pos is already where we want to be. + break; + + case SEEK_CUR: + // Add pos to current offset. + pos += fp->f_offset; + break; + + case SEEK_END: + // Add pos to file size. + pos += node->size; + break; + + default: + return EINVAL; + } + + // Check that pos is still within current file size, or at the + // very end. + if( pos < 0 || pos > node->size ) + return EINVAL; + + // All OK, set fp offset and return new position. + *apos = fp->f_offset = pos; + + return ENOERR; +} + +// ------------------------------------------------------------------------- +// romfs_fo_ioctl() +// Handle ioctls. Currently none are defined. + +static int romfs_fo_ioctl (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com, + CYG_ADDRWORD data) +{ + // No Ioctls currenly defined. + + return EINVAL; +} + +// ------------------------------------------------------------------------- +// romfs_fo_fsync(). +// Force the file out to data storage. + +static int romfs_fo_fsync (struct CYG_FILE_TAG *fp, int mode ) +{ + // Data is always permanently where it belongs, nothing to do + // here. + + return ENOERR; +} + +// ------------------------------------------------------------------------- +// romfs_fo_close() +// Close a file. We just clear out the data pointer. + +static int romfs_fo_close (struct CYG_FILE_TAG *fp) +{ + fp->f_data = 0; // zero data pointer + + return ENOERR; +} + +// ------------------------------------------------------------------------- +//romfs_fo_fstat() +// Get file status. + +static int romfs_fo_fstat (struct CYG_FILE_TAG *fp, struct stat *buf ) +{ + romfs_node *node = (romfs_node *)fp->f_data; + romfs_disk *disk = (romfs_disk*)(fp->f_mte->data); + + // Fill in the status + buf->st_mode = node->mode; + buf->st_ino = (ino_t)(node - &disk->node[0]); + buf->st_dev = disk->dev_id; + buf->st_nlink = node->nlink; + buf->st_uid = node->uid; + buf->st_gid = node->gid; + buf->st_size = node->size; + buf->st_atime = node->ctime; + buf->st_mtime = node->ctime; + buf->st_ctime = node->ctime; + + return ENOERR; +} + +// ------------------------------------------------------------------------- +// romfs_fo_getinfo() +// Get info. Currently only supports fpathconf(). + +static int romfs_fo_getinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len ) +{ + romfs_node *node = (romfs_node *)fp->f_data; + int err; + + switch( key ) + { + case FS_INFO_CONF: + err = romfs_pathconf( node, (struct cyg_pathconf_info *)buf ); + break; + + default: + err = EINVAL; + } + return err; +} + +// ------------------------------------------------------------------------- +// romfs_fo_setinfo() +// Set info. Nothing supported here. + +static int romfs_fo_setinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len ) +{ + // No setinfo key supported at present + + return ENOERR; +} + + +//========================================================================== +// Directory operations + +// ------------------------------------------------------------------------- +// romfs_fo_dirread() +// Read a single directory entry from a file. + +static int romfs_fo_dirread (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio) +{ + romfs_node *dir = (romfs_node *)fp->f_data; + off_t pos = fp->f_offset; + int err = ENOERR; + struct dirent *ent = (struct dirent *)uio->uio_iov[0].iov_base; + char *nbuf = ent->d_name; + int nlen = sizeof(ent->d_name)-1; + off_t len = uio->uio_iov[0].iov_len; + romfs_dirent *d = NULL; + cyg_uint8 *buf; + size_t size; + int i; + + if( len < sizeof(struct dirent) ) + return EINVAL; + + // Get the next entry + err = findbuffer_node( (romfs_disk *)fp->f_mte->data, dir, pos, &buf, &size ); + if( err != ENOERR || size == 0 || pos >= dir->size ) + return err; + + d = (romfs_dirent *)buf; + + for ( i = 0 ; i < nlen && d->name[i] ; i++, nbuf++ ) + *nbuf = d->name[i]; +#ifdef CYGPKG_FS_ROM_RET_DIRENT_DTYPE + ent->d_type = (((romfs_disk *)fp->f_mte->data)->node[d->node]).mode; +#endif + + // A successful read. Terminate the entry name with a NUL, set the + // residue and set the file offset to restart at the next + // directory entry. + + *nbuf = '\0'; + uio->uio_resid -= sizeof(struct dirent); + fp->f_offset = d->next; + + return ENOERR; +} + +// ------------------------------------------------------------------------- +// romfs_fo_dirlseek() +// Seek directory to start. + +static int romfs_fo_dirlseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence ) +{ + // Only allow SEEK_SET to zero + + if( whence != SEEK_SET || *pos != 0) + return EINVAL; + + *pos = fp->f_offset = 0; + + return ENOERR; +} + +// ------------------------------------------------------------------------- +// EOF romfs.c diff --git a/ecos/packages/fs/rom/current/support/Makefile b/ecos/packages/fs/rom/current/support/Makefile new file mode 100644 index 0000000..985e8fc --- /dev/null +++ b/ecos/packages/fs/rom/current/support/Makefile @@ -0,0 +1,38 @@ +#========================================================================== +## ####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +## +## eCos 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 or (at your option) any later +## version. +## +## eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +## +## As a special exception, if other files instantiate templates or use +## macros or inline functions from this file, or you compile this file +## and link it with other works to produce a work based on this file, +## this file does not by itself cause the resulting work to be covered by +## the GNU General Public License. However the source code for this file +## must still be made available in accordance with section (3) of the GNU +## General Public License v2. +## +## This exception does not invalidate any other reasons why a work based +## on this file might be covered by the GNU General Public License. +## ------------------------------------------- +## ####ECOSGPLCOPYRIGHTEND#### +#========================================================================== + +CC = gcc +CFLAGS = -ggdb -Wall + +mk_romfs: diff --git a/ecos/packages/fs/rom/current/support/file2c.tcl b/ecos/packages/fs/rom/current/support/file2c.tcl new file mode 100755 index 0000000..1313c6d --- /dev/null +++ b/ecos/packages/fs/rom/current/support/file2c.tcl @@ -0,0 +1,118 @@ +#!/usr/bin/env tclsh + +#=============================================================================== +# +# file2c.tcl +# +# Convert a file into a header that can be #included from C. +# +#=============================================================================== +## ####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +## +## eCos 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 or (at your option) any later +## version. +## +## eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +## +## As a special exception, if other files instantiate templates or use +## macros or inline functions from this file, or you compile this file +## and link it with other works to produce a work based on this file, +## this file does not by itself cause the resulting work to be covered by +## the GNU General Public License. However the source code for this file +## must still be made available in accordance with section (3) of the GNU +## General Public License v2. +## +## This exception does not invalidate any other reasons why a work based +## on this file might be covered by the GNU General Public License. +## ------------------------------------------- +## ####ECOSGPLCOPYRIGHTEND#### +#=============================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): jlarmour,bartv +# Contact(s): +# Date: 2001-07-20 +# Purpose: +# Description: +# Usage: file2c.tcl <file to encode> <output C header file> +# +#####DESCRIPTIONEND#### +#=============================================================================== + + + +if { $argc != 2 } { + puts "Usage: file2c.tcl <file to encode> <output C header file>" + exit 1 +} +set infile [lindex $argv 0] +set outfile [lindex $argv 1] + +set status [ catch { + set infilefd [open $infile "r"] + fconfigure $infilefd -translation binary + set data [read $infilefd] + close $infilefd +} message] + +if { $status != 0 } { + error "Unable to read file $infile: $message" +} + +set result "" + +set status [ catch { + set outfilefd [ open $outfile "w" ] +} message ] + +if { $status != 0 } { + error "Unable to create file $outfile: $message" +} + +append result "/* This is a generated file. Do not edit. */\n\n" +append result "static CYGBLD_ATTRIB_ALIGN(4) const unsigned char filedata\[\] = {\n" + +set datalength [ string length $data ] + +set aligned_datalength [expr $datalength - ($datalength % 8)] + +for { set i 0 } {$i < $aligned_datalength} {incr i 8} { + binary scan $data "@[set i]H16" var0 + append result [format " 0x%2s, 0x%2s, 0x%2s, 0x%2s, 0x%2s, 0x%2s, 0x%2s, 0x%2s,\n" \ + [string range $var0 0 1] \ + [string range $var0 2 3] \ + [string range $var0 4 5] \ + [string range $var0 6 7] \ + [string range $var0 8 9] \ + [string range $var0 10 11] \ + [string range $var0 12 13] \ + [string range $var0 14 15]] +} + +if { $aligned_datalength != $datalength } { + append result " " + for { set i $aligned_datalength } {$i < $datalength} {incr i} { + binary scan $data "@[set i]H2" var0 + append result [format "0x%2s, " $var0] + } +} + +# Remove either comma+newline or comma+space from the end +set result [string range $result 0 [expr [string length $result] - 3]] + +append result "\n};" + +puts $outfilefd $result +close $outfilefd diff --git a/ecos/packages/fs/rom/current/support/mk_romfs.c b/ecos/packages/fs/rom/current/support/mk_romfs.c new file mode 100644 index 0000000..6bde153 --- /dev/null +++ b/ecos/packages/fs/rom/current/support/mk_romfs.c @@ -0,0 +1,744 @@ +//========================================================================== +// +// mk_romfs.c +// +// Create ROM file system image +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2010 Free Software Foundation, Inc. +// +// eCos 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 or (at your option) any later +// version. +// +// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): richard.panton@3glab.com +// Contributors: richard.panton@3glab.com +// Date: 2000-07-25 +// Purpose: ROM file system +// Description: This program creates a ROM file system image, suitable +// for use with the sample ROM file system implemented by +// this package. +// * CAUTION! * This is host code and can only be built +// in a host, e.g. Linux, environment. +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <dirent.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <stdint.h> + +//========================================================================== +// +// CONFIGURABLE ITEMS HERE +// +//========================================================================== + +// define LONG to be a four byte unsigned integer on the host +#define LONG uint32_t + +// define SHORT to be a two byte unsigned integer on the host +#define SHORT uint16_t + +// All data files should be aligned to this sized boundary (minimum probably 32) +#define DATA_ALIGN 32 + +// The data stored in a directory should be aligned to this size boundary +#define DIRECTORY_ALIGN 32 + +// All executable files should be aligned to this sized boundary (minimum probably 32) +#define EXEC_ALIGN 32 + +// Undefine this if the host filesystem does not support lstat() +#define HAS_LSTAT + +// Win32 definitions +#ifdef _WIN32 +#undef HAS_LSTAT +#define S_ISLNK(m) (0) +typedef unsigned int uid_t; +typedef unsigned int gid_t; +#endif + +//========================================================================== + +// Return (n) aligned to the next (b) byte boundary +#define ALIGN_TO( n, b ) (( (n) + (b)-1 ) & ~((b)-1)) + +// Set the stat call to use +#ifdef HAS_LSTAT +#define get_status( p, b ) lstat( (p), (b) ) +#else +#define get_status( p, b ) stat( (p), (b) ) +#endif + +// This is how we identify a directory from its mode +#define IS_DIRECTORY( m ) (S_ISDIR(m)) + +// This is how we identify a data file from its mode +#define IS_DATAFILE( m ) (S_ISREG(m) && ((m)&S_IXUSR) == 0 ) + +// This is how we identify an executable from its mode +#define IS_EXECUTABLE( m ) (S_ISREG(m) && ((m)&S_IXUSR) != 0 ) + +// This is how we identify a symbolic link from its mode +#define IS_SYMLINK( m ) (S_ISLNK(m)) + +#define ROMFS_MAGIC 0x526f6d2e + +//========================================================================= +// EXIT CODES +#define EXIT_SUCCESS 0 +#define EXIT_ARGS 1 +#define EXIT_MALLOC 2 +#define EXIT_FILESYS 3 +#define EXIT_WRITE 4 +#define EXIT_SEEK 5 +#define EXIT_COMPILE 6 +#define EXIT_BUG 7 + + + +// These are the structures we will build into the ROMFS image. +// The sizes of these structures should be fixed for all architectures +typedef struct romfs_dirent { + LONG node; // 4 + LONG next; // 8 + char name[0]; // 8 + strlen(name) + 1 +} romfs_dirent; // Aligns to next 32 byte boundary + +typedef struct romfs_node { + LONG mode; // 4 + LONG nlink; // 8 + SHORT uid; // 10 + SHORT gid; // 12 + LONG size; // 16 + LONG ctime; // 20 + LONG data_offset; // 24 + char pad[8]; // 32 +} romfs_node; // Next node begins here + +typedef struct romfs_disk { + LONG magic; // 4 + LONG nodecount; // 8 + LONG disksize; // 12 + LONG dev_id; // 16 + char name[16]; // 32 +} romfs_disk; // Nodes start here + +// This is the holding structure for a node +typedef struct node { + const char *path; // Filename (inc. path) of a link to this node + size_t size; // Size of file/directory/link + mode_t st_mode; // Type and permissions + uid_t uid; // Owner id + gid_t gid; // Group id + time_t ctime; // File creation time + int nodenum; // Nodenumber of this node in the ROMFS image + dev_t device; // Device (for hardlink check) + ino_t inode; // Inode (for hardlink check) + int nlink; // [DIRECTORIES] Number of sub-directories [FILES] hard links + romfs_dirent *entry; // [DIRECTORIES] Points to an array of directory entries + int entry_size; // Size to be allocated to file (includes alignment bytes) + unsigned long offset; // Offset within ROMFS image of data + struct node *sibling; // Points to the next entry in this directory + struct node *child; // [DIRECTORIES] Points to any subdirectories + struct node *next_in_rom; // Next in ROMFS write order + struct node *next_multilink;// Next node that is multilinked +} node; + +static int nodes = 0; +static char *prog; +static int verbose = 1; +static int dowrite = 1; +static int bigendian = 0; +static int hardlinks = 0; +static unsigned long coffset = 0; +static node * first = NULL; +static node ** last_p = &first; +static node * first_multilink = NULL; +static node ** last_multilink_p = &first_multilink; +static int fd = -1; + +#define VERB_NONE 0 +#define VERB_MINIMUM 1 +#define VERB_SUB 2 +#define VERB_MAX 3 +#define VERB_EXCESSIVE 4 + +// Use gcc format argument checking on this function, which cannot return +static void fatal_error( int exitcode, const char *fmt, ... ) \ + __attribute__ (( noreturn,format (printf, 2, 3) )); + +// Use gcc format argument checking on this function +static void verb_printf( int level, const char *fmt, ... ) \ + __attribute__ ((format (printf, 2, 3) )); + +static void fatal_error( int exitcode, const char *fmt, ... ) { + va_list v; + + va_start( v, fmt ); + vfprintf( stderr, fmt, v ); + + exit(exitcode); +} + +static void verb_printf( int level, const char *fmt, ... ){ + if ( level <= verbose ) { + va_list v; + va_start( v,fmt ); + vprintf(fmt, v); + } +} + +static void *mymalloc( size_t size ) { + void *p = malloc(size); + if ( !p ) { + fatal_error( EXIT_MALLOC, "Out of memory allocating %d bytes\n", size ); + } + return p; +} + +static void myrealloc( void **o, size_t newsize ) { + if ( *o == NULL ) + *o = mymalloc( newsize ); + else if ( !(*o = realloc( *o, newsize )) ) { + fatal_error( EXIT_MALLOC, "Out of memory re-allocating %d bytes\n", newsize ); + } +} + +static void outputlong( unsigned char *b, LONG w ) { + if ( bigendian ) { + b[0] = (w>>24) & 0xff; + b[1] = (w>>16) & 0xff; + b[2] = (w>> 8) & 0xff; + b[3] = (w ) & 0xff; + } else { + b[3] = (w>>24) & 0xff; + b[2] = (w>>16) & 0xff; + b[1] = (w>> 8) & 0xff; + b[0] = (w ) & 0xff; + } +} + +static void outputshort( unsigned char *b, SHORT w ) { + if ( bigendian ) { + b[0] = (w>> 8) & 0xff; + b[1] = (w ) & 0xff; + } else { + b[1] = (w>> 8) & 0xff; + b[0] = (w ) & 0xff; + } +} + +static unsigned long ConvertMode( unsigned long posix_mode ) { + unsigned long result = 0; + if ( S_ISDIR( posix_mode ) ) result |= 1<<0; + if ( S_ISCHR( posix_mode ) ) result |= 1<<1; + if ( S_ISBLK( posix_mode ) ) result |= 1<<2; + if ( S_ISREG( posix_mode ) ) result |= 1<<3; + if ( S_ISFIFO(posix_mode ) ) result |= 1<<4; + // We cannot create MQ, SEM, or SHM entries here + if ( posix_mode & S_IRUSR ) result |= 1<<16; + if ( posix_mode & S_IWUSR ) result |= 1<<17; + if ( posix_mode & S_IXUSR ) result |= 1<<18; +#ifndef _WIN32 + if ( posix_mode & S_IRGRP ) result |= 1<<19; + if ( posix_mode & S_IWGRP ) result |= 1<<20; + if ( posix_mode & S_IXGRP ) result |= 1<<21; + if ( posix_mode & S_IROTH ) result |= 1<<22; + if ( posix_mode & S_IWOTH ) result |= 1<<23; + if ( posix_mode & S_IXOTH ) result |= 1<<24; + if ( posix_mode & S_ISUID ) result |= 1<<25; + if ( posix_mode & S_ISGID ) result |= 1<<26; +#endif + return result; +} + +static const char *AddDirEntry( const char *name, node *parent_node, int node_num ) { + int this_size = ((strlen(name) + 4 + 4 + 1) + 31) & ~31; + int start = parent_node->size; + romfs_dirent *g; + myrealloc( (void**)&parent_node->entry, (parent_node->size += this_size) ); + g = (romfs_dirent *)((unsigned char *)parent_node->entry + start); + memset( (void*)g, '\0', this_size ); + outputlong( (unsigned char*)&g->node, node_num); + outputlong( (unsigned char*)&g->next, parent_node->size); + strcpy(g->name,name); + verb_printf( VERB_MAX, "\t%s --> node %d\n", name, node_num ); + return (const char *)g->name; +} + +extern int errno; + +static node * FindLink( dev_t d, ino_t i ) { + // See if the node has been previously included by checking the device/inode + // combinations of all known multi-linked nodes + node *np = first_multilink; + + for ( ; np ; np = np->next_multilink ) { + if ( np->device == d && np->inode == i ) + return np; + } + return NULL; +} + +static node * GetNodeInfo( const char *path, const char *name, int *hlink ) { + char newpath[1024]; + node *node, *lnode; + struct stat stbuff; + + sprintf(newpath,"%s/%s",path,name); + if ( (get_status(newpath,&stbuff)) < 0 ) { + fatal_error(EXIT_FILESYS, "stat(%s) failed: %s\n", newpath, strerror(errno)); + } + if ( !(stbuff.st_mode & S_IRUSR) ) { + fatal_error(EXIT_FILESYS, "\"%s\" is not readable\n", newpath ); + } + if ( hardlinks && S_ISREG( stbuff.st_mode ) && stbuff.st_nlink > 1 ) { + + // See if this node has already been loaded + lnode = FindLink( stbuff.st_dev, stbuff.st_ino ); + + if ( lnode ) { + lnode->nlink++; + *hlink = 1; + return lnode; // Return the found link instead + } + + // Create a new node + node = mymalloc( sizeof(struct node) ); + + // Incorporate the new link into the 'multi-linked' node list + *last_multilink_p = node; + last_multilink_p = &node->next_multilink; + } else { + // Create a new node + node = mymalloc( sizeof(struct node) ); + } + node->path = strdup( newpath ); + // We re-calculate the size for directories + node->size = IS_DIRECTORY( stbuff.st_mode ) ? 0 : stbuff.st_size; + node->st_mode = stbuff.st_mode; + node->uid = stbuff.st_uid; + node->gid = stbuff.st_gid; + node->ctime = stbuff.st_ctime; + node->nodenum = nodes++; + node->device = stbuff.st_dev; + node->inode = stbuff.st_ino; + // We always re-calculate the number of links + node->nlink = IS_DIRECTORY( stbuff.st_mode ) ? 2 : 1; + node->entry = NULL; + node->entry_size = 0; + node->offset = 0; + node->sibling = NULL; + node->child = NULL; + node->next_in_rom = NULL; + node->next_multilink = NULL; + *hlink = 0; + return node; +} + +static void ScanDirectory(node *mynode, int p_node) { + + DIR *dh; + struct dirent *e; + node **last_p = &mynode->child; + node *th; + int was_hardlinked; + + if ( (dh = opendir( mynode->path )) == NULL ) { + perror(mynode->path); + return; + } + + verb_printf(VERB_EXCESSIVE, "Construct directory '%s'(%d):\n", + mynode->path, mynode->nodenum ); + + // Add . & .. here because they MUST be present in the image + AddDirEntry( ".", mynode, mynode->nodenum ); + AddDirEntry( "..", mynode, p_node ); + + while ( (e = readdir( dh )) ) { + // Ignore . & .. here because they MAY NOT be in the host filesystem + if ( strcmp(e->d_name,".") && strcmp(e->d_name,"..") ) { + + + th = GetNodeInfo( mynode->path, e->d_name, &was_hardlinked ); + AddDirEntry( e->d_name, mynode, th->nodenum ); + + if ( !was_hardlinked ) { + verb_printf( VERB_EXCESSIVE, "\t\tNew node %d for entry '%s'\n", th->nodenum, e->d_name); + *last_p = th; + last_p = &th->sibling; + } else { + verb_printf( VERB_EXCESSIVE, "\t\tRe-used node %d for entry '%s'\n", th->nodenum, e->d_name); + } + } + } + closedir( dh ); + verb_printf(VERB_EXCESSIVE,"Completed '%s'. Checking for child directories...\n", mynode->path); + + for ( th = mynode->child ; th ; th = th->sibling ) { + if ( IS_DIRECTORY( th->st_mode ) ) { + mynode->nlink++; + ScanDirectory( th, mynode->nodenum ); + } + } +} + +static void AllocateSpaceToDirectories( node *first ) { + node *np; + + for ( np = first ; np ; np = np->sibling ) { + if ( IS_DIRECTORY( np->st_mode ) ) { + // The first node is a directory. Add its data + np->offset = coffset; + np->entry_size = ALIGN_TO( np->size, DIRECTORY_ALIGN ); + coffset += np->entry_size; + + verb_printf( VERB_MAX, "\t\tnode %5d : 0x%06lX (+0x%05X)\n", + np->nodenum, np->offset, np->entry_size ); + + // Link this node into the write order chain. + // For node 0 (the root), this will overwrite the first pointer with itself + *last_p = np; + last_p = &np->next_in_rom; + } + } + + // Now add any child directories + for ( np = first ; np ; np = np->sibling ) { + if ( IS_DIRECTORY( np->st_mode ) && np->child ) + AllocateSpaceToDirectories( np->child ); + } +} + +static void AllocateSpaceToDataFiles( node *first ) { + node *np; + + // There are two loops below. It CAN be done in just one, but this re-orders + // the file positions in relation to their inode numbers. To keep it simple + // to check, allocation takes place in the first loop, recursion in the second + + // Search for child data files + for ( np = first->child ; np ; np = np->sibling ) { + if ( IS_DATAFILE( np->st_mode ) || IS_SYMLINK( np->st_mode ) ) { + np->offset = coffset; + np->entry_size = ALIGN_TO( np->size, DATA_ALIGN ); + coffset += np->entry_size; + + // Link in to the rom write order list + *last_p = np; + last_p = &np->next_in_rom; + + verb_printf( VERB_MAX, "\t\tnode %5d : 0x%06lX (+0x%05X)\n", + np->nodenum, np->offset, np->entry_size ); + } + } + + // Recurse into sub-directories + for ( np = first->child ; np ; np = np->sibling ) { + if ( IS_DIRECTORY( np->st_mode ) ) { + AllocateSpaceToDataFiles( np ); + } + } +} + +static void AllocateSpaceToExecutables( node *first ) { + node *np; + + // The first node is a directory. Don't bother with that... + + // Search for child executables + for ( np = first->child ; np ; np = np->sibling ) { + if ( IS_EXECUTABLE( np->st_mode ) ) { + np->offset = coffset; + np->entry_size = ALIGN_TO( np->size, EXEC_ALIGN ); + coffset += np->entry_size; + + // Link in to the rom write order list + *last_p = np; + last_p = &np->next_in_rom; + + verb_printf( VERB_MAX, "\t\tnode %5d : 0x%06lX (+0x%05X)\n", + np->nodenum, np->offset, np->entry_size ); + } + } + + // Recurse into sub-directories + for ( np = first->child ; np ; np = np->sibling ) { + if ( IS_DIRECTORY( np->st_mode ) ) { + AllocateSpaceToExecutables( np ); + } + } +} + +static void WriteNode( int fd, node *np ) { + romfs_node anode; + char padhere[9]; + outputlong( (unsigned char*) &anode.mode, ConvertMode( np->st_mode ) ); + outputlong( (unsigned char*) &anode.nlink, np->nlink ); + outputshort((unsigned char*) &anode.uid, np->uid ); + outputshort((unsigned char*) &anode.gid, np->gid ); + outputlong( (unsigned char*) &anode.size, np->size ); + outputlong( (unsigned char*) &anode.ctime, np->ctime ); + outputlong( (unsigned char*) &anode.data_offset, np->offset ); + sprintf( padhere, "<%6d>", np->nodenum ); + memcpy( anode.pad, padhere, 8 ); + if ( dowrite && write( fd, (void*)&anode, sizeof(anode) ) != sizeof(anode) ) + fatal_error(EXIT_WRITE, "Error writing node %d (%s): %s\n", np->nodenum, np->path, strerror(errno) ); +} + +static int WriteNodeAndSiblings( int fd, int nodenum, node *first ) { + node *np; + + for ( np = first ; np ; np = np->sibling ) { + if ( np->nodenum != nodenum++ ) { + fatal_error(EXIT_BUG, "BUG: Out of sequence node number; got %d, expected %d\n", np->nodenum, nodenum-1); + } + WriteNode( fd, np ); + } + + for ( np = first ; np ; np = np->sibling ) { + if ( IS_DIRECTORY( np->st_mode ) && np->child ) { + nodenum = WriteNodeAndSiblings( fd, nodenum, np->child ); + } + } + return nodenum; +} + +static void WriteNodeTable( int fd ) { + romfs_disk header; + int wnodes; + + outputlong( (unsigned char*) &header.magic, ROMFS_MAGIC ); + outputlong( (unsigned char*) &header.nodecount, nodes ); + outputlong( (unsigned char*) &header.disksize, coffset ); + outputlong( (unsigned char*) &header.dev_id, 0x01020304 ); + strcpy( header.name, "ROMFS v1.0" ); + if ( dowrite && write( fd, (void*)&header, sizeof(header) ) != sizeof(header) ) + fatal_error(EXIT_WRITE, "Error writing ROMFS header: %s\n", strerror(errno) ); + + if ( (wnodes = WriteNodeAndSiblings( fd, 0, first )) != nodes ) { + fatal_error(EXIT_BUG, "BUG: Lost/gained some nodes; wrote %d, expected %d\n", wnodes, nodes ); + } +} + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +static void WriteData( int fd, node *np ) { + char newpath[1024]; + int ffd; + unsigned long todo; + + if ( IS_SYMLINK( np->st_mode ) ) { + if ( (ffd = readlink( np->path, newpath, sizeof(newpath) )) < 0 ) + fatal_error(EXIT_FILESYS, "Error reading symlink \"%s\": %s\n", np->path, strerror(errno) ); + + if ( !dowrite ) return; + + if ( lseek( fd, np->offset, SEEK_SET ) != np->offset ) + fatal_error(EXIT_SEEK, "Error seeking to offset 0x%lX: %s\n", np->offset, strerror(errno) ); + + if ( write( fd, newpath, ffd ) != ffd ) + fatal_error(EXIT_WRITE, "Write error: %s\n", strerror(errno) ); + + return; + } + + if ( (ffd=open(np->path, O_RDONLY | O_BINARY )) < 0 ) + fatal_error(EXIT_FILESYS, "Error opening \"%s\": %s\n", np->path, strerror(errno) ); + + if ( dowrite && lseek( fd, np->offset, SEEK_SET ) != np->offset ) + fatal_error(EXIT_SEEK, "Error seeking to offset 0x%lX: %s\n", np->offset, strerror(errno) ); + + todo = np->size; + while ( todo >= 1024 ) { + if ( read( ffd, newpath, 1024 ) != 1024 ) + fatal_error(EXIT_FILESYS, "Error reading file \"%s\" at offset 0x%lX: %s\n", np->path, np->size - todo, strerror(errno) ); + if ( dowrite && write( fd, newpath, 1024 ) != 1024 ) + fatal_error(EXIT_WRITE, "Write error: %s\n", strerror(errno) ); + todo -= 1024; + } + + if ( todo ) { + if ( read( ffd, newpath, todo ) != todo ) + fatal_error(EXIT_FILESYS, "Error reading file \"%s\" at offset 0x%lX: %s\n", np->path, np->size - todo, strerror(errno) ); + if ( dowrite && write( fd, newpath, todo ) != todo ) + fatal_error(EXIT_WRITE, "Write error: %s\n", strerror(errno) ); + } + + close(ffd); + +} + +static void WriteDataBlocks( int fd, node *first ) { + for ( ; first ; first = first->next_in_rom ) { + if ( dowrite && lseek( fd, first->offset, SEEK_SET ) != first->offset ) + fatal_error(EXIT_SEEK, "Error seeking to offset 0x%lX: %s\n", first->offset, strerror(errno) ); + if ( IS_DIRECTORY( first->st_mode ) ) { + if ( dowrite && write( fd, first->entry, first->size ) != first->size ) + fatal_error(EXIT_WRITE, "Write error: %s\n", strerror(errno) ); + } else { + WriteData( fd, first ); + } + } +} + +static void usage(void) { + fprintf(stderr,"\n%s - Create an eCos ROMFS disk image from the files\n",prog); + fprintf(stderr,"%*s contained under a specified directory\n\n", strlen(prog), ""); + fprintf(stderr,"Usage: %s [options] <fs_root> <fs_file>\n", prog); + fprintf(stderr," fs_root is the directory containing the files to package into the ROMFS image\n"); + fprintf(stderr," fs_file is the name of the ROMFS image file to create\n"); + fprintf(stderr," Options include:\n"); + fprintf(stderr," -v / -q increase / decrease verbosity\n"); + fprintf(stderr," -n do everything EXCEPT creating the output file\n"); + fprintf(stderr," -b write a big-endian image (default is little endian)\n"); + fprintf(stderr," -l collapse hard links to a single node\n"); + fprintf(stderr,"\n"); + exit(EXIT_ARGS); +} + +int main(int ac, char *av[]) { + int dummy; + + prog = av[0]; + + // Check structure sizes + if (sizeof(romfs_node) != 32) { + fatal_error(EXIT_COMPILE , "Size of romfs_node is %d, NOT 32\n", sizeof(romfs_node) ); + } else if (sizeof(romfs_dirent) != 8) { + fatal_error(EXIT_COMPILE , "Size of romfs_dirent is %d, NOT 8\n", sizeof(romfs_dirent) ); + } else if (sizeof(romfs_disk) != 32) { + fatal_error(EXIT_COMPILE , "Size of romfs_disk is %d, NOT 32\n", sizeof(romfs_disk) ); + } + + // Parse option arguments + while ( ac > 1 && av[1][0] == '-' ) { + char *o = &av[1][1]; + for ( ; *o ; o++ ) { + switch ( *o ) { + case 'q' : + verbose--; + break; + case 'v' : + verbose++; + break; + case 'n' : + dowrite = 0; + break; + case 'b' : + bigendian = 1; + break; + case 'l' : + hardlinks = 1; + break; + default : + fprintf(stderr,"%s: Invalid flag -%c\n", prog, *o ); + usage(); + } + } + av++; ac--; + } + + // Check remaining arguments + if ( ac != 3 ) usage(); + + + verb_printf( VERB_MINIMUM, "%s: Verbosity %d %s%s endian\n", + prog, verbose, + dowrite ? "" : "no write, ", + bigendian ? "big" : "little" ); + + // Phase 1. Recursively scan the root directory for files and directories. + verb_printf(VERB_MINIMUM, "Phase 1 - Build file list\n"); + + first = GetNodeInfo( av[1], ".", &dummy ); // Initialize the root node entry. + ScanDirectory( first, 0 ); + + // Phase 2. Work out space allocations for filesystem + verb_printf(VERB_MINIMUM, "Phase 2 - Calculate space allocation\n"); + coffset = sizeof(romfs_disk) + nodes * sizeof(romfs_node); + verb_printf(VERB_MAX,"\t\tnode table : 0x000000 (+0x%05lX) %d nodes\n", coffset, nodes ); + + // Phase 2a. Work out space allocations for the directories of the filesystem + verb_printf(VERB_SUB,"Phase 2a - * Directories\n"); + coffset = ALIGN_TO( coffset, DIRECTORY_ALIGN ); + AllocateSpaceToDirectories( first ); + + // Phase 2b. Work out space allocations for the data files of the filesystem + verb_printf(VERB_SUB,"Phase 2b - * Regular files\n"); + coffset = ALIGN_TO( coffset, DATA_ALIGN ); + AllocateSpaceToDataFiles( first ); + + // Phase 2c. Work out space allocations for the executable files of the filesystem + verb_printf(VERB_SUB,"Phase 2c - * Executable files\n"); + coffset = ALIGN_TO( coffset, EXEC_ALIGN ); + AllocateSpaceToExecutables( first ); + + // Round off the image size... + coffset = ALIGN_TO( coffset, EXEC_ALIGN ); + + // Phase 3. Write out the image file + verb_printf(VERB_MINIMUM, "Phase 3 - Construct ROMFS image file (%ld kb)\n", ALIGN_TO( coffset, 1024 )/1024); + + if ( dowrite ) { + if ( (fd = open( av[2], O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666 )) < 0 ) { + fatal_error(EXIT_WRITE,"Failed to open output file '%s', errno=%d\n", av[2], errno ); + } + } else { + verb_printf(VERB_NONE," (No image is being written)\n"); + } + + verb_printf(VERB_SUB,"Phase 3a - * Node table\n"); + WriteNodeTable( fd ); + + verb_printf(VERB_SUB,"Phase 3b - * Data blocks\n"); + WriteDataBlocks( fd, first ); + + if ( fd >= 0 ) close(fd); + + verb_printf(VERB_MINIMUM, "%s completed\n", av[2] ); + + return 0; +} diff --git a/ecos/packages/fs/rom/current/tests/romfs1.c b/ecos/packages/fs/rom/current/tests/romfs1.c new file mode 100644 index 0000000..dc994fb --- /dev/null +++ b/ecos/packages/fs/rom/current/tests/romfs1.c @@ -0,0 +1,408 @@ +//========================================================================== +// +// romfs1.c +// +// Test fileio system +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. +// +// eCos 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 or (at your option) any later +// version. +// +// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg, richard.panton@3glab.com, jlarmour +// Date: 2000-05-25 +// Purpose: Test fileio system +// Description: This test uses the testfs to check out the initialization +// and basic operation of the fileio system +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <pkgconf/hal.h> +#include <pkgconf/io_fileio.h> +#include <pkgconf/isoinfra.h> +#include <pkgconf/system.h> +#include <pkgconf/fs_rom.h> + +#include <unistd.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <errno.h> +#include <string.h> +#include <dirent.h> +#include <stdio.h> + +#include <cyg/fileio/fileio.h> + +#include <cyg/infra/cyg_type.h> +#include <cyg/infra/testcase.h> +#include <cyg/infra/diag.h> // HAL polled output + +// Test ROMFS data. Two example data files are generated so that +// the test will work on both big-endian and little-endian targets. +#if (CYG_BYTEORDER == CYG_LSBFIRST) +# include <cyg/romfs/testromfs_le.h> +#else +# include <cyg/romfs/testromfs_be.h> +#endif + +//========================================================================== + +MTAB_ENTRY( romfs_mte1, + "/", + "romfs", + "", + (CYG_ADDRWORD) &filedata[0] ); + + +//========================================================================== + +#define SHOW_RESULT( _fn, _res ) \ + diag_printf("<FAIL>: " #_fn "() returned %d %s\n", (int)_res, _res<0?strerror(errno):""); + +#define CHKFAIL_TYPE( _fn, _res, _type ) { \ +if ( _res != -1 ) \ + diag_printf("<FAIL>: " #_fn "() returned %d (expected -1)\n", (int)_res); \ +else if ( errno != _type ) \ + diag_printf("<FAIL>: " #_fn "() failed with errno %d (%s),\n expected %d (%s)\n", errno, strerror(errno), _type, strerror(_type) ); \ +} + +//========================================================================== + +#define IOSIZE 100 + +#define LONGNAME1 "long_file_name_that_should_take_up_more_than_one_directory_entry_1" +#define LONGNAME2 "long_file_name_that_should_take_up_more_than_one_directory_entry_2" + + +//========================================================================== + +#ifndef CYGINT_ISO_STRING_STRFUNCS + +char *strcat( char *s1, const char *s2 ) +{ + char *s = s1; + while( *s1 ) s1++; + while( (*s1++ = *s2++) != 0); + return s; +} + +#endif + +//========================================================================== + +static void listdir( char *name, int statp ) +{ + int err; + DIR *dirp; + + diag_printf("<INFO>: reading directory %s\n",name); + + dirp = opendir( name ); + if( dirp == NULL ) SHOW_RESULT( opendir, -1 ); + + for(;;) + { + struct dirent *entry = readdir( dirp ); + + if( entry == NULL ) + break; + + diag_printf("<INFO>: entry %14s",entry->d_name); +#ifdef CYGPKG_FS_ROM_RET_DIRENT_DTYPE + diag_printf(" d_type %2x", entry->d_type); +#endif + if( statp ) + { + char fullname[PATH_MAX]; + struct stat sbuf; + + if( name[0] ) + { + strcpy(fullname, name ); + if( !(name[0] == '/' && name[1] == 0 ) ) + strcat(fullname, "/" ); + } + else fullname[0] = 0; + + strcat(fullname, entry->d_name ); + + err = stat( fullname, &sbuf ); + if( err < 0 ) + { + if( errno == ENOSYS ) + diag_printf(" <no status available>"); + else SHOW_RESULT( stat, err ); + } + else + { + diag_printf(" [mode %08x ino %08x nlink %d size %ld]", + sbuf.st_mode,sbuf.st_ino,sbuf.st_nlink,sbuf.st_size); + } +#ifdef CYGPKG_FS_ROM_RET_DIRENT_DTYPE + if ((entry->d_type & S_IFMT) != (sbuf.st_mode & S_IFMT)) + CYG_TEST_FAIL("File mode's don't match between dirent and stat"); +#endif + } + + diag_printf("\n"); + } + + err = closedir( dirp ); + if( err < 0 ) SHOW_RESULT( stat, err ); +} + +//========================================================================== + +#ifdef CYGPKG_FS_RAM +static void copyfile( char *name2, char *name1 ) +{ + + int err; + char buf[IOSIZE]; + int fd1, fd2; + ssize_t done, wrote; + + diag_printf("<INFO>: copy file %s -> %s\n",name2,name1); + + err = access( name1, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + err = access( name2, F_OK ); + if( err != 0 ) SHOW_RESULT( access, err ); + + fd1 = open( name1, O_WRONLY|O_CREAT ); + if( fd1 < 0 ) SHOW_RESULT( open, fd1 ); + + fd2 = open( name2, O_RDONLY ); + if( fd2 < 0 ) SHOW_RESULT( open, fd2 ); + + for(;;) + { + done = read( fd2, buf, IOSIZE ); + if( done < 0 ) SHOW_RESULT( read, done ); + + if( done == 0 ) break; + + wrote = write( fd1, buf, done ); + if( wrote != done ) SHOW_RESULT( write, wrote ); + + if( wrote != done ) break; + } + + err = close( fd1 ); + if( err < 0 ) SHOW_RESULT( close, err ); + + err = close( fd2 ); + if( err < 0 ) SHOW_RESULT( close, err ); + +} +#endif + +//========================================================================== + +static void comparefiles( char *name2, char *name1 ) +{ + int err; + char buf1[IOSIZE]; + char buf2[IOSIZE]; + int fd1, fd2; + ssize_t done1, done2; + int i; + + diag_printf("<INFO>: compare files %s == %s\n",name2,name1); + + err = access( name1, F_OK ); + if( err != 0 ) SHOW_RESULT( access, err ); + + err = access( name1, F_OK ); + if( err != 0 ) SHOW_RESULT( access, err ); + + fd1 = open( name1, O_RDONLY ); + if( fd1 < 0 ) SHOW_RESULT( open, fd1 ); + + fd2 = open( name2, O_RDONLY ); + if( fd2 < 0 ) SHOW_RESULT( open, fd2 ); + + for(;;) + { + done1 = read( fd1, buf1, IOSIZE ); + if( done1 < 0 ) SHOW_RESULT( read, done1 ); + + done2 = read( fd2, buf2, IOSIZE ); + if( done2 < 0 ) SHOW_RESULT( read, done2 ); + + if( done1 != done2 ) + diag_printf("Files different sizes\n"); + + if( done1 == 0 ) break; + + for( i = 0; i < done1; i++ ) + if( buf1[i] != buf2[i] ) + { + diag_printf("buf1[%d](%02x) != buf1[%d](%02x)\n",i,buf1[i],i,buf2[i]); + CYG_TEST_FAIL("Data in files not equal\n"); + } + } + + err = close( fd1 ); + if( err < 0 ) SHOW_RESULT( close, err ); + + err = close( fd2 ); + if( err < 0 ) SHOW_RESULT( close, err ); + +} + +//========================================================================== +// main + +int main( int argc, char **argv ) +{ + int err; + char address[16]; +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) + struct cyg_fs_block_usage usage; +#endif + + CYG_TEST_INIT(); + + // -------------------------------------------------------------- + + diag_printf("<INFO>: ROMFS root follows\n"); + listdir( "/", true ); + + diag_printf("<INFO>: cd /etc\n" ); + err = chdir( "/etc" ); + if ( err < 0 ) { + SHOW_RESULT( chdir, err ); + CYG_TEST_FAIL_FINISH("romfs1"); + } + + diag_printf("<INFO>: ROMFS list of '' follows\n"); + listdir( "", true ); + + diag_printf("<INFO>: ROMFS list of /etc follows\n"); + listdir( "/etc", true ); + + diag_printf("<INFO>: ROMFS list of . follows\n"); + listdir( ".", true ); + +#ifdef CYGPKG_FS_RAM + err = mount( "", "/var", "ramfs" ); + if( err < 0 ) SHOW_RESULT( mount, err ); + + copyfile( "/etc/passwd", "/var/passwd_copy" ); + + comparefiles( "/etc/passwd", "/var/passwd_copy" ); +#endif + + diag_printf("<INFO>: ROMFS list of / follows\n"); +#ifdef CYGPKG_FS_RAM + diag_printf("<INFO>: Note that /var now gives stat() info for RAMFS\n"); +#endif + listdir( "/", true ); + + diag_printf("<INFO>: Mount ROMFS again onto /mnt\n"); + sprintf( address, "%p", (void*)&filedata[0] ); + err = mount( address, "/mnt", "romfs" ); + if( err < 0 ) SHOW_RESULT( mount, err ); + + comparefiles( "/etc/passwd", "/mnt/etc/passwd" ); + + + err = mkdir( "/foo", 0 ); + CHKFAIL_TYPE( mkdir, err, EROFS ); + + err = rename( "/var", "/tmp" ); // RAMFS is mounted here +#ifdef CYGPKG_FS_RAM + CHKFAIL_TYPE( rename, err, EXDEV ); +#else + CHKFAIL_TYPE( rename, err, EROFS ); +#endif + + err = rename( "/var/passwd_copy", "/mnt/etc/passwd_copy" ); + CHKFAIL_TYPE( rename, err, EXDEV ); + + err = rename( "/etc", "/tmp" ); + CHKFAIL_TYPE( rename, err, EROFS ); + + diag_printf("<INFO>: cd /etc\n"); + err = chdir( "/etc" ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + err = chdir( "/mnt/etc" ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + listdir( ".", true ); + + diag_printf("<INFO>: unlink /tmp\n"); + err = unlink( "/tmp" ); + CHKFAIL_TYPE( unlink, err, EROFS ); + + diag_printf("<INFO>: mount random area\n"); + sprintf(address, "%p", (void*)(&filedata[0] + 0x100)); + err = mount( address, "/tmp", "romfs" ); + CHKFAIL_TYPE( mount, err, ENOENT ); + + err = umount( "/mnt" ); + if( err < 0 ) SHOW_RESULT( umount, err ); + + err = umount( "/var" ); +#ifdef CYGPKG_FS_RAM + if( err < 0 ) SHOW_RESULT( umount, err ); +#else + CHKFAIL_TYPE( umount, err, EINVAL ); +#endif + +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) + err = cyg_fs_getinfo("/", FS_INFO_BLOCK_USAGE, &usage, sizeof(usage)); + if( err < 0 ) SHOW_RESULT( cyg_fs_getinfo, err ); + diag_printf("<INFO>: total size: %6lld blocks, %10lld bytes\n", + usage.total_blocks, usage.total_blocks * usage.block_size); + diag_printf("<INFO>: free size: %6lld blocks, %10lld bytes\n", + usage.free_blocks, usage.free_blocks * usage.block_size); + diag_printf("<INFO>: block size: %6u bytes\n", usage.block_size); +#endif + // -------------------------------------------------------------- + + err = umount( "/" ); + if( err < 0 ) SHOW_RESULT( umount, err ); + + + CYG_TEST_PASS_FINISH("romfs1"); +} + +// ------------------------------------------------------------------------- +// EOF romfs1.c diff --git a/ecos/packages/fs/rom/current/tests/testromfs/etc/hosts b/ecos/packages/fs/rom/current/tests/testromfs/etc/hosts new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/ecos/packages/fs/rom/current/tests/testromfs/etc/hosts diff --git a/ecos/packages/fs/rom/current/tests/testromfs/etc/inetd b/ecos/packages/fs/rom/current/tests/testromfs/etc/inetd new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/ecos/packages/fs/rom/current/tests/testromfs/etc/inetd diff --git a/ecos/packages/fs/rom/current/tests/testromfs/etc/passwd b/ecos/packages/fs/rom/current/tests/testromfs/etc/passwd new file mode 100644 index 0000000..85aa954 --- /dev/null +++ b/ecos/packages/fs/rom/current/tests/testromfs/etc/passwd @@ -0,0 +1,32 @@ +root:x:0:0:root:/root:/bin/bash +daemon:x:1:1:daemon:/usr/sbin:/bin/sh +bin:x:2:2:bin:/bin:/bin/sh +sys:x:3:3:sys:/dev:/bin/sh +sync:x:4:100:sync:/bin:/bin/sync +games:x:5:100:games:/usr/games:/bin/sh +man:x:6:100:man:/var/cache/man:/bin/sh +lp:x:7:7:lp:/var/spool/lpd:/bin/sh +mail:x:8:8:mail:/var/spool/mail:/bin/sh +news:x:9:9:news:/var/spool/news:/bin/sh +uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh +proxy:x:13:13:proxy:/bin:/bin/sh +majordom:x:30:31:Majordomo:/usr/lib/majordomo:/bin/sh +postgres:x:31:32:postgres:/var/lib/postgres:/bin/sh +www-data:x:33:33:www-data:/var/www:/bin/sh +backup:x:34:34:backup:/var/backups:/bin/sh +msql:x:36:36:Mini SQL Database Manager:/var/lib/msql:/bin/sh +operator:x:37:37:Operator:/var:/bin/sh +list:x:38:38:SmartList:/var/list:/bin/sh +irc:x:39:39:ircd:/var:/bin/sh +gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats/gnats-db:/bin/sh +alias:x:70:65534:qmail alias:/var/qmail/alias:/bin/sh +qmaild:x:71:65534:qmail daemon:/var/qmail:/bin/sh +qmails:x:72:70:qmail send:/var/qmail:/bin/sh +qmailr:x:73:70:qmail remote:/var/qmail:/bin/sh +qmailq:x:74:70:qmail queue:/var/qmail:/bin/sh +qmaill:x:75:65534:qmail log:/var/qmail:/bin/sh +qmailp:x:76:65534:qmail pw:/var/qmail:/bin/sh +ftp:x:60000:65534::/lhome/ftp:/bin/false +nobody:x:65534:65534:nobody:/home:/bin/sh +identd:x:60001:65534::/var/run/identd:/bin/false +telnetd:x:60002:60002::/usr/lib/telnetd:/bin/false diff --git a/ecos/packages/fs/rom/current/tests/testromfs/mnt/thing b/ecos/packages/fs/rom/current/tests/testromfs/mnt/thing new file mode 100644 index 0000000..45b983b --- /dev/null +++ b/ecos/packages/fs/rom/current/tests/testromfs/mnt/thing @@ -0,0 +1 @@ +hi diff --git a/ecos/packages/fs/rom/current/tests/testromfs/var/foobar b/ecos/packages/fs/rom/current/tests/testromfs/var/foobar new file mode 100644 index 0000000..9cbcf6f --- /dev/null +++ b/ecos/packages/fs/rom/current/tests/testromfs/var/foobar @@ -0,0 +1 @@ +flibble |