Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 157 additions & 0 deletions apps/system/utils/fscmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <tinyara/fs/fs_utils.h>
#include <tinyara/fs/mtd.h>
#include <tinyara/fs/ioctl.h>
#ifdef CONFIG_TASH
#include <apps/shell/tash.h>
#endif
Expand Down Expand Up @@ -994,6 +996,155 @@ static int tash_umount(int argc, char **args)
#endif
#endif /* END OF CONFIG_DISABLE_MOUNTPOINT */

/****************************************************************************
* Name: tash_smartfs_dump
*
* Description:
* Unmount specific file system.
*
* Usage:
* umount <mounted directory>
****************************************************************************/
#ifdef CONFIG_SMARTFS_DEBUG
#ifndef CONFIG_DISABLE_ENVIRON
static int tash_smartfs_dump(int argc, char **args)
{
int fd;
int ret;
char device_path[32];
struct mtd_geometry_s mtd_geo;
uint8_t *buffer;
ssize_t nbytes;
off_t seekpos;
size_t sector_size = 1024; /* SMARTFS sector size = 1024 bytes */
uint16_t BlkperSect;
uint16_t SectperEraseBlk;
uint16_t total_sectors;
uint16_t sector_idx;
uint16_t erase_block;
uint16_t sector_in_block;
uint16_t njournaleraseblocks;

int i, j;

bool found = false;

printf("Searching for MTD BLOCK device managed smartfs...\n");
for (int minor = 0; minor < 2; minor++) {
for (int part = 0; part < 32; part++) {
snprintf(device_path, sizeof(device_path), "/dev/mtdblock%dp%d", minor, part);

fd = open(device_path, O_RDONLY);
if (fd >= 0) {
printf("Found MTD BLOCK device managed smartfs: %s\n", device_path);
found = true;
break;
}
}
if (found) {
break;
}
}

if (!found) {
printf("Can Not Find MTD BLOCK device managed smartfs\n");
return ERROR;
}

ret = ioctl(fd, MTDIOC_GEOMETRY, (unsigned long)&mtd_geo);
if (ret < 0) {
printf("Failed to get MTD geometry, errno: %d\n", errno);
close(fd);
return ERROR;
}

printf("\n=== MTD Geometry ===\n");
printf(" Block size: %u bytes\n", mtd_geo.blocksize);
printf(" Erase Blocksize: %u bytes\n", mtd_geo.erasesize);
printf(" Num Erase Blocks: %u\n", mtd_geo.neraseblocks);

BlkperSect = sector_size / mtd_geo.blocksize;
SectperEraseBlk = mtd_geo.erasesize / sector_size;
total_sectors = mtd_geo.neraseblocks * SectperEraseBlk;

printf(" Sector size: %u bytes\n", sector_size);
printf(" Sectors per Erase Block: %u\n", SectperEraseBlk);
printf(" Total sectors: %u\n", total_sectors);


uint16_t nsector = (mtd_geo.neraseblocks * SectperEraseBlk * 13) / (sector_size + 13);
njournaleraseblocks = nsector / SectperEraseBlk;
if (nsector % SectperEraseBlk != 0) {
njournaleraseblocks++;
}
if (njournaleraseblocks % 2 != 0) {
njournaleraseblocks++;
}
njournaleraseblocks *= 3;

printf(" njournaleraseblocks: %u\n", njournaleraseblocks);

buffer = (uint8_t *)malloc(sector_size);
if (!buffer) {
printf("Failed to allocate buffer\n");
close(fd);
return ERROR;
}

printf("\n=== Dumping All Sectors (Block 0 ~ %u) ===\n", mtd_geo.neraseblocks - 1);

sector_idx = 0;
for (erase_block = 0; erase_block < mtd_geo.neraseblocks; erase_block++) {
for (sector_in_block = 0; sector_in_block < SectperEraseBlk; sector_in_block++) {
unsigned int mtd_block = sector_idx * BlkperSect;

printf("\n=== Sector %u (block %u) ===\n", sector_idx, erase_block);

seekpos = (off_t)mtd_block * mtd_geo.blocksize;
ret = lseek(fd, seekpos, SEEK_SET);
if (ret != seekpos) {
printf("Failed to seek to sector %u (offset %ld), errno: %d\n",
sector_idx, (long)seekpos, errno);
sector_idx++;
continue;
}

nbytes = read(fd, buffer, sector_size);
if (nbytes < 0) {
printf("Read failed, errno: %d\n", errno);
sector_idx++;
continue;
} else if (nbytes != (ssize_t)sector_size) {
printf("Short read: got %ld bytes, expected %u\n", (long)nbytes, sector_size);
}

int dump_size = nbytes;
for (i = 0; i < dump_size; i += 16) {
printf("%04X: ", i);

for (j = 0; j < 16; j++) {
if (i + j < dump_size) {
printf("%02X ", buffer[i + j]);
} else {
printf(" ");
}
}
printf("\n");
}

sector_idx++;
}
}

free(buffer);
close(fd);

printf("\n=== Dump Complete ===\n");
return OK;
}
#endif
#endif

