1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3 * Early Device Tree with bootinfo hooks
4 *
5 * Copyright (C) 2012-2014 Citrix Systems, Inc.
6 */
7
8 #include <xen/bootinfo.h>
9 #include <xen/device_tree.h>
10 #include <xen/efi.h>
11 #include <xen/init.h>
12 #include <xen/kernel.h>
13 #include <xen/lib.h>
14 #include <xen/libfdt/libfdt-xen.h>
15 #include <xen/sort.h>
16 #include <xen/unaligned.h>
17 #include <xen/static-shmem.h>
18 #include <xsm/xsm.h>
19 #include <asm/setup.h>
20
build_assertions(void)21 static void __init __maybe_unused build_assertions(void)
22 {
23 /*
24 * Check that no padding is between struct membanks "bank" flexible array
25 * member and struct meminfo "bank" member
26 */
27 BUILD_BUG_ON((offsetof(struct membanks, bank) !=
28 offsetof(struct meminfo, bank)));
29 /* Ensure "struct membanks" and "struct membank" are equally aligned */
30 BUILD_BUG_ON(alignof(struct membanks) != alignof(struct membank));
31 }
32
device_tree_node_is_available(const void * fdt,int node)33 static bool __init device_tree_node_is_available(const void *fdt, int node)
34 {
35 const char *status;
36 int len;
37
38 status = fdt_getprop(fdt, node, "status", &len);
39 if ( !status )
40 return true;
41
42 if ( len > 0 )
43 {
44 if ( !strcmp(status, "ok") || !strcmp(status, "okay") )
45 return true;
46 }
47
48 return false;
49 }
50
device_tree_node_matches(const void * fdt,int node,const char * match)51 static bool __init device_tree_node_matches(const void *fdt, int node,
52 const char *match)
53 {
54 const char *name;
55 size_t match_len;
56
57 name = fdt_get_name(fdt, node, NULL);
58 match_len = strlen(match);
59
60 /* Match both "match" and "match@..." patterns but not
61 "match-foo". */
62 return strncmp(name, match, match_len) == 0
63 && (name[match_len] == '@' || name[match_len] == '\0');
64 }
65
device_tree_node_compatible(const void * fdt,int node,const char * match)66 static bool __init device_tree_node_compatible(const void *fdt, int node,
67 const char *match)
68 {
69 int len, l;
70 const void *prop;
71
72 prop = fdt_getprop(fdt, node, "compatible", &len);
73 if ( prop == NULL )
74 return false;
75
76 while ( len > 0 ) {
77 if ( !dt_compat_cmp(prop, match) )
78 return true;
79 l = strlen(prop) + 1;
80 prop += l;
81 len -= l;
82 }
83
84 return false;
85 }
86
87 /*
88 * Check if a node is a proper /memory node according to Devicetree
89 * Specification v0.4, chapter 3.4.
90 */
device_tree_is_memory_node(const void * fdt,int node,int depth)91 static bool __init device_tree_is_memory_node(const void *fdt, int node,
92 int depth)
93 {
94 const char *type;
95 int len;
96
97 if ( depth != 1 )
98 return false;
99
100 if ( !device_tree_node_matches(fdt, node, "memory") )
101 return false;
102
103 type = fdt_getprop(fdt, node, "device_type", &len);
104 if ( !type )
105 return false;
106
107 if ( (len <= strlen("memory")) || strcmp(type, "memory") )
108 return false;
109
110 return true;
111 }
112
device_tree_get_meminfo(const void * fdt,int node,const char * prop_name,u32 address_cells,u32 size_cells,struct membanks * mem,enum membank_type type)113 static int __init device_tree_get_meminfo(const void *fdt, int node,
114 const char *prop_name,
115 u32 address_cells, u32 size_cells,
116 struct membanks *mem,
117 enum membank_type type)
118 {
119 const struct fdt_property *prop;
120 unsigned int i, banks;
121 const __be32 *cell;
122 u32 reg_cells = address_cells + size_cells;
123 paddr_t start, size;
124
125 if ( !device_tree_node_is_available(fdt, node) )
126 return 0;
127
128 if ( address_cells < 1 || size_cells < 1 )
129 {
130 printk("fdt: property `%s': invalid #address-cells or #size-cells",
131 prop_name);
132 return -EINVAL;
133 }
134
135 prop = fdt_get_property(fdt, node, prop_name, NULL);
136 if ( !prop )
137 return -ENOENT;
138
139 cell = (const __be32 *)prop->data;
140 banks = fdt32_to_cpu(prop->len) / (reg_cells * sizeof (u32));
141
142 for ( i = 0; i < banks && mem->nr_banks < mem->max_banks; i++ )
143 {
144 device_tree_get_reg(&cell, address_cells, size_cells, &start, &size);
145 /*
146 * Some valid device trees, such as those generated by OpenPOWER
147 * skiboot firmware, expose all reserved memory regions in the
148 * FDT memory reservation block AND in the reserved-memory node which
149 * has already been parsed. Thus, any matching overlaps in the
150 * reserved_mem banks should be ignored.
151 */
152 if ( mem == bootinfo_get_reserved_mem() &&
153 check_reserved_regions_overlap(start, size, true) )
154 return -EINVAL;
155 /* Some DT may describe empty bank, ignore them */
156 if ( !size )
157 continue;
158 mem->bank[mem->nr_banks].start = start;
159 mem->bank[mem->nr_banks].size = size;
160 mem->bank[mem->nr_banks].type = type;
161 mem->nr_banks++;
162 }
163
164 if ( i < banks )
165 {
166 printk("Warning: Max number of supported memory regions reached.\n");
167 return -ENOSPC;
168 }
169
170 return 0;
171 }
172
process_memory_node(const void * fdt,int node,const char * name,int depth,u32 address_cells,u32 size_cells,struct membanks * mem)173 static int __init process_memory_node(const void *fdt, int node,
174 const char *name, int depth,
175 u32 address_cells, u32 size_cells,
176 struct membanks *mem)
177 {
178 return device_tree_get_meminfo(fdt, node, "reg", address_cells, size_cells,
179 mem, MEMBANK_DEFAULT);
180 }
181
process_reserved_memory_node(const void * fdt,int node,const char * name,int depth,u32 address_cells,u32 size_cells,void * data)182 static int __init process_reserved_memory_node(const void *fdt, int node,
183 const char *name, int depth,
184 u32 address_cells,
185 u32 size_cells,
186 void *data)
187 {
188 int rc = process_memory_node(fdt, node, name, depth, address_cells,
189 size_cells, data);
190
191 if ( rc == -ENOSPC )
192 panic("Max number of supported reserved-memory regions reached.\n");
193 else if ( rc != -ENOENT )
194 return rc;
195 return 0;
196 }
197
process_reserved_memory(const void * fdt,int node,const char * name,int depth,u32 address_cells,u32 size_cells)198 static int __init process_reserved_memory(const void *fdt, int node,
199 const char *name, int depth,
200 u32 address_cells, u32 size_cells)
201 {
202 return device_tree_for_each_node(fdt, node,
203 process_reserved_memory_node,
204 bootinfo_get_reserved_mem());
205 }
206
process_multiboot_node(const void * fdt,int node,const char * name,u32 address_cells,u32 size_cells)207 static void __init process_multiboot_node(const void *fdt, int node,
208 const char *name,
209 u32 address_cells, u32 size_cells)
210 {
211 static int __initdata kind_guess = 0;
212 const struct fdt_property *prop;
213 const __be32 *cell;
214 boot_module_kind kind;
215 paddr_t start, size;
216 int len;
217 /* sizeof("/chosen/") + DT_MAX_NAME + '/' + DT_MAX_NAME + '/0' => 92 */
218 char path[92];
219 int parent_node, ret;
220 bool domU;
221
222 parent_node = fdt_parent_offset(fdt, node);
223 ASSERT(parent_node >= 0);
224
225 /* Check that the node is under "/chosen" (first 7 chars of path) */
226 ret = fdt_get_path(fdt, node, path, sizeof (path));
227 if ( ret != 0 || strncmp(path, "/chosen", 7) )
228 return;
229
230 prop = fdt_get_property(fdt, node, "reg", &len);
231 if ( !prop )
232 panic("node %s missing `reg' property\n", name);
233
234 if ( len < dt_cells_to_size(address_cells + size_cells) )
235 panic("fdt: node `%s': `reg` property length is too short\n",
236 name);
237
238 cell = (const __be32 *)prop->data;
239 device_tree_get_reg(&cell, address_cells, size_cells, &start, &size);
240 kind = fdt_node_to_kind(fdt, node);
241
242 /**
243 * Guess the kind of these first two unknowns respectively:
244 * (1) The first unknown must be kernel.
245 * (2) Detect the XSM Magic from the 2nd unknown:
246 * a. If it's XSM, set the kind as XSM, and that also means we
247 * won't load ramdisk;
248 * b. if it's not XSM, set the kind as ramdisk.
249 * So if user want to load ramdisk, it must be the 2nd unknown.
250 * We also detect the XSM Magic for the following unknowns,
251 * then set its kind according to the return value of has_xsm_magic.
252 */
253 if ( kind == BOOTMOD_UNKNOWN )
254 {
255 switch ( kind_guess++ )
256 {
257 case 0: kind = BOOTMOD_KERNEL; break;
258 case 1: kind = BOOTMOD_RAMDISK; break;
259 default: break;
260 }
261 if ( kind_guess > 1 && has_xsm_magic(start) )
262 kind = BOOTMOD_XSM_POLICY;
263 }
264
265 domU = fdt_node_check_compatible(fdt, parent_node, "xen,domain") == 0;
266 add_boot_module(kind, start, size, domU);
267
268 prop = fdt_get_property(fdt, node, "bootargs", &len);
269 if ( !prop )
270 return;
271 add_boot_cmdline(fdt_get_name(fdt, parent_node, &len), prop->data,
272 kind, start, domU);
273 }
274
process_chosen_node(const void * fdt,int node,const char * name,u32 address_cells,u32 size_cells)275 static int __init process_chosen_node(const void *fdt, int node,
276 const char *name,
277 u32 address_cells, u32 size_cells)
278 {
279 const struct fdt_property *prop;
280 paddr_t start, end;
281 int len;
282
283 if ( fdt_get_property(fdt, node, "xen,static-heap", NULL) )
284 {
285 int rc;
286
287 printk("Checking for static heap in /chosen\n");
288
289 rc = device_tree_get_meminfo(fdt, node, "xen,static-heap",
290 address_cells, size_cells,
291 bootinfo_get_reserved_mem(),
292 MEMBANK_STATIC_HEAP);
293 if ( rc )
294 return rc;
295
296 using_static_heap = true;
297 }
298
299 printk("Checking for initrd in /chosen\n");
300
301 prop = fdt_get_property(fdt, node, "linux,initrd-start", &len);
302 if ( !prop )
303 /* No initrd present. */
304 return 0;
305 if ( len != sizeof(u32) && len != sizeof(u64) )
306 {
307 printk("linux,initrd-start property has invalid length %d\n", len);
308 return -EINVAL;
309 }
310 start = dt_read_paddr((const void *)&prop->data, dt_size_to_cells(len));
311
312 prop = fdt_get_property(fdt, node, "linux,initrd-end", &len);
313 if ( !prop )
314 {
315 printk("linux,initrd-end not present but -start was\n");
316 return -EINVAL;
317 }
318 if ( len != sizeof(u32) && len != sizeof(u64) )
319 {
320 printk("linux,initrd-end property has invalid length %d\n", len);
321 return -EINVAL;
322 }
323 end = dt_read_paddr((const void *)&prop->data, dt_size_to_cells(len));
324
325 if ( start >= end )
326 {
327 printk("linux,initrd limits invalid: %"PRIpaddr" >= %"PRIpaddr"\n",
328 start, end);
329 return -EINVAL;
330 }
331
332 printk("Initrd %"PRIpaddr"-%"PRIpaddr"\n", start, end - 1);
333
334 add_boot_module(BOOTMOD_RAMDISK, start, end-start, false);
335
336 return 0;
337 }
338
process_domain_node(const void * fdt,int node,const char * name,u32 address_cells,u32 size_cells)339 static int __init process_domain_node(const void *fdt, int node,
340 const char *name,
341 u32 address_cells, u32 size_cells)
342 {
343 const struct fdt_property *prop;
344
345 printk("Checking for \"xen,static-mem\" in domain node\n");
346
347 prop = fdt_get_property(fdt, node, "xen,static-mem", NULL);
348 if ( !prop )
349 /* No "xen,static-mem" present. */
350 return 0;
351
352 return device_tree_get_meminfo(fdt, node, "xen,static-mem", address_cells,
353 size_cells, bootinfo_get_reserved_mem(),
354 MEMBANK_STATIC_DOMAIN);
355 }
356
357 #ifndef CONFIG_STATIC_SHM
process_shm_node(const void * fdt,int node,uint32_t address_cells,uint32_t size_cells)358 static inline int process_shm_node(const void *fdt, int node,
359 uint32_t address_cells, uint32_t size_cells)
360 {
361 printk("CONFIG_STATIC_SHM must be enabled for parsing static shared"
362 " memory nodes\n");
363 return -EINVAL;
364 }
365 #endif
366
early_scan_node(const void * fdt,int node,const char * name,int depth,u32 address_cells,u32 size_cells,void * data)367 static int __init early_scan_node(const void *fdt,
368 int node, const char *name, int depth,
369 u32 address_cells, u32 size_cells,
370 void *data)
371 {
372 int rc = 0;
373
374 /*
375 * If Xen has been booted via UEFI, the memory banks are
376 * populated. So we should skip the parsing.
377 */
378 if ( !efi_enabled(EFI_BOOT) &&
379 device_tree_is_memory_node(fdt, node, depth) )
380 rc = process_memory_node(fdt, node, name, depth,
381 address_cells, size_cells, bootinfo_get_mem());
382 else if ( depth == 1 && !dt_node_cmp(name, "reserved-memory") )
383 rc = process_reserved_memory(fdt, node, name, depth,
384 address_cells, size_cells);
385 else if ( depth <= 3 && (device_tree_node_compatible(fdt, node, "xen,multiboot-module" ) ||
386 device_tree_node_compatible(fdt, node, "multiboot,module" )))
387 process_multiboot_node(fdt, node, name, address_cells, size_cells);
388 else if ( depth == 1 && device_tree_node_matches(fdt, node, "chosen") )
389 rc = process_chosen_node(fdt, node, name, address_cells, size_cells);
390 else if ( depth == 2 && device_tree_node_compatible(fdt, node, "xen,domain") )
391 rc = process_domain_node(fdt, node, name, address_cells, size_cells);
392 else if ( depth <= 3 && device_tree_node_compatible(fdt, node, "xen,domain-shared-memory-v1") )
393 rc = process_shm_node(fdt, node, address_cells, size_cells);
394
395 if ( rc < 0 )
396 printk("fdt: node `%s': parsing failed\n", name);
397 return rc;
398 }
399
early_print_info(void)400 static void __init early_print_info(void)
401 {
402 const struct membanks *mi = bootinfo_get_mem();
403 const struct membanks *mem_resv = bootinfo_get_reserved_mem();
404 struct boot_modules *mods = &bootinfo.modules;
405 struct bootcmdlines *cmds = &bootinfo.cmdlines;
406 unsigned int i;
407
408 for ( i = 0; i < mi->nr_banks; i++ )
409 printk("RAM: %"PRIpaddr" - %"PRIpaddr"\n",
410 mi->bank[i].start,
411 mi->bank[i].start + mi->bank[i].size - 1);
412 printk("\n");
413 for ( i = 0 ; i < mods->nr_mods; i++ )
414 printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %-12s\n",
415 i,
416 mods->module[i].start,
417 mods->module[i].start + mods->module[i].size - 1,
418 boot_module_kind_as_string(mods->module[i].kind));
419
420 for ( i = 0; i < mem_resv->nr_banks; i++ )
421 {
422 printk(" RESVD[%u]: %"PRIpaddr" - %"PRIpaddr"\n", i,
423 mem_resv->bank[i].start,
424 mem_resv->bank[i].start + mem_resv->bank[i].size - 1);
425 }
426 #ifdef CONFIG_STATIC_SHM
427 early_print_info_shmem();
428 #endif
429 printk("\n");
430 for ( i = 0 ; i < cmds->nr_mods; i++ )
431 printk("CMDLINE[%"PRIpaddr"]:%s %s\n", cmds->cmdline[i].start,
432 cmds->cmdline[i].dt_name,
433 &cmds->cmdline[i].cmdline[0]);
434 printk("\n");
435 }
436
437 /* This function assumes that memory regions are not overlapped */
cmp_memory_node(const void * key,const void * elem)438 static int __init cmp_memory_node(const void *key, const void *elem)
439 {
440 const struct membank *handler0 = key;
441 const struct membank *handler1 = elem;
442
443 if ( handler0->start < handler1->start )
444 return -1;
445
446 if ( handler0->start >= (handler1->start + handler1->size) )
447 return 1;
448
449 return 0;
450 }
451
swap_memory_node(void * _a,void * _b)452 static void __init swap_memory_node(void *_a, void *_b)
453 {
454 struct membank *a = _a, *b = _b;
455
456 SWAP(*a, *b);
457 }
458
459 /**
460 * boot_fdt_info - initialize bootinfo from a DTB
461 * @fdt: flattened device tree binary
462 *
463 * Returns the size of the DTB.
464 */
boot_fdt_info(const void * fdt,paddr_t paddr)465 size_t __init boot_fdt_info(const void *fdt, paddr_t paddr)
466 {
467 struct membanks *reserved_mem = bootinfo_get_reserved_mem();
468 struct membanks *mem = bootinfo_get_mem();
469 unsigned int i;
470 int nr_rsvd;
471 int ret;
472
473 ret = fdt_check_header(fdt);
474 if ( ret < 0 )
475 panic("No valid device tree\n");
476
477 add_boot_module(BOOTMOD_FDT, paddr, fdt_totalsize(fdt), false);
478
479 nr_rsvd = fdt_num_mem_rsv(fdt);
480 if ( nr_rsvd < 0 )
481 panic("Parsing FDT memory reserve map failed (%d)\n", nr_rsvd);
482
483 for ( i = 0; i < nr_rsvd; i++ )
484 {
485 struct membank *bank;
486 paddr_t s, sz;
487
488 if ( fdt_get_mem_rsv_paddr(device_tree_flattened, i, &s, &sz) < 0 )
489 continue;
490
491 if ( reserved_mem->nr_banks < reserved_mem->max_banks )
492 {
493 bank = &reserved_mem->bank[reserved_mem->nr_banks];
494 bank->start = s;
495 bank->size = sz;
496 bank->type = MEMBANK_FDT_RESVMEM;
497 reserved_mem->nr_banks++;
498 }
499 else
500 panic("Cannot allocate reserved memory bank\n");
501 }
502
503 ret = device_tree_for_each_node(fdt, 0, early_scan_node, NULL);
504 if ( ret )
505 panic("Early FDT parsing failed (%d)\n", ret);
506
507 /*
508 * On Arm64 setup_directmap_mappings() expects to be called with the lowest
509 * bank in memory first. There is no requirement that the DT will provide
510 * the banks sorted in ascending order. So sort them through.
511 */
512 sort(mem->bank, mem->nr_banks, sizeof(struct membank),
513 cmp_memory_node, swap_memory_node);
514
515 early_print_info();
516
517 return fdt_totalsize(fdt);
518 }
519
boot_fdt_cmdline(const void * fdt)520 const __init char *boot_fdt_cmdline(const void *fdt)
521 {
522 int node;
523 const struct fdt_property *prop;
524
525 node = fdt_path_offset(fdt, "/chosen");
526 if ( node < 0 )
527 return NULL;
528
529 prop = fdt_get_property(fdt, node, "xen,xen-bootargs", NULL);
530 if ( prop == NULL )
531 {
532 struct bootcmdline *dom0_cmdline =
533 boot_cmdline_find_by_kind(BOOTMOD_KERNEL);
534
535 if (fdt_get_property(fdt, node, "xen,dom0-bootargs", NULL) ||
536 ( dom0_cmdline && dom0_cmdline->cmdline[0] ) )
537 prop = fdt_get_property(fdt, node, "bootargs", NULL);
538 }
539 if ( prop == NULL )
540 return NULL;
541
542 return prop->data;
543 }
544
545 /*
546 * Wrapper to convert physical address from paddr_t to uint64_t and
547 * invoke fdt_begin_node(). This is required as the physical address
548 * provided as part of node name should not contain any leading
549 * zeroes. Thus, one should use PRIx64 (instead of PRIpaddr) to append
550 * unit (which contains the physical address) with name to generate a
551 * node name.
552 */
domain_fdt_begin_node(void * fdt,const char * name,uint64_t unit)553 int __init domain_fdt_begin_node(void *fdt, const char *name, uint64_t unit)
554 {
555 /*
556 * The size of the buffer to hold the longest possible string (i.e.
557 * interrupt-controller@ + a 64-bit number + \0).
558 */
559 char buf[38];
560 int ret;
561
562 /* ePAPR 3.4 */
563 ret = snprintf(buf, sizeof(buf), "%s@%"PRIx64, name, unit);
564
565 if ( ret >= sizeof(buf) )
566 {
567 printk(XENLOG_ERR
568 "Insufficient buffer. Minimum size required is %d\n",
569 (ret + 1));
570
571 return -FDT_ERR_TRUNCATED;
572 }
573
574 return fdt_begin_node(fdt, buf);
575 }
576
577 /*
578 * Local variables:
579 * mode: C
580 * c-file-style: "BSD"
581 * c-basic-offset: 4
582 * indent-tabs-mode: nil
583 * End:
584 */
585