Exemplo n.º 1
0
int exfat_truncate(struct exfat* ef, struct exfat_node* node, uint64_t size)
{
	uint32_t c1 = bytes2clusters(ef, node->size);
	uint32_t c2 = bytes2clusters(ef, size);
	int rc = 0;

	if (node->references == 0 && node->parent)
		exfat_bug("no references, node changes can be lost");

	if (node->size == size)
		return 0;

	if (c1 < c2)
		rc = grow_file(ef, node, c1, c2 - c1);
	else if (c1 > c2)
		rc = shrink_file(ef, node, c1, c1 - c2);

	if (rc != 0)
		return rc;

	rc = erase_range(ef, node, node->size, size);
	if (rc != 0)
		return rc;

	exfat_update_mtime(node);
	node->size = size;
	node->flags |= EXFAT_ATTRIB_DIRTY;
	return 0;
}
Exemplo n.º 2
0
static void set_ecc(uint32_t start, uint32_t size)
{
    uint32_t i = start + 8;
    uint8_t ecc = 0;

    printf("About to erase and set ECC bits in region 0x%08x to 0x%08x\n", start, start + size);
    check_confirm();
    erase_range(start, size, true);

    printf("Programming ECC bits...\n");
    progress_init(size);
    while (i < start + size) {
        blocklevel_write(bl, i, &ecc, sizeof(ecc));
        i += 9;
        progress_tick(i - start);
    }
    progress_end();
}
Exemplo n.º 3
0
int main(int argc, char *argv[])
{
    const char *pname = argv[0];
    uint32_t address = 0, read_size = 0, write_size = 0;
    uint32_t erase_start = 0, erase_size = 0;
    bool erase = false, do_clear = false;
    bool program = false, erase_all = false, info = false, do_read = false;
    bool enable_4B = false, disable_4B = false;
    bool show_help = false, show_version = false;
    bool no_action = false, tune = false;
    char *write_file = NULL, *read_file = NULL, *part_name = NULL;
    bool ffs_toc_seen = false;
    int rc;

    while(1) {
        static struct option long_opts[] = {
            {"address",	required_argument,	NULL,	'a'},
            {"size",	required_argument,	NULL,	's'},
            {"partition",	required_argument,	NULL,	'P'},
            {"bmc",		no_argument,		NULL,	'b'},
            {"enable-4B",	no_argument,		NULL,	'4'},
            {"disable-4B",	no_argument,		NULL,	'3'},
            {"read",	required_argument,	NULL,	'r'},
            {"erase-all",	no_argument,		NULL,	'E'},
            {"erase",	no_argument,		NULL,	'e'},
            {"program",	required_argument,	NULL,	'p'},
            {"force",	no_argument,		NULL,	'f'},
            {"info",	no_argument,		NULL,	'i'},
            {"tune",	no_argument,		NULL,	't'},
            {"dummy",	no_argument,		NULL,	'd'},
            {"help",	no_argument,		NULL,	'h'},
            {"version",	no_argument,		NULL,	'v'},
            {"debug",	no_argument,		NULL,	'g'},
            {"side",	required_argument,	NULL,	'S'},
            {"toc",		required_argument,	NULL,	'T'},
            {"clear",   no_argument,        NULL,   'c'}
        };
        int c, oidx = 0;

        c = getopt_long(argc, argv, "a:s:P:r:43Eep:fdihvbtgS:T:c",
                        long_opts, &oidx);
        if (c == EOF)
            break;
        switch(c) {
        case 'a':
            address = strtoul(optarg, NULL, 0);
            break;
        case 's':
            read_size = write_size = strtoul(optarg, NULL, 0);
            break;
        case 'P':
            part_name = strdup(optarg);
            break;
        case '4':
            enable_4B = true;
            break;
        case '3':
            disable_4B = true;
            break;
        case 'r':
            do_read = true;
            read_file = strdup(optarg);
            break;
        case 'E':
            erase_all = erase = true;
            break;
        case 'e':
            erase = true;
            break;
        case 'p':
            program = true;
            write_file = strdup(optarg);
            break;
        case 'f':
            must_confirm = false;
            break;
        case 'd':
            must_confirm = false;
            dummy_run = true;
            break;
        case 'i':
            info = true;
            break;
        case 'b':
            bmc_flash = true;
            break;
        case 't':
            tune = true;
            break;
        case 'v':
            show_version = true;
            break;
        case 'h':
            show_help = show_version = true;
            break;
        case 'g':
            libflash_debug = true;
            break;
        case 'S':
            flash_side = atoi(optarg);
            break;
        case 'T':
            ffs_toc_seen = true;
            ffs_toc = strtoul(optarg, NULL, 0);
            break;
        case 'c':
            do_clear = true;
            break;
        default:
            exit(1);
        }
    }

    /* Check if we need to access the flash at all (which will
     * also tune them as a side effect
     */
    no_action = !erase && !program && !info && !do_read &&
                !enable_4B && !disable_4B && !tune && !do_clear;

    /* Nothing to do, if we didn't already, print usage */
    if (no_action && !show_version)
        show_help = show_version = true;

    if (show_version)
        print_version();
    if (show_help)
        print_help(pname);

    if (no_action)
        return 0;

    /* --enable-4B and --disable-4B are mutually exclusive */
    if (enable_4B && disable_4B) {
        fprintf(stderr, "--enable-4B and --disable-4B are mutually"
                " exclusive !\n");
        exit(1);
    }

    /* 4B not supported on BMC flash */
    if (enable_4B && bmc_flash) {
        fprintf(stderr, "--enable-4B not supported on BMC flash !\n");
        exit(1);
    }

    /* partitions not supported on BMC flash */
    if (part_name && bmc_flash) {
        fprintf(stderr, "--partition not supported on BMC flash !\n");
        exit(1);
    }

    /* part-name and erase-all make no sense together */
    if (part_name && erase_all) {
        fprintf(stderr, "--partition and --erase-all are mutually"
                " exclusive !\n");
        exit(1);
    }

    /* Read command should always come with a file */
    if (do_read && !read_file) {
        fprintf(stderr, "Read with no file specified !\n");
        exit(1);
    }

    /* Program command should always come with a file */
    if (program && !write_file) {
        fprintf(stderr, "Program with no file specified !\n");
        exit(1);
    }

    /* If both partition and address specified, error out */
    if (address && part_name) {
        fprintf(stderr, "Specify partition or address, not both !\n");
        exit(1);
    }

    if (do_clear && !part_name) {
        fprintf(stderr, "--clear only supported on a partition name\n");
        exit(1);
    }

    /* Explicitly only support two sides */
    if (flash_side != 0 && flash_side != 1) {
        fprintf(stderr, "Unexpected value for --side '%d'\n", flash_side);
        exit(1);
    }

    if (ffs_toc_seen && flash_side) {
        fprintf(stderr, "--toc and --side are exclusive");
        exit(1);
    }

    /* If file specified but not size, get size from file
     */
    if (write_file && !write_size) {
        struct stat stbuf;

        if (stat(write_file, &stbuf)) {
            perror("Failed to get file size");
            exit(1);
        }
        write_size = stbuf.st_size;
    }

    if (bmc_flash) {
        if (arch_flash_bmc(NULL, 1) == -1) {
            fprintf(stderr, "Can't switch to BMC flash on this architecture\n");
            exit(1);
        }
    }

    if (arch_flash_init(&bl, NULL, true))
        exit(1);

    on_exit(exiting, NULL);


    rc = blocklevel_get_info(bl, &fl_name,
                             &fl_total_size, &fl_erase_granule);
    if (rc) {
        fprintf(stderr, "Error %d getting flash info\n", rc);
        exit(1);
    }

    /* If -t is passed, then print a nice message */
    if (tune)
        printf("Flash and controller tuned\n");

    /* If read specified and no read_size, use flash size */
    if (do_read && !read_size && !part_name)
        read_size = fl_total_size;

    /* We have a partition specified, grab the details */
    if (part_name)
        lookup_partition(part_name);

    /* We have a partition, adjust read/write size if needed */
    if (ffsh && ffs_index >= 0) {
        uint32_t pstart, pmaxsz, pactsize;
        bool ecc;
        int rc;

        rc = ffs_part_info(ffsh, ffs_index, NULL,
                           &pstart, &pmaxsz, &pactsize, &ecc);
        if (rc) {
            fprintf(stderr,"Failed to get partition info\n");
            exit(1);
        }

        if (!ecc && do_clear) {
            fprintf(stderr, "The partition on which to do --clear "
                    "does not have ECC, are you sure?\n");
            check_confirm();
            /* Still confirm later on */
            must_confirm = true;
        }

        /* Read size is obtained from partition "actual" size */
        if (!read_size)
            read_size = pactsize;

        /* Write size is max size of partition */
        if (!write_size)
            write_size = pmaxsz;

        /* Crop write size to partition size */
        if (write_size > pmaxsz) {
            printf("WARNING: Size (%d bytes) larger than partition"
                   " (%d bytes), cropping to fit\n",
                   write_size, pmaxsz);
            write_size = pmaxsz;
        }

        /* If erasing, check partition alignment */
        if (erase && ((pstart | pmaxsz) & 0xfff)) {
            fprintf(stderr,"Partition not aligned properly\n");
            exit(1);
        }

        /* Set address */
        address = pstart;
    }

    /* Align erase boundaries */
    if (erase && !erase_all) {
        uint32_t mask = 0xfff;
        uint32_t erase_end;

        /* Dummy size for erase, will be adjusted later */
        if (!write_size)
            write_size = 1;
        erase_start = address & ~mask;
        erase_end = ((address + write_size) + mask) & ~mask;
        erase_size = erase_end - erase_start;

        if (erase_start != address || erase_size != write_size)
            fprintf(stderr, "WARNING: Erase region adjusted"
                    " to 0x%08x..0x%08x\n",
                    erase_start, erase_end);
    }

    /* Process commands */
    if (enable_4B)
        enable_4B_addresses();
    if (disable_4B)
        disable_4B_addresses();
    if (info) {
        /*
         * Don't pass through modfied TOC value if the modification was done
         * because of --size, but still respect if it came from --toc (we
         * assume the user knows what they're doing in that case)
         */
        print_flash_info(flash_side ? 0 : ffs_toc);
    }

    /* Unlock flash (PNOR only) */
    if ((erase || program || do_clear) && !bmc_flash) {
        need_relock = arch_flash_set_wrprotect(bl, false);
        if (need_relock == -1) {
            fprintf(stderr, "Architecture doesn't support write protection on flash\n");
            need_relock = 0;
            exit (1);
        }
    }
    if (do_read)
        do_read_file(read_file, address, read_size);
    if (erase_all)
        erase_chip();
    else if (erase)
        erase_range(erase_start, erase_size, program);
    if (program)
        program_file(write_file, address, write_size);
    if (do_clear)
        set_ecc(address, write_size);
    return 0;
}