Am 22.09.2013 21:10 schrieb Stefan Tauner:
This fixes a SEGFAULT if a layout entry is included that addresses memory outside the current chip's address range.
Signed-off-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at
Before continuing with the other layout patches, I'd like to fix this issue (and copy the patch that fixes this also to the .7 stable branch).
Good idea.
The macros are open for discussion not only regarding naming... e.g. it might be easier to declare a macro that provides the full printf format specification for the address, '0x06" PRIx32 "' to make the resulting code more readable.
flash.h | 11 ++++++++++- flashrom.c | 11 ++++++++--- layout.c | 29 +++++++++++++++++++++++++++-- 3 files changed, 45 insertions(+), 6 deletions(-)
diff --git a/flash.h b/flash.h index 7b88477..a5033ef 100644 --- a/flash.h +++ b/flash.h @@ -45,6 +45,14 @@ typedef uintptr_t chipaddr; #define PRIxPTR_WIDTH ((int)(sizeof(uintptr_t)*2))
+/* To be used in technology-independent code. */ +#define FL_MAX_CHIPADDR (24)
This looks suspiciously like the number of address bits. It's not, and that confused me.
+#define FL_MAX_CHIPSIZE ((1<<FL_MAX_CHIPADDR)-1)
AFAICS it should be 1ULL, not 1.
+#define PRIxCHIPADDR_WIDTH ((int)(FL_MAX_CHIPADDR/4))
Incorrect rounding. If FL_MAX_CHIPADDR=23, PRIxCHIPADDR_WIDTH is 5, but it should be 6. Suggested fix: Replace FL_MAX_CHIPADDR/4 with (FL_MAX_CHIPADDR+3)/4.
+typedef uint32_t chipoff_t; /* Able to store any addressable offset within a supported flash memory. */ +typedef uint32_t chipsize_t; /* Able to store the number of bytes of any supported flash memory. */ +#define PRIxCHIPADDR PRIx32
int register_shutdown(int (*function) (void *data), void *data); void *programmer_map_flash_region(const char *descr, uintptr_t phys_addr, size_t len); void programmer_unmap_flash_region(void *virt_addr, size_t len); @@ -319,7 +327,8 @@ __attribute__((format(printf, 2, 3))); int register_include_arg(char *name); int process_include_args(void); int read_romlayout(char *name); -int handle_romentries(const struct flashctx *flash, uint8_t *oldcontents, uint8_t *newcontents); +int normalize_romentries(const struct flashctx *flash); +int build_new_image(const struct flashctx *flash, uint8_t *oldcontents, uint8_t *newcontents);
Good idea.
void layout_cleanup(void);
/* spi.c */ diff --git a/flashrom.c b/flashrom.c index 9169620..afab57c 100644 --- a/flashrom.c +++ b/flashrom.c @@ -1916,6 +1916,12 @@ int doit(struct flashctx *flash, int force, const char *filename, int read_it, goto out_nofree; }
- if (normalize_romentries(flash)) {
msg_cerr("Requested regions can not be handled. Aborting.\n");
ret = 1;
goto out_nofree;
- }
- /* Given the existence of read locks, we want to unlock for read,
*/
- erase and write.
@@ -1995,9 +2001,8 @@ int doit(struct flashctx *flash, int force, const char *filename, int read_it, } msg_cinfo("done.\n");
- // This should be moved into each flash part's code to do it
- // cleanly. This does the job.
- handle_romentries(flash, oldcontents, newcontents);
/* Build a new image taking the given layout into account. */
build_new_image(flash, oldcontents, newcontents);
// ////////////////////////////////////////////////////////////
diff --git a/layout.c b/layout.c index 86351b8..5adec67 100644 --- a/layout.c +++ b/layout.c @@ -37,7 +37,7 @@ typedef struct {
/* rom_entries store the entries specified in a layout file and associated run-time data */ static romentry_t rom_entries[MAX_ROMLAYOUT]; -static int num_rom_entries = 0; /* the number of valid rom_entries */ +static int num_rom_entries = 0; /* the number of successfully parsed rom_entries */
/* include_args holds the 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 rom_entries list. */
@@ -232,7 +232,32 @@ romentry_t *get_next_included_romentry(unsigned int start) return best_entry; }
-int handle_romentries(const struct flashctx *flash, uint8_t *oldcontents, uint8_t *newcontents) +/* Validate and - if needed - normalize layout entries. */ +int normalize_romentries(const struct flashctx *flash) +{
- chipsize_t total_size = flash->chip->total_size * 1024;
- int ret = 0;
- int i;
- for (i = 0; i < num_rom_entries; i++) {
if (rom_entries[i].start >= total_size || rom_entries[i].end >= total_size) {
If you want to do this, please make sure struct romentry has members start/end with type chipoff_t. Otherwise that check may backfire eventually.
msg_gwarn("Warning: Address range of region \"%s\" exeeds the current chip's "
"address space.\n", rom_entries[i].name);
if (rom_entries[i].included)
ret = 1;
}
if (rom_entries[i].start >= rom_entries[i].end) {
Off-by-one: If start==end, the length is 1, but this check will trigger. The check should be > instead of >=.
msg_gwarn("Warning: Size of the address range of region \"%s\" is not positive.\n",
rom_entries[i].name);
if (rom_entries[i].included)
ret = 1;
}
- }
- return ret;
+}
+int build_new_image(const struct flashctx *flash, uint8_t *oldcontents, uint8_t *newcontents) { unsigned int start = 0; romentry_t *entry;
Looks good otherwise.
Regards, Carl-Daniel