Browse Source

libfdt: Implement fdt_move()

Implement the fdt_move() function for copying/moving device trees
to a new buffer, or within an existing buffer.
main
David Gibson 19 years ago
parent
commit
423697628a
  1. 33
      fdt.c
  2. 21
      fdt_ro.c
  3. 5
      libfdt.h
  4. 1
      libfdt_internal.h
  5. 3
      tests/Makefile
  6. 71
      tests/move_and_save.c
  7. 9
      tests/run_tests.sh

33
fdt.c

@ -23,6 +23,25 @@


#include "libfdt_internal.h" #include "libfdt_internal.h"


int _fdt_check_header(const struct fdt_header *fdt)
{
if (fdt_magic(fdt) == FDT_MAGIC) {
/* Complete tree */
if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
return FDT_ERR_BADVERSION;
if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
return FDT_ERR_BADVERSION;
} else if (fdt_magic(fdt) == SW_MAGIC) {
/* Unfinished sequential-write blob */
if (sw_size_dt_struct(fdt) == 0)
return FDT_ERR_BADSTATE;
} else {
return FDT_ERR_BADMAGIC;
}

return 0;
}

void *fdt_offset_ptr(const struct fdt_header *fdt, int offset, int len) void *fdt_offset_ptr(const struct fdt_header *fdt, int offset, int len)
{ {
void *p; void *p;
@ -72,3 +91,17 @@ uint32_t _fdt_next_tag(const struct fdt_header *fdt, int offset, int *nextoffset


return tag; return tag;
} }

struct fdt_header *fdt_move(const struct fdt_header *fdt, void *buf, int bufsize)
{
int err = _fdt_check_header(fdt);

if (err)
return PTR_ERROR(err);

if (fdt_totalsize(fdt) > bufsize)
return PTR_ERROR(FDT_ERR_NOSPACE);

memmove(buf, fdt, fdt_totalsize(fdt));
return (struct fdt_header *)buf;
}

21
fdt_ro.c

@ -23,29 +23,10 @@


#include "libfdt_internal.h" #include "libfdt_internal.h"


static int check_header(const struct fdt_header *fdt)
{
if (fdt_magic(fdt) == FDT_MAGIC) {
/* Complete tree */
if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
return FDT_ERR_BADVERSION;
if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
return FDT_ERR_BADVERSION;
} else if (fdt_magic(fdt) == SW_MAGIC) {
/* Unfinished sequential-write blob */
if (sw_size_dt_struct(fdt) == 0)
return FDT_ERR_BADSTATE;
} else {
return FDT_ERR_BADMAGIC;
}

return 0;
}

#define OFFSET_CHECK_HEADER(fdt) \ #define OFFSET_CHECK_HEADER(fdt) \
{ \ { \
int err; \ int err; \
if ((err = check_header(fdt)) != 0) \ if ((err = _fdt_check_header(fdt)) != 0) \
return OFFSET_ERROR(err); \ return OFFSET_ERROR(err); \
} }



5
libfdt.h

@ -64,6 +64,8 @@ void *fdt_offset_ptr(const struct fdt_header *fdt, int offset, int checklen);
#define fdt_ptr_error(ptr) \ #define fdt_ptr_error(ptr) \
( (((long)(ptr) < 0) && ((long)(ptr) >= -FDT_ERR_MAX)) ? -(long)(ptr) : 0 ) ( (((long)(ptr) < 0) && ((long)(ptr) >= -FDT_ERR_MAX)) ? -(long)(ptr) : 0 )


struct fdt_header *fdt_move(const struct fdt_header *fdt, void *buf, int bufsize);

/* Read-only functions */ /* Read-only functions */
char *fdt_string(const struct fdt_header *fdt, int stroffset); char *fdt_string(const struct fdt_header *fdt, int stroffset);


@ -115,9 +117,6 @@ int fdt_add_subnode(struct fdt_header *fdtx, void *node, const char *name);
int fdt_set_property(struct fdt_header *fdtx, void *node, const char *name, int fdt_set_property(struct fdt_header *fdtx, void *node, const char *name,
const void *val, int len); const void *val, int len);
int fdt_del_property(struct fdt_header *fdtx, void *node, const char *name); int fdt_del_property(struct fdt_header *fdtx, void *node, const char *name);

/* Misc functions */
struct fdt_header *fdt_move(struct fdt_header *fdt, void *buf, int bufsize);
#endif #endif


#endif /* _LIBFDT_H */ #endif /* _LIBFDT_H */

1
libfdt_internal.h

@ -26,6 +26,7 @@
#define memeq(p, q, n) (memcmp((p), (q), (n)) == 0) #define memeq(p, q, n) (memcmp((p), (q), (n)) == 0)
#define streq(p, q) (strcmp((p), (q)) == 0) #define streq(p, q) (strcmp((p), (q)) == 0)


int _fdt_check_header(const struct fdt_header *fdt);
uint32_t _fdt_next_tag(const struct fdt_header *fdt, int startoffset, int *nextoffset); uint32_t _fdt_next_tag(const struct fdt_header *fdt, int startoffset, int *nextoffset);
struct fdt_property *_fdt_getprop(const struct fdt_header *fdt, int nodeoffset, struct fdt_property *_fdt_getprop(const struct fdt_header *fdt, int nodeoffset,
const char *name, int *lenp); const char *name, int *lenp);

3
tests/Makefile

@ -3,7 +3,8 @@ PREFIX = /usr/local
LIB_TESTS = root_node property_offset subnode_offset path_offset getprop \ LIB_TESTS = root_node property_offset subnode_offset path_offset getprop \
notfound \ notfound \
setprop_inplace nop_property nop_node \ setprop_inplace nop_property nop_node \
sw_tree1 sw_tree1 \
move_and_save
TESTS = $(LIB_TESTS) TESTS = $(LIB_TESTS)
UTILS = dumptrees UTILS = dumptrees



71
tests/move_and_save.c

@ -0,0 +1,71 @@
/*
* libfdt - Flat Device Tree manipulation
* Basic testcase for read-only access
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <fdt.h>
#include <libfdt.h>

#include "tests.h"
#include "testdata.h"

int main(int argc, char *argv[])
{
struct fdt_header *fdt, *fdt1, *fdt2, *fdt3;
void *buf;
int shuntsize;
int bufsize;
int err;
const char *inname;
char outname[PATH_MAX];

test_init(argc, argv);
fdt = load_blob_arg(argc, argv);
inname = argv[1];

shuntsize = ALIGN(fdt_totalsize(fdt) / 2, sizeof(uint64_t));
bufsize = fdt_totalsize(fdt) + shuntsize;
buf = xmalloc(bufsize);

fdt1 = fdt_move(fdt, buf, bufsize);
if ((err = fdt_ptr_error(fdt1)))
FAIL("Failed to move tree into new buffer: %s",
fdt_strerror(err));
sprintf(outname, "moved.%s", inname);
save_blob(outname, fdt1);

fdt2 = fdt_move(fdt1, buf + shuntsize, bufsize-shuntsize);
if ((err = fdt_ptr_error(fdt2)))
FAIL("Failed to shunt tree %d bytes: %s",
shuntsize, fdt_strerror(err));
sprintf(outname, "shunted.%s", inname);
save_blob(outname, fdt2);

fdt3 = fdt_move(fdt2, buf, bufsize);
if ((err = fdt_ptr_error(fdt3)))
FAIL("Failed to deshunt tree %d bytes: %s",
shuntsize, fdt_strerror(err));
sprintf(outname, "deshunted.%s", inname);
save_blob(outname, fdt3);

PASS();
}

9
tests/run_tests.sh

@ -36,6 +36,15 @@ functional_tests () {
run_test sw_tree1 run_test sw_tree1
tree1_tests sw_tree1.test.dtb tree1_tests sw_tree1.test.dtb
tree1_tests unfinished_tree1.test.dtb tree1_tests unfinished_tree1.test.dtb

# 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
run_test move_and_save $tree
tree1_tests moved.$tree
tree1_tests shunted.$tree
tree1_tests deshunted.$tree
done
} }


stress_tests () { stress_tests () {

Loading…
Cancel
Save