[PATCH rtems6 - v1 10/16] Flashdev: Refactoring, replace region with partition jargon and allow IOTCLs to return a value

berndmoessner80 at gmail.com berndmoessner80 at gmail.com
Thu Jan 4 18:34:34 UTC 2024


From: Bernd Moessner <berndmoessner80 at gmail.com>

---
 cpukit/dev/flash/flashdev.c                   | 1051 +++++++++--------
 cpukit/include/dev/flash/flashdev.h           |  250 ++--
 cpukit/libmisc/shell/main_flashdev.c          |    2 +-
 testsuites/libtests/flashdev01/init.c         |   97 +-
 .../libtests/flashdev01/test_flashdev.c       |   16 +-
 5 files changed, 794 insertions(+), 622 deletions(-)

diff --git a/cpukit/dev/flash/flashdev.c b/cpukit/dev/flash/flashdev.c
index 363d12e3ff..de6556c19a 100644
--- a/cpukit/dev/flash/flashdev.c
+++ b/cpukit/dev/flash/flashdev.c
@@ -40,25 +40,25 @@
 #include <unistd.h>
 #include <assert.h>
 
-#define RTEMS_FLASHDEV_REGION_ALLOC_FULL 0xFFFFFFFFUL
-#define RTEMS_FLASHDEV_REGION_UNDEFINED 0xFFFFFFFFUL
-#define RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH 32
+#define RTEMS_FLASHDEV_MAX_PARTITIONS 16
+#define RTEMS_FLASHDEV_PARTITION_ALLOC_FULL 0xFFFFFFFFUL
+#define RTEMS_FLASHDEV_PARTITION_UNDEFINED 0xFFFFFFFFUL
 
-#define RTEMS_FLASHDEV_BITALLOC_LENGTH(t) \
-  (t->max_regions/RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH)
-#define RTEMS_FLASHDEV_BITALLOC_FINAL_BITS(t) \
-  (t->max_regions%RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH)
 
-static int rtems_flashdev_do_init(
-  rtems_flashdev *flash,
-  void ( *destroy )( rtems_flashdev *flash )
-);
+static inline uint32_t set_bit(uint32_t in, uint32_t bit_idx)
+{
+  return in | ( 1 << bit_idx );
+}
 
