libfdt: Add function to resize the buffer for a sequential write tree
At present, when using sequential write mode, there's no straightforward means of resizing the buffer the fdt is being built into. This patch adds an fdt_resize() function for this purpose. Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
parent
883238dc50
commit
79eebb23db
4 changed files with 114 additions and 8 deletions
|
@ -107,6 +107,38 @@ int fdt_create(void *buf, int bufsize)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int fdt_resize(void *fdt, void *buf, int bufsize)
|
||||
{
|
||||
size_t headsize, tailsize;
|
||||
char *oldtail, *newtail;
|
||||
|
||||
FDT_SW_CHECK_HEADER(fdt);
|
||||
|
||||
headsize = fdt_off_dt_struct(fdt);
|
||||
tailsize = fdt_size_dt_strings(fdt);
|
||||
|
||||
if ((headsize + tailsize) > bufsize)
|
||||
return -FDT_ERR_NOSPACE;
|
||||
|
||||
oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize;
|
||||
newtail = (char *)buf + bufsize - tailsize;
|
||||
|
||||
/* Two cases to avoid clobbering data if the old and new
|
||||
* buffers partially overlap */
|
||||
if (buf <= fdt) {
|
||||
memmove(buf, fdt, headsize);
|
||||
memmove(newtail, oldtail, tailsize);
|
||||
} else {
|
||||
memmove(newtail, oldtail, tailsize);
|
||||
memmove(buf, fdt, headsize);
|
||||
}
|
||||
|
||||
fdt_set_off_dt_strings(buf, bufsize);
|
||||
fdt_set_totalsize(buf, bufsize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
|
||||
{
|
||||
struct fdt_reserve_entry *re;
|
||||
|
|
|
@ -1023,6 +1023,7 @@ int fdt_nop_node(void *fdt, int nodeoffset);
|
|||
/**********************************************************************/
|
||||
|
||||
int fdt_create(void *buf, int bufsize);
|
||||
int fdt_resize(void *fdt, void *buf, int bufsize);
|
||||
int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
|
||||
int fdt_finish_reservemap(void *fdt);
|
||||
int fdt_begin_node(void *fdt, const char *name);
|
||||
|
|
|
@ -190,6 +190,14 @@ libfdt_tests () {
|
|||
tree1_tests unfinished_tree1.test.dtb
|
||||
run_test dtbs_equal_ordered test_tree1.dtb sw_tree1.test.dtb
|
||||
|
||||
# Resizing tests
|
||||
for mode in resize realloc; do
|
||||
run_test sw_tree1 $mode
|
||||
tree1_tests sw_tree1.test.dtb
|
||||
tree1_tests unfinished_tree1.test.dtb
|
||||
run_test dtbs_equal_ordered test_tree1.dtb sw_tree1.test.dtb
|
||||
done
|
||||
|
||||
# fdt_move tests
|
||||
for tree in test_tree1.dtb sw_tree1.test.dtb unfinished_tree1.test.dtb; do
|
||||
rm -f moved.$tree shunted.$tree deshunted.$tree
|
||||
|
|
|
@ -31,22 +31,87 @@
|
|||
|
||||
#define SPACE 65536
|
||||
|
||||
#define CHECK(code) \
|
||||
{ \
|
||||
err = (code); \
|
||||
if (err) \
|
||||
FAIL(#code ": %s", fdt_strerror(err)); \
|
||||
static enum {
|
||||
FIXED = 0,
|
||||
RESIZE,
|
||||
REALLOC,
|
||||
} alloc_mode;
|
||||
|
||||
static void realloc_fdt(void **fdt, size_t *size)
|
||||
{
|
||||
switch (alloc_mode) {
|
||||
case FIXED:
|
||||
if (!(*fdt))
|
||||
fdt = xmalloc(*size);
|
||||
else
|
||||
FAIL("Ran out of space");
|
||||
return;
|
||||
|
||||
case RESIZE:
|
||||
if (!(*fdt)) {
|
||||
fdt = xmalloc(SPACE);
|
||||
} else if (*size < SPACE) {
|
||||
*size += 1;
|
||||
fdt_resize(*fdt, *fdt, *size);
|
||||
} else {
|
||||
FAIL("Ran out of space");
|
||||
}
|
||||
return;
|
||||
|
||||
case REALLOC:
|
||||
*size += 1;
|
||||
*fdt = xrealloc(*fdt, *size);
|
||||
fdt_resize(*fdt, *fdt, *size);
|
||||
return;
|
||||
|
||||
default:
|
||||
CONFIG("Bad allocation mode");
|
||||
}
|
||||
}
|
||||
|
||||
#define CHECK(code) \
|
||||
do { \
|
||||
err = (code); \
|
||||
if (err == -FDT_ERR_NOSPACE) \
|
||||
realloc_fdt(&fdt, &size); \
|
||||
else if (err) \
|
||||
FAIL(#code ": %s", fdt_strerror(err)); \
|
||||
} while (err != 0)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
void *fdt;
|
||||
void *fdt = NULL;
|
||||
size_t size;
|
||||
int err;
|
||||
|
||||
test_init(argc, argv);
|
||||
|
||||
fdt = xmalloc(SPACE);
|
||||
CHECK(fdt_create(fdt, SPACE));
|
||||
if (argc == 1) {
|
||||
alloc_mode = FIXED;
|
||||
size = SPACE;
|
||||
} else if (argc == 2) {
|
||||
if (streq(argv[1], "resize")) {
|
||||
alloc_mode = REALLOC;
|
||||
size = 0;
|
||||
} else if (streq(argv[1], "realloc")) {
|
||||
alloc_mode = REALLOC;
|
||||
size = 0;
|
||||
} else {
|
||||
char *endp;
|
||||
|
||||
size = strtoul(argv[1], &endp, 0);
|
||||
if (*endp == '\0')
|
||||
alloc_mode = FIXED;
|
||||
else
|
||||
CONFIG("Bad allocation mode \"%s\" specified",
|
||||
argv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
realloc_fdt(&fdt, &size);
|
||||
|
||||
fdt = xmalloc(size);
|
||||
CHECK(fdt_create(fdt, size));
|
||||
|
||||
CHECK(fdt_add_reservemap_entry(fdt, TEST_ADDR_1, TEST_SIZE_1));
|
||||
CHECK(fdt_add_reservemap_entry(fdt, TEST_ADDR_2, TEST_SIZE_2));
|
||||
|
|
Loading…
Reference in a new issue