To implement the -kernel, -initrd, and -append options, 4xx board emulation must load the guest kernel as if firmware had loaded it. Where u-boot would be the firmware, we must load the flat device tree into memory and set key fields such as /chosen/bootargs. This patch introduces a dependency on libfdt for flat device tree support. Signed-off-by: Hollis Blanchard <hollisb@xxxxxxxxxx> --- Makefile.target | 4 ++ configure | 18 ++++++++ device_tree.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ device_tree.h | 26 ++++++++++++ libfdt_env.h | 22 ++++++++++ 5 files changed, 186 insertions(+), 0 deletions(-) create mode 100644 device_tree.c create mode 100644 device_tree.h create mode 100644 libfdt_env.h diff --git a/Makefile.target b/Makefile.target index d01231d..5da4994 100644 --- a/Makefile.target +++ b/Makefile.target @@ -655,6 +655,10 @@ OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o ifdef CONFIG_KVM OBJS+= kvm_ppc.o endif +ifdef FDT_LIBS +OBJS+= device_tree.o +LIBS+= $(FDT_LIBS) +endif # virtio support OBJS+= virtio.o virtio-blk.o virtio-balloon.o endif diff --git a/configure b/configure index c534441..b54c15d 100755 --- a/configure +++ b/configure @@ -119,6 +119,7 @@ kvm="yes" kerneldir="" aix="no" blobs="yes" +fdt="yes" # OS specific targetos=`uname -s` @@ -976,6 +977,18 @@ if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then iovec=yes fi +########################################## +# fdt probe +if test "$fdt" = "yes" ; then + fdt=no + cat > $TMPC << EOF +int main(void) { return 0; } +EOF + if $cc $ARCH_CFLAGS -o $TMPE ${OS_CFLAGS} $TMPC -lfdt 2> /dev/null ; then + fdt=yes + fi +fi + # Check if tools are available to build documentation. if [ -x "`which texi2html 2>/dev/null`" ] && \ [ -x "`which pod2man 2>/dev/null`" ]; then @@ -1051,6 +1064,7 @@ echo "vde support $vde" echo "AIO support $aio" echo "Install blobs $blobs" echo "KVM support $kvm" +echo "fdt support $kvm" if test $sdl_too_old = "yes"; then echo "-> Your SDL version is too old - please upgrade to have SDL support" @@ -1340,6 +1354,10 @@ fi if test "$iovec" = "yes" ; then echo "#define HAVE_IOVEC 1" >> $config_h fi +if test "$fdt" = "yes" ; then + echo "#define HAVE_FDT 1" >> $config_h + echo "FDT_LIBS=-lfdt" >> $config_mak +fi # XXX: suppress that if [ "$bsd" = "yes" ] ; then diff --git a/device_tree.c b/device_tree.c new file mode 100644 index 0000000..d7350e3 --- /dev/null +++ b/device_tree.c @@ -0,0 +1,116 @@ +/* + * Functions to help device tree manipulation using libfdt. + * It also provides functions to read entries from device tree proc + * interface. + * + * Copyright 2008 IBM Corporation. + * Authors: Jerone Young <jyoung5@xxxxxxxxxx> + * Hollis Blanchard <hollisb@xxxxxxxxxx> + * + * This work is licensed under the GNU GPL license version 2 or later. + * + */ + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> + +#include "config.h" +#include "qemu-common.h" +#include "sysemu.h" +#include "device_tree.h" + +#include "libfdt.h" + +void *load_device_tree(const char *filename_path, void *load_addr) +{ + int dt_file_size; + int dt_file_load_size; + int new_dt_size; + int ret; + void *dt_file = NULL; + void *fdt; + + dt_file_size = get_image_size(filename_path); + if (dt_file_size < 0) { + printf("Unable to get size of device tree file '%s'\n", + filename_path); + goto fail; + } + + /* First allocate space in qemu for device tree */ + dt_file = qemu_malloc(dt_file_size); + if (dt_file == NULL) { + printf("Unable to allocate memory in qemu for device tree\n"); + goto fail; + } + memset(dt_file, 0, dt_file_size); + + dt_file_load_size = load_image(filename_path, dt_file); + + /* Second we place new copy of 2x size in guest memory + * This give us enough room for manipulation. + */ + new_dt_size = dt_file_size * 2; + + fdt = load_addr; + ret = fdt_open_into(dt_file, fdt, new_dt_size); + if (ret) { + printf("Unable to copy device tree in memory\n"); + goto fail; + } + + /* Check sanity of device tree */ + if (fdt_check_header(fdt)) { + printf ("Device tree file loaded into memory is invalid: %s\n", + filename_path); + goto fail; + } + /* free qemu memory with old device tree */ + qemu_free(dt_file); + return fdt; + +fail: + if (dt_file) + qemu_free(dt_file); + return NULL; +} + +int qemu_devtree_setprop(void *fdt, const char *node_path, + const char *property, uint32_t *val_array, int size) +{ + int offset; + + offset = fdt_path_offset(fdt, node_path); + if (offset < 0) + return offset; + + return fdt_setprop(fdt, offset, property, val_array, size); +} + +int qemu_devtree_setprop_cell(void *fdt, const char *node_path, + const char *property, uint32_t val) +{ + int offset; + + offset = fdt_path_offset(fdt, node_path); + if (offset < 0) + return offset; + + return fdt_setprop_cell(fdt, offset, property, val); +} + +int qemu_devtree_setprop_string(void *fdt, const char *node_path, + const char *property, const char *string) +{ + int offset; + + offset = fdt_path_offset(fdt, node_path); + if (offset < 0) + return offset; + + return fdt_setprop_string(fdt, offset, property, string); +} diff --git a/device_tree.h b/device_tree.h new file mode 100644 index 0000000..9e6ef3d --- /dev/null +++ b/device_tree.h @@ -0,0 +1,26 @@ +/* + * Header with function prototypes to help device tree manipulation using + * libfdt. It also provides functions to read entries from device tree proc + * interface. + * + * Copyright 2008 IBM Corporation. + * Authors: Jerone Young <jyoung5@xxxxxxxxxx> + * Hollis Blanchard <hollisb@xxxxxxxxxx> + * + * This work is licensed under the GNU GPL license version 2 or later. + * + */ + +#ifndef __DEVICE_TREE_H__ +#define __DEVICE_TREE_H__ + +void *load_device_tree(const char *filename_path, void *load_addr); + +int qemu_devtree_setprop(void *fdt, const char *node_path, + const char *property, uint32_t *val_array, int size); +int qemu_devtree_setprop_cell(void *fdt, const char *node_path, + const char *property, uint32_t val); +int qemu_devtree_setprop_string(void *fdt, const char *node_path, + const char *property, const char *string); + +#endif /* __DEVICE_TREE_H__ */ diff --git a/libfdt_env.h b/libfdt_env.h new file mode 100644 index 0000000..59f2536 --- /dev/null +++ b/libfdt_env.h @@ -0,0 +1,22 @@ +#ifndef _LIBFDT_ENV_H +#define _LIBFDT_ENV_H + +#include <stddef.h> +#include <stdint.h> +#include <string.h> +#include <endian.h> +#include <byteswap.h> + +#if __BYTE_ORDER == __BIG_ENDIAN +#define fdt32_to_cpu(x) (x) +#define cpu_to_fdt32(x) (x) +#define fdt64_to_cpu(x) (x) +#define cpu_to_fdt64(x) (x) +#else +#define fdt32_to_cpu(x) (bswap_32((x))) +#define cpu_to_fdt32(x) (bswap_32((x))) +#define fdt64_to_cpu(x) (bswap_64((x))) +#define cpu_to_fdt64(x) (bswap_64((x))) +#endif + +#endif /* _LIBFDT_ENV_H */ -- 1.5.6.5 -- To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html