diff options
-rw-r--r-- | board/host/board.c | 1 | ||||
-rw-r--r-- | board/host/board.h | 3 | ||||
-rw-r--r-- | chip/host/build.mk | 2 | ||||
-rw-r--r-- | chip/host/config.h | 11 | ||||
-rw-r--r-- | chip/host/flash.c | 135 | ||||
-rw-r--r-- | chip/host/registers.h | 11 | ||||
-rw-r--r-- | chip/lm4/config.h | 1 | ||||
-rw-r--r-- | chip/stm32/config.h | 1 | ||||
-rw-r--r-- | common/build.mk | 3 | ||||
-rw-r--r-- | common/system_common.c | 2 | ||||
-rw-r--r-- | common/test_util.c | 5 | ||||
-rw-r--r-- | core/host/main.c | 3 | ||||
-rw-r--r-- | include/test_util.h | 2 | ||||
-rw-r--r-- | test/build.mk | 2 | ||||
-rw-r--r-- | test/flash.c | 52 |
15 files changed, 211 insertions, 23 deletions
diff --git a/board/host/board.c b/board/host/board.c index 10d8d1d3c4..0eda62b0ee 100644 --- a/board/host/board.c +++ b/board/host/board.c @@ -12,6 +12,7 @@ const struct gpio_info gpio_list[GPIO_COUNT] = { {"EC_INT", 0, 0, 0, 0}, {"LID_OPEN", 0, 0, 0, 0}, {"POWER_BUTTON_L", 0, 0, 0, 0}, + {"WP", 0, 0, 0, 0}, }; static int dummy_temp_get_val(int idx, int *temp_ptr) diff --git a/board/host/board.h b/board/host/board.h index 553f55c76c..632596b64d 100644 --- a/board/host/board.h +++ b/board/host/board.h @@ -20,10 +20,13 @@ #define CONFIG_POWER_BUTTON #define CONFIG_TEMP_SENSOR +#define CONFIG_WP_ACTIVE_HIGH + enum gpio_signal { GPIO_EC_INT, GPIO_LID_OPEN, GPIO_POWER_BUTTON_L, + GPIO_WP, GPIO_COUNT }; diff --git a/chip/host/build.mk b/chip/host/build.mk index 110daefb8b..866c84da20 100644 --- a/chip/host/build.mk +++ b/chip/host/build.mk @@ -8,5 +8,5 @@ CORE:=host -chip-y=system.o gpio.o uart.o persistence.o +chip-y=system.o gpio.o uart.o persistence.o flash.o chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o diff --git a/chip/host/config.h b/chip/host/config.h index c296e1b7cc..9825f086e9 100644 --- a/chip/host/config.h +++ b/chip/host/config.h @@ -9,14 +9,16 @@ #define __CONFIG_H /* Memory mapping */ -#define CONFIG_FLASH_BASE 0x08000000 #define CONFIG_FLASH_PHYSICAL_SIZE 0x00020000 #define CONFIG_FLASH_SIZE CONFIG_FLASH_PHYSICAL_SIZE +extern char __host_flash[CONFIG_FLASH_PHYSICAL_SIZE]; + +#define CONFIG_FLASH_BASE ((uintptr_t)__host_flash) #define CONFIG_FLASH_BANK_SIZE 0x1000 #define CONFIG_FLASH_ERASE_SIZE 0x0400 /* erase bank size */ #define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */ -#define CONFIG_RAM_BASE 0x20000000 -#define CONFIG_RAM_SIZE 0x00002000 +#define CONFIG_RAM_BASE 0x0 /* Not supported */ +#define CONFIG_RAM_SIZE 0x0 /* Not supported */ /* Size of one firmware image in flash */ #define CONFIG_FW_IMAGE_SIZE (64 * 1024) @@ -28,6 +30,9 @@ #define CONFIG_FW_WP_RO_OFF CONFIG_FW_RO_OFF #define CONFIG_FW_WP_RO_SIZE CONFIG_FW_IMAGE_SIZE +/* Features */ +#define CONFIG_FLASH + /* * Put this after RO to give RW more space and make RO write protect region * contiguous. diff --git a/chip/host/flash.c b/chip/host/flash.c new file mode 100644 index 0000000000..24023c5155 --- /dev/null +++ b/chip/host/flash.c @@ -0,0 +1,135 @@ +/* Copyright (c) 2013 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. + */ + +/* Flash module for emulator */ + +#include <stdio.h> + +#include "config.h" +#include "flash.h" +#include "persistence.h" +#include "util.h" + +char __host_flash[CONFIG_FLASH_PHYSICAL_SIZE]; +uint8_t __host_flash_protect[PHYSICAL_BANKS]; + +static int flash_check_protect(int offset, int size) +{ + int first_bank = offset / CONFIG_FLASH_BANK_SIZE; + int last_bank = DIV_ROUND_UP(offset + size + 1, + CONFIG_FLASH_BANK_SIZE); + int bank; + + for (bank = first_bank; bank <= last_bank; ++bank) + if (__host_flash_protect[bank]) + return 1; + return 0; +} + +static void flash_set_persistent(void) +{ + FILE *f = get_persistent_storage("flash", "wb"); + int sz; + + ASSERT(f != NULL); + + sz = fwrite(__host_flash, sizeof(__host_flash), 1, f); + ASSERT(sz == 1); + + release_persistent_storage(f); +} + +static void flash_get_persistent(void) +{ + FILE *f = get_persistent_storage("flash", "rb"); + + if (f == NULL) { + fprintf(stderr, + "No flash storage found. Initializing to 0xff.\n"); + memset(__host_flash, 0xff, sizeof(__host_flash)); + return; + } + + fread(__host_flash, sizeof(__host_flash), 1, f); + + release_persistent_storage(f); +} + +int flash_physical_write(int offset, int size, const char *data) +{ + ASSERT((size & (CONFIG_FLASH_WRITE_SIZE - 1)) == 0); + + if (flash_check_protect(offset, size)) + return EC_ERROR_ACCESS_DENIED; + + memcpy(__host_flash + offset, data, size); + flash_set_persistent(); + + return EC_SUCCESS; +} + +int flash_physical_erase(int offset, int size) +{ + ASSERT((size & (CONFIG_FLASH_ERASE_SIZE - 1)) == 0); + + if (flash_check_protect(offset, size)) + return EC_ERROR_ACCESS_DENIED; + + memset(__host_flash + offset, 0xff, size); + flash_set_persistent(); + + return EC_SUCCESS; +} + +int flash_physical_get_protect(int bank) +{ + return __host_flash_protect[bank]; +} + +uint32_t flash_physical_get_protect_flags(void) +{ + int i; + uint32_t flags = EC_FLASH_PROTECT_ALL_NOW; + + for (i = 0; i < PHYSICAL_BANKS; ++i) + if (__host_flash_protect[i] == 0) + flags = 0; + + return flags; +} + +int flash_physical_protect_now(int all) +{ + memset(__host_flash_protect, 1, all ? PHYSICAL_BANKS : RO_BANK_COUNT); + return EC_SUCCESS; +} + +int flash_pre_init(void) +{ + uint32_t prot_flags; + + flash_get_persistent(); + + prot_flags = flash_get_protect(); + + if (prot_flags & EC_FLASH_PROTECT_GPIO_ASSERTED) { + /* + * Write protect is asserted. If we want RO flash protected, + * protect it now. + */ + if ((prot_flags & EC_FLASH_PROTECT_RO_AT_BOOT) && + !(prot_flags & EC_FLASH_PROTECT_RO_NOW)) { + int rv = flash_set_protect(EC_FLASH_PROTECT_RO_NOW, + EC_FLASH_PROTECT_RO_NOW); + if (rv) + return rv; + + /* Re-read flags */ + prot_flags = flash_get_protect(); + } + } + + return EC_SUCCESS; +} diff --git a/chip/host/registers.h b/chip/host/registers.h new file mode 100644 index 0000000000..0ee68b8e23 --- /dev/null +++ b/chip/host/registers.h @@ -0,0 +1,11 @@ +/* Copyright (c) 2013 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. + */ + +/* Empty registers header for emulator */ + +/* + * There is no register for emulator, but this file exists to prevent + * compilation failure if any file includes registers.h + */ diff --git a/chip/lm4/config.h b/chip/lm4/config.h index 609a88ae90..6be1085c02 100644 --- a/chip/lm4/config.h +++ b/chip/lm4/config.h @@ -101,6 +101,7 @@ /* Optional features present on this chip */ #define CONFIG_ADC #define CONFIG_FLASH +#define CONFIG_FMAP #define CONFIG_FPU #define CONFIG_I2C #define CONFIG_WATCHDOG diff --git a/chip/stm32/config.h b/chip/stm32/config.h index d4107b1d36..6eb8a48b51 100644 --- a/chip/stm32/config.h +++ b/chip/stm32/config.h @@ -39,6 +39,7 @@ /* support programming on-chip flash */ #define CONFIG_FLASH +#define CONFIG_FMAP /* build with assertions and debug messages */ #define CONFIG_DEBUG diff --git a/common/build.mk b/common/build.mk index 5df925b7d0..912097ce46 100644 --- a/common/build.mk +++ b/common/build.mk @@ -22,7 +22,8 @@ common-$(CONFIG_EOPTION)+=eoption.o common-$(CONFIG_EXTPOWER_GPIO)+=extpower_gpio.o common-$(CONFIG_EXTPOWER_SNOW)+=extpower_snow.o common-$(CONFIG_EXTPOWER_USB)+=extpower_usb.o -common-$(CONFIG_FLASH)+=flash_common.o fmap.o +common-$(CONFIG_FLASH)+=flash_common.o +common-$(CONFIG_FMAP)+=fmap.o common-$(CONFIG_I2C)+=i2c_common.o common-$(CONFIG_I2C_ARBITRATION)+=i2c_arbitration.o common-$(CONFIG_IR357x)+=ir357x.o diff --git a/common/system_common.c b/common/system_common.c index ac85c8051b..03febba603 100644 --- a/common/system_common.c +++ b/common/system_common.c @@ -256,7 +256,7 @@ int system_get_image_used(enum system_image_copy_t copy) return size ? size + 1 : 0; /* 0xea byte IS part of the image */ } -int system_unsafe_to_overwrite(uint32_t offset, uint32_t size) +test_mockable int system_unsafe_to_overwrite(uint32_t offset, uint32_t size) { uint32_t r_offset; uint32_t r_size; diff --git a/common/test_util.c b/common/test_util.c index 8594f3468e..7cd9850645 100644 --- a/common/test_util.c +++ b/common/test_util.c @@ -27,6 +27,11 @@ void test_print_result(void) ccprintf("Pass!\n"); } +int test_get_error_count(void) +{ + return __test_error_count; +} + static int command_run_test(int argc, char **argv) { run_test(); diff --git a/core/host/main.c b/core/host/main.c index e96dc40faa..ba8ec95dcf 100644 --- a/core/host/main.c +++ b/core/host/main.c @@ -5,12 +5,15 @@ /* Entry point of unit test executable */ +#include "flash.h" #include "hooks.h" #include "task.h" #include "timer.h" int main(void) { + flash_pre_init(); + timer_init(); hook_init(); diff --git a/include/test_util.h b/include/test_util.h index e940beda1c..8b99c560d2 100644 --- a/include/test_util.h +++ b/include/test_util.h @@ -56,6 +56,8 @@ void test_reset(void); void test_print_result(void); +int test_get_error_count(void); + extern int __test_error_count; #endif /* __CROS_EC_TEST_UTIL_H */ diff --git a/test/build.mk b/test/build.mk index 17cb6c9853..90f775de0a 100644 --- a/test/build.mk +++ b/test/build.mk @@ -28,7 +28,7 @@ test-list-$(BOARD_peppy)= # Emulator tests test-list-host=mutex pingpong utils kb_scan kb_mkbp lid_sw power_button hooks -test-list-host+=thermal +test-list-host+=thermal flash flash-y=flash.o hooks-y=hooks.o diff --git a/test/flash.c b/test/flash.c index cf6ee659fd..33f47543bd 100644 --- a/test/flash.c +++ b/test/flash.c @@ -17,8 +17,6 @@ #include "timer.h" #include "util.h" -static int error_count; - static int last_write_offset; static int last_write_size; static char last_write_data[64]; @@ -33,9 +31,21 @@ static int mock_wp = -1; #define TEST_STATE_STEP_3 (1 << 2) #define TEST_STATE_BOOT_WP_ON (1 << 3) #define TEST_STATE_PASSED (1 << 4) +#define TEST_STATE_FAILED (1 << 5) #define CLEAN_UP_FLAG_PASSED TEST_STATE_PASSED -#define CLEAN_UP_FLAG_FAILED 0 +#define CLEAN_UP_FLAG_FAILED TEST_STATE_FAILED + +/*****************************************************************************/ +/* 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 */ @@ -240,6 +250,10 @@ static int test_overwrite_current(void) size = CONFIG_FW_RW_SIZE; } +#ifdef EMU_BUILD + mock_is_running_img = 1; +#endif + VERIFY_NO_ERASE(offset, sizeof(d)); VERIFY_NO_ERASE(offset + size - sizeof(d), sizeof(d)); VERIFY_NO_WRITE(offset, sizeof(d), d); @@ -262,6 +276,10 @@ static int test_overwrite_other(void) size = CONFIG_FW_RW_SIZE; } +#ifdef EMU_BUILD + mock_is_running_img = 0; +#endif + VERIFY_ERASE(offset, sizeof(d)); VERIFY_ERASE(offset + size - sizeof(d), sizeof(d)); VERIFY_WRITE(offset, sizeof(d), d); @@ -344,43 +362,37 @@ static void reboot_to_next_step(uint32_t step) static void run_test_step1(void) { - error_count = 0; + test_reset(); 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); + if (test_get_error_count()) reboot_to_clean_up(CLEAN_UP_FLAG_FAILED); - } else { + else reboot_to_next_step(TEST_STATE_STEP_2 | TEST_STATE_BOOT_WP_ON); - } } static void run_test_step2(void) { RUN_TEST(test_boot_write_protect); - if (error_count) { - ccprintf("Failed %d tests!\n", error_count); + if (test_get_error_count()) reboot_to_clean_up(CLEAN_UP_FLAG_FAILED); - } else { + else reboot_to_next_step(TEST_STATE_STEP_3); - } } static void run_test_step3(void) { RUN_TEST(test_boot_no_write_protect); - if (error_count) { - ccprintf("Failed %d tests!\n", error_count); + if (test_get_error_count()) reboot_to_clean_up(CLEAN_UP_FLAG_FAILED); - } else { + else reboot_to_clean_up(CLEAN_UP_FLAG_PASSED); - } } int TaskTest(void *data) @@ -389,6 +401,8 @@ int TaskTest(void *data) if (state & TEST_STATE_PASSED) ccprintf("Pass!\n"); + else if (state & TEST_STATE_FAILED) + ccprintf("Fail!\n"); if (state & TEST_STATE_STEP_2) run_test_step2(); @@ -396,11 +410,17 @@ int TaskTest(void *data) run_test_step3(); else if (state & TEST_STATE_CLEAN_UP) clean_up(); +#ifdef EMU_BUILD + else + run_test_step1(); +#endif return EC_SUCCESS; } +#ifndef EMU_BUILD void run_test(void) { run_test_step1(); } +#endif |