diff options
author | Gerrit <chrome-bot@google.com> | 2012-05-02 12:57:45 -0700 |
---|---|---|
committer | Gerrit Code Review <gerrit@gerrit.golo.chromium.org> | 2012-05-02 12:57:45 -0700 |
commit | 09def9037323f0f6e286d8f1b08be41a052aeefb (patch) | |
tree | 7cf41c021e81742c5247f44380f3133c8a75efca | |
parent | 9f7fa4e800ffb7cffc4d40d170785caf7e6a38e9 (diff) | |
parent | 0467763f5a75125d734e7ed20e2a18c41aae26bf (diff) | |
download | chrome-ec-09def9037323f0f6e286d8f1b08be41a052aeefb.tar.gz |
Merge "Enhance LPC EC REBOOT reset command to allow to request recovery"
-rw-r--r-- | chip/lm4/power_button.c | 4 | ||||
-rw-r--r-- | common/system_common.c | 60 | ||||
-rw-r--r-- | common/vboot.c | 2 | ||||
-rw-r--r-- | include/lpc_commands.h | 3 | ||||
-rw-r--r-- | include/system.h | 8 |
5 files changed, 55 insertions, 22 deletions
diff --git a/chip/lm4/power_button.c b/chip/lm4/power_button.c index f037cb2139..f6597d30d5 100644 --- a/chip/lm4/power_button.c +++ b/chip/lm4/power_button.c @@ -92,6 +92,10 @@ static void update_other_switches(void) else *memmap_switches &= ~EC_LPC_SWITCH_DEDICATED_RECOVERY; + /* Was this a reboot requesting recovery? */ + if (system_get_recovery_required()) + *memmap_switches |= EC_LPC_SWITCH_DEDICATED_RECOVERY; + #ifdef CONFIG_FAKE_DEV_SWITCH if (eoption_get_bool(EOPTION_BOOL_FAKE_DEV)) *memmap_switches |= EC_LPC_SWITCH_FAKE_DEVELOPER; diff --git a/common/system_common.c b/common/system_common.c index f1b5473eb7..6394a434de 100644 --- a/common/system_common.c +++ b/common/system_common.c @@ -36,6 +36,8 @@ struct jump_data { * _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. */ + uint8_t recovery_required; /* signal recovery mode to BIOS */ + /* Fields from version 2 */ int jump_tag_total; /* Total size of all jump tags */ @@ -75,6 +77,12 @@ enum system_reset_cause_t system_get_reset_cause(void) } +int system_get_recovery_required(void) +{ + return jdata->recovery_required; +} + + int system_jumped_to_this_image(void) { return jumped_to_image; @@ -194,7 +202,8 @@ const char *system_get_image_copy_string(void) /* Jump to what we hope is the init address of an image. This function does * not return. */ -static void jump_to_image(uint32_t init_addr) +static void jump_to_image(uint32_t init_addr, + int recovery_required) { void (*resetvec)(void) = (void(*)(void))init_addr; @@ -206,6 +215,7 @@ static void jump_to_image(uint32_t init_addr) interrupt_disable(); /* Fill in preserved data between jumps */ + jdata->recovery_required = recovery_required != 0; jdata->magic = JUMP_DATA_MAGIC; jdata->version = JUMP_DATA_VERSION; jdata->reset_cause = reset_cause; @@ -237,7 +247,15 @@ static uint32_t get_base(enum system_image_copy_t copy) } -int system_run_image_copy(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) { uint32_t base; uint32_t init_addr; @@ -260,7 +278,9 @@ int system_run_image_copy(enum system_image_copy_t copy) if (init_addr < base || init_addr >= base + CONFIG_FW_IMAGE_SIZE) return EC_ERROR_UNKNOWN; - jump_to_image(init_addr); + CPRINTF("Rebooting to image %s\n", image_names[copy]); + + jump_to_image(init_addr, recovery_required); /* Should never get here */ return EC_ERROR_UNIMPLEMENTED; @@ -426,16 +446,15 @@ static int command_sysjump(int argc, char **argv) return EC_ERROR_INVAL; } + ccputs("Processing sysjump command\n"); + /* Handle named images */ if (!strcasecmp(argv[1], "RO")) { - ccputs("Jumping directly to RO image...\n"); - return system_run_image_copy(SYSTEM_IMAGE_RO); + return system_run_image_copy(SYSTEM_IMAGE_RO, 0); } else if (!strcasecmp(argv[1], "A")) { - ccputs("Jumping directly to image A...\n"); - return system_run_image_copy(SYSTEM_IMAGE_RW_A); + return system_run_image_copy(SYSTEM_IMAGE_RW_A, 0); } else if (!strcasecmp(argv[1], "B")) { - ccputs("Jumping directly to image B...\n"); - return system_run_image_copy(SYSTEM_IMAGE_RW_B); + return system_run_image_copy(SYSTEM_IMAGE_RW_B, 0); } /* Check for arbitrary address */ @@ -446,7 +465,7 @@ static int command_sysjump(int argc, char **argv) } ccprintf("Jumping directly to 0x%08x...\n", addr); cflush(); - jump_to_image(addr); + jump_to_image(addr, 0); return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(sysjump, command_sysjump); @@ -533,32 +552,35 @@ static void clean_busy_bits(void) { enum lpc_status host_command_reboot(uint8_t *data) { + enum system_image_copy_t copy; + struct lpc_params_reboot_ec *p = (struct lpc_params_reboot_ec *)data; + int recovery_request = p->reboot_flags & + EC_LPC_COMMAND_REBOOT_BIT_RECOVERY; + /* TODO: (crosbug.com/p/7468) For this command to be allowed, WP must * be disabled. */ switch (p->target) { case EC_LPC_IMAGE_RO: - CPUTS("[Rebooting to image RO!\n]"); - clean_busy_bits(); - system_run_image_copy(SYSTEM_IMAGE_RO); + copy = SYSTEM_IMAGE_RO; break; case EC_LPC_IMAGE_RW_A: - CPUTS("[Rebooting to image A!]\n"); - clean_busy_bits(); - system_run_image_copy(SYSTEM_IMAGE_RW_A); + copy = SYSTEM_IMAGE_RW_A; break; case EC_LPC_IMAGE_RW_B: - CPUTS("[Rebooting to image B!]\n"); - clean_busy_bits(); - system_run_image_copy(SYSTEM_IMAGE_RW_B); + copy = SYSTEM_IMAGE_RW_B; break; default: return EC_LPC_RESULT_ERROR; } + clean_busy_bits(); + CPUTS("Executing host reboot command\n"); + system_run_image_copy(copy, recovery_request); + /* We normally never get down here, because we'll have jumped to * another image. To confirm this command worked, the host will need * to check what image is current using GET_VERSION. diff --git a/common/vboot.c b/common/vboot.c index b96765b97b..fa6c2c27aa 100644 --- a/common/vboot.c +++ b/common/vboot.c @@ -52,7 +52,7 @@ static void jump_to_other_image(void) * image, enable this there too. */ /* TODO: real verified boot (including recovery reason); for now, just * jump to image A. */ - system_run_image_copy(SYSTEM_IMAGE_RW_A); + system_run_image_copy(SYSTEM_IMAGE_RW_A, 0); #endif } diff --git a/include/lpc_commands.h b/include/lpc_commands.h index a3386c7280..354c059b1f 100644 --- a/include/lpc_commands.h +++ b/include/lpc_commands.h @@ -499,8 +499,11 @@ struct lpc_response_host_event_mask { #define EC_LPC_COMMAND_REBOOT 0xd1 /* Think "die" */ #define EC_LPC_COMMAND_REBOOT_EC 0xd2 +#define EC_LPC_COMMAND_REBOOT_BIT_RECOVERY (1 << 0) + struct lpc_params_reboot_ec { uint8_t target; /* enum lpc_current_image */ + uint8_t reboot_flags; } __attribute__ ((packed)); #endif /* !__ACPI__ */ diff --git a/include/system.h b/include/system.h index c84830bec4..3246242971 100644 --- a/include/system.h +++ b/include/system.h @@ -57,6 +57,9 @@ int system_common_pre_init(void); * the cause is not known. */ enum system_reset_cause_t system_get_reset_cause(void); +/* returns a Boolean indicating if BIOS should come up in recovery mode */ +int system_get_recovery_required(void); + /* Record the cause of the last reset. */ void system_set_reset_cause(enum system_reset_cause_t cause); @@ -93,8 +96,9 @@ int system_unsafe_to_overwrite(uint32_t offset, uint32_t size); /* Returns a text description of the image copy which is currently running. */ const char *system_get_image_copy_string(void); -/* Jumps to the specified image copy. Only works from RO firmware. */ -int system_run_image_copy(enum system_image_copy_t copy); +/* Jumps to the specified image copy. */ +int system_run_image_copy(enum system_image_copy_t copy, + int recovery_request); /* Returns the version string for an image copy, or an empty string if * error. If copy==SYSTEM_IMAGE_UNKNOWN, returns the version for the |