]>
git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - arch/arm/boot/compressed/atags_to_fdt.c
4 #if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND)
5 #define do_extend_cmdline 1
7 #define do_extend_cmdline 0
12 static int node_offset(void *fdt
, const char *node_path
)
14 int offset
= fdt_path_offset(fdt
, node_path
);
15 if (offset
== -FDT_ERR_NOTFOUND
)
16 offset
= fdt_add_subnode(fdt
, 0, node_path
);
20 static int setprop(void *fdt
, const char *node_path
, const char *property
,
21 uint32_t *val_array
, int size
)
23 int offset
= node_offset(fdt
, node_path
);
26 return fdt_setprop(fdt
, offset
, property
, val_array
, size
);
29 static int setprop_string(void *fdt
, const char *node_path
,
30 const char *property
, const char *string
)
32 int offset
= node_offset(fdt
, node_path
);
35 return fdt_setprop_string(fdt
, offset
, property
, string
);
38 static int setprop_cell(void *fdt
, const char *node_path
,
39 const char *property
, uint32_t val
)
41 int offset
= node_offset(fdt
, node_path
);
44 return fdt_setprop_cell(fdt
, offset
, property
, val
);
47 static const void *getprop(const void *fdt
, const char *node_path
,
48 const char *property
, int *len
)
50 int offset
= fdt_path_offset(fdt
, node_path
);
52 if (offset
== -FDT_ERR_NOTFOUND
)
55 return fdt_getprop(fdt
, offset
, property
, len
);
58 static uint32_t get_cell_size(const void *fdt
)
61 uint32_t cell_size
= 1;
62 const uint32_t *size_len
= getprop(fdt
, "/", "#size-cells", &len
);
65 cell_size
= fdt32_to_cpu(*size_len
);
69 static void merge_fdt_bootargs(void *fdt
, const char *fdt_cmdline
)
71 char cmdline
[COMMAND_LINE_SIZE
];
72 const char *fdt_bootargs
;
76 /* copy the fdt command line into the buffer */
77 fdt_bootargs
= getprop(fdt
, "/chosen", "bootargs", &len
);
79 if (len
< COMMAND_LINE_SIZE
) {
80 memcpy(ptr
, fdt_bootargs
, len
);
81 /* len is the length of the string
82 * including the NULL terminator */
86 /* and append the ATAG_CMDLINE */
88 len
= strlen(fdt_cmdline
);
89 if (ptr
- cmdline
+ len
+ 2 < COMMAND_LINE_SIZE
) {
91 memcpy(ptr
, fdt_cmdline
, len
);
97 setprop_string(fdt
, "/chosen", "bootargs", cmdline
);
101 * Convert and fold provided ATAGs into the provided FDT.
104 * = 0 -> pretend success
105 * = 1 -> bad ATAG (may retry with another possible ATAG pointer)
106 * < 0 -> error from libfdt
108 int atags_to_fdt(void *atag_list
, void *fdt
, int total_space
)
110 struct tag
*atag
= atag_list
;
111 /* In the case of 64 bits memory size, need to reserve 2 cells for
112 * address and size for each bank */
113 uint32_t mem_reg_property
[2 * 2 * NR_BANKS
];
117 /* make sure we've got an aligned pointer */
118 if ((u32
)atag_list
& 0x3)
121 /* if we get a DTB here we're done already */
122 if (*(u32
*)atag_list
== fdt32_to_cpu(FDT_MAGIC
))
125 /* validate the ATAG */
126 if (atag
->hdr
.tag
!= ATAG_CORE
||
127 (atag
->hdr
.size
!= tag_size(tag_core
) &&
128 atag
->hdr
.size
!= 2))
131 /* let's give it all the room it could need */
132 ret
= fdt_open_into(fdt
, fdt
, total_space
);
136 for_each_tag(atag
, atag_list
) {
137 if (atag
->hdr
.tag
== ATAG_CMDLINE
) {
138 /* Append the ATAGS command line to the device tree
140 * NB: This means that if the same parameter is set in
141 * the device tree and in the tags, the one from the
142 * tags will be chosen.
144 if (do_extend_cmdline
)
145 merge_fdt_bootargs(fdt
,
146 atag
->u
.cmdline
.cmdline
);
148 setprop_string(fdt
, "/chosen", "bootargs",
149 atag
->u
.cmdline
.cmdline
);
150 } else if (atag
->hdr
.tag
== ATAG_MEM
) {
151 if (memcount
>= sizeof(mem_reg_property
)/4)
153 if (!atag
->u
.mem
.size
)
155 memsize
= get_cell_size(fdt
);
158 /* if memsize is 2, that means that
159 * each data needs 2 cells of 32 bits,
160 * so the data are 64 bits */
161 uint64_t *mem_reg_prop64
=
162 (uint64_t *)mem_reg_property
;
163 mem_reg_prop64
[memcount
++] =
164 cpu_to_fdt64(atag
->u
.mem
.start
);
165 mem_reg_prop64
[memcount
++] =
166 cpu_to_fdt64(atag
->u
.mem
.size
);
168 mem_reg_property
[memcount
++] =
169 cpu_to_fdt32(atag
->u
.mem
.start
);
170 mem_reg_property
[memcount
++] =
171 cpu_to_fdt32(atag
->u
.mem
.size
);
174 } else if (atag
->hdr
.tag
== ATAG_INITRD2
) {
175 uint32_t initrd_start
, initrd_size
;
176 initrd_start
= atag
->u
.initrd
.start
;
177 initrd_size
= atag
->u
.initrd
.size
;
178 setprop_cell(fdt
, "/chosen", "linux,initrd-start",
180 setprop_cell(fdt
, "/chosen", "linux,initrd-end",
181 initrd_start
+ initrd_size
);
186 setprop(fdt
, "/memory", "reg", mem_reg_property
,
187 4 * memcount
* memsize
);
190 return fdt_pack(fdt
);