Пример #1
0
int loteardown(const char *devname)
{
  FAR struct loop_struct_s *dev;
  FAR struct inode *inode;
  int ret;

  /* Sanity check */

#ifdef CONFIG_DEBUG
  if (!devname)
    {
      return -EINVAL;
    }
#endif

  /* Open the block driver associated with devname so that we can get the inode
   * reference.
   */

  ret = open_blockdriver(devname, MS_RDONLY, &inode);
  if (ret < 0)
    {
      dbg("Failed to open %s: %d\n", devname, -ret);
      return ret;
    }

  /* Inode private data is a reference to the loop device stgructure */

  dev = (FAR struct loop_struct_s *)inode->i_private;
  close_blockdriver(inode);

  DEBUGASSERT(dev);

  /* Are there still open references to the device */

  if (dev->opencnt > 0)
    {
      return -EBUSY;
    }

  /* Otherwise, unregister the block device */

  ret = unregister_blockdriver(devname);

  /* Release the device structure */

  if (dev->fd >= 0)
    {
      (void)close(dev->fd);
    }

  kfree(dev);
  return ret;
}
Пример #2
0
int flash_eraseall(FAR const char *driver)
{
  FAR struct inode *inode;
  FAR const struct block_operations *ops;
  int ret;

  /* Open the block driver */

  ret = open_blockdriver(driver ,0, &inode);
  if (ret < 0)
    {
      fdbg("ERROR: Failed to open '%s': %d\n", driver, ret);
      return ret;
    }

  /* Get the block operations */

  ops = inode->u.i_bops;

  /* Invoke the block driver ioctl method */

  ret = -EPERM;
  if (ops->ioctl)
    {
      ret = ops->ioctl(inode, MTDIOC_BULKERASE, 0);
      if (ret < 0)
        {
          fdbg("ERROR: MTD ioctl(%04x) failed: %d\n", MTDIOC_BULKERASE, ret);
        }
    }

  /* Close the block driver */

  close_blockdriver(inode);
  return ret;
}
int flash_test_main(int argc, char *argv[])
{
  struct inode* inode;
  int           ret;
  int           x;
  int           logsector;
  uint16_t      seq;
  struct smart_format_s fmt;
  uint16_t     *sectors;
  uint16_t     *seqs;
  char         *buffer;
  struct smart_read_write_s readwrite;

  /* Argument given? */

  if (argc < 2)
    {
      fprintf(stderr, "usage: flash_test flash_block_device\n");
      return -1;
    }

  /* Find the inode of the block driver indentified by 'source' */

  ret = open_blockdriver(argv[1], 0, &inode);
  if (ret < 0)
    {
      fprintf(stderr, "Failed to open %s\n", argv[1]);
      goto errout;
    }

  /* Get the low-level format from the device. */

  ret = inode->u.i_bops->ioctl(inode, BIOC_GETFORMAT, (unsigned long) &fmt);
  if (ret != OK)
    {
      fprintf(stderr, "Device is not a SMART block device\n");
      goto errout_with_driver;
    }

  /* Test if the device is formatted.  If not, then we must do a 
   * low-level format first */
  
  if (!(fmt.flags & SMART_FMT_ISFORMATTED))
    {
      /* Perform a low-level format */

      ret = inode->u.i_bops->ioctl(inode, BIOC_LLFORMAT, 0);
      ret = inode->u.i_bops->ioctl(inode, BIOC_GETFORMAT, (unsigned long) &fmt);
    }

  if (!(fmt.flags & SMART_FMT_ISFORMATTED))
    {
      fprintf(stderr, "Unable to get device format\n");
      goto errout_with_driver;
    }

  /* Report the device structure */

  printf("FLASH Test on device with:\n");
  printf("   Sector size:  %10d\n", fmt.sectorsize);
  printf("   Sector count: %10d\n", fmt.nsectors);
  printf("   Avail bytes:  %10d\n", fmt.availbytes);
  printf("   Total size:   %10d\n", fmt.sectorsize * fmt.nsectors);

  /* Allocate buffers to use */

  buffer = (char *) malloc(fmt.availbytes);
  if (buffer == NULL)
    {
      fprintf(stderr, "Error allocating buffer\n");
      goto errout_with_driver;
    }

  seqs = (uint16_t *) malloc(fmt.nsectors << 1);
  if (seqs == NULL)
    {
      (void) free(buffer);
      fprintf(stderr, "Error allocating seqs buffer\n");
      goto errout_with_driver;
    }

  sectors = (uint16_t *) malloc(fmt.nsectors << 1);
  if (sectors == NULL)
    {
      (void) free(seqs);
      (void) free(buffer);
      fprintf(stderr, "Error allocating sectors buffer\n");
      goto errout_with_driver;
    }

  /* Write a bunch of data to the flash */

  printf("\nAllocating and writing to logical sectors\n");

  seq = 0;
  for (x = 0; x < fmt.nsectors >> 1; x++)
    {
      /* Allocate a new sector */

      logsector = inode->u.i_bops->ioctl(inode, BIOC_ALLOCSECT, 
                                         (unsigned long) -1);
      if (logsector < 0)
        {
          fprintf(stderr, "Error allocating sector: %d\n", logsector);
          goto errout_with_driver; 
        }

      /* Save the sector in our array */
     
      sectors[x] = (uint16_t) logsector;
      seqs[x] = seq++;

      /* Now write some data to the sector */

      sprintf(buffer, "Logical sector %d sequence %d\n",
              sectors[x], seqs[x]);

      readwrite.logsector = sectors[x];
      readwrite.offset = 0;
      readwrite.count = strlen(buffer) + 1;
      readwrite.buffer = (uint8_t *) buffer;
      ret = inode->u.i_bops->ioctl(inode, BIOC_WRITESECT, (unsigned long)
                                   &readwrite);

      /* Print the logical sector number */

      printf("\r%d    ", sectors[x]);
    }

  /* Now read the data back to validate everything was written and can 
   * be read. */

  printf("\nDoing read verify test\n");
  for (x = 0; x < fmt.nsectors >> 1; x++)
    {
      /* Read from the logical sector */

      readwrite.logsector = sectors[x];
      readwrite.offset = 0;
      readwrite.count = fmt.availbytes;
      readwrite.buffer = (uint8_t *) buffer;
      ret = inode->u.i_bops->ioctl(inode, BIOC_READSECT, (unsigned long)
                                   &readwrite);

      if (ret != fmt.availbytes)
        {
          fprintf(stderr, "Error reading sector %d\n", sectors[x]);
          goto errout_with_buffers;
        }

      /* Generate compare string and do the comapre */

      printf("\r%d     ", sectors[x]);

      sprintf(&buffer[100], "Logical sector %d sequence %d\n",
              sectors[x], seqs[x]);

      if (strcmp(buffer, &buffer[100]) != 0)
        {
          printf("Sector %d read verify failed\n", sectors[x]);
        }
    }

  printf("\nPeforming sector re-write\n");

  /* Overwrite data on the sectors to cause relocation */

  for (x = 0; x < fmt.nsectors >> 1; x++)
    {
      /* Save a new sequence number for the sector */

      seqs[x] = seq++;

      /* Now write over the sector data with new data, causing a relocation. */

      sprintf(buffer, "Logical sector %d sequence %d\n", sectors[x], seqs[x]);
      readwrite.logsector = sectors[x];
      readwrite.offset = 0;
      readwrite.count = strlen(buffer) + 1;
      readwrite.buffer = (uint8_t *) buffer;
      ret = inode->u.i_bops->ioctl(inode, BIOC_WRITESECT, (unsigned long)
                                   &readwrite);

      /* Print the logical sector number */

      printf("\r%d    ", sectors[x]);
    }

  /* Now append data to empty region of sector */

  printf("\nAppending data to empty region of sector\n");

  for (x = 0; x < fmt.nsectors >> 1; x++)
    {
      /* Save a new sequence number for the sector */

      seqs[x] = seq++;

      /* Now write over the sector data with new data, causing a relocation. */

      sprintf(buffer, "Appended data in sector %d\n", sectors[x]);
      readwrite.logsector = sectors[x];
      readwrite.offset = 64;
      readwrite.count = strlen(buffer) + 1;
      readwrite.buffer = (uint8_t *) buffer;
      ret = inode->u.i_bops->ioctl(inode, BIOC_WRITESECT, (unsigned long)
                                   &readwrite);

      /* Print the logical sector number */

      printf("\r%d    ", sectors[x]);
    }

  printf("\nDone\n");

  /* Free all the allocated sectors */

  for (x = 0; x < fmt.nsectors >> 1; x++)
    {
      /* Only free the sector if it is still valid */

      if (sectors[x] != 0xFFFF)
        {
          ret = inode->u.i_bops->ioctl(inode, BIOC_FREESECT, (unsigned long)
                                       sectors[x]);
        }
    }

errout_with_buffers:
  /* Free the allocated buffers */

  (void) free(seqs);
  (void) free(sectors);
  (void) free(buffer);

errout_with_driver:
  /* Now close the block device and exit */

  (void)close_blockdriver(inode);

errout:

  return 0;
}
Пример #4
0
int bchlib_setup(const char *blkdev, bool readonly, FAR void **handle)
{
  FAR struct bchlib_s *bch;
  struct geometry geo;
  int ret;

  DEBUGASSERT(blkdev);

  /* Allocate the BCH state structure */

  bch = (FAR struct bchlib_s *)kmm_zalloc(sizeof(struct bchlib_s));
  if (!bch)
    {
      fdbg("Failed to allocate BCH structure\n");
      return -ENOMEM;
    }

  /* Open the block driver */

  ret = open_blockdriver(blkdev, readonly ? MS_RDONLY : 0, &bch->inode);
  if (ret < 0)
    {
      fdbg("Failed to open driver %s: %d\n", blkdev, -ret);
      goto errout_with_bch;
    }

  DEBUGASSERT(bch->inode && bch->inode->u.i_bops && bch->inode->u.i_bops->geometry);

  ret = bch->inode->u.i_bops->geometry(bch->inode, &geo);
  if (ret < 0)
    {
      fdbg("geometry failed: %d\n", -ret);
      goto errout_with_bch;
    }

  if (!geo.geo_available)
    {
      fdbg("geometry failed: %d\n", -ret);
      ret = -ENODEV;
      goto errout_with_bch;
    }

  if (!readonly && (!bch->inode->u.i_bops->write || !geo.geo_writeenabled))
    {
      fdbg("write access not supported\n");
      ret = -EACCES;
      goto errout_with_bch;
    }

  /* Save the geometry info and complete initialization of the structure */

  sem_init(&bch->sem, 0, 1);
  bch->nsectors = geo.geo_nsectors;
  bch->sectsize = geo.geo_sectorsize;
  bch->sector   = (size_t)-1;
  bch->readonly = readonly;

  /* Allocate the sector I/O buffer */

  bch->buffer = (FAR uint8_t *)kmm_malloc(bch->sectsize);
  if (!bch->buffer)
    {
      fdbg("Failed to allocate sector buffer\n");
      ret = -ENOMEM;
      goto errout_with_bch;
    }

  *handle = bch;
  return OK;

errout_with_bch:
  kmm_free(bch);
  return ret;
}
Пример #5
0
int usbmsc_bindlun(FAR void *handle, FAR const char *drvrpath, unsigned int lunno, off_t startsector, size_t nsectors, bool readonly)
{
	FAR struct usbmsc_alloc_s *alloc = (FAR struct usbmsc_alloc_s *)handle;
	FAR struct usbmsc_dev_s *priv;
	FAR struct usbmsc_lun_s *lun;
	FAR struct inode *inode;
	struct geometry geo;
	int ret;

#ifdef CONFIG_DEBUG
	if (!alloc || !drvrpath || startsector < 0) {
		usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_BINLUNINVALIDARGS1), 0);
		return -EINVAL;
	}
