diff options
author | Aseda Aboagye <aaboagye@google.com> | 2015-10-15 18:27:41 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2015-11-08 07:59:39 -0800 |
commit | 260e85cd07135c4d7ab2696ac1cc8212e092ecdb (patch) | |
tree | ed154bd876afe57dec79d517afc83f7c93b29e9d /common/system.c | |
parent | e97da2f17c8eb188c09177b821521bebf5d830ea (diff) | |
download | chrome-ec-260e85cd07135c4d7ab2696ac1cc8212e092ecdb.tar.gz |
system: Copy the loader lastly before jumping.
The point at which we reloaded the loader was too early. When items are
placed into .bss.slow via CONFIG_REPLACE_LOADER_WITH_BSS_SLOW, other
tasks could still access their variables that may have been in that
region after we had replaced those contents with the loader. This
commit moves the reloading of the loader to as late as possible once all
tasks have done their HOOK_SYSJUMP work.
Also, fixed a bug with the .bss.slow section. If a board is not using
the config option but items are placed in that section, that part of RAM
would not be cleared out.
BUG=chrome-os-partner:46056
BRANCH=None
TEST=Enable config option on GLaDOS and add a few variables to the
.bss.slow section. 'sysjump' between RO and RW and verify that no data
bus error is encountered.
TEST=make -j buildall tests
Change-Id: I3084700b9d5c144e86e2e408b72d2e3075a67413
Signed-off-by: Aseda Aboagye <aaboagye@google.com>
Reviewed-on: https://chromium-review.googlesource.com/306173
Commit-Ready: Aseda Aboagye <aaboagye@chromium.org>
Tested-by: Aseda Aboagye <aaboagye@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'common/system.c')
-rw-r--r-- | common/system.c | 75 |
1 files changed, 43 insertions, 32 deletions
diff --git a/common/system.c b/common/system.c index 0cecb18dc3..64adef88cd 100644 --- a/common/system.c +++ b/common/system.c @@ -7,6 +7,7 @@ #include "clock.h" #include "common.h" #include "console.h" +#include "cpu.h" #include "dma.h" #include "flash.h" #include "gpio.h" @@ -424,7 +425,11 @@ const char *system_image_copy_t_to_string(enum system_image_copy_t copy) */ static void jump_to_image(uintptr_t init_addr) { - void (*resetvec)(void) = (void(*)(void))init_addr; + void (*resetvec)(void); +#ifdef CONFIG_REPLACE_LOADER_WITH_BSS_SLOW + uint8_t *buf; + int rv; +#endif /* defined(CONFIG_REPLACE_LOADER_WITH_BSS_SLOW) */ /* * Jumping to any image asserts the signal to the Silego chip that that @@ -447,14 +452,6 @@ static void jump_to_image(uintptr_t init_addr) /* Flush UART output */ cflush(); - /* Disable interrupts before jump */ - interrupt_disable(); - -#ifdef CONFIG_DMA - /* Disable all DMA channels to avoid memory corruption */ - dma_disable_all(); -#endif /* CONFIG_DMA */ - /* Fill in preserved data between jumps */ jdata->reserved0 = 0; jdata->magic = JUMP_DATA_MAGIC; @@ -466,7 +463,42 @@ static void jump_to_image(uintptr_t init_addr) /* Call other hooks; these may add tags */ hook_notify(HOOK_SYSJUMP); +#ifdef CONFIG_REPLACE_LOADER_WITH_BSS_SLOW + /* + * We've used the region in which the loader resided as data space for + * the .bss.slow section. Therefore, we need to reload the loader from + * the external storage back into program memory so that we can load a + * different image. + */ + buf = (uint8_t *)(CONFIG_PROGRAM_MEMORY_BASE + CONFIG_LOADER_MEM_OFF); + rv = flash_read((CONFIG_EC_PROTECTED_STORAGE_OFF + + CONFIG_LOADER_STORAGE_OFF), + CONFIG_LOADER_SIZE, buf); + /* + * If there's a problem with the flash_read, we might randomly crash in + * the loader. There's nothing we can really do at this point. On + * reset, we'll just load the loader from external flash again and boot + * from RO. Log a message to indicate what happened though. + */ + if (rv) { + CPRINTS("ldr fail!"); + cflush(); + } + + /* Now that the lfw is loaded again, get the reset vector. */ + init_addr = system_get_lfw_address(); +#endif /* defined(CONFIG_REPLACE_LOADER_WITH_BSS_SLOW) */ + + /* Disable interrupts before jump */ + interrupt_disable(); + +#ifdef CONFIG_DMA + /* Disable all DMA channels to avoid memory corruption */ + dma_disable_all(); +#endif /* CONFIG_DMA */ + /* Jump to the reset vector */ + resetvec = (void(*)(void))init_addr; resetvec(); } @@ -474,12 +506,6 @@ int system_run_image_copy(enum system_image_copy_t copy) { uintptr_t base; uintptr_t init_addr; -#ifdef CONFIG_REPLACE_LOADER_WITH_BSS_SLOW - uint8_t *buf; - uint32_t offset; - uint32_t bytes_to_load; - int rv; -#endif /* defined(CONFIG_REPLACE_LOADER_WITH_BSS_SLOW) */ /* If system is already running the requested image, done */ if (system_get_image_copy() == copy) @@ -508,25 +534,10 @@ int system_run_image_copy(enum system_image_copy_t copy) return EC_ERROR_INVAL; #ifdef CONFIG_EXTERNAL_STORAGE -#ifdef CONFIG_REPLACE_LOADER_WITH_BSS_SLOW - /* - * We've used the region in which the loader resided as data space for - * the .bss.slow section. Therefore, we need to reload the loader from - * the external storage back into program memory so that we can load a - * different image. - */ - buf = (uint8_t *)(CONFIG_PROGRAM_MEMORY_BASE + CONFIG_LOADER_MEM_OFF); - bytes_to_load = CONFIG_LOADER_SIZE; - offset = CONFIG_EC_PROTECTED_STORAGE_OFF + CONFIG_LOADER_STORAGE_OFF; - - rv = flash_read(offset, bytes_to_load, buf); - if (rv) - return rv; -#endif /* defined(CONFIG_REPLACE_LOADER_WITH_BSS_SLOW) */ - +#ifndef CONFIG_REPLACE_LOADER_WITH_BSS_SLOW /* Jump to loader */ init_addr = system_get_lfw_address(); - +#endif /* !defined(CONFIG_REPLACE_LOADER_WITH_BSS_SLOW) */ system_set_image_copy(copy); #else #ifdef CONFIG_FW_RESET_VECTOR |