示例#1
0
static int write_block(MtdWriteContext *ctx, const char *data)
{
    const MtdPartition *partition = ctx->partition;
    int fd = ctx->fd;

    off_t pos = lseek(fd, 0, SEEK_CUR);
    if (pos == (off_t) -1) return 1;

    ssize_t size = partition->erase_size;

    char *verify = malloc(size);
    if (verify == NULL)
        return 1;

    while (pos + size <= (int) partition->size) {
        loff_t bpos = pos;
        int ret = ioctl(fd, MEMGETBADBLOCK, &bpos);
        if (ret != 0 && !(ret == -1 && errno == EOPNOTSUPP)) {
            add_bad_block_offset(ctx, pos);
            fprintf(stderr,
                    "mtd: not writing bad block at 0x%08lx (ret %d errno %d)\n",
                    pos, ret, errno);
            pos += partition->erase_size;
            continue;  // Don't try to erase known factory-bad blocks.
        }

        struct erase_info_user erase_info;
        erase_info.start = pos;
        erase_info.length = size;
        int retry;
        for (retry = 0; retry < 2; ++retry) {
#ifdef RK3066
            if (rk30_zero_out(fd, pos, size) < 0) {
                fprintf(stderr, "mtd: erase failure at 0x%08lx (%s)\n",
                        pos, strerror(errno));
                continue;
            }
#else
            if (ioctl(fd, MEMERASE, &erase_info) < 0) {
                printf("mtd: erase failure at 0x%08lx (%s)\n",
                        pos, strerror(errno));
                continue;
            }
#endif
            if (lseek(fd, pos, SEEK_SET) != pos ||
                write(fd, data, size) != size) {
                printf("mtd: write error at 0x%08lx (%s)\n",
                        pos, strerror(errno));
            }

            char verify[size];
            if (lseek(fd, pos, SEEK_SET) != pos ||
                read(fd, verify, size) != size) {
                printf("mtd: re-read error at 0x%08lx (%s)\n",
                        pos, strerror(errno));
                continue;
            }
            if (memcmp(data, verify, size) != 0) {
                printf("mtd: verification error at 0x%08lx (%s)\n",
                        pos, strerror(errno));
                continue;
            }

            if (retry > 0) {
                printf("mtd: wrote block after %d retries\n", retry);
            }
            printf("mtd: successfully wrote block at %lx\n", pos);
            free(verify);
            return 0;  // Success!
        }

        // Try to erase it once more as we give up on this block
        add_bad_block_offset(ctx, pos);
        printf("mtd: skipping write block at 0x%08lx\n", pos);
#ifdef RK3066
        rk30_zero_out(fd, pos, size);
#else

        ioctl(fd, MEMERASE, &erase_info);
#endif
        pos += partition->erase_size;
    }

    free(verify);

    // Ran out of space on the device
    errno = ENOSPC;
    return -1;
}
示例#2
0
int mtd_write_block_ex(MtdWriteContext *ctx, const char *data, off64_t addr)
{
    const MtdPartition *partition = ctx->partition;
    int fd = ctx->fd;

    off64_t pos = lseek64(fd, addr, SEEK_SET);
    if (pos == (off64_t) -1) return 1;

    fprintf(stdout, "[%s] addr=0x%X, pos=0x%X, erase=0x%X\n", __func__, (int) addr, (int) pos, partition->erase_size);

    ssize_t size = partition->erase_size;
    while (pos + size <= (int) partition->size) {
        off64_t bpos = pos;
        if (ioctl(fd, MEMGETBADBLOCK, &bpos) > 0) {
            add_bad_block_offset(ctx, pos);
            fprintf(stderr, "mtd: not writing bad block at 0x%08llx\n", pos);
            pos += partition->erase_size;
            continue;  // Don't try to erase known factory-bad blocks.
        }

        struct erase_info_user erase_info;
        erase_info.start = pos;
        erase_info.length = size;
        int retry;
        for (retry = 0; retry < 2; ++retry) {
            fprintf(stdout, "[%s] erase\n", __func__);
            if (ioctl(fd, MEMERASE, &erase_info) < 0) {
                fprintf(stderr, "mtd: erase failure at 0x%08llx (%s)\n",
                        pos, strerror(errno));
                continue;
            }
            fprintf(stdout, "[%s] write\n", __func__);
            if (lseek64(fd, pos, SEEK_SET) != pos ||
                write(fd, data, size) != size) {
                fprintf(stderr, "mtd: write error at 0x%08llx (%s)\n",
                        pos, strerror(errno));
            }

            char verify[size];
            fprintf(stdout, "[%s] read back\n", __func__);
            if (lseek64(fd, pos, SEEK_SET) != pos ||
                read(fd, verify, size) != size) {
                fprintf(stderr, "mtd: re-read error at 0x%08llx (%s)\n",
                        pos, strerror(errno));
                continue;
            }
            fprintf(stdout, "[%s] compare : %X %X %X %X %X %X %X %X\n", __func__,
                    verify[0], verify[1], verify[2], verify[3],
                    verify[4], verify[5], verify[6], verify[7]);
            if (memcmp(data, verify, size) != 0) {
                fprintf(stderr, "mtd: verification error at 0x%08llx (%s)\n",
                        pos, strerror(errno));
                continue;
            }

            if (retry > 0) {
                fprintf(stderr, "mtd: wrote block after %d retries\n", retry);
            }
            return 0;  // Success!
        }

        fprintf(stdout, "[%s] write next\n", __func__);

        // Try to erase it once more as we give up on this block
        add_bad_block_offset(ctx, pos);
        fprintf(stderr, "mtd: skipping write block at 0x%08llx\n", pos);
        ioctl(fd, MEMERASE, &erase_info);
        pos += partition->erase_size;
    }

    // Ran out of space on the device
    errno = ENOSPC;
    return -1;
}