]> git.proxmox.com Git - mirror_edk2.git/blame - EmbeddedPkg/Library/FdtLib/fdt_rw.c
EmbeddedPkg: Apply uncrustify changes
[mirror_edk2.git] / EmbeddedPkg / Library / FdtLib / fdt_rw.c
CommitLineData
1e57a462 1/*\r
2 * libfdt - Flat Device Tree manipulation\r
3 * Copyright (C) 2006 David Gibson, IBM Corporation.\r
4 *\r
5 * libfdt is dual licensed: you can use it either under the terms of\r
6 * the GPL, or the BSD license, at your option.\r
7 *\r
8 * a) This library is free software; you can redistribute it and/or\r
9 * modify it under the terms of the GNU General Public License as\r
10 * published by the Free Software Foundation; either version 2 of the\r
11 * License, or (at your option) any later version.\r
12 *\r
13 * This library is distributed in the hope that it will be useful,\r
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
16 * GNU General Public License for more details.\r
17 *\r
18 * You should have received a copy of the GNU General Public\r
19 * License along with this library; if not, write to the Free\r
20 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,\r
21 * MA 02110-1301 USA\r
22 *\r
23 * Alternatively,\r
24 *\r
25 * b) Redistribution and use in source and binary forms, with or\r
26 * without modification, are permitted provided that the following\r
27 * conditions are met:\r
28 *\r
29 * 1. Redistributions of source code must retain the above\r
30 * copyright notice, this list of conditions and the following\r
31 * disclaimer.\r
32 * 2. Redistributions in binary form must reproduce the above\r
33 * copyright notice, this list of conditions and the following\r
34 * disclaimer in the documentation and/or other materials\r
35 * provided with the distribution.\r
36 *\r
37 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\r
38 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,\r
39 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
40 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
41 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
42 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
47 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\r
48 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
49 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
50 */\r
51#include "libfdt_env.h"\r
52\r
53#include <fdt.h>\r
54#include <libfdt.h>\r
55\r
56#include "libfdt_internal.h"\r
57\r
e7108d0e
MK
58static int\r
59_fdt_blocks_misordered (\r
60 const void *fdt,\r
61 int mem_rsv_size,\r
62 int struct_size\r
63 )\r
1e57a462 64{\r
e7108d0e
MK
65 return (fdt_off_mem_rsvmap (fdt) < FDT_ALIGN (sizeof (struct fdt_header), 8))\r
66 || (fdt_off_dt_struct (fdt) <\r
67 (fdt_off_mem_rsvmap (fdt) + mem_rsv_size))\r
68 || (fdt_off_dt_strings (fdt) <\r
69 (fdt_off_dt_struct (fdt) + struct_size))\r
70 || (fdt_totalsize (fdt) <\r
71 (fdt_off_dt_strings (fdt) + fdt_size_dt_strings (fdt)));\r
1e57a462 72}\r
73\r
e7108d0e
MK
74static int\r
75_fdt_rw_check_header (\r
76 void *fdt\r
77 )\r
1e57a462 78{\r
e7108d0e
MK
79 FDT_CHECK_HEADER (fdt);\r
80\r
81 if (fdt_version (fdt) < 17) {\r
82 return -FDT_ERR_BADVERSION;\r
83 }\r
84\r
85 if (_fdt_blocks_misordered (\r
86 fdt,\r
87 sizeof (struct fdt_reserve_entry),\r
88 fdt_size_dt_struct (fdt)\r
89 ))\r
90 {\r
91 return -FDT_ERR_BADLAYOUT;\r
92 }\r
93\r
94 if (fdt_version (fdt) > 17) {\r
95 fdt_set_version (fdt, 17);\r
96 }\r
97\r
98 return 0;\r
1e57a462 99}\r
100\r
101#define FDT_RW_CHECK_HEADER(fdt) \\r
e7108d0e
MK
102 { \\r
103 int __err; \\r
104 if ((__err = _fdt_rw_check_header(fdt)) != 0) \\r
105 return __err; \\r
106 }\r
107\r
108static inline int\r
109_fdt_data_size (\r
110 void *fdt\r
111 )\r
1e57a462 112{\r
e7108d0e 113 return fdt_off_dt_strings (fdt) + fdt_size_dt_strings (fdt);\r
1e57a462 114}\r
115\r
e7108d0e
MK
116static int\r
117_fdt_splice (\r
118 void *fdt,\r
119 void *splicepoint,\r
120 int oldlen,\r
121 int newlen\r
122 )\r
1e57a462 123{\r
e7108d0e
MK
124 char *p = splicepoint;\r
125 char *end = (char *)fdt + _fdt_data_size (fdt);\r
1e57a462 126\r
e7108d0e
MK
127 if (((p + oldlen) < p) || ((p + oldlen) > end)) {\r
128 return -FDT_ERR_BADOFFSET;\r
129 }\r
1e57a462 130\r
e7108d0e
MK
131 if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt)) {\r
132 return -FDT_ERR_BADOFFSET;\r
133 }\r
1e57a462 134\r
e7108d0e
MK
135 if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize (fdt))) {\r
136 return -FDT_ERR_NOSPACE;\r
137 }\r
1e57a462 138\r
e7108d0e
MK
139 memmove (p + newlen, p + oldlen, end - p - oldlen);\r
140 return 0;\r
1e57a462 141}\r
142\r
e7108d0e
MK
143static int\r
144_fdt_splice_mem_rsv (\r
145 void *fdt,\r
146 struct fdt_reserve_entry *p,\r
147 int oldn,\r
148 int newn\r
149 )\r
1e57a462 150{\r
e7108d0e
MK
151 int delta = (newn - oldn) * sizeof (*p);\r
152 int err;\r
1e57a462 153\r
e7108d0e
MK
154 err = _fdt_splice (fdt, p, oldn * sizeof (*p), newn * sizeof (*p));\r
155 if (err) {\r
156 return err;\r
157 }\r
1e57a462 158\r
e7108d0e
MK
159 fdt_set_off_dt_struct (fdt, fdt_off_dt_struct (fdt) + delta);\r
160 fdt_set_off_dt_strings (fdt, fdt_off_dt_strings (fdt) + delta);\r
161 return 0;\r
1e57a462 162}\r
163\r
e7108d0e
MK
164static int\r
165_fdt_splice_struct (\r
166 void *fdt,\r
167 void *p,\r
168 int oldlen,\r
169 int newlen\r
170 )\r
1e57a462 171{\r
e7108d0e
MK
172 int delta = newlen - oldlen;\r
173 int err;\r
1e57a462 174\r
e7108d0e
MK
175 if ((err = _fdt_splice (fdt, p, oldlen, newlen))) {\r
176 return err;\r
177 }\r
1e57a462 178\r
e7108d0e
MK
179 fdt_set_size_dt_struct (fdt, fdt_size_dt_struct (fdt) + delta);\r
180 fdt_set_off_dt_strings (fdt, fdt_off_dt_strings (fdt) + delta);\r
181 return 0;\r
1e57a462 182}\r
183\r
e7108d0e
MK
184static int\r
185_fdt_splice_string (\r
186 void *fdt,\r
187 int newlen\r
188 )\r
1e57a462 189{\r
e7108d0e
MK
190 void *p = (char *)fdt\r
191 + fdt_off_dt_strings (fdt) + fdt_size_dt_strings (fdt);\r
192 int err;\r
1e57a462 193\r
e7108d0e
MK
194 if ((err = _fdt_splice (fdt, p, 0, newlen))) {\r
195 return err;\r
196 }\r
1e57a462 197\r
e7108d0e
MK
198 fdt_set_size_dt_strings (fdt, fdt_size_dt_strings (fdt) + newlen);\r
199 return 0;\r
200}\r
1e57a462 201\r
e7108d0e
MK
202static int\r
203_fdt_find_add_string (\r
204 void *fdt,\r
205 const char *s\r
206 )\r
207{\r
208 char *strtab = (char *)fdt + fdt_off_dt_strings (fdt);\r
209 const char *p;\r
210 char *new;\r
211 int len = strlen (s) + 1;\r
212 int err;\r
213\r
214 p = _fdt_find_string (strtab, fdt_size_dt_strings (fdt), s);\r
215 if (p) {\r
216 /* found it */\r
217 return (p - strtab);\r
218 }\r
219\r
220 new = strtab + fdt_size_dt_strings (fdt);\r
221 err = _fdt_splice_string (fdt, len);\r
222 if (err) {\r
223 return err;\r
224 }\r
225\r
226 memcpy (new, s, len);\r
227 return (new - strtab);\r
1e57a462 228}\r
229\r
e7108d0e
MK
230int\r
231fdt_add_mem_rsv (\r
232 void *fdt,\r
233 uint64_t address,\r
234 uint64_t size\r
235 )\r
1e57a462 236{\r
e7108d0e
MK
237 struct fdt_reserve_entry *re;\r
238 int err;\r
1e57a462 239\r
e7108d0e 240 FDT_RW_CHECK_HEADER (fdt);\r
1e57a462 241\r
e7108d0e
MK
242 re = _fdt_mem_rsv_w (fdt, fdt_num_mem_rsv (fdt));\r
243 err = _fdt_splice_mem_rsv (fdt, re, 0, 1);\r
244 if (err) {\r
245 return err;\r
246 }\r
1e57a462 247\r
e7108d0e
MK
248 re->address = cpu_to_fdt64 (address);\r
249 re->size = cpu_to_fdt64 (size);\r
250 return 0;\r
1e57a462 251}\r
252\r
e7108d0e
MK
253int\r
254fdt_del_mem_rsv (\r
255 void *fdt,\r
256 int n\r
257 )\r
1e57a462 258{\r
e7108d0e 259 struct fdt_reserve_entry *re = _fdt_mem_rsv_w (fdt, n);\r
1e57a462 260\r
e7108d0e 261 FDT_RW_CHECK_HEADER (fdt);\r
1e57a462 262\r
e7108d0e
MK
263 if (n >= fdt_num_mem_rsv (fdt)) {\r
264 return -FDT_ERR_NOTFOUND;\r
265 }\r
1e57a462 266\r
e7108d0e 267 return _fdt_splice_mem_rsv (fdt, re, 1, 0);\r
1e57a462 268}\r
269\r
e7108d0e
MK
270static int\r
271_fdt_resize_property (\r
272 void *fdt,\r
273 int nodeoffset,\r
274 const char *name,\r
275 int len,\r
276 struct fdt_property **prop\r
277 )\r
1e57a462 278{\r
e7108d0e
MK
279 int oldlen;\r
280 int err;\r
281\r
282 *prop = fdt_get_property_w (fdt, nodeoffset, name, &oldlen);\r
283 if (!*prop) {\r
284 return oldlen;\r
285 }\r
286\r
287 if ((err = _fdt_splice_struct (\r
288 fdt,\r
289 (*prop)->data,\r
290 FDT_TAGALIGN (oldlen),\r
291 FDT_TAGALIGN (len)\r
292 )))\r
293 {\r
294 return err;\r
295 }\r
296\r
297 (*prop)->len = cpu_to_fdt32 (len);\r
298 return 0;\r
299}\r
1e57a462 300\r
e7108d0e
MK
301static int\r
302_fdt_add_property (\r
303 void *fdt,\r
304 int nodeoffset,\r
305 const char *name,\r
306 int len,\r
307 struct fdt_property **prop\r
308 )\r
309{\r
310 int proplen;\r
311 int nextoffset;\r
312 int namestroff;\r
313 int err;\r
314\r
315 if ((nextoffset = _fdt_check_node_offset (fdt, nodeoffset)) < 0) {\r
316 return nextoffset;\r
317 }\r
318\r
319 namestroff = _fdt_find_add_string (fdt, name);\r
320 if (namestroff < 0) {\r
321 return namestroff;\r
322 }\r
323\r
324 *prop = _fdt_offset_ptr_w (fdt, nextoffset);\r
325 proplen = sizeof (**prop) + FDT_TAGALIGN (len);\r
326\r
327 err = _fdt_splice_struct (fdt, *prop, 0, proplen);\r
328 if (err) {\r
329 return err;\r
330 }\r
331\r
332 (*prop)->tag = cpu_to_fdt32 (FDT_PROP);\r
333 (*prop)->nameoff = cpu_to_fdt32 (namestroff);\r
334 (*prop)->len = cpu_to_fdt32 (len);\r
335 return 0;\r
336}\r
1e57a462 337\r
e7108d0e
MK
338int\r
339fdt_set_name (\r
340 void *fdt,\r
341 int nodeoffset,\r
342 const char *name\r
343 )\r
344{\r
345 char *namep;\r
346 int oldlen, newlen;\r
347 int err;\r
348\r
349 FDT_RW_CHECK_HEADER (fdt);\r
350\r
351 namep = (char *)(uintptr_t)fdt_get_name (fdt, nodeoffset, &oldlen);\r
352 if (!namep) {\r
353 return oldlen;\r
354 }\r
355\r
356 newlen = strlen (name);\r
357\r
358 err = _fdt_splice_struct (\r
359 fdt,\r
360 namep,\r
361 FDT_TAGALIGN (oldlen+1),\r
362 FDT_TAGALIGN (newlen+1)\r
363 );\r
364 if (err) {\r
365 return err;\r
366 }\r
367\r
368 memcpy (namep, name, newlen+1);\r
369 return 0;\r
1e57a462 370}\r
371\r
e7108d0e
MK
372int\r
373fdt_setprop_placeholder (\r
374 void *fdt,\r
375 int nodeoffset,\r
376 const char *name,\r
377 int len,\r
378 void **prop_data\r
379 )\r
1e57a462 380{\r
e7108d0e
MK
381 struct fdt_property *prop;\r
382 int err;\r
383\r
384 FDT_RW_CHECK_HEADER (fdt);\r
1e57a462 385\r
e7108d0e
MK
386 err = _fdt_resize_property (fdt, nodeoffset, name, len, &prop);\r
387 if (err == -FDT_ERR_NOTFOUND) {\r
388 err = _fdt_add_property (fdt, nodeoffset, name, len, &prop);\r
389 }\r
1e57a462 390\r
e7108d0e
MK
391 if (err) {\r
392 return err;\r
393 }\r
1e57a462 394\r
e7108d0e
MK
395 *prop_data = prop->data;\r
396 return 0;\r
a0992390
PB
397}\r
398\r
e7108d0e
MK
399int\r
400fdt_setprop (\r
401 void *fdt,\r
402 int nodeoffset,\r
403 const char *name,\r
404 const void *val,\r
405 int len\r
406 )\r
a0992390 407{\r
e7108d0e
MK
408 void *prop_data;\r
409 int err;\r
a0992390 410\r
e7108d0e
MK
411 err = fdt_setprop_placeholder (fdt, nodeoffset, name, len, &prop_data);\r
412 if (err) {\r
413 return err;\r
414 }\r
a0992390 415\r
e7108d0e
MK
416 if (len) {\r
417 memcpy (prop_data, val, len);\r
418 }\r
419\r
420 return 0;\r
1e57a462 421}\r
422\r
e7108d0e
MK
423int\r
424fdt_appendprop (\r
425 void *fdt,\r
426 int nodeoffset,\r
427 const char *name,\r
428 const void *val,\r
429 int len\r
430 )\r
1e57a462 431{\r
e7108d0e
MK
432 struct fdt_property *prop;\r
433 int err, oldlen, newlen;\r
434\r
435 FDT_RW_CHECK_HEADER (fdt);\r
436\r
437 prop = fdt_get_property_w (fdt, nodeoffset, name, &oldlen);\r
438 if (prop) {\r
439 newlen = len + oldlen;\r
440 err = _fdt_splice_struct (\r
441 fdt,\r
442 prop->data,\r
443 FDT_TAGALIGN (oldlen),\r
444 FDT_TAGALIGN (newlen)\r
445 );\r
446 if (err) {\r
447 return err;\r
448 }\r
449\r
450 prop->len = cpu_to_fdt32 (newlen);\r
451 memcpy (prop->data + oldlen, val, len);\r
452 } else {\r
453 err = _fdt_add_property (fdt, nodeoffset, name, len, &prop);\r
454 if (err) {\r
455 return err;\r
456 }\r
457\r
458 memcpy (prop->data, val, len);\r
459 }\r
460\r
461 return 0;\r
1e57a462 462}\r
463\r
e7108d0e
MK
464int\r
465fdt_delprop (\r
466 void *fdt,\r
467 int nodeoffset,\r
468 const char *name\r
469 )\r
1e57a462 470{\r
e7108d0e
MK
471 struct fdt_property *prop;\r
472 int len, proplen;\r
1e57a462 473\r
e7108d0e 474 FDT_RW_CHECK_HEADER (fdt);\r
1e57a462 475\r
e7108d0e
MK
476 prop = fdt_get_property_w (fdt, nodeoffset, name, &len);\r
477 if (!prop) {\r
478 return len;\r
479 }\r
1e57a462 480\r
e7108d0e
MK
481 proplen = sizeof (*prop) + FDT_TAGALIGN (len);\r
482 return _fdt_splice_struct (fdt, prop, proplen, 0);\r
1e57a462 483}\r
484\r
e7108d0e
MK
485int\r
486fdt_add_subnode_namelen (\r
487 void *fdt,\r
488 int parentoffset,\r
489 const char *name,\r
490 int namelen\r
491 )\r
1e57a462 492{\r
e7108d0e
MK
493 struct fdt_node_header *nh;\r
494 int offset, nextoffset;\r
495 int nodelen;\r
496 int err;\r
497 uint32_t tag;\r
498 fdt32_t *endtag;\r
499\r
500 FDT_RW_CHECK_HEADER (fdt);\r
501\r
502 offset = fdt_subnode_offset_namelen (fdt, parentoffset, name, namelen);\r
503 if (offset >= 0) {\r
504 return -FDT_ERR_EXISTS;\r
505 } else if (offset != -FDT_ERR_NOTFOUND) {\r
506 return offset;\r
507 }\r
508\r
509 /* Try to place the new node after the parent's properties */\r
510 fdt_next_tag (fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */\r
511 do {\r
512 offset = nextoffset;\r
513 tag = fdt_next_tag (fdt, offset, &nextoffset);\r
514 } while ((tag == FDT_PROP) || (tag == FDT_NOP));\r
515\r
516 nh = _fdt_offset_ptr_w (fdt, offset);\r
517 nodelen = sizeof (*nh) + FDT_TAGALIGN (namelen+1) + FDT_TAGSIZE;\r
518\r
519 err = _fdt_splice_struct (fdt, nh, 0, nodelen);\r
520 if (err) {\r
521 return err;\r
522 }\r
523\r
524 nh->tag = cpu_to_fdt32 (FDT_BEGIN_NODE);\r
525 memset (nh->name, 0, FDT_TAGALIGN (namelen+1));\r
526 memcpy (nh->name, name, namelen);\r
527 endtag = (fdt32_t *)((char *)nh + nodelen - FDT_TAGSIZE);\r
528 *endtag = cpu_to_fdt32 (FDT_END_NODE);\r
529\r
530 return offset;\r
1e57a462 531}\r
532\r
e7108d0e
MK
533int\r
534fdt_add_subnode (\r
535 void *fdt,\r
536 int parentoffset,\r
537 const char *name\r
538 )\r
1e57a462 539{\r
e7108d0e 540 return fdt_add_subnode_namelen (fdt, parentoffset, name, strlen (name));\r
1e57a462 541}\r
542\r
e7108d0e
MK
543int\r
544fdt_del_node (\r
545 void *fdt,\r
546 int nodeoffset\r
547 )\r
1e57a462 548{\r
e7108d0e 549 int endoffset;\r
1e57a462 550\r
e7108d0e 551 FDT_RW_CHECK_HEADER (fdt);\r
1e57a462 552\r
e7108d0e
MK
553 endoffset = _fdt_node_end_offset (fdt, nodeoffset);\r
554 if (endoffset < 0) {\r
555 return endoffset;\r
556 }\r
1e57a462 557\r
e7108d0e
MK
558 return _fdt_splice_struct (\r
559 fdt,\r
560 _fdt_offset_ptr_w (fdt, nodeoffset),\r
561 endoffset - nodeoffset,\r
562 0\r
563 );\r
1e57a462 564}\r
565\r
e7108d0e
MK
566static void\r
567_fdt_packblocks (\r
568 const char *old,\r
569 char *new,\r
570 int mem_rsv_size,\r
571 int struct_size\r
572 )\r
1e57a462 573{\r
e7108d0e
MK
574 int mem_rsv_off, struct_off, strings_off;\r
575\r
576 mem_rsv_off = FDT_ALIGN (sizeof (struct fdt_header), 8);\r
577 struct_off = mem_rsv_off + mem_rsv_size;\r
578 strings_off = struct_off + struct_size;\r
579\r
580 memmove (new + mem_rsv_off, old + fdt_off_mem_rsvmap (old), mem_rsv_size);\r
581 fdt_set_off_mem_rsvmap (new, mem_rsv_off);\r
582\r
583 memmove (new + struct_off, old + fdt_off_dt_struct (old), struct_size);\r
584 fdt_set_off_dt_struct (new, struct_off);\r
585 fdt_set_size_dt_struct (new, struct_size);\r
586\r
587 memmove (\r
588 new + strings_off,\r
589 old + fdt_off_dt_strings (old),\r
590 fdt_size_dt_strings (old)\r
591 );\r
592 fdt_set_off_dt_strings (new, strings_off);\r
593 fdt_set_size_dt_strings (new, fdt_size_dt_strings (old));\r
1e57a462 594}\r
595\r
e7108d0e
MK
596int\r
597fdt_open_into (\r
598 const void *fdt,\r
599 void *buf,\r
600 int bufsize\r
601 )\r
1e57a462 602{\r
e7108d0e
MK
603 int err;\r
604 int mem_rsv_size, struct_size;\r
605 int newsize;\r
606 const char *fdtstart = fdt;\r
607 const char *fdtend = fdtstart + fdt_totalsize (fdt);\r
608 char *tmp;\r
609\r
610 FDT_CHECK_HEADER (fdt);\r
611\r
612 mem_rsv_size = (fdt_num_mem_rsv (fdt)+1)\r
613 * sizeof (struct fdt_reserve_entry);\r
614\r
615 if (fdt_version (fdt) >= 17) {\r
616 struct_size = fdt_size_dt_struct (fdt);\r
617 } else {\r
618 struct_size = 0;\r
619 while (fdt_next_tag (fdt, struct_size, &struct_size) != FDT_END) {\r
620 }\r
621\r
622 if (struct_size < 0) {\r
623 return struct_size;\r
624 }\r
625 }\r
626\r
627 if (!_fdt_blocks_misordered (fdt, mem_rsv_size, struct_size)) {\r
628 /* no further work necessary */\r
629 err = fdt_move (fdt, buf, bufsize);\r
630 if (err) {\r
631 return err;\r
632 }\r
633\r
634 fdt_set_version (buf, 17);\r
635 fdt_set_size_dt_struct (buf, struct_size);\r
636 fdt_set_totalsize (buf, bufsize);\r
637 return 0;\r
638 }\r
639\r
640 /* Need to reorder */\r
641 newsize = FDT_ALIGN (sizeof (struct fdt_header), 8) + mem_rsv_size\r
642 + struct_size + fdt_size_dt_strings (fdt);\r
643\r
644 if (bufsize < newsize) {\r
645 return -FDT_ERR_NOSPACE;\r
646 }\r
647\r
648 /* First attempt to build converted tree at beginning of buffer */\r
649 tmp = buf;\r
650 /* But if that overlaps with the old tree... */\r
651 if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) {\r
652 /* Try right after the old tree instead */\r
653 tmp = (char *)(uintptr_t)fdtend;\r
654 if ((tmp + newsize) > ((char *)buf + bufsize)) {\r
655 return -FDT_ERR_NOSPACE;\r
656 }\r
657 }\r
658\r
659 _fdt_packblocks (fdt, tmp, mem_rsv_size, struct_size);\r
660 memmove (buf, tmp, newsize);\r
661\r
662 fdt_set_magic (buf, FDT_MAGIC);\r
663 fdt_set_totalsize (buf, bufsize);\r
664 fdt_set_version (buf, 17);\r
665 fdt_set_last_comp_version (buf, 16);\r
666 fdt_set_boot_cpuid_phys (buf, fdt_boot_cpuid_phys (fdt));\r
667\r
668 return 0;\r
1e57a462 669}\r
670\r
e7108d0e
MK
671int\r
672fdt_pack (\r
673 void *fdt\r
674 )\r
1e57a462 675{\r
e7108d0e 676 int mem_rsv_size;\r
1e57a462 677\r
e7108d0e 678 FDT_RW_CHECK_HEADER (fdt);\r
1e57a462 679\r
e7108d0e
MK
680 mem_rsv_size = (fdt_num_mem_rsv (fdt)+1)\r
681 * sizeof (struct fdt_reserve_entry);\r
682 _fdt_packblocks (fdt, fdt, mem_rsv_size, fdt_size_dt_struct (fdt));\r
683 fdt_set_totalsize (fdt, _fdt_data_size (fdt));\r
1e57a462 684\r
e7108d0e 685 return 0;\r
1e57a462 686}\r