Annotation of src/sys/arch/evbarm/fdt/fdt_machdep.c, Revision 1.65.2.2
1.65.2.2! ad 1: /* $NetBSD: fdt_machdep.c,v 1.65.2.1 2020/01/25 22:38:39 ad Exp $ */
1.1 jmcneill 2:
3: /*-
4: * Copyright (c) 2015-2017 Jared McNeill <jmcneill@invisible.ca>
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23: * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26: * SUCH DAMAGE.
27: */
28:
29: #include <sys/cdefs.h>
1.65.2.2! ad 30: __KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.65.2.1 2020/01/25 22:38:39 ad Exp $");
1.1 jmcneill 31:
32: #include "opt_machdep.h"
1.21 ryo 33: #include "opt_bootconfig.h"
1.1 jmcneill 34: #include "opt_ddb.h"
35: #include "opt_md.h"
36: #include "opt_arm_debug.h"
37: #include "opt_multiprocessor.h"
38: #include "opt_cpuoptions.h"
1.46 jmcneill 39: #include "opt_efi.h"
1.1 jmcneill 40:
1.14 jmcneill 41: #include "ukbd.h"
1.39 bouyer 42: #include "wsdisplay.h"
1.14 jmcneill 43:
1.1 jmcneill 44: #include <sys/param.h>
45: #include <sys/systm.h>
46: #include <sys/bus.h>
47: #include <sys/atomic.h>
48: #include <sys/cpu.h>
49: #include <sys/device.h>
50: #include <sys/exec.h>
51: #include <sys/kernel.h>
52: #include <sys/kmem.h>
53: #include <sys/ksyms.h>
54: #include <sys/msgbuf.h>
55: #include <sys/proc.h>
56: #include <sys/reboot.h>
57: #include <sys/termios.h>
1.34 jmcneill 58: #include <sys/bootblock.h>
59: #include <sys/disklabel.h>
60: #include <sys/vnode.h>
61: #include <sys/kauth.h>
62: #include <sys/fcntl.h>
1.53 jmcneill 63: #include <sys/uuid.h>
64: #include <sys/disk.h>
1.34 jmcneill 65: #include <sys/md5.h>
1.55 jmcneill 66: #include <sys/pserialize.h>
1.65 riastrad 67: #include <sys/rnd.h>
1.55 jmcneill 68:
69: #include <net/if.h>
70: #include <net/if_dl.h>
1.1 jmcneill 71:
1.23 ryo 72: #include <dev/cons.h>
1.1 jmcneill 73: #include <uvm/uvm_extern.h>
74:
75: #include <sys/conf.h>
76:
77: #include <machine/db_machdep.h>
78: #include <ddb/db_sym.h>
79: #include <ddb/db_extern.h>
80:
81: #include <machine/bootconfig.h>
82: #include <arm/armreg.h>
83:
1.21 ryo 84: #include <arm/cpufunc.h>
1.1 jmcneill 85:
86: #include <evbarm/include/autoconf.h>
1.30 skrll 87: #include <evbarm/fdt/machdep.h>
1.1 jmcneill 88: #include <evbarm/fdt/platform.h>
1.49 jmcneill 89: #include <evbarm/fdt/fdt_memory.h>
1.1 jmcneill 90:
91: #include <arm/fdt/arm_fdtvar.h>
92:
1.46 jmcneill 93: #ifdef EFI_RUNTIME
94: #include <arm/arm/efi_runtime.h>
95: #endif
96:
1.14 jmcneill 97: #if NUKBD > 0
98: #include <dev/usb/ukbdvar.h>
99: #endif
1.39 bouyer 100: #if NWSDISPLAY > 0
101: #include <dev/wscons/wsdisplayvar.h>
102: #endif
1.14 jmcneill 103:
1.8 jmcneill 104: #ifdef MEMORY_DISK_DYNAMIC
105: #include <dev/md.h>
106: #endif
107:
1.1 jmcneill 108: #ifndef FDT_MAX_BOOT_STRING
109: #define FDT_MAX_BOOT_STRING 1024
110: #endif
111:
112: BootConfig bootconfig;
113: char bootargs[FDT_MAX_BOOT_STRING] = "";
114: char *boot_args = NULL;
1.26 christos 115:
116: /* filled in before cleaning bss. keep in .data */
1.27 christos 117: u_long uboot_args[4] __attribute__((__section__(".data")));
1.28 skrll 118: const uint8_t *fdt_addr_r __attribute__((__section__(".data")));
1.1 jmcneill 119:
1.8 jmcneill 120: static uint64_t initrd_start, initrd_end;
1.65 riastrad 121: static uint64_t rndseed_start, rndseed_end;
1.8 jmcneill 122:
1.1 jmcneill 123: #include <libfdt.h>
124: #include <dev/fdt/fdtvar.h>
1.40 jmcneill 125: #define FDT_BUF_SIZE (512*1024)
1.1 jmcneill 126: static uint8_t fdt_data[FDT_BUF_SIZE];
127:
128: extern char KERNEL_BASE_phys[];
129: #define KERNEL_BASE_PHYS ((paddr_t)KERNEL_BASE_phys)
130:
1.5 jmcneill 131: static void fdt_update_stdout_path(void);
1.1 jmcneill 132: static void fdt_device_register(device_t, void *);
1.39 bouyer 133: static void fdt_device_register_post_config(device_t, void *);
1.34 jmcneill 134: static void fdt_cpu_rootconf(void);
1.1 jmcneill 135: static void fdt_reset(void);
136: static void fdt_powerdown(void);
137:
138: static void
1.23 ryo 139: earlyconsputc(dev_t dev, int c)
1.1 jmcneill 140: {
1.48 skrll 141: uartputc(c);
1.1 jmcneill 142: }
143:
1.23 ryo 144: static int
145: earlyconsgetc(dev_t dev)
1.1 jmcneill 146: {
1.54 skrll 147: return 0;
1.23 ryo 148: }
1.1 jmcneill 149:
1.54 skrll 150: static struct consdev earlycons = {
151: .cn_putc = earlyconsputc,
152: .cn_getc = earlyconsgetc,
153: .cn_pollc = nullcnpollc,
154: };
155:
1.23 ryo 156: #ifdef VERBOSE_INIT_ARM
1.29 skrll 157: #define VPRINTF(...) printf(__VA_ARGS__)
1.1 jmcneill 158: #else
1.43 skrll 159: #define VPRINTF(...) __nothing
1.1 jmcneill 160: #endif
161:
1.7 jmcneill 162: /*
1.61 jmcneill 163: * Get all of physical memory, including holes.
1.7 jmcneill 164: */
165: static void
1.21 ryo 166: fdt_get_memory(uint64_t *pstart, uint64_t *pend)
1.7 jmcneill 167: {
168: const int memory = OF_finddevice("/memory");
169: uint64_t cur_addr, cur_size;
170: int index;
171:
172: /* Assume the first entry is the start of memory */
1.21 ryo 173: if (fdtbus_get_reg64(memory, 0, &cur_addr, &cur_size) != 0)
1.7 jmcneill 174: panic("Cannot determine memory size");
175:
1.21 ryo 176: *pstart = cur_addr;
177: *pend = cur_addr + cur_size;
178:
1.29 skrll 179: VPRINTF("FDT /memory [%d] @ 0x%" PRIx64 " size 0x%" PRIx64 "\n",
1.21 ryo 180: 0, *pstart, *pend - *pstart);
1.7 jmcneill 181:
182: for (index = 1;
183: fdtbus_get_reg64(memory, index, &cur_addr, &cur_size) == 0;
184: index++) {
1.29 skrll 185: VPRINTF("FDT /memory [%d] @ 0x%" PRIx64 " size 0x%" PRIx64 "\n",
1.7 jmcneill 186: index, cur_addr, cur_size);
1.21 ryo 187:
188: if (cur_addr + cur_size > *pend)
189: *pend = cur_addr + cur_size;
1.7 jmcneill 190: }
191: }
192:
1.16 skrll 193: void
1.8 jmcneill 194: fdt_add_reserved_memory_range(uint64_t addr, uint64_t size)
195: {
1.49 jmcneill 196: fdt_memory_remove_range(addr, size);
1.8 jmcneill 197: }
198:
199: /*
1.11 jmcneill 200: * Exclude memory ranges from memory config from the device tree
1.8 jmcneill 201: */
202: static void
1.33 jmcneill 203: fdt_add_reserved_memory(uint64_t min_addr, uint64_t max_addr)
1.8 jmcneill 204: {
1.44 skrll 205: uint64_t lstart = 0, lend = 0;
1.8 jmcneill 206: uint64_t addr, size;
1.11 jmcneill 207: int index, error;
1.8 jmcneill 208:
1.11 jmcneill 209: const int num = fdt_num_mem_rsv(fdtbus_get_data());
210: for (index = 0; index <= num; index++) {
211: error = fdt_get_mem_rsv(fdtbus_get_data(), index,
212: &addr, &size);
1.44 skrll 213: if (error != 0)
214: continue;
215: if (lstart <= addr && addr <= lend) {
216: size -= (lend - addr);
217: addr = lend;
218: }
219: if (size == 0)
1.11 jmcneill 220: continue;
1.33 jmcneill 221: if (addr + size <= min_addr)
222: continue;
1.8 jmcneill 223: if (addr >= max_addr)
224: continue;
1.33 jmcneill 225: if (addr < min_addr) {
226: size -= (min_addr - addr);
227: addr = min_addr;
228: }
1.8 jmcneill 229: if (addr + size > max_addr)
230: size = max_addr - addr;
231: fdt_add_reserved_memory_range(addr, size);
1.44 skrll 232: lstart = addr;
233: lend = addr + size;
1.8 jmcneill 234: }
235: }
236:
1.49 jmcneill 237: static void
238: fdt_add_dram_blocks(const struct fdt_memory *m, void *arg)
239: {
240: BootConfig *bc = arg;
241:
1.52 jmcneill 242: VPRINTF(" %" PRIx64 " - %" PRIx64 "\n", m->start, m->end - 1);
1.49 jmcneill 243: bc->dram[bc->dramblocks].address = m->start;
244: bc->dram[bc->dramblocks].pages =
245: (m->end - m->start) / PAGE_SIZE;
246: bc->dramblocks++;
247: }
248:
249: #define MAX_PHYSMEM 64
250: static int nfdt_physmem = 0;
251: static struct boot_physmem fdt_physmem[MAX_PHYSMEM];
252:
253: static void
254: fdt_add_boot_physmem(const struct fdt_memory *m, void *arg)
255: {
1.62 skrll 256: const paddr_t saddr = round_page(m->start);
257: const paddr_t eaddr = trunc_page(m->end);
258:
259: VPRINTF(" %" PRIx64 " - %" PRIx64, m->start, m->end - 1);
260: if (saddr >= eaddr) {
261: VPRINTF(" skipped\n");
262: return;
263: }
264: VPRINTF("\n");
265:
1.49 jmcneill 266: struct boot_physmem *bp = &fdt_physmem[nfdt_physmem++];
267:
268: KASSERT(nfdt_physmem <= MAX_PHYSMEM);
269:
1.62 skrll 270: bp->bp_start = atop(saddr);
271: bp->bp_pages = atop(eaddr) - bp->bp_start;
1.49 jmcneill 272: bp->bp_freelist = VM_FREELIST_DEFAULT;
273:
274: #ifdef PMAP_NEED_ALLOC_POOLPAGE
275: const uint64_t memory_size = *(uint64_t *)arg;
276: if (atop(memory_size) > bp->bp_pages) {
277: arm_poolpage_vmfreelist = VM_FREELIST_DIRECTMAP;
278: bp->bp_freelist = VM_FREELIST_DIRECTMAP;
279: }
280: #endif
281: }
282:
1.8 jmcneill 283: /*
284: * Define usable memory regions.
285: */
286: static void
1.21 ryo 287: fdt_build_bootconfig(uint64_t mem_start, uint64_t mem_end)
1.8 jmcneill 288: {
289: const int memory = OF_finddevice("/memory");
290: BootConfig *bc = &bootconfig;
291: uint64_t addr, size;
1.49 jmcneill 292: int index;
1.8 jmcneill 293:
294: for (index = 0;
295: fdtbus_get_reg64(memory, index, &addr, &size) == 0;
296: index++) {
1.21 ryo 297: if (addr >= mem_end || size == 0)
1.8 jmcneill 298: continue;
1.21 ryo 299: if (addr + size > mem_end)
300: size = mem_end - addr;
1.8 jmcneill 301:
1.49 jmcneill 302: fdt_memory_add_range(addr, size);
1.8 jmcneill 303: }
304:
1.33 jmcneill 305: fdt_add_reserved_memory(mem_start, mem_end);
1.8 jmcneill 306:
307: const uint64_t initrd_size = initrd_end - initrd_start;
308: if (initrd_size > 0)
1.49 jmcneill 309: fdt_memory_remove_range(initrd_start, initrd_size);
1.8 jmcneill 310:
1.65 riastrad 311: const uint64_t rndseed_size = rndseed_end - rndseed_start;
312: if (rndseed_size > 0)
313: fdt_memory_remove_range(rndseed_start, rndseed_size);
314:
1.47 jmcneill 315: const int framebuffer = OF_finddevice("/chosen/framebuffer");
316: if (framebuffer >= 0) {
317: for (index = 0;
318: fdtbus_get_reg64(framebuffer, index, &addr, &size) == 0;
319: index++) {
320: fdt_add_reserved_memory_range(addr, size);
321: }
322: }
323:
1.29 skrll 324: VPRINTF("Usable memory:\n");
1.8 jmcneill 325: bc->dramblocks = 0;
1.49 jmcneill 326: fdt_memory_foreach(fdt_add_dram_blocks, bc);
1.8 jmcneill 327: }
328:
329: static void
330: fdt_probe_initrd(uint64_t *pstart, uint64_t *pend)
331: {
332: *pstart = *pend = 0;
333:
334: #ifdef MEMORY_DISK_DYNAMIC
335: const int chosen = OF_finddevice("/chosen");
336: if (chosen < 0)
337: return;
338:
339: int len;
340: const void *start_data = fdtbus_get_prop(chosen,
341: "linux,initrd-start", &len);
342: const void *end_data = fdtbus_get_prop(chosen,
343: "linux,initrd-end", NULL);
344: if (start_data == NULL || end_data == NULL)
345: return;
346:
347: switch (len) {
348: case 4:
349: *pstart = be32dec(start_data);
350: *pend = be32dec(end_data);
351: break;
352: case 8:
353: *pstart = be64dec(start_data);
354: *pend = be64dec(end_data);
355: break;
356: default:
357: printf("Unsupported len %d for /chosen/initrd-start\n", len);
358: return;
359: }
360: #endif
361: }
362:
363: static void
364: fdt_setup_initrd(void)
365: {
366: #ifdef MEMORY_DISK_DYNAMIC
367: const uint64_t initrd_size = initrd_end - initrd_start;
368: paddr_t startpa = trunc_page(initrd_start);
369: paddr_t endpa = round_page(initrd_end);
370: paddr_t pa;
371: vaddr_t va;
372: void *md_start;
373:
374: if (initrd_size == 0)
375: return;
376:
377: va = uvm_km_alloc(kernel_map, initrd_size, 0,
378: UVM_KMF_VAONLY | UVM_KMF_NOWAIT);
379: if (va == 0) {
380: printf("Failed to allocate VA for initrd\n");
381: return;
382: }
383:
384: md_start = (void *)va;
385:
386: for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE)
387: pmap_kenter_pa(va, pa, VM_PROT_READ|VM_PROT_WRITE, 0);
388: pmap_update(pmap_kernel());
389:
390: md_root_setconf(md_start, initrd_size);
391: #endif
392: }
393:
1.65 riastrad 394: static void
395: fdt_probe_rndseed(uint64_t *pstart, uint64_t *pend)
396: {
397: int chosen, len;
398: const void *start_data, *end_data;
399:
400: *pstart = *pend = 0;
401: chosen = OF_finddevice("/chosen");
402: if (chosen < 0)
403: return;
404:
405: start_data = fdtbus_get_prop(chosen, "netbsd,rndseed-start", &len);
406: end_data = fdtbus_get_prop(chosen, "netbsd,rndseed-end", NULL);
407: if (start_data == NULL || end_data == NULL)
408: return;
409:
410: switch (len) {
411: case 4:
412: *pstart = be32dec(start_data);
413: *pend = be32dec(end_data);
414: break;
415: case 8:
416: *pstart = be64dec(start_data);
417: *pend = be64dec(end_data);
418: break;
419: default:
420: printf("Unsupported len %d for /chosen/rndseed-start\n", len);
421: return;
422: }
423: }
424:
425: static void
426: fdt_setup_rndseed(void)
427: {
428: const uint64_t rndseed_size = rndseed_end - rndseed_start;
429: const paddr_t startpa = trunc_page(rndseed_start);
430: const paddr_t endpa = round_page(rndseed_end);
431: paddr_t pa;
432: vaddr_t va;
433: void *rndseed;
434:
435: if (rndseed_size == 0)
436: return;
437:
438: va = uvm_km_alloc(kernel_map, endpa - startpa, 0,
439: UVM_KMF_VAONLY | UVM_KMF_NOWAIT);
440: if (va == 0) {
441: printf("Failed to allocate VA for rndseed\n");
442: return;
443: }
444: rndseed = (void *)va;
445:
446: for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE)
447: pmap_kenter_pa(va, pa, VM_PROT_READ|VM_PROT_WRITE, 0);
448: pmap_update(pmap_kernel());
449:
450: rnd_seed(rndseed, rndseed_size);
451: }
452:
1.46 jmcneill 453: #ifdef EFI_RUNTIME
454: static void
1.51 jmcneill 455: fdt_map_efi_runtime(const char *prop, enum arm_efirt_mem_type type)
1.46 jmcneill 456: {
457: int len;
458:
459: const int chosen_off = fdt_path_offset(fdt_data, "/chosen");
460: if (chosen_off < 0)
461: return;
462:
463: const uint64_t *map = fdt_getprop(fdt_data, chosen_off, prop, &len);
464: if (map == NULL)
465: return;
466:
467: while (len >= 24) {
468: const paddr_t pa = be64toh(map[0]);
469: const vaddr_t va = be64toh(map[1]);
470: const uint64_t sz = be64toh(map[2]);
1.51 jmcneill 471: VPRINTF("%s: %s %lx-%lx (%lx-%lx)\n", __func__, prop, pa, pa+sz-1, va, va+sz-1);
472: arm_efirt_md_map_range(va, pa, sz, type);
1.46 jmcneill 473: map += 3;
474: len -= 24;
475: }
476: }
477: #endif
478:
1.64 skrll 479: vaddr_t
1.1 jmcneill 480: initarm(void *arg)
481: {
482: const struct arm_platform *plat;
1.21 ryo 483: uint64_t memory_start, memory_end;
1.1 jmcneill 484:
1.23 ryo 485: /* set temporally to work printf()/panic() even before consinit() */
486: cn_tab = &earlycons;
487:
1.1 jmcneill 488: /* Load FDT */
489: int error = fdt_check_header(fdt_addr_r);
490: if (error == 0) {
1.41 jmcneill 491: /* If the DTB is too big, try to pack it in place first. */
492: if (fdt_totalsize(fdt_addr_r) > sizeof(fdt_data))
493: (void)fdt_pack(__UNCONST(fdt_addr_r));
1.38 jmcneill 494: error = fdt_open_into(fdt_addr_r, fdt_data, sizeof(fdt_data));
1.1 jmcneill 495: if (error != 0)
496: panic("fdt_move failed: %s", fdt_strerror(error));
1.65.2.2! ad 497: fdtbus_init(fdt_data);
1.1 jmcneill 498: } else {
499: panic("fdt_check_header failed: %s", fdt_strerror(error));
500: }
501:
502: /* Lookup platform specific backend */
503: plat = arm_fdt_platform();
504: if (plat == NULL)
505: panic("Kernel does not support this device");
506:
507: /* Early console may be available, announce ourselves. */
1.29 skrll 508: VPRINTF("FDT<%p>\n", fdt_addr_r);
1.1 jmcneill 509:
1.6 jmcneill 510: const int chosen = OF_finddevice("/chosen");
511: if (chosen >= 0)
512: OF_getprop(chosen, "bootargs", bootargs, sizeof(bootargs));
513: boot_args = bootargs;
514:
1.1 jmcneill 515: /* Heads up ... Setup the CPU / MMU / TLB functions. */
1.29 skrll 516: VPRINTF("cpufunc\n");
1.1 jmcneill 517: if (set_cpufuncs())
518: panic("cpu not recognized!");
519:
1.44 skrll 520: /*
521: * Memory is still identity/flat mapped this point so using ttbr for
522: * l1pt VA is fine
523: */
524:
525: VPRINTF("devmap\n");
526: extern char ARM_BOOTSTRAP_LxPT[];
527: pmap_devmap_bootstrap((vaddr_t)ARM_BOOTSTRAP_LxPT, plat->ap_devmap());
528:
1.29 skrll 529: VPRINTF("bootstrap\n");
1.32 skrll 530: plat->ap_bootstrap();
1.16 skrll 531:
1.5 jmcneill 532: /*
533: * If stdout-path is specified on the command line, override the
534: * value in /chosen/stdout-path before initializing console.
535: */
1.44 skrll 536: VPRINTF("stdout\n");
1.5 jmcneill 537: fdt_update_stdout_path();
538:
1.38 jmcneill 539: /*
540: * Done making changes to the FDT.
541: */
542: fdt_pack(fdt_data);
543:
1.29 skrll 544: VPRINTF("consinit ");
1.1 jmcneill 545: consinit();
1.29 skrll 546: VPRINTF("ok\n");
1.1 jmcneill 547:
1.29 skrll 548: VPRINTF("uboot: args %#lx, %#lx, %#lx, %#lx\n",
1.1 jmcneill 549: uboot_args[0], uboot_args[1], uboot_args[2], uboot_args[3]);
550:
551: cpu_reset_address = fdt_reset;
552: cpu_powerdown_address = fdt_powerdown;
553: evbarm_device_register = fdt_device_register;
1.39 bouyer 554: evbarm_device_register_post_config = fdt_device_register_post_config;
1.34 jmcneill 555: evbarm_cpu_rootconf = fdt_cpu_rootconf;
1.1 jmcneill 556:
557: /* Talk to the user */
1.45 skrll 558: printf("NetBSD/evbarm (fdt) booting ...\n");
1.1 jmcneill 559:
560: #ifdef BOOT_ARGS
561: char mi_bootargs[] = BOOT_ARGS;
562: parse_mi_bootargs(mi_bootargs);
563: #endif
564:
1.21 ryo 565: fdt_get_memory(&memory_start, &memory_end);
1.1 jmcneill 566:
567: #if !defined(_LP64)
568: /* Cannot map memory above 4GB */
1.21 ryo 569: if (memory_end >= 0x100000000ULL)
570: memory_end = 0x100000000ULL - PAGE_SIZE;
571:
1.31 skrll 572: #endif
1.21 ryo 573: uint64_t memory_size = memory_end - memory_start;
1.1 jmcneill 574:
1.44 skrll 575: VPRINTF("%s: memory start %" PRIx64 " end %" PRIx64 " (len %"
576: PRIx64 ")\n", __func__, memory_start, memory_end, memory_size);
577:
1.8 jmcneill 578: /* Parse ramdisk info */
579: fdt_probe_initrd(&initrd_start, &initrd_end);
580:
1.65 riastrad 581: /* Parse rndseed */
582: fdt_probe_rndseed(&rndseed_start, &rndseed_end);
583:
1.16 skrll 584: /*
585: * Populate bootconfig structure for the benefit of
586: * dodumpsys
587: */
1.44 skrll 588: VPRINTF("%s: fdt_build_bootconfig\n", __func__);
1.21 ryo 589: fdt_build_bootconfig(memory_start, memory_end);
590:
1.46 jmcneill 591: #ifdef EFI_RUNTIME
1.51 jmcneill 592: fdt_map_efi_runtime("netbsd,uefi-runtime-code", ARM_EFIRT_MEM_CODE);
593: fdt_map_efi_runtime("netbsd,uefi-runtime-data", ARM_EFIRT_MEM_DATA);
594: fdt_map_efi_runtime("netbsd,uefi-runtime-mmio", ARM_EFIRT_MEM_MMIO);
1.46 jmcneill 595: #endif
596:
1.31 skrll 597: /* Perform PT build and VM init */
598: cpu_kernel_vm_init(memory_start, memory_size);
1.1 jmcneill 599:
1.29 skrll 600: VPRINTF("bootargs: %s\n", bootargs);
1.1 jmcneill 601:
602: parse_mi_bootargs(boot_args);
603:
1.49 jmcneill 604: VPRINTF("Memory regions:\n");
605: fdt_memory_foreach(fdt_add_boot_physmem, &memory_size);
1.1 jmcneill 606:
1.64 skrll 607: vaddr_t sp = initarm_common(KERNEL_VM_BASE, KERNEL_VM_SIZE, fdt_physmem,
1.16 skrll 608: nfdt_physmem);
1.44 skrll 609:
1.59 skrll 610: /*
1.60 skrll 611: * initarm_common flushes cache if required before AP start
1.59 skrll 612: */
1.58 skrll 613: error = 0;
1.56 ryo 614: if ((boothowto & RB_MD1) == 0) {
615: VPRINTF("mpstart\n");
616: if (plat->ap_mpstart)
1.58 skrll 617: error = plat->ap_mpstart();
1.56 ryo 618: }
1.44 skrll 619:
1.58 skrll 620: if (error)
621: return sp;
1.44 skrll 622: /*
623: * Now we have APs started the pages used for stacks and L1PT can
624: * be given to uvm
625: */
1.57 skrll 626: extern char const __start__init_memory[];
627: extern char const __stop__init_memory[] __weak;
628:
1.44 skrll 629: if (__start__init_memory != __stop__init_memory) {
630: const paddr_t spa = KERN_VTOPHYS((vaddr_t)__start__init_memory);
631: const paddr_t epa = KERN_VTOPHYS((vaddr_t)__stop__init_memory);
632: const paddr_t spg = atop(spa);
633: const paddr_t epg = atop(epa);
634:
1.63 skrll 635: VPRINTF(" start %08lx end %08lx... "
636: "loading in freelist %d\n", spa, epa, VM_FREELIST_DEFAULT);
637:
1.44 skrll 638: uvm_page_physload(spg, epg, spg, epg, VM_FREELIST_DEFAULT);
639:
640: }
641:
642: return sp;
1.1 jmcneill 643: }
644:
1.5 jmcneill 645: static void
646: fdt_update_stdout_path(void)
647: {
648: char *stdout_path, *ep;
649: int stdout_path_len;
650: char buf[256];
651:
652: const int chosen_off = fdt_path_offset(fdt_data, "/chosen");
653: if (chosen_off == -1)
654: return;
655:
656: if (get_bootconf_option(boot_args, "stdout-path",
657: BOOTOPT_TYPE_STRING, &stdout_path) == 0)
658: return;
659:
660: ep = strchr(stdout_path, ' ');
661: stdout_path_len = ep ? (ep - stdout_path) : strlen(stdout_path);
662: if (stdout_path_len >= sizeof(buf))
663: return;
664:
665: strncpy(buf, stdout_path, stdout_path_len);
666: buf[stdout_path_len] = '\0';
667: fdt_setprop(fdt_data, chosen_off, "stdout-path",
668: buf, stdout_path_len + 1);
669: }
670:
1.1 jmcneill 671: void
672: consinit(void)
673: {
674: static bool initialized = false;
675: const struct arm_platform *plat = arm_fdt_platform();
676: const struct fdt_console *cons = fdtbus_get_console();
677: struct fdt_attach_args faa;
1.4 jmcneill 678: u_int uart_freq = 0;
1.1 jmcneill 679:
680: if (initialized || cons == NULL)
681: return;
682:
1.32 skrll 683: plat->ap_init_attach_args(&faa);
1.1 jmcneill 684: faa.faa_phandle = fdtbus_get_stdout_phandle();
685:
1.32 skrll 686: if (plat->ap_uart_freq != NULL)
687: uart_freq = plat->ap_uart_freq();
1.4 jmcneill 688:
689: cons->consinit(&faa, uart_freq);
1.1 jmcneill 690:
691: initialized = true;
692: }
693:
1.3 jmcneill 694: void
1.65 riastrad 695: cpu_startup_hook(void)
696: {
697:
698: fdt_setup_rndseed();
699: }
700:
701: void
1.3 jmcneill 702: delay(u_int us)
703: {
704: const struct arm_platform *plat = arm_fdt_platform();
705:
1.32 skrll 706: plat->ap_delay(us);
1.3 jmcneill 707: }
708:
1.1 jmcneill 709: static void
1.34 jmcneill 710: fdt_detect_root_device(device_t dev)
711: {
712: struct mbr_sector mbr;
713: uint8_t buf[DEV_BSIZE];
714: uint8_t hash[16];
715: const uint8_t *rhash;
1.53 jmcneill 716: char rootarg[64];
1.34 jmcneill 717: struct vnode *vp;
718: MD5_CTX md5ctx;
719: int error, len;
720: size_t resid;
721: u_int part;
722:
723: const int chosen = OF_finddevice("/chosen");
724: if (chosen < 0)
725: return;
726:
727: if (of_hasprop(chosen, "netbsd,mbr") &&
728: of_hasprop(chosen, "netbsd,partition")) {
729:
730: /*
731: * The bootloader has passed in a partition index and MD5 hash
732: * of the MBR sector. Read the MBR of this device, calculate the
733: * hash, and compare it with the value passed in.
734: */
735: rhash = fdtbus_get_prop(chosen, "netbsd,mbr", &len);
736: if (rhash == NULL || len != 16)
737: return;
738: of_getprop_uint32(chosen, "netbsd,partition", &part);
739: if (part >= MAXPARTITIONS)
740: return;
741:
742: vp = opendisk(dev);
743: if (!vp)
744: return;
745: error = vn_rdwr(UIO_READ, vp, buf, sizeof(buf), 0, UIO_SYSSPACE,
746: 0, NOCRED, &resid, NULL);
747: VOP_CLOSE(vp, FREAD, NOCRED);
748: vput(vp);
749:
750: if (error != 0)
751: return;
752:
753: memcpy(&mbr, buf, sizeof(mbr));
754: MD5Init(&md5ctx);
755: MD5Update(&md5ctx, (void *)&mbr, sizeof(mbr));
756: MD5Final(hash, &md5ctx);
757:
758: if (memcmp(rhash, hash, 16) != 0)
759: return;
760:
761: snprintf(rootarg, sizeof(rootarg), " root=%s%c", device_xname(dev), part + 'a');
762: strcat(boot_args, rootarg);
763: }
1.53 jmcneill 764:
765: if (of_hasprop(chosen, "netbsd,gpt-guid")) {
766: char guidbuf[UUID_STR_LEN];
767: const struct uuid *guid = fdtbus_get_prop(chosen, "netbsd,gpt-guid", &len);
768: if (guid == NULL || len != 16)
769: return;
770:
771: uuid_snprintf(guidbuf, sizeof(guidbuf), guid);
772: snprintf(rootarg, sizeof(rootarg), " root=wedge:%s", guidbuf);
773: strcat(boot_args, rootarg);
774: }
775:
776: if (of_hasprop(chosen, "netbsd,gpt-label")) {
777: const char *label = fdtbus_get_string(chosen, "netbsd,gpt-label");
778: if (label == NULL || *label == '\0')
779: return;
780:
781: device_t dv = dkwedge_find_by_wname(label);
782: if (dv != NULL)
783: booted_device = dv;
784: }
1.55 jmcneill 785:
786: if (of_hasprop(chosen, "netbsd,booted-mac-address")) {
787: const uint8_t *macaddr = fdtbus_get_prop(chosen, "netbsd,booted-mac-address", &len);
788: if (macaddr == NULL || len != 6)
789: return;
790: int s = pserialize_read_enter();
791: struct ifnet *ifp;
792: IFNET_READER_FOREACH(ifp) {
793: if (memcmp(macaddr, CLLADDR(ifp->if_sadl), len) == 0) {
794: device_t dv = device_find_by_xname(ifp->if_xname);
795: if (dv != NULL)
796: booted_device = dv;
797: break;
798: }
799: }
800: pserialize_read_exit(s);
801: }
1.34 jmcneill 802: }
803:
804: static void
1.1 jmcneill 805: fdt_device_register(device_t self, void *aux)
806: {
807: const struct arm_platform *plat = arm_fdt_platform();
808:
1.8 jmcneill 809: if (device_is_a(self, "armfdt"))
810: fdt_setup_initrd();
811:
1.32 skrll 812: if (plat && plat->ap_device_register)
813: plat->ap_device_register(self, aux);
1.1 jmcneill 814: }
815:
816: static void
1.39 bouyer 817: fdt_device_register_post_config(device_t self, void *aux)
818: {
819: #if NUKBD > 0 && NWSDISPLAY > 0
820: if (device_is_a(self, "wsdisplay")) {
821: struct wsdisplay_softc *sc = device_private(self);
822: if (wsdisplay_isconsole(sc))
823: ukbd_cnattach();
824: }
825: #endif
826: }
827:
828: static void
1.34 jmcneill 829: fdt_cpu_rootconf(void)
830: {
831: device_t dev;
832: deviter_t di;
833: char *ptr;
834:
835: for (dev = deviter_first(&di, 0); dev; dev = deviter_next(&di)) {
836: if (device_class(dev) != DV_DISK)
837: continue;
838:
839: if (get_bootconf_option(boot_args, "root", BOOTOPT_TYPE_STRING, &ptr) != 0)
840: break;
841:
1.36 jakllsch 842: if (device_is_a(dev, "ld") || device_is_a(dev, "sd") || device_is_a(dev, "wd"))
1.34 jmcneill 843: fdt_detect_root_device(dev);
844: }
845: deviter_release(&di);
846: }
847:
848: static void
1.1 jmcneill 849: fdt_reset(void)
850: {
851: const struct arm_platform *plat = arm_fdt_platform();
852:
853: fdtbus_power_reset();
854:
1.32 skrll 855: if (plat && plat->ap_reset)
856: plat->ap_reset();
1.1 jmcneill 857: }
858:
859: static void
860: fdt_powerdown(void)
861: {
862: fdtbus_power_poweroff();
863: }
CVSweb <webmaster@jp.NetBSD.org>