4 #if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND)
5 #define do_extend_cmdline 1
7 #define do_extend_cmdline 0
10 static int node_offset(void *fdt, const char *node_path)
12 int offset = fdt_path_offset(fdt, node_path);
13 if (offset == -FDT_ERR_NOTFOUND)
14 offset = fdt_add_subnode(fdt, 0, node_path);
18 static int setprop(void *fdt, const char *node_path, const char *property,
19 uint32_t *val_array, int size)
21 int offset = node_offset(fdt, node_path);
24 return fdt_setprop(fdt, offset, property, val_array, size);
27 static int setprop_string(void *fdt, const char *node_path,
28 const char *property, const char *string)
30 int offset = node_offset(fdt, node_path);
33 return fdt_setprop_string(fdt, offset, property, string);
36 static int setprop_cell(void *fdt, const char *node_path,
37 const char *property, uint32_t val)
39 int offset = node_offset(fdt, node_path);
42 return fdt_setprop_cell(fdt, offset, property, val);
45 static const void *getprop(const void *fdt, const char *node_path,
46 const char *property, int *len)
48 int offset = fdt_path_offset(fdt, node_path);
50 if (offset == -FDT_ERR_NOTFOUND)
53 return fdt_getprop(fdt, offset, property, len);
56 static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline)
58 char cmdline[COMMAND_LINE_SIZE];
59 const char *fdt_bootargs;
63 /* copy the fdt command line into the buffer */
64 fdt_bootargs = getprop(fdt, "/chosen", "bootargs", &len);
66 if (len < COMMAND_LINE_SIZE) {
67 memcpy(ptr, fdt_bootargs, len);
68 /* len is the length of the string
69 * including the NULL terminator */
73 /* and append the ATAG_CMDLINE */
75 len = strlen(fdt_cmdline);
76 if (ptr - cmdline + len + 2 < COMMAND_LINE_SIZE) {
78 memcpy(ptr, fdt_cmdline, len);
84 setprop_string(fdt, "/chosen", "bootargs", cmdline);
88 * Convert and fold provided ATAGs into the provided FDT.
91 * = 0 -> pretend success
92 * = 1 -> bad ATAG (may retry with another possible ATAG pointer)
93 * < 0 -> error from libfdt
95 int atags_to_fdt(void *atag_list, void *fdt, int total_space)
97 struct tag *atag = atag_list;
98 uint32_t mem_reg_property[2 * NR_BANKS];
102 /* make sure we've got an aligned pointer */
103 if ((u32)atag_list & 0x3)
106 /* if we get a DTB here we're done already */
107 if (*(u32 *)atag_list == fdt32_to_cpu(FDT_MAGIC))
110 /* validate the ATAG */
111 if (atag->hdr.tag != ATAG_CORE ||
112 (atag->hdr.size != tag_size(tag_core) &&
113 atag->hdr.size != 2))
116 /* let's give it all the room it could need */
117 ret = fdt_open_into(fdt, fdt, total_space);
121 for_each_tag(atag, atag_list) {
122 if (atag->hdr.tag == ATAG_CMDLINE) {
123 /* Append the ATAGS command line to the device tree
125 * NB: This means that if the same parameter is set in
126 * the device tree and in the tags, the one from the
127 * tags will be chosen.
129 if (do_extend_cmdline)
130 merge_fdt_bootargs(fdt,
131 atag->u.cmdline.cmdline);
133 setprop_string(fdt, "/chosen", "bootargs",
134 atag->u.cmdline.cmdline);
135 } else if (atag->hdr.tag == ATAG_MEM) {
136 if (memcount >= sizeof(mem_reg_property)/4)
138 if (!atag->u.mem.size)
140 mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.start);
141 mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.size);
142 } else if (atag->hdr.tag == ATAG_INITRD2) {
143 uint32_t initrd_start, initrd_size;
144 initrd_start = atag->u.initrd.start;
145 initrd_size = atag->u.initrd.size;
146 setprop_cell(fdt, "/chosen", "linux,initrd-start",
148 setprop_cell(fdt, "/chosen", "linux,initrd-end",
149 initrd_start + initrd_size);
154 setprop(fdt, "/memory", "reg", mem_reg_property, 4*memcount);
156 return fdt_pack(fdt);