cbi: allow fields to be resized

Since we now have a dynamically sized CBI field (DRAM), it is more
convenient to be able to resize fields. We accomplish this by deleting
the old field and adding the field at the end, after copying all of
the data forward.

BRANCH=none
BUG=b:116075074
TEST=Updated various CBI fields and watch them move to the end. tested
updating the last field and middle fields

Change-Id: Icb9b3cb36445d8e78315f9fd3a74483ff2d52ebf
Signed-off-by: Jett Rink <jettrink@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1234747
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
This commit is contained in:
Jett Rink 2018-09-19 17:43:22 -06:00 committed by chrome-bot
parent 48f662d5ba
commit 4a237232c2
1 changed files with 22 additions and 6 deletions

View File

@ -161,11 +161,29 @@ int cbi_get_board_info(enum cbi_data_tag tag, uint8_t *buf, uint8_t *size)
return EC_SUCCESS;
}
static void cbi_remove_tag(void *const cbi, struct cbi_data *const d)
{
struct cbi_header *const h = cbi;
const size_t size = sizeof(*d) + d->size;
const uint8_t *next = (uint8_t *)d + size;
const size_t bytes_after = ((uint8_t *)cbi + h->total_size) - next;
memmove(d, next, bytes_after);
h->total_size -= size;
}
int cbi_set_board_info(enum cbi_data_tag tag, const uint8_t *buf, uint8_t size)
{
struct cbi_data *d;
d = cbi_find_tag(cbi, tag);
/* If we found the entry, but the size doesn't match, delete it */
if (d && d->size != size) {
cbi_remove_tag(cbi, d);
d = NULL;
}
if (!d) {
/* Not found. Check if new item would fit */
if (sizeof(cbi) < head->total_size + sizeof(*d) + size)
@ -173,13 +191,11 @@ int cbi_set_board_info(enum cbi_data_tag tag, const uint8_t *buf, uint8_t size)
/* Append new item */
cbi_set_data(&cbi[head->total_size], tag, buf, size);
head->total_size += (sizeof(*d) + size);
return EC_SUCCESS;
} else {
/* Overwrite existing item */
memcpy(d->value, buf, d->size);
}
/* No expand or shrink. Items are tightly packed. */
if (d->size != size)
return EC_ERROR_INVAL;
/* Overwrite existing item */
memcpy(d->value, buf, d->size);
return EC_SUCCESS;
}