File indexing completed on 2025-05-11 08:24:14
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #ifdef HAVE_CONFIG_H
0037 #include "config.h"
0038 #endif
0039
0040 #include <sys/stat.h>
0041 #include <stdlib.h>
0042 #include <unistd.h>
0043 #include <fcntl.h>
0044 #include <string.h>
0045
0046 #include <rtems/blkdev.h>
0047 #include <rtems/bdbuf.h>
0048 #include <rtems/imfs.h>
0049
0050 typedef struct {
0051 rtems_disk_device dd;
0052 int fd;
0053 } rtems_blkdev_imfs_context;
0054
0055 static ssize_t rtems_blkdev_imfs_read(
0056 rtems_libio_t *iop,
0057 void *buffer,
0058 size_t count
0059 )
0060 {
0061 int rv;
0062 rtems_blkdev_imfs_context *ctx = IMFS_generic_get_context_by_iop(iop);
0063 rtems_disk_device *dd = &ctx->dd;
0064 ssize_t remaining = (ssize_t) count;
0065 off_t offset = iop->offset;
0066 ssize_t block_size = (ssize_t) rtems_disk_get_block_size(dd);
0067 rtems_blkdev_bnum block = (rtems_blkdev_bnum) (offset / block_size);
0068 ssize_t block_offset = (ssize_t) (offset % block_size);
0069 char *dst = buffer;
0070
0071 while (remaining > 0) {
0072 rtems_bdbuf_buffer *bd;
0073 rtems_status_code sc = rtems_bdbuf_read(dd, block, &bd);
0074
0075 if (sc == RTEMS_SUCCESSFUL) {
0076 ssize_t copy = block_size - block_offset;
0077
0078 if (copy > remaining) {
0079 copy = remaining;
0080 }
0081
0082 memcpy(dst, (char *) bd->buffer + block_offset, (size_t) copy);
0083
0084 sc = rtems_bdbuf_release(bd);
0085 if (sc == RTEMS_SUCCESSFUL) {
0086 block_offset = 0;
0087 remaining -= copy;
0088 dst += copy;
0089 ++block;
0090 } else {
0091 remaining = -1;
0092 }
0093 } else {
0094 remaining = -1;
0095 }
0096 }
0097
0098 if (remaining >= 0) {
0099 iop->offset += count;
0100 rv = (ssize_t) count;
0101 } else {
0102 errno = EIO;
0103 rv = -1;
0104 }
0105
0106 return rv;
0107 }
0108
0109 static ssize_t rtems_blkdev_imfs_write(
0110 rtems_libio_t *iop,
0111 const void *buffer,
0112 size_t count
0113 )
0114 {
0115 int rv;
0116 rtems_blkdev_imfs_context *ctx = IMFS_generic_get_context_by_iop(iop);
0117 rtems_disk_device *dd = &ctx->dd;
0118 ssize_t remaining = (ssize_t) count;
0119 off_t offset = iop->offset;
0120 ssize_t block_size = (ssize_t) rtems_disk_get_block_size(dd);
0121 rtems_blkdev_bnum block = (rtems_blkdev_bnum) (offset / block_size);
0122 ssize_t block_offset = (ssize_t) (offset % block_size);
0123 const char *src = buffer;
0124
0125 while (remaining > 0) {
0126 rtems_status_code sc;
0127 rtems_bdbuf_buffer *bd;
0128
0129 if (block_offset == 0 && remaining >= block_size) {
0130 sc = rtems_bdbuf_get(dd, block, &bd);
0131 } else {
0132 sc = rtems_bdbuf_read(dd, block, &bd);
0133 }
0134
0135 if (sc == RTEMS_SUCCESSFUL) {
0136 ssize_t copy = block_size - block_offset;
0137
0138 if (copy > remaining) {
0139 copy = remaining;
0140 }
0141
0142 memcpy((char *) bd->buffer + block_offset, src, (size_t) copy);
0143
0144 sc = rtems_bdbuf_release_modified(bd);
0145 if (sc == RTEMS_SUCCESSFUL) {
0146 block_offset = 0;
0147 remaining -= copy;
0148 src += copy;
0149 ++block;
0150 } else {
0151 remaining = -1;
0152 }
0153 } else {
0154 remaining = -1;
0155 }
0156 }
0157
0158 if (remaining >= 0) {
0159 iop->offset += count;
0160 rv = (ssize_t) count;
0161 } else {
0162 errno = EIO;
0163 rv = -1;
0164 }
0165
0166 return rv;
0167 }
0168
0169 static int rtems_blkdev_imfs_ioctl(
0170 rtems_libio_t *iop,
0171 ioctl_command_t request,
0172 void *buffer
0173 )
0174 {
0175 int rv = 0;
0176
0177 if (request != RTEMS_BLKIO_REQUEST) {
0178 rtems_blkdev_imfs_context *ctx = IMFS_generic_get_context_by_iop(iop);
0179 rtems_disk_device *dd = &ctx->dd;
0180
0181 rv = (*dd->ioctl)(dd, request, buffer);
0182 } else {
0183
0184
0185
0186 errno = EINVAL;
0187 rv = -1;
0188 }
0189
0190 return rv;
0191 }
0192
0193 static int rtems_blkdev_imfs_fstat(
0194 const rtems_filesystem_location_info_t *loc,
0195 struct stat *buf
0196 )
0197 {
0198 rtems_blkdev_imfs_context *ctx;
0199 rtems_disk_device *dd;
0200 IMFS_jnode_t *node;
0201
0202 ctx = IMFS_generic_get_context_by_location(loc);
0203 dd = &ctx->dd;
0204
0205 buf->st_blksize = rtems_disk_get_block_size(dd);
0206 buf->st_blocks = rtems_disk_get_block_count(dd);
0207
0208 node = loc->node_access;
0209 buf->st_rdev = IMFS_generic_get_device_identifier_by_node(node);
0210
0211 return IMFS_stat(loc, buf);
0212 }
0213
0214 static int rtems_blkdev_imfs_fsync_or_fdatasync(
0215 rtems_libio_t *iop
0216 )
0217 {
0218 int rv = 0;
0219 rtems_blkdev_imfs_context *ctx = IMFS_generic_get_context_by_iop(iop);
0220 rtems_disk_device *dd = &ctx->dd;
0221 rtems_status_code sc = rtems_bdbuf_syncdev(dd);
0222
0223 if (sc != RTEMS_SUCCESSFUL) {
0224 errno = EIO;
0225 rv = -1;
0226 }
0227
0228 return rv;
0229 }
0230
0231 static const rtems_filesystem_file_handlers_r rtems_blkdev_imfs_node = {
0232 .open_h = rtems_filesystem_default_open,
0233 .close_h = rtems_filesystem_default_close,
0234 .read_h = rtems_blkdev_imfs_read,
0235 .write_h = rtems_blkdev_imfs_write,
0236 .ioctl_h = rtems_blkdev_imfs_ioctl,
0237 .lseek_h = rtems_filesystem_default_lseek_file,
0238 .fstat_h = rtems_blkdev_imfs_fstat,
0239 .ftruncate_h = rtems_filesystem_default_ftruncate,
0240 .fsync_h = rtems_blkdev_imfs_fsync_or_fdatasync,
0241 .fdatasync_h = rtems_blkdev_imfs_fsync_or_fdatasync,
0242 .fcntl_h = rtems_filesystem_default_fcntl,
0243 .kqfilter_h = rtems_filesystem_default_kqfilter,
0244 .mmap_h = rtems_filesystem_default_mmap,
0245 .poll_h = rtems_filesystem_default_poll,
0246 .readv_h = rtems_filesystem_default_readv,
0247 .writev_h = rtems_filesystem_default_writev
0248 };
0249
0250 static IMFS_jnode_t *rtems_blkdev_imfs_initialize(
0251 IMFS_jnode_t *node,
0252 void *arg
0253 )
0254 {
0255 rtems_blkdev_imfs_context *ctx;
0256 rtems_disk_device *dd;
0257
0258 node = IMFS_node_initialize_generic(node, arg);
0259
0260 ctx = IMFS_generic_get_context_by_node(node);
0261 dd = &ctx->dd;
0262 dd->dev = IMFS_generic_get_device_identifier_by_node(node);
0263
0264 return node;
0265 }
0266
0267 static void rtems_blkdev_imfs_destroy(IMFS_jnode_t *node)
0268 {
0269 rtems_blkdev_imfs_context *ctx = IMFS_generic_get_context_by_node(node);
0270 rtems_disk_device *dd = &ctx->dd;
0271
0272 (void) rtems_bdbuf_syncdev(dd);
0273 rtems_bdbuf_purge_dev(dd);
0274
0275 if (ctx->fd >= 0) {
0276 close(ctx->fd);
0277 } else {
0278 (*dd->ioctl)(dd, RTEMS_BLKIO_DELETED, NULL);
0279 }
0280
0281 free(ctx);
0282
0283 IMFS_node_destroy_default(node);
0284 }
0285
0286 static const IMFS_node_control rtems_blkdev_imfs_control =
0287 IMFS_GENERIC_INITIALIZER(
0288 &rtems_blkdev_imfs_node,
0289 rtems_blkdev_imfs_initialize,
0290 rtems_blkdev_imfs_destroy
0291 );
0292
0293 rtems_status_code rtems_blkdev_create(
0294 const char *device,
0295 uint32_t media_block_size,
0296 rtems_blkdev_bnum media_block_count,
0297 rtems_block_device_ioctl handler,
0298 void *driver_data
0299 )
0300 {
0301 rtems_status_code sc;
0302 rtems_blkdev_imfs_context *ctx;
0303
0304 sc = rtems_bdbuf_init();
0305 if (sc != RTEMS_SUCCESSFUL) {
0306 return RTEMS_INCORRECT_STATE;
0307 }
0308
0309 ctx = malloc(sizeof(*ctx));
0310 if (ctx != NULL) {
0311 sc = rtems_disk_init_phys(
0312 &ctx->dd,
0313 media_block_size,
0314 media_block_count,
0315 handler,
0316 driver_data
0317 );
0318
0319 ctx->fd = -1;
0320
0321 if (sc == RTEMS_SUCCESSFUL) {
0322 int rv = IMFS_make_generic_node(
0323 device,
0324 S_IFBLK | S_IRWXU | S_IRWXG | S_IRWXO,
0325 &rtems_blkdev_imfs_control,
0326 ctx
0327 );
0328
0329 if (rv != 0) {
0330 free(ctx);
0331 sc = RTEMS_UNSATISFIED;
0332 }
0333 } else {
0334 free(ctx);
0335 }
0336 } else {
0337 sc = RTEMS_NO_MEMORY;
0338 }
0339
0340 return sc;
0341 }
0342
0343 rtems_status_code rtems_blkdev_create_partition(
0344 const char *partition,
0345 const char *parent_block_device,
0346 rtems_blkdev_bnum media_block_begin,
0347 rtems_blkdev_bnum media_block_count
0348 )
0349 {
0350 rtems_status_code sc = RTEMS_SUCCESSFUL;
0351 int fd = open(parent_block_device, O_RDWR);
0352
0353 if (fd >= 0) {
0354 int rv;
0355 struct stat st;
0356
0357 rv = fstat(fd, &st);
0358 if (rv == 0 && S_ISBLK(st.st_mode)) {
0359 rtems_disk_device *phys_dd;
0360
0361 rv = rtems_disk_fd_get_disk_device(fd, &phys_dd);
0362 if (rv == 0) {
0363 rtems_blkdev_imfs_context *ctx = malloc(sizeof(*ctx));
0364
0365 if (ctx != NULL) {
0366 sc = rtems_disk_init_log(
0367 &ctx->dd,
0368 phys_dd,
0369 media_block_begin,
0370 media_block_count
0371 );
0372
0373 if (sc == RTEMS_SUCCESSFUL) {
0374 ctx->fd = fd;
0375
0376 rv = IMFS_make_generic_node(
0377 partition,
0378 S_IFBLK | S_IRWXU | S_IRWXG | S_IRWXO,
0379 &rtems_blkdev_imfs_control,
0380 ctx
0381 );
0382
0383 if (rv != 0) {
0384 free(ctx);
0385 sc = RTEMS_UNSATISFIED;
0386 }
0387 } else {
0388 free(ctx);
0389 }
0390 } else {
0391 sc = RTEMS_NO_MEMORY;
0392 }
0393 } else {
0394 sc = RTEMS_NOT_IMPLEMENTED;
0395 }
0396 } else {
0397 sc = RTEMS_INVALID_NODE;
0398 }
0399
0400 if (sc != RTEMS_SUCCESSFUL) {
0401 close(fd);
0402 }
0403 } else {
0404 sc = RTEMS_INVALID_ID;
0405 }
0406
0407 return sc;
0408 }