void system_disable_jump(void) { disable_jump = 1; #ifdef CONFIG_MPU if (system_is_locked()) { int ret; int enable_mpu = 0; enum system_image_copy_t copy; CPRINTS("MPU type: %08x", mpu_get_type()); /* * Protect RAM from code execution */ ret = mpu_protect_ram(); if (ret == EC_SUCCESS) { enable_mpu = 1; CPRINTS("RAM locked. Exclusion %08x-%08x", &__iram_text_start, &__iram_text_end); } else { CPRINTS("Failed to lock RAM (%d)", ret); } /* * Protect inactive image (ie. RO if running RW, vice versa) * from code execution. */ switch (system_get_image_copy()) { case SYSTEM_IMAGE_RO: ret = mpu_lock_rw_flash(); copy = SYSTEM_IMAGE_RW; break; case SYSTEM_IMAGE_RW: ret = mpu_lock_ro_flash(); copy = SYSTEM_IMAGE_RO; break; default: copy = SYSTEM_IMAGE_UNKNOWN; ret = !EC_SUCCESS; } if (ret == EC_SUCCESS) { enable_mpu = 1; CPRINTS("%s image locked", system_image_copy_t_to_string(copy)); } else { CPRINTS("Failed to lock %s image (%d)", system_image_copy_t_to_string(copy), ret); } if (enable_mpu) mpu_enable(); } else { CPRINTS("System is unlocked. Skip MPU configuration"); } #endif }
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; }
const char *system_get_image_copy_string(void) { return system_image_copy_t_to_string(system_get_image_copy()); }
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; }