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; }
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; }
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; }
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; }
/**************************************************************************** * 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; }