blob: 6326e82a2ad66b4e963b2b60f01c81b14a35588b [file] [log] [blame]
Channagoud Kadabiafd62bf2013-01-08 20:32:52 -08001/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07002 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*/
28
29#include <libfdt.h>
30#include <dev_tree.h>
31#include <lib/ptable.h>
32#include <malloc.h>
33#include <qpic_nand.h>
34#include <stdlib.h>
35#include <string.h>
36#include <platform.h>
37#include <board.h>
38
Joel Kingaa335dc2013-06-03 16:11:08 -070039struct dt_entry_v1
40{
41 uint32_t platform_id;
42 uint32_t variant_id;
43 uint32_t soc_rev;
44 uint32_t offset;
45 uint32_t size;
46};
47
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070048extern int target_is_emmc_boot(void);
49extern uint32_t target_dev_tree_mem(void *fdt, uint32_t memory_node_offset);
Deepa Dinamanic55f01b2013-05-30 14:05:56 -070050/* TODO: This function needs to be moved to target layer to check violations
51 * against all the other regions as well.
52 */
53extern int check_aboot_addr_range_overlap(uint32_t start, uint32_t size);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070054
Dima Zavinc46f8382013-05-03 12:23:06 -070055struct msm_id
56{
57 uint32_t platform_id;
58 uint32_t hardware_id;
59 uint32_t soc_rev;
60};
61
Shashank Mittalc0f10282013-07-15 14:53:31 -070062/* Returns soc version if platform id and hardware id matches
63 otherwise return 0xFFFFFFFF */
64#define INVALID_SOC_REV_ID 0XFFFFFFFF
65static uint32_t dev_tree_compatible(void *dtb)
Dima Zavinc46f8382013-05-03 12:23:06 -070066{
67 int root_offset;
68 const void *prop;
69 char model[128];
70 struct msm_id msm_id;
71 int len;
72
73 root_offset = fdt_path_offset(dtb, "/");
74 if (root_offset < 0)
75 return false;
76
77 prop = fdt_getprop(dtb, root_offset, "model", &len);
78 if (prop && len > 0) {
79 memcpy(model, prop, MIN((int)sizeof(model), len));
80 model[sizeof(model) - 1] = '\0';
81 } else {
82 model[0] = '\0';
83 }
84
85 prop = fdt_getprop(dtb, root_offset, "qcom,msm-id", &len);
86 if (!prop || len <= 0) {
87 dprintf(INFO, "qcom,msm-id entry not found\n");
88 return false;
89 } else if (len < (int)sizeof(struct msm_id)) {
90 dprintf(INFO, "qcom,msm-id entry size mismatch (%d != %d)\n",
91 len, sizeof(struct msm_id));
92 return false;
93 }
94 msm_id.platform_id = fdt32_to_cpu(((const struct msm_id *)prop)->platform_id);
95 msm_id.hardware_id = fdt32_to_cpu(((const struct msm_id *)prop)->hardware_id);
96 msm_id.soc_rev = fdt32_to_cpu(((const struct msm_id *)prop)->soc_rev);
97
98 dprintf(INFO, "Found an appended flattened device tree (%s - %d %d 0x%x)\n",
99 *model ? model : "unknown",
100 msm_id.platform_id, msm_id.hardware_id, msm_id.soc_rev);
101
102 if (msm_id.platform_id != board_platform_id() ||
Shashank Mittalc0f10282013-07-15 14:53:31 -0700103 msm_id.hardware_id != board_hardware_id()) {
Dima Zavinc46f8382013-05-03 12:23:06 -0700104 dprintf(INFO, "Device tree's msm_id doesn't match the board: <%d %d 0x%x> != <%d %d 0x%x>\n",
105 msm_id.platform_id,
106 msm_id.hardware_id,
107 msm_id.soc_rev,
108 board_platform_id(),
109 board_hardware_id(),
110 board_soc_version());
Shashank Mittalc0f10282013-07-15 14:53:31 -0700111 return INVALID_SOC_REV_ID;
Dima Zavinc46f8382013-05-03 12:23:06 -0700112 }
113
Channagoud Kadabie153f502013-08-02 11:56:38 -0700114 dprintf(INFO, "Device tree's msm_id matches the board: <%d %d 0x%x> == <%d %d 0x%x>\n",
Shashank Mittalc0f10282013-07-15 14:53:31 -0700115 msm_id.platform_id,
116 msm_id.hardware_id,
117 msm_id.soc_rev,
118 board_platform_id(),
119 board_hardware_id(),
120 board_soc_version());
121 return msm_id.soc_rev;
Dima Zavinc46f8382013-05-03 12:23:06 -0700122}
123
Channagoud Kadabi11682e92013-02-28 11:21:46 -0800124/*
Dima Zavin77e41f32013-03-06 16:10:43 -0800125 * Will relocate the DTB to the tags addr if the device tree is found and return
126 * its address
127 *
128 * Arguments: kernel - Start address of the kernel loaded in RAM
129 * tags - Start address of the tags loaded in RAM
Channagoud Kadabi704cd562013-04-25 15:19:59 -0700130 * kernel_size - Size of the kernel in bytes
131 *
Channagoud Kadabi11682e92013-02-28 11:21:46 -0800132 * Return Value: DTB address : If appended device tree is found
Dima Zavin77e41f32013-03-06 16:10:43 -0800133 * 'NULL' : Otherwise
Channagoud Kadabi11682e92013-02-28 11:21:46 -0800134 */
Dima Zavinc46f8382013-05-03 12:23:06 -0700135void *dev_tree_appended(void *kernel, uint32_t kernel_size, void *tags)
Channagoud Kadabi11682e92013-02-28 11:21:46 -0800136{
Dima Zavinc46f8382013-05-03 12:23:06 -0700137 void *kernel_end = kernel + kernel_size;
Channagoud Kadabi11682e92013-02-28 11:21:46 -0800138 uint32_t app_dtb_offset = 0;
Dima Zavinc46f8382013-05-03 12:23:06 -0700139 void *dtb;
Shashank Mittalc0f10282013-07-15 14:53:31 -0700140 void *bestmatch_tag = NULL;
141 uint32_t bestmatch_tag_size;
142 uint32_t bestmatch_soc_rev_id = INVALID_SOC_REV_ID;
Channagoud Kadabi11682e92013-02-28 11:21:46 -0800143
144 memcpy((void*) &app_dtb_offset, (void*) (kernel + DTB_OFFSET), sizeof(uint32_t));
Channagoud Kadabi11682e92013-02-28 11:21:46 -0800145
Dima Zavinc46f8382013-05-03 12:23:06 -0700146 dtb = kernel + app_dtb_offset;
147 while (dtb + sizeof(struct fdt_header) < kernel_end) {
Shashank Mittalc0f10282013-07-15 14:53:31 -0700148 uint32_t dtb_soc_rev_id;
Dima Zavinc46f8382013-05-03 12:23:06 -0700149 struct fdt_header dtb_hdr;
150 uint32_t dtb_size;
Dima Zavin77e41f32013-03-06 16:10:43 -0800151
Dima Zavinc46f8382013-05-03 12:23:06 -0700152 /* the DTB could be unaligned, so extract the header,
153 * and operate on it separately */
154 memcpy(&dtb_hdr, dtb, sizeof(struct fdt_header));
155 if (fdt_check_header((const void *)&dtb_hdr) != 0 ||
156 (dtb + fdt_totalsize((const void *)&dtb_hdr) > kernel_end))
157 break;
158 dtb_size = fdt_totalsize(&dtb_hdr);
159
vijay kumard3ba56f2014-06-24 16:30:18 +0530160 if (check_aboot_addr_range_overlap(tags, dtb_size)) {
161 dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
162 return NULL;
163 }
164
Dima Zavinc46f8382013-05-03 12:23:06 -0700165 /* now that we know we have a valid DTB, we need to copy
166 * it somewhere aligned, like tags */
167 memcpy(tags, dtb, dtb_size);
168
Shashank Mittalc0f10282013-07-15 14:53:31 -0700169 dtb_soc_rev_id = dev_tree_compatible(tags);
170 if (dtb_soc_rev_id == board_soc_version()) {
Dima Zavinc46f8382013-05-03 12:23:06 -0700171 /* clear out the old DTB magic so kernel doesn't find it */
172 *((uint32_t *)(kernel + app_dtb_offset)) = 0;
173 return tags;
Shashank Mittalc0f10282013-07-15 14:53:31 -0700174 } else if ((dtb_soc_rev_id != INVALID_SOC_REV_ID) &&
175 (dtb_soc_rev_id < board_soc_version())) {
176 /* if current bestmatch is less than new dtb_soc_rev_id then update
177 bestmatch_tag */
178 if((bestmatch_soc_rev_id == INVALID_SOC_REV_ID) ||
179 (bestmatch_soc_rev_id < dtb_soc_rev_id)) {
180 bestmatch_tag = dtb;
181 bestmatch_tag_size = dtb_size;
182 bestmatch_soc_rev_id = dtb_soc_rev_id;
183 }
Dima Zavin77e41f32013-03-06 16:10:43 -0800184 }
Dima Zavinc46f8382013-05-03 12:23:06 -0700185
186 /* goto the next device tree if any */
187 dtb += dtb_size;
Channagoud Kadabi11682e92013-02-28 11:21:46 -0800188 }
Dima Zavinc46f8382013-05-03 12:23:06 -0700189
Shashank Mittalc0f10282013-07-15 14:53:31 -0700190 if(bestmatch_tag) {
191 dprintf(INFO,"DTB found with bestmatch soc rev id 0x%x.Board soc rev id 0x%x\n",
192 bestmatch_soc_rev_id, board_soc_version());
193 memcpy(tags, bestmatch_tag, bestmatch_tag_size);
194 /* clear out the old DTB magic so kernel doesn't find it */
195 *((uint32_t *)(kernel + app_dtb_offset)) = 0;
196 return tags;
197 }
198
Dima Zavinc46f8382013-05-03 12:23:06 -0700199 dprintf(CRITICAL, "DTB offset is incorrect, kernel image does not have appended DTB\n");
Channagoud Kadabi11682e92013-02-28 11:21:46 -0800200
Dima Zavin77e41f32013-03-06 16:10:43 -0800201 return NULL;
Channagoud Kadabi11682e92013-02-28 11:21:46 -0800202}
203
Joel Kingaa335dc2013-06-03 16:11:08 -0700204/* Returns 0 if the device tree is valid. */
Deepa Dinamani87252952013-09-09 13:58:27 -0700205int dev_tree_validate(struct dt_table *table, unsigned int page_size, uint32_t *dt_hdr_size)
Joel Kingaa335dc2013-06-03 16:11:08 -0700206{
207 int dt_entry_size;
Deepa Dinamani87252952013-09-09 13:58:27 -0700208 uint32_t hdr_size;
Joel Kingaa335dc2013-06-03 16:11:08 -0700209
210 /* Validate the device tree table header */
211 if(table->magic != DEV_TREE_MAGIC) {
212 dprintf(CRITICAL, "ERROR: Bad magic in device tree table \n");
213 return -1;
214 }
215
216 if (table->version == DEV_TREE_VERSION_V1) {
217 dt_entry_size = sizeof(struct dt_entry_v1);
218 } else if (table->version == DEV_TREE_VERSION_V2) {
219 dt_entry_size = sizeof(struct dt_entry);
220 } else {
221 dprintf(CRITICAL, "ERROR: Unsupported version (%d) in DT table \n",
222 table->version);
223 return -1;
224 }
225
Deepa Dinamani87252952013-09-09 13:58:27 -0700226 hdr_size = table->num_entries * dt_entry_size + DEV_TREE_HEADER_SIZE;
227 /* Roundup to page_size. */
228 hdr_size = ROUNDUP(hdr_size, page_size);
229
230 *dt_hdr_size = hdr_size;
Joel Kingaa335dc2013-06-03 16:11:08 -0700231
232 return 0;
233}
234
Maria Yu2e2d2c22013-07-03 19:20:33 +0800235static int platform_dt_match(struct dt_entry *cur_dt_entry, uint32_t target_variant_id, uint32_t subtype_mask)
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700236{
Maria Yu2e2d2c22013-07-03 19:20:33 +0800237 /* 1. must match the platform_id, hardware_id, platform_version
238 * 2. soc rev number equal then return 0
239 * 3. dt soc rev number less than cdt return -1
240 * 4. otherwise return 1
241 */
242 uint32_t cur_dt_target_id ;
Maria Yuca51ee22013-06-27 21:45:24 +0800243
Maria Yu2e2d2c22013-07-03 19:20:33 +0800244 cur_dt_target_id = cur_dt_entry->variant_id | ((cur_dt_entry->board_hw_subtype & subtype_mask & 0xff) << 24);
245
246 if((cur_dt_entry->platform_id == board_platform_id()) &&
247 (cur_dt_target_id == target_variant_id)) {
248 if(cur_dt_entry->soc_rev == board_soc_version()) {
Maria Yuca51ee22013-06-27 21:45:24 +0800249 return 0;
Maria Yu2e2d2c22013-07-03 19:20:33 +0800250 } else if(cur_dt_entry->soc_rev < board_soc_version()) {
251 return -1;
Maria Yuca51ee22013-06-27 21:45:24 +0800252 }
253 }
Maria Yuca51ee22013-06-27 21:45:24 +0800254
Maria Yu2e2d2c22013-07-03 19:20:33 +0800255 return 1;
Maria Yuca51ee22013-06-27 21:45:24 +0800256}
257
Maria Yu2e2d2c22013-07-03 19:20:33 +0800258static int __dev_tree_get_entry_info(struct dt_table *table, struct dt_entry *dt_entry_info,
259 uint32_t target_variant_id, uint32_t subtype_mask)
Maria Yuca51ee22013-06-27 21:45:24 +0800260{
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700261 uint32_t i;
Joel Kingaa335dc2013-06-03 16:11:08 -0700262 unsigned char *table_ptr;
263 struct dt_entry dt_entry_buf_1;
264 struct dt_entry dt_entry_buf_2;
265 struct dt_entry *cur_dt_entry;
266 struct dt_entry *best_match_dt_entry;
267 struct dt_entry_v1 *dt_entry_v1;
Maria Yu2e2d2c22013-07-03 19:20:33 +0800268 uint32_t found = 0;
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700269
Joel Kingaa335dc2013-06-03 16:11:08 -0700270 if (!dt_entry_info) {
271 dprintf(CRITICAL, "ERROR: Bad parameter passed to %s \n",
272 __func__);
273 return -1;
274 }
275
276 table_ptr = (unsigned char *)table + DEV_TREE_HEADER_SIZE;
277 cur_dt_entry = &dt_entry_buf_1;
278 best_match_dt_entry = NULL;
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700279
Maria Yu2e2d2c22013-07-03 19:20:33 +0800280 for(i = 0; found == 0 && i < table->num_entries; i++)
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700281 {
Joel Kingaa335dc2013-06-03 16:11:08 -0700282 memset(cur_dt_entry, 0, sizeof(struct dt_entry));
283 switch(table->version) {
284 case DEV_TREE_VERSION_V1:
285 dt_entry_v1 = (struct dt_entry_v1 *)table_ptr;
286 cur_dt_entry->platform_id = dt_entry_v1->platform_id;
287 cur_dt_entry->variant_id = dt_entry_v1->variant_id;
288 cur_dt_entry->soc_rev = dt_entry_v1->soc_rev;
289 cur_dt_entry->board_hw_subtype = board_hardware_subtype();
290 cur_dt_entry->offset = dt_entry_v1->offset;
291 cur_dt_entry->size = dt_entry_v1->size;
292 table_ptr += sizeof(struct dt_entry_v1);
293 break;
294 case DEV_TREE_VERSION_V2:
295 memcpy(cur_dt_entry, (struct dt_entry *)table_ptr,
296 sizeof(struct dt_entry));
297 table_ptr += sizeof(struct dt_entry);
298 break;
299 default:
300 dprintf(CRITICAL, "ERROR: Unsupported version (%d) in DT table \n",
301 table->version);
302 return -1;
303 }
304
Channagoud Kadabiafd62bf2013-01-08 20:32:52 -0800305 /* DTBs are stored in the ascending order of soc revision.
306 * For eg: Rev0..Rev1..Rev2 & so on.
307 * we pickup the DTB with highest soc rev number which is less
308 * than or equal to actual hardware
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700309 */
Maria Yu2e2d2c22013-07-03 19:20:33 +0800310 switch(platform_dt_match(cur_dt_entry, target_variant_id, subtype_mask)) {
311 case 0:
312 best_match_dt_entry = cur_dt_entry;
313 found = 1;
314 break;
315 case -1:
316 if (!best_match_dt_entry) {
317 /* copy structure */
David Ng618293a2013-06-25 12:29:03 -0700318 best_match_dt_entry = cur_dt_entry;
Maria Yu2e2d2c22013-07-03 19:20:33 +0800319 cur_dt_entry = &dt_entry_buf_2;
320 } else {
321 /* Swap dt_entry buffers */
322 struct dt_entry *temp = cur_dt_entry;
323 cur_dt_entry = best_match_dt_entry;
324 best_match_dt_entry = temp;
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700325 }
Maria Yu2e2d2c22013-07-03 19:20:33 +0800326 default:
327 break;
Channagoud Kadabiafd62bf2013-01-08 20:32:52 -0800328 }
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700329 }
Channagoud Kadabiafd62bf2013-01-08 20:32:52 -0800330
Joel Kingaa335dc2013-06-03 16:11:08 -0700331 if (best_match_dt_entry) {
332 *dt_entry_info = *best_match_dt_entry;
Maria Yu2e2d2c22013-07-03 19:20:33 +0800333 found = 1;
334 }
335
336 if (found != 0) {
David Ng618293a2013-06-25 12:29:03 -0700337 dprintf(INFO, "Using DTB entry %u/%08x/%u/%u for device %u/%08x/%u/%u\n",
338 dt_entry_info->platform_id, dt_entry_info->soc_rev,
339 dt_entry_info->variant_id, dt_entry_info->board_hw_subtype,
340 board_platform_id(), board_soc_version(),
341 board_hardware_id(), board_hardware_subtype());
Joel Kingaa335dc2013-06-03 16:11:08 -0700342 return 0;
Channagoud Kadabiafd62bf2013-01-08 20:32:52 -0800343 }
344
David Ng618293a2013-06-25 12:29:03 -0700345 dprintf(CRITICAL, "ERROR: Unable to find suitable device tree for device (%u/0x%08x/%u/%u)\n",
346 board_platform_id(), board_soc_version(),
347 board_hardware_id(), board_hardware_subtype());
Joel Kingaa335dc2013-06-03 16:11:08 -0700348 return -1;
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700349}
350
Maria Yu2e2d2c22013-07-03 19:20:33 +0800351/* Function to obtain the index information for the correct device tree
352 * based on the platform data.
353 * If a matching device tree is found, the information is returned in the
354 * "dt_entry_info" out parameter and a function value of 0 is returned, otherwise
355 * a non-zero function value is returned.
356 */
357int dev_tree_get_entry_info(struct dt_table *table, struct dt_entry *dt_entry_info)
358{
359 uint32_t target_variant_id;
360
361 if(board_hardware_id() == HW_PLATFORM_QRD) {
362 target_variant_id = board_target_id();
363 if (__dev_tree_get_entry_info(table, dt_entry_info, target_variant_id, 0xff) == 0) {
364 return 0;
365 }
366 }
367 /*
368 * for compatible with version 1 and version 2 dtbtool
369 * will compare the subtype inside the variant id
370 */
371 target_variant_id = board_hardware_id() | ((board_hardware_subtype() & 0xff) << 24);
372 if (__dev_tree_get_entry_info(table, dt_entry_info, target_variant_id, 0xff) == 0) {
373 return 0;
374 }
375
376 /*
377 * add compatible with old device selection method which don't compare subtype
378 */
379 target_variant_id = board_hardware_id();
380 return __dev_tree_get_entry_info(table, dt_entry_info, target_variant_id, 0);
381}
382
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700383/* Function to add the first RAM partition info to the device tree.
384 * Note: The function replaces the reg property in the "/memory" node
385 * with the addr and size provided.
386 */
387int dev_tree_add_first_mem_info(uint32_t *fdt, uint32_t offset, uint32_t addr, uint32_t size)
388{
389 int ret;
390
391 ret = fdt_setprop_u32(fdt, offset, "reg", addr);
392
393 if (ret)
394 {
395 dprintf(CRITICAL, "Failed to add the memory information addr: %d\n",
396 ret);
397 }
398
399
400 ret = fdt_appendprop_u32(fdt, offset, "reg", size);
401
402 if (ret)
403 {
404 dprintf(CRITICAL, "Failed to add the memory information size: %d\n",
405 ret);
406 }
407
408 return ret;
409}
410
411/* Function to add the subsequent RAM partition info to the device tree. */
412int dev_tree_add_mem_info(void *fdt, uint32_t offset, uint32_t addr, uint32_t size)
413{
414 static int mem_info_cnt = 0;
415 int ret;
416
417 if (!mem_info_cnt)
418 {
419 /* Replace any other reg prop in the memory node. */
420 ret = fdt_setprop_u32(fdt, offset, "reg", addr);
421 mem_info_cnt = 1;
422 }
423 else
424 {
425 /* Append the mem info to the reg prop for subsequent nodes. */
426 ret = fdt_appendprop_u32(fdt, offset, "reg", addr);
427 }
428
429 if (ret)
430 {
431 dprintf(CRITICAL, "Failed to add the memory information addr: %d\n",
432 ret);
433 }
434
435
436 ret = fdt_appendprop_u32(fdt, offset, "reg", size);
437
438 if (ret)
439 {
440 dprintf(CRITICAL, "Failed to add the memory information size: %d\n",
441 ret);
442 }
443
444 return ret;
445}
446
447/* Top level function that updates the device tree. */
448int update_device_tree(void *fdt, const char *cmdline,
449 void *ramdisk, uint32_t ramdisk_size)
450{
451 int ret = 0;
452 uint32_t offset;
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700453
454 /* Check the device tree header */
455 ret = fdt_check_header(fdt);
456 if (ret)
457 {
458 dprintf(CRITICAL, "Invalid device tree header \n");
459 return ret;
460 }
461
Deepa Dinamani1c970732013-04-19 14:23:01 -0700462 /* Add padding to make space for new nodes and properties. */
463 ret = fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + DTB_PAD_SIZE);
464 if (ret!= 0)
465 {
466 dprintf(CRITICAL, "Failed to move/resize dtb buffer: %d\n", ret);
467 return ret;
468 }
469
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700470 /* Get offset of the memory node */
471 ret = fdt_path_offset(fdt, "/memory");
472 if (ret < 0)
473 {
474 dprintf(CRITICAL, "Could not find memory node.\n");
475 return ret;
476 }
477
478 offset = ret;
479
480 ret = target_dev_tree_mem(fdt, offset);
481 if(ret)
482 {
483 dprintf(CRITICAL, "ERROR: Cannot update memory node\n");
484 return ret;
485 }
486
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700487 /* Get offset of the chosen node */
488 ret = fdt_path_offset(fdt, "/chosen");
489 if (ret < 0)
490 {
491 dprintf(CRITICAL, "Could not find chosen node.\n");
492 return ret;
493 }
494
495 offset = ret;
496 /* Adding the cmdline to the chosen node */
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800497 ret = fdt_setprop_string(fdt, offset, (const char*)"bootargs", (const void*)cmdline);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700498 if (ret)
499 {
500 dprintf(CRITICAL, "ERROR: Cannot update chosen node [bootargs]\n");
501 return ret;
502 }
503
504 /* Adding the initrd-start to the chosen node */
505 ret = fdt_setprop_u32(fdt, offset, "linux,initrd-start", (uint32_t)ramdisk);
506 if (ret)
507 {
508 dprintf(CRITICAL, "ERROR: Cannot update chosen node [linux,initrd-start]\n");
509 return ret;
510 }
511
512 /* Adding the initrd-end to the chosen node */
513 ret = fdt_setprop_u32(fdt, offset, "linux,initrd-end", ((uint32_t)ramdisk + ramdisk_size));
514 if (ret)
515 {
516 dprintf(CRITICAL, "ERROR: Cannot update chosen node [linux,initrd-end]\n");
517 return ret;
518 }
519
520 fdt_pack(fdt);
521
522 return ret;
523}
Maria Yuca51ee22013-06-27 21:45:24 +0800524