flash write and erase commands protect the active image.

Comapre the range to be write (erase) with the range of active image.
If overlap, return error to indicate the access denied.

Note that we actually protect only runtime code and ro data.
FMAP is intentional unprotected so that flashrom can update to new map
before jumping. Since the vector table and init code are in the same
erase page, they are unprotected as well.

BUG=chrome-os-partner:7478
TEST=

Change-Id: Icb5cc89836432a11cef80e18eb66bb39a6c9b1d9
This commit is contained in:
Louis Yung-Chieh Lo
2012-03-21 22:18:39 +08:00
parent 43686b0588
commit b71837716d
4 changed files with 42 additions and 0 deletions

View File

@@ -10,6 +10,7 @@
#include "host_command.h"
#include "registers.h" /* TODO: remove; only for temp debugging */
#include "shared_mem.h"
#include "system.h"
#include "uart.h"
#include "util.h"
@@ -258,6 +259,9 @@ enum lpc_status flash_command_write(uint8_t *data)
if (p->size > sizeof(p->data))
return EC_LPC_RESULT_ERROR;
if (system_unsafe_to_overwrite(p->offset, p->size))
return EC_LPC_RESULT_ACCESS_DENIED;
if (flash_write(p->offset, p->size, p->data))
return EC_LPC_RESULT_ERROR;
@@ -271,6 +275,9 @@ enum lpc_status flash_command_erase(uint8_t *data)
struct lpc_params_flash_erase *p =
(struct lpc_params_flash_erase *)data;
if (system_unsafe_to_overwrite(p->offset, p->size))
return EC_LPC_RESULT_ACCESS_DENIED;
if (flash_erase(p->offset, p->size))
return EC_LPC_RESULT_ERROR;

View File

@@ -7,6 +7,7 @@
#include "console.h"
#include "host_command.h"
#include "lpc.h"
#include "lpc_commands.h"
#include "system.h"
#include "task.h"
@@ -57,6 +58,26 @@ enum system_image_copy_t system_get_image_copy(void)
}
/* Returns true if the given range is overlapped with the active image.
*
* We only care the runtime code since the EC is running over it.
* We don't care about the vector table, FMAP, and init code.
* Read core/$CORE/ec.lds.S about the below extern symbols.
*/
int system_unsafe_to_overwrite(uint32_t offset, uint32_t size) {
int copy = ((uint32_t)system_unsafe_to_overwrite - CONFIG_FLASH_BASE) /
CONFIG_FW_IMAGE_SIZE;
uint32_t r_offset = copy * CONFIG_FW_IMAGE_SIZE;
uint32_t r_size = CONFIG_FW_IMAGE_SIZE;
if ((offset >= r_offset && offset < (r_offset + r_size)) ||
(r_offset >= offset && r_offset < (offset + size)))
return 1;
else
return 0;
}
const char *system_get_image_copy_string(void)
{
static const char * const copy_descs[] = {"unknown", "RO", "A", "B"};
@@ -335,6 +356,13 @@ DECLARE_HOST_COMMAND(EC_LPC_COMMAND_GET_BUILD_INFO, host_command_build_info);
#ifdef CONFIG_REBOOT_EC
static void clean_busy_bits(void) {
#ifdef CONFIG_LPC
lpc_send_host_response(0, EC_LPC_RESULT_SUCCESS);
lpc_send_host_response(1, EC_LPC_RESULT_SUCCESS);
#endif
}
enum lpc_status host_command_reboot(uint8_t *data)
{
struct lpc_params_reboot_ec *p =
@@ -346,14 +374,17 @@ enum lpc_status host_command_reboot(uint8_t *data)
switch (p->target) {
case EC_LPC_IMAGE_RO:
uart_puts("[Rebooting to image RO!\n]");
clean_busy_bits();
system_run_image_copy(SYSTEM_IMAGE_RO);
break;
case EC_LPC_IMAGE_RW_A:
uart_puts("[Rebooting to image A!]\n");
clean_busy_bits();
system_run_image_copy(SYSTEM_IMAGE_RW_A);
break;
case EC_LPC_IMAGE_RW_B:
uart_puts("[Rebooting to image B!]\n");
clean_busy_bits();
system_run_image_copy(SYSTEM_IMAGE_RW_B);
break;
default:

View File

@@ -102,6 +102,7 @@ enum lpc_status {
EC_LPC_RESULT_INVALID_COMMAND = 1,
EC_LPC_RESULT_ERROR = 2,
EC_LPC_RESULT_INVALID_PARAM = 3,
EC_LPC_RESULT_ACCESS_DENIED = 4,
};

View File

@@ -65,6 +65,9 @@ const char *system_get_reset_cause_string(void);
/* Returns the image copy which is currently running. */
enum system_image_copy_t system_get_image_copy(void);
/* Returns true if the given range is overlapped with the active image. */
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);