/** * Handle a pending reboot command. */ static int handle_pending_reboot(enum ec_reboot_cmd cmd) { switch (cmd) { case EC_REBOOT_CANCEL: return EC_SUCCESS; case EC_REBOOT_JUMP_RO: return system_run_image_copy(SYSTEM_IMAGE_RO); case EC_REBOOT_JUMP_RW: return system_run_image_copy(SYSTEM_IMAGE_RW); case EC_REBOOT_COLD: #ifdef HAS_TASK_PDCMD /* Reboot the PD chip as well */ gpio_set_level(GPIO_USB_MCU_RST, 1); usleep(100); gpio_set_level(GPIO_USB_MCU_RST, 0); #endif system_reset(SYSTEM_RESET_HARD); /* That shouldn't return... */ return EC_ERROR_UNKNOWN; case EC_REBOOT_DISABLE_JUMP: system_disable_jump(); return EC_SUCCESS; #ifdef CONFIG_HIBERNATE case EC_REBOOT_HIBERNATE: CPRINTS("system hibernating"); system_hibernate(0, 0); /* That shouldn't return... */ return EC_ERROR_UNKNOWN; #endif default: return EC_ERROR_INVAL; } }
/** * Handle a pending reboot command. */ static int handle_pending_reboot(enum ec_reboot_cmd cmd) { switch (cmd) { case EC_REBOOT_CANCEL: return EC_SUCCESS; case EC_REBOOT_JUMP_RO: return system_run_image_copy(SYSTEM_IMAGE_RO); case EC_REBOOT_JUMP_RW: return system_run_image_copy(SYSTEM_IMAGE_RW); case EC_REBOOT_COLD: system_reset(SYSTEM_RESET_HARD); /* That shouldn't return... */ return EC_ERROR_UNKNOWN; case EC_REBOOT_DISABLE_JUMP: system_disable_jump(); return EC_SUCCESS; case EC_REBOOT_HIBERNATE: CPRINTS("system hibernating"); system_hibernate(0, 0); /* That shouldn't return... */ return EC_ERROR_UNKNOWN; default: return EC_ERROR_INVAL; } }
static int test_sysjump(void) { set_scancode(2); enable_keystroke(1); system_run_image_copy(SYSTEM_IMAGE_RW); /* Shouldn't reach here */ return EC_ERROR_UNKNOWN; }
static int command_sysjump(int argc, char **argv) { uint32_t addr; char *e; if (argc < 2) return EC_ERROR_PARAM_COUNT; /* Handle named images */ if (!strcasecmp(argv[1], "RO")) return system_run_image_copy(SYSTEM_IMAGE_RO); else if (!strcasecmp(argv[1], "RW") || !strcasecmp(argv[1], "A")) { /* * TODO(crosbug.com/p/11149): remove "A" once all scripts are * updated to use "RW". */ return system_run_image_copy(SYSTEM_IMAGE_RW); } else if (!strcasecmp(argv[1], "disable")) { system_disable_jump(); return EC_SUCCESS; } /* Arbitrary jumps are only allowed on an unlocked system */ if (system_is_locked()) return EC_ERROR_ACCESS_DENIED; /* Check for arbitrary address */ addr = strtoi(argv[1], &e, 0); if (*e) return EC_ERROR_PARAM1; ccprintf("Jumping to 0x%08x\n", addr); cflush(); jump_to_image(addr); return EC_SUCCESS; }
void check_rw_signature(void) { struct sha256_ctx ctx; int good, res; uint8_t *hash; uint32_t *rsa_workbuf; /* Only the Read-Only firmware needs to do the signature check */ if (system_get_image_copy() != SYSTEM_IMAGE_RO) return; /* Check if we have a RW firmware flashed */ if (*rw_rst == 0xffffffff) return; CPRINTS("Verifying RW image..."); /* Large buffer for RSA computation : could be re-use afterwards... */ res = shared_mem_acquire(3 * RSANUMBYTES, (char **)&rsa_workbuf); if (res) { CPRINTS("No memory for RW verification"); return; } /* SHA-256 Hash of the RW firmware */ /* TODO(crosbug.com/p/44803): Do we have to hash the whole region? */ SHA256_init(&ctx); SHA256_update(&ctx, (void *)CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RW_MEM_OFF, CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE); hash = SHA256_final(&ctx); good = rsa_verify((const struct rsa_public_key *)CONFIG_RO_PUBKEY_ADDR, (const uint8_t *)CONFIG_RW_SIG_ADDR, hash, rsa_workbuf); if (good) { CPRINTS("RW image verified"); /* Jump to the RW firmware */ system_run_image_copy(SYSTEM_IMAGE_RW); } else { CPRINTS("RSA verify FAILED"); pd_log_event(PD_EVENT_ACC_RW_FAIL, 0, 0, NULL); /* RW firmware is invalid : do not jump there */ if (system_is_locked()) system_disable_jump(); } shared_mem_release(rsa_workbuf); }