diff options
-rw-r--r-- | libflash/file.c | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/libflash/file.c b/libflash/file.c index 5f074cf..8d1ed02 100644 --- a/libflash/file.c +++ b/libflash/file.c @@ -15,6 +15,7 @@ */ #define _GNU_SOURCE #include <errno.h> +#include <inttypes.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -130,13 +131,44 @@ static int file_erase(struct blocklevel_device *bl, uint64_t dst, uint64_t len) static int mtd_erase(struct blocklevel_device *bl, uint64_t dst, uint64_t len) { struct file_data *file_data = container_of(bl, struct file_data, bl); - struct erase_info_user64 erase_info = { - .start = dst, - .length = len - }; + int err; - if (ioctl(file_data->fd, MEMERASE64, &erase_info) == -1) - return FLASH_ERR_PARM_ERROR; + FL_DBG("%s: dst: 0x%" PRIx64 ", len: 0x%" PRIx64 "\n", __func__, dst, len); + + /* + * Some kernels that pflash supports do not know about the 64bit + * version of the ioctl() therefore we'll just use the 32bit (which + * should always be supported...) unless we MUST use the 64bit and + * then lets just hope the kernel knows how to deal with it. If it + * is unsupported the ioctl() will fail and we'll report that - + * there is no other option. + */ + if (dst > UINT_MAX || len > UINT_MAX) { + struct erase_info_user64 erase_info = { + .start = dst, + .length = len + }; + + if (ioctl(file_data->fd, MEMERASE64, &erase_info) == -1) { + err = errno; + if (err == 25) /* Kernel doesn't do 64bit MTD erase ioctl() */ + FL_DBG("Attempted a 64bit erase on a kernel which doesn't support it\n"); + FL_ERR("%s: IOCTL to kernel failed! %s\n", __func__, strerror(err)); + errno = err; + return FLASH_ERR_PARM_ERROR; + } + } else { + struct erase_info_user erase_info = { + .start = dst, + .length = len + }; + if (ioctl(file_data->fd, MEMERASE, &erase_info) == -1) { + err = errno; + FL_ERR("%s: IOCTL to kernel failed! %s\n", __func__, strerror(err)); + errno = err; + return FLASH_ERR_PARM_ERROR; + } + } return 0; } |