static int flash_write_nand_hamming1(int mtdnum, struct img_type *img) { struct flash_description *flash = get_flash_info(); struct mtd_dev_info *mtd = &flash->mtd_info[mtdnum].mtd; int fd = img->fdin; int ofd; unsigned char *page; unsigned char code[3]; unsigned char ecc[12]; int cnt; int i, j; int len; long long imglen = 0; int page_idx = 0; int ret = EXIT_FAILURE; char mtd_device[LINESIZE]; bool rawNand = isNand(flash, mtdnum); snprintf(mtd_device, sizeof(mtd_device), "/dev/mtd%d", mtdnum); /* * Get page size */ len = mtd->min_io_size; if (!rawNand) len *= 2; imglen = img->size; page = (unsigned char *) malloc(len); if (page == NULL) { ERROR("Error opening input file"); goto out; } ofd = open(mtd_device, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG); if (ofd < 0) { ERROR("Error opening output file"); goto out_input; } if (rawNand) /* The device has to be accessed in RAW mode to fill oob area */ if (ioctl(ofd, MTDFILEMODE, (void *) MTD_FILE_MODE_RAW)) { ERROR("RAW mode access"); goto out_input; } while (imglen > 0) { cnt = read(fd, page, min(mtd->min_io_size, imglen)); if (cnt < 0) break; /* Writes has to be page aligned */ if (cnt < mtd->min_io_size) memset(page + cnt, 0xff, mtd->min_io_size - cnt); if (rawNand) for (i = 0; i < mtd->min_io_size / mtd->subpage_size; i++) { /* Obtain ECC code for sector */ ecc_sector(page + i * mtd->subpage_size, code, mtd->subpage_size); for (j = 0; j < 3; j++) ecc[i * 3 + j] = code[j]; } else /* The OneNAND has a 2-plane memory but the ROM boot * can only access one of them, so we have to double * copy each 2K page. */ memcpy(page + mtd->min_io_size, page, mtd->min_io_size); if (write(ofd, page, len) != len) { perror("Error writing to output file"); goto out_output; } if (rawNand) if (write_ecc(ofd, ecc, page_idx * mtd->min_io_size)) { perror("Error writing ECC in OOB area"); goto out_output; } page_idx++; imglen -= cnt; } if (cnt < 0) { ERROR("File I/O error on input file"); goto out_output; } TRACE("Successfully written %s to mtd %d", img->fname, mtdnum); ret = EXIT_SUCCESS; out_output: close(ofd); out_input: free(page); out: return ret; }
int main(int argc, char *argv[]) { int fd; int ofd; unsigned char *page; unsigned char code[3]; unsigned char ecc[12]; int cnt; int i, j; int len; int page_idx = 0; int ret = EXIT_FAILURE; process_options(argc, argv); flash_type = find_nand(); if (flash_type < 0) goto out; len = PAGE_SIZE; if (flash_type == ONENAND) len *= 2; page = (unsigned char *)malloc(len); if (page == NULL) { perror("Error opening input file"); goto out; } fd = open(input_file, O_RDWR); if (fd < 0) { perror("Error opening input file"); goto out_malloc; } ofd = open(output_file, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG); if (ofd < 0) { perror("Error opening output file"); goto out_input; } if (flash_type == NAND) /* The device has to be accessed in RAW mode to fill oob area */ if (ioctl(ofd, MTDFILEMODE, (void *) MTD_FILE_MODE_RAW)) { perror("RAW mode access"); goto out_input; } while ((cnt = read(fd, page, PAGE_SIZE)) > 0) { /* Writes has to be page aligned */ if (cnt < PAGE_SIZE) memset(page + cnt, 0xff, PAGE_SIZE - cnt); if (flash_type == NAND) for (i = 0; i < PAGE_SIZE / SECTOR_SIZE; i++) { /* Obtain ECC code for sector */ ecc_sector(page + i * SECTOR_SIZE, code); for (j = 0; j < 3; j++) ecc[i * 3 + j] = code[j]; } else /* The OneNAND has a 2-plane memory but the ROM boot * can only access one of them, so we have to double * copy each 2K page. */ memcpy(page + PAGE_SIZE, page, PAGE_SIZE); if (write(ofd, page, len) != len) { perror("Error writing to output file"); goto out_output; } if (flash_type == NAND) if (write_ecc(ofd, ecc, page_idx * PAGE_SIZE)) { perror("Error writing ECC in OOB area"); goto out_output; } page_idx++; } if (cnt < 0) { perror("File I/O error on input file"); goto out_output; } printf("Successfully written %s to %s\n", input_file, output_file); ret = EXIT_SUCCESS; out_output: close(ofd); out_input: close(fd); out_malloc: free(page); out: return ret; }