int system_run_image_copy(enum system_image_copy_t copy) { uintptr_t base; uintptr_t init_addr; /* If system is already running the requested image, done */ if (system_get_image_copy() == copy) return EC_SUCCESS; if (system_is_locked()) { /* System is locked, so disallow jumping between images unless * this is the initial jump from RO to RW code. */ /* Must currently be running the RO image */ if (system_get_image_copy() != SYSTEM_IMAGE_RO) return EC_ERROR_ACCESS_DENIED; /* Target image must be RW image */ if (copy != SYSTEM_IMAGE_RW) return EC_ERROR_ACCESS_DENIED; /* Jumping must still be enabled */ if (disable_jump) return EC_ERROR_ACCESS_DENIED; } /* Load the appropriate reset vector */ base = get_base(copy); if (base == 0xffffffff) return EC_ERROR_INVAL; /* TODO: (ML) jump to little FW for code ram architecture */ #ifdef CONFIG_CODERAM_ARCH init_addr = system_get_lfw_address(base); #else /* Make sure the reset vector is inside the destination image */ init_addr = *(uintptr_t *)(base + 4); #ifndef EMU_BUILD if (init_addr < base || init_addr >= base + get_size(copy)) return EC_ERROR_UNKNOWN; #endif #endif CPRINTS("Jumping to image %s", system_image_copy_t_to_string(copy)); jump_to_image(init_addr); /* Should never get here */ return EC_ERROR_UNKNOWN; }
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) return EC_SUCCESS; if (system_is_locked()) { /* System is locked, so disallow jumping between images unless * this is the initial jump from RO to RW code. */ /* Must currently be running the RO image */ if (system_get_image_copy() != SYSTEM_IMAGE_RO) return EC_ERROR_ACCESS_DENIED; /* Target image must be RW image */ if (copy != SYSTEM_IMAGE_RW) return EC_ERROR_ACCESS_DENIED; /* Jumping must still be enabled */ if (disable_jump) return EC_ERROR_ACCESS_DENIED; } /* Load the appropriate reset vector */ base = get_program_memory_addr(copy); if (base == 0xffffffff) 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) */ /* Jump to loader */ init_addr = system_get_lfw_address(); system_set_image_copy(copy); #else #ifdef CONFIG_FW_RESET_VECTOR /* Get reset vector */ init_addr = system_get_fw_reset_vector(base); #else #if defined(CONFIG_RO_HEAD_ROOM) /* Skip any head room in the RO image */ if (copy == SYSTEM_IMAGE_RO) /* Don't change base, though! */ init_addr = *(uintptr_t *)(base + CONFIG_RO_HEAD_ROOM + 4); else #endif init_addr = *(uintptr_t *)(base + 4); #endif #ifndef EMU_BUILD /* Make sure the reset vector is inside the destination image */ if (init_addr < base || init_addr >= base + get_size(copy)) return EC_ERROR_UNKNOWN; #endif #endif CPRINTS("Jumping to image %s", system_image_copy_t_to_string(copy)); jump_to_image(init_addr); /* Should never get here */ return EC_ERROR_UNKNOWN; }