kvm: libkvm: export KVM_CAP_DESTROY_MEMORY_REGION_WORKS
[qemu-kvm/fedora.git] / hw / device_tree.c
blob2621ff1125d4bd431232d7d15562e90da5ba08cd
1 /*
2 * Functions to help device tree manipulation using libfdt.
3 * It also provides functions to read entries from device tree proc
4 * interface.
6 * Copyright 2008 IBM Corporation.
7 * Authors: Jerone Young <jyoung5@us.ibm.com>
9 * This work is licensed under the GNU GPL license version 2 or later.
13 #include <stdio.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <fcntl.h>
17 #include <unistd.h>
18 #include <stdlib.h>
20 #include "config.h"
21 #include "ppc440.h"
23 #ifdef CONFIG_LIBFDT
24 #include "libfdt.h"
25 #endif
27 #define DT_PROC_INTERFACE_PATH "/proc/device-tree"
29 /* FUNCTIONS FOR READING FROM DEVICE TREE OF HOST IN /PROC */
31 /* This function reads device-tree property files that are of
32 * a single cell size
34 uint32_t read_proc_dt_prop_cell(const char *path_in_device_tree)
36 char *buf = NULL;
37 int i;
38 uint32_t num;
39 FILE *stream;
41 i = asprintf(&buf, "%s/%s", DT_PROC_INTERFACE_PATH,
42 path_in_device_tree);
44 if (i < 0) {
45 printf("%s: Unable to malloc string buffer buf\n",
46 __func__);
47 exit(1);
50 stream = fopen(buf, "rb");
52 if (stream == NULL) {
53 printf("%s: Unable to open '%s'\n", __func__, buf);
54 exit(1);
57 fread(&num, sizeof(num), 1, stream);
58 fclose(stream);
59 free(buf);
61 return num;
64 /* FUNCTIONS FOR LOADING & MANIPULATION OF DEVICE TREE IN GUEST */
66 #ifdef CONFIG_LIBFDT
67 /* support functions */
68 static int get_offset_of_node(void *fdt, const char *node_path)
70 int node_offset;
71 node_offset = fdt_path_offset(fdt, node_path);
72 if (node_offset < 0) {
73 printf("Unable to find node in device tree '%s'\n",
74 node_path);
75 exit(1);
77 return node_offset;
80 /* public functions */
81 void *load_device_tree(const char *filename_path, unsigned long load_addr)
83 int dt_file_size;
84 int dt_file_load_size;
85 int new_dt_size;
86 int ret;
87 void *dt_file = NULL;
88 void *fdt;
90 dt_file_size = get_image_size(filename_path);
91 if (dt_file_size < 0) {
92 printf("Unable to get size of device tree file '%s'\n",
93 filename_path);
94 goto fail;
97 /* First allocate space in qemu for device tree */
98 dt_file = qemu_malloc(dt_file_size);
99 if (dt_file == NULL) {
100 printf("Unable to allocate memory in qemu for device tree\n");
101 goto fail;
103 memset(dt_file, 0, dt_file_size);
105 dt_file_load_size = load_image(filename_path, dt_file);
108 /* XXX Second we place new copy of 2x size in guest memory
109 * This give us enough room for manipulation.
111 new_dt_size = dt_file_size * 2;
113 fdt = (void *)load_addr;
115 ret = fdt_open_into(dt_file, fdt, new_dt_size);
116 if (ret) {
117 printf("Unable to copy device tree in memory\n");
118 goto fail;
121 /* Check sanity of device tree */
122 if (fdt_check_header(fdt)) {
123 printf ("Device tree file loaded into memory is invalid: %s\n",
124 filename_path);
125 goto fail;
127 /* free qemu memory with old device tree */
128 qemu_free(dt_file);
129 return fdt;
131 fail:
132 if (dt_file)
133 qemu_free(dt_file);
134 return NULL;
137 void dump_device_tree_to_file(void *fdt, const char *filename)
139 int fd;
140 fd = open(filename, O_RDWR|O_CREAT, O_RDWR);
141 if (fd < 0) {
142 printf("Failed to open file %s\n Cannot dum device-tree\n",
143 filename);
144 return;
147 write(fd, fdt, fdt_totalsize(fdt));
148 close(fd);
151 void dt_cell(void *fdt, const char *node_path, const char *property,
152 uint32_t val)
154 int offset;
155 int ret;
156 offset = get_offset_of_node(fdt, node_path);
157 ret = fdt_setprop_cell(fdt, offset, property, val);
158 if (ret < 0) {
159 printf("Unable to set device tree property '%s'\n",
160 property);
161 exit(1);
165 /* This function is to manipulate a cell with multiple values */
166 void dt_cell_multi(void *fdt, const char *node_path, const char *property,
167 uint32_t *val_array, int size)
169 int offset;
170 int ret;
171 offset = get_offset_of_node(fdt, node_path);
172 ret = fdt_setprop(fdt, offset, property, val_array, size);
173 if (ret < 0) {
174 printf("Unable to set device tree property '%s'\n",
175 property);
176 exit(1);
180 void dt_string(void *fdt, const char *node_path, const char *property,
181 char *string)
183 int offset;
184 int ret;
185 offset = get_offset_of_node(fdt, node_path);
186 ret = fdt_setprop_string(fdt, offset, property, string);
187 if (ret < 0) {
188 printf("Unable to set device tree property '%s'\n",
189 property);
190 exit(1);
193 #endif