#ifndef CONFIG_DISABLE_ENVIRON
/****************************************************************************
* Name: tash_pwd
Expand Down Expand Up @@ -1557,6 +1708,12 @@ const static tash_cmdlist_t fs_utilcmds[] = {
{"rmdir", tash_rmdir, TASH_EXECMD_SYNC},
#endif

#ifdef CONFIG_SMARTFS_DEBUG
#ifndef CONFIG_DISABLE_ENVIRON
{"smartfs_dump", tash_smartfs_dump, TASH_EXECMD_SYNC},
#endif
#endif

{NULL, NULL, 0}
};

Expand Down
1 change: 1 addition & 0 deletions build/configs/rtl8730e/flat_dev_ddr/defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1121,6 +1121,7 @@ CONFIG_SMARTFS_MAXNAMLEN=32
CONFIG_SMARTFS_ALIGNED_ACCESS=y
# CONFIG_SMARTFS_DYNAMIC_HEADER is not set
CONFIG_SMARTFS_ENTRY_TIMESTAMP=y
CONFIG_SMARTFS_DEBUG=y
CONFIG_FS_PROCFS=y
CONFIG_FS_AUTOMOUNT_PROCFS=y

Expand Down
6 changes: 6 additions & 0 deletions os/board/common/partitions.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,12 @@ static int type_specific_initialize(int minor, FAR struct mtd_dev_s *mtd_part, c
char partref[4];

snprintf(partref, sizeof(partref), "p%d", g_partno);
#ifdef CONFIG_SMARTFS_DEBUG
if (ftl_initialize_ext(minor, mtd_part, partref)) {
printf("ERROR: failed to initialise mtd ftl errno :%d\n", errno);
return ERROR;
}
#endif
smart_initialize(minor, mtd_part, partref);
partinfo->smartfs_partno = g_partno;
mtd_setpartitiontagno(mtd_part, MTD_FS);
Expand Down
107 changes: 107 additions & 0 deletions os/fs/driver/mtd/ftl.c
Original file line number Diff line number Diff line change
Expand Up @@ -582,3 +582,110 @@ int ftl_initialize(int minor, FAR struct mtd_dev_s *mtd)

return ret;
}

/****************************************************************************
* Public Functions
****************************************************************************/

/****************************************************************************
* Name: ftl_initialize_ext
*
* Description:
* Initialize to provide a block driver wrapper around an MTD interface
*
* Input Parameters:
* minor - The minor device number. The MTD block device will be
* registered as as /dev/mtdblockN where N is the minor number.
* mtd - The MTD device that supports the FLASH interface.
* partname - Optional partition name to append to dev entry, NULL if
* not supplied.
****************************************************************************/

#ifdef CONFIG_SMARTFS_DEBUG
int ftl_initialize_ext(int minor, FAR struct mtd_dev_s *mtd, FAR const char *partname)
{
struct ftl_struct_s *dev;
char devname[22];
int ret = -ENOMEM;

/* Sanity check */

if (minor < 0 || minor > 255 || !mtd) {
return -EINVAL;
}

/* Allocate a FTL device structure */

dev = (struct ftl_struct_s *)kmm_malloc(sizeof(struct ftl_struct_s));
if (dev) {
/* Initialize the FTL device structure */

dev->mtd = mtd;

/* Get the device geometry. (casting to uintptr_t first eliminates
* complaints on some architectures where the sizeof long is different
* from the size of a pointer).
*/

ret = MTD_IOCTL(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&dev->geo));
if (ret < 0) {
dbg("ERROR: MTD ioctl(MTDIOC_GEOMETRY) failed: %d\n", ret);
kmm_free(dev);
return ret;
}

/* Allocate one, in-memory erase block buffer */

#ifdef CONFIG_FS_WRITABLE
dev->eblock = (FAR uint8_t *)kmm_malloc(dev->geo.erasesize);
if (!dev->eblock) {
dbg("ERROR: Failed to allocate an erase block buffer\n");
kmm_free(dev);
return -ENOMEM;
}
#endif

/* Get the number of R/W blocks per erase block */

dev->blkper = dev->geo.erasesize / dev->geo.blocksize;
DEBUGASSERT(dev->blkper * dev->geo.blocksize == dev->geo.erasesize);

/* Configure read-ahead/write buffering */

#ifdef FTL_HAVE_RWBUFFER
dev->rwb.blocksize = dev->geo.blocksize;
dev->rwb.nblocks = dev->geo.neraseblocks * dev->blkper;
dev->rwb.dev = (FAR void *)dev;

#if defined(CONFIG_FS_WRITABLE) && defined(CONFIG_FTL_WRITEBUFFER)
dev->rwb.wrmaxblocks = dev->blkper;
dev->rwb.wrflush = ftl_flush;
#endif

#ifdef CONFIG_FTL_READAHEAD
dev->rwb.rhmaxblocks = dev->blkper;
dev->rwb.rhreload = ftl_reload;
#endif

ret = rwb_initialize(&dev->rwb);
if (ret < 0) {
dbg("ERROR: rwb_initialize failed: %d\n", ret);
kmm_free(dev);
return ret;
}
#endif

/* Create a MTD block device name */
snprintf(devname, 22, "/dev/mtdblock%d%s", minor, partname);
/* Inode private data is a reference to the FTL device structure */

ret = register_blockdriver(devname, &g_bops, 0, dev);
if (ret < 0) {
dbg("ERROR: register_blockdriver failed: %d\n", -ret);
kmm_free(dev);
}
}

return ret;
}
#endif