summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2013-04-16 15:18:06 +0800
committerChromeBot <chrome-bot@google.com>2013-04-17 21:07:09 -0700
commit5b04478423ef30739db9baf5ed3ebc1135c8504f (patch)
treeceda777746fc51eaccc1f522eca4d1870c6f69db
parent36317d46f7be6ea6f6b4ed82012ae2c5a5a95d48 (diff)
downloadchrome-ec-5b04478423ef30739db9baf5ed3ebc1135c8504f.tar.gz
Add flash write protect test
BUG=chrome-os-partner:18598 TEST=Run on Spring BRANCH=None Change-Id: I6488ace5d6b758410c76d7625787413eba37cbe9 Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/48208 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--chip/lm4/gpio.c2
-rw-r--r--chip/stm32/gpio-stm32f100.c2
-rw-r--r--chip/stm32/gpio-stm32l15x.c2
-rw-r--r--test/flash.c140
4 files changed, 133 insertions, 13 deletions
diff --git a/chip/lm4/gpio.c b/chip/lm4/gpio.c
index d49eeae4f5..8429262abe 100644
--- a/chip/lm4/gpio.c
+++ b/chip/lm4/gpio.c
@@ -77,7 +77,7 @@ void gpio_set_alternate_function(int port, int mask, int func)
LM4_GPIO_DEN(port) |= mask;
}
-int gpio_get_level(enum gpio_signal signal)
+test_mockable int gpio_get_level(enum gpio_signal signal)
{
return LM4_GPIO_DATA(gpio_list[signal].port,
gpio_list[signal].mask) ? 1 : 0;
diff --git a/chip/stm32/gpio-stm32f100.c b/chip/stm32/gpio-stm32f100.c
index 9ce1ab110a..fdc2ff2549 100644
--- a/chip/stm32/gpio-stm32f100.c
+++ b/chip/stm32/gpio-stm32f100.c
@@ -169,7 +169,7 @@ uint16_t *gpio_get_level_reg(enum gpio_signal signal, uint32_t *mask)
}
-int gpio_get_level(enum gpio_signal signal)
+test_mockable int gpio_get_level(enum gpio_signal signal)
{
return !!(STM32_GPIO_IDR(gpio_list[signal].port) &
gpio_list[signal].mask);
diff --git a/chip/stm32/gpio-stm32l15x.c b/chip/stm32/gpio-stm32l15x.c
index 70cdec0b31..7b17cd363c 100644
--- a/chip/stm32/gpio-stm32l15x.c
+++ b/chip/stm32/gpio-stm32l15x.c
@@ -172,7 +172,7 @@ void gpio_set_alternate_function(int port, int mask, int func)
STM32_GPIO_MODER(port) = moder;
}
-int gpio_get_level(enum gpio_signal signal)
+test_mockable int gpio_get_level(enum gpio_signal signal)
{
return !!(STM32_GPIO_IDR(gpio_list[signal].port) &
gpio_list[signal].mask);
diff --git a/test/flash.c b/test/flash.c
index 23623ad59a..52a4ec625f 100644
--- a/test/flash.c
+++ b/test/flash.c
@@ -8,6 +8,8 @@
#include "board.h"
#include "console.h"
#include "ec_commands.h"
+#include "gpio.h"
+#include "hooks.h"
#include "host_command.h"
#include "system.h"
#include "timer.h"
@@ -22,6 +24,8 @@ static char last_write_data[64];
static int last_erase_offset;
static int last_erase_size;
+static int mock_wp;
+
/*****************************************************************************/
/* Mock functions */
void host_send_response(struct host_cmd_handler_args *args)
@@ -44,6 +48,21 @@ int flash_erase(int offset, int size)
return EC_SUCCESS;
}
+int gpio_get_level(enum gpio_signal signal)
+{
+ const char *name = gpio_list[signal].name;
+
+ if (strcasecmp(name, "WRITE_PROTECTn") == 0 ||
+ strcasecmp(name, "WP_L") == 0)
+ return !mock_wp;
+ if (strcasecmp(name, "WRITE_PROTECT") == 0 ||
+ strcasecmp(name, "WP") == 0)
+ return mock_wp;
+
+ /* Signal other than write protect. Just return 0. */
+ return 0;
+}
+
/*****************************************************************************/
/* Test utilities */
#define RUN_TEST(n) \
@@ -80,36 +99,60 @@ static int verify_write(int offset, int size, const char *data)
return EC_SUCCESS;
}
+
+#define TEST_ASSERT(x) \
+ do { \
+ if (!(x)) \
+ return EC_ERROR_UNKNOWN; \
+ } while (0)
+
#define VERIFY_NO_WRITE(off, sz, d) \
do { \
begin_verify(); \
host_command_write(off, sz, d); \
- if (last_write_offset != -1 || last_write_size != -1) \
- return EC_ERROR_UNKNOWN; \
+ TEST_ASSERT(last_write_offset == -1 && last_write_size == -1); \
} while (0)
#define VERIFY_NO_ERASE(off, sz) \
do { \
begin_verify(); \
host_command_erase(off, sz); \
- if (last_erase_offset != -1 || last_erase_size != -1) \
- return EC_ERROR_UNKNOWN; \
+ TEST_ASSERT(last_erase_offset == -1 && last_erase_size == -1); \
} while (0)
#define VERIFY_WRITE(off, sz, d) \
do { \
begin_verify(); \
host_command_write(off, sz, d); \
- if (verify_write(off, sz, d) != EC_SUCCESS) \
- return EC_ERROR_UNKNOWN; \
+ TEST_ASSERT(verify_write(off, sz, d) == EC_SUCCESS); \
} while (0)
#define VERIFY_ERASE(off, sz) \
do { \
begin_verify(); \
host_command_erase(off, sz); \
- if (last_erase_offset != off || last_erase_size != sz) \
- return EC_ERROR_UNKNOWN; \
+ TEST_ASSERT(last_erase_offset == off && \
+ last_erase_size == sz); \
+ } while (0)
+
+#define SET_WP_FLAGS(m, f) \
+ TEST_ASSERT(host_command_protect(m, ((f) ? m : 0), \
+ NULL, NULL, NULL) == EC_RES_SUCCESS)
+
+#define ASSERT_WP_FLAGS(f) \
+ do { \
+ uint32_t flags; \
+ TEST_ASSERT(host_command_protect(0, 0, &flags, NULL, NULL) == \
+ EC_RES_SUCCESS); \
+ TEST_ASSERT(flags & (f)); \
+ } while (0)
+
+#define ASSERT_WP_NO_FLAGS(f) \
+ do { \
+ uint32_t flags; \
+ TEST_ASSERT(host_command_protect(0, 0, &flags, NULL, NULL) == \
+ EC_RES_SUCCESS); \
+ TEST_ASSERT((flags & (f)) == 0); \
} while (0)
int host_command_write(int offset, int size, const char *data)
@@ -151,6 +194,41 @@ int host_command_erase(int offset, int size)
return host_command_process(&args);
}
+int host_command_protect(uint32_t mask, uint32_t flags,
+ uint32_t *flags_out, uint32_t *valid_out,
+ uint32_t *writable_out)
+{
+ struct host_cmd_handler_args args;
+ struct ec_params_flash_protect params;
+ struct ec_response_flash_protect *r =
+ (struct ec_response_flash_protect *)&params;
+ int res;
+
+ params.mask = mask;
+ params.flags = flags;
+
+ args.version = 1;
+ args.command = EC_CMD_FLASH_PROTECT;
+ args.params = &params;
+ args.params_size = sizeof(params);
+ args.response = &params;
+ args.response_max = EC_HOST_PARAM_SIZE;
+ args.response_size = 0;
+
+ res = host_command_process(&args);
+
+ if (res == EC_RES_SUCCESS) {
+ if (flags_out)
+ *flags_out = r->flags;
+ if (valid_out)
+ *valid_out = r->valid_flags;
+ if (writable_out)
+ *writable_out = r->writable_flags;
+ }
+
+ return res;
+}
+
/*****************************************************************************/
/* Tests */
static int test_overwrite_current(void)
@@ -197,20 +275,62 @@ static int test_overwrite_other(void)
return EC_SUCCESS;
}
+static int test_write_protect(void)
+{
+ /* Test we can control write protect GPIO */
+ mock_wp = 0;
+ ASSERT_WP_NO_FLAGS(EC_FLASH_PROTECT_GPIO_ASSERTED);
+
+ mock_wp = 1;
+ ASSERT_WP_FLAGS(EC_FLASH_PROTECT_GPIO_ASSERTED);
+
+ /* Test software WP can be disable if nothing is actually protected */
+ SET_WP_FLAGS(EC_FLASH_PROTECT_RO_AT_BOOT, 1);
+ SET_WP_FLAGS(EC_FLASH_PROTECT_RO_AT_BOOT, 0);
+ ASSERT_WP_NO_FLAGS(EC_FLASH_PROTECT_RO_AT_BOOT);
+
+ /* Actually protect flash and test software WP cannot be disabled */
+ SET_WP_FLAGS(EC_FLASH_PROTECT_RO_AT_BOOT, 1);
+ SET_WP_FLAGS(EC_FLASH_PROTECT_ALL_NOW, 1);
+ SET_WP_FLAGS(EC_FLASH_PROTECT_RO_AT_BOOT, 0);
+ ASSERT_WP_FLAGS(EC_FLASH_PROTECT_ALL_NOW | EC_FLASH_PROTECT_RO_AT_BOOT);
+
+ return EC_SUCCESS;
+}
+
+static int clear_wp(void)
+{
+ SET_WP_FLAGS(EC_FLASH_PROTECT_RO_AT_BOOT, 0);
+ return EC_SUCCESS;
+}
+
+static void test_setup(void)
+{
+ clear_wp();
+}
+DECLARE_HOOK(HOOK_INIT, test_setup, HOOK_PRIO_LAST);
+
static int command_run_test(int argc, char **argv)
{
error_count = 0;
+ mock_wp = 0;
RUN_TEST(test_overwrite_current);
RUN_TEST(test_overwrite_other);
+ RUN_TEST(test_write_protect);
if (error_count) {
ccprintf("Failed %d tests!\n", error_count);
- return EC_ERROR_UNKNOWN;
} else {
ccprintf("Pass!\n");
- return EC_SUCCESS;
}
+
+ ccprintf("Rebooting to clear WP...\n");
+ cflush();
+ system_reset(SYSTEM_RESET_HARD);
+
+ /* Never reaches here */
+ return EC_ERROR_UNKNOWN;
}
DECLARE_CONSOLE_COMMAND(runtest, command_run_test,
NULL, NULL, NULL);