-static int rtems_flashdev_read_write(
-  rtems_libio_t *iop,
-  const void *write_buff,
-  void *read_buff,
-  size_t count
+static inline uint32_t clear_bit(uint32_t in, uint32_t bit_idx)
+{
+  return in & ~( 1 << (bit_idx) );
+}
+
+
+/* IOCTL Functions*/
+static uint32_t rtems_flashdev_ioctl_get_jedec_id(
+  rtems_flashdev *flash
 );
 
 static int rtems_flashdev_ioctl_erase(
@@ -67,41 +67,34 @@ static int rtems_flashdev_ioctl_erase(
   void *arg
 );
 
-static off_t rtems_flashdev_get_region_offset(
-  rtems_flashdev *flash,
-  rtems_libio_t *iop
-);
-
-static size_t rtems_flashdev_get_region_size(
+static int rtems_flashdev_ioctl_create_partition(
   rtems_flashdev *flash,
-  rtems_libio_t *iop
+  rtems_libio_t *iop,
+  void *arg
 );
 
-static int rtems_flashdev_ioctl_set_region(
+static int rtems_flashdev_ioctl_delete_partition(
   rtems_flashdev *flash,
   rtems_libio_t *iop,
   void *arg
 );
 
-static int rtems_flashdev_ioctl_create_region(
+static int rtems_flashdev_ioctl_resize_partition(
   rtems_flashdev *flash,
   rtems_libio_t *iop,
-  rtems_flashdev_region *region_in
+  void *arg
 );
 
-static int rtems_flashdev_ioctl_update_region(
+static int rtems_flashdev_ioctl_activate_partition(
   rtems_flashdev *flash,
   rtems_libio_t *iop,
-  rtems_flashdev_region *region_in
+  void *arg
 );
 
-static int rtems_flashdev_ioctl_clear_region(
+static int rtems_flashdev_ioctl_deactivate_partition(
   rtems_flashdev *flash,
-  rtems_libio_t *iop
-);
-
-static uint32_t rtems_flashdev_ioctl_get_jedec_id(
-  rtems_flashdev *flash
+  rtems_libio_t *iop,
+  void *arg
 );
 
 static uint32_t rtems_flashdev_ioctl_get_flash_type(
@@ -109,12 +102,12 @@ static uint32_t rtems_flashdev_ioctl_get_flash_type(
   void *arg
 );
 
-static int rtems_flashdev_ioctl_get_pageinfo_offset(
+static int rtems_flashdev_ioctl_get_pageinfo_by_offset(
   rtems_flashdev *flash,
   void *arg
 );
 
-static int rtems_flashdev_ioctl_get_pageinfo_index(
+static int rtems_flashdev_ioctl_get_pageinfo_by_index(
   rtems_flashdev *flash,
   void *arg
 );
@@ -134,6 +127,49 @@ static int rtems_flashdev_ioctl_get_erase_size(
   void *arg
 );
 
+
+static int rtems_flashdev_do_init(
+  rtems_flashdev *flash,
+  void ( *destroy )( rtems_flashdev *flash )
+);
+
+static int rtems_flashdev_read_write(
+  rtems_libio_t *iop,
+  const void *write_buff,
+  void *read_buff,
+  size_t count
+);
+
+static ssize_t rtems_flashdev_read(
+  rtems_libio_t *iop,
+  void *buffer,
+  size_t count
+);
+
+static ssize_t rtems_flashdev_write(
+  rtems_libio_t *iop,
+  const void *buffer,
+  size_t count
+);
+
+static off_t rtems_flashdev_get_partition_offset(
+  rtems_flashdev *flash,
+  rtems_libio_t *iop
+);
+
+static size_t rtems_flashdev_get_partition_size(
+  rtems_flashdev *flash,
+  rtems_libio_t *iop
+);
+
+static int rtems_flashdev_create_partition(
+  rtems_libio_t *iop,
+  rtems_flashdev_partition *partition_table,
+  uint32_t partition_idx,
+  rtems_flashdev_partition *region_in
+);
+
+
 static int rtems_flashdev_get_addr(
   rtems_flashdev *flash,
   rtems_libio_t *iop,
@@ -154,28 +190,13 @@ static int rtems_flashdev_update_and_return(
   size_t count
 );
 
-static int rtems_flashdev_check_region_valid(
+static int rtems_flashdev_check_partition_valid(
   rtems_flashdev *flash,
-  rtems_flashdev_region * region
-);
-
-static uint32_t rtems_flashdev_find_unallocated_region(
-  rtems_flashdev_region_table *region_table
+  rtems_flashdev_partition * region
 );
 
-static uint32_t rtems_flashdev_set_region(
-  rtems_flashdev_region_table *region_table,
-  int index
-);
-
-static uint32_t rtems_flashdev_unset_region(
-  rtems_flashdev_region_table *region_table,
-  int index
-);
-
-static uint32_t rtems_flashdev_check_allocation(
-  rtems_flashdev_region_table *region_table,
-  int index
+static uint32_t rtems_flashdev_find_unallocated_partition(
+  rtems_libio_t *iop
 );
 
 static int rtems_flashdev_open(
@@ -189,18 +210,6 @@ static int rtems_flashdev_close(
   rtems_libio_t *iop
 );
 
-static ssize_t rtems_flashdev_read(
-  rtems_libio_t *iop,
-  void *buffer,
-  size_t count
-);
-
-static ssize_t rtems_flashdev_write(
-  rtems_libio_t *iop,
-  const void *buffer,
-  size_t count
-);
-
 static int rtems_flashdev_ioctl(
   rtems_libio_t *iop,
   ioctl_command_t command,
@@ -217,6 +226,59 @@ static void rtems_flashdev_node_destroy(
   IMFS_jnode_t *node
 );
 
+static uint32_t rtems_flashdev_get_defined_partitions(
+  rtems_libio_t *iop
+);
+
+static bool rtems_flashdev_is_a_partition_active(
+  rtems_libio_t *iop
+);
+
+static bool rtems_flashdev_is_partition_defined(
+  rtems_libio_t *iop,
+  uint32_t partition_idx
+);
+
+static int rtems_flashdev_activate_partition(
+  rtems_libio_t *iop,
+  uint32_t partition_idx
+);
+
+static int rtems_flashdev_deactivate_partition(
+  rtems_libio_t *iop,
+  uint32_t partition_idx
+);
+
+static void rtems_flashdev_mark_partition_defined(
+  rtems_libio_t *iop,
+  uint32_t partition_idx
+);
+
+static void rtems_flashdev_mark_partition_undefined(
+  rtems_libio_t *iop,
+  uint32_t partition_idx
+);
+
+static bool rtems_flashdev_check_partition_overlap(
+  rtems_libio_t *iop,
+  rtems_flashdev_partition *partition_table,
+  rtems_flashdev_partition *region_in
+);
+
+static int rtems_flashdev_check_partition_offset(
+  rtems_flashdev *flash,
+  rtems_libio_t *iop,
+  off_t offset
+);
+
+static uint32_t rtems_flashdev_get_active_partition_index(
+  rtems_libio_t *iop
+);
+
+static void rtems_flashdev_obtain( rtems_flashdev *flash );
+
+static void rtems_flashdev_release( rtems_flashdev *flash );
+
 static const rtems_filesystem_file_handlers_r rtems_flashdev_handler = {
   .open_h = rtems_flashdev_open,
   .close_h = rtems_flashdev_close,
@@ -234,97 +296,37 @@ static const rtems_filesystem_file_handlers_r rtems_flashdev_handler = {
   .poll_h = rtems_filesystem_default_poll,
   .readv_h = rtems_filesystem_default_readv,
   .writev_h = rtems_filesystem_default_writev };
-/*
+
 static const IMFS_node_control
   rtems_flashdev_node_control = IMFS_GENERIC_INITIALIZER(
     &rtems_flashdev_handler,
     IMFS_node_initialize_generic,
     rtems_flashdev_node_destroy
 );
-*/
-static const IMFS_node_control rtems_flashdev_node_control = {
-  .handlers = &rtems_flashdev_handler,
-  .node_initialize = IMFS_node_initialize_generic,
-  .node_remove = IMFS_node_remove_default,
-  .node_destroy = rtems_flashdev_node_destroy
-};
-
-static void rtems_flashdev_node_destroy(
-  IMFS_jnode_t *node
-)
-{
-  rtems_flashdev *flash;
 
-  flash = IMFS_generic_get_context_by_node( node );
-
-  ( *flash->destroy )( flash );
-
-  IMFS_node_destroy_default( node );
-}
-
-static uint32_t rtems_flashdev_get_region_index(
-  rtems_libio_t *iop
-)
-{
-  return (uint32_t)iop->data0;
-}
-
-static int rtems_flashdev_is_region_defined(
-  rtems_libio_t *iop
-)
-{
-  return (rtems_flashdev_get_region_index( iop ) != RTEMS_FLASHDEV_REGION_UNDEFINED);
-}
-
-static void rtems_flashdev_set_region_index(
-  rtems_libio_t *iop,
-  uint32_t index
-)
-{
-  iop->data0 = index;
-}
-
-static int rtems_flashdev_check_offset_region(
+static int rtems_flashdev_do_init(
   rtems_flashdev *flash,
-  rtems_libio_t *iop,
-  off_t offset
+  void ( *destroy )( rtems_flashdev *flash )
 )
 {
-  if ( ( rtems_flashdev_is_region_defined( iop ) ) &&
-       ( offset > rtems_flashdev_get_region_size( flash, iop ) ) ) {
-    rtems_set_errno_and_return_minus_one( EINVAL );
-  }
+  char mtx_name[19];
+  sprintf(mtx_name, "FDEV_MTX_%08x", (unsigned int) flash);
+  rtems_recursive_mutex_init( &flash->mutex, (const char*) &mtx_name);
+  flash->destroy = destroy;
+  flash->read = NULL;
+  flash->write = NULL;
+  flash->erase = NULL;
+  flash->get_jedec_id = NULL;
+  flash->get_flash_type = NULL;
+  flash->get_page_info_by_offset = NULL;
+  flash->get_page_info_by_index = NULL;
+  flash->get_page_count = NULL;
+  flash->get_min_write_size = NULL;
+  flash->get_erase_size = NULL;
+  flash->partition_table = NULL;
   return 0;
 }
 
-static void rtems_flashdev_obtain( rtems_flashdev *flash )
-{
-  rtems_recursive_mutex_lock( &flash->mutex );
-}
-
-static void rtems_flashdev_release( rtems_flashdev *flash )
-{
-  rtems_recursive_mutex_unlock( &flash->mutex );
-}
-
-static ssize_t rtems_flashdev_read(
-  rtems_libio_t *iop,
-  void *buffer,
-  size_t count
-)
-{
-  return rtems_flashdev_read_write( iop, NULL, buffer, count );
-}
-
-static ssize_t rtems_flashdev_write(
-  rtems_libio_t *iop,
-  const void *buffer,
-  size_t count
-)
-{
-  return rtems_flashdev_read_write( iop, buffer, NULL, count);
-}
-
 static int rtems_flashdev_read_write(
   rtems_libio_t *iop,
   const void *write_buff,
@@ -337,7 +339,7 @@ static int rtems_flashdev_read_write(
   int status;
 
   if ( read_buff == NULL && write_buff == NULL ) {
-    return EINVAL;
+    rtems_set_errno_and_return_minus_one( EINVAL );
   }
 
   /* Get flash address */
@@ -382,6 +384,183 @@ static int rtems_flashdev_read_write(
   return rtems_flashdev_update_and_return( iop, status, count );
 }
 
+static ssize_t rtems_flashdev_read(
+  rtems_libio_t *iop,
+  void *buffer,
+  size_t count
+)
+{
+  return rtems_flashdev_read_write( iop, NULL, buffer, count );
+}
+
+static ssize_t rtems_flashdev_write(
+  rtems_libio_t *iop,
+  const void *buffer,
+  size_t count
+)
+{
+  return rtems_flashdev_read_write( iop, buffer, NULL, count);
+}
+
+static off_t rtems_flashdev_get_partition_offset(
+  rtems_flashdev *flash,
+  rtems_libio_t *iop
+)
+{
+  /* Region is already checked to be defined */
+  assert( rtems_flashdev_get_active_partition_index( iop ) != RTEMS_FLASHDEV_PARTITION_UNDEFINED );
+  rtems_flashdev_partition *table = flash->partition_table;
+  return table[ rtems_flashdev_get_active_partition_index( iop ) ].offset;
+}
+
+static size_t rtems_flashdev_get_partition_size(
+  rtems_flashdev *flash,
+  rtems_libio_t *iop
+)
+{
+  /* Region is already checked to be defined */
+  assert( rtems_flashdev_get_active_partition_index( iop ) != RTEMS_FLASHDEV_PARTITION_UNDEFINED );
+  rtems_flashdev_partition *table = flash->partition_table;
+  return table[ rtems_flashdev_get_active_partition_index( iop ) ].size;
+}
+
+static int rtems_flashdev_get_addr(
+  rtems_flashdev *flash,
+  rtems_libio_t *iop,
+  size_t count,
+  off_t *addr
+)
+{
+  off_t new_offset;
+
+  /* Check address is in valid partition */
+  new_offset = iop->offset + count;
+
+  if (rtems_flashdev_check_partition_offset(flash, iop, new_offset)) {
+    return -1;
+  }
+
+  /* Get address for operation */
+  if ( !rtems_flashdev_is_a_partition_active( iop ) ) {
+    *addr = iop->offset;
+  } else {
+    *addr = ( iop->offset + rtems_flashdev_get_partition_offset( flash, iop ) );
+  }
+  return 0;
+}
+
+static int rtems_flashdev_get_abs_addr(
+  rtems_flashdev *flash,
+  rtems_libio_t *iop,
+  size_t count,
+  off_t *addr
+)
+{
+  off_t new_offset;
+
+  /* Check address is in valid partition */
+  new_offset = *addr + count;
+
+  if (rtems_flashdev_check_partition_offset(flash, iop, new_offset)) {
+    return -1;
+  }
+
+  /* Get address for operation */
+  if ( rtems_flashdev_is_a_partition_active( iop ) ) {
+    *addr = ( *addr + rtems_flashdev_get_partition_offset( flash, iop ) );
+  }
+  return 0;
+}
+
+static int rtems_flashdev_update_and_return(
+  rtems_libio_t *iop,
+  int status,
+  size_t count
+)
+{
+  /* Update offset and return */
+  if ( status == 0 ) {
+    iop->offset += count;
+    return count;
+  } else {
+    rtems_set_errno_and_return_minus_one( status );
+  }
+}
+
+static int rtems_flashdev_create_partition(
+  rtems_libio_t *iop,
+  rtems_flashdev_partition *partition_table,
+  uint32_t partition_idx,
+  rtems_flashdev_partition *partition_in
+)
+{
+  int i = 0x0000FFFF & partition_idx;
+
+  /* Set partitions values */
+  partition_table[ i ].offset = partition_in->offset;
+  partition_table[ i ].size = partition_in->size;
+
+  rtems_flashdev_mark_partition_defined( iop, i );
+
+  return i;
+}
+
+static int rtems_flashdev_check_partition_valid(
+  rtems_flashdev *flash,
+  rtems_flashdev_partition * region
+)
+{
+  size_t erase_size = 0;
+  int status = (flash)->get_erase_size(flash, &erase_size);
+
+  if (0 != status)
+  {
+    return status;
+  }
+  if (region->offset % erase_size || region->size % erase_size)
+  {
+    return -1;
+  }
+
+  return 0;
+}
+
+static uint32_t rtems_flashdev_find_unallocated_partition(
+  rtems_libio_t *iop
+)
+{
+  uint16_t defined_partitions = rtems_flashdev_get_defined_partitions(iop);
+
+  for (uint32_t idx = 0; idx < RTEMS_FLASHDEV_MAX_PARTITIONS; ++idx)
+  {
+    if (!(defined_partitions & ( 1 << idx )))
+    {
+      return idx;
+    }
+  }
+
+  return RTEMS_FLASHDEV_PARTITION_ALLOC_FULL;
+}
+
+static int rtems_flashdev_open(
+  rtems_libio_t *iop,
+  const char *path,
+  int oflag,
+  mode_t mode
+)
+{
+  int ret = rtems_filesystem_default_open( iop, path, oflag, mode );
+  rtems_flashdev_mark_partition_defined(iop, RTEMS_FLASHDEV_PARTITION_UNDEFINED);
+  return ret;
+}
+
+static int rtems_flashdev_close(
+  rtems_libio_t *iop
+)
+{
+  return rtems_filesystem_default_close( iop );
+}
+
 static int rtems_flashdev_ioctl(
   rtems_libio_t *iop,
   ioctl_command_t command,
@@ -409,20 +588,28 @@ static int rtems_flashdev_ioctl(
     case RTEMS_FLASHDEV_IOCTL_ERASE:
       err = rtems_flashdev_ioctl_erase( flash, iop, arg );
       break;
-    case RTEMS_FLASHDEV_IOCTL_SET_REGION:
-      err = rtems_flashdev_ioctl_set_region( flash, iop, arg );
+    case RTEMS_FLASHDEV_IOCTL_CREATE_PARTITION:
+      err = rtems_flashdev_ioctl_create_partition( flash, iop, arg );
+      break;
+    case RTEMS_FLASHDEV_IOCTL_DELETE_PARTITION:
+      err = rtems_flashdev_ioctl_delete_partition( flash, iop, arg );
+      break;
+    case RTEMS_FLASHDEV_IOCTL_RESIZE_PARTITION:
+      err = rtems_flashdev_ioctl_resize_partition( flash, iop, arg );
+    case RTEMS_FLASHDEV_IOCTL_ACTIVATE_PARTITION:
+      err = rtems_flashdev_ioctl_activate_partition( flash, iop, arg );
       break;
-    case RTEMS_FLASHDEV_IOCTL_UNSET_REGION:
-      err = rtems_flashdev_ioctl_clear_region( flash, iop );
+    case RTEMS_FLASHDEV_IOCTL_DEACTIVATE_PARTITION:
+      err = rtems_flashdev_ioctl_deactivate_partition( flash, iop, arg );
       break;
     case RTEMS_FLASHDEV_IOCTL_GET_TYPE:
       err = rtems_flashdev_ioctl_get_flash_type( flash, arg );
       break;
     case RTEMS_FLASHDEV_IOCTL_GET_PAGEINFO_BY_OFFSET:
-      err = rtems_flashdev_ioctl_get_pageinfo_offset( flash, arg );
+      err = rtems_flashdev_ioctl_get_pageinfo_by_offset( flash, arg );
       break;
     case RTEMS_FLASHDEV_IOCTL_GET_PAGEINFO_BY_INDEX:
-      err = rtems_flashdev_ioctl_get_pageinfo_index( flash, arg );
+      err = rtems_flashdev_ioctl_get_pageinfo_by_index( flash, arg );
       break;
     case RTEMS_FLASHDEV_IOCTL_GET_PAGE_COUNT:
       err = rtems_flashdev_ioctl_get_page_count( flash, arg );
@@ -434,15 +621,15 @@ static int rtems_flashdev_ioctl(
       err = rtems_flashdev_ioctl_get_erase_size( flash, arg );
       break;
     default:
-      err = EINVAL;
+      err = -EINVAL;
   }
 
   rtems_flashdev_release( flash );
-  if ( err != 0 ) {
+  if ( err < 0 ) {
     rtems_set_errno_and_return_minus_one( err );
-  } else {
-    return 0;
   }
+
+  return err;
 }
 
 static off_t rtems_flashdev_lseek(
@@ -470,8 +657,8 @@ static off_t rtems_flashdev_lseek(
       rtems_set_errno_and_return_minus_one( EINVAL );
   }
 
-  if ( ( rtems_flashdev_is_region_defined(iop) ) &&
-       ( tmp_offset > rtems_flashdev_get_region_size( flash, iop ) ) ) {
+  if ( ( rtems_flashdev_is_a_partition_active(iop) ) &&
+       ( tmp_offset > rtems_flashdev_get_partition_size( flash, iop ) ) ) {
     rtems_set_errno_and_return_minus_one( EINVAL );
   }
 
@@ -479,192 +666,248 @@ static off_t rtems_flashdev_lseek(
   return iop->offset;
 }
 
-static int rtems_flashdev_close(
-  rtems_libio_t *iop
+static void rtems_flashdev_node_destroy(
+  IMFS_jnode_t *node
 )
 {
-  rtems_flashdev *flash = IMFS_generic_get_context_by_iop( iop );
-  rtems_flashdev_ioctl_clear_region( flash, iop );
-  return rtems_filesystem_default_close( iop );
+  rtems_flashdev *flash;
+
+  flash = IMFS_generic_get_context_by_node( node );
+
+  ( *flash->destroy )( flash );
+
+  IMFS_node_destroy_default( node );
 }
 
-static int rtems_flashdev_open(
-  rtems_libio_t *iop,
-  const char *path,
-  int oflag,
-  mode_t mode
+static uint32_t rtems_flashdev_get_defined_partitions(
+  rtems_libio_t *iop
 )
 {
-  int ret = rtems_filesystem_default_open( iop, path, oflag, mode );
-  rtems_flashdev_set_region_index(iop, RTEMS_FLASHDEV_REGION_UNDEFINED);
-  return ret;
+  return 0x0000FFFF & ((uint32_t) iop->data0);
 }
 
-int rtems_flashdev_register(
-  rtems_flashdev *flash,
-  const char *flash_path
+static bool rtems_flashdev_is_a_partition_active(
+  rtems_libio_t *iop
 )
 {
-  int rv;
-  rtems_flashdev_region_table *table = flash->region_table;
-  int alloc_array_len;
+  return (rtems_flashdev_get_active_partition_index( iop )
+    != RTEMS_FLASHDEV_PARTITION_UNDEFINED);
+}
 
-  rv = IMFS_make_generic_node(
-    flash_path,
-    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
-    &rtems_flashdev_node_control,
-    flash
-  );
+static bool rtems_flashdev_is_partition_defined(
+  rtems_libio_t *iop,
+  uint32_t partition_idx
+)
+{
+  uint32_t defined_partitions = rtems_flashdev_get_defined_partitions(iop);
+  return (defined_partitions & ( 1 << partition_idx ));
+}
 
-  if ( rv != 0 ) {
-    ( *flash->destroy )( flash );
-  }
+static int rtems_flashdev_activate_partition(
+  rtems_libio_t *iop,
+  uint32_t partition_idx
+)
+{
+  if(!rtems_flashdev_is_partition_defined(iop, partition_idx)){return -1;}
+  iop->data0 = set_bit(iop->data0, partition_idx + RTEMS_FLASHDEV_MAX_PARTITIONS);
+  return 0;
+}
 
-  alloc_array_len = RTEMS_FLASHDEV_BITALLOC_LENGTH(table) +
-    ((RTEMS_FLASHDEV_BITALLOC_FINAL_BITS(table)) != 0);
+static int rtems_flashdev_deactivate_partition(
+  rtems_libio_t *iop,
+  uint32_t partition_idx
+)
+{
+  if(!rtems_flashdev_is_partition_defined(iop, partition_idx)){return -1;}
+  iop->data0 = clear_bit(iop->data0, partition_idx + RTEMS_FLASHDEV_MAX_PARTITIONS);
+  return 0;
+}
 
-  memset(table->bit_allocator, 0, alloc_array_len);
+static void rtems_flashdev_mark_partition_defined(
+  rtems_libio_t *iop,
+  uint32_t partition_idx
+)
+{
+  iop->data0 = set_bit(iop->data0, partition_idx);
+}
 
-  return rv;
+static void rtems_flashdev_mark_partition_undefined(
+  rtems_libio_t *iop,
+  uint32_t partition_idx
+)
+{
+  if (rtems_flashdev_is_a_partition_active( iop ))
+  {
+    if( partition_idx == rtems_flashdev_get_active_partition_index( iop ) )
+    {
+      rtems_flashdev_deactivate_partition(iop, partition_idx);
+    }
+  }
+  iop->data0 = clear_bit(iop->data0, partition_idx);
 }
 
-int rtems_flashdev_deregister(
-  const char *flash_path
+static bool rtems_flashdev_check_partition_overlap(
+  rtems_libio_t *iop,
+  rtems_flashdev_partition *partition_table,
+  rtems_flashdev_partition *partition_in
 )
 {
-  rtems_filesystem_eval_path_context_t ctx;
-  int eval_flags = RTEMS_FS_FOLLOW_LINK;
-  const rtems_filesystem_location_info_t *currentloc =
-    rtems_filesystem_eval_path_start( &ctx , flash_path, eval_flags );
+  off_t cp_start;
+  off_t cp_end;
+  off_t partition_in_start = partition_in->offset;
+  off_t partition_in_end = partition_in->offset + partition_in->size;
+  uint16_t defined_partitions = rtems_flashdev_get_defined_partitions(iop);
 
-  return IMFS_rmnod(NULL, currentloc);
+  for (uint16_t idx = 0; idx < RTEMS_FLASHDEV_MAX_PARTITIONS; ++idx)
+  {
+    if (defined_partitions & ( 1 << idx ))
+    {
+      cp_start = partition_table[ idx ].offset;
+      cp_end = partition_table[ idx ].offset
+        + partition_table[ idx ].size;
+
+      if( (partition_in_start < cp_end) && (partition_in_end > cp_start) )
+      {
+        return true;
+      }
+    }
+  }
+  return false;
 }
 
-static int rtems_flashdev_do_init(
+static int rtems_flashdev_check_partition_offset(
   rtems_flashdev *flash,
-  void ( *destroy )( rtems_flashdev *flash )
+  rtems_libio_t *iop,
+  off_t offset
 )
 {
-  char mtx_name[19];
-  sprintf(mtx_name, "FDEV_MTX_%08x", (unsigned int) flash);
-  rtems_recursive_mutex_init( &flash->mutex, (const char*) &mtx_name);
-  flash->destroy = destroy;
-  flash->read = NULL;
-  flash->write = NULL;
-  flash->erase = NULL;
-  flash->get_jedec_id = NULL;
-  flash->get_flash_type = NULL;
-  flash->get_page_info_by_offset = NULL;
-  flash->get_page_info_by_index = NULL;
-  flash->get_page_count = NULL;
-  flash->get_min_write_size = NULL;
-  flash->get_erase_size = NULL;
-  flash->region_table = NULL;
+  if ( ( rtems_flashdev_is_a_partition_active( iop ) ) &&
+       ( offset > rtems_flashdev_get_partition_size( flash, iop ) ) ) {
+    rtems_set_errno_and_return_minus_one( EINVAL );
+  }
   return 0;
 }
 
-void rtems_flashdev_destroy( rtems_flashdev *flash )
+static uint32_t rtems_flashdev_get_active_partition_index(
+  rtems_libio_t *iop
+)
 {
-  rtems_recursive_mutex_destroy( &flash->mutex );
-}
+  uint32_t active = ((uint32_t)iop->data0) >> RTEMS_FLASHDEV_MAX_PARTITIONS;
 
-void rtems_flashdev_destroy_and_free( rtems_flashdev *flash )
-{
-  if ( flash == NULL ) {
-    return;
+  for (uint32_t idx = 0; idx < RTEMS_FLASHDEV_MAX_PARTITIONS; idx++)
+  {
+    if (active & ( 1 << idx ))
+    {
+      return 0x0000FFFF & idx;
+    }
   }
-  rtems_recursive_mutex_destroy( &( flash->mutex ) );
-  free( flash );
-  return;
+
+  return RTEMS_FLASHDEV_PARTITION_UNDEFINED;
 }
 
-int rtems_flashdev_init( rtems_flashdev *flash )
+static void rtems_flashdev_obtain( rtems_flashdev *flash )
 {
-  memset( flash, 0, sizeof( *flash ) );
+  rtems_recursive_mutex_lock( &flash->mutex );
+}
 
-  return rtems_flashdev_do_init( flash, rtems_flashdev_destroy );
+static void rtems_flashdev_release( rtems_flashdev *flash )
+{
+  rtems_recursive_mutex_unlock( &flash->mutex );
 }
 
+/* API Implementation*/
 rtems_flashdev *rtems_flashdev_alloc_and_init( size_t size )
 {
   rtems_flashdev *flash = NULL;
 
   if ( size >= sizeof( *flash ) ) {
     flash = calloc( 1, size );
-    if ( flash != NULL ) {
+    if ( NULL != flash ) {
       int rv;
-
+      rtems_flashdev_partition * table = calloc( RTEMS_FLASHDEV_MAX_PARTITIONS, sizeof(rtems_flashdev_partition));
       rv = rtems_flashdev_do_init( flash, rtems_flashdev_destroy_and_free );
-      if ( rv != 0 ) {
+      if ( (rv != 0) || (table == NULL) ) {
         rtems_recursive_mutex_destroy( &flash->mutex );
         free( flash );
+        if  (NULL != table)
+        {
+          free( table );
+        }
         return NULL;
       }
+      flash->partition_table = table;
     }
   }
 
   return flash;
 }
 
-static int rtems_flashdev_get_addr(
+int rtems_flashdev_init( rtems_flashdev *flash )
+{
+  memset( flash, 0, sizeof( *flash ) );
+  return rtems_flashdev_do_init( flash, rtems_flashdev_destroy );
+}
+
+int rtems_flashdev_register(
   rtems_flashdev *flash,
-  rtems_libio_t *iop,
-  size_t count,
-  off_t *addr
+  const char *flash_path
 )
 {
-  off_t new_offset;
+  int rv;
 
-  /* Check address is in valid region */
-  new_offset = iop->offset + count;
+  rv = IMFS_make_generic_node(
+    flash_path,
+    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
+    &rtems_flashdev_node_control,
+    flash
+  );
 
-  if (rtems_flashdev_check_offset_region(flash, iop, new_offset)) {
-    return -1;
+  if ( rv != 0 ) {
+    ( *flash->destroy )( flash );
   }
 
-  /* Get address for operation */
-  if ( !rtems_flashdev_is_region_defined( iop ) ) {
-    *addr = iop->offset;
-  } else {
-    *addr = ( iop->offset + rtems_flashdev_get_region_offset( flash, iop ) );
-  }
-  return 0;
+  return rv;
 }
 
-static int rtems_flashdev_get_abs_addr(
-  rtems_flashdev *flash,
-  rtems_libio_t *iop,
-  size_t count,
-  off_t *addr
+int rtems_flashdev_deregister(
+  const char *flash_path
 )
 {
-  off_t new_offset;
+  rtems_filesystem_eval_path_context_t ctx;
+  int eval_flags = RTEMS_FS_FOLLOW_LINK;
+  const rtems_filesystem_location_info_t *currentloc =
+    rtems_filesystem_eval_path_start( &ctx , flash_path, eval_flags );
 
-  /* Check address is in valid region */
-  new_offset = *addr + count;
+  return IMFS_rmnod(NULL, currentloc);
+}
 
-  if (rtems_flashdev_check_offset_region(flash, iop, new_offset)) {
-    return -1;
+void rtems_flashdev_destroy( rtems_flashdev *flash )
+{
+  rtems_recursive_mutex_destroy( &flash->mutex );
+}
+
+void rtems_flashdev_destroy_and_free( rtems_flashdev *flash )
+{
+  if ( NULL == flash ) {
+    return;
   }
 
-  /* Get address for operation */
-  if ( rtems_flashdev_is_region_defined( iop ) ) {
-    *addr = ( *addr + rtems_flashdev_get_region_offset( flash, iop ) );
+  if (NULL != flash->partition_table )
+  {
+    free( flash->partition_table );
   }
-  return 0;
+
+  rtems_recursive_mutex_destroy( &( flash->mutex ) );
+  free( flash );
+  return;
 }
-static int rtems_flashdev_update_and_return(
-  rtems_libio_t *iop,
-  int status,
-  size_t count
-)
+
+static uint32_t rtems_flashdev_ioctl_get_jedec_id( rtems_flashdev *flash )
 {
-  /* Update offset and return */
-  if ( status == 0 ) {
-    iop->offset += count;
-    return count;
+  if ( flash->get_jedec_id == NULL ) {
+    return 0;
   } else {
-    rtems_set_errno_and_return_minus_one( status );
+    return ( *flash->get_jedec_id )( flash );
   }
 }
 
@@ -674,7 +917,7 @@ static int rtems_flashdev_ioctl_erase(
   void *arg
 )
 {
-  rtems_flashdev_region *erase_args_1;
+  rtems_flashdev_partition *erase_args_1;
   off_t new_offset;
   int status;
 
@@ -682,9 +925,9 @@ static int rtems_flashdev_ioctl_erase(
     return 0;
   }
 
-  erase_args_1 = (rtems_flashdev_region *) arg;
-  /* Check erasing valid region */
-  if ( 0 != rtems_flashdev_check_region_valid(flash, erase_args_1))
+  erase_args_1 = (rtems_flashdev_partition *) arg;
+  /* Check erasing valid partition */
+  if ( 0 != rtems_flashdev_check_partition_valid(flash, erase_args_1))
   {
     return EINVAL;
   }
@@ -700,149 +943,122 @@ static int rtems_flashdev_ioctl_erase(
   return status;
 }
 
-static int rtems_flashdev_ioctl_set_region(
+
+static int rtems_flashdev_ioctl_create_partition(
   rtems_flashdev *flash,
   rtems_libio_t *iop,
   void *arg
 )
 {
-  rtems_flashdev_region *region_in;
-  rtems_flashdev_region_table *table = flash->region_table;
-  region_in = (rtems_flashdev_region *) arg;
+  rtems_flashdev_partition *partition_in;
+  rtems_flashdev_partition *table = flash->partition_table;
+  partition_in = (rtems_flashdev_partition *) arg;
+  uint32_t partition_idx = 0;
 
-  if (flash->region_table == NULL) {
+  if (table == NULL) {
     rtems_set_errno_and_return_minus_one( ENOMEM );
   }
 
-  if ( 0 != rtems_flashdev_check_region_valid(flash, region_in))
+  if ( 0 != rtems_flashdev_check_partition_valid(flash, partition_in))
   {
-    return EINVAL;
+    rtems_set_errno_and_return_minus_one( EINVAL );
   }
 
-  if ( !rtems_flashdev_is_region_defined( iop ) ) {
-    if (
-      rtems_flashdev_find_unallocated_region(table)
-        == RTEMS_FLASHDEV_REGION_ALLOC_FULL
-    )
-    {
-      /* New region to allocate and all regions allocated */
-      rtems_set_errno_and_return_minus_one( ENOMEM );
-    } else {
-      /* New region to allocate and space to allocate region */
-      return rtems_flashdev_ioctl_create_region( flash, iop, region_in );
-    }
-  } else {
-    /* Updating existing region */
-    return rtems_flashdev_ioctl_update_region( flash, iop, region_in );
+  if (rtems_flashdev_check_partition_overlap(iop, table, partition_in)) {
+    rtems_set_errno_and_return_minus_one( EINVAL );
+  }
+  partition_idx = rtems_flashdev_find_unallocated_partition(iop);
+
+  if (RTEMS_FLASHDEV_PARTITION_ALLOC_FULL == partition_idx)
+  {
+    /* New partition to allocate and all partitions allocated */
+    rtems_set_errno_and_return_minus_one( ENOMEM );
   }
 
+  /* New partition to allocate and space to allocate partition */
+  return rtems_flashdev_create_partition( iop, table, partition_idx, partition_in );
 }
 
-static int rtems_flashdev_ioctl_create_region(
+static int rtems_flashdev_ioctl_delete_partition(
   rtems_flashdev *flash,
   rtems_libio_t *iop,
-  rtems_flashdev_region *region_in
+  void *arg
 )
 {
-  int i;
-  rtems_flashdev_region_table *table = flash->region_table;
+  uint32_t *partition_idx = (uint32_t*) arg;
 
-  /* Find unallocated region slot */
-  i = rtems_flashdev_find_unallocated_region(flash->region_table);
-  if (i == RTEMS_FLASHDEV_REGION_ALLOC_FULL) {
+  if (flash->partition_table == NULL) {
     rtems_set_errno_and_return_minus_one( ENOMEM );
   }
 
-  /* Set region values */
-  table->regions[ i ].offset = region_in->offset;
-  table->regions[ i ].size = region_in->size;
-
-  /* Set region as allocated and link iop */
-  rtems_flashdev_set_region(flash->region_table, i);
-  rtems_flashdev_set_region_index( iop, i );
-
-  return 0;
-}
-
-static int rtems_flashdev_ioctl_update_region(
-  rtems_flashdev *flash,
-  rtems_libio_t *iop,
-  rtems_flashdev_region *region_in
-)
-{
-  uint32_t region_index = rtems_flashdev_get_region_index( iop );
-  rtems_flashdev_region_table *table = flash->region_table;
-
-  /**
-   * If region index is larger then maximum region index or region
-   * index at given index is undefined return an error.
-   */
-  if (
-       ( region_index >= flash->region_table->max_regions ) ||
-       ( rtems_flashdev_check_allocation( table, region_index ) == 0)
-     )
-  {
+  /* Check partition to clear */
+  if ( *partition_idx >=  RTEMS_FLASHDEV_MAX_PARTITIONS ) {
     rtems_set_errno_and_return_minus_one( EINVAL );
   }
 
-  /* Set region values */
-  table->regions[ region_index ].offset = region_in->offset;
-  table->regions[ region_index ].size = region_in->size;
-
+  /* Clear partition */
+  rtems_flashdev_mark_partition_undefined( iop, *partition_idx );
   return 0;
 }
 
-static int rtems_flashdev_ioctl_clear_region(
+static int rtems_flashdev_ioctl_resize_partition(
   rtems_flashdev *flash,
-  rtems_libio_t *iop
+  rtems_libio_t *iop,
+  void *arg
 )
 {
-  uint32_t region_index = rtems_flashdev_get_region_index( iop );
+  rtems_flashdev_partition storage;
 
-  if (flash->region_table == NULL) {
-    rtems_set_errno_and_return_minus_one( ENOMEM );
+  uint32_t partition_idx = 0;
+  int ret = -1;
+  if ( !rtems_flashdev_is_a_partition_active( iop ) ) {
+    return -1;
   }
 
-  /* Check region to clear */
-  if ( region_index == RTEMS_FLASHDEV_REGION_UNDEFINED ) {
-    rtems_set_errno_and_return_minus_one( EINVAL );
+  partition_idx = rtems_flashdev_get_active_partition_index( iop );
+  storage = flash->partition_table[ partition_idx ];
+
+  if ( 0 == rtems_flashdev_ioctl_delete_partition( flash, iop, &partition_idx ))
+  {
+    ret = rtems_flashdev_ioctl_create_partition( flash, iop, arg);
+
+    if (ret >= 0)
+    {
+      rtems_flashdev_activate_partition(iop, (uint32_t) ret);
+      return  ret;
+    }
+    else
+    {
+      ret = rtems_flashdev_create_partition( iop, flash->partition_table, partition_idx, &storage);
+      if (ret >= 0)
+      {
+        rtems_flashdev_activate_partition(iop, partition_idx);
+        return  -1;
+      }
+    }
   }
 
-  /* Clear region */
-  rtems_flashdev_unset_region( flash->region_table, region_index );
-  rtems_flashdev_set_region_index( iop, RTEMS_FLASHDEV_REGION_UNDEFINED );
-  return 0;
+  return -1;
 }
 
-static off_t rtems_flashdev_get_region_offset(
+static int rtems_flashdev_ioctl_activate_partition(
   rtems_flashdev *flash,
-  rtems_libio_t *iop
+  rtems_libio_t *iop,
+  void *arg
 )
 {
-  /* Region is already checked to be defined */
-  assert( rtems_flashdev_get_region_index( iop ) != RTEMS_FLASHDEV_REGION_UNDEFINED );
-  rtems_flashdev_region_table *table = flash->region_table;
-  return table->regions[ rtems_flashdev_get_region_index( iop ) ].offset;
+  uint32_t *partition_idx = (uint32_t*) arg;
+  return rtems_flashdev_activate_partition(iop, *partition_idx);
 }
 
-static size_t rtems_flashdev_get_region_size(
+static int rtems_flashdev_ioctl_deactivate_partition(
   rtems_flashdev *flash,
-  rtems_libio_t *iop
+  rtems_libio_t *iop,
+  void *arg
 )
 {
-  /* Region is already checked to be defined */
-  assert( rtems_flashdev_get_region_index( iop ) != RTEMS_FLASHDEV_REGION_UNDEFINED );
-  rtems_flashdev_region_table *table = flash->region_table;
-  return table->regions[ rtems_flashdev_get_region_index( iop ) ].size;
-}
-
-static uint32_t rtems_flashdev_ioctl_get_jedec_id( rtems_flashdev *flash )
-{
-  if ( flash->get_jedec_id == NULL ) {
-    return 0;
-  } else {
-    return ( *flash->get_jedec_id )( flash );
-  }
+  uint32_t *partition_idx = (uint32_t*) arg;
+  return rtems_flashdev_deactivate_partition(iop, *partition_idx);
 }
 
 static uint32_t rtems_flashdev_ioctl_get_flash_type(
@@ -858,7 +1074,7 @@ static uint32_t rtems_flashdev_ioctl_get_flash_type(
   }
 }
 
-static int rtems_flashdev_ioctl_get_pageinfo_offset(
+static int rtems_flashdev_ioctl_get_pageinfo_by_offset(
   rtems_flashdev *flash,
   void *arg
 )
@@ -879,7 +1095,7 @@ static int rtems_flashdev_ioctl_get_pageinfo_offset(
   }
 }
 
-static int rtems_flashdev_ioctl_get_pageinfo_index( rtems_flashdev *flash,
+static int rtems_flashdev_ioctl_get_pageinfo_by_index( rtems_flashdev *flash,
                                                 void *arg )
 {
   rtems_flashdev_ioctl_page_info *page_info;
@@ -938,95 +1154,4 @@ static int rtems_flashdev_ioctl_get_erase_size(
   } else {
     return ( *flash->get_erase_size )( flash, ( (size_t *) arg ) );
   }
-}
-
-static int rtems_flashdev_check_region_valid(
-  rtems_flashdev *flash,
-  rtems_flashdev_region * region
-)
-{
-  size_t erase_size = 0;
-  int status = (flash)->get_erase_size(flash, &erase_size);
-
-  if (0 != status)
-  {
-    return status;
-  }
-  if (region->offset % erase_size || region->size % erase_size)
-  {
-    return -1;
-  }
-
-  return 0;
-}
-
-static uint32_t rtems_flashdev_find_unallocated_region(
-  rtems_flashdev_region_table *region_table
-)
-{
-  int array_index = 0;
-  int bit_index = 0;
-  int shift;
-
-  while ( bit_index < region_table->max_regions) {
-    /* Get uint32_t holding the ith bit */
-    array_index = bit_index / RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
-    shift = bit_index % RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
-
-    /* Check if region available in next BITALLOC_LENGTH regions */
-    if (
-        (shift == 0) &&
-        (region_table->bit_allocator[ array_index ] == RTEMS_FLASHDEV_REGION_ALLOC_FULL)
-    )
-    {
-      bit_index = bit_index + RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
-      continue;
-    }
-
-    /* Check individual bit */
-    if ( ! ( ( ( region_table->bit_allocator[ array_index ] ) >> shift ) & 1UL ) ) {
-      return bit_index;
-    }
-
-    bit_index++;
-  }
-
-  return RTEMS_FLASHDEV_REGION_ALLOC_FULL;
-}
-
-static uint32_t rtems_flashdev_set_region(
-  rtems_flashdev_region_table *region_table,
-  int index
-)
-{
-  int array_index = index / RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
-  int shift = index % RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
-
-  region_table->bit_allocator[ array_index ] |= 1UL << shift;
-
-  return index;
-}
-
-static uint32_t rtems_flashdev_unset_region(
-  rtems_flashdev_region_table *region_table,
-  int index
-)
-{
-  int array_index = index / RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
-  int shift = index % RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
-
-  region_table->bit_allocator[ array_index ] &= ~( 1UL << shift );
-
-  return index;
-}
-
-static uint32_t rtems_flashdev_check_allocation(
-  rtems_flashdev_region_table *region_table,
-  int index
-)
-{
-  int array_index = index / RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
-  int shift = index%RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
-
-  return ( ( region_table->bit_allocator[ array_index ] >> shift ) & 1UL );
-}
+}
\ No newline at end of file
diff --git a/cpukit/include/dev/flash/flashdev.h b/cpukit/include/dev/flash/flashdev.h
index 0b54fcc71e..91a189ff6f 100644
--- a/cpukit/include/dev/flash/flashdev.h
+++ b/cpukit/include/dev/flash/flashdev.h
@@ -57,105 +57,135 @@ typedef struct rtems_flashdev rtems_flashdev;
  */
 
 /* IOCTL Calls */
+typedef enum {
+  /**
+   * @brief Obtains the flash device.
+   *
+   * This command has no argument.
+   */
+  RTEMS_FLASHDEV_IOCTL_OBTAIN = 0,
 
-/**
- * @brief Obtains the flash device.
- *
- * This command has no argument.
- */
-#define RTEMS_FLASHDEV_IOCTL_OBTAIN 0
-/**
- * @brief Releases the flash device.
- *
- * This command has no argument.
- */
-#define RTEMS_FLASHDEV_IOCTL_RELEASE 1
-/**
- * @brief Returns the JEDEC ID of the flash device. This IOCTL call
- * is informational only.
- *
- * @param[out] jedec_id Pointer to uint32_t in which the JEDEC ID is
- * returned in.
- */
-#define RTEMS_FLASHDEV_IOCTL_GET_JEDEC_ID 2
-/**
- * @brief Erases flash device.
- *
- * @param[in] erase_args Pointer to rtems_flashdev_region struct
- * containing offset and size of erase to be performed.
- */
-#define RTEMS_FLASHDEV_IOCTL_ERASE 3
-/**
- * @brief Set a region that limits read, write and erase calls to within it.
- * Regions are file descriptor specific and limited to a single region per
- * file descriptor and 32 regions total per flash device. Regions can be
- * changed or updated by calling this IOCTL again.
- *
- * @param[in] region Pointer to rtems_flashdev_region struct containing
- * base and length of defined region.
- */
-#define RTEMS_FLASHDEV_IOCTL_SET_REGION 4
-/**
- * @brief Removes the set region on the file descriptor.
- *
- * This command has no argument.
- */
-#define RTEMS_FLASHDEV_IOCTL_UNSET_REGION 5
-/**
- * @brief Returns the type of flash device (e.g. NOR or NAND).
- *
- * @param[out] flash_type Pointer to integer which is set to the flash
- * type macro value.
- */
-#define RTEMS_FLASHDEV_IOCTL_GET_TYPE 6
+  /**
+   * @brief Releases the flash device.
+   *
+   * This command has no argument.
+   */
+  RTEMS_FLASHDEV_IOCTL_RELEASE,
 
-/**
- * @brief Get the size and address of flash page at given offset
- *
- * The offset ignores the region limiting. To find page of region
- * limited offset add the base of the region to the desired offset.
- *
- * @param[in,out] rtems_flashdev_ioctl_page_info arg Pointer to struct
- * with offset and space for return values.
- */
-#define RTEMS_FLASHDEV_IOCTL_GET_PAGEINFO_BY_OFFSET 7
+  /**
+   * @brief Returns the JEDEC ID of the flash device. This IOCTL call
+   * is informational only.
+   *
+   * @param[out] jedec_id Pointer to uint32_t in which the JEDEC ID is
+   * returned in.
+   */
+  RTEMS_FLASHDEV_IOCTL_GET_JEDEC_ID,
 
-/**
- * @brief Get the size and address of nth flash page where n is index passed in.
- *
- * The index ignores the region limiting.
- *
- * @param[in,out] rtems_flashdev_ioctl_page_info arg Pointer to struct
- * with index and space for return values.
- */
-#define RTEMS_FLASHDEV_IOCTL_GET_PAGEINFO_BY_INDEX 8
+  /**
+   * @brief Erases flash device.
+   *
+   * @param[in] erase_args Pointer to rtems_flashdev_partition struct
+   * containing offset and size of erase to be performed.
+   */
+  RTEMS_FLASHDEV_IOCTL_ERASE,
 
-/**
- * @brief Get the number of pages in flash device.
- *
- * @param[out] count Integer containing the number of pages.
- */
-#define RTEMS_FLASHDEV_IOCTL_GET_PAGE_COUNT 9
+  /**
+   * @brief Create a partition that limits read, write and erase calls to
+   * within it. Partitions are file descriptor specific and limited to a
+   * single partition per file descriptor and 32 partitions total per
+   * flash device.
+   *
+   * @param[in] partition Pointer to rtems_flashdev_partition struct containing
+   * base and length of defined partition.
+   *
+   * @return partition_idx Integer containing the partition index or error
+   */
+  RTEMS_FLASHDEV_IOCTL_CREATE_PARTITION,
 
-/**
- * @brief Get the minimum write size supported by the driver.
- *
- * @param[out] count Integer containing the minimum write size.
- */
-#define RTEMS_FLASHDEV_IOCTL_GET_MIN_WRITE_SIZE 10
+  /**
+   * @brief Delete a partition
+   *
+   * @param[in] partition_idx Integer containing the partition index
+   *
+   */
+  RTEMS_FLASHDEV_IOCTL_DELETE_PARTITION,
 
-/**
- * @brief Get the erase size supported by the driver.
- *
- * @param[out] count Integer containing the erase size.
- */
-#define RTEMS_FLASHDEV_IOCTL_GET_ERASE_SIZE 11
+  /**
+   * @brief Resize active partition
+   *
+   * @param[in] partition Pointer to rtems_flashdev_partition struct containing
+   * base and length of defined partition.
+   *
+   */
+  RTEMS_FLASHDEV_IOCTL_RESIZE_PARTITION,
 
-/**
- * @brief The maximum number of region limited file descriptors
- * allowed to be open at once.
- */
-#define RTEMS_FLASHDEV_MAX_REGIONS 32
+  /**
+   * @brief Activate a partition
+   *
+   * @param[in] partition_idx Integer containing the partition index
+   *
+   */
+  RTEMS_FLASHDEV_IOCTL_ACTIVATE_PARTITION,
+
+  /**
+   * @brief Deactivate a partition
+   *
+   * @param[in] partition_idx Integer containing the partition index
+   *
+   */
+  RTEMS_FLASHDEV_IOCTL_DEACTIVATE_PARTITION,
+
+  /**
+   * @brief Returns the type of flash device (e.g. NOR or NAND).
+   *
+   * @param[out] flash_type Pointer to integer which is set to the flash
+   * type macro value.
+   */
+  RTEMS_FLASHDEV_IOCTL_GET_TYPE,
+
+  /**
+   * @brief Get the size and address of flash page at given offset
+   *
+   * The offset ignores the region limiting. To find page of region
+   * limited offset add the base of the region to the desired offset.
+   *
+   * @param[in,out] rtems_flashdev_ioctl_page_info arg Pointer to struct
+   * with offset and space for return values.
+   */
+  RTEMS_FLASHDEV_IOCTL_GET_PAGEINFO_BY_OFFSET,
+
+  /**
+   * @brief Get the size and address of nth flash page where n is index passed in.
+   *
+   * The index ignores the region limiting.
+   *
+   * @param[in,out] rtems_flashdev_ioctl_page_info arg Pointer to struct
+   * with index and space for return values.
+   */
+  RTEMS_FLASHDEV_IOCTL_GET_PAGEINFO_BY_INDEX,
+
+  /**
+   * @brief Get the number of pages in flash device.
+   *
+   * @param[out] count Integer containing the number of pages.
+   */
+  RTEMS_FLASHDEV_IOCTL_GET_PAGE_COUNT,
+
+  /**
+   * @brief Get the minimum write size supported by the driver.
+   *
+   * @param[out] count Integer containing the minimum write size.
+   */
+  RTEMS_FLASHDEV_IOCTL_GET_MIN_WRITE_SIZE,
+
+  /**
+   * @brief Get the erase size supported by the driver.
+   *
+   * @param[out] count Integer containing the erase size.
+   */
+  RTEMS_FLASHDEV_IOCTL_GET_ERASE_SIZE
+
+} rtems_flashdev_ioctl_token;
 
 /**
  * @brief Enum for flash type returned from IOCTL call.
@@ -174,38 +204,16 @@ typedef enum rtems_flashdev_flash_type {
 /**
  * @brief General definition for on flash device.
  */
-typedef struct rtems_flashdev_region {
+typedef struct rtems_flashdev_partition {
   /**
-   * @brief Base of region.
+   * @brief Base of partition.
    */
   off_t offset;
   /**
-   * @brief Length of region.
+   * @brief Length of partition.
    */
   size_t size;
-} rtems_flashdev_region;
-
-/**
- * @brief Struct holding region definitions
- */
-typedef struct rtems_flashdev_region_table {
-  /**
-   * @brief The maximum regions that can be defined at once.
-   */
-  int max_regions;
-
-  /**
-   * @brief Pointer to array of rtems_flashdev_region of length
-   * max_regions
-   */
-  rtems_flashdev_region* regions;
-
-  /**
-   * @brief Array of uint32_t acting as bit allocator
-   * for regions array.
-   */
-  uint32_t *bit_allocator;
-} rtems_flashdev_region_table;
+} rtems_flashdev_partition;
 
 /**
  * @brief Page information returned from IOCTL calls.
@@ -220,7 +228,7 @@ typedef struct rtems_flashdev_ioctl_page_info {
    * @brief Information returned about the page. Including the
    * base offset and size of page.
    */
-  rtems_flashdev_region page_info;
+  rtems_flashdev_partition page_info;
 } rtems_flashdev_ioctl_page_info;
 
 /**
@@ -405,9 +413,9 @@ struct rtems_flashdev {
   rtems_recursive_mutex mutex;
 
   /**
-   * @brief Region table defining size and memory for region allocations
+   * @brief Partition table
    */
-  rtems_flashdev_region_table *region_table;
+  rtems_flashdev_partition *partition_table;
 };
 
 /**
diff --git a/cpukit/libmisc/shell/main_flashdev.c b/cpukit/libmisc/shell/main_flashdev.c
index e070642cca..2b703a88ec 100644
--- a/cpukit/libmisc/shell/main_flashdev.c
+++ b/cpukit/libmisc/shell/main_flashdev.c
@@ -337,7 +337,7 @@ int flashdev_shell_erase(
   uint32_t bytes;
   int fd;
   int status;
-  rtems_flashdev_region args;
+  rtems_flashdev_partition args;
 
   /* Check arguments */
   if (argc < 5) {
diff --git a/testsuites/libtests/flashdev01/init.c b/testsuites/libtests/flashdev01/init.c
index 118367a62f..a6f7251496 100644
--- a/testsuites/libtests/flashdev01/init.c
+++ b/testsuites/libtests/flashdev01/init.c
@@ -55,9 +55,9 @@ static void run_test(void) {
   int status;
   char* read_data;
   size_t bytes_read;
-  rtems_flashdev_region e_args;
+  rtems_flashdev_partition e_args;
   rtems_flashdev_ioctl_page_info pg_info;
-  rtems_flashdev_region region;
+  rtems_flashdev_partition partition;
   uint32_t jedec;
   int page_count;
   int type;
@@ -133,7 +133,6 @@ static void run_test(void) {
     status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_ERASE, &e_args);
     rtems_test_assert(!status);
 
-
     fseek(file, 0x0, SEEK_SET);
     fgets(buff, TEST_DATA_SIZE, file);
     rtems_test_assert(buff[0] == 0);
@@ -215,53 +214,107 @@ static void run_test(void) {
   rtems_test_assert(bytes_read == TEST_DATA_SIZE);
   memset(buff,0x00,TEST_DATA_SIZE);
 
-  /* Test Regions - this one must fail */
-  region.offset = ERASE_SIZE;
-  region.size = 0x200;
-  status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_SET_REGION, &region);
+  /* Test Partitions - this one must fail */
+  partition.offset = ERASE_SIZE;
+  partition.size = 0x200;
+  status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_CREATE_PARTITION, &partition);
+  rtems_test_assert(status);
+
+  /* Test Partitions - this one must fail*/
+  partition.offset = 0x200;
+  partition.size = ERASE_SIZE;
+  status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_CREATE_PARTITION, &partition);
   rtems_test_assert(status);
 
-  /* Test Regions - this one must fail*/
-  region.offset = 0x200;
-  region.size = ERASE_SIZE;
-  status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_SET_REGION, &region);
+  /* Test Partitions - create partition 0*/
+  partition.offset = 0;
+  partition.size = ERASE_SIZE;
+  status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_CREATE_PARTITION, &partition);
+  rtems_test_assert(status == 0);
+
+  /* Activate Partition 0*/
+  status = 0;
+  status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_ACTIVATE_PARTITION, &status);
+  rtems_test_assert(!status);
+
+  /* Try to resize partition 0 above limit*/
+  partition.offset = 1;
+  partition.size = ERASE_SIZE;
+  status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_RESIZE_PARTITION, &partition);
   rtems_test_assert(status);
 
-  /* Test Regions */
-  region.offset = ERASE_SIZE;
-  region.size = ERASE_SIZE;
-  status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_SET_REGION, &region);
+  /* Try to resize partition 0 within limit*/
+  partition.offset = 0;
+  partition.size = 2*ERASE_SIZE;
+  status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_RESIZE_PARTITION, &partition);
+  rtems_test_assert(status == 0);
+
+  /* Try to resize partition 0 to original size*/
+  partition.size = ERASE_SIZE;
+  status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_RESIZE_PARTITION, &partition);
+  rtems_test_assert(status == 0);
+
+  /* Deactivate Partition 0*/
+  status = 0;
+  status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_DEACTIVATE_PARTITION, &status);
   rtems_test_assert(!status);
 
-  /* Test Erasing*/
+  /* Test Partitions - ioctl returns partition idx*/
+  partition.offset = ERASE_SIZE;
+  partition.size = ERASE_SIZE;
+  status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_CREATE_PARTITION, &partition);
+  rtems_test_assert(status == 1);
+
+  /* Activate Partition - wrong partion idx*/
+  status = 3;
+  status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_ACTIVATE_PARTITION, &status);
+  rtems_test_assert(status);
+
+  /* Activate Partition - ioctl returns partition idx*/
+  status = 1;
+  status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_ACTIVATE_PARTITION, &status);
+  rtems_test_assert(!status);
+
+  /* Test Erasing - ioctl returns partition idx*/
   e_args.offset = 0x0;
   e_args.size = ERASE_SIZE;
   status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_ERASE, &e_args);
   rtems_test_assert(!status);
 
-  /* Test read within then region */
+  /* Test read within then partition */
   status = fseek(file, 0x0, SEEK_SET);
   rtems_test_assert(!status);
   bytes_read = fread(buff, 1, 0x200, file);
   rtems_test_assert(bytes_read == 0x200);
 
-  /* Test read to larger then region */
+  /* Test read to larger then partition */
   fseek(file, 0x0, SEEK_SET);
   rtems_test_assert(!status);
   read_data = fgets(buff, 2048, file);
   rtems_test_assert(buff[0] == 0);
 
-  /* Test fseek outside of region */
+  /* Test fseek outside of partition */
   fseek(file, 0x0, SEEK_SET);
   rtems_test_assert(!status);
   status = fseek(file, ERASE_SIZE+1, SEEK_SET);
   rtems_test_assert(status);
 
-  /* Write to base unset region and check the writes location */
+  /* Write to base unset partition and check the writes location */
   fseek(file, 0x0, SEEK_SET);
   fwrite("HELLO WORLD!!!!!", 1, 16, file);
-  ioctl(fd, RTEMS_FLASHDEV_IOCTL_UNSET_REGION, NULL);
-  /* Test read within then region */
+
+  /* delete partition 0 */
+  status = 0;
+  status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_DELETE_PARTITION, &status);
+  rtems_test_assert(!status);
+
+  /* delete partition 1 */
+  status = 1;
+  status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_DELETE_PARTITION, &status);
+  rtems_test_assert(!status);
+
+
+  /* Test read within then partition */
   status = fseek(file, 0x0, SEEK_SET);
   rtems_test_assert(!status);
   bytes_read = fread(buff, 1, 0x200, file);
diff --git a/testsuites/libtests/flashdev01/test_flashdev.c b/testsuites/libtests/flashdev01/test_flashdev.c
index 9b8d1dbba5..012e1ed152 100644
--- a/testsuites/libtests/flashdev01/test_flashdev.c
+++ b/testsuites/libtests/flashdev01/test_flashdev.c
@@ -33,9 +33,7 @@
 #define TEST_DATA_SIZE (PAGE_SIZE * PAGE_COUNT)
 #define PAGE_COUNT 16
 #define PAGE_SIZE 128
-#define MAX_NUM_REGIONS 48
-#define BITALLOC_SIZE 32
-#define NUM_BITALLOC ((MAX_NUM_REGIONS + BITALLOC_SIZE - 1) / BITALLOC_SIZE)
+#define MAX_NUM_PARTITIONS 16
 
 static size_t g_min_write_size = 0;
 static size_t g_erase_size = 0;
@@ -47,8 +45,6 @@ static size_t g_erase_size = 0;
 typedef struct test_flashdev {
   char* data;
   uint32_t jedec_id;
-  uint32_t bit_allocator[NUM_BITALLOC];
-  rtems_flashdev_region regions[MAX_NUM_REGIONS];
 } test_flashdev;
 
 int test_flashdev_get_page_by_off(
@@ -287,11 +283,6 @@ rtems_flashdev* test_flashdev_init(size_t min_write_size, size_t erase_size)
 
   flash_driver->jedec_id = 0x00ABCDEF;
 
-  rtems_flashdev_region_table *ftable = calloc(1, sizeof(rtems_flashdev_region_table));
-  ftable->max_regions = MAX_NUM_REGIONS;
-  ftable->regions = flash_driver->regions;
-  ftable->bit_allocator = flash_driver->bit_allocator;
-
   flash->driver = flash_driver;
   flash->read = &test_flashdev_read;
   flash->write = &test_flashdev_write;
@@ -303,7 +294,6 @@ rtems_flashdev* test_flashdev_init(size_t min_write_size, size_t erase_size)
   flash->get_page_count = &test_flashdev_get_page_count;
   flash->get_min_write_size = &test_flashdev_get_min_write_size;
   flash->get_erase_size = &test_flashdev_get_erase_size;
-  flash->region_table = ftable;
 
   return flash;
 }
@@ -315,10 +305,6 @@ void test_flashdev_deinit(
 {
   if (NULL != flash)
   {
-    if (NULL != flash->driver)
-    {
-      free(flash->region_table);
-    }
     if (NULL != flash->driver)
     {
       test_flashdev* flash_driver = (test_flashdev*) flash->driver;
-- 
2.34.1



More information about the devel mailing list