Skip to content

Commit

Permalink
NVM and software EEPROM vector write.
Browse files Browse the repository at this point in the history
  • Loading branch information
eerimoq committed Sep 29, 2018
1 parent c8738f0 commit 6d72f17
Show file tree
Hide file tree
Showing 13 changed files with 482 additions and 134 deletions.
11 changes: 6 additions & 5 deletions src/debug/harness.c
Expand Up @@ -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;

Expand All @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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;

Expand Down
13 changes: 9 additions & 4 deletions src/debug/harness.h
Expand Up @@ -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;
Expand Down
92 changes: 61 additions & 31 deletions src/drivers/storage/eeprom_soft.c
Expand Up @@ -240,40 +240,46 @@ 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) {
return (-1);
}

/* 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,
Expand All @@ -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. */
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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);
Expand Down
18 changes: 18 additions & 0 deletions src/drivers/storage/eeprom_soft.h
Expand Up @@ -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
31 changes: 31 additions & 0 deletions src/kernel/types.h
Expand Up @@ -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
11 changes: 11 additions & 0 deletions src/oam/nvm.c
Expand Up @@ -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));
}
15 changes: 15 additions & 0 deletions src/oam/nvm.h
Expand Up @@ -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
7 changes: 7 additions & 0 deletions src/oam/ports/linux/nvm_port.i
Expand Up @@ -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);
}
10 changes: 10 additions & 0 deletions src/oam/ports/nvm_port_eeprom_soft.i
Expand Up @@ -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));
}

0 comments on commit 6d72f17

Please sign in to comment.