#endif

	priv = &alloc->dev;

#ifdef CONFIG_DEBUG
	if (!priv->luntab) {
		usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_INTERNALCONFUSION1), 0);
		return -EIO;
	}

	if (lunno > priv->nluns) {
		usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_BINDLUNINVALIDARGS2), 0);
		return -EINVAL;
	}
#endif

	lun = &priv->luntab[lunno];

#ifdef CONFIG_DEBUG
	if (lun->inode != NULL) {
		usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_LUNALREADYBOUND), 0);
		return -EBUSY;
	}
#endif

	/* Open the block driver */

	ret = open_blockdriver(drvrpath, 0, &inode);
	if (ret < 0) {
		usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_BLKDRVEOPEN), 0);
		return ret;
	}

	/* Get the drive geometry */

	if (!inode || !inode->u.i_bops || !inode->u.i_bops->geometry || inode->u.i_bops->geometry(inode, &geo) != OK || !geo.geo_available) {
		usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_NOGEOMETRY), 0);
		return -ENODEV;
	}

	/* Verify that the partition parameters are valid */

	if (startsector >= geo.geo_nsectors) {
		usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_BINDLUNINVALIDARGS3), 0);
		return -EDOM;
	} else if (nsectors == 0) {
		nsectors = geo.geo_nsectors - startsector;
	} else if (startsector + nsectors >= geo.geo_nsectors) {
		usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_BINDLUNINVALIDARGS4), 0);
		return -EDOM;
	}

	/* Initialize the LUN structure */

	memset(lun, 0, sizeof(struct usbmsc_lun_s *));

	/* Allocate an I/O buffer big enough to hold one hardware sector.  SCSI commands
	 * are processed one at a time so all LUNs may share a single I/O buffer.  The
	 * I/O buffer will be allocated so that is it as large as the largest block
	 * device sector size
	 */

	if (!priv->iobuffer) {
		priv->iobuffer = (FAR uint8_t *)kmm_malloc(geo.geo_sectorsize);
		if (!priv->iobuffer) {
			usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_ALLOCIOBUFFER), geo.geo_sectorsize);
			return -ENOMEM;
		}

		priv->iosize = geo.geo_sectorsize;
	} else if (priv->iosize < geo.geo_sectorsize) {
		void *tmp;
		tmp = (FAR uint8_t *)kmm_realloc(priv->iobuffer, geo.geo_sectorsize);
		if (!tmp) {
			usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_REALLOCIOBUFFER), geo.geo_sectorsize);
			return -ENOMEM;
		}

		priv->iobuffer = (FAR uint8_t *)tmp;
		priv->iosize = geo.geo_sectorsize;
	}

	lun->inode = inode;
	lun->startsector = startsector;
	lun->nsectors = nsectors;
	lun->sectorsize = geo.geo_sectorsize;

	/* If the driver does not support the write method, then this is read-only */

	if (!inode->u.i_bops->write) {
		lun->readonly = true;
	}

	return OK;
}
int mksmartfs(FAR const char *pathname)
#endif
{
  struct inode* inode;
  struct smart_format_s fmt;
  int ret;
  int x;
  uint8_t type; 
  struct smart_read_write_s request;

  /* Find the inode of the block driver indentified by 'source' */

  ret = open_blockdriver(pathname, 0, &inode);
  if (ret < 0)
    {
      fdbg("Failed to open %s\n", pathname);
      goto errout;
    }

  /* Make sure that the inode supports the write and geometry methods at a minimum */

  if (!inode->u.i_bops->write || !inode->u.i_bops->geometry)
    {
      fdbg("%s does not support write or geometry methods\n", pathname);
      ret = -EACCES;
      goto errout_with_driver;
    }

  /* Validate the block device is a SMART device */

  /* Perform a low-level SMART format */

#ifdef CONFIG_SMARTFS_MULTI_ROOT_DIRS
  ret = inode->u.i_bops->ioctl(inode, BIOC_LLFORMAT, nrootdirs);
#else
  ret = inode->u.i_bops->ioctl(inode, BIOC_LLFORMAT, 0);
#endif
  if (ret != OK)
    {
      fdbg("Error creating low-level format: %d\n", ret);
      goto errout_with_driver;
    }

  /* Get the format information so we know how big the sectors are */

  ret = inode->u.i_bops->ioctl(inode, BIOC_GETFORMAT, (unsigned long) &fmt);

  /* Now Write the filesystem to media.  Loop for each root dir entry and
   * allocate the reserved Root Dir Enty, then write a blank root dir for it.
   */

  type = SMARTFS_SECTOR_TYPE_DIR;
  request.offset = 0;
  request.count = 1;
  request.buffer = &type;
  x = 0;
#ifdef CONFIG_SMARTFS_MULTI_ROOT_DIRS
  for (; x < nrootdirs; x++)
#endif
    {
      ret = inode->u.i_bops->ioctl(inode, BIOC_ALLOCSECT, SMARTFS_ROOT_DIR_SECTOR + x);
      if (ret != SMARTFS_ROOT_DIR_SECTOR + x)
        {
          ret = -EIO;
          goto errout_with_driver;
        }

      /* Mark this block as a directory entry */

      request.logsector = SMARTFS_ROOT_DIR_SECTOR + x;

      /* Issue a write to the sector, single byte */

      ret = inode->u.i_bops->ioctl(inode, BIOC_WRITESECT, (unsigned long) &request);
      if (ret != 0)
        {
          ret = -EIO;
          goto errout_with_driver;
        }
    }

errout_with_driver:
  /* Close the driver */

  (void)close_blockdriver(inode);

errout:
  /* Release all allocated memory */

  /* Return any reported errors */

  if (ret < 0)
    {
      errno = -ret;
      return ERROR; 
    }

  return OK;
}
Пример #7
0
/****************************************************************************
 * Name: mkfatfs
 *
 * Description:
 *   Make a FAT file system image on the specified block device
 *
 * Inputs:
 *   pathname - the full path to a registered block driver
 *   fmt - Describes characteristics of the desired filesystem
 *
 * Return:
 *   Zero (OK) on success; -1 (ERROR) on failure with errno set appropriately:
 *
 *   EINVAL  - NULL block driver string, bad number of FATS in 'fmt', bad FAT
 *     size in 'fmt', bad cluster size in 'fmt'
 *   ENOENT  - 'pathname' does not refer to anything in the filesystem.
 *   ENOTBLK - 'pathname' does not refer to a block driver
 *   EACCES  - block driver does not support wrie or geometry methods
 *
 * Assumptions:
 *   - The caller must assure that the block driver is not mounted and not in
 *     use when this function is called.  The result of formatting a mounted
 *     device is indeterminate (but likely not good).
 *
 ****************************************************************************/
