summary refs log tree commit diff stats
path: root/device_tree.c
diff options
context:
space:
mode:
authorBlue Swirl <blauwirbel@gmail.com>2012-06-24 10:48:56 +0000
committerBlue Swirl <blauwirbel@gmail.com>2012-06-24 10:48:56 +0000
commit4e469a438f40a53dc6217fa5c3d456861b00d80c (patch)
tree3eb0db99ac318738016463b56250da6bdfd64d9e /device_tree.c
parent959a255dfbe085a47e00fd21c57e87ad4c92719e (diff)
parent960916988b9ec45bb10400d892351f360b4aac96 (diff)
downloadfocaccia-qemu-4e469a438f40a53dc6217fa5c3d456861b00d80c.tar.gz
focaccia-qemu-4e469a438f40a53dc6217fa5c3d456861b00d80c.zip
Merge branch 'ppc-for-upstream' of git://repo.or.cz/qemu/agraf
* 'ppc-for-upstream' of git://repo.or.cz/qemu/agraf: (72 commits)
  PPC: BookE206: Bump MAS2 to 64bit
  PPC: BookE: Support 32 and 64 bit wide MAS2
  PPC: Extract SPR dump generation into its own function
  PPC: Add e5500 CPU target
  PPC: BookE: Make ivpr selectable by CPU type
  PPC: BookE: Implement EPR SPR
  PPC: Add support for MSR_CM
  PPC: Add some booke SPR defines
  uImage: increase the gzip load size
  PPC: e500: allow users to set the /compatible property via -machine
  dt: make setprop argument static
  PPC: e500: Refactor serial dt generation
  dt: Add global option to set phandle start offset
  PPC: e500: Extend address/size of / to 64bit
  PPC: e500: Define addresses as always 64bit
  PPC: e500: Use new SOC dt format
  PPC: e500: Use new MPIC dt format
  Revert "dt: temporarily disable subtree creation failure check"
  PPC: e500: enable manual loading of dtb blob
  PPC: e500: dt: use target_phys_addr_t for ramsize
  ...
Diffstat (limited to 'device_tree.c')
-rw-r--r--device_tree.c108
1 files changed, 106 insertions, 2 deletions
diff --git a/device_tree.c b/device_tree.c
index 86a694c955..b366fddeaf 100644
--- a/device_tree.c
+++ b/device_tree.c
@@ -22,9 +22,48 @@
 #include "qemu-common.h"
 #include "device_tree.h"
 #include "hw/loader.h"
+#include "qemu-option.h"
+#include "qemu-config.h"
 
 #include <libfdt.h>
 
+#define FDT_MAX_SIZE  0x10000
+
+void *create_device_tree(int *sizep)
+{
+    void *fdt;
+    int ret;
+
+    *sizep = FDT_MAX_SIZE;
+    fdt = g_malloc0(FDT_MAX_SIZE);
+    ret = fdt_create(fdt, FDT_MAX_SIZE);
+    if (ret < 0) {
+        goto fail;
+    }
+    ret = fdt_begin_node(fdt, "");
+    if (ret < 0) {
+        goto fail;
+    }
+    ret = fdt_end_node(fdt);
+    if (ret < 0) {
+        goto fail;
+    }
+    ret = fdt_finish(fdt);
+    if (ret < 0) {
+        goto fail;
+    }
+    ret = fdt_open_into(fdt, fdt, *sizep);
+    if (ret) {
+        fprintf(stderr, "Unable to copy device tree in memory\n");
+        exit(1);
+    }
+
+    return fdt;
+fail:
+    fprintf(stderr, "%s Couldn't create dt: %s\n", __func__, fdt_strerror(ret));
+    exit(1);
+}
+
 void *load_device_tree(const char *filename_path, int *sizep)
 {
     int dt_size;
@@ -88,7 +127,7 @@ static int findnode_nofail(void *fdt, const char *node_path)
 }
 
 int qemu_devtree_setprop(void *fdt, const char *node_path,
-                         const char *property, void *val_array, int size)
+                         const char *property, const void *val_array, int size)
 {
     int r;
 
@@ -117,6 +156,13 @@ int qemu_devtree_setprop_cell(void *fdt, const char *node_path,
     return r;
 }
 
+int qemu_devtree_setprop_u64(void *fdt, const char *node_path,
+                             const char *property, uint64_t val)
+{
+    val = cpu_to_be64(val);
+    return qemu_devtree_setprop(fdt, node_path, property, &val, sizeof(val));
+}
+
 int qemu_devtree_setprop_string(void *fdt, const char *node_path,
                                 const char *property, const char *string)
 {
@@ -132,6 +178,59 @@ int qemu_devtree_setprop_string(void *fdt, const char *node_path,
     return r;
 }
 
+uint32_t qemu_devtree_get_phandle(void *fdt, const char *path)
+{
+    uint32_t r;
+
+    r = fdt_get_phandle(fdt, findnode_nofail(fdt, path));
+    if (r <= 0) {
+        fprintf(stderr, "%s: Couldn't get phandle for %s: %s\n", __func__,
+                path, fdt_strerror(r));
+        exit(1);
+    }
+
+    return r;
+}
+
+int qemu_devtree_setprop_phandle(void *fdt, const char *node_path,
+                                 const char *property,
+                                 const char *target_node_path)
+{
+    uint32_t phandle = qemu_devtree_get_phandle(fdt, target_node_path);
+    return qemu_devtree_setprop_cell(fdt, node_path, property, phandle);
+}
+
+uint32_t qemu_devtree_alloc_phandle(void *fdt)
+{
+    static int phandle = 0x0;
+
+    /*
+     * We need to find out if the user gave us special instruction at
+     * which phandle id to start allocting phandles.
+     */
+    if (!phandle) {
+        QemuOpts *machine_opts;
+        machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
+        if (machine_opts) {
+            const char *phandle_start;
+            phandle_start = qemu_opt_get(machine_opts, "phandle_start");
+            if (phandle_start) {
+                phandle = strtoul(phandle_start, NULL, 0);
+            }
+        }
+    }
+
+    if (!phandle) {
+        /*
+         * None or invalid phandle given on the command line, so fall back to
+         * default starting point.
+         */
+        phandle = 0x8000;
+    }
+
+    return phandle++;
+}
+
 int qemu_devtree_nop_node(void *fdt, const char *node_path)
 {
     int r;
@@ -151,6 +250,7 @@ int qemu_devtree_add_subnode(void *fdt, const char *name)
     char *dupname = g_strdup(name);
     char *basename = strrchr(dupname, '/');
     int retval;
+    int parent = 0;
 
     if (!basename) {
         g_free(dupname);
@@ -160,7 +260,11 @@ int qemu_devtree_add_subnode(void *fdt, const char *name)
     basename[0] = '\0';
     basename++;
 
-    retval = fdt_add_subnode(fdt, findnode_nofail(fdt, dupname), basename);
+    if (dupname[0]) {
+        parent = findnode_nofail(fdt, dupname);
+    }
+
+    retval = fdt_add_subnode(fdt, parent, basename);
     if (retval < 0) {
         fprintf(stderr, "FDT: Failed to create subnode %s: %s\n", name,
                 fdt_strerror(retval));