mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 11:56:10 +08:00
Add ioctl's to support XIP
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@913 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
@@ -466,4 +466,10 @@
|
|||||||
* Added support for ROMFS filesystem.
|
* Added support for ROMFS filesystem.
|
||||||
* Added a simple test the ROMFS filesystem (examples/romfs)
|
* Added a simple test the ROMFS filesystem (examples/romfs)
|
||||||
* NSH: Use ROMFS to provide an option for a start-up script at /etc/init.d/rcS
|
* NSH: Use ROMFS to provide an option for a start-up script at /etc/init.d/rcS
|
||||||
|
* Add definition of BIOC_XIPBASE ioctl and implement in RAM disk block driver.
|
||||||
|
This is a low level requirement for eXecute In Place (XIP) support.
|
||||||
|
* Add a FIOC_MMAP to perform memory mapping of a file and implemented the
|
||||||
|
ioctl command in the ROMFS filesystem. This is a requirement for eXecute
|
||||||
|
In Place (XIP) support.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<tr align="center" bgcolor="#e4e4e4">
|
<tr align="center" bgcolor="#e4e4e4">
|
||||||
<td>
|
<td>
|
||||||
<h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1>
|
<h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1>
|
||||||
<p>Last Updated: September 11, 2008</p>
|
<p>Last Updated: September 12, 2008</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@@ -1100,6 +1100,11 @@ nuttx-0.3.15 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
|
|||||||
* Added support for ROMFS filesystem.
|
* Added support for ROMFS filesystem.
|
||||||
* Added a simple test the ROMFS filesystem (examples/romfs)
|
* Added a simple test the ROMFS filesystem (examples/romfs)
|
||||||
* NSH: Use ROMFS to provide an option for a start-up script at /etc/init.d/rcS
|
* NSH: Use ROMFS to provide an option for a start-up script at /etc/init.d/rcS
|
||||||
|
* Add definition of BIOC_XIPBASE ioctl and implement in RAM disk block driver.
|
||||||
|
This is a low level requirement for eXecute In Place (XIP) support.
|
||||||
|
* Add a FIOC_MMAP to perform memory mapping of a file and implemented the
|
||||||
|
ioctl command in the ROMFS filesystem. This is a requirement for eXecute
|
||||||
|
In Place (XIP) support.
|
||||||
|
|
||||||
pascal-0.1.3 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
|
pascal-0.1.3 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||||
|
|
||||||
|
|||||||
@@ -82,8 +82,7 @@ struct file_operations g_serialops =
|
|||||||
|
|
||||||
static int lowconsole_ioctl(struct file *filep, int cmd, unsigned long arg)
|
static int lowconsole_ioctl(struct file *filep, int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
*get_errno_ptr() = ENOTTY;
|
return -ENOTTY;
|
||||||
return ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
+54
-31
@@ -40,6 +40,7 @@
|
|||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -82,6 +83,7 @@ static ssize_t rd_write(FAR struct inode *inode, const unsigned char *buffer,
|
|||||||
size_t start_sector, unsigned int nsectors);
|
size_t start_sector, unsigned int nsectors);
|
||||||
#endif
|
#endif
|
||||||
static int rd_geometry(FAR struct inode *inode, struct geometry *geometry);
|
static int rd_geometry(FAR struct inode *inode, struct geometry *geometry);
|
||||||
|
static int rd_ioctl(FAR struct inode *inode, int cmd, unsigned long arg);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
@@ -98,7 +100,7 @@ static const struct block_operations g_bops =
|
|||||||
NULL, /* write */
|
NULL, /* write */
|
||||||
#endif
|
#endif
|
||||||
rd_geometry, /* geometry */
|
rd_geometry, /* geometry */
|
||||||
NULL /* ioctl */
|
rd_ioctl /* ioctl */
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -140,18 +142,16 @@ static ssize_t rd_read(FAR struct inode *inode, unsigned char *buffer,
|
|||||||
size_t start_sector, unsigned int nsectors)
|
size_t start_sector, unsigned int nsectors)
|
||||||
{
|
{
|
||||||
struct rd_struct_s *dev;
|
struct rd_struct_s *dev;
|
||||||
if (inode)
|
|
||||||
|
DEBUGASSERT(inode && inode->i_private);
|
||||||
|
dev = (struct rd_struct_s *)inode->i_private;
|
||||||
|
if (start_sector < dev->rd_nsectors &&
|
||||||
|
start_sector + nsectors <= dev->rd_nsectors)
|
||||||
{
|
{
|
||||||
dev = (struct rd_struct_s *)inode->i_private;
|
memcpy(buffer,
|
||||||
if (dev &&
|
&dev->rd_buffer[start_sector * dev->rd_sectsize],
|
||||||
start_sector < dev->rd_nsectors &&
|
nsectors * dev->rd_sectsize);
|
||||||
start_sector + nsectors <= dev->rd_nsectors)
|
return nsectors;
|
||||||
{
|
|
||||||
memcpy(buffer,
|
|
||||||
&dev->rd_buffer[start_sector * dev->rd_sectsize],
|
|
||||||
nsectors * dev->rd_sectsize);
|
|
||||||
return nsectors;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -168,26 +168,22 @@ static ssize_t rd_write(FAR struct inode *inode, const unsigned char *buffer,
|
|||||||
size_t start_sector, unsigned int nsectors)
|
size_t start_sector, unsigned int nsectors)
|
||||||
{
|
{
|
||||||
struct rd_struct_s *dev;
|
struct rd_struct_s *dev;
|
||||||
if (inode)
|
|
||||||
|
DEBUGASSERT(inode && inode->i_private);
|
||||||
|
dev = (struct rd_struct_s *)inode->i_private;
|
||||||
|
if (!dev->rd_writeenabled)
|
||||||
{
|
{
|
||||||
dev = (struct rd_struct_s *)inode->i_private;
|
return -EACCES;
|
||||||
if (dev)
|
|
||||||
{
|
|
||||||
if (!dev->rd_writeenabled)
|
|
||||||
{
|
|
||||||
return -EACCES;
|
|
||||||
}
|
|
||||||
else if (start_sector < dev->rd_nsectors &&
|
|
||||||
start_sector + nsectors <= dev->rd_nsectors)
|
|
||||||
{
|
|
||||||
memcpy(&dev->rd_buffer[start_sector * dev->rd_sectsize],
|
|
||||||
buffer,
|
|
||||||
nsectors * dev->rd_sectsize);
|
|
||||||
return nsectors;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return -EINVAL;
|
else if (start_sector < dev->rd_nsectors &&
|
||||||
|
start_sector + nsectors <= dev->rd_nsectors)
|
||||||
|
{
|
||||||
|
memcpy(&dev->rd_buffer[start_sector * dev->rd_sectsize],
|
||||||
|
buffer,
|
||||||
|
nsectors * dev->rd_sectsize);
|
||||||
|
return nsectors;
|
||||||
|
}
|
||||||
|
return -EFBIG;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -201,7 +197,9 @@ static ssize_t rd_write(FAR struct inode *inode, const unsigned char *buffer,
|
|||||||
static int rd_geometry(FAR struct inode *inode, struct geometry *geometry)
|
static int rd_geometry(FAR struct inode *inode, struct geometry *geometry)
|
||||||
{
|
{
|
||||||
struct rd_struct_s *dev;
|
struct rd_struct_s *dev;
|
||||||
if (inode && geometry)
|
|
||||||
|
DEBUGASSERT(inode);
|
||||||
|
if (geometry)
|
||||||
{
|
{
|
||||||
dev = (struct rd_struct_s *)inode->i_private;
|
dev = (struct rd_struct_s *)inode->i_private;
|
||||||
geometry->geo_available = TRUE;
|
geometry->geo_available = TRUE;
|
||||||
@@ -218,6 +216,31 @@ static int rd_geometry(FAR struct inode *inode, struct geometry *geometry)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: rd_geometry
|
||||||
|
*
|
||||||
|
* Description: Return device geometry
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int rd_ioctl(FAR struct inode *inode, int cmd, unsigned long arg)
|
||||||
|
{
|
||||||
|
struct rd_struct_s *dev ;
|
||||||
|
void **ppv = (void**)arg;
|
||||||
|
|
||||||
|
/* Only one ioctl command is supported */
|
||||||
|
|
||||||
|
DEBUGASSERT(inode && inode->i_private);
|
||||||
|
if (cmd == BIOC_XIPBASE && ppv)
|
||||||
|
{
|
||||||
|
dev = (struct rd_struct_s *)inode->i_private;
|
||||||
|
*ppv = (void*)dev->rd_buffer;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOTTY;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|||||||
+71
-50
@@ -55,6 +55,7 @@
|
|||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#include <nuttx/fs.h>
|
#include <nuttx/fs.h>
|
||||||
|
#include <nuttx/ioctl.h>
|
||||||
|
|
||||||
#include "fs_romfs.h"
|
#include "fs_romfs.h"
|
||||||
|
|
||||||
@@ -71,6 +72,7 @@ static int romfs_open(FAR struct file *filep, const char *relpath,
|
|||||||
static int romfs_close(FAR struct file *filep);
|
static int romfs_close(FAR struct file *filep);
|
||||||
static ssize_t romfs_read(FAR struct file *filep, char *buffer, size_t buflen);
|
static ssize_t romfs_read(FAR struct file *filep, char *buffer, size_t buflen);
|
||||||
static off_t romfs_seek(FAR struct file *filep, off_t offset, int whence);
|
static off_t romfs_seek(FAR struct file *filep, off_t offset, int whence);
|
||||||
|
static int romfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
|
||||||
|
|
||||||
static int romfs_opendir(struct inode *mountpt, const char *relpath,
|
static int romfs_opendir(struct inode *mountpt, const char *relpath,
|
||||||
struct internal_dir_s *dir);
|
struct internal_dir_s *dir);
|
||||||
@@ -104,7 +106,7 @@ const struct mountpt_operations romfs_operations =
|
|||||||
romfs_read, /* read */
|
romfs_read, /* read */
|
||||||
NULL, /* write */
|
NULL, /* write */
|
||||||
romfs_seek, /* seek */
|
romfs_seek, /* seek */
|
||||||
NULL, /* ioctl */
|
romfs_ioctl, /* ioctl */
|
||||||
NULL, /* sync */
|
NULL, /* sync */
|
||||||
|
|
||||||
romfs_opendir, /* opendir */
|
romfs_opendir, /* opendir */
|
||||||
@@ -135,7 +137,6 @@ static int romfs_open(FAR struct file *filep, const char *relpath,
|
|||||||
int oflags, mode_t mode)
|
int oflags, mode_t mode)
|
||||||
{
|
{
|
||||||
struct romfs_dirinfo_s dirinfo;
|
struct romfs_dirinfo_s dirinfo;
|
||||||
struct inode *inode;
|
|
||||||
struct romfs_mountpt_s *rm;
|
struct romfs_mountpt_s *rm;
|
||||||
struct romfs_file_s *rf;
|
struct romfs_file_s *rf;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -144,12 +145,11 @@ static int romfs_open(FAR struct file *filep, const char *relpath,
|
|||||||
|
|
||||||
DEBUGASSERT(filep->f_priv == NULL && filep->f_inode != NULL);
|
DEBUGASSERT(filep->f_priv == NULL && filep->f_inode != NULL);
|
||||||
|
|
||||||
/* Get the mountpoint inode reference from the file structure and the
|
/* mountpoint private data from the inode reference from the file
|
||||||
* mountpoint private data from the inode structure
|
* structure
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inode = filep->f_inode;
|
rm = (struct romfs_mountpt_s*)filep->f_inode->i_private;
|
||||||
rm = (struct romfs_mountpt_s*)inode->i_private;
|
|
||||||
|
|
||||||
DEBUGASSERT(rm != NULL);
|
DEBUGASSERT(rm != NULL);
|
||||||
|
|
||||||
@@ -211,21 +211,19 @@ static int romfs_open(FAR struct file *filep, const char *relpath,
|
|||||||
goto errout_with_semaphore;
|
goto errout_with_semaphore;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a file buffer to support partial sector accesses */
|
|
||||||
|
|
||||||
rf->rf_buffer = (ubyte*)malloc(rm->rm_hwsectorsize);
|
|
||||||
if (!rf->rf_buffer)
|
|
||||||
{
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto errout_with_struct;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize the file private data (only need to initialize non-zero elements) */
|
/* Initialize the file private data (only need to initialize non-zero elements) */
|
||||||
|
|
||||||
rf->rf_open = TRUE;
|
rf->rf_open = TRUE;
|
||||||
rf->rf_startoffset = romfs_datastart(rm, dirinfo.rd_dir.fr_curroffset);
|
rf->rf_startoffset = romfs_datastart(rm, dirinfo.rd_dir.fr_curroffset);
|
||||||
rf->rf_size = dirinfo.rd_size;
|
rf->rf_size = dirinfo.rd_size;
|
||||||
rf->rf_cachesector = (uint32)-1;
|
|
||||||
|
/* Confiure a buffering to support access to this file */
|
||||||
|
|
||||||
|
ret = romfs_fileconfigure(rm, rf);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
goto errout_with_semaphore;
|
||||||
|
}
|
||||||
|
|
||||||
/* Attach the private date to the struct file instance */
|
/* Attach the private date to the struct file instance */
|
||||||
|
|
||||||
@@ -243,12 +241,7 @@ static int romfs_open(FAR struct file *filep, const char *relpath,
|
|||||||
romfs_semgive(rm);
|
romfs_semgive(rm);
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
/* Error exits -- goto's are nasty things, but they sure can make error
|
/* Error exits */
|
||||||
* handling a lot simpler.
|
|
||||||
*/
|
|
||||||
|
|
||||||
errout_with_struct:
|
|
||||||
free(rf);
|
|
||||||
|
|
||||||
errout_with_semaphore:
|
errout_with_semaphore:
|
||||||
romfs_semgive(rm);
|
romfs_semgive(rm);
|
||||||
@@ -261,7 +254,6 @@ errout_with_semaphore:
|
|||||||
|
|
||||||
static int romfs_close(FAR struct file *filep)
|
static int romfs_close(FAR struct file *filep)
|
||||||
{
|
{
|
||||||
struct inode *inode;
|
|
||||||
struct romfs_mountpt_s *rm;
|
struct romfs_mountpt_s *rm;
|
||||||
struct romfs_file_s *rf;
|
struct romfs_file_s *rf;
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
@@ -273,8 +265,7 @@ static int romfs_close(FAR struct file *filep)
|
|||||||
/* Recover our private data from the struct file instance */
|
/* Recover our private data from the struct file instance */
|
||||||
|
|
||||||
rf = filep->f_priv;
|
rf = filep->f_priv;
|
||||||
inode = filep->f_inode;
|
rm = filep->f_inode->i_private;
|
||||||
rm = inode->i_private;
|
|
||||||
|
|
||||||
DEBUGASSERT(rm != NULL);
|
DEBUGASSERT(rm != NULL);
|
||||||
|
|
||||||
@@ -289,7 +280,7 @@ static int romfs_close(FAR struct file *filep)
|
|||||||
* accesses.
|
* accesses.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (rf->rf_buffer)
|
if (!rm->rm_xipbase && rf->rf_buffer)
|
||||||
{
|
{
|
||||||
free(rf->rf_buffer);
|
free(rf->rf_buffer);
|
||||||
}
|
}
|
||||||
@@ -307,7 +298,6 @@ static int romfs_close(FAR struct file *filep)
|
|||||||
|
|
||||||
static ssize_t romfs_read(FAR struct file *filep, char *buffer, size_t buflen)
|
static ssize_t romfs_read(FAR struct file *filep, char *buffer, size_t buflen)
|
||||||
{
|
{
|
||||||
struct inode *inode;
|
|
||||||
struct romfs_mountpt_s *rm;
|
struct romfs_mountpt_s *rm;
|
||||||
struct romfs_file_s *rf;
|
struct romfs_file_s *rf;
|
||||||
unsigned int bytesread;
|
unsigned int bytesread;
|
||||||
@@ -327,8 +317,7 @@ static ssize_t romfs_read(FAR struct file *filep, char *buffer, size_t buflen)
|
|||||||
/* Recover our private data from the struct file instance */
|
/* Recover our private data from the struct file instance */
|
||||||
|
|
||||||
rf = filep->f_priv;
|
rf = filep->f_priv;
|
||||||
inode = filep->f_inode;
|
rm = filep->f_inode->i_private;
|
||||||
rm = inode->i_private;
|
|
||||||
|
|
||||||
DEBUGASSERT(rm != NULL);
|
DEBUGASSERT(rm != NULL);
|
||||||
|
|
||||||
@@ -445,7 +434,6 @@ errout_with_semaphore:
|
|||||||
|
|
||||||
static off_t romfs_seek(FAR struct file *filep, off_t offset, int whence)
|
static off_t romfs_seek(FAR struct file *filep, off_t offset, int whence)
|
||||||
{
|
{
|
||||||
struct inode *inode;
|
|
||||||
struct romfs_mountpt_s *rm;
|
struct romfs_mountpt_s *rm;
|
||||||
struct romfs_file_s *rf;
|
struct romfs_file_s *rf;
|
||||||
ssize_t position;
|
ssize_t position;
|
||||||
@@ -458,12 +446,12 @@ static off_t romfs_seek(FAR struct file *filep, off_t offset, int whence)
|
|||||||
/* Recover our private data from the struct file instance */
|
/* Recover our private data from the struct file instance */
|
||||||
|
|
||||||
rf = filep->f_priv;
|
rf = filep->f_priv;
|
||||||
inode = filep->f_inode;
|
rm = filep->f_inode->i_private;
|
||||||
rm = inode->i_private;
|
|
||||||
|
|
||||||
DEBUGASSERT(rm != NULL);
|
DEBUGASSERT(rm != NULL);
|
||||||
|
|
||||||
/* Map the offset according to the whence option */
|
/* Map the offset according to the whence option */
|
||||||
|
|
||||||
switch (whence)
|
switch (whence)
|
||||||
{
|
{
|
||||||
case SEEK_SET: /* The offset is set to offset bytes. */
|
case SEEK_SET: /* The offset is set to offset bytes. */
|
||||||
@@ -516,10 +504,47 @@ errout_with_semaphore:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: romfs_ioctl
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int romfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||||
|
{
|
||||||
|
struct romfs_mountpt_s *rm;
|
||||||
|
struct romfs_file_s *rf;
|
||||||
|
void **ppv = (void**)arg;
|
||||||
|
|
||||||
|
/* Sanity checks */
|
||||||
|
|
||||||
|
DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
|
||||||
|
|
||||||
|
/* Recover our private data from the struct file instance */
|
||||||
|
|
||||||
|
rf = filep->f_priv;
|
||||||
|
rm = filep->f_inode->i_private;
|
||||||
|
|
||||||
|
DEBUGASSERT(rm != NULL);
|
||||||
|
|
||||||
|
/* Only one ioctl command is supported */
|
||||||
|
|
||||||
|
if (cmd == FIOC_MMAP && rm->rm_xipbase && ppv)
|
||||||
|
{
|
||||||
|
/* Return the address on the media corresponding to the start of
|
||||||
|
* the file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
*ppv = (void*)(rm->rm_xipbase + rf->rf_startoffset);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOTTY;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: romfs_opendir
|
* Name: romfs_opendir
|
||||||
*
|
*
|
||||||
* Description: Open a directory for read access
|
* Description:
|
||||||
|
* Open a directory for read access
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
@@ -743,41 +768,37 @@ static int romfs_bind(FAR struct inode *blkdriver, const void *data,
|
|||||||
|
|
||||||
sem_init(&rm->rm_sem, 0, 0); /* Initialize the semaphore that controls access */
|
sem_init(&rm->rm_sem, 0, 0); /* Initialize the semaphore that controls access */
|
||||||
rm->rm_blkdriver = blkdriver; /* Save the block driver reference */
|
rm->rm_blkdriver = blkdriver; /* Save the block driver reference */
|
||||||
rm->rm_cachesector = (uint32)-1; /* No sector in the cache */
|
|
||||||
|
|
||||||
/* Get the hardware configuration */
|
/* Get the hardware configuration and setup buffering appropriately */
|
||||||
|
|
||||||
ret = romfs_getgeometry(rm);
|
ret = romfs_hwconfigure(rm);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
goto errout_with_sem;
|
goto errout_with_sem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate the device cache buffer */
|
/* Then complete the mount by getting the ROMFS configuratrion from
|
||||||
|
* the ROMF header
|
||||||
|
*/
|
||||||
|
|
||||||
rm->rm_buffer = (ubyte*)malloc(rm->rm_hwsectorsize);
|
ret = romfs_fsconfigure(rm);
|
||||||
if (!rm->rm_buffer)
|
|
||||||
{
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto errout_with_sem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Then complete the mount */
|
|
||||||
|
|
||||||
ret = romfs_mount(rm);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
goto errout_with_buffer;
|
goto errout_with_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mounted */
|
/* Mounted! */
|
||||||
|
|
||||||
*handle = (void*)rm;
|
*handle = (void*)rm;
|
||||||
romfs_semgive(rm);
|
romfs_semgive(rm);
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
errout_with_buffer:
|
errout_with_buffer:
|
||||||
free(rm->rm_buffer);
|
if (!rm->rm_xipbase)
|
||||||
|
{
|
||||||
|
free(rm->rm_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
errout_with_sem:
|
errout_with_sem:
|
||||||
sem_destroy(&rm->rm_sem);
|
sem_destroy(&rm->rm_sem);
|
||||||
free(rm);
|
free(rm);
|
||||||
@@ -841,7 +862,7 @@ static int romfs_unbind(void *handle, FAR struct inode **blkdriver)
|
|||||||
|
|
||||||
/* Release the mountpoint private data */
|
/* Release the mountpoint private data */
|
||||||
|
|
||||||
if (rm->rm_buffer)
|
if (!rm->rm_xipbase && rm->rm_buffer)
|
||||||
{
|
{
|
||||||
free(rm->rm_buffer);
|
free(rm->rm_buffer);
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-4
@@ -141,7 +141,8 @@ struct romfs_mountpt_s
|
|||||||
uint32 rm_hwnsectors; /* HW: The number of sectors reported by the hardware */
|
uint32 rm_hwnsectors; /* HW: The number of sectors reported by the hardware */
|
||||||
uint32 rm_volsize; /* Size of the ROMFS volume */
|
uint32 rm_volsize; /* Size of the ROMFS volume */
|
||||||
uint32 rm_cachesector; /* Current sector in the rm_buffer */
|
uint32 rm_cachesector; /* Current sector in the rm_buffer */
|
||||||
ubyte *rm_buffer; /* Device sector buffer */
|
ubyte *rm_xipbase; /* Base address of directly accessible media */
|
||||||
|
ubyte *rm_buffer; /* Device sector buffer, allocated if rm_xipbase==0 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This structure represents on open file under the mountpoint. An instance
|
/* This structure represents on open file under the mountpoint. An instance
|
||||||
@@ -156,7 +157,7 @@ struct romfs_file_s
|
|||||||
uint32 rf_startoffset; /* Offset to the start of the file data */
|
uint32 rf_startoffset; /* Offset to the start of the file data */
|
||||||
uint32 rf_size; /* Size of the file in bytes */
|
uint32 rf_size; /* Size of the file in bytes */
|
||||||
uint32 rf_cachesector; /* Current sector in the rf_buffer */
|
uint32 rf_cachesector; /* Current sector in the rf_buffer */
|
||||||
ubyte *rf_buffer; /* File sector buffer */
|
ubyte *rf_buffer; /* File sector buffer, allocated if rm_xipbase==0 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This structure is used internally for describing the result of
|
/* This structure is used internally for describing the result of
|
||||||
@@ -201,8 +202,10 @@ EXTERN int romfs_hwread(struct romfs_mountpt_s *rm, ubyte *buffer,
|
|||||||
EXTERN int romfs_devcacheread(struct romfs_mountpt_s *rm, uint32 sector);
|
EXTERN int romfs_devcacheread(struct romfs_mountpt_s *rm, uint32 sector);
|
||||||
EXTERN int romfs_filecacheread(struct romfs_mountpt_s *rm,
|
EXTERN int romfs_filecacheread(struct romfs_mountpt_s *rm,
|
||||||
struct romfs_file_s *rf, uint32 sector);
|
struct romfs_file_s *rf, uint32 sector);
|
||||||
EXTERN int romfs_getgeometry(struct romfs_mountpt_s *rm);
|
EXTERN int romfs_hwconfigure(struct romfs_mountpt_s *rm);
|
||||||
EXTERN int romfs_mount(struct romfs_mountpt_s *rm);
|
EXTERN int romfs_fsconfigure(struct romfs_mountpt_s *rm);
|
||||||
|
EXTERN int romfs_fileconfigure(struct romfs_mountpt_s *rm,
|
||||||
|
struct romfs_file_s *rf);
|
||||||
EXTERN int romfs_checkmount(struct romfs_mountpt_s *rm);
|
EXTERN int romfs_checkmount(struct romfs_mountpt_s *rm);
|
||||||
EXTERN int romfs_finddirentry(struct romfs_mountpt_s *rm,
|
EXTERN int romfs_finddirentry(struct romfs_mountpt_s *rm,
|
||||||
struct romfs_dirinfo_s *dirinfo,
|
struct romfs_dirinfo_s *dirinfo,
|
||||||
|
|||||||
+171
-47
@@ -42,12 +42,15 @@
|
|||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include <nuttx/ioctl.h>
|
||||||
|
|
||||||
#include "fs_romfs.h"
|
#include "fs_romfs.h"
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -298,14 +301,28 @@ void romfs_semgive(struct romfs_mountpt_s *rm)
|
|||||||
int romfs_hwread(struct romfs_mountpt_s *rm, ubyte *buffer, uint32 sector,
|
int romfs_hwread(struct romfs_mountpt_s *rm, ubyte *buffer, uint32 sector,
|
||||||
unsigned int nsectors)
|
unsigned int nsectors)
|
||||||
{
|
{
|
||||||
struct inode *inode;;
|
|
||||||
ssize_t nsectorsread;
|
|
||||||
int ret = -ENODEV;
|
int ret = -ENODEV;
|
||||||
|
|
||||||
if (rm && rm->rm_blkdriver)
|
/* Check the access mode */
|
||||||
|
|
||||||
|
if (rm->rm_xipbase)
|
||||||
{
|
{
|
||||||
inode = rm->rm_blkdriver;
|
/* In XIP mode, we just copy the requested data */
|
||||||
if (inode && inode->u.i_bops && inode->u.i_bops->read)
|
|
||||||
|
memcpy(buffer,
|
||||||
|
rm->rm_xipbase + sector*rm->rm_hwsectorsize,
|
||||||
|
nsectors*rm->rm_hwsectorsize);
|
||||||
|
ret = OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* In non-XIP mode, we have to read the data from the device */
|
||||||
|
|
||||||
|
struct inode *inode = rm->rm_blkdriver;
|
||||||
|
ssize_t nsectorsread;
|
||||||
|
|
||||||
|
DEBUGASSERT(inode);
|
||||||
|
if (inode->u.i_bops && inode->u.i_bops->read)
|
||||||
{
|
{
|
||||||
nsectorsread =
|
nsectorsread =
|
||||||
inode->u.i_bops->read(inode, buffer, sector, nsectors);
|
inode->u.i_bops->read(inode, buffer, sector, nsectors);
|
||||||
@@ -335,24 +352,39 @@ int romfs_devcacheread(struct romfs_mountpt_s *rm, uint32 sector)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* rm->rm_cachesector holds the current sector that is buffered in
|
/* rm->rm_cachesector holds the current sector that is buffer in or referenced
|
||||||
* rm->tm_buffer. If the requested sector is the same as this sector, then
|
* by rm->tm_buffer. If the requested sector is the same as this sector,
|
||||||
* we do nothing. Otherwise, we will have to read the new sector.
|
* then we do nothing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (rm->rm_cachesector != sector)
|
if (rm->rm_cachesector != sector)
|
||||||
{
|
{
|
||||||
ret = romfs_hwread(rm, rm->rm_buffer, sector, 1);
|
/* Check the access mode */
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update the cached sector number */
|
if (rm->rm_xipbase)
|
||||||
|
{
|
||||||
|
/* In XIP mode, rf_buffer is just an offset pointer into the device
|
||||||
|
* address space.
|
||||||
|
*/
|
||||||
|
|
||||||
rm->rm_cachesector = sector;
|
rm->rm_buffer = rm->rm_xipbase + sector*rm->rm_hwsectorsize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* In non-XIP mode, we will have to read the new sector.*/
|
||||||
|
|
||||||
|
ret = romfs_hwread(rm, rm->rm_buffer, sector, 1);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the cached sector number */
|
||||||
|
|
||||||
|
rm->rm_cachesector = sector;
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -367,35 +399,53 @@ int romfs_filecacheread(struct romfs_mountpt_s *rm, struct romfs_file_s *rf, uin
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* rf->rf_cachesector holds the current sector that is buffered in
|
/* rf->rf_cachesector holds the current sector that is buffer in or referenced
|
||||||
* rf->rf_buffer. If the requested sector is the same as this sector, then
|
* by rf->rf_buffer. If the requested sector is the same as this sector,
|
||||||
* we do nothing. Otherwise, we will have to read the new sector.
|
* then we do nothing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (rf->rf_cachesector != sector)
|
if (rf->rf_cachesector != sector)
|
||||||
{
|
{
|
||||||
ret = romfs_hwread(rm, rf->rf_buffer, sector, 1);
|
/* Check the access mode */
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update the cached sector number */
|
if (rm->rm_xipbase)
|
||||||
|
{
|
||||||
|
/* In XIP mode, rf_buffer is just an offset pointer into the device
|
||||||
|
* address space.
|
||||||
|
*/
|
||||||
|
|
||||||
rf->rf_cachesector = sector;
|
rf->rf_buffer = rm->rm_xipbase + sector*rm->rm_hwsectorsize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* In non-XIP mode, we will have to read the new sector.*/
|
||||||
|
|
||||||
|
ret = romfs_hwread(rm, rf->rf_buffer, sector, 1);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the cached sector number */
|
||||||
|
|
||||||
|
rf->rf_cachesector = sector;
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: romfs_getgeometry
|
* Name: romfs_hwconfigure
|
||||||
*
|
*
|
||||||
* Desciption:
|
* Desciption:
|
||||||
* Get the geometry of the device (part of the mount operation)
|
* This function is called as part of the ROMFS mount operation It
|
||||||
|
* configures the ROMFS filestem for use on this block driver. This includes
|
||||||
|
* the accounting for the geometry of the device, setting up any XIP modes
|
||||||
|
* of operation, and/or allocating any cache buffers.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int romfs_getgeometry(struct romfs_mountpt_s *rm)
|
int romfs_hwconfigure(struct romfs_mountpt_s *rm)
|
||||||
{
|
{
|
||||||
struct inode *inode = rm->rm_blkdriver;
|
struct inode *inode = rm->rm_blkdriver;
|
||||||
struct geometry geo;
|
struct geometry geo;
|
||||||
@@ -403,10 +453,12 @@ int romfs_getgeometry(struct romfs_mountpt_s *rm)
|
|||||||
|
|
||||||
/* Get the underlying device geometry */
|
/* Get the underlying device geometry */
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG
|
||||||
if (!inode || !inode->u.i_bops || !inode->u.i_bops->geometry)
|
if (!inode || !inode->u.i_bops || !inode->u.i_bops->geometry)
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ret = inode->u.i_bops->geometry(inode, &geo);
|
ret = inode->u.i_bops->geometry(inode, &geo);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
@@ -423,18 +475,50 @@ int romfs_getgeometry(struct romfs_mountpt_s *rm)
|
|||||||
|
|
||||||
rm->rm_hwsectorsize = geo.geo_sectorsize;
|
rm->rm_hwsectorsize = geo.geo_sectorsize;
|
||||||
rm->rm_hwnsectors = geo.geo_nsectors;
|
rm->rm_hwnsectors = geo.geo_nsectors;
|
||||||
|
|
||||||
|
/* Determine if block driver supports the XIP mode of operation */
|
||||||
|
|
||||||
|
rm->rm_cachesector = (uint32)-1;
|
||||||
|
|
||||||
|
if (inode->u.i_bops->ioctl)
|
||||||
|
{
|
||||||
|
ret = inode->u.i_bops->ioctl(inode, BIOC_XIPBASE,
|
||||||
|
(unsigned long)&rm->rm_xipbase);
|
||||||
|
if (ret == OK && rm->rm_xipbase)
|
||||||
|
{
|
||||||
|
/* Yes.. Then we will directly access the media (vs.
|
||||||
|
* copying into an allocated sector buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
rm->rm_buffer = rm->rm_xipbase;
|
||||||
|
rm->rm_cachesector = 0;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate the device cache buffer for normal sector accesses */
|
||||||
|
|
||||||
|
rm->rm_buffer = (ubyte*)malloc(rm->rm_hwsectorsize);
|
||||||
|
if (!rm->rm_buffer)
|
||||||
|
{
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: romfs_mount
|
* Name: romfs_fsconfigure
|
||||||
*
|
*
|
||||||
* Desciption:
|
* Desciption:
|
||||||
* Setup ROMFS on the block driver
|
* This function is called as part of the ROMFS mount operation It
|
||||||
|
* sets up the mount structure to include configuration information contained
|
||||||
|
* in the ROMFS header. This is the place where we actually determine if
|
||||||
|
* the media contains a ROMFS filesystem.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int romfs_mount(struct romfs_mountpt_s *rm)
|
int romfs_fsconfigure(struct romfs_mountpt_s *rm)
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -471,6 +555,46 @@ int romfs_mount(struct romfs_mountpt_s *rm)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: romfs_ffileconfigure
|
||||||
|
*
|
||||||
|
* Desciption:
|
||||||
|
* This function is called as part of the ROMFS file open operation It
|
||||||
|
* sets up the file structure to handle buffer appropriately, depending
|
||||||
|
* upon XIP mode or not.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int romfs_fileconfigure(struct romfs_mountpt_s *rm, struct romfs_file_s *rf)
|
||||||
|
{
|
||||||
|
/* Check if XIP access mode is supported. If so, then we do not need
|
||||||
|
* to allocate anything.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (rm->rm_xipbase)
|
||||||
|
{
|
||||||
|
/* We'll put a valid address in rf_buffer just in case. */
|
||||||
|
|
||||||
|
rf->rf_cachesector = 0;
|
||||||
|
rf->rf_buffer = rm->rm_xipbase + rf->rf_startoffset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Nothing in the cache buffer */
|
||||||
|
|
||||||
|
rf->rf_cachesector = (uint32)-1;
|
||||||
|
|
||||||
|
/* Create a file buffer to support partial sector accesses */
|
||||||
|
|
||||||
|
rf->rf_buffer = (ubyte*)malloc(rm->rm_hwsectorsize);
|
||||||
|
if (!rf->rf_buffer)
|
||||||
|
{
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: romfs_checkmount
|
* Name: romfs_checkmount
|
||||||
*
|
*
|
||||||
@@ -482,29 +606,29 @@ int romfs_mount(struct romfs_mountpt_s *rm)
|
|||||||
|
|
||||||
int romfs_checkmount(struct romfs_mountpt_s *rm)
|
int romfs_checkmount(struct romfs_mountpt_s *rm)
|
||||||
{
|
{
|
||||||
|
struct romfs_file_s *file;
|
||||||
|
struct inode *inode;
|
||||||
|
struct geometry geo;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* If the fs_mounted flag is FALSE, then we have already handled the loss
|
/* If the fs_mounted flag is FALSE, then we have already handled the loss
|
||||||
* of the mount.
|
* of the mount.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (rm && rm->rm_mounted)
|
DEBUGASSERT(rm && rm->rm_blkdriver);
|
||||||
|
if (rm->rm_mounted)
|
||||||
{
|
{
|
||||||
struct romfs_file_s *file;
|
|
||||||
|
|
||||||
/* We still think the mount is healthy. Check an see if this is
|
/* We still think the mount is healthy. Check an see if this is
|
||||||
* still the case
|
* still the case
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (rm->rm_blkdriver)
|
inode = rm->rm_blkdriver;
|
||||||
|
if (inode->u.i_bops && inode->u.i_bops->geometry)
|
||||||
{
|
{
|
||||||
struct inode *inode = rm->rm_blkdriver;
|
ret = inode->u.i_bops->geometry(inode, &geo);
|
||||||
if (inode && inode->u.i_bops && inode->u.i_bops->geometry)
|
if (ret == OK && geo.geo_available && !geo.geo_mediachanged)
|
||||||
{
|
{
|
||||||
struct geometry geo;
|
return OK;
|
||||||
int errcode = inode->u.i_bops->geometry(inode, &geo);
|
|
||||||
if (errcode == OK && geo.geo_available && !geo.geo_mediachanged)
|
|
||||||
{
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-4
@@ -52,6 +52,7 @@
|
|||||||
* defined below:
|
* defined below:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define _FIOCBASE (0x8700) /* File system ioctl commands */
|
||||||
#define _BIOCBASE (0x8800) /* Block driver ioctl commands */
|
#define _BIOCBASE (0x8800) /* Block driver ioctl commands */
|
||||||
#define _SIOCBASE (0x8900) /* Socket ioctl commandss */
|
#define _SIOCBASE (0x8900) /* Socket ioctl commandss */
|
||||||
|
|
||||||
@@ -63,14 +64,25 @@
|
|||||||
|
|
||||||
#define _IOC(type,nr) ((type)|(nr))
|
#define _IOC(type,nr) ((type)|(nr))
|
||||||
|
|
||||||
|
/* NuttX file system ioctl definitions */
|
||||||
|
|
||||||
|
#define _FIOCVALID(c) (_IOC_TYPE(c)==_FIOCBASE)
|
||||||
|
#define _FIOC(nr) _IOC(_FIOCBASE,nr)
|
||||||
|
|
||||||
|
#define FIOC_MMAP _FIOC(0x0001) /* IN: None
|
||||||
|
* OUT: If media is directly acccesible,
|
||||||
|
* return (void*) base address
|
||||||
|
* of file */
|
||||||
|
|
||||||
/* NuttX block driver ioctl definitions */
|
/* NuttX block driver ioctl definitions */
|
||||||
|
|
||||||
#define _BIOCVALID(c) (_IOC_TYPE(c)==_BIOCBASE)
|
#define _BIOCVALID(c) (_IOC_TYPE(c)==_BIOCBASE)
|
||||||
#define _BIOC(nr) _IOC(_SIOCBASE,nr)
|
#define _BIOC(nr) _IOC(_BIOCBASE,nr)
|
||||||
|
|
||||||
#define _BIOC_XIPBASE _BIOC(0x0001) /* IN: None
|
#define BIOC_XIPBASE _BIOC(0x0001) /* IN: None
|
||||||
* OUT: If underlying is random acccesible,
|
* OUT: If media is directly acccesible,
|
||||||
* return (void*) base address */
|
* return (void*) base address
|
||||||
|
* of device memory */
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Type Definitions
|
* Public Type Definitions
|
||||||
|
|||||||
Reference in New Issue
Block a user