diff options
Diffstat (limited to 'test/flash.c')
-rw-r--r-- | test/flash.c | 507 |
1 files changed, 0 insertions, 507 deletions
diff --git a/test/flash.c b/test/flash.c deleted file mode 100644 index 4f9ca74016..0000000000 --- a/test/flash.c +++ /dev/null @@ -1,507 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Console commands to trigger flash host commands */ - -#include "console.h" -#include "ec_commands.h" -#include "flash.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "system.h" -#include "task.h" -#include "test_util.h" -#include "timer.h" -#include "util.h" - -static int mock_wp = -1; - -static int mock_flash_op_fail = EC_SUCCESS; - -const char *testdata = "TestData00000000"; /* 16 bytes excluding NULL end */ - -char flash_recorded_data[128]; - -#define BOOT_WP_MASK TEST_STATE_MASK(TEST_STATE_STEP_2) - -/*****************************************************************************/ -/* Emulator-only mock functions */ -#ifdef EMU_BUILD -static int mock_is_running_img; - -int system_unsafe_to_overwrite(uint32_t offset, uint32_t size) -{ - return mock_is_running_img; -} -#endif - -/*****************************************************************************/ -/* Mock functions */ -void host_send_response(struct host_cmd_handler_args *args) -{ - /* Do nothing */ -} - -int flash_pre_op(void) -{ - return mock_flash_op_fail; -} - -int gpio_get_level(enum gpio_signal signal) -{ - if (mock_wp == -1) - mock_wp = !!(test_get_state() & BOOT_WP_MASK); - -#if defined(CONFIG_WP_ACTIVE_HIGH) - if (signal == GPIO_WP) - return mock_wp; -#else - if (signal == GPIO_WP_L) - return !mock_wp; -#endif - - /* Signal other than write protect. Just return 0. */ - return 0; -} - -/*****************************************************************************/ -/* Test utilities */ - -static void record_flash(int offset, int size) -{ - memcpy(flash_recorded_data, __host_flash + offset, size); -} - -static int verify_flash(int offset, int size) -{ - TEST_ASSERT_ARRAY_EQ(flash_recorded_data, __host_flash + offset, size); - return EC_SUCCESS; -} - -static int verify_write(int offset, int size, const char *data) -{ - int i; - - for (i = 0; i < size; ++i) - if (__host_flash[offset + i] != data[i]) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -static int verify_erase(int offset, int size) -{ - int i; - - for (i = 0; i < size; ++i) - if ((__host_flash[offset + i] & 0xff) != 0xff) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - - -#define VERIFY_NO_WRITE(off, sz, d) \ - do { \ - record_flash(off, sz); \ - TEST_ASSERT(host_command_write(off, sz, d) != EC_SUCCESS); \ - TEST_ASSERT(verify_flash(off, sz) == EC_SUCCESS); \ - } while (0) - -#define VERIFY_NO_ERASE(off, sz) \ - do { \ - record_flash(off, sz); \ - TEST_ASSERT(host_command_erase(off, sz) != EC_SUCCESS); \ - TEST_ASSERT(verify_flash(off, sz) == EC_SUCCESS); \ - } while (0) - -#define VERIFY_WRITE(off, sz, d) \ - do { \ - TEST_ASSERT(host_command_write(off, sz, d) == EC_SUCCESS); \ - TEST_ASSERT(verify_write(off, sz, d) == EC_SUCCESS); \ - } while (0) - -#define VERIFY_ERASE(off, sz) \ - do { \ - TEST_ASSERT(host_command_erase(off, sz) == EC_SUCCESS); \ - TEST_ASSERT(verify_erase(off, sz) == EC_SUCCESS); \ - } 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) - -#define VERIFY_REGION_INFO(r, o, s) \ - do { \ - uint32_t offset, size; \ - TEST_ASSERT(host_command_region_info(r, &offset, &size) == \ - EC_RES_SUCCESS); \ - TEST_ASSERT(offset == (o)); \ - TEST_ASSERT(size == (s)); \ - } while (0) - -int host_command_read(int offset, int size, char *out) -{ - struct ec_params_flash_read params; - - params.offset = offset; - params.size = size; - - return test_send_host_command(EC_CMD_FLASH_READ, 0, ¶ms, - sizeof(params), out, size); -} - -int host_command_write(int offset, int size, const char *data) -{ - uint8_t buf[256]; - struct ec_params_flash_write *params = - (struct ec_params_flash_write *)buf; - - params->offset = offset; - params->size = size; - memcpy(params + 1, data, size); - - return test_send_host_command(EC_CMD_FLASH_WRITE, EC_VER_FLASH_WRITE, - buf, size + sizeof(*params), NULL, 0); -} - -int host_command_erase(int offset, int size) -{ - struct ec_params_flash_write params; - - params.offset = offset; - params.size = size; - - return test_send_host_command(EC_CMD_FLASH_ERASE, 0, ¶ms, - sizeof(params), NULL, 0); -} - -int host_command_protect(uint32_t mask, uint32_t flags, - uint32_t *flags_out, uint32_t *valid_out, - uint32_t *writable_out) -{ - struct ec_params_flash_protect params; - struct ec_response_flash_protect resp; - int res; - - params.mask = mask; - params.flags = flags; - - res = test_send_host_command(EC_CMD_FLASH_PROTECT, 1, ¶ms, - sizeof(params), &resp, sizeof(resp)); - - if (res == EC_RES_SUCCESS) { - if (flags_out) - *flags_out = resp.flags; - if (valid_out) - *valid_out = resp.valid_flags; - if (writable_out) - *writable_out = resp.writable_flags; - } - - return res; -} - -int host_command_region_info(enum ec_flash_region reg, uint32_t *offset, - uint32_t *size) -{ - struct ec_params_flash_region_info params; - struct ec_response_flash_region_info resp; - int res; - - params.region = reg; - - res = test_send_host_command(EC_CMD_FLASH_REGION_INFO, 1, ¶ms, - sizeof(params), &resp, sizeof(resp)); - - *offset = resp.offset; - *size = resp.size; - - return res; -} - -/*****************************************************************************/ -/* Tests */ -static int test_read(void) -{ - char buf[16]; - -#ifdef EMU_BUILD - int i; - /* Fill in some numbers so they are not all 0xff */ - for (i = 0; i < sizeof(buf); ++i) - __host_flash[i] = i * i + i; -#endif - - /* The first few bytes in the flash should always contain some code */ - TEST_ASSERT(!crec_flash_is_erased(0, sizeof(buf))); - - TEST_ASSERT(host_command_read(0, sizeof(buf), buf) == EC_RES_SUCCESS); - TEST_ASSERT_ARRAY_EQ(buf, (char *)CONFIG_PROGRAM_MEMORY_BASE, - sizeof(buf)); - - return EC_SUCCESS; -} - -static int test_is_erased(void) -{ - int i; - -#ifdef EMU_BUILD - memset(__host_flash, 0xff, 1024); - TEST_ASSERT(crec_flash_is_erased(0, 1024)); - - for (i = 0; i < 1024; ++i) { - __host_flash[i] = 0xec; - TEST_ASSERT(!crec_flash_is_erased(0, 1024)); - __host_flash[i] = 0xff; - } -#else - ccprintf("Skip. Emulator only test.\n"); -#endif - - return EC_SUCCESS; -} - -static int test_overwrite_current(void) -{ - uint32_t offset, size; - - /* Test that we cannot overwrite current image */ - if (system_get_image_copy() == EC_IMAGE_RO) { - offset = CONFIG_RO_STORAGE_OFF; - size = CONFIG_RO_SIZE; - } else { - offset = CONFIG_RW_STORAGE_OFF; - size = CONFIG_RW_SIZE; - } - -#ifdef EMU_BUILD - mock_is_running_img = 1; -#endif - - VERIFY_NO_ERASE(offset, strlen(testdata)); - VERIFY_NO_ERASE(offset + size - strlen(testdata), strlen(testdata)); - VERIFY_NO_WRITE(offset, strlen(testdata), testdata); - VERIFY_NO_WRITE(offset + size - strlen(testdata), strlen(testdata), - testdata); - - return EC_SUCCESS; -} - -static int test_overwrite_other(void) -{ - uint32_t offset, size; - - /* Test that we can overwrite the other image */ - if (system_is_in_rw()) { - offset = CONFIG_RO_STORAGE_OFF; - size = CONFIG_RO_SIZE; - } else { - offset = CONFIG_RW_STORAGE_OFF; - size = CONFIG_RW_SIZE; - } - -#ifdef EMU_BUILD - mock_is_running_img = 0; -#endif - - VERIFY_ERASE(offset, strlen(testdata)); - VERIFY_ERASE(offset + size - strlen(testdata), strlen(testdata)); - VERIFY_WRITE(offset, strlen(testdata), testdata); - VERIFY_WRITE(offset + size - strlen(testdata), strlen(testdata), - testdata); - - return EC_SUCCESS; -} - -static int test_op_failure(void) -{ - mock_flash_op_fail = EC_ERROR_UNKNOWN; - VERIFY_NO_WRITE(CONFIG_RO_STORAGE_OFF, sizeof(testdata), testdata); - VERIFY_NO_WRITE(CONFIG_RW_STORAGE_OFF, sizeof(testdata), testdata); - VERIFY_NO_ERASE(CONFIG_RO_STORAGE_OFF, CONFIG_FLASH_ERASE_SIZE); - VERIFY_NO_ERASE(CONFIG_RW_STORAGE_OFF, CONFIG_FLASH_ERASE_SIZE); - mock_flash_op_fail = EC_SUCCESS; - - return EC_SUCCESS; -} - -static int test_flash_info(void) -{ - struct ec_response_flash_info_1 resp; - - TEST_ASSERT(test_send_host_command(EC_CMD_FLASH_INFO, 1, NULL, 0, - &resp, sizeof(resp)) == EC_RES_SUCCESS); - - TEST_CHECK((resp.flash_size == CONFIG_FLASH_SIZE_BYTES) && - (resp.write_block_size == CONFIG_FLASH_WRITE_SIZE) && - (resp.erase_block_size == CONFIG_FLASH_ERASE_SIZE) && - (resp.protect_block_size == CONFIG_FLASH_BANK_SIZE)); -} - -static int test_region_info(void) -{ - VERIFY_REGION_INFO(EC_FLASH_REGION_RO, - CONFIG_EC_PROTECTED_STORAGE_OFF + - CONFIG_RO_STORAGE_OFF, EC_FLASH_REGION_RO_SIZE); - VERIFY_REGION_INFO(EC_FLASH_REGION_ACTIVE, - CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_STORAGE_OFF, - CONFIG_EC_WRITABLE_STORAGE_SIZE); - VERIFY_REGION_INFO(EC_FLASH_REGION_WP_RO, - CONFIG_WP_STORAGE_OFF, CONFIG_WP_STORAGE_SIZE); - VERIFY_REGION_INFO(EC_FLASH_REGION_UPDATE, - CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_STORAGE_OFF, - CONFIG_EC_WRITABLE_STORAGE_SIZE); - - 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); - SET_WP_FLAGS(EC_FLASH_PROTECT_ALL_NOW, 0); - ASSERT_WP_FLAGS(EC_FLASH_PROTECT_ALL_NOW | EC_FLASH_PROTECT_RO_AT_BOOT); - - /* Check we cannot erase anything */ - TEST_ASSERT(crec_flash_physical_erase(CONFIG_RO_STORAGE_OFF, - CONFIG_FLASH_ERASE_SIZE) != EC_SUCCESS); - TEST_ASSERT(crec_flash_physical_erase(CONFIG_RW_STORAGE_OFF, - CONFIG_FLASH_ERASE_SIZE) != EC_SUCCESS); - - /* We should not even try to write/erase */ - VERIFY_NO_ERASE(CONFIG_RO_STORAGE_OFF, CONFIG_FLASH_ERASE_SIZE); - VERIFY_NO_ERASE(CONFIG_RW_STORAGE_OFF, CONFIG_FLASH_ERASE_SIZE); - VERIFY_NO_WRITE(CONFIG_RO_STORAGE_OFF, sizeof(testdata), testdata); - VERIFY_NO_WRITE(CONFIG_RW_STORAGE_OFF, sizeof(testdata), testdata); - - return EC_SUCCESS; -} - -static int test_boot_write_protect(void) -{ - /* Check write protect state persists through reboot */ - ASSERT_WP_FLAGS(EC_FLASH_PROTECT_RO_NOW | EC_FLASH_PROTECT_RO_AT_BOOT); - TEST_ASSERT(crec_flash_physical_erase(CONFIG_RO_STORAGE_OFF, - CONFIG_FLASH_ERASE_SIZE) != EC_SUCCESS); - - return EC_SUCCESS; -} - -static int test_boot_no_write_protect(void) -{ - /* Check write protect is not enabled if WP GPIO is deasserted */ - ASSERT_WP_NO_FLAGS(EC_FLASH_PROTECT_RO_NOW); - ASSERT_WP_FLAGS(EC_FLASH_PROTECT_RO_AT_BOOT); - - return EC_SUCCESS; -} - -int test_clean_up_(void) -{ - SET_WP_FLAGS(EC_FLASH_PROTECT_RO_AT_BOOT, 0); - return EC_SUCCESS; -} - -void test_clean_up(void) -{ - test_clean_up_(); /* Throw away return value */ -} - -static void run_test_step1(void) -{ - test_reset(); - mock_wp = 0; - - RUN_TEST(test_read); - RUN_TEST(test_is_erased); - RUN_TEST(test_overwrite_current); - RUN_TEST(test_overwrite_other); - RUN_TEST(test_op_failure); - RUN_TEST(test_flash_info); - RUN_TEST(test_region_info); - RUN_TEST(test_write_protect); - - if (test_get_error_count()) - test_reboot_to_next_step(TEST_STATE_FAILED); - else - test_reboot_to_next_step(TEST_STATE_STEP_2); -} - -static void run_test_step2(void) -{ - RUN_TEST(test_boot_write_protect); - - if (test_get_error_count()) - test_reboot_to_next_step(TEST_STATE_FAILED); - else - test_reboot_to_next_step(TEST_STATE_STEP_3); -} - -static void run_test_step3(void) -{ - RUN_TEST(test_boot_no_write_protect); - - if (test_get_error_count()) - test_reboot_to_next_step(TEST_STATE_FAILED); - else - test_reboot_to_next_step(TEST_STATE_PASSED); -} - -void test_run_step(uint32_t state) -{ - if (state & TEST_STATE_MASK(TEST_STATE_STEP_1)) - run_test_step1(); - else if (state & TEST_STATE_MASK(TEST_STATE_STEP_2)) - run_test_step2(); - else if (state & TEST_STATE_MASK(TEST_STATE_STEP_3)) - run_test_step3(); -} - -int task_test(void *data) -{ - test_run_multistep(); - return EC_SUCCESS; -} - -void run_test(int argc, char **argv) -{ - msleep(30); /* Wait for TASK_ID_TEST to initialize */ - task_wake(TASK_ID_TEST); -} |