fdt_sw.c (c1144d29f405ce1f4e6ede6482beb3d0d09750c6) | fdt_sw.c (f858927fd6ce394a7f431153d44ad0a09e8f49a1) |
---|---|
1/* 2 * libfdt - Flat Device Tree manipulation 3 * Copyright (C) 2006 David Gibson, IBM Corporation. 4 * 5 * libfdt is dual licensed: you can use it either under the terms of 6 * the GPL, or the BSD license, at your option. 7 * 8 * a) This library is free software; you can redistribute it and/or --- 41 unchanged lines hidden (view full) --- 50 */ 51#include "libfdt_env.h" 52 53#include <fdt.h> 54#include <libfdt.h> 55 56#include "libfdt_internal.h" 57 | 1/* 2 * libfdt - Flat Device Tree manipulation 3 * Copyright (C) 2006 David Gibson, IBM Corporation. 4 * 5 * libfdt is dual licensed: you can use it either under the terms of 6 * the GPL, or the BSD license, at your option. 7 * 8 * a) This library is free software; you can redistribute it and/or --- 41 unchanged lines hidden (view full) --- 50 */ 51#include "libfdt_env.h" 52 53#include <fdt.h> 54#include <libfdt.h> 55 56#include "libfdt_internal.h" 57 |
58static int fdt_sw_check_header_(void *fdt) | 58static int fdt_sw_probe_(void *fdt) |
59{ | 59{ |
60 if (fdt_magic(fdt) != FDT_SW_MAGIC) | 60 if (fdt_magic(fdt) == FDT_MAGIC) 61 return -FDT_ERR_BADSTATE; 62 else if (fdt_magic(fdt) != FDT_SW_MAGIC) |
61 return -FDT_ERR_BADMAGIC; | 63 return -FDT_ERR_BADMAGIC; |
62 /* FIXME: should check more details about the header state */ | |
63 return 0; 64} 65 | 64 return 0; 65} 66 |
66#define FDT_SW_CHECK_HEADER(fdt) \ | 67#define FDT_SW_PROBE(fdt) \ |
67 { \ 68 int err; \ | 68 { \ 69 int err; \ |
69 if ((err = fdt_sw_check_header_(fdt)) != 0) \ | 70 if ((err = fdt_sw_probe_(fdt)) != 0) \ |
70 return err; \ 71 } 72 | 71 return err; \ 72 } 73 |
74/* 'memrsv' state: Initial state after fdt_create() 75 * 76 * Allowed functions: 77 * fdt_add_reservmap_entry() 78 * fdt_finish_reservemap() [moves to 'struct' state] 79 */ 80static int fdt_sw_probe_memrsv_(void *fdt) 81{ 82 int err = fdt_sw_probe_(fdt); 83 if (err) 84 return err; 85 86 if (fdt_off_dt_strings(fdt) != 0) 87 return -FDT_ERR_BADSTATE; 88 return 0; 89} 90 91#define FDT_SW_PROBE_MEMRSV(fdt) \ 92 { \ 93 int err; \ 94 if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \ 95 return err; \ 96 } 97 98/* 'struct' state: Enter this state after fdt_finish_reservemap() 99 * 100 * Allowed functions: 101 * fdt_begin_node() 102 * fdt_end_node() 103 * fdt_property*() 104 * fdt_finish() [moves to 'complete' state] 105 */ 106static int fdt_sw_probe_struct_(void *fdt) 107{ 108 int err = fdt_sw_probe_(fdt); 109 if (err) 110 return err; 111 112 if (fdt_off_dt_strings(fdt) != fdt_totalsize(fdt)) 113 return -FDT_ERR_BADSTATE; 114 return 0; 115} 116 117#define FDT_SW_PROBE_STRUCT(fdt) \ 118 { \ 119 int err; \ 120 if ((err = fdt_sw_probe_struct_(fdt)) != 0) \ 121 return err; \ 122 } 123 124/* 'complete' state: Enter this state after fdt_finish() 125 * 126 * Allowed functions: none 127 */ 128 |
|
73static void *fdt_grab_space_(void *fdt, size_t len) 74{ 75 int offset = fdt_size_dt_struct(fdt); 76 int spaceleft; 77 78 spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) 79 - fdt_size_dt_strings(fdt); 80 81 if ((offset + len < offset) || (offset + len > spaceleft)) 82 return NULL; 83 84 fdt_set_size_dt_struct(fdt, offset + len); 85 return fdt_offset_ptr_w_(fdt, offset); 86} 87 88int fdt_create(void *buf, int bufsize) 89{ | 129static void *fdt_grab_space_(void *fdt, size_t len) 130{ 131 int offset = fdt_size_dt_struct(fdt); 132 int spaceleft; 133 134 spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) 135 - fdt_size_dt_strings(fdt); 136 137 if ((offset + len < offset) || (offset + len > spaceleft)) 138 return NULL; 139 140 fdt_set_size_dt_struct(fdt, offset + len); 141 return fdt_offset_ptr_w_(fdt, offset); 142} 143 144int fdt_create(void *buf, int bufsize) 145{ |
146 const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header), 147 sizeof(struct fdt_reserve_entry)); |
|
90 void *fdt = buf; 91 | 148 void *fdt = buf; 149 |
92 if (bufsize < sizeof(struct fdt_header)) | 150 if (bufsize < hdrsize) |
93 return -FDT_ERR_NOSPACE; 94 95 memset(buf, 0, bufsize); 96 97 fdt_set_magic(fdt, FDT_SW_MAGIC); 98 fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); 99 fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); 100 fdt_set_totalsize(fdt, bufsize); 101 | 151 return -FDT_ERR_NOSPACE; 152 153 memset(buf, 0, bufsize); 154 155 fdt_set_magic(fdt, FDT_SW_MAGIC); 156 fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); 157 fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); 158 fdt_set_totalsize(fdt, bufsize); 159 |
102 fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header), 103 sizeof(struct fdt_reserve_entry))); | 160 fdt_set_off_mem_rsvmap(fdt, hdrsize); |
104 fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); | 161 fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); |
105 fdt_set_off_dt_strings(fdt, bufsize); | 162 fdt_set_off_dt_strings(fdt, 0); |
106 107 return 0; 108} 109 110int fdt_resize(void *fdt, void *buf, int bufsize) 111{ 112 size_t headsize, tailsize; 113 char *oldtail, *newtail; 114 | 163 164 return 0; 165} 166 167int fdt_resize(void *fdt, void *buf, int bufsize) 168{ 169 size_t headsize, tailsize; 170 char *oldtail, *newtail; 171 |
115 FDT_SW_CHECK_HEADER(fdt); | 172 FDT_SW_PROBE(fdt); |
116 | 173 |
117 headsize = fdt_off_dt_struct(fdt); | 174 headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); |
118 tailsize = fdt_size_dt_strings(fdt); 119 | 175 tailsize = fdt_size_dt_strings(fdt); 176 |
177 if ((headsize + tailsize) > fdt_totalsize(fdt)) 178 return -FDT_ERR_INTERNAL; 179 |
|
120 if ((headsize + tailsize) > bufsize) 121 return -FDT_ERR_NOSPACE; 122 123 oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize; 124 newtail = (char *)buf + bufsize - tailsize; 125 126 /* Two cases to avoid clobbering data if the old and new 127 * buffers partially overlap */ 128 if (buf <= fdt) { 129 memmove(buf, fdt, headsize); 130 memmove(newtail, oldtail, tailsize); 131 } else { 132 memmove(newtail, oldtail, tailsize); 133 memmove(buf, fdt, headsize); 134 } 135 | 180 if ((headsize + tailsize) > bufsize) 181 return -FDT_ERR_NOSPACE; 182 183 oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize; 184 newtail = (char *)buf + bufsize - tailsize; 185 186 /* Two cases to avoid clobbering data if the old and new 187 * buffers partially overlap */ 188 if (buf <= fdt) { 189 memmove(buf, fdt, headsize); 190 memmove(newtail, oldtail, tailsize); 191 } else { 192 memmove(newtail, oldtail, tailsize); 193 memmove(buf, fdt, headsize); 194 } 195 |
136 fdt_set_off_dt_strings(buf, bufsize); | |
137 fdt_set_totalsize(buf, bufsize); | 196 fdt_set_totalsize(buf, bufsize); |
197 if (fdt_off_dt_strings(buf)) 198 fdt_set_off_dt_strings(buf, bufsize); |
|
138 139 return 0; 140} 141 142int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) 143{ 144 struct fdt_reserve_entry *re; 145 int offset; 146 | 199 200 return 0; 201} 202 203int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) 204{ 205 struct fdt_reserve_entry *re; 206 int offset; 207 |
147 FDT_SW_CHECK_HEADER(fdt); | 208 FDT_SW_PROBE_MEMRSV(fdt); |
148 | 209 |
149 if (fdt_size_dt_struct(fdt)) 150 return -FDT_ERR_BADSTATE; 151 | |
152 offset = fdt_off_dt_struct(fdt); 153 if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) 154 return -FDT_ERR_NOSPACE; 155 156 re = (struct fdt_reserve_entry *)((char *)fdt + offset); 157 re->address = cpu_to_fdt64(addr); 158 re->size = cpu_to_fdt64(size); 159 160 fdt_set_off_dt_struct(fdt, offset + sizeof(*re)); 161 162 return 0; 163} 164 165int fdt_finish_reservemap(void *fdt) 166{ | 210 offset = fdt_off_dt_struct(fdt); 211 if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) 212 return -FDT_ERR_NOSPACE; 213 214 re = (struct fdt_reserve_entry *)((char *)fdt + offset); 215 re->address = cpu_to_fdt64(addr); 216 re->size = cpu_to_fdt64(size); 217 218 fdt_set_off_dt_struct(fdt, offset + sizeof(*re)); 219 220 return 0; 221} 222 223int fdt_finish_reservemap(void *fdt) 224{ |
167 return fdt_add_reservemap_entry(fdt, 0, 0); | 225 int err = fdt_add_reservemap_entry(fdt, 0, 0); 226 227 if (err) 228 return err; 229 230 fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt)); 231 return 0; |
168} 169 170int fdt_begin_node(void *fdt, const char *name) 171{ 172 struct fdt_node_header *nh; | 232} 233 234int fdt_begin_node(void *fdt, const char *name) 235{ 236 struct fdt_node_header *nh; |
173 int namelen = strlen(name) + 1; | 237 int namelen; |
174 | 238 |
175 FDT_SW_CHECK_HEADER(fdt); | 239 FDT_SW_PROBE_STRUCT(fdt); |
176 | 240 |
241 namelen = strlen(name) + 1; |
|
177 nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); 178 if (! nh) 179 return -FDT_ERR_NOSPACE; 180 181 nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); 182 memcpy(nh->name, name, namelen); 183 return 0; 184} 185 186int fdt_end_node(void *fdt) 187{ 188 fdt32_t *en; 189 | 242 nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); 243 if (! nh) 244 return -FDT_ERR_NOSPACE; 245 246 nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); 247 memcpy(nh->name, name, namelen); 248 return 0; 249} 250 251int fdt_end_node(void *fdt) 252{ 253 fdt32_t *en; 254 |
190 FDT_SW_CHECK_HEADER(fdt); | 255 FDT_SW_PROBE_STRUCT(fdt); |
191 192 en = fdt_grab_space_(fdt, FDT_TAGSIZE); 193 if (! en) 194 return -FDT_ERR_NOSPACE; 195 196 *en = cpu_to_fdt32(FDT_END_NODE); 197 return 0; 198} --- 21 unchanged lines hidden (view full) --- 220 return offset; 221} 222 223int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) 224{ 225 struct fdt_property *prop; 226 int nameoff; 227 | 256 257 en = fdt_grab_space_(fdt, FDT_TAGSIZE); 258 if (! en) 259 return -FDT_ERR_NOSPACE; 260 261 *en = cpu_to_fdt32(FDT_END_NODE); 262 return 0; 263} --- 21 unchanged lines hidden (view full) --- 285 return offset; 286} 287 288int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) 289{ 290 struct fdt_property *prop; 291 int nameoff; 292 |
228 FDT_SW_CHECK_HEADER(fdt); | 293 FDT_SW_PROBE_STRUCT(fdt); |
229 230 nameoff = fdt_find_add_string_(fdt, name); 231 if (nameoff == 0) 232 return -FDT_ERR_NOSPACE; 233 234 prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); 235 if (! prop) 236 return -FDT_ERR_NOSPACE; --- 20 unchanged lines hidden (view full) --- 257int fdt_finish(void *fdt) 258{ 259 char *p = (char *)fdt; 260 fdt32_t *end; 261 int oldstroffset, newstroffset; 262 uint32_t tag; 263 int offset, nextoffset; 264 | 294 295 nameoff = fdt_find_add_string_(fdt, name); 296 if (nameoff == 0) 297 return -FDT_ERR_NOSPACE; 298 299 prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); 300 if (! prop) 301 return -FDT_ERR_NOSPACE; --- 20 unchanged lines hidden (view full) --- 322int fdt_finish(void *fdt) 323{ 324 char *p = (char *)fdt; 325 fdt32_t *end; 326 int oldstroffset, newstroffset; 327 uint32_t tag; 328 int offset, nextoffset; 329 |
265 FDT_SW_CHECK_HEADER(fdt); | 330 FDT_SW_PROBE_STRUCT(fdt); |
266 267 /* Add terminator */ 268 end = fdt_grab_space_(fdt, sizeof(*end)); 269 if (! end) 270 return -FDT_ERR_NOSPACE; 271 *end = cpu_to_fdt32(FDT_END); 272 273 /* Relocate the string table */ --- 27 unchanged lines hidden --- | 331 332 /* Add terminator */ 333 end = fdt_grab_space_(fdt, sizeof(*end)); 334 if (! end) 335 return -FDT_ERR_NOSPACE; 336 *end = cpu_to_fdt32(FDT_END); 337 338 /* Relocate the string table */ --- 27 unchanged lines hidden --- |