Ejemplo n.º 1
0
/*
 * Black box test the disk parameters of a sparse disk
 */
static void test_disk_params(
  const int               file_descriptor,
  const uint32_t          block_size,
  const uint32_t          media_block_size,
  const rtems_blkdev_bnum block_number )
{
  int                rv;
  uint32_t           value       = 0;
  rtems_disk_device *fd_dd       = NULL;
  rtems_blkdev_bnum  block_count = 0;


  rv = rtems_disk_fd_get_media_block_size( file_descriptor, &value );
  rtems_test_assert( 0 == rv );
  rtems_test_assert( media_block_size == value );

  value = 0;
  rv    = rtems_disk_fd_get_block_size( file_descriptor, &value );
  rtems_test_assert( 0 == rv );
  rtems_test_assert( block_size == value );

  block_count = 0;
  rv          = rtems_disk_fd_get_block_count( file_descriptor, &block_count );
  rtems_test_assert( 0 == rv );
  rtems_test_assert( block_number == block_count );

  rv = rtems_disk_fd_get_disk_device( file_descriptor, &fd_dd );
  rtems_test_assert( 0 == rv );
  rtems_test_assert( NULL != fd_dd );
}
Ejemplo n.º 2
0
static void test_block_io_control_api(dev_t dev, ramdisk *rd)
{
    rtems_status_code sc = RTEMS_SUCCESSFUL;
    rtems_disk_device *dd = NULL;
    const rtems_disk_device *fd_dd = NULL;
    int fd = -1;
    int rv = -1;
    uint32_t value = 0;
    rtems_blkdev_bnum block_count = 0;

    sc = rtems_disk_create_phys(dev, BLOCK_SIZE, BLOCK_COUNT, ramdisk_ioctl, rd, "/dev/rda");
    ASSERT_SC(sc);

    dd = rtems_disk_obtain(dev);
    rtems_test_assert(dd != NULL);

    fd = open("/dev/rda", O_RDWR);
    rtems_test_assert(fd >= 0);

    value = 0;
    rv = rtems_disk_fd_get_media_block_size(fd, &value);
    rtems_test_assert(rv == 0);
    rtems_test_assert(value == BLOCK_SIZE);

    value = 0;
    rv = rtems_disk_fd_get_block_size(fd, &value);
    rtems_test_assert(rv == 0);
    rtems_test_assert(value == BLOCK_SIZE);

    value = 1024;
    rv = rtems_disk_fd_set_block_size(fd, value);
    rtems_test_assert(rv == 0);

    value = 0;
    rv = rtems_disk_fd_get_block_size(fd, &value);
    rtems_test_assert(rv == 0);
    rtems_test_assert(value == 1024);

    block_count = 0;
    rv = rtems_disk_fd_get_block_count(fd, &block_count);
    rtems_test_assert(rv == 0);
    rtems_test_assert(block_count == BLOCK_COUNT);

    rv = rtems_disk_fd_get_disk_device(fd, &fd_dd);
    rtems_test_assert(rv == 0);
    rtems_test_assert(fd_dd == dd);

    rv = rtems_disk_fd_sync(fd);
    rtems_test_assert(rv == 0);

    rv = close(fd);
    rtems_test_assert(rv == 0);

    sc = rtems_disk_release(dd);
    ASSERT_SC(sc);

    sc = rtems_disk_delete(dev);
    ASSERT_SC(sc);
}
Ejemplo n.º 3
0
/*=========================================================================*\
| Function:                                                                 |
\*-------------------------------------------------------------------------*/
static int msdos_format_determine_fmt_params
(
/*-------------------------------------------------------------------------*\
| Purpose:                                                                  |
|     determine parameters for formatting                                   |
+---------------------------------------------------------------------------+
| Input Parameters:                                                         |
\*-------------------------------------------------------------------------*/
 int fd,                                       /* disk file descriptor */
 const msdos_format_request_param_t *rqdata,   /* requested fmt parameters */
 msdos_format_param_t               *fmt_params/* computed fmt parameters        */
 )
