コード例 #1
0
ファイル: mtdutils.c プロジェクト: NestorIT/recovery_twrp2.7
off_t mtd_erase_blocks(MtdWriteContext *ctx, int blocks)
{
    // Zero-pad and write any pending data to get us to a block boundary
    if (ctx->stored > 0) {
        size_t zero = ctx->partition->erase_size - ctx->stored;
        memset(ctx->buffer + ctx->stored, 0, zero);
        if (write_block(ctx, ctx->buffer)) return -1;
        ctx->stored = 0;
    }

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

    const int total = (ctx->partition->size - pos) / ctx->partition->erase_size;
    if (blocks < 0) blocks = total;
    if (blocks > total) {
        errno = ENOSPC;
        return -1;
    }

    // Erase the specified number of blocks
    while (blocks-- > 0) {
        loff_t bpos = pos;
        if (ioctl(ctx->fd, MEMGETBADBLOCK, &bpos) > 0) {
            printf("mtd: not erasing bad block at 0x%08lx\n", pos);
            pos += ctx->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 = ctx->partition->erase_size;
#ifdef RK3066
        if (rk30_zero_out(ctx->fd, pos, ctx->partition->erase_size) < 0) {
            fprintf(stderr, "mtd: erase failure at 0x%08lx\n", pos);
        }
#else
        if (ioctl(ctx->fd, MEMERASE, &erase_info) < 0) {
            printf("mtd: erase failure at 0x%08lx\n", pos);
        }
#endif
        pos += ctx->partition->erase_size;
    }

    return pos;
}
コード例 #2
0
ファイル: mtdutils.c プロジェクト: NestorIT/recovery_twrp2.7
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;
}
コード例 #3
0
static ssize_t bml_over_mtd_write_block(int fd, ssize_t erase_size, char* data)
{
    off_t pos = lseek(fd, 0, SEEK_CUR);
    if (pos == (off_t) -1) return -1;

    ssize_t size = erase_size;
    loff_t bpos = pos;
    int ret = ioctl(fd, MEMGETBADBLOCK, &bpos);
    if (ret != 0 && !(ret == -1 && errno == EOPNOTSUPP)) {
        fprintf(stderr,
                "Mapping failure: Trying to write bad block at 0x%08lx (ret %d errno %d)\n",
                pos, ret, errno);
        return -1;
    }

    struct erase_info_user erase_info;
    erase_info.start = pos;
    erase_info.length = size;
    int retry;
    for (retry = 0; retry < 2; ++retry) {
#ifdef RK3X
        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) {
            fprintf(stderr, "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) {
            fprintf(stderr, "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) {
            fprintf(stderr, "mtd: re-read error at 0x%08lx (%s)\n",
                    pos, strerror(errno));
            continue;
        }
        if (memcmp(data, verify, size) != 0) {
            fprintf(stderr, "mtd: verification error at 0x%08lx (%s)\n",
                    pos, strerror(errno));
            continue;
        }

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


    fprintf(stderr, "mtd: Block at %llx could not be properly written.\n", pos);
    // Ran out of space on the device
    errno = ENOSPC;
    return -1;
}