123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910 |
- /*
- * This file is part of the flashrom project.
- *
- * Copyright (C) 2005-2008 coresystems GmbH
- * (Written by Stefan Reinauer <stepan@coresystems.de> for coresystems GmbH)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <limits.h>
- #include <errno.h>
- #include <sys/stat.h>
- #include "flash.h"
- #include "fdtmap.h"
- #include "fmap.h"
- #include "libfdt.h"
- #include "layout.h"
- #include "programmer.h"
- #include "search.h"
- #if CONFIG_INTERNAL == 1
- char *mainboard_vendor = NULL;
- char *mainboard_part = NULL;
- #endif
- static int romimages = 0;
- #define MAX_ROMLAYOUT 64
- /*
- * include_args lists arguments specified at the command line with -i. They
- * must be processed at some point so that desired regions are marked as
- * "included" in the master rom_entries list.
- */
- static char *include_args[MAX_ROMLAYOUT];
- static int num_include_args = 0; /* the number of valid entries. */
- static romlayout_t rom_entries[MAX_ROMLAYOUT];
- #if CONFIG_INTERNAL == 1 /* FIXME: Move the whole block to cbtable.c? */
- static char *def_name = "DEFAULT";
- /* Return TRUE if user specifies any -i argument. */
- int specified_partition() {
- return num_include_args != 0;
- }
- int show_id(uint8_t *bios, int size, int force)
- {
- unsigned int *walk;
- unsigned int mb_part_offset, mb_vendor_offset;
- char *mb_part, *mb_vendor;
- mainboard_vendor = def_name;
- mainboard_part = def_name;
- walk = (unsigned int *)(bios + size - 0x10);
- walk--;
- if ((*walk) == 0 || ((*walk) & 0x3ff) != 0) {
- /* We might have an NVIDIA chipset BIOS which stores the ID
- * information at a different location.
- */
- walk = (unsigned int *)(bios + size - 0x80);
- walk--;
- }
- /*
- * Check if coreboot last image size is 0 or not a multiple of 1k or
- * bigger than the chip or if the pointers to vendor ID or mainboard ID
- * are outside the image of if the start of ID strings are nonsensical
- * (nonprintable and not \0).
- */
- mb_part_offset = *(walk - 1);
- mb_vendor_offset = *(walk - 2);
- if ((*walk) == 0 || ((*walk) & 0x3ff) != 0 || (*walk) > size ||
- mb_part_offset > size || mb_vendor_offset > size) {
- msg_pdbg("Flash image seems to be a legacy BIOS. "
- "Disabling coreboot-related checks.\n");
- return 0;
- }
- mb_part = (char *)(bios + size - mb_part_offset);
- mb_vendor = (char *)(bios + size - mb_vendor_offset);
- if (!isprint((unsigned char)*mb_part) ||
- !isprint((unsigned char)*mb_vendor)) {
- msg_pdbg("Flash image seems to have garbage in the ID location."
- " Disabling checks.\n");
- return 0;
- }
- msg_pdbg("coreboot last image size "
- "(not ROM size) is %d bytes.\n", *walk);
- mainboard_part = strdup(mb_part);
- mainboard_vendor = strdup(mb_vendor);
- msg_pdbg("Manufacturer: %s\n", mainboard_vendor);
- msg_pdbg("Mainboard ID: %s\n", mainboard_part);
- /*
- * If lb_vendor is not set, the coreboot table was
- * not found. Nor was -p internal:mainboard=VENDOR:PART specified.
- */
- if (!lb_vendor || !lb_part) {
- msg_pdbg("Note: If the following flash access fails, try"
- "-p internal:mainboard= <vendor>:<mainboard>.\n");
- return 0;
- }
- /* These comparisons are case insensitive to make things
- * a little less user error prone.
- */
- if (!strcasecmp(mainboard_vendor, lb_vendor) &&
- !strcasecmp(mainboard_part, lb_part)) {
- msg_pdbg("This firmware image matches this mainboard.\n");
- } else {
- if (force_boardmismatch) {
- msg_pinfo("WARNING: This firmware image does not "
- "seem to fit to this machine - forcing it.\n");
- } else {
- msg_pinfo("ERROR: Your firmware image (%s:%s) does not "
- "appear to\n"
- " be correct for the detected "
- "mainboard (%s:%s)\n\n"
- "Override with -p internal:boardmismatch="
- "force to ignore the board name in the\n"
- "firmware image or override the detected "
- "mainboard with\n"
- "-p internal:mainboard=<vendor>:<mainboard>."
- "\n\n",
- mainboard_vendor, mainboard_part, lb_vendor,
- lb_part);
- exit(1);
- }
- }
- return 0;
- }
- #endif
- #ifndef __LIBPAYLOAD__
- int read_romlayout(char *name)
- {
- FILE *romlayout;
- char tempstr[256];
- int i;
- romlayout = fopen(name, "r");
- if (!romlayout) {
- msg_gerr("ERROR: Could not open ROM layout (%s).\n",
- name);
- return -1;
- }
- while (!feof(romlayout)) {
- char *tstr1, *tstr2;
- if (romimages >= MAX_ROMLAYOUT) {
- msg_gerr("Maximum number of ROM images (%i) in layout "
- "file reached before end of layout file.\n",
- MAX_ROMLAYOUT);
- msg_gerr("Ignoring the rest of the layout file.\n");
- break;
- }
- if (2 != fscanf(romlayout, "%255s %255s\n", tempstr, rom_entries[romimages].name))
- continue;
- #if 0
- // fscanf does not like arbitrary comments like that :( later
- if (tempstr[0] == '#') {
- continue;
- }
- #endif
- tstr1 = strtok(tempstr, ":");
- tstr2 = strtok(NULL, ":");
- if (!tstr1 || !tstr2) {
- msg_gerr("Error parsing layout file.\n");
- fclose(romlayout);
- return 1;
- }
- rom_entries[romimages].start = strtol(tstr1, (char **)NULL, 16);
- rom_entries[romimages].end = strtol(tstr2, (char **)NULL, 16);
- rom_entries[romimages].included = 0;
- strcpy(rom_entries[romimages].file, "");
- romimages++;
- }
- for (i = 0; i < romimages; i++) {
- msg_gdbg("romlayout %08x - %08x named %s\n",
- rom_entries[i].start,
- rom_entries[i].end, rom_entries[i].name);
- }
- fclose(romlayout);
- return 0;
- }
- #endif
- /*
- * Invoke crossystem and parse the returned string to produce an offset
- * @search: Search information
- * @offset: Place to put offset
- * @return 0 if offset found, -1 if not
- */
- static int get_crossystem_fmap_base(struct search_info *search, off_t *offset)
- {
- char cmd[] = "crossystem fmap_base";
- FILE *fp;
- int n;
- char buf[16];
- unsigned long fmap_base;
- unsigned long from_top;
- if (!(fp = popen(cmd, "r")))
- return -1;
- n = fread(buf, 1, sizeof(buf) - 1, fp);
- fclose(fp);
- if (n < 0)
- return -1;
- buf[n] = '\0';
- if (strlen(buf) == 0)
- return -1;
- /*
- * There are 2 kinds of fmap_base returned from crossystem.
- *
- * 1. Shadow ROM/BIOS area (x86), such as 0xFFxxxxxx.
- * 2. Offset to start of flash, such as 0x00xxxxxx.
- *
- * The shadow ROM is a cached copy of the BIOS ROM which resides below
- * 4GB host/CPU memory address space on x86. The top of BIOS address
- * aligns to the last byte of address space, 0xFFFFFFFF. So to obtain
- * the ROM offset when shadow ROM is used, we subtract the fmap_base
- * from 4G minus 1.
- *
- * CPU address flash address
- * space p space
- * 0xFFFFFFFF +-------+ --- +-------+ 0x400000
- * | | ^ | | ^
- * | 4MB | | | | | from_top
- * | | v | | v
- * fmap_base--> | -fmap | ------|--fmap-|-- the offset we need.
- * ^ | | | |
- * | +-------+-------+-------+ 0x000000
- * | | |
- * | | |
- * | | |
- * | | |
- * 0x00000000 +-------+
- *
- * We'll use bit 31 to determine if the shadow BIOS area is being used.
- * This is sort of a hack, but allows us to perform sanity checking for
- * older x86-based Chrome OS platforms.
- */
- fmap_base = (unsigned long)strtoll(buf, (char **) NULL, 0);
- msg_gdbg("%s: fmap_base: %#lx, ROM size: 0x%x\n",
- __func__, fmap_base, search->flash->total_size * 1024);
- if (fmap_base & (1 << 31)) {
- from_top = 0xFFFFFFFF - fmap_base + 1;
- msg_gdbg("%s: fmap is located in shadow ROM, from_top: %#lx\n",
- __func__, from_top);
- if (from_top > search->flash->total_size * 1024)
- return -1;
- *offset = (search->flash->total_size * 1024) - from_top;
- } else {
- msg_gdbg("%s: fmap is located in physical ROM\n", __func__);
- if (fmap_base > search->flash->total_size * 1024)
- return -1;
- *offset = fmap_base;
- }
- msg_gdbg("%s: ROM offset: %#lx\n", __func__, *offset);
- return 0;
- }
- static int add_fmap_entries_from_buf(struct flashctx *flash,
- const uint8_t *buf)
- {
- struct fmap *fmap;
- int i;
- fmap = (struct fmap *)(buf);
- for (i = 0; i < fmap->nareas; i++) {
- if (romimages >= MAX_ROMLAYOUT) {
- msg_gerr("ROM image contains too many regions\n");
- return -1;
- }
- rom_entries[romimages].start = fmap->areas[i].offset;
- /*
- * Flashrom rom entries use absolute addresses. So for non-zero
- * length entries, we need to subtract 1 from offset + size to
- * determine the end address.
- */
- rom_entries[romimages].end = fmap->areas[i].offset +
- fmap->areas[i].size;
- if (fmap->areas[i].size)
- rom_entries[romimages].end--;
- memset(rom_entries[romimages].name, 0,
- sizeof(rom_entries[romimages].name));
- memcpy(rom_entries[romimages].name, fmap->areas[i].name,
- min(sizeof(rom_entries[romimages].name),
- sizeof(fmap->areas[i].name)));
- rom_entries[romimages].included = 0;
- strcpy(rom_entries[romimages].file, "");
- msg_gdbg("added fmap region \"%s\" (file=\"%s\") as %sincluded,"
- " start: 0x%08x, end: 0x%08x\n",
- rom_entries[romimages].name,
- rom_entries[romimages].file,
- rom_entries[romimages].included ? "" : "not ",
- rom_entries[romimages].start,
- rom_entries[romimages].end);
- romimages++;
- }
- return romimages;
- }
- enum found_t {
- FOUND_NONE,
- FOUND_FMAP,
- FOUND_FDTMAP,
- };
- /* returns the number of entries added, or <0 to indicate error */
- int add_fmap_entries(struct flashctx *flash)
- {
- enum found_t found = FOUND_NONE;
- int ret = -1;
- struct search_info search;
- union {
- struct fdtmap_hdr fdtmap;
- struct fmap fmap;
- } hdr;
- uint8_t *buf = NULL;
- off_t offset;
- search_init(&search, flash, sizeof(hdr));
- search.handler = get_crossystem_fmap_base;
- while (found == FOUND_NONE && !search_find_next(&search, &offset)) {
- if (search.image)
- memcpy(&hdr, search.image + offset, sizeof(hdr));
- else if (read_flash(flash, (uint8_t *)&hdr, offset,
- sizeof(hdr))) {
- msg_gdbg("[L%d] failed to read flash at offset %#lx\n",
- __LINE__, offset);
- return -1;
- }
- ret = fmap_find(flash, &hdr.fmap, offset, &buf);
- if (ret == 1) {
- found = FOUND_FMAP;
- }
- #ifdef CONFIG_FDTMAP
- if (ret == 0) {
- ret = fdtmap_find(flash, &hdr.fdtmap, offset, &buf);
- if (ret == 1)
- found = FOUND_FDTMAP;
- }
- #endif
- if (ret < 0)
- return ret;
- }
- switch (found) {
- #ifdef CONFIG_FDTMAP
- case FOUND_FDTMAP:
- /* It looks valid, so use it */
- romimages = fdtmap_add_entries_from_buf(buf, rom_entries,
- MAX_ROMLAYOUT);
- break;
- #endif
- case FOUND_FMAP:
- romimages = add_fmap_entries_from_buf(flash, buf);
- break;
- default:
- msg_gdbg("%s: no fmap present\n", __func__);
- }
- if (buf)
- free(buf);
- search_free(&search);
- return romimages;
- }
- int get_num_include_args(void) {
- return num_include_args;
- }
- /* register an include argument (-i) for later processing */
- int register_include_arg(char *name)
- {
- if (num_include_args >= MAX_ROMLAYOUT) {
- msg_gerr("too many regions included\n");
- return -1;
- }
- include_args[num_include_args] = name;
- num_include_args++;
- return num_include_args;
- }
- int find_romentry(char *name)
- {
- int i;
- char *file = NULL;
- char *has_colon;
- if (!romimages)
- return -1;
- /* -i <image>[:<file>] */
- has_colon = strchr(name, ':');
- if (strtok(name, ":")) {
- file = strtok(NULL, "");
- if (has_colon && file == NULL) {
- msg_gerr("Missing filename parameter in %s\n", name);
- return -1;
- }
- }
- msg_gdbg("Looking for \"%s\" (file=\"%s\")... ",
- name, file ? file : "<not specified>");
- for (i = 0; i < romimages; i++) {
- if (!strcmp(rom_entries[i].name, name)) {
- rom_entries[i].included = 1;
- snprintf(rom_entries[i].file,
- sizeof(rom_entries[i].file),
- "%s", file ? file : "");
- msg_gdbg("found.\n");
- return i;
- }
- }
- msg_gdbg("not found.\n"); // Not found. Error.
- return -1;
- }
- int fill_romentry(romlayout_t *entry, int n)
- {
- if (!entry)
- return 1;
- memcpy(entry, &rom_entries[n], sizeof(*entry));
- return 0;
- }
- /*
- * num_include_files - count filenames used with -i args
- *
- * This function is intended to help command syntax parser determine if
- * operations such as read and write require a file as an argument. This can
- * be used with get_num_include_args() to determine if all -i args have
- * filenames.
- *
- * returns number of filenames supplied with -i args
- */
- int num_include_files(void)
- {
- int i, count = 0;
- for (i = 0; i < get_num_include_args(); i++) {
- if (strchr(include_args[i], ':'))
- count++;
- }
- return count;
- }
- /*
- * process_include_args - process -i arguments
- *
- * returns 0 to indicate success, <0 to indicate failure
- */
- int process_include_args() {
- int i;
- for (i = 0; i < num_include_args; i++) {
- if (include_args[i]) {
- /* User has specified the area name, but no layout file
- * is loaded, and no fmap is stored in BIOS.
- * Return error. */
- if (!romimages) {
- msg_gerr("No layout info is available.\n");
- return -1;
- }
- if (find_romentry(include_args[i]) < 0) {
- msg_gerr("Invalid entry specified: %s\n",
- include_args[i]);
- return -1;
- }
- } else {
- break;
- }
- }
- return 0;
- }
- romlayout_t *get_next_included_romentry(unsigned int start)
- {
- int i;
- unsigned int best_start = UINT_MAX;
- romlayout_t *best_entry = NULL;
- romlayout_t *cur;
- /* First come, first serve for overlapping regions. */
- for (i = 0; i < romimages; i++) {
- cur = &rom_entries[i];
- if (!cur->included)
- continue;
- /* Already past the current entry? */
- if (start > cur->end)
- continue;
- /* Inside the current entry? */
- if (start >= cur->start)
- return cur;
- /* Entry begins after start. */
- if (best_start > cur->start) {
- best_start = cur->start;
- best_entry = cur;
- }
- }
- return best_entry;
- }
- /* returns boolean 1 if regions overlap, 0 otherwise */
- int included_regions_overlap()
- {
- int i;
- int overlap_detected = 0;
- for (i = 0; i < romimages; i++) {
- int j;
- if (!rom_entries[i].included)
- continue;
- for (j = 0; j < romimages; j++) {
- if (!rom_entries[j].included)
- continue;
- if (i == j)
- continue;
- if (rom_entries[i].start > rom_entries[j].end)
- continue;
- if (rom_entries[i].end < rom_entries[j].start)
- continue;
- msg_gdbg("Regions %s [0x%08x-0x%08x] and "
- "%s [0x%08x-0x%08x] overlap\n",
- rom_entries[i].name, rom_entries[i].start,
- rom_entries[i].end, rom_entries[j].name,
- rom_entries[j].start, rom_entries[j].end);
- overlap_detected = 1;
- goto out;
- }
- }
- out:
- return overlap_detected;
- }
- static int read_content_from_file(romlayout_t *entry, uint8_t *newcontents) {
- char *file;
- FILE *fp;
- int len;
- /* If file name is specified for this partition, read file
- * content to overwrite. */
- file = entry->file;
- len = entry->end - entry->start + 1;
- if (file[0]) {
- int numbytes;
- struct stat s;
- if (stat(file, &s) < 0) {
- msg_gerr("Cannot stat file %s: %s.\n",
- file, strerror(errno));
- return -1;
- }
- if (s.st_size > len) {
- msg_gerr("File %s is %d bytes, region %s is %d bytes.\n"
- , file, (int)s.st_size,
- entry->name, len);
- return -1;
- }
- if ((fp = fopen(file, "rb")) == NULL) {
- perror(file);
- return -1;
- }
- numbytes = fread(newcontents + entry->start,
- 1, s.st_size, fp);
- fclose(fp);
- if (numbytes == -1) {
- perror(file);
- return -1;
- }
- }
- return 0;
- }
- int handle_romentries(struct flashctx *flash, uint8_t *oldcontents, uint8_t *newcontents)
- {
- unsigned int start = 0;
- romlayout_t *entry;
- unsigned int size = flash->total_size * 1024;
- /* If no regions were specified for inclusion, assume
- * that the user wants to write the complete new image.
- */
- if (num_include_args == 0)
- return 0;
- /* Non-included romentries are ignored.
- * The union of all included romentries is used from the new image.
- */
- while (start < size) {
- entry = get_next_included_romentry(start);
- /* No more romentries for remaining region? */
- if (!entry) {
- memcpy(newcontents + start, oldcontents + start,
- size - start);
- break;
- }
- if (entry->start > size) {
- msg_gerr("Layout entry \"%s\" begins beyond ROM size.\n",
- entry->name);
- return 1;
- } else if (entry->end > (size - 1)) {
- msg_gerr("Layout entry \"%s\" ends beyond ROM size.\n",
- entry->name);
- return 1;
- }
- if (entry->start > entry->end) {
- msg_gerr("Layout entry \"%s\" has an invalid range.\n",
- entry->name);
- return 1;
- }
- /* For non-included region, copy from old content. */
- if (entry->start > start)
- memcpy(newcontents + start, oldcontents + start,
- entry->start - start);
- /* For included region, copy from file if specified. */
- if (read_content_from_file(entry, newcontents) < 0) return -1;
- /* Skip to location after current romentry. */
- start = entry->end + 1;
- /* Catch overflow. */
- if (!start)
- break;
- }
- return 0;
- }
- static int write_content_to_file(romlayout_t *entry, uint8_t *buf) {
- char *file;
- FILE *fp;
- int len = entry->end - entry->start + 1;
- file = entry->file;
- if (file[0]) { /* save to file if name is specified. */
- int numbytes;
- if ((fp = fopen(file, "wb")) == NULL) {
- perror(file);
- return -1;
- }
- numbytes = fwrite(buf + entry->start, 1, len, fp);
- fclose(fp);
- if (numbytes != len) {
- perror(file);
- return -1;
- }
- }
- return 0;
- }
- /* sets required_erase_size (global variable), returns 0 if successful */
- static int set_required_erase_size(struct flashctx *flash)
- {
- int i, erase_size_found = 0;
- /*
- * Find eraseable block size for read alignment.
- * FIXME: This assumes the smallest block erase size is useable
- * by erase_and_write_flash().
- */
- required_erase_size = ~0;
- for (i = 0; i < NUM_ERASEFUNCTIONS; i++) {
- struct block_eraser eraser = flash->block_erasers[i];
- int j;
- for (j = 0; j < NUM_ERASEREGIONS; j++) {
- unsigned int size = eraser.eraseblocks[j].size;
- if (size && (size < required_erase_size)) {
- required_erase_size = size;
- erase_size_found = 1;
- }
- }
- }
- /* likely an error in flashchips[] */
- if (!erase_size_found) {
- msg_cerr("%s: No usable erase size found.\n", __func__);
- return -1;
- }
- return 0;
- }
- /* Reads flash content specified with -i argument into *buf. */
- int handle_partial_read(
- struct flashctx *flash,
- uint8_t *buf,
- int (*read) (struct flashctx *flash, uint8_t *buf,
- unsigned int start, unsigned int len),
- int write_to_file) {
- int i, count = 0;
- /* If no regions were specified for inclusion, assume
- * that the user wants to read the complete image.
- */
- if (num_include_args == 0)
- return 0;
- if (set_required_erase_size(flash))
- return -1;
- for (i = 0; i < romimages; i++) {
- unsigned int start, len, start_align, len_align;
- if (!rom_entries[i].included)
- continue;
- /* round down to nearest eraseable block boundary */
- start_align = rom_entries[i].start % required_erase_size;
- start = rom_entries[i].start - start_align;
- /* round up to nearest eraseable block boundary */
- len = rom_entries[i].end - start + 1;
- len_align = len % required_erase_size;
- if (len_align)
- len = len + required_erase_size - len_align;
- if (start_align || len_align) {
- msg_gdbg("\n%s: Re-aligned partial read due to "
- "eraseable block size requirement:\n"
- "\trom_entries[%d].start: 0x%06x, len: 0x%06x, "
- "aligned start: 0x%06x, len: 0x%06x\n",
- __func__, i, rom_entries[i].start,
- rom_entries[i].end - rom_entries[i].start + 1,
- start, len);
- }
- if (read(flash, buf + start, start, len)) {
- msg_perr("flash partial read failed.");
- return -1;
- }
- /* If file is specified, write this partition to file. */
- if (write_to_file) {
- if (write_content_to_file(&rom_entries[i], buf) < 0)
- return -1;
- }
- count++;
- }
- return count;
- }
- /* Instead of verifying the whole chip, this functions only verifies those
- * content in specified partitions (-i).
- */
- int handle_partial_verify(
- struct flashctx *flash,
- uint8_t *buf,
- int (*verify) (struct flashctx *flash, uint8_t *buf,
- unsigned int start, unsigned int len, const char *message)) {
- int i;
- /* If no regions were specified for inclusion, assume
- * that the user wants to read the complete image.
- */
- if (num_include_args == 0)
- return 0;
- if (set_required_erase_size(flash))
- return -1;
- /* Walk through the table and write content to file for those included
- * partition. */
- for (i = 0; i < romimages; i++) {
- unsigned int start, len, start_align, len_align;
- if (!rom_entries[i].included)
- continue;
- /* round down to nearest eraseable block boundary */
- start_align = rom_entries[i].start % required_erase_size;
- start = rom_entries[i].start - start_align;
- /* round up to nearest eraseable block boundary */
- len = rom_entries[i].end - start + 1;
- len_align = len % required_erase_size;
- if (len_align)
- len = len + required_erase_size - len_align;
- if (start_align || len_align) {
- msg_gdbg("\n%s: Re-aligned partial verify due to "
- "eraseable block size requirement:\n"
- "\trom_entries[%d].start: 0x%06x, len: 0x%06x, "
- "aligned start: 0x%06x, len: 0x%06x\n",
- __func__, i, rom_entries[i].start,
- rom_entries[i].end -
- rom_entries[i].start + 1,
- start, len);
- }
- /* read content from flash. */
- if (verify(flash, buf + start, start, len, NULL)) {
- msg_perr("flash partial verify failed.");
- return -1;
- }
- }
- return 0;
- }
- int extract_regions(struct flashctx *flash)
- {
- unsigned long size = flash->total_size * 1024;
- unsigned char *buf = calloc(size, sizeof(char));
- int i, ret = 0;
- if (!buf) {
- msg_gerr("Memory allocation failed!\n");
- msg_cinfo("FAILED.\n");
- return 1;
- }
- msg_cinfo("Reading flash... ");
- if (read_flash(flash, buf, 0, size)) {
- msg_cerr("Read operation failed!\n");
- ret = 1;
- goto out_free;
- }
- msg_gdbg("Extracting %d images\n", romimages);
- for (i = 0; !ret && i < romimages; i++) {
- romlayout_t *region = &rom_entries[i];
- char fname[256];
- char *from, *to;
- unsigned long region_size;
- for (to = fname, from = region->name; *from; from++, to++) {
- if (*from == ' ')
- *to = '_';
- else
- *to = *from;
- }
- *to = '\0';
- msg_gdbg("dumping region %s to %s\n", region->name,
- fname);
- region_size = region->end - region->start + 1;
- ret = write_buf_to_file(buf + region->start, region_size,
- fname);
- }
- out_free:
- free(buf);
- if (ret)
- msg_cerr("FAILED.");
- else
- msg_cdbg("done.");
- return ret;
- }
|