Signed-off-by: Stefan Tauner <[email protected]>
---
 flashrom.8.tmpl |  9 ++++++++-
 layout.c        | 57 +++++++++++++++++++++++++++++++++++++++++++--------------
 2 files changed, 51 insertions(+), 15 deletions(-)

diff --git a/flashrom.8.tmpl b/flashrom.8.tmpl
index 06282f6..765d7f6 100644
--- a/flashrom.8.tmpl
+++ b/flashrom.8.tmpl
@@ -222,7 +222,14 @@ a region). One entry per line is allowed with the 
following syntax:
 .sp
 .BR "startaddr " "and " "endaddr "
 are addresses within the ROM image representing the flash ROM contents. They 
are interpreted in the 'usual' form
-i.e.\ a leading 0 means octal, leading 0x or 0X means hexadecimal, everything 
else is just decimal.
+i.e.\ a leading 0 means octal, leading 0x or 0X means hexadecimal, everything 
else is just decimal. Negative
+numbers are interpreted as addresses aligned to the top of the current chip's 
address space, for example
+.sp
+  0:-0 "whole chip"
+.sp
+will always describe the complete flash space no matter which chip is used. 
This syntax is useful for specifying
+"the top 1MB" (-0x100000:-0) etc.
+.sp
 .BR "regionname " "is the name for the region from " "startaddr " "to " 
"endaddr " "(both addresses included)."
 If the name contains spaces it has to be written in double quotes, or else 
only the part before the first space
 will be used.
diff --git a/layout.c b/layout.c
index 6150e7e..d94cbe0 100644
--- a/layout.c
+++ b/layout.c
@@ -37,6 +37,8 @@
 typedef struct {
        chipoff_t start;
        chipoff_t end;
+       bool start_topalign;
+       bool end_topalign;
        bool included;
        char *name;
        char *file;
@@ -146,14 +148,15 @@ static int parse_entry(char *file_name, unsigned int 
linecnt, char *buf, romentr
                         "Could not convert start address in \"%s\".\n", 
file_name, linecnt, buf);
                return -1;
        }
