Commit f3bb31fe authored by Daisuke Nojiri's avatar Daisuke Nojiri Committed by chrome-bot
Browse files

vboot: Support EC early firmware selection



This patch adds support for EC EFS: EC verifies and jumps to RW
image before AP boots.

Depthcharge refers the active slot for checking RW version and
the update slot for update (a.k.a. soft sync).

This change removes reboot_all_ecs and adds cros_ec_reboot, which
takes EC_REBOOT_FLAG_*. Other ECs are expected to be rebooted
when the main EC reboots the whole system.

BUG=b:65028930,b:65264494
BRANCH=none
CQ-DEPEND=CL:616346
TEST=On Fizz, verify:
1. RW_B is old and updated by soft sync. RW_B is activated and
   executed after reboot. System continues to boot to OS.
2. RW_A is old and updated by soft sync. RW_A is activated and
   executed after reboot. System continues to boot to OS.

Change-Id: Ida61e51ab5e61376f836c9d8027f7f21eb205ace
Signed-off-by: default avatarDaisuke Nojiri <dnojiri@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/616248
parent bcccd402
......@@ -1237,13 +1237,15 @@ struct __ec_align4 ec_response_flash_protect {
enum ec_flash_region {
/* Region which holds read-only EC image */
EC_FLASH_REGION_RO = 0,
/* Region which holds rewritable EC image */
EC_FLASH_REGION_RW,
/* Region which holds active rewritable EC image */
EC_FLASH_REGION_ACTIVE,
/*
* Region which should be write-protected in the factory (a superset of
* EC_FLASH_REGION_RO)
*/
EC_FLASH_REGION_WP_RO,
/* Region which holds updatable image */
EC_FLASH_REGION_UPDATE,
/* Number of regions */
EC_FLASH_REGION_COUNT,
};
......@@ -1789,8 +1791,9 @@ enum ec_vboot_hash_status {
* If one of these is specified, the EC will automatically update offset and
* size to the correct values for the specified image (RO or RW).
*/
#define EC_VBOOT_HASH_OFFSET_RO 0xfffffffe
#define EC_VBOOT_HASH_OFFSET_RW 0xfffffffd
#define EC_VBOOT_HASH_OFFSET_RO 0xfffffffe
#define EC_VBOOT_HASH_OFFSET_ACTIVE 0xfffffffd
#define EC_VBOOT_HASH_OFFSET_UPDATE 0xfffffffc
/*****************************************************************************/
/*
......@@ -3518,6 +3521,7 @@ enum ec_reboot_cmd {
/* Flags for ec_params_reboot_ec.reboot_flags */
#define EC_REBOOT_FLAG_RESERVED0 (1 << 0) /* Was recovery request */
#define EC_REBOOT_FLAG_ON_AP_SHUTDOWN (1 << 1) /* Reboot after AP shutdown */
#define EC_REBOOT_FLAG_SWITCH_RW_SLOT (1 << 2) /* Switch RW slot */
struct __ec_align1 ec_params_reboot_ec {
uint8_t cmd; /* enum ec_reboot_cmd */
......
......@@ -25,6 +25,7 @@
#include <assert.h>
#include <libpayload.h>
#include <vboot_api.h>
#include "base/container_of.h"
#include "drivers/ec/cros/message.h"
......@@ -462,10 +463,28 @@ static VbError_t vboot_running_rw(VbootEcOps *vbec, int *in_rw)
return VBERROR_SUCCESS;
}
static uint32_t get_vboot_hash_offset(enum VbSelectFirmware_t select)
{
switch (select) {
case VB_SELECT_FIRMWARE_READONLY:
return EC_VBOOT_HASH_OFFSET_RO;
case VB_SELECT_FIRMWARE_EC_UPDATE:
return EC_VBOOT_HASH_OFFSET_UPDATE;
default:
return EC_VBOOT_HASH_OFFSET_ACTIVE;
}
}
static enum ec_flash_region vboot_to_ec_region(enum VbSelectFirmware_t select)
{
return (select == VB_SELECT_FIRMWARE_READONLY) ? EC_FLASH_REGION_WP_RO :
EC_FLASH_REGION_RW;
switch (select) {
case VB_SELECT_FIRMWARE_READONLY:
return EC_FLASH_REGION_WP_RO;
case VB_SELECT_FIRMWARE_EC_UPDATE:
return EC_FLASH_REGION_UPDATE;
default:
return EC_FLASH_REGION_ACTIVE;
}
}
static VbError_t vboot_hash_image(VbootEcOps *vbec,
......@@ -479,10 +498,7 @@ static VbError_t vboot_hash_image(VbootEcOps *vbec,
int recalc_requested = 0;
uint32_t hash_offset;
if (vboot_to_ec_region(select) == EC_FLASH_REGION_WP_RO)
hash_offset = EC_VBOOT_HASH_OFFSET_RO;
else
hash_offset = EC_VBOOT_HASH_OFFSET_RW;
hash_offset = get_vboot_hash_offset(select);
start = timer_us(0);
do {
......@@ -1141,6 +1157,11 @@ int cros_ec_read_batt_state_of_charge(uint32_t *state)
return 0;
}
int cros_ec_reboot(uint8_t flags)
{
return ec_reboot(get_main_ec(), EC_REBOOT_COLD, flags);
}
/*
* Set backlight. Note that duty value needs to be passed
* to the EC as a 16 bit number for increased precision.
......
......@@ -292,6 +292,14 @@ int cros_ec_read_power_btn(uint32_t *pwr_btn);
*/
int cros_ec_config_powerbtn(uint32_t enable);
/**
* Reboots main EC
*
* @param flags
* @return 0 if ok, -1 on error
*/
int cros_ec_reboot(uint8_t flags);
CrosEc *new_cros_ec(CrosEcBusOps *bus, int devidx, GpioOps *interrupt_gpio);
#endif
......@@ -26,18 +26,3 @@ void register_vboot_ec(VbootEcOps *ec, int devidx)
vboot_ec[devidx] = ec;
}
void reboot_all_ecs(void)
{
int devidx;
printf("Preparing all ECs to reboot to RO...\n");
for (devidx = 0; devidx < NUM_MAX_VBOOT_ECS; devidx++) {
VbootEcOps *ec = vboot_ec[devidx];
if (!ec)
continue;
if (ec->reboot_to_ro(ec) != VBERROR_SUCCESS)
printf("...EC[%d] failed, ignoring\n", devidx);
}
printf("...done!\n");
}
......@@ -42,6 +42,5 @@ typedef struct VbootEcOps {
extern VbootEcOps *vboot_ec[];
void register_vboot_ec(VbootEcOps *ec, int devidx);
void reboot_all_ecs(void);
#endif /* __DRIVERS_EC_VBOOT_EC_H */
......@@ -101,7 +101,13 @@ int vboot_select_and_load_kernel(void)
}
if (res == VBERROR_EC_REBOOT_TO_RO_REQUIRED) {
reboot_all_ecs();
if (IS_ENABLED(CONFIG_DRIVER_EC_CROS))
cros_ec_reboot(0);
if (power_off())
return 1;
} else if (res == VBERROR_EC_REBOOT_TO_SWITCH_RW) {
if (IS_ENABLED(CONFIG_DRIVER_EC_CROS))
cros_ec_reboot(EC_REBOOT_FLAG_SWITCH_RW_SLOT);
if (power_off())
return 1;
} else if (res == VBERROR_SHUTDOWN_REQUESTED) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment