diff options
author | Randall Spangler <rspangler@chromium.org> | 2012-05-07 16:24:13 -0700 |
---|---|---|
committer | Randall Spangler <rspangler@chromium.org> | 2012-05-07 16:26:43 -0700 |
commit | cbdd518422ad794b6bf660bc85aff29edf9bdbc2 (patch) | |
tree | e4473ad508dfa2d766e1de4b8726ed348f3e7562 | |
parent | d01657060e33bd08b7b544804e1698b0bf4165c0 (diff) | |
download | chrome-ec-cbdd518422ad794b6bf660bc85aff29edf9bdbc2.tar.gz |
Clean up sysjump struct parsing and add memmove()
Signed-off-by: Randall Spangler <rspangler@chromium.org>
BUG=chrome-os-partner:9447
TEST=update from old EC 517 to this one
Change-Id: I275b5bf6c4ae1ab6e0c0a05cf9260314d644c79b
-rw-r--r-- | chip/lm4/power_button.c | 2 | ||||
-rw-r--r-- | common/system_common.c | 68 | ||||
-rw-r--r-- | common/util.c | 21 | ||||
-rw-r--r-- | include/util.h | 1 |
4 files changed, 51 insertions, 41 deletions
diff --git a/chip/lm4/power_button.c b/chip/lm4/power_button.c index f6597d30d5..b2841c77b1 100644 --- a/chip/lm4/power_button.c +++ b/chip/lm4/power_button.c @@ -93,6 +93,8 @@ static void update_other_switches(void) *memmap_switches &= ~EC_LPC_SWITCH_DEDICATED_RECOVERY; /* Was this a reboot requesting recovery? */ + /* TODO: should use a different flag, not the dedicated recovery + * switch flag! */ if (system_get_recovery_required()) *memmap_switches |= EC_LPC_SWITCH_DEDICATED_RECOVERY; diff --git a/common/system_common.c b/common/system_common.c index 793bdaf263..d429780aaa 100644 --- a/common/system_common.c +++ b/common/system_common.c @@ -31,14 +31,15 @@ struct jump_tag { * images. */ #define JUMP_DATA_MAGIC 0x706d754a /* "Jump" */ #define JUMP_DATA_VERSION 3 +#define JUMP_DATA_SIZE_V2 16 /* Size of version 2 jump data struct */ struct jump_data { /* Add new fields to the _start_ of the struct, since we copy it to the * _end_ of RAM between images. This way, the magic number will always * be the last word in RAM regardless of how many fields are added. */ /* Fields from version 3 */ - uint8_t recovery_required; /* signal recovery mode to BIOS */ - int header_size; /* Header size to correctly point to jump tags. */ + uint8_t recovery_required; /* Signal recovery mode to BIOS */ + int struct_size; /* Size of struct jump_data */ /* Fields from version 2 */ int jump_tag_total; /* Total size of all jump tags */ @@ -56,13 +57,14 @@ static struct jump_data * const jdata = (struct jump_data *)(CONFIG_RAM_BASE + CONFIG_RAM_SIZE - sizeof(struct jump_data)); +static const char * const image_names[] = {"unknown", "RO", "A", "B"}; static enum system_reset_cause_t reset_cause = SYSTEM_RESET_UNKNOWN; static int jumped_to_image; int system_usable_ram_end(void) { - /* Leave space at the end of RAM for jump data. + /* Leave space at the end of RAM for jump data and tags. * * Note that jump_tag_total is 0 on a reboot, so we have the maximum * amount of RAM available on a reboot; we only lose space for stored @@ -196,9 +198,8 @@ int system_unsafe_to_overwrite(uint32_t offset, uint32_t size) { const char *system_get_image_copy_string(void) { - static const char * const copy_descs[] = {"unknown", "RO", "A", "B"}; int copy = system_get_image_copy(); - return copy < ARRAY_SIZE(copy_descs) ? copy_descs[copy] : "?"; + return copy < ARRAY_SIZE(image_names) ? image_names[copy] : "?"; } @@ -222,7 +223,7 @@ static void jump_to_image(uint32_t init_addr, jdata->version = JUMP_DATA_VERSION; jdata->reset_cause = reset_cause; jdata->jump_tag_total = 0; /* Reset tags */ - jdata->header_size = sizeof(struct jump_data); + jdata->struct_size = sizeof(struct jump_data); /* Call other hooks; these may add tags */ hook_notify(HOOK_SYSJUMP, 0); @@ -250,13 +251,6 @@ static uint32_t get_base(enum system_image_copy_t copy) } -static const char * const image_names[] = { - "Unknown", - "RO", - "A", - "B" -}; - int system_run_image_copy(enum system_image_copy_t copy, int recovery_required) { @@ -330,37 +324,28 @@ int system_common_pre_init(void) if (jdata->magic == JUMP_DATA_MAGIC && jdata->version >= 1 && reset_cause == SYSTEM_RESET_SOFT_WARM) { - int jtag_total; /* #byte of jump tags */ - int delta; /* delta of header size */ - uint8_t *jtag; /* point to _real_ start of jump tags */ + int delta; /* Change in jump data struct size between the + * previous image and this one. */ /* Yes, we jumped to this image */ jumped_to_image = 1; /* Overwrite the reset cause with the real one */ reset_cause = jdata->reset_cause; - /* Header version 3 introduces the header_size field. - * Thus we can estimate the real offset of jump tags - * between different header versions. - */ - if (jdata->version == 1) { - jtag_total = 0; - delta = sizeof(struct jump_data) - 12; - } else if (jdata->version == 2) { - jtag_total = jdata->jump_tag_total; - delta = sizeof(struct jump_data) - 16; - } else { - jtag_total = jdata->jump_tag_total; - delta = sizeof(struct jump_data) - jdata->header_size; - } - jtag = ((uint8_t*)jdata) + delta - jtag_total; - /* TODO: re-write with memmove(). */ - if (delta > 0) { - memcpy(jtag - delta, jtag, jtag_total); - } else { - int i; - for (i = jtag_total - 1; i >= 0; i--) - jtag[i - delta] = jtag[i]; + /* If the jump data structure isn't the same size as the + * current one, shift the jump tags to immediately before the + * current jump data structure, to make room for initalizing + * the new fields below. */ + if (jdata->version == 1) + delta = 0; /* No tags in v1, so no need for move */ + else if (jdata->version == 2) + delta = sizeof(struct jump_data) - JUMP_DATA_SIZE_V2; + else + delta = sizeof(struct jump_data) - jdata->struct_size; + + if (delta && jdata->jump_tag_total) { + uint8_t *d = (uint8_t *)system_usable_ram_end(); + memmove(d, d + delta, jdata->jump_tag_total); } /* Initialize fields added after version 1 */ @@ -368,10 +353,11 @@ int system_common_pre_init(void) jdata->jump_tag_total = 0; /* Initialize fields added after version 2 */ - if (jdata->version < 3) { + if (jdata->version < 3) jdata->recovery_required = 0; - jdata->header_size = 16; - } + + /* Struct size is now the current struct size */ + jdata->struct_size = sizeof(struct jump_data); /* Clear the jump struct's magic number. This prevents * accidentally detecting a jump when there wasn't one, and diff --git a/common/util.c b/common/util.c index fe30ffa518..47e9ba1226 100644 --- a/common/util.c +++ b/common/util.c @@ -144,6 +144,27 @@ void *memset(void *dest, int c, int len) } +void *memmove(void *dest, const void *src, int len) +{ + if ((uint32_t)dest <= (uint32_t)src || + (uint32_t)dest >= (uint32_t)src + len) { + /* Start of destination doesn't overlap source, so just use + * memcpy(). */ + return memcpy(dest, src, len); + } else { + /* Copy from end, so we don't overwrite the source */ + char *d = (char *)dest + len; + const char *s = (const char *)src + len; + /* TODO: optimized version using LDM/STM would be much faster */ + while (len > 0) { + *(--d) = *(--s); + len--; + } + return dest; + } +} + + char *strzcpy(char *dest, const char *src, int len) { char *d = dest; diff --git a/include/util.h b/include/util.h index 5b9dd364db..6f8fe1c581 100644 --- a/include/util.h +++ b/include/util.h @@ -56,6 +56,7 @@ int isspace(int c); int isalpha(int c); void *memcpy(void *dest, const void *src, int len); void *memset(void *dest, int c, int len); +void *memmove(void *dest, const void *src, int len); int strcasecmp(const char *s1, const char *s2); int strlen(const char *s); int strtoi(const char *nptr, char **endptr, int base); |