Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:04

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (C) 2024 On-Line Applications Research Corporation (OAR)
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0025  * POSSIBILITY OF SUCH DAMAGE.
0026  */
0027 
0028 #include <dev/flash/jffs2_flashdev.h>
0029 #include <rtems/jffs2.h>
0030 #include <rtems/libio.h>
0031 #include <stdio.h>
0032 #include <stdlib.h>
0033 #include <string.h>
0034 
0035 typedef struct {
0036   rtems_jffs2_flash_control super;
0037   FILE *handle;
0038   rtems_jffs2_mount_data *mount_data;
0039 } flash_control;
0040 
0041 static flash_control *get_flash_control( rtems_jffs2_flash_control *super )
0042 {
0043   return (flash_control *) super;
0044 }
0045 
0046 static int do_read(
0047   rtems_jffs2_flash_control *super,
0048   uint32_t offset,
0049   unsigned char *buffer,
0050   size_t length
0051 )
0052 {
0053   int status;
0054   flash_control *self = get_flash_control( super );
0055   int fd = fileno(self->handle);
0056 
0057   status = lseek(fd, offset, SEEK_SET);
0058   if (status == -1) {
0059       return status;
0060   }
0061 
0062   status = read(fd, buffer, length);
0063   if (status == -1) {
0064       return status;
0065   }
0066 
0067   return 0;
0068 }
0069 
0070 static int do_write(
0071   rtems_jffs2_flash_control *super,
0072   uint32_t offset,
0073   const unsigned char *buffer,
0074   size_t length
0075 )
0076 {
0077   int status;
0078   flash_control *self = get_flash_control( super );
0079   int fd = fileno(self->handle);
0080 
0081   status = lseek(fd, offset, SEEK_SET);
0082   if (status == -1) {
0083       return status;
0084   }
0085 
0086   status = write(fd, buffer, length);
0087   if (status == -1) {
0088       return status;
0089   }
0090 
0091   return 0;
0092 }
0093 
0094 static int do_erase(
0095   rtems_jffs2_flash_control *super,
0096   uint32_t offset
0097 )
0098 {
0099   int status;
0100   flash_control *self = get_flash_control( super );
0101   int fd = fileno(self->handle);
0102   rtems_flashdev_region args;
0103 
0104   args.offset = offset;
0105   args.size = super->block_size;
0106 
0107   status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_ERASE, &args);
0108   if (status == -1) {
0109       return status;
0110   }
0111 
0112   return 0;
0113 }
0114 
0115 static void do_destroy( rtems_jffs2_flash_control *super )
0116 {
0117   flash_control *self = get_flash_control( super );
0118   fclose(self->handle);
0119   free(self->mount_data);
0120   free(self);
0121 }
0122 
0123 static int get_sector_size(int fd, uint32_t *size)
0124 {
0125   rtems_flashdev_ioctl_sector_info sec_info = {0, };
0126   int status;
0127 
0128   status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_SECTORINFO_BY_OFFSET, &sec_info);
0129   if (status == 0) {
0130     *size = sec_info.sector_info.size;
0131   }
0132 
0133   return status;
0134 }
0135 
0136 static int get_page_size(int fd, uint32_t *size)
0137 {
0138   rtems_flashdev_ioctl_page_info page_info = {0, };
0139   int status;
0140 
0141   status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_PAGEINFO_BY_OFFSET, &page_info);
0142   if (status == 0) {
0143     *size = page_info.page_info.size;
0144   }
0145 
0146   return status;
0147 }
0148 
0149 static int get_jedec_id(int fd, dev_t *dev_jedec_id)
0150 {
0151   uint32_t jedec_id;
0152   int status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_JEDEC_ID, &jedec_id);
0153 
0154   *dev_jedec_id = jedec_id;
0155 
0156   return status;
0157 }
0158 
0159 static int get_flash_type(int fd, rtems_flashdev_flash_type *flash_type)
0160 {
0161   return ioctl(fd, RTEMS_FLASHDEV_IOCTL_TYPE, flash_type);
0162 }
0163 
0164 rtems_status_code jffs2_flashdev_mount(
0165   const char *flashdev_path,
0166   const char *mount_dir,
0167   rtems_flashdev_region *region,
0168   rtems_jffs2_compressor_control *compressor_control,
0169   bool read_only
0170 )
0171 {
0172   FILE *file;
0173   int fd;
0174   int status;
0175   rtems_jffs2_mount_data *mount_data;
0176   flash_control *instance;
0177   rtems_flashdev_flash_type flash_type;
0178 
0179   file = fopen(flashdev_path, read_only ? "r" : "r+");
0180   if (file == NULL) {
0181     return RTEMS_NO_MEMORY;
0182   }
0183 
0184   fd = fileno(file);
0185   status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_REGION_SET, region);
0186   if (status) {
0187     fclose(file);
0188     return RTEMS_NOT_IMPLEMENTED;
0189   }
0190 
0191   mount_data = malloc(sizeof(*mount_data));
0192   if (mount_data == NULL) {
0193     fclose(file);
0194     return RTEMS_NO_MEMORY;
0195   }
0196   memset(mount_data, 0, sizeof(*mount_data));
0197 
0198   instance = malloc(sizeof(*instance));
0199   if (instance == NULL) {
0200     free(mount_data);
0201     fclose(file);
0202     return RTEMS_NO_MEMORY;
0203   }
0204   memset(instance, 0, sizeof(*instance));
0205 
0206   instance->handle = file;
0207   instance->mount_data = mount_data;
0208   mount_data->flash_control = &instance->super;
0209   mount_data->compressor_control = compressor_control;
0210 
0211   instance->super.read = do_read;
0212   instance->super.write = do_write;
0213   instance->super.erase = do_erase;
0214   instance->super.destroy = do_destroy;
0215 
0216   /* Get JEDEC ID, device_identifier is a 64bit dev_t */
0217   status = get_jedec_id(fd, &instance->super.device_identifier);
0218   if ( status != 0 ) {
0219     return status;
0220   }
0221 
0222   /* Set flash size from region size */
0223   instance->super.flash_size = region->size;
0224 
0225   /* Retrieve page size as sector/block size */
0226   status = get_sector_size(fd, &instance->super.block_size);
0227   if ( status != 0 ) {
0228     return status;
0229   }
0230 
0231   status = get_flash_type(fd, &flash_type);
0232   if ( status != 0 ) {
0233     return status;
0234   }
0235 
0236   /*
0237    * Write size should only be provided to JFFS2 for NAND flash since JFFS2 uses
0238    * a write size of 0 to indicate non-NAND flash to disable write buffers.
0239    */
0240   if (flash_type == RTEMS_FLASHDEV_NAND) {
0241     status = get_page_size(fd, &instance->super.write_size);
0242     if ( status != 0 ) {
0243       return status;
0244     }
0245   }
0246 
0247   status = mount(
0248     NULL,
0249     mount_dir,
0250     RTEMS_FILESYSTEM_TYPE_JFFS2,
0251     RTEMS_FILESYSTEM_READ_WRITE,
0252     mount_data
0253   );
0254   if ( status != 0 ) {
0255     return status;
0256   }
0257 
0258   return 0;
0259 }