]> git.proxmox.com Git - qemu.git/blobdiff - device_tree.c
prep: Initialize PC speaker
[qemu.git] / device_tree.c
index 22386829deb6adf9ffa57f4cd865a4028b5e7875..86a694c95503357a6ee15cbe427922cd31ec319a 100644 (file)
 
 #include "config.h"
 #include "qemu-common.h"
-#include "sysemu.h"
 #include "device_tree.h"
+#include "hw/loader.h"
 
 #include <libfdt.h>
 
-void *load_device_tree(const char *filename_path, void *load_addr)
+void *load_device_tree(const char *filename_path, int *sizep)
 {
-    int dt_file_size;
+    int dt_size;
     int dt_file_load_size;
-    int new_dt_size;
     int ret;
-    void *dt_file = NULL;
-    void *fdt;
+    void *fdt = NULL;
 
-    dt_file_size = get_image_size(filename_path);
-    if (dt_file_size < 0) {
+    *sizep = 0;
+    dt_size = get_image_size(filename_path);
+    if (dt_size < 0) {
         printf("Unable to get size of device tree file '%s'\n",
             filename_path);
         goto fail;
     }
 
+    /* Expand to 2x size to give enough room for manipulation.  */
+    dt_size += 10000;
+    dt_size *= 2;
     /* 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");
+    fdt = g_malloc0(dt_size);
+
+    dt_file_load_size = load_image(filename_path, fdt);
+    if (dt_file_load_size < 0) {
+        printf("Unable to open device tree file '%s'\n",
+               filename_path);
         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);
+    ret = fdt_open_into(fdt, fdt, dt_size);
     if (ret) {
         printf("Unable to copy device tree in memory\n");
         goto fail;
@@ -68,47 +65,108 @@ void *load_device_tree(const char *filename_path, void *load_addr)
             filename_path);
         goto fail;
     }
-    /* free qemu memory with old device tree */
-    qemu_free(dt_file);
+    *sizep = dt_size;
     return fdt;
 
 fail:
-    qemu_free(dt_file);
+    g_free(fdt);
     return NULL;
 }
 
-int qemu_devtree_setprop(void *fdt, const char *node_path,
-                         const char *property, uint32_t *val_array, int size)
+static int findnode_nofail(void *fdt, const char *node_path)
 {
     int offset;
 
     offset = fdt_path_offset(fdt, node_path);
-    if (offset < 0)
-        return offset;
+    if (offset < 0) {
+        fprintf(stderr, "%s Couldn't find node %s: %s\n", __func__, node_path,
+                fdt_strerror(offset));
+        exit(1);
+    }
 
-    return fdt_setprop(fdt, offset, property, val_array, size);
+    return offset;
+}
+
+int qemu_devtree_setprop(void *fdt, const char *node_path,
+                         const char *property, void *val_array, int size)
+{
+    int r;
+
+    r = fdt_setprop(fdt, findnode_nofail(fdt, node_path), property, val_array, size);
+    if (r < 0) {
+        fprintf(stderr, "%s: Couldn't set %s/%s: %s\n", __func__, node_path,
+                property, fdt_strerror(r));
+        exit(1);
+    }
+
+    return r;
 }
 
 int qemu_devtree_setprop_cell(void *fdt, const char *node_path,
                               const char *property, uint32_t val)
 {
-    int offset;
+    int r;
 
-    offset = fdt_path_offset(fdt, node_path);
-    if (offset < 0)
-        return offset;
+    r = fdt_setprop_cell(fdt, findnode_nofail(fdt, node_path), property, val);
+    if (r < 0) {
+        fprintf(stderr, "%s: Couldn't set %s/%s = %#08x: %s\n", __func__,
+                node_path, property, val, fdt_strerror(r));
+        exit(1);
+    }
 
-    return fdt_setprop_cell(fdt, offset, property, val);
+    return r;
 }
 
 int qemu_devtree_setprop_string(void *fdt, const char *node_path,
                                 const char *property, const char *string)
 {
-    int offset;
+    int r;
 
-    offset = fdt_path_offset(fdt, node_path);
-    if (offset < 0)
-        return offset;
+    r = fdt_setprop_string(fdt, findnode_nofail(fdt, node_path), property, string);
+    if (r < 0) {
+        fprintf(stderr, "%s: Couldn't set %s/%s = %s: %s\n", __func__,
+                node_path, property, string, fdt_strerror(r));
+        exit(1);
+    }
+
+    return r;
+}
+
+int qemu_devtree_nop_node(void *fdt, const char *node_path)
+{
+    int r;
+
+    r = fdt_nop_node(fdt, findnode_nofail(fdt, node_path));
+    if (r < 0) {
+        fprintf(stderr, "%s: Couldn't nop node %s: %s\n", __func__, node_path,
+                fdt_strerror(r));
+        exit(1);
+    }
+
+    return r;
+}
+
+int qemu_devtree_add_subnode(void *fdt, const char *name)
+{
+    char *dupname = g_strdup(name);
+    char *basename = strrchr(dupname, '/');
+    int retval;
+
+    if (!basename) {
+        g_free(dupname);
+        return -1;
+    }
+
+    basename[0] = '\0';
+    basename++;
+
+    retval = fdt_add_subnode(fdt, findnode_nofail(fdt, dupname), basename);
+    if (retval < 0) {
+        fprintf(stderr, "FDT: Failed to create subnode %s: %s\n", name,
+                fdt_strerror(retval));
+        exit(1);
+    }
 
-    return fdt_setprop_string(fdt, offset, property, string);
+    g_free(dupname);
+    return retval;
 }