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 <holl...@us.ibm.com> --- Makefile.target | 4 ++ configure | 18 +++++++++ device_tree.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ device_tree.h | 26 ++++++++++++ libfdt_env.h | 41 ++++++++++++++++++++ 5 files changed, 203 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 8229b4f..d80ce2c 100644 --- a/Makefile.target +++ b/Makefile.target @@ -655,6 +655,10 @@ OBJS+= heathrow_pic.o grackle_pci.o ppc_oldworld.o OBJS+= unin_pci.o ppc_chrp.o # PowerPC 4xx boards OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o +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 455dbef..562f113 100755 --- a/configure +++ b/configure @@ -119,6 +119,7 @@ kvm="yes" kerneldir="" aix="no" blobs="yes" +fdt="yes" # OS specific targetos=`uname -s` @@ -966,6 +967,18 @@ if $cc $ARCH_CFLAGS -o $TMPE $TMPC > /dev/null 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 @@ -1061,6 +1074,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" @@ -1350,6 +1364,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..2238682 --- /dev/null +++ b/device_tree.c @@ -0,0 +1,114 @@ +/* + * 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 <jyou...@us.ibm.com> + * Hollis Blanchard <holl...@us.ibm.com> + * + * 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_mallocz(dt_file_size); + if (dt_file == NULL) { + printf("Unable to allocate memory in qemu for device tree\n"); + goto fail; + } + + 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: + 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 <jyou...@us.ibm.com> + * Hollis Blanchard <holl...@us.ibm.com> + * + * 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..e154b8e --- /dev/null +++ b/libfdt_env.h @@ -0,0 +1,41 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright IBM Corp. 2008 + * Authors: Hollis Blanchard <holl...@us.ibm.com> + * + */ + +#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 majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html