📄 romfs.c
字号:
//==========================================================================
//
// romfs.c
//
// ROM file system
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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>
//==========================================================================
// 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 );
}
//==========================================================================
// 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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -