mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-11 18:35:28 +00:00
rwsig: Make it possible to run as a task
(Optionally) split rwsig verification into a separate task. This
allows us to initialize other components (e.g. USB) while the
verification is in progress, speeding up the boot process to active
USB in RO case.
After CONFIG_RWSIG_JUMP_TIMEOUT, the EC will jump to the RW section
if no action is taken by the AP (such as a forced request to jump
to RW, or starting an update).
Note: This comes with a ~36ms boot time regression, as other code
gets to run before verification starts.
BRANCH=none
BUG=b:35587171
TEST=Flash, board boots to RW after 1s
TEST=Change jump timeout to 5s, add 5s delay in check_signature,
add console command to manually abort/continue rwsig verification.
'rwsig continue' works => Board jumps to RW after check_signature
is completed (or immediately while waiting for timeout)
'rwsig abort' works => Board does not jump to RW.
Change-Id: Ica5732b9298bb4d3b743cae2ba78df259db915ef
Reviewed-on: https://chromium-review.googlesource.com/468709
Commit-Ready: Nicolas Boichat <drinkcat@chromium.org>
Tested-by: Nicolas Boichat <drinkcat@chromium.org>
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
This commit is contained in:
committed by
chrome-bot
parent
629c3964a2
commit
68a537e466
@@ -162,12 +162,15 @@ test_mockable __keep int main(void)
|
||||
button_init();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RWSIG
|
||||
#if defined(CONFIG_RWSIG) && !defined(HAS_TASK_RWSIG)
|
||||
/*
|
||||
* Check the RW firmware signature
|
||||
* and eventually jump to it if it is good.
|
||||
* Check the RW firmware signature and jump to it if it is good.
|
||||
*
|
||||
* Only the Read-Only firmware needs to do the signature check.
|
||||
*/
|
||||
check_rw_signature();
|
||||
if (system_get_image_copy() == SYSTEM_IMAGE_RO &&
|
||||
rwsig_check_signature())
|
||||
rwsig_jump_now();
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "sha256.h"
|
||||
#include "shared_mem.h"
|
||||
#include "system.h"
|
||||
#include "task.h"
|
||||
#include "usb_pd.h"
|
||||
#include "util.h"
|
||||
#include "vb21_struct.h"
|
||||
@@ -28,6 +29,15 @@
|
||||
static uint32_t * const rw_rst =
|
||||
(uint32_t *)(CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RW_MEM_OFF + 4);
|
||||
|
||||
|
||||
void rwsig_jump_now(void)
|
||||
{
|
||||
/*
|
||||
* TODO(b/35587171): This should also check RW flash is protected.
|
||||
*/
|
||||
system_run_image_copy(SYSTEM_IMAGE_RW);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that memory between rwdata[start] and rwdata[len-1] is filled
|
||||
* with ones. data, start and len must be aligned on 4-byte boundary.
|
||||
@@ -49,14 +59,14 @@ static int check_padding(const uint8_t *data,
|
||||
return 1;
|
||||
}
|
||||
|
||||
void check_rw_signature(void)
|
||||
int rwsig_check_signature(void)
|
||||
{
|
||||
struct sha256_ctx ctx;
|
||||
int res;
|
||||
const struct rsa_public_key *key;
|
||||
const uint8_t *sig;
|
||||
uint8_t *hash;
|
||||
uint32_t *rsa_workbuf;
|
||||
uint32_t *rsa_workbuf = NULL;
|
||||
const uint8_t *rwdata = (uint8_t *)CONFIG_PROGRAM_MEMORY_BASE
|
||||
+ CONFIG_RW_MEM_OFF;
|
||||
int good = 0;
|
||||
@@ -71,13 +81,9 @@ void check_rw_signature(void)
|
||||
int32_t min_rollback_version;
|
||||
#endif
|
||||
|
||||
/* 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;
|
||||
goto out;
|
||||
|
||||
CPRINTS("Verifying RW image...");
|
||||
|
||||
@@ -89,7 +95,7 @@ void check_rw_signature(void)
|
||||
rw_rollback_version < min_rollback_version) {
|
||||
CPRINTS("Rollback error (%d < %d)",
|
||||
rw_rollback_version, min_rollback_version);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -97,7 +103,7 @@ void check_rw_signature(void)
|
||||
res = shared_mem_acquire(3 * RSANUMBYTES, (char **)&rsa_workbuf);
|
||||
if (res) {
|
||||
CPRINTS("No memory for RW verification");
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RWSIG_TYPE_USBPD1
|
||||
@@ -186,14 +192,65 @@ void check_rw_signature(void)
|
||||
out:
|
||||
CPRINTS("RW verify %s", good ? "OK" : "FAILED");
|
||||
|
||||
if (good) {
|
||||
/* Jump to the RW firmware */
|
||||
system_run_image_copy(SYSTEM_IMAGE_RW);
|
||||
} else {
|
||||
if (!good) {
|
||||
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);
|
||||
if (rsa_workbuf)
|
||||
shared_mem_release(rsa_workbuf);
|
||||
|
||||
return good;
|
||||
}
|
||||
|
||||
#ifdef HAS_TASK_RWSIG
|
||||
#define TASK_EVENT_ABORT TASK_EVENT_CUSTOM(1)
|
||||
#define TASK_EVENT_CONTINUE TASK_EVENT_CUSTOM(2)
|
||||
|
||||
static enum rwsig_status rwsig_status;
|
||||
|
||||
enum rwsig_status rwsig_get_status(void)
|
||||
{
|
||||
return rwsig_status;
|
||||
}
|
||||
|
||||
void rwsig_abort(void)
|
||||
{
|
||||
task_set_event(TASK_ID_RWSIG, TASK_EVENT_ABORT, 0);
|
||||
}
|
||||
|
||||
void rwsig_continue(void)
|
||||
{
|
||||
task_set_event(TASK_ID_RWSIG, TASK_EVENT_CONTINUE, 0);
|
||||
}
|
||||
|
||||
void rwsig_task(void)
|
||||
{
|
||||
uint32_t evt;
|
||||
|
||||
if (system_get_image_copy() != SYSTEM_IMAGE_RO)
|
||||
goto exit;
|
||||
|
||||
rwsig_status = RWSIG_IN_PROGRESS;
|
||||
if (!rwsig_check_signature()) {
|
||||
rwsig_status = RWSIG_INVALID;
|
||||
goto exit;
|
||||
}
|
||||
rwsig_status = RWSIG_VALID;
|
||||
|
||||
/* Jump to RW after a timeout */
|
||||
evt = task_wait_event(CONFIG_RWSIG_JUMP_TIMEOUT);
|
||||
|
||||
/* Jump now if we timed out, or were told to continue. */
|
||||
if (evt == TASK_EVENT_TIMER || evt == TASK_EVENT_CONTINUE)
|
||||
rwsig_jump_now();
|
||||
else
|
||||
rwsig_status = RWSIG_ABORTED;
|
||||
|
||||
exit:
|
||||
/* We're done, yield forever. */
|
||||
while (1)
|
||||
task_wait_event(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1818,6 +1818,13 @@
|
||||
*/
|
||||
#undef CONFIG_RWSIG
|
||||
|
||||
/*
|
||||
* When RWSIG verification is performed as a task, time to wait from signature
|
||||
* verification to an automatic jump to RW (if AP does not request the wait to
|
||||
* be interrupted).
|
||||
*/
|
||||
#define CONFIG_RWSIG_JUMP_TIMEOUT (1000 * MSEC)
|
||||
|
||||
/*
|
||||
* Defines what type of futility signature type should be used.
|
||||
* RWSIG should be used for new designs.
|
||||
|
||||
@@ -10,9 +10,46 @@
|
||||
#include "rsa.h"
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#ifdef HAS_TASK_RWSIG
|
||||
/* The functions below only make sense if RWSIG task is defined. */
|
||||
|
||||
/* Checks RW signature. */
|
||||
void check_rw_signature(void);
|
||||
/* Current status of RW signature verification */
|
||||
enum rwsig_status {
|
||||
RWSIG_UNKNOWN = 0, /* Unknown/not started */
|
||||
RWSIG_IN_PROGRESS,
|
||||
RWSIG_VALID,
|
||||
RWSIG_INVALID,
|
||||
RWSIG_ABORTED,
|
||||
};
|
||||
|
||||
/* Returns current rwsig verification status. */
|
||||
enum rwsig_status rwsig_get_status(void);
|
||||
|
||||
/*
|
||||
* Aborts current verification, also prevents RWSIG task from automatically
|
||||
* jumping to RW.
|
||||
* This is used by usb_updater when a RW update is required, giving it enough
|
||||
* time to actually perform the update.
|
||||
*/
|
||||
void rwsig_abort(void);
|
||||
|
||||
/*
|
||||
* Tells RWSIG task to jump to RW immediately, if the signature is correct.
|
||||
* This is used by usb_updater when no RW update is required, to speed up
|
||||
* boot time.
|
||||
*/
|
||||
void rwsig_continue(void);
|
||||
|
||||
#else /* !HAS_TASK_RWSIG */
|
||||
/* These functions can only be called directly if RWSIG task is not defined. */
|
||||
|
||||
/* Checks RW signature. Returns a boolean indicating success. */
|
||||
int rwsig_check_signature(void);
|
||||
|
||||
/* Jumps to RW, if signature is fine, returns on error (otherwise, jumps). */
|
||||
void rwsig_jump_now(void);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !__ASSEMBLER__ */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user