/*-------------------------------------------------------------------------*\
| Return Value:                                                             |
|    0, if success, -1 and errno if failed                                  |
\*=========================================================================*/
{
  int ret_val = 0;
  uint32_t sectors_per_cluster_adj = 0;
  uint64_t total_size = 0;
  uint32_t data_clusters_cnt;
  uint8_t  iteration_cnt = 0;
  uint8_t  fat_type = UINT8_MAX;

  memset(fmt_params,0,sizeof(*fmt_params));

  /*
   * this one is fixed in this implementation.
   * At least one thing we don't have to magically guess...
   */
  if (ret_val == 0) {
    ret_val = rtems_disk_fd_get_media_block_size(fd, &fmt_params->bytes_per_sector);
  }
  if (ret_val == 0) {
    ret_val = rtems_disk_fd_get_block_count(fd, &fmt_params->totl_sector_cnt);
  }
  if (ret_val == 0) {
    total_size = (uint64_t)fmt_params->bytes_per_sector * fmt_params->totl_sector_cnt;
    msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
                         "bytes per sector: %" PRIu32 "\ntotal sectors: %" PRIu32 "\ntotal size: %" PRIu64 "\n",
                         fmt_params->bytes_per_sector, fmt_params->totl_sector_cnt, total_size);
  }

  /*
   * determine number of FATs
   */
  if (ret_val == 0) {
    if ((rqdata == NULL) || (rqdata->fat_num == 0)) {
      fmt_params->fat_num = 2;
    }
    else if (rqdata->fat_num <= 6) {
      fmt_params->fat_num = rqdata->fat_num;
    }
    else {
      errno = EINVAL;
      ret_val = -1;
    }
  }

  if (ret_val == 0)
    msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
                         "number of fats: %d\n", fmt_params->fat_num);

  /*
   * Now we get sort of a loop when determining things:
   * The FAT type (FAT12/16/32) is determined ONLY from the
   * data cluster count:
   * Disks with data cluster count <  4085 are FAT12.
   * Disks with data cluster count < 65525 are FAT16.
   * The rest is FAT32 (no FAT128 available yet :-)
   *
   * The number of data clusters is the
   * total capacity
   * minus reserved sectors
   * minus root directory ares
   * minus storage needed for the FAT (and its copy/copies).
   *
   * The last item once again depends on the FAT type and the cluster count.
   *
   * So here is what we do in this formatter:
   * - If a FAT type is requested from the caller, we try to modify
   * the cluster size, until the data cluster count is in range
   * - If no FAT type is given, we estimate a useful FAT type from
   * the disk capacity and then adapt the cluster size
   */

  /*
   * determine characteristic values:
   * - number of sectors
   * - number of reserved sectors
   * - number of used sectors
   * - sectors per cluster
   */
  /*
   * determine FAT type and sectors per cluster
   * depends on
   */
  if (ret_val == 0) {
    fmt_params->sectors_per_cluster = 1;
    /*
     * limiting values for disk size, fat type, sectors per cluster
     * NOTE: maximum sect_per_clust is arbitrarily choosen with values that
     * are a compromise concerning capacity and efficency
     */
    uint32_t fat12_sect_per_clust = 8;
    uint32_t fat16_sect_per_clust = 32;

    if (rqdata != NULL && rqdata->sectors_per_cluster != 0) {
      fat12_sect_per_clust = rqdata->sectors_per_cluster;
      fat16_sect_per_clust = rqdata->sectors_per_cluster;
    }

    if (fmt_params->totl_sector_cnt < FAT_FAT12_MAX_CLN * fat12_sect_per_clust) {
      fmt_params->fattype = FAT_FAT12;
      /* start trying with small clusters */
      fmt_params->sectors_per_cluster = 2;
    }
    else if (fmt_params->totl_sector_cnt < FAT_FAT16_MAX_CLN * fat16_sect_per_clust) {
      fmt_params->fattype = FAT_FAT16;
      /* start trying with small clusters */
      fmt_params->sectors_per_cluster = 2;
    }
    else {
      uint32_t gigs = (total_size + ONE_GB) / ONE_GB;
      int b;
      fmt_params->fattype = FAT_FAT32;
      /* scale with the size of disk... */
      for (b = 31; b > 0; b--)
        if ((gigs & (1 << b)) != 0)
          break;
      fmt_params->sectors_per_cluster = 1 << b;
    }

    ret_val = msdos_set_sectors_per_cluster_from_request( rqdata, fmt_params );

    /* For now we will estimate the number of data clusters to the total number
     *  of clusters */
    if (ret_val == 0) {
      data_clusters_cnt =
        fmt_params->totl_sector_cnt / fmt_params->sectors_per_cluster;
    }

    while(   ret_val == 0
          && fmt_params->fattype != fat_type
          && fmt_params->totl_sector_cnt > 0 ) {
      /*
       * Skip aligning structures or d align them
       */
      if (ret_val == 0 && rqdata != NULL)
        fmt_params->skip_alignment = rqdata->skip_alignment;

      if (ret_val == 0) {
        msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
                             "sectors per cluster: %d\n", fmt_params->sectors_per_cluster);

        if (fmt_params->fattype == FAT_FAT32) {
          /* recommended: for FAT32, always set reserved sector count to 32 */
          fmt_params->rsvd_sector_cnt = 32;
          /* for FAT32, always set files per root directory 0 */
          fmt_params->files_per_root_dir = 0;
          /* location of copy of MBR */
          fmt_params->mbr_copy_sec = 6;
          /* location of fsinfo sector */
          fmt_params->fsinfo_sec = 1;

        }
        else {
          /* recommended: for FAT12/FAT16, always set reserved sector count to 1 */
          fmt_params->rsvd_sector_cnt = 1;
          /* recommended: for FAT16, set files per root directory to 512 */
          /* for FAT12/FAT16, set files per root directory */
          /* must fill up an even count of sectors         */
          if ((rqdata != NULL) &&
              (rqdata->files_per_root_dir > 0)) {
            fmt_params->files_per_root_dir = rqdata->files_per_root_dir;
          }
          else {
            if (fmt_params->fattype == FAT_FAT16) {
              fmt_params->files_per_root_dir = 512;
            }
            else {
              fmt_params->files_per_root_dir = 64;
            }
          }
          fmt_params->files_per_root_dir = (fmt_params->files_per_root_dir +
                                           (2*fmt_params->bytes_per_sector/
                                           FAT_DIRENTRY_SIZE-1));
          fmt_params->files_per_root_dir -= (fmt_params->files_per_root_dir %
                                            (2*fmt_params->bytes_per_sector
                                            /FAT_DIRENTRY_SIZE));

        }
        fmt_params->root_dir_sectors =
          (((fmt_params->files_per_root_dir * FAT_DIRENTRY_SIZE)
            + fmt_params->bytes_per_sector - 1)
           / fmt_params->bytes_per_sector);
      }
      if (ret_val == 0) {
        /*
         * check values to get legal arrangement of FAT type and cluster count
         */

        ret_val = msdos_format_eval_sectors_per_cluster(fmt_params->fattype,
                     fmt_params->bytes_per_sector,
                     fmt_params->totl_sector_cnt,
                     fmt_params->rsvd_sector_cnt,
                     fmt_params->root_dir_sectors,
                     fmt_params->fat_num,
                     fmt_params->sectors_per_cluster,
                     fmt_params->skip_alignment,
                     &sectors_per_cluster_adj,
                     &fmt_params->sectors_per_fat,
                     &data_clusters_cnt);
        fmt_params->sectors_per_cluster = sectors_per_cluster_adj;
        fat_type = fmt_params->fattype;

        /* Correct the FAT type according to the new data cluster count */
        if ( ret_val == 0 ) {
          fmt_params->fattype = msdos_get_fat_type(
            fmt_params->bytes_per_sector,
            fmt_params->sectors_per_cluster,
            data_clusters_cnt );
          /* Correct sectors per cluster to the fat type specific default value */
          if (fat_type != fmt_params->fattype) {
            msdos_set_default_sectors_per_cluster_for_fattype( fmt_params,
                                                               total_size );
            ret_val = msdos_set_sectors_per_cluster_from_request( rqdata,
                                                                  fmt_params );
          }
        }
        if (fat_type != fmt_params->fattype && 1 < iteration_cnt) {
          --fmt_params->totl_sector_cnt;
        }

      }

      ++iteration_cnt;
    }
  }
  if ( fmt_params->totl_sector_cnt == 0 )
  {
    errno = EINVAL;
    ret_val = -1;
  }

  if (0 == ret_val)
  {
    if (FAT_FAT32 != fmt_params->fattype)
    {
      fmt_params->files_per_root_dir = loc_align_object (fmt_params->root_dir_sectors,
                                                         fmt_params->sectors_per_cluster,
                                                         fmt_params->skip_alignment)
                                       * (fmt_params->bytes_per_sector / FAT_DIRENTRY_SIZE);
    }

    fmt_params->rsvd_sector_cnt = loc_align_object (fmt_params->rsvd_sector_cnt,
                                                    fmt_params->sectors_per_cluster,
                                                    fmt_params->skip_alignment);
  }

  /*
   * determine media code
   */
  if (ret_val == 0) {
    if ((rqdata != NULL) && (rqdata->media != 0)) {
      const char valid_media_codes[] =
        {0xF0,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF};
      if (NULL==memchr(valid_media_codes,
                       rqdata->media,
                       sizeof(valid_media_codes))) {
        ret_val = -1;
        errno = EINVAL;
      }
      else {
        fmt_params->media_code = rqdata->media;
      }
    }
    else {
      fmt_params->media_code = FAT_BR_MEDIA_FIXED;
    }
  }
  /*
   * determine location and size of root directory
   * for formatting
   */
  if (fmt_params->root_dir_sectors > 0) {
    fmt_params->root_dir_start_sec =
      fmt_params->rsvd_sector_cnt
      + (fmt_params-> fat_num*fmt_params->sectors_per_fat);
    fmt_params->root_dir_fmt_sec_cnt = fmt_params->root_dir_sectors;
  }
  else {
    /*
     * for FAT32: root directory is in cluster 2
     */
    fmt_params->root_dir_start_sec =
      fmt_params->rsvd_sector_cnt
      + (fmt_params-> fat_num*fmt_params->sectors_per_fat);
    fmt_params->root_dir_fmt_sec_cnt = fmt_params->sectors_per_cluster;
  }
  /*
   * determine usable OEMName
   */
  if (ret_val == 0) {
      const char *from;
      char        *to = fmt_params->OEMName;
      int          cnt;
      from = "RTEMS"; /* default: make "from" point to OS Name */
    if ((rqdata != NULL) && (rqdata->OEMName != NULL)) {
      from = rqdata->OEMName;
    }
    for (cnt = 0; cnt < (sizeof(fmt_params->OEMName)-1); cnt++) {
      if (isprint((unsigned char)*from)) {
        *to++ = *from++;
      }
      else {
        /*
         * non-printable character in given name, so keep stuck
         * at that character and replace all following characters
         * with a ' '
         */
        *to++=' ';
      }
      *to = '\0';
    }
  }

  /*
   * determine usable Volume Label
   */
  if (ret_val == 0) {
      const char *from;
      char        *to = fmt_params->VolLabel;
      int          cnt;
      from = ""; /* default: make "from" point to empty string */
    if ((rqdata != NULL) &&
        (rqdata->VolLabel != NULL)) {
      from = rqdata->VolLabel;
      fmt_params->VolLabel_present = true;
    }
    for (cnt = 0; cnt < (sizeof(fmt_params->VolLabel)-1); cnt++) {
      if (isprint((unsigned char)*from)) {
        *to++ = *from++;
      }
      else {
        /*
         * non-printable character in given name, so keep stuck
         * at that character and replace all following characters
         * with a ' '
         */
        *to++=' ';
      }
      *to = '\0';
    }
  }

  /*
   * determine usable Volume ID
   */
  if (ret_val == 0) {
    msdos_format_gen_volid(&(fmt_params->vol_id));
  }
  /*
   * Phuuu.... That's it.
   */
  return ret_val;
}