blob: 23e89e3b90286d12c3fbe237f8de7341c600d5a2 [file] [log] [blame]
aurel32f652e6a2008-12-16 10:43:48 +00001/*
2 * Functions to help device tree manipulation using libfdt.
3 * It also provides functions to read entries from device tree proc
4 * interface.
5 *
6 * Copyright 2008 IBM Corporation.
7 * Authors: Jerone Young <jyoung5@us.ibm.com>
8 * Hollis Blanchard <hollisb@us.ibm.com>
9 *
10 * This work is licensed under the GNU GPL license version 2 or later.
11 *
12 */
13
14#include <stdio.h>
15#include <sys/types.h>
16#include <sys/stat.h>
17#include <fcntl.h>
18#include <unistd.h>
19#include <stdlib.h>
20
21#include "config.h"
22#include "qemu-common.h"
aurel32f652e6a2008-12-16 10:43:48 +000023#include "device_tree.h"
Blue Swirl39b7f202009-09-22 17:51:36 +000024#include "hw/loader.h"
aurel32f652e6a2008-12-16 10:43:48 +000025
26#include <libfdt.h>
27
pbrook7ec632b2009-04-10 16:23:59 +000028void *load_device_tree(const char *filename_path, int *sizep)
aurel32f652e6a2008-12-16 10:43:48 +000029{
pbrook7ec632b2009-04-10 16:23:59 +000030 int dt_size;
aurel32f652e6a2008-12-16 10:43:48 +000031 int dt_file_load_size;
aurel32f652e6a2008-12-16 10:43:48 +000032 int ret;
pbrook7ec632b2009-04-10 16:23:59 +000033 void *fdt = NULL;
aurel32f652e6a2008-12-16 10:43:48 +000034
pbrook7ec632b2009-04-10 16:23:59 +000035 *sizep = 0;
36 dt_size = get_image_size(filename_path);
37 if (dt_size < 0) {
aurel32f652e6a2008-12-16 10:43:48 +000038 printf("Unable to get size of device tree file '%s'\n",
39 filename_path);
40 goto fail;
41 }
42
pbrook7ec632b2009-04-10 16:23:59 +000043 /* Expand to 2x size to give enough room for manipulation. */
44 dt_size *= 2;
aurel32f652e6a2008-12-16 10:43:48 +000045 /* First allocate space in qemu for device tree */
Anthony Liguori7267c092011-08-20 22:09:37 -050046 fdt = g_malloc0(dt_size);
aurel32f652e6a2008-12-16 10:43:48 +000047
pbrook7ec632b2009-04-10 16:23:59 +000048 dt_file_load_size = load_image(filename_path, fdt);
49 if (dt_file_load_size < 0) {
50 printf("Unable to open device tree file '%s'\n",
51 filename_path);
52 goto fail;
53 }
aurel32f652e6a2008-12-16 10:43:48 +000054
pbrook7ec632b2009-04-10 16:23:59 +000055 ret = fdt_open_into(fdt, fdt, dt_size);
aurel32f652e6a2008-12-16 10:43:48 +000056 if (ret) {
57 printf("Unable to copy device tree in memory\n");
58 goto fail;
59 }
60
61 /* Check sanity of device tree */
62 if (fdt_check_header(fdt)) {
63 printf ("Device tree file loaded into memory is invalid: %s\n",
64 filename_path);
65 goto fail;
66 }
pbrook7ec632b2009-04-10 16:23:59 +000067 *sizep = dt_size;
aurel32f652e6a2008-12-16 10:43:48 +000068 return fdt;
69
70fail:
Anthony Liguori7267c092011-08-20 22:09:37 -050071 g_free(fdt);
aurel32f652e6a2008-12-16 10:43:48 +000072 return NULL;
73}
74
75int qemu_devtree_setprop(void *fdt, const char *node_path,
David Gibsonc4897492011-04-01 15:15:09 +110076 const char *property, void *val_array, int size)
aurel32f652e6a2008-12-16 10:43:48 +000077{
78 int offset;
79
80 offset = fdt_path_offset(fdt, node_path);
81 if (offset < 0)
82 return offset;
83
84 return fdt_setprop(fdt, offset, property, val_array, size);
85}
86
87int qemu_devtree_setprop_cell(void *fdt, const char *node_path,
88 const char *property, uint32_t val)
89{
90 int offset;
91
92 offset = fdt_path_offset(fdt, node_path);
93 if (offset < 0)
94 return offset;
95
96 return fdt_setprop_cell(fdt, offset, property, val);
97}
98
99int qemu_devtree_setprop_string(void *fdt, const char *node_path,
100 const char *property, const char *string)
101{
102 int offset;
103
104 offset = fdt_path_offset(fdt, node_path);
105 if (offset < 0)
106 return offset;
107
108 return fdt_setprop_string(fdt, offset, property, string);
109}
Alexander Grafd69a8e62011-07-21 01:52:57 +0200110
111int qemu_devtree_nop_node(void *fdt, const char *node_path)
112{
113 int offset;
114
115 offset = fdt_path_offset(fdt, node_path);
116 if (offset < 0)
117 return offset;
118
119 return fdt_nop_node(fdt, offset);
120}