From 6d72f17d5ba5ebfcb5b2251394d95f72eac9e7c4 Mon Sep 17 00:00:00 2001 From: Erik Moqvist Date: Sat, 29 Sep 2018 12:44:50 +0200 Subject: [PATCH] NVM and software EEPROM vector write. --- src/debug/harness.c | 11 +- src/debug/harness.h | 13 +- src/drivers/storage/eeprom_soft.c | 92 ++++--- src/drivers/storage/eeprom_soft.h | 18 ++ src/kernel/types.h | 31 +++ src/oam/nvm.c | 11 + src/oam/nvm.h | 15 ++ src/oam/ports/linux/nvm_port.i | 7 + src/oam/ports/nvm_port_eeprom_soft.i | 10 + tst/debug/harness/main.c | 31 ++- .../software/storage/eeprom_soft/main.c | 234 ++++++++++++------ tst/stubs/drivers/storage/flash_mock.c | 131 +++++++++- tst/stubs/drivers/storage/flash_mock.h | 12 + 13 files changed, 482 insertions(+), 134 deletions(-) diff --git a/src/debug/harness.c b/src/debug/harness.c index d09fb1b15..89620250c 100644 --- a/src/debug/harness.c +++ b/src/debug/harness.c @@ -272,7 +272,7 @@ static struct mock_entry_t *find_mock_entry(const char *id_p) { struct list_iter_t iter; struct mock_entry_t *entry_p; - struct mock_entry_t *unmodified_entry_p; + struct mock_entry_t *new_entry_p; struct mock_entry_cb_t *entry_cb_p; int res; @@ -295,10 +295,11 @@ static struct mock_entry_t *find_mock_entry(const char *id_p) } else { /* Make a copy of the mock entry since the mock callback may modify it. */ - unmodified_entry_p = copy_mock_entry_no_lock(entry_p); + new_entry_p = copy_mock_entry_no_lock(entry_p); res = entry_cb_p->fn(&entry_cb_p->arg[0], - &entry_p->data.buf[0]); + &new_entry_p->data.buf[0], + &new_entry_p->data.size); if (res == 1) { list_remove(&module.mock.list, entry_p); @@ -307,7 +308,7 @@ static struct mock_entry_t *find_mock_entry(const char *id_p) list_add_tail(&module.mock.cb_list, entry_cb_p); } - entry_p = unmodified_entry_p; + entry_p = new_entry_p; } break; @@ -370,7 +371,7 @@ static int read_mock_entry(struct mock_entry_t *entry_p, return (res); } -static int mwrite_cb(void *arg_p, void *buf_p) +static int mwrite_cb(void *arg_p, void *buf_p, size_t *size_p) { int *length_p; diff --git a/src/debug/harness.h b/src/debug/harness.h index fa83c0d3a..0522a6a10 100644 --- a/src/debug/harness.h +++ b/src/debug/harness.h @@ -157,18 +157,23 @@ typedef int (*harness_testcase_cb_t)(void); /** - * The read/assert callback function. + * The read/assert callback function. Modifies a copy of the original + * mock entry. The modified mock entry is read by read/assert + * functions. * * @param[in] arg_p `arg_size` bytes copied from `arg_p` given to * `harness_mock_cwrite()`. - * @param[in] buf_p Mock entry data buffer, equivalent to `buf_p` - * given to `harness_mock_cwrite()`. + * @param[in,out] buf_p Mock entry data buffer, equivalent to `buf_p` + * given to `harness_mock_cwrite()`. + * @param[in,out] size_p Mock entry size, equivalent to `size` given + * to `harness_mock_cwrite()`. * * @return true(1) if the mock entry shall be removed, otherwise * false(0). */ typedef int (*harness_mock_cb_t)(void *arg_p, - void *buf_p); + void *buf_p, + size_t *size_p); struct harness_testcase_t { harness_testcase_cb_t callback; diff --git a/src/drivers/storage/eeprom_soft.c b/src/drivers/storage/eeprom_soft.c index 2baba2f68..0ae2e3b39 100644 --- a/src/drivers/storage/eeprom_soft.c +++ b/src/drivers/storage/eeprom_soft.c @@ -240,31 +240,39 @@ static int write_header(struct eeprom_soft_driver_t *self_p, return (0); } -static ssize_t write_inner(struct eeprom_soft_driver_t *self_p, - uintptr_t dst, - const void *src_p, - size_t size) +static ssize_t vwrite_inner(struct eeprom_soft_driver_t *self_p, + struct iov_uintptr_t *dst_p, + struct iov_t *src_p, + size_t length) { const struct eeprom_soft_block_t *block_p; uint8_t buf[8]; uintptr_t chunk_address; uint16_t revision; uintptr_t offset; - const uint8_t *u8_src_p; + uint8_t *u8_src_p; int overwrite_index; size_t overwrite_size; ssize_t res; + size_t i; + uintptr_t dst; + size_t size; if (self_p->current.block_p == NULL) { return (-ENOTMOUNTED); } - if (dst >= self_p->eeprom_size) { - return (-EINVAL); - } + for (i = 0; i < length; i++) { + dst = dst_p[i].address; + size = dst_p[i].size; - if (dst + size > self_p->eeprom_size) { - return (-EINVAL); + if (dst >= self_p->eeprom_size) { + return (-EINVAL); + } + + if (dst + size > self_p->eeprom_size) { + return (-EINVAL); + } } if (get_blank_chunk(self_p, &block_p, &chunk_address) != 0) { @@ -272,8 +280,6 @@ static ssize_t write_inner(struct eeprom_soft_driver_t *self_p, } /* Write to new chunk. */ - u8_src_p = src_p; - for (offset = 0; offset < self_p->eeprom_size; offset += sizeof(buf)) { /* Read from old chunk. */ res = flash_read(self_p->flash_p, @@ -285,24 +291,29 @@ static ssize_t write_inner(struct eeprom_soft_driver_t *self_p, return (-1); } - /* Overwrite given data region. */ - if ((dst < offset + sizeof(buf)) && (dst + size > offset)) { - if (dst <= offset) { - overwrite_index = 0; - } else { - overwrite_index = (dst - offset); + /* Overwrite given data regions. */ + for (i = 0; i < length; i++) { + dst = dst_p[i].address; + size = dst_p[i].size; + u8_src_p = src_p[i].buf_p; + + if ((dst < offset + sizeof(buf)) && (dst + size > offset)) { + if (dst <= offset) { + overwrite_index = 0; + } else { + overwrite_index = (dst - offset); + } + + if (dst + size >= offset + sizeof(buf)) { + overwrite_size = sizeof(buf); + } else { + overwrite_size = (dst + size - offset); + } + + overwrite_size -= overwrite_index; + memcpy(&buf[overwrite_index], u8_src_p, overwrite_size); + src_p[i].buf_p = (u8_src_p + overwrite_size); } - - if (dst + size >= offset + sizeof(buf)) { - overwrite_size = sizeof(buf); - } else { - overwrite_size = (dst + size - offset); - } - - overwrite_size -= overwrite_index; - - memcpy(&buf[overwrite_index], u8_src_p, overwrite_size); - u8_src_p += overwrite_size; } /* Write to new chunk. */ @@ -331,7 +342,7 @@ static ssize_t write_inner(struct eeprom_soft_driver_t *self_p, self_p->current.chunk_address = chunk_address; self_p->current.revision = revision; - return (size); + return (iov_uintptr_size(dst_p, length)); } int eeprom_soft_module_init() @@ -492,13 +503,32 @@ ssize_t eeprom_soft_write(struct eeprom_soft_driver_t *self_p, ASSERTN(self_p != NULL, EINVAL); ASSERTN(src_p != NULL, EINVAL); + struct iov_uintptr_t iov_dst; + struct iov_t iov_src; + + iov_dst.address = dst; + iov_dst.size = size; + iov_src.buf_p = (void *)src_p; + + return (eeprom_soft_vwrite(self_p, &iov_dst, &iov_src, 1)); +} + +ssize_t eeprom_soft_vwrite(struct eeprom_soft_driver_t *self_p, + struct iov_uintptr_t *dst_p, + struct iov_t *src_p, + size_t length) +{ + ASSERTN(self_p != NULL, EINVAL); + ASSERTN(dst_p != NULL, EINVAL); + ASSERTN(src_p != NULL, EINVAL); + ssize_t res; #if CONFIG_EEPROM_SOFT_SEMAPHORE == 1 mutex_lock(&self_p->mutex); #endif - res = write_inner(self_p, dst, src_p, size); + res = vwrite_inner(self_p, dst_p, src_p, length); #if CONFIG_EEPROM_SOFT_SEMAPHORE == 1 mutex_unlock(&self_p->mutex); diff --git a/src/drivers/storage/eeprom_soft.h b/src/drivers/storage/eeprom_soft.h index 8c7e32eed..10a505ec4 100644 --- a/src/drivers/storage/eeprom_soft.h +++ b/src/drivers/storage/eeprom_soft.h @@ -133,4 +133,22 @@ ssize_t eeprom_soft_write(struct eeprom_soft_driver_t *self_p, const void *src_p, size_t size); +/** + * Write given buffers to given NVM addresses. + * + * @param[in] self_p Initialized driver object. + * @param[in] dst_p Software EEPROM address ranges to write, sorted + * from lowest to highest. Addressing starts at + * zero(0). + * @param[in] src_p Buffers to write in the same order as in + * `dst_p`. The size fields are not used. + * @param[in] length Number of elements in `dst_p` and `src_p`. + * + * @return Number of bytes written or negative error code. + */ +ssize_t eeprom_soft_vwrite(struct eeprom_soft_driver_t *self_p, + struct iov_uintptr_t *dst_p, + struct iov_t *src_p, + size_t length); + #endif diff --git a/src/kernel/types.h b/src/kernel/types.h index a9dd5b25e..feff00cab 100644 --- a/src/kernel/types.h +++ b/src/kernel/types.h @@ -169,4 +169,35 @@ struct thrd_prio_list_t { struct thrd_prio_list_elem_t *head_p; }; +/** + * Input-output vector. + */ +struct iov_t { + void *buf_p; + size_t size; +}; + +/** + * Input-output vector with address. + */ +struct iov_uintptr_t { + uintptr_t address; + size_t size; +}; + +static inline size_t iov_uintptr_size(struct iov_uintptr_t *iov_p, + size_t length) +{ + size_t i; + size_t size; + + size = 0; + + for (i = 0; i < length; i++) { + size += iov_p[i].size; + } + + return (size); +} + #endif diff --git a/src/oam/nvm.c b/src/oam/nvm.c index 7efb36fed..060baeef9 100644 --- a/src/oam/nvm.c +++ b/src/oam/nvm.c @@ -197,3 +197,14 @@ ssize_t nvm_write(uint32_t dst, const void *src_p, size_t size) return (nvm_port_write(dst, src_p, size)); } + +ssize_t nvm_vwrite(struct iov_uintptr_t *dst_p, + struct iov_t *src_p, + size_t length) +{ + ASSERTN(module.initialized == 1, EINVAL); + ASSERTN(dst_p != NULL, EINVAL); + ASSERTN(src_p != NULL, EINVAL); + + return (nvm_port_vwrite(dst_p, src_p, length)); +} diff --git a/src/oam/nvm.h b/src/oam/nvm.h index dc8ae6d90..9b01ba720 100644 --- a/src/oam/nvm.h +++ b/src/oam/nvm.h @@ -82,4 +82,19 @@ ssize_t nvm_read(void *dst_p, uint32_t src, size_t size); */ ssize_t nvm_write(uint32_t dst, const void *src_p, size_t size); +/** + * Write given buffers to given NVM addresses. + * + * @param[in] dst_p Address ranges in NVM to write, sorted from lowest + * to highest. Addressing starts at zero(0). + * @param[in] src_p Buffers to write in the same order as in + * `dst_p`. The size fields are not used. + * @param[in] length Number of elements in `dst_p` and `src_p`. + * + * @return Number of bytes written or negative error code. + */ +ssize_t nvm_vwrite(struct iov_uintptr_t *dst_p, + struct iov_t *src_p, + size_t length); + #endif diff --git a/src/oam/ports/linux/nvm_port.i b/src/oam/ports/linux/nvm_port.i index dba2d1daa..69ddb1056 100644 --- a/src/oam/ports/linux/nvm_port.i +++ b/src/oam/ports/linux/nvm_port.i @@ -100,3 +100,10 @@ static ssize_t nvm_port_write(size_t dst, const void *src_p, size_t size) return (fwrite(src_p, 1, size, module.port.nvm_p)); } + +static ssize_t nvm_port_vwrite(struct iov_uintptr_t *dst_p, + struct iov_t *src_p, + size_t length) +{ + return (-ENOSYS); +} diff --git a/src/oam/ports/nvm_port_eeprom_soft.i b/src/oam/ports/nvm_port_eeprom_soft.i index 91614eed8..631218f77 100644 --- a/src/oam/ports/nvm_port_eeprom_soft.i +++ b/src/oam/ports/nvm_port_eeprom_soft.i @@ -80,3 +80,13 @@ static ssize_t nvm_port_write(size_t dst, const void *src_p, size_t size) { return (eeprom_soft_write(&module.port.eeprom_soft, dst, src_p, size)); } + +static ssize_t nvm_port_vwrite(struct aiov_t *dst_p, + struct iov_t *src_p, + size_t length) +{ + return (eeprom_soft_vwrite(&module.port.eeprom_soft, + dst_p, + src_p, + length)); +} diff --git a/tst/debug/harness/main.c b/tst/debug/harness/main.c index b5e05b11c..668773338 100644 --- a/tst/debug/harness/main.c +++ b/tst/debug/harness/main.c @@ -30,6 +30,11 @@ #include "my_module.h" #include "my_module_mock.h" +struct arg_t { + size_t offset; + size_t length; +}; + static THRD_STACK(mock_thread_stack, 512); static int asserti(int actual, int expected) @@ -66,18 +71,19 @@ static void *mock_thread(void *arg_p) return (NULL); } -static int cwrite_cb(void *arg_p, void *buf_p) +static int cwrite_cb(void *v_arg_p, void *buf_p, size_t *size_p) { - int *length_p; + struct arg_t *arg_p; int *value_p; - length_p = arg_p; + arg_p = v_arg_p; value_p = buf_p; - (*length_p)--; - *value_p += 2; + arg_p->length--; + *value_p = (1 + 2 * arg_p->offset); + arg_p->offset++; - return (*length_p == 0); + return (arg_p->length == 0); } static int test_asserti(void) @@ -213,28 +219,29 @@ static int test_mock_mwrite(void) static int test_mock_cwrite(void) { int value; - int length; + struct arg_t arg; value = 1; - length = 2; + arg.length = 2; + arg.offset = 0; BTASSERT(harness_mock_cwrite("cwrite(value)", &value, sizeof(value), cwrite_cb, - &length, - sizeof(length)) == sizeof(value)); + &arg, + sizeof(arg)) == sizeof(value)); value = 0; BTASSERT(harness_mock_read("cwrite(value)", &value, sizeof(value)) == sizeof(value)); - BTASSERT(value == 1); + BTASSERTI(value, ==, 1); BTASSERT(harness_mock_read("cwrite(value)", &value, sizeof(value)) == sizeof(value)); - BTASSERT(value == 3); + BTASSERTI(value, ==, 3); BTASSERT(harness_mock_read("cwrite(value)", &value, diff --git a/tst/drivers/software/storage/eeprom_soft/main.c b/tst/drivers/software/storage/eeprom_soft/main.c index 61fdf7cd9..4ef31acd1 100644 --- a/tst/drivers/software/storage/eeprom_soft/main.c +++ b/tst/drivers/software/storage/eeprom_soft/main.c @@ -41,8 +41,8 @@ static const struct eeprom_soft_block_t blocks[2] = { }; static struct flash_driver_t flash; -static int mock_write_calculate_chunk_crc_blank(uintptr_t address, - size_t size) +static int write_calculate_chunk_crc_blank(uintptr_t address, + size_t size) { uint8_t buf[8]; @@ -57,14 +57,13 @@ static int mock_write_calculate_chunk_crc_blank(uintptr_t address, return (0); } -static int mock_write_write_header_blank(uintptr_t address, - uint16_t revision, - uint16_t valid) +static int write_write_header_blank(uintptr_t address, + uint16_t revision, + uint16_t valid) { struct header_t header; - mock_write_calculate_chunk_crc_blank(address, - 512); + write_calculate_chunk_crc_blank(address, 512); header.crc = 0xa3295e14; header.revision = revision; @@ -78,10 +77,10 @@ static int mock_write_write_header_blank(uintptr_t address, return (0); } -static int mock_write_read_header(uintptr_t address, - uint32_t crc, - uint16_t revision, - uint16_t valid) +static int write_read_header(uintptr_t address, + uint32_t crc, + uint16_t revision, + uint16_t valid) { struct header_t header; @@ -97,34 +96,34 @@ static int mock_write_read_header(uintptr_t address, return (0); } -static int mock_write_read_header_blank(uintptr_t address, - uint16_t revision, - uint16_t valid) +static int write_read_header_blank(uintptr_t address, + uint16_t revision, + uint16_t valid) { - return (mock_write_read_header(address, - 0xa3295e14, - revision, - valid)); + return (write_read_header(address, + 0xa3295e14, + revision, + valid)); } -static int mock_write_mount_read_chunks(struct header_t headers[2][4]) +static int write_mount_read_chunks(struct header_t headers[2][4]) { int i; int j; for (i = 0; i < membersof(blocks); i++) { for (j = 0; j < membersof(headers[0]); j++) { - mock_write_read_header(blocks[i].address + j * 512, - headers[i][j].crc, - headers[i][j].revision, - headers[i][j].valid); + write_read_header(blocks[i].address + j * 512, + headers[i][j].crc, + headers[i][j].revision, + headers[i][j].valid); } } return (0); } -static int mock_write_mount_block_0_chunk_0_latest(void) +static int write_mount_block_0_chunk_0_latest(void) { struct header_t headers[2][4] = { /* Block 0. */ @@ -143,12 +142,12 @@ static int mock_write_mount_block_0_chunk_0_latest(void) } }; - mock_write_mount_read_chunks(headers); + write_mount_read_chunks(headers); return (0); } -static int mock_write_get_blank_chunk_block_0_chunk_1_blank() +static int write_get_blank_chunk_block_0_chunk_1_blank() { uint8_t data; @@ -191,9 +190,9 @@ static int test_format(void) 0); } - mock_write_write_header_blank(blocks[0].address, - 0, - 0xa5c3); + write_write_header_blank(blocks[0].address, + 0, + 0xa5c3); BTASSERT(eeprom_soft_format(&eeprom) == 0); @@ -230,12 +229,12 @@ static int test_mount(void) 512) == 0); /* Block (revision 0) is latest and valid. */ - mock_write_mount_block_0_chunk_0_latest(); - mock_write_read_header_blank(blocks[0].address, + write_mount_block_0_chunk_0_latest(); + write_read_header_blank(blocks[0].address, 0, 0xa5c3); - mock_write_calculate_chunk_crc_blank(blocks[0].address, - 512); + write_calculate_chunk_crc_blank(blocks[0].address, + 512); BTASSERT(eeprom_soft_mount(&eeprom) == 0); @@ -295,12 +294,12 @@ static int test_mount_revision_1_later_than_0(void) membersof(blocks), 512) == 0); - mock_write_mount_read_chunks(headers); - mock_write_read_header_blank(blocks[0].address + 1024, - 1, - 0xa5c3); - mock_write_calculate_chunk_crc_blank(blocks[0].address + 1024, - 512); + write_mount_read_chunks(headers); + write_read_header_blank(blocks[0].address + 1024, + 1, + 0xa5c3); + write_calculate_chunk_crc_blank(blocks[0].address + 1024, + 512); BTASSERT(eeprom_soft_mount(&eeprom) == 0); @@ -333,11 +332,11 @@ static int test_mount_revision_1_later_than_33000(void) membersof(blocks), 512) == 0); - mock_write_mount_read_chunks(headers); - mock_write_read_header_blank(blocks[0].address + 1024, + write_mount_read_chunks(headers); + write_read_header_blank(blocks[0].address + 1024, 1, 0xa5c3); - mock_write_calculate_chunk_crc_blank(blocks[0].address + 1024, + write_calculate_chunk_crc_blank(blocks[0].address + 1024, 512); BTASSERT(eeprom_soft_mount(&eeprom) == 0); @@ -356,7 +355,7 @@ static int test_mount_is_valid_chunk_flash_read_fail(void) membersof(blocks), 512) == 0); - mock_write_mount_block_0_chunk_0_latest(); + write_mount_block_0_chunk_0_latest(); /* Header read of latest chunk fails. */ mock_write_flash_read(&header, @@ -379,10 +378,10 @@ static int test_mount_is_valid_chunk_not_valid(void) membersof(blocks), 512) == 0); - mock_write_mount_block_0_chunk_0_latest(); - mock_write_read_header_blank(blocks[0].address, - 0, - 0xffff); + write_mount_block_0_chunk_0_latest(); + write_read_header_blank(blocks[0].address, + 0, + 0xffff); BTASSERT(eeprom_soft_mount(&eeprom) == -1); @@ -400,10 +399,10 @@ static int test_mount_is_valid_chunk_calculate_crc_fail(void) membersof(blocks), 512) == 0); - mock_write_mount_block_0_chunk_0_latest(); - mock_write_read_header_blank(blocks[0].address, - 0, - 0xa5c3); + write_mount_block_0_chunk_0_latest(); + write_read_header_blank(blocks[0].address, + 0, + 0xa5c3); /* Flash read of the CRC fails. */ mock_write_flash_read(&buf[0], @@ -426,13 +425,13 @@ static int test_mount_is_valid_chunk_crc_mismatch(void) membersof(blocks), 512) == 0); - mock_write_mount_block_0_chunk_0_latest(); - mock_write_read_header(blocks[0].address, - 0x12345678, /* Does not match a blank chunk - CRC. */ - 0, - 0xa5c3); - mock_write_calculate_chunk_crc_blank(blocks[0].address, + write_mount_block_0_chunk_0_latest(); + write_read_header(blocks[0].address, + 0x12345678, /* Does not match a blank chunk + CRC. */ + 0, + 0xa5c3); + write_calculate_chunk_crc_blank(blocks[0].address, 512); BTASSERT(eeprom_soft_mount(&eeprom) == -1); @@ -452,16 +451,16 @@ static int test_write(void) membersof(blocks), 512) == 0); - mock_write_mount_block_0_chunk_0_latest(); - mock_write_read_header_blank(blocks[0].address, - 0, - 0xa5c3); - mock_write_calculate_chunk_crc_blank(blocks[0].address, - 512); + write_mount_block_0_chunk_0_latest(); + write_read_header_blank(blocks[0].address, + 0, + 0xa5c3); + write_calculate_chunk_crc_blank(blocks[0].address, + 512); BTASSERT(eeprom_soft_mount(&eeprom) == 0); - mock_write_get_blank_chunk_block_0_chunk_1_blank(); + write_get_blank_chunk_block_0_chunk_1_blank(); memset(&buf[0], -1, sizeof(buf)); @@ -487,14 +486,88 @@ static int test_write(void) sizeof(buf), (512 - 16) / sizeof(buf)); - mock_write_write_header_blank(blocks[0].address + 512, - 1, - 0xa5c3); + write_write_header_blank(blocks[0].address + 512, + 1, + 0xa5c3); - BTASSERT(eeprom_soft_write(&eeprom, - 0, - &data, - sizeof(data)) == 1); + BTASSERTI(eeprom_soft_write(&eeprom, + 0, + &data, + sizeof(data)), ==, 1); + + return (0); +} + +static int test_vwrite(void) +{ + struct eeprom_soft_driver_t eeprom; + uint8_t buf[504]; + char part_1[] = "012"; + char part_2[] = "3456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLM"; + char part_3[] = "NOPQRSTUVWXYZ"; + struct iov_uintptr_t dst[3]; + struct iov_t src[3]; + ssize_t size; + + BTASSERT(eeprom_soft_init(&eeprom, + &flash, + &blocks[0], + membersof(blocks), + 512) == 0); + + /* Mount. */ + write_mount_block_0_chunk_0_latest(); + write_read_header_blank(blocks[0].address, + 0, + 0xa5c3); + write_calculate_chunk_crc_blank(blocks[0].address, + 512); + + BTASSERT(eeprom_soft_mount(&eeprom) == 0); + + /* Write. */ + write_get_blank_chunk_block_0_chunk_1_blank(); + memset(&buf[0], -1, sizeof(buf)); + mock_write_flash_read_seq2(&buf[0], + blocks[0].address + 8, + sizeof(buf), + 8, + sizeof(buf) / 8); + memcpy(&buf[33], + &part_1[0], + strlen(part_1)); + memcpy(&buf[33 + strlen(part_1)], + &part_2[0], + strlen(part_2)); + memcpy(&buf[33 + strlen(part_1) + strlen(part_2)], + &part_3[0], + strlen(part_3)); + mock_write_flash_write_seq2(blocks[0].address + 512 + 8, + &buf[0], + sizeof(buf), + 8, + sizeof(buf) / 8); + write_write_header_blank(blocks[0].address + 512, + 1, + 0xa5c3); + + dst[0].address = 33; + dst[0].size = strlen(part_1); + dst[1].address = (33 + strlen(part_1)); + dst[1].size = strlen(part_2); + dst[2].address = (33 + strlen(part_1) + strlen(part_2)); + dst[2].size = strlen(part_3); + + src[0].buf_p = part_1; + src[1].buf_p = part_2; + src[2].buf_p = part_3; + + size = iov_uintptr_size(&dst[0], membersof(dst)); + + BTASSERT(eeprom_soft_vwrite(&eeprom, + &dst[0], + &src[0], + membersof(dst)) == size); return (0); } @@ -511,14 +584,14 @@ static int test_read_write_after_failed_mount(void) 512) == 0); /* Mount fails (with chunk CRC mismatch). */ - mock_write_mount_block_0_chunk_0_latest(); - mock_write_read_header(blocks[0].address, - 0x12345678, /* Does not match a blank chunk - CRC. */ - 0, - 0xa5c3); - mock_write_calculate_chunk_crc_blank(blocks[0].address, - 512); + write_mount_block_0_chunk_0_latest(); + write_read_header(blocks[0].address, + 0x12345678, /* Does not match a blank chunk + CRC. */ + 0, + 0xa5c3); + write_calculate_chunk_crc_blank(blocks[0].address, + 512); BTASSERT(eeprom_soft_mount(&eeprom) == -1); @@ -573,6 +646,7 @@ int main() "test_mount_is_valid_chunk_crc_mismatch" }, { test_write, "test_write" }, + { test_vwrite, "test_vwrite" }, { test_read_write_after_failed_mount, "test_read_write_after_failed_mount" diff --git a/tst/stubs/drivers/storage/flash_mock.c b/tst/stubs/drivers/storage/flash_mock.c index 08a912e7e..d5ae1ab8c 100644 --- a/tst/stubs/drivers/storage/flash_mock.c +++ b/tst/stubs/drivers/storage/flash_mock.c @@ -30,12 +30,20 @@ #include "flash_mock.h" struct seq_arg_t { + uintptr_t address; + size_t size; + size_t length; +}; + +struct seq_data_arg_t { + size_t offset; size_t size; size_t length; }; static int write_seq(void *v_arg_p, - void *buf_p) + void *buf_p, + size_t *size_p) { uintptr_t *src_p; struct seq_arg_t *arg_p; @@ -43,12 +51,39 @@ static int write_seq(void *v_arg_p, src_p = buf_p; arg_p = v_arg_p; + *src_p = arg_p->address; + arg_p->address += arg_p->size; + + if (arg_p->length == 1) { + return (1); + } + + arg_p->length--; + + return (0); +} + +static int write_seq_data(void *v_arg_p, + void *buf_p, + size_t *size_p) +{ + struct seq_data_arg_t *arg_p; + uint8_t *u8_buf_p; + + arg_p = v_arg_p; + u8_buf_p = buf_p; + + *size_p = arg_p->size; + if (arg_p->length == 1) { return (1); } - (*src_p) += arg_p->size; arg_p->length--; + memmove(&u8_buf_p[0], + &u8_buf_p[arg_p->offset * arg_p->size], + arg_p->size); + arg_p->offset++; return (0); } @@ -124,6 +159,7 @@ int mock_write_flash_read_seq(void *dst_p, size, length); + arg.address = src; arg.size = size; arg.length = length; @@ -147,6 +183,51 @@ int mock_write_flash_read_seq(void *dst_p, return (0); } +int mock_write_flash_read_seq2(void *dst_p, + uintptr_t src, + size_t size, + ssize_t res, + size_t length) +{ + struct seq_data_arg_t data_arg; + struct seq_arg_t src_arg; + + data_arg.offset = 0; + data_arg.size = (size / length); + data_arg.length = length; + + harness_mock_cwrite("flash_read(dst_p)", + dst_p, + size, + write_seq_data, + &data_arg, + sizeof(data_arg)); + + src_arg.address = src; + src_arg.size = (size / length); + src_arg.length = length; + + harness_mock_cwrite("flash_read(src)", + &src, + sizeof(src), + write_seq, + &src_arg, + sizeof(src_arg)); + + size /= length; + harness_mock_mwrite("flash_read(size)", + &size, + sizeof(size), + length); + + harness_mock_mwrite("flash_read(): return (res)", + &res, + sizeof(res), + length); + + return (0); +} + int mock_write_flash_read(void *dst_p, uintptr_t src, size_t size, @@ -193,6 +274,7 @@ int mock_write_flash_write_seq(uintptr_t dst, { struct seq_arg_t arg; + arg.address = dst; arg.size = size; arg.length = length; @@ -221,6 +303,51 @@ int mock_write_flash_write_seq(uintptr_t dst, return (0); } +int mock_write_flash_write_seq2(uintptr_t dst, + const void *src_p, + size_t size, + ssize_t res, + size_t length) +{ + struct seq_arg_t dst_arg; + struct seq_data_arg_t data_arg; + + dst_arg.address = dst; + dst_arg.size = (size / length); + dst_arg.length = length; + + harness_mock_cwrite("flash_write(dst)", + &dst, + sizeof(dst), + write_seq, + &dst_arg, + sizeof(dst_arg)); + + data_arg.offset = 0; + data_arg.size = (size / length); + data_arg.length = length; + + harness_mock_cwrite("flash_write(src_p)", + src_p, + size, + write_seq_data, + &data_arg, + sizeof(data_arg)); + + size /= length; + harness_mock_mwrite("flash_write(size)", + &size, + sizeof(size), + length); + + harness_mock_mwrite("flash_write(): return (res)", + &res, + sizeof(res), + length); + + return (0); +} + int mock_write_flash_write(uintptr_t dst, const void *src_p, size_t size, diff --git a/tst/stubs/drivers/storage/flash_mock.h b/tst/stubs/drivers/storage/flash_mock.h index 4555fb208..0bc7da3de 100644 --- a/tst/stubs/drivers/storage/flash_mock.h +++ b/tst/stubs/drivers/storage/flash_mock.h @@ -47,6 +47,12 @@ int mock_write_flash_read_seq(void *dst_p, ssize_t res, size_t length); +int mock_write_flash_read_seq2(void *dst_p, + uintptr_t src, + size_t size, + ssize_t res, + size_t length); + int mock_write_flash_write(uintptr_t dst, const void *src_p, size_t size, @@ -58,6 +64,12 @@ int mock_write_flash_write_seq(uintptr_t dst, ssize_t res, size_t length); +int mock_write_flash_write_seq2(uintptr_t dst, + const void *src_p, + size_t size, + ssize_t res, + size_t length); + int mock_write_flash_erase(uintptr_t addr, size_t size, int res);