summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerrit <chrome-bot@google.com>2012-05-02 12:57:45 -0700
committerGerrit Code Review <gerrit@gerrit.golo.chromium.org>2012-05-02 12:57:45 -0700
commit09def9037323f0f6e286d8f1b08be41a052aeefb (patch)
tree7cf41c021e81742c5247f44380f3133c8a75efca
parent9f7fa4e800ffb7cffc4d40d170785caf7e6a38e9 (diff)
parent0467763f5a75125d734e7ed20e2a18c41aae26bf (diff)
downloadchrome-ec-09def9037323f0f6e286d8f1b08be41a052aeefb.tar.gz
Merge "Enhance LPC EC REBOOT reset command to allow to request recovery"
-rw-r--r--chip/lm4/power_button.c4
-rw-r--r--common/system_common.c60
-rw-r--r--common/vboot.c2
-rw-r--r--include/lpc_commands.h3
-rw-r--r--include/system.h8
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