-       if (tmp_addr < 0 || tmp_addr > FL_MAX_CHIPADDR) {
+       bool start_topalign = (tmp_str[0] == '-');
+       if (llabs(tmp_addr) > FL_MAX_CHIPADDR) {
                msg_gerr("Error parsing version 2 layout entry in file \"%s\" 
at line %d:\n"
                         "Start address (%s0x%llx) in \"%s\" is beyond the 
supported range (max 0x%"
-                        PRIxCHIPADDR ").\n", file_name, linecnt, (tmp_addr < 
0) ? "-" : "",
+                        PRIxCHIPADDR ").\n", file_name, linecnt, 
start_topalign ? "-" : "",
                         llabs(tmp_addr), buf, FL_MAX_CHIPADDR);
                return -1;
        }
-       chipoff_t start = (chipoff_t)tmp_addr;
+       chipoff_t start = (chipoff_t)llabs(tmp_addr);
 
        tmp_str = endptr + strspn(endptr, WHITESPACE_CHARS);
        if (*tmp_str != ':') {
@@ -172,14 +175,15 @@ static int parse_entry(char *file_name, unsigned int 
linecnt, char *buf, romentr
                         "Could not convert end address in \"%s\".\n", 
file_name, linecnt, buf);
                return -1;
        }
-       if (tmp_addr < 0 || tmp_addr > FL_MAX_CHIPADDR) {
+       bool end_topalign = (tmp_str[0] == '-');
+       if (llabs(tmp_addr) > FL_MAX_CHIPADDR) {
                msg_gerr("Error parsing version 2 layout entry in file \"%s\" 
at line %d:\n"
                         "End address (%s0x%llx) in \"%s\" is beyond the 
supported range (max 0x%"
-                        PRIxCHIPADDR ").\n", file_name, linecnt, (tmp_addr < 
0) ? "-" : "",
+                        PRIxCHIPADDR ").\n", file_name, linecnt, end_topalign 
? "-" : "",
                         llabs(tmp_addr), buf, FL_MAX_CHIPADDR);
                return -1;
        }
-       chipoff_t end = (chipoff_t)tmp_addr;
+       chipoff_t end = (chipoff_t)llabs(tmp_addr);
 
        size_t skip = strspn(endptr, WHITESPACE_CHARS);
        if (skip == 0) {
@@ -197,10 +201,15 @@ static int parse_entry(char *file_name, unsigned int 
linecnt, char *buf, romentr
                return -1;
        }
 
-       msg_gdbg2("Parsed entry: 0x%" PRIxCHIPADDR " - 0x%" PRIxCHIPADDR " 
named \"%s\"\n",
-                 start, end, tmp_str);
+       msg_gdbg2("Parsed entry: 0x%" PRIxCHIPADDR " (%s) : 0x%" PRIxCHIPADDR " 
(%s) named \"%s\"\n",
+                 start, start_topalign ? "top-aligned" : "bottom-aligned",
+                 end, end_topalign ? "top-aligned" : "bottom-aligned", 
tmp_str);
 
-       if (start >= end) {
+       /* We can only check address ranges if the chip size is available in 
case one address is relative to
+        * the top and the other to the bottom. But if they are both relative 
to the same end we can without
+        * knowing the complete size. This allows us to bail out before 
probing. */
+       if ((!start_topalign && !end_topalign && start > end) ||
+           (start_topalign && end_topalign && start < end)) {
                msg_gerr("Error parsing version 2 layout entry in file \"%s\" 
at line %d:\n"
                         "Length of region \"%s\" is not positive.\n", 
file_name, linecnt, tmp_str);
                return -1;
@@ -218,6 +227,7 @@ static int parse_entry(char *file_name, unsigned int 
linecnt, char *buf, romentr
                          "Region name \"%s\" is not followed by white space 
only.\n",
                          file_name, linecnt, tmp_str);
 
+
        if (entry != NULL) {
                entry->name = strdup(tmp_str);
                if (entry->name == NULL) {
@@ -228,6 +238,8 @@ static int parse_entry(char *file_name, unsigned int 
linecnt, char *buf, romentr
                entry->start = start;
                entry->end = end;
                entry->included = 0;
+               entry->start_topalign = start_topalign;
+               entry->end_topalign = end_topalign;
                entry->file = NULL;
        }
        return 0;
@@ -496,15 +508,32 @@ int normalize_romentries(const struct flashctx *flash)
 
        int i;
        for (i = 0; i < num_rom_entries; i++) {
-               if (rom_entries[i].start >= total_size || rom_entries[i].end >= 
total_size) {
+               romentry_t *cur = &rom_entries[i];
+               /* Normalize top-aligned address. */
+               if (cur->start_topalign || cur->end_topalign) {
+                       if (cur->start_topalign) {
+                               cur->start = total_size - cur->start - 1;
+                               cur->start_topalign = 0;
+                       }
+
+                       if (cur->end_topalign) {
+                               cur->end = total_size - cur->end - 1;
+                               cur->end_topalign = 0;
+                       }
+
+                       msg_gspew("Normalized entry %d \"%s\": 0x%" 
PRIxCHIPADDR " - 0x%" PRIxCHIPADDR "\n",
+                                 i, cur->name, cur->start, cur->end);
+               }
+
+               if (cur->start >= total_size || cur->end >= total_size) {
                        msg_gwarn("Warning: Address range of region \"%s\" 
exceeds the current chip's "
-                                 "address space.\n", rom_entries[i].name);
-                       if (rom_entries[i].included)
+                                 "address space.\n", cur->name);
+                       if (cur->included)
                                ret = 1;
                }
-               if (rom_entries[i].start > rom_entries[i].end) {
+               if (cur->start > cur->end) {
                        msg_gerr("Error: Size of the address range of region 
\"%s\" is not positive.\n",
-                                 rom_entries[i].name);
+                                 cur->name);
                        ret = 1;
                }
        }
-- 
Kind regards, Stefan Tauner


_______________________________________________
flashrom mailing list
[email protected]
http://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to