/* * 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 ); }
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); }
/*=========================================================================*\ | 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, §ors_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; }