diff --git a/hal/va416x0.c b/hal/va416x0.c index 446e3cd1..1e6c8b62 100644 --- a/hal/va416x0.c +++ b/hal/va416x0.c @@ -369,7 +369,7 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len) (void)len; return 0; } - +#endif /* !WOLFBOOT_UNIT_TEST_VA416X0_FRAM */ #ifdef EXT_FLASH void ext_flash_lock(void) @@ -395,7 +395,9 @@ void ext_flash_unlock(void) static void iram_write(void *dst, const void *src, int len) { while (len > 0) { - uintptr_t addr = (uintptr_t)dst & ~3u; + /* Pointer-width mask: ~3u is 32 bits and would zero the high + * word of the address on 64-bit platforms. */ + uintptr_t addr = (uintptr_t)dst & ~(uintptr_t)3; uint32_t off = (uintptr_t)dst & 3u; uint32_t word = *(volatile uint32_t *)addr; uint8_t *wp = (uint8_t *)&word; @@ -412,7 +414,8 @@ static void iram_write(void *dst, const void *src, int len) static void iram_fill(void *dst, uint8_t val, int len) { while (len > 0) { - uintptr_t addr = (uintptr_t)dst & ~3u; + /* Pointer-width mask (see iram_write). */ + uintptr_t addr = (uintptr_t)dst & ~(uintptr_t)3; uint32_t off = (uintptr_t)dst & 3u; uint32_t word = *(volatile uint32_t *)addr; uint8_t *wp = (uint8_t *)&word; @@ -527,6 +530,7 @@ static int test_ext_flash(void) #endif /* TEST_EXT_FLASH */ #endif /* EXT_FLASH */ +#ifndef WOLFBOOT_UNIT_TEST_VA416X0_FRAM #ifdef __WOLFBOOT /* build for wolfBoot only */ /* Configure Error Detection and Correction (EDAC) */ static void ConfigEdac(uint32_t ramScrub, uint32_t romScrub) diff --git a/tools/unit-tests/unit-va416x0-fram.c b/tools/unit-tests/unit-va416x0-fram.c index 9383647f..3a1e279b 100644 --- a/tools/unit-tests/unit-va416x0-fram.c +++ b/tools/unit-tests/unit-va416x0-fram.c @@ -4,8 +4,12 @@ #include #define WOLFBOOT_UNIT_TEST_VA416X0_FRAM +#define EXT_FLASH -#define FRAM_SIZE (256U * 1024U) +/* The host shadow IRAM lives at a 64-bit pointer address, so keep the + * FRAM bounds check from rejecting the test buffer (the hardware value + * is 256 KiB). */ +#define FRAM_SIZE (0xFFFFFFFFU) #define ROM_SPI_BANK 0 #define SPI_NUM_BANKS 1 #define SPI_STATUS_TFE_Msk 0x01U @@ -61,6 +65,16 @@ enum { static mock_spi_regs_t mock_vor_spi; #define VOR_SPI (&mock_vor_spi) +/* Mock of the Vorago SYSCONFIG register block (vendor headers are not + * available on the host). */ +typedef struct { + uint32_t ROM_PROT; +} mock_vor_sysconfig_t; + +static mock_vor_sysconfig_t mock_vor_sysconfig; +#define VOR_SYSCONFIG (&mock_vor_sysconfig) +#define SYSCONFIG_ROM_PROT_WREN_Msk (1U << 0) + static hal_status_t transmit_script[8]; static bool transmit_close_flags[8]; static int transmit_script_len; @@ -169,12 +183,58 @@ START_TEST(test_fram_write_command_failure_aborts_split_transaction) } END_TEST +/* Shadow IRAM buffer for the ext_flash_erase() tests: the HAL writes + * the erased bytes through the raw address, so the address must point + * at real host memory. */ +static uint8_t g_iram[64]; + +/* iram_write/iram_fill compute the enclosing word with + * (uintptr_t)dst & ~3u - a 32-bit mask. That is the whole pointer on + * the 32-bit va416x0 target, but on 64-bit platforms it zeroes the + * high word of the address. Unaligned start and end so off != 0 and + * the word boundary crossing are exercised. */ +START_TEST(test_iram_write_unaligned_64bit_addr) +{ + uint8_t data[12]; + int i; + + memset(g_iram, 0x00, sizeof(g_iram)); + for (i = 0; i < 12; i++) + data[i] = (uint8_t)(0x40 + i); + + iram_write((void *)(g_iram + 1), data, 12); + + for (i = 0; i < 12; i++) + ck_assert_uint_eq(g_iram[1 + i], data[i]); + /* Neighboring bytes untouched. */ + ck_assert_uint_eq(g_iram[0], 0x00); + ck_assert_uint_eq(g_iram[13], 0x00); +} +END_TEST + +START_TEST(test_iram_fill_unaligned_64bit_addr) +{ + int i; + + memset(g_iram, 0x00, sizeof(g_iram)); + iram_fill((void *)(g_iram + 2), 0xEE, 10); + + for (i = 0; i < 10; i++) + ck_assert_uint_eq(g_iram[2 + i], 0xEE); + ck_assert_uint_eq(g_iram[0], 0x00); + ck_assert_uint_eq(g_iram[1], 0x00); + ck_assert_uint_eq(g_iram[12], 0x00); +} +END_TEST + Suite *va416x0_fram_suite(void) { Suite *s = suite_create("va416x0-fram"); TCase *tc = tcase_create("fram"); tcase_add_test(tc, test_fram_write_command_failure_aborts_split_transaction); + tcase_add_test(tc, test_iram_write_unaligned_64bit_addr); + tcase_add_test(tc, test_iram_fill_unaligned_64bit_addr); suite_add_tcase(s, tc); return s;