int mkfatfs(FAR const char *pathname, FAR struct fat_format_s *fmt)
{
  struct fat_var_s var;
  int ret;

  /* Initialize */

  memset(&var, 0, sizeof(struct fat_var_s));

  /* Get the filesystem creation time */

  var.fv_createtime = fat_systime2fattime();

  /* Verify format options (only when DEBUG enabled) */

#ifdef CONFIG_DEBUG
  if (!pathname)
    {
      fdbg("No block driver path\n");
      ret = -EINVAL;
      goto errout;
    }

  if (fmt->ff_nfats < 1 || fmt->ff_nfats > 4)
    {
      fdbg("Invalid number of fats: %d\n", fmt->ff_nfats);
      ret = -EINVAL;
      goto errout;
    }

  if (fmt->ff_fattype != 0  && fmt->ff_fattype != 12 &&
      fmt->ff_fattype != 16 && fmt->ff_fattype != 32)
    {
      fdbg("Invalid FAT size: %d\n", fmt->ff_fattype);
      ret = -EINVAL;
      goto errout;
    }
#endif
  var.fv_fattype = fmt->ff_fattype;

  /* The valid range off ff_clustshift is {0,1,..7} corresponding to
   * cluster sizes of {1,2,..128} sectors.  The special value of 0xff
   * means that we should autoselect the cluster sizel.
   */
#ifdef CONFIG_DEBUG
  if (fmt->ff_clustshift > 7 && fmt->ff_clustshift != 0xff)
    {
      fdbg("Invalid cluster shift value: %d\n", fmt->ff_clustshift);
      ret = -EINVAL;
      goto errout;
    }

   if (fmt->ff_rootdirentries != 0 && (fmt->ff_rootdirentries < 16 || fmt->ff_rootdirentries > 32767))
    {
      fdbg("Invalid number of root dir entries: %d\n", fmt->ff_rootdirentries);
      ret = -EINVAL;
      goto errout;
    }

   if (fmt->ff_rsvdseccount != 0 && (fmt->ff_rsvdseccount < 1 || fmt->ff_rsvdseccount > 32767))
    {
      fdbg("Invalid number of reserved sectors: %d\n", fmt->ff_rsvdseccount);
      ret = -EINVAL;
      goto errout;
    }
#endif

  /* Find the inode of the block driver indentified by 'source' */

  ret = open_blockdriver(pathname, 0, &var.fv_inode);
  if (ret < 0)
    {
      fdbg("Failed to open %s\n", pathname);
      goto errout;
    }

  /* Make sure that the inode supports the write and geometry methods at a minimum */

  if (!var.fv_inode->u.i_bops->write || !var.fv_inode->u.i_bops->geometry)
    {
      fdbg("%s does not support write or geometry methods\n", pathname);
      ret = -EACCES;
      goto errout_with_driver;
    }

  /* Determine the volume configuration based upon the input values and upon the
   * reported device geometry.
   */

  ret = mkfatfs_getgeometry(fmt, &var);
  if (ret < 0)
    {
      goto errout_with_driver;
    }

  /* Configure the file system */

  ret = mkfatfs_configfatfs(fmt, &var);
  if (ret < 0)
    {
      goto errout_with_driver;
    }

  /* Allocate a buffer that will be working sector memory */

  var.fv_sect = (uint8_t*)malloc(var.fv_sectorsize);
  if (!var.fv_sect)
    {
      fdbg("Failed to allocate working buffers\n");
      goto errout_with_driver;
    }

  /* Write the filesystem to media */

  ret = mkfatfs_writefatfs(fmt, &var);

errout_with_driver:
  /* Close the driver */

  (void)close_blockdriver(var.fv_inode);

errout:
  /* Release all allocated memory */

  if (var.fv_sect)
    {
      free(var.fv_sect);
    }

    /* Return any reported errors */

    if (ret < 0)
      {
        errno = -ret;
        return ERROR; 
      }
    return OK;
}