aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libflash/file.c44
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;
}