summaryrefslogtreecommitdiff
path: root/ubi-utils/src/libpfiflash.c
diff options
context:
space:
mode:
Diffstat (limited to 'ubi-utils/src/libpfiflash.c')
-rw-r--r--ubi-utils/src/libpfiflash.c52
1 files changed, 51 insertions, 1 deletions
diff --git a/ubi-utils/src/libpfiflash.c b/ubi-utils/src/libpfiflash.c
index 0be1f2c..4dfafea 100644
--- a/ubi-utils/src/libpfiflash.c
+++ b/ubi-utils/src/libpfiflash.c
@@ -34,11 +34,13 @@
#define __USE_GNU
#include <string.h>
#include <stdlib.h>
+#include <sys/ioctl.h>
#include <libubi.h>
#include <pfiflash.h>
#include <mtd/ubi-user.h> /* FIXME Is this ok here? */
+#include <mtd/mtd-user.h>
#include "pfiflash_error.h"
#include "ubimirror.h"
@@ -554,6 +556,45 @@ write_normal_volume(int devno, uint32_t id, size_t update_size, FILE* fp_in,
return rc;
}
+static int
+erase_mtd_region(FILE* file_p, int start, int length)
+{
+ int rc, fd;
+ erase_info_t erase;
+ mtd_info_t mtdinfo;
+ loff_t offset = start;
+ loff_t end = offset + length;
+
+ fd = fileno(file_p);
+ if (fd < 0)
+ return -PFIFLASH_ERR_MTD_ERASE;
+
+ rc = ioctl(fd, MEMGETINFO, &mtdinfo);
+ if (rc)
+ return -PFIFLASH_ERR_MTD_ERASE;
+
+ /* check for bad blocks in case of NAND flash */
+ if (mtdinfo.type == MTD_NANDFLASH) {
+ while (offset < end) {
+ rc = ioctl(fd, MEMGETBADBLOCK, &offset);
+ if (rc > 0) {
+ return -PFIFLASH_ERR_MTD_ERASE;
+ }
+
+ offset += mtdinfo.erasesize;
+ }
+ }
+
+ erase.start = start;
+ erase.length = length;
+
+ rc = ioctl(fd, MEMERASE, &erase);
+ if (rc) {
+ return -PFIFLASH_ERR_MTD_ERASE;
+ }
+
+ return rc;
+}
/**
* process_raw_volumes - writes the raw sections of the PFI data
@@ -582,7 +623,7 @@ process_raw_volumes(FILE* pfi, list_t pfi_raws, const char* rawdev,
void *i;
uint32_t crc, crc32_table[256];
size_t j, k;
- FILE* mtd;
+ FILE* mtd = NULL;
list_t ptr;
if (is_empty(pfi_raws))
@@ -639,6 +680,12 @@ process_raw_volumes(FILE* pfi, list_t pfi_raws, const char* rawdev,
}
for (j = 0; j < r->starts_size; j++) {
+ rc = erase_mtd_region(mtd, r->starts[j], r->data_size);
+ if (rc) {
+ EBUF(PFIFLASH_ERRSTR[-rc]);
+ goto err;
+ }
+
fseek(mtd, r->starts[j], SEEK_SET);
for (k = 0; k < r->data_size; k++) {
int c = fputc((int)pfi_data[k], mtd);
@@ -656,6 +703,7 @@ process_raw_volumes(FILE* pfi, list_t pfi_raws, const char* rawdev,
}
}
rc = fclose(mtd);
+ mtd = NULL;
if (rc != 0) {
rc = -PFIFLASH_ERR_MTD_CLOSE;
EBUF(PFIFLASH_ERRSTR[-rc], rawdev);
@@ -664,6 +712,8 @@ process_raw_volumes(FILE* pfi, list_t pfi_raws, const char* rawdev,
}
err:
+ if (mtd != NULL)
+ fclose(mtd);
if (pfi_data != NULL)
free(pfi_data);
return rc;