[BACK]Return to fdt_machdep.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / evbarm / fdt

Annotation of src/sys/arch/evbarm/fdt/fdt_machdep.c, Revision 1.96

1.96    ! skrll       1: /* $NetBSD: fdt_machdep.c,v 1.95 2022/09/30 06:39:54 skrll 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.96    ! skrll      30: __KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.95 2022/09/30 06:39:54 skrll Exp $");
1.1       jmcneill   31:
1.84      skrll      32: #include "opt_arm_debug.h"
1.21      ryo        33: #include "opt_bootconfig.h"
1.84      skrll      34: #include "opt_cpuoptions.h"
1.1       jmcneill   35: #include "opt_ddb.h"
1.84      skrll      36: #include "opt_efi.h"
                     37: #include "opt_machdep.h"
1.1       jmcneill   38: #include "opt_md.h"
                     39: #include "opt_multiprocessor.h"
                     40:
1.75      jmcneill   41: #include "genfb.h"
1.14      jmcneill   42: #include "ukbd.h"
1.39      bouyer     43: #include "wsdisplay.h"
1.14      jmcneill   44:
1.1       jmcneill   45: #include <sys/param.h>
1.93      skrll      46: #include <sys/types.h>
                     47:
                     48: #include <sys/atomic.h>
                     49: #include <sys/bootblock.h>
1.1       jmcneill   50: #include <sys/bus.h>
1.93      skrll      51: #include <sys/conf.h>
1.1       jmcneill   52: #include <sys/cpu.h>
                     53: #include <sys/device.h>
1.93      skrll      54: #include <sys/disk.h>
                     55: #include <sys/disklabel.h>
1.76      rin        56: #include <sys/endian.h>
1.1       jmcneill   57: #include <sys/exec.h>
1.93      skrll      58: #include <sys/fcntl.h>
                     59: #include <sys/kauth.h>
1.1       jmcneill   60: #include <sys/kernel.h>
                     61: #include <sys/kmem.h>
                     62: #include <sys/ksyms.h>
1.93      skrll      63: #include <sys/md5.h>
1.1       jmcneill   64: #include <sys/msgbuf.h>
                     65: #include <sys/proc.h>
1.93      skrll      66: #include <sys/pserialize.h>
1.1       jmcneill   67: #include <sys/reboot.h>
1.93      skrll      68: #include <sys/rnd.h>
                     69: #include <sys/rndsource.h>
                     70: #include <sys/systm.h>
1.1       jmcneill   71: #include <sys/termios.h>
1.34      jmcneill   72: #include <sys/vnode.h>
1.53      jmcneill   73: #include <sys/uuid.h>
1.55      jmcneill   74:
                     75: #include <net/if.h>
                     76: #include <net/if_dl.h>
1.1       jmcneill   77:
1.23      ryo        78: #include <dev/cons.h>
1.1       jmcneill   79: #include <uvm/uvm_extern.h>
                     80:
                     81: #include <machine/db_machdep.h>
                     82: #include <ddb/db_sym.h>
                     83: #include <ddb/db_extern.h>
                     84:
                     85: #include <machine/bootconfig.h>
                     86: #include <arm/armreg.h>
                     87:
1.21      ryo        88: #include <arm/cpufunc.h>
1.1       jmcneill   89:
                     90: #include <evbarm/include/autoconf.h>
1.30      skrll      91: #include <evbarm/fdt/machdep.h>
1.1       jmcneill   92: #include <evbarm/fdt/platform.h>
                     93:
                     94: #include <arm/fdt/arm_fdtvar.h>
1.68      skrll      95: #include <dev/fdt/fdt_private.h>
1.83      skrll      96: #include <dev/fdt/fdt_memory.h>
1.1       jmcneill   97:
1.46      jmcneill   98: #ifdef EFI_RUNTIME
                     99: #include <arm/arm/efi_runtime.h>
                    100: #endif
                    101:
1.75      jmcneill  102: #if NWSDISPLAY > 0 && NGENFB > 0
                    103: #include <arm/fdt/arm_simplefb.h>
                    104: #endif
                    105:
1.14      jmcneill  106: #if NUKBD > 0
                    107: #include <dev/usb/ukbdvar.h>
                    108: #endif
1.39      bouyer    109: #if NWSDISPLAY > 0
                    110: #include <dev/wscons/wsdisplayvar.h>
                    111: #endif
1.14      jmcneill  112:
1.8       jmcneill  113: #ifdef MEMORY_DISK_DYNAMIC
                    114: #include <dev/md.h>
                    115: #endif
                    116:
1.1       jmcneill  117: #ifndef FDT_MAX_BOOT_STRING
                    118: #define FDT_MAX_BOOT_STRING 1024
                    119: #endif
                    120:
                    121: BootConfig bootconfig;
                    122: char bootargs[FDT_MAX_BOOT_STRING] = "";
                    123: char *boot_args = NULL;
1.26      christos  124:
                    125: /* filled in before cleaning bss. keep in .data */
1.27      christos  126: u_long uboot_args[4] __attribute__((__section__(".data")));
1.28      skrll     127: const uint8_t *fdt_addr_r __attribute__((__section__(".data")));
1.1       jmcneill  128:
1.8       jmcneill  129: static uint64_t initrd_start, initrd_end;
1.69      riastrad  130: static uint64_t rndseed_start, rndseed_end; /* our on-disk seed */
                    131: static uint64_t efirng_start, efirng_end;   /* firmware's EFI RNG output */
1.8       jmcneill  132:
1.1       jmcneill  133: #include <libfdt.h>
                    134: #include <dev/fdt/fdtvar.h>
1.40      jmcneill  135: #define FDT_BUF_SIZE   (512*1024)
1.1       jmcneill  136: static uint8_t fdt_data[FDT_BUF_SIZE];
                    137:
                    138: extern char KERNEL_BASE_phys[];
                    139: #define KERNEL_BASE_PHYS ((paddr_t)KERNEL_BASE_phys)
                    140:
1.5       jmcneill  141: static void fdt_update_stdout_path(void);
1.1       jmcneill  142: static void fdt_device_register(device_t, void *);
1.39      bouyer    143: static void fdt_device_register_post_config(device_t, void *);
1.34      jmcneill  144: static void fdt_cpu_rootconf(void);
1.1       jmcneill  145: static void fdt_reset(void);
                    146: static void fdt_powerdown(void);
                    147:
1.76      rin       148: #if BYTE_ORDER == BIG_ENDIAN
                    149: static void fdt_update_fb_format(void);
                    150: #endif
                    151:
1.1       jmcneill  152: static void
1.23      ryo       153: earlyconsputc(dev_t dev, int c)
1.1       jmcneill  154: {
1.48      skrll     155:        uartputc(c);
1.1       jmcneill  156: }
                    157:
1.23      ryo       158: static int
                    159: earlyconsgetc(dev_t dev)
1.1       jmcneill  160: {
1.87      jmcneill  161:        return -1;
1.23      ryo       162: }
1.1       jmcneill  163:
1.54      skrll     164: static struct consdev earlycons = {
                    165:        .cn_putc = earlyconsputc,
                    166:        .cn_getc = earlyconsgetc,
                    167:        .cn_pollc = nullcnpollc,
                    168: };
                    169:
1.23      ryo       170: #ifdef VERBOSE_INIT_ARM
1.29      skrll     171: #define VPRINTF(...)   printf(__VA_ARGS__)
1.1       jmcneill  172: #else
1.43      skrll     173: #define VPRINTF(...)   __nothing
1.1       jmcneill  174: #endif
                    175:
1.49      jmcneill  176: static void
                    177: fdt_add_dram_blocks(const struct fdt_memory *m, void *arg)
                    178: {
                    179:        BootConfig *bc = arg;
                    180:
1.52      jmcneill  181:        VPRINTF("  %" PRIx64 " - %" PRIx64 "\n", m->start, m->end - 1);
1.49      jmcneill  182:        bc->dram[bc->dramblocks].address = m->start;
                    183:        bc->dram[bc->dramblocks].pages =
                    184:            (m->end - m->start) / PAGE_SIZE;
                    185:        bc->dramblocks++;
                    186: }
                    187:
                    188: #define MAX_PHYSMEM 64
                    189: static int nfdt_physmem = 0;
                    190: static struct boot_physmem fdt_physmem[MAX_PHYSMEM];
                    191:
                    192: static void
                    193: fdt_add_boot_physmem(const struct fdt_memory *m, void *arg)
                    194: {
1.62      skrll     195:        const paddr_t saddr = round_page(m->start);
                    196:        const paddr_t eaddr = trunc_page(m->end);
                    197:
                    198:        VPRINTF("  %" PRIx64 " - %" PRIx64, m->start, m->end - 1);
                    199:        if (saddr >= eaddr) {
                    200:                VPRINTF(" skipped\n");
                    201:                return;
                    202:        }
                    203:        VPRINTF("\n");
                    204:
1.49      jmcneill  205:        struct boot_physmem *bp = &fdt_physmem[nfdt_physmem++];
                    206:
                    207:        KASSERT(nfdt_physmem <= MAX_PHYSMEM);
                    208:
1.62      skrll     209:        bp->bp_start = atop(saddr);
                    210:        bp->bp_pages = atop(eaddr) - bp->bp_start;
1.49      jmcneill  211:        bp->bp_freelist = VM_FREELIST_DEFAULT;
                    212:
                    213: #ifdef PMAP_NEED_ALLOC_POOLPAGE
                    214:        const uint64_t memory_size = *(uint64_t *)arg;
                    215:        if (atop(memory_size) > bp->bp_pages) {
                    216:                arm_poolpage_vmfreelist = VM_FREELIST_DIRECTMAP;
                    217:                bp->bp_freelist = VM_FREELIST_DIRECTMAP;
                    218:        }
                    219: #endif
                    220: }
                    221:
1.83      skrll     222:
                    223: static void
                    224: fdt_print_memory(const struct fdt_memory *m, void *arg)
                    225: {
                    226:
                    227:        VPRINTF("FDT /memory @ 0x%" PRIx64 " size 0x%" PRIx64 "\n",
                    228:            m->start, m->end - m->start);
                    229: }
                    230:
                    231:
1.8       jmcneill  232: /*
                    233:  * Define usable memory regions.
                    234:  */
                    235: static void
1.21      ryo       236: fdt_build_bootconfig(uint64_t mem_start, uint64_t mem_end)
1.8       jmcneill  237: {
                    238:        BootConfig *bc = &bootconfig;
1.83      skrll     239:
1.8       jmcneill  240:        uint64_t addr, size;
1.49      jmcneill  241:        int index;
1.8       jmcneill  242:
1.73      jmcneill  243:        const uint64_t initrd_size =
                    244:            round_page(initrd_end) - trunc_page(initrd_start);
1.8       jmcneill  245:        if (initrd_size > 0)
1.73      jmcneill  246:                fdt_memory_remove_range(trunc_page(initrd_start), initrd_size);
1.8       jmcneill  247:
1.73      jmcneill  248:        const uint64_t rndseed_size =
                    249:            round_page(rndseed_end) - trunc_page(rndseed_start);
1.65      riastrad  250:        if (rndseed_size > 0)
1.73      jmcneill  251:                fdt_memory_remove_range(trunc_page(rndseed_start),
                    252:                    rndseed_size);
1.65      riastrad  253:
1.73      jmcneill  254:        const uint64_t efirng_size =
                    255:            round_page(efirng_end) - trunc_page(efirng_start);
1.69      riastrad  256:        if (efirng_size > 0)
1.73      jmcneill  257:                fdt_memory_remove_range(trunc_page(efirng_start), efirng_size);
1.69      riastrad  258:
1.47      jmcneill  259:        const int framebuffer = OF_finddevice("/chosen/framebuffer");
                    260:        if (framebuffer >= 0) {
                    261:                for (index = 0;
                    262:                     fdtbus_get_reg64(framebuffer, index, &addr, &size) == 0;
                    263:                     index++) {
1.83      skrll     264:                        fdt_memory_remove_range(addr, size);
1.47      jmcneill  265:                }
                    266:        }
                    267:
1.29      skrll     268:        VPRINTF("Usable memory:\n");
1.8       jmcneill  269:        bc->dramblocks = 0;
1.49      jmcneill  270:        fdt_memory_foreach(fdt_add_dram_blocks, bc);
1.8       jmcneill  271: }
                    272:
                    273: static void
1.70      riastrad  274: fdt_probe_range(const char *startname, const char *endname,
                    275:     uint64_t *pstart, uint64_t *pend)
1.8       jmcneill  276: {
1.70      riastrad  277:        int chosen, len;
                    278:        const void *start_data, *end_data;
                    279:
1.8       jmcneill  280:        *pstart = *pend = 0;
                    281:
1.70      riastrad  282:        chosen = OF_finddevice("/chosen");
1.8       jmcneill  283:        if (chosen < 0)
                    284:                return;
                    285:
1.70      riastrad  286:        start_data = fdtbus_get_prop(chosen, startname, &len);
                    287:        end_data = fdtbus_get_prop(chosen, endname, NULL);
1.8       jmcneill  288:        if (start_data == NULL || end_data == NULL)
                    289:                return;
                    290:
                    291:        switch (len) {
                    292:        case 4:
                    293:                *pstart = be32dec(start_data);
                    294:                *pend = be32dec(end_data);
                    295:                break;
                    296:        case 8:
                    297:                *pstart = be64dec(start_data);
                    298:                *pend = be64dec(end_data);
                    299:                break;
                    300:        default:
1.70      riastrad  301:                printf("Unsupported len %d for /chosen `%s'\n",
                    302:                    len, startname);
1.8       jmcneill  303:                return;
                    304:        }
                    305: }
                    306:
1.70      riastrad  307: static void *
                    308: fdt_map_range(uint64_t start, uint64_t end, uint64_t *psize,
                    309:     const char *purpose)
1.8       jmcneill  310: {
1.70      riastrad  311:        const paddr_t startpa = trunc_page(start);
                    312:        const paddr_t endpa = round_page(end);
1.8       jmcneill  313:        paddr_t pa;
                    314:        vaddr_t va;
1.70      riastrad  315:        void *ptr;
1.8       jmcneill  316:
1.70      riastrad  317:        *psize = end - start;
                    318:        if (*psize == 0)
                    319:                return NULL;
1.8       jmcneill  320:
1.72      skrll     321:        const vaddr_t voff = start & PAGE_MASK;
                    322:
1.94      skrll     323:        va = uvm_km_alloc(kernel_map, *psize, 0, UVM_KMF_VAONLY | UVM_KMF_NOWAIT);
1.8       jmcneill  324:        if (va == 0) {
1.70      riastrad  325:                printf("Failed to allocate VA for %s\n", purpose);
                    326:                return NULL;
1.8       jmcneill  327:        }
1.72      skrll     328:        ptr = (void *)(va + voff);
1.8       jmcneill  329:
                    330:        for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE)
1.94      skrll     331:                pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, 0);
1.8       jmcneill  332:        pmap_update(pmap_kernel());
                    333:
1.70      riastrad  334:        return ptr;
                    335: }
                    336:
                    337: static void
1.71      riastrad  338: fdt_unmap_range(void *ptr, uint64_t size)
                    339: {
                    340:        const char *start = ptr, *end = start + size;
                    341:        const vaddr_t startva = trunc_page((vaddr_t)(uintptr_t)start);
                    342:        const vaddr_t endva = round_page((vaddr_t)(uintptr_t)end);
1.95      skrll     343:        const vsize_t sz = endva - startva;
1.71      riastrad  344:
1.95      skrll     345:        pmap_kremove(startva, sz);
1.71      riastrad  346:        pmap_update(pmap_kernel());
1.95      skrll     347:
                    348:        uvm_km_free(kernel_map, startva, sz, UVM_KMF_VAONLY);
1.71      riastrad  349: }
                    350:
                    351: static void
1.70      riastrad  352: fdt_probe_initrd(uint64_t *pstart, uint64_t *pend)
                    353: {
                    354:        *pstart = *pend = 0;
                    355:
                    356: #ifdef MEMORY_DISK_DYNAMIC
                    357:        fdt_probe_range("linux,initrd-start", "linux,initrd-end", pstart, pend);
1.8       jmcneill  358: #endif
                    359: }
                    360:
1.65      riastrad  361: static void
1.70      riastrad  362: fdt_setup_initrd(void)
1.65      riastrad  363: {
1.70      riastrad  364: #ifdef MEMORY_DISK_DYNAMIC
                    365:        void *md_start;
                    366:        uint64_t initrd_size;
1.65      riastrad  367:
1.70      riastrad  368:        md_start = fdt_map_range(initrd_start, initrd_end, &initrd_size,
                    369:            "initrd");
                    370:        if (md_start == NULL)
1.65      riastrad  371:                return;
1.70      riastrad  372:        md_root_setconf(md_start, initrd_size);
                    373: #endif
                    374: }
1.65      riastrad  375:
1.70      riastrad  376: static void
                    377: fdt_probe_rndseed(uint64_t *pstart, uint64_t *pend)
                    378: {
1.65      riastrad  379:
1.70      riastrad  380:        fdt_probe_range("netbsd,rndseed-start", "netbsd,rndseed-end",
                    381:            pstart, pend);
1.65      riastrad  382: }
                    383:
                    384: static void
                    385: fdt_setup_rndseed(void)
                    386: {
1.70      riastrad  387:        uint64_t rndseed_size;
1.65      riastrad  388:        void *rndseed;
                    389:
1.70      riastrad  390:        rndseed = fdt_map_range(rndseed_start, rndseed_end, &rndseed_size,
                    391:            "rndseed");
                    392:        if (rndseed == NULL)
1.65      riastrad  393:                return;
                    394:        rnd_seed(rndseed, rndseed_size);
1.71      riastrad  395:        fdt_unmap_range(rndseed, rndseed_size);
1.65      riastrad  396: }
                    397:
1.69      riastrad  398: static void
                    399: fdt_probe_efirng(uint64_t *pstart, uint64_t *pend)
                    400: {
                    401:
1.70      riastrad  402:        fdt_probe_range("netbsd,efirng-start", "netbsd,efirng-end",
                    403:            pstart, pend);
1.69      riastrad  404: }
                    405:
                    406: static struct krndsource efirng_source;
                    407:
                    408: static void
                    409: fdt_setup_efirng(void)
                    410: {
1.70      riastrad  411:        uint64_t efirng_size;
1.69      riastrad  412:        void *efirng;
                    413:
1.70      riastrad  414:        efirng = fdt_map_range(efirng_start, efirng_end, &efirng_size,
                    415:            "efirng");
                    416:        if (efirng == NULL)
1.69      riastrad  417:                return;
                    418:
                    419:        rnd_attach_source(&efirng_source, "efirng", RND_TYPE_RNG,
                    420:            RND_FLAG_DEFAULT);
1.82      riastrad  421:
                    422:        /*
                    423:         * We don't really have specific information about the physical
                    424:         * process underlying the data provided by the firmware via the
                    425:         * EFI RNG API, so the entropy estimate here is heuristic.
                    426:         * What efiboot provides us is up to 4096 bytes of data from
                    427:         * the EFI RNG API, although in principle it may return short.
                    428:         *
                    429:         * The UEFI Specification (2.8 Errata A, February 2020[1]) says
                    430:         *
                    431:         *      When a Deterministic Random Bit Generator (DRBG) is
                    432:         *      used on the output of a (raw) entropy source, its
                    433:         *      security level must be at least 256 bits.
                    434:         *
                    435:         * It's not entirely clear whether `it' refers to the DRBG or
                    436:         * the entropy source; if it refers to the DRBG, it's not
                    437:         * entirely clear how ANSI X9.31 3DES, one of the options for
                    438:         * DRBG in the UEFI spec, can provide a `256-bit security
                    439:         * level' because it has only 232 bits of inputs (three 56-bit
                    440:         * keys and one 64-bit block).  That said, even if it provides
                    441:         * only 232 bits of entropy, that's enough to prevent all
                    442:         * attacks and we probably get a few more bits from sampling
                    443:         * the clock anyway.
                    444:         *
                    445:         * In the event we get raw samples, e.g. the bits sampled by a
                    446:         * ring oscillator, we hope that the samples have at least half
                    447:         * a bit of entropy per bit of data -- and efiboot tries to
                    448:         * draw 4096 bytes to provide plenty of slop.  Hence we divide
                    449:         * the total number of bits by two and clamp at 256.  There are
                    450:         * ways this could go wrong, but on most machines it should
                    451:         * behave reasonably.
                    452:         *
                    453:         * [1] https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_A_Feb14.pdf
                    454:         */
                    455:        rnd_add_data(&efirng_source, efirng, efirng_size,
                    456:            MIN(256, efirng_size*NBBY/2));
                    457:
1.69      riastrad  458:        explicit_memset(efirng, 0, efirng_size);
1.71      riastrad  459:        fdt_unmap_range(efirng, efirng_size);
1.69      riastrad  460: }
                    461:
1.46      jmcneill  462: #ifdef EFI_RUNTIME
                    463: static void
1.51      jmcneill  464: fdt_map_efi_runtime(const char *prop, enum arm_efirt_mem_type type)
1.46      jmcneill  465: {
                    466:        int len;
                    467:
                    468:        const int chosen_off = fdt_path_offset(fdt_data, "/chosen");
                    469:        if (chosen_off < 0)
                    470:                return;
                    471:
                    472:        const uint64_t *map = fdt_getprop(fdt_data, chosen_off, prop, &len);
                    473:        if (map == NULL)
                    474:                return;
                    475:
                    476:        while (len >= 24) {
                    477:                const paddr_t pa = be64toh(map[0]);
                    478:                const vaddr_t va = be64toh(map[1]);
1.85      skrll     479:                const size_t sz = be64toh(map[2]);
1.89      skrll     480:                VPRINTF("%s: %s %#" PRIxPADDR "-%#" PRIxVADDR " (%#" PRIxVADDR
                    481:                    "-%#" PRIxVSIZE ")\n", __func__, prop, pa, pa + sz - 1,
1.85      skrll     482:                    va, va + sz - 1);
1.51      jmcneill  483:                arm_efirt_md_map_range(va, pa, sz, type);
1.46      jmcneill  484:                map += 3;
                    485:                len -= 24;
                    486:        }
                    487: }
                    488: #endif
                    489:
1.64      skrll     490: vaddr_t
1.1       jmcneill  491: initarm(void *arg)
                    492: {
                    493:        const struct arm_platform *plat;
1.21      ryo       494:        uint64_t memory_start, memory_end;
1.1       jmcneill  495:
1.23      ryo       496:        /* set temporally to work printf()/panic() even before consinit() */
                    497:        cn_tab = &earlycons;
                    498:
1.1       jmcneill  499:        /* Load FDT */
                    500:        int error = fdt_check_header(fdt_addr_r);
1.79      skrll     501:        if (error != 0)
1.1       jmcneill  502:                panic("fdt_check_header failed: %s", fdt_strerror(error));
1.79      skrll     503:
                    504:        /* If the DTB is too big, try to pack it in place first. */
                    505:        if (fdt_totalsize(fdt_addr_r) > sizeof(fdt_data))
                    506:                (void)fdt_pack(__UNCONST(fdt_addr_r));
1.83      skrll     507:
1.79      skrll     508:        error = fdt_open_into(fdt_addr_r, fdt_data, sizeof(fdt_data));
                    509:        if (error != 0)
                    510:                panic("fdt_move failed: %s", fdt_strerror(error));
                    511:
                    512:        fdtbus_init(fdt_data);
1.1       jmcneill  513:
                    514:        /* Lookup platform specific backend */
                    515:        plat = arm_fdt_platform();
                    516:        if (plat == NULL)
                    517:                panic("Kernel does not support this device");
                    518:
                    519:        /* Early console may be available, announce ourselves. */
1.29      skrll     520:        VPRINTF("FDT<%p>\n", fdt_addr_r);
1.1       jmcneill  521:
1.6       jmcneill  522:        const int chosen = OF_finddevice("/chosen");
                    523:        if (chosen >= 0)
                    524:                OF_getprop(chosen, "bootargs", bootargs, sizeof(bootargs));
                    525:        boot_args = bootargs;
                    526:
1.1       jmcneill  527:        /* Heads up ... Setup the CPU / MMU / TLB functions. */
1.29      skrll     528:        VPRINTF("cpufunc\n");
1.1       jmcneill  529:        if (set_cpufuncs())
                    530:                panic("cpu not recognized!");
                    531:
1.44      skrll     532:        /*
                    533:         * Memory is still identity/flat mapped this point so using ttbr for
                    534:         * l1pt VA is fine
                    535:         */
                    536:
1.78      skrll     537:        VPRINTF("devmap %p\n", plat->ap_devmap());
1.44      skrll     538:        extern char ARM_BOOTSTRAP_LxPT[];
                    539:        pmap_devmap_bootstrap((vaddr_t)ARM_BOOTSTRAP_LxPT, plat->ap_devmap());
                    540:
1.29      skrll     541:        VPRINTF("bootstrap\n");
1.32      skrll     542:        plat->ap_bootstrap();
1.16      skrll     543:
1.5       jmcneill  544:        /*
                    545:         * If stdout-path is specified on the command line, override the
                    546:         * value in /chosen/stdout-path before initializing console.
                    547:         */
1.44      skrll     548:        VPRINTF("stdout\n");
1.5       jmcneill  549:        fdt_update_stdout_path();
                    550:
1.76      rin       551: #if BYTE_ORDER == BIG_ENDIAN
                    552:        /*
1.92      skrll     553:         * Most boards are configured to little-endian mode initially, and
1.76      rin       554:         * switched to big-endian mode after kernel is loaded. In this case,
                    555:         * framebuffer seems byte-swapped to CPU. Override FDT to let
                    556:         * drivers know.
                    557:         */
                    558:        VPRINTF("fb_format\n");
                    559:        fdt_update_fb_format();
                    560: #endif
                    561:
1.38      jmcneill  562:        /*
                    563:         * Done making changes to the FDT.
                    564:         */
                    565:        fdt_pack(fdt_data);
                    566:
1.29      skrll     567:        VPRINTF("consinit ");
1.1       jmcneill  568:        consinit();
1.29      skrll     569:        VPRINTF("ok\n");
1.1       jmcneill  570:
1.29      skrll     571:        VPRINTF("uboot: args %#lx, %#lx, %#lx, %#lx\n",
1.1       jmcneill  572:            uboot_args[0], uboot_args[1], uboot_args[2], uboot_args[3]);
                    573:
                    574:        cpu_reset_address = fdt_reset;
                    575:        cpu_powerdown_address = fdt_powerdown;
                    576:        evbarm_device_register = fdt_device_register;
1.39      bouyer    577:        evbarm_device_register_post_config = fdt_device_register_post_config;
1.34      jmcneill  578:        evbarm_cpu_rootconf = fdt_cpu_rootconf;
1.1       jmcneill  579:
                    580:        /* Talk to the user */
1.45      skrll     581:        printf("NetBSD/evbarm (fdt) booting ...\n");
1.1       jmcneill  582:
                    583: #ifdef BOOT_ARGS
                    584:        char mi_bootargs[] = BOOT_ARGS;
                    585:        parse_mi_bootargs(mi_bootargs);
                    586: #endif
                    587:
1.83      skrll     588:        fdt_memory_get(&memory_start, &memory_end);
                    589:
                    590:        fdt_memory_foreach(fdt_print_memory, NULL);
1.1       jmcneill  591:
                    592: #if !defined(_LP64)
1.81      skrll     593:        /* Cannot map memory above 4GB (remove last page as well) */
                    594:        const uint64_t memory_limit = 0x100000000ULL - PAGE_SIZE;
1.83      skrll     595:        if (memory_end > memory_limit) {
                    596:                fdt_memory_remove_range(memory_limit , memory_end);
1.81      skrll     597:                memory_end = memory_limit;
1.83      skrll     598:        }
1.31      skrll     599: #endif
1.21      ryo       600:        uint64_t memory_size = memory_end - memory_start;
1.1       jmcneill  601:
1.44      skrll     602:        VPRINTF("%s: memory start %" PRIx64 " end %" PRIx64 " (len %"
                    603:            PRIx64 ")\n", __func__, memory_start, memory_end, memory_size);
                    604:
1.8       jmcneill  605:        /* Parse ramdisk info */
                    606:        fdt_probe_initrd(&initrd_start, &initrd_end);
                    607:
1.69      riastrad  608:        /* Parse our on-disk rndseed and the firmware's RNG from EFI */
1.65      riastrad  609:        fdt_probe_rndseed(&rndseed_start, &rndseed_end);
1.69      riastrad  610:        fdt_probe_efirng(&efirng_start, &efirng_end);
1.65      riastrad  611:
1.96    ! skrll     612:        fdt_memory_remove_reserved(mem_start, mem_end);
        !           613:
1.16      skrll     614:        /*
1.80      skrll     615:         * Populate bootconfig structure for the benefit of dodumpsys
1.16      skrll     616:         */
1.44      skrll     617:        VPRINTF("%s: fdt_build_bootconfig\n", __func__);
1.21      ryo       618:        fdt_build_bootconfig(memory_start, memory_end);
                    619:
1.31      skrll     620:        /* Perform PT build and VM init */
                    621:        cpu_kernel_vm_init(memory_start, memory_size);
1.1       jmcneill  622:
1.29      skrll     623:        VPRINTF("bootargs: %s\n", bootargs);
1.1       jmcneill  624:
                    625:        parse_mi_bootargs(boot_args);
                    626:
1.49      jmcneill  627:        VPRINTF("Memory regions:\n");
1.86      skrll     628:
                    629:        /* Populate fdt_physmem / nfdt_physmem for initarm_common */
1.49      jmcneill  630:        fdt_memory_foreach(fdt_add_boot_physmem, &memory_size);
1.1       jmcneill  631:
1.64      skrll     632:        vaddr_t sp = initarm_common(KERNEL_VM_BASE, KERNEL_VM_SIZE, fdt_physmem,
1.16      skrll     633:             nfdt_physmem);
1.44      skrll     634:
1.59      skrll     635:        /*
1.60      skrll     636:         * initarm_common flushes cache if required before AP start
1.59      skrll     637:         */
1.58      skrll     638:        error = 0;
1.56      ryo       639:        if ((boothowto & RB_MD1) == 0) {
                    640:                VPRINTF("mpstart\n");
                    641:                if (plat->ap_mpstart)
1.58      skrll     642:                        error = plat->ap_mpstart();
1.56      ryo       643:        }
1.44      skrll     644:
1.58      skrll     645:        if (error)
                    646:                return sp;
1.74      skrll     647:
1.44      skrll     648:        /*
                    649:         * Now we have APs started the pages used for stacks and L1PT can
                    650:         * be given to uvm
                    651:         */
1.57      skrll     652:        extern char const __start__init_memory[];
                    653:        extern char const __stop__init_memory[] __weak;
                    654:
1.44      skrll     655:        if (__start__init_memory != __stop__init_memory) {
                    656:                const paddr_t spa = KERN_VTOPHYS((vaddr_t)__start__init_memory);
                    657:                const paddr_t epa = KERN_VTOPHYS((vaddr_t)__stop__init_memory);
                    658:                const paddr_t spg = atop(spa);
                    659:                const paddr_t epg = atop(epa);
                    660:
1.63      skrll     661:                VPRINTF("         start %08lx  end %08lx... "
                    662:                    "loading in freelist %d\n", spa, epa, VM_FREELIST_DEFAULT);
                    663:
1.44      skrll     664:                uvm_page_physload(spg, epg, spg, epg, VM_FREELIST_DEFAULT);
                    665:
                    666:        }
                    667:
                    668:        return sp;
1.1       jmcneill  669: }
                    670:
1.5       jmcneill  671: static void
                    672: fdt_update_stdout_path(void)
                    673: {
                    674:        char *stdout_path, *ep;
                    675:        int stdout_path_len;
                    676:        char buf[256];
                    677:
                    678:        const int chosen_off = fdt_path_offset(fdt_data, "/chosen");
                    679:        if (chosen_off == -1)
                    680:                return;
                    681:
                    682:        if (get_bootconf_option(boot_args, "stdout-path",
                    683:            BOOTOPT_TYPE_STRING, &stdout_path) == 0)
                    684:                return;
                    685:
                    686:        ep = strchr(stdout_path, ' ');
                    687:        stdout_path_len = ep ? (ep - stdout_path) : strlen(stdout_path);
                    688:        if (stdout_path_len >= sizeof(buf))
                    689:                return;
                    690:
                    691:        strncpy(buf, stdout_path, stdout_path_len);
                    692:        buf[stdout_path_len] = '\0';
                    693:        fdt_setprop(fdt_data, chosen_off, "stdout-path",
                    694:            buf, stdout_path_len + 1);
                    695: }
                    696:
1.1       jmcneill  697: void
                    698: consinit(void)
                    699: {
                    700:        static bool initialized = false;
                    701:        const struct arm_platform *plat = arm_fdt_platform();
                    702:        const struct fdt_console *cons = fdtbus_get_console();
                    703:        struct fdt_attach_args faa;
1.4       jmcneill  704:        u_int uart_freq = 0;
1.1       jmcneill  705:
                    706:        if (initialized || cons == NULL)
                    707:                return;
                    708:
1.32      skrll     709:        plat->ap_init_attach_args(&faa);
1.1       jmcneill  710:        faa.faa_phandle = fdtbus_get_stdout_phandle();
                    711:
1.32      skrll     712:        if (plat->ap_uart_freq != NULL)
                    713:                uart_freq = plat->ap_uart_freq();
1.4       jmcneill  714:
                    715:        cons->consinit(&faa, uart_freq);
1.1       jmcneill  716:
                    717:        initialized = true;
                    718: }
                    719:
1.3       jmcneill  720: void
1.65      riastrad  721: cpu_startup_hook(void)
                    722: {
1.91      skrll     723: #ifdef EFI_RUNTIME
                    724:        fdt_map_efi_runtime("netbsd,uefi-runtime-code", ARM_EFIRT_MEM_CODE);
                    725:        fdt_map_efi_runtime("netbsd,uefi-runtime-data", ARM_EFIRT_MEM_DATA);
                    726:        fdt_map_efi_runtime("netbsd,uefi-runtime-mmio", ARM_EFIRT_MEM_MMIO);
                    727: #endif
1.65      riastrad  728:
1.68      skrll     729:        fdtbus_intr_init();
                    730:
1.65      riastrad  731:        fdt_setup_rndseed();
1.69      riastrad  732:        fdt_setup_efirng();
1.65      riastrad  733: }
                    734:
                    735: void
1.3       jmcneill  736: delay(u_int us)
                    737: {
                    738:        const struct arm_platform *plat = arm_fdt_platform();
                    739:
1.32      skrll     740:        plat->ap_delay(us);
1.3       jmcneill  741: }
                    742:
1.1       jmcneill  743: static void
1.34      jmcneill  744: fdt_detect_root_device(device_t dev)
                    745: {
                    746:        struct mbr_sector mbr;
                    747:        uint8_t buf[DEV_BSIZE];
                    748:        uint8_t hash[16];
                    749:        const uint8_t *rhash;
1.53      jmcneill  750:        char rootarg[64];
1.34      jmcneill  751:        struct vnode *vp;
                    752:        MD5_CTX md5ctx;
                    753:        int error, len;
                    754:        size_t resid;
                    755:        u_int part;
                    756:
                    757:        const int chosen = OF_finddevice("/chosen");
                    758:        if (chosen < 0)
                    759:                return;
                    760:
                    761:        if (of_hasprop(chosen, "netbsd,mbr") &&
                    762:            of_hasprop(chosen, "netbsd,partition")) {
                    763:
                    764:                /*
                    765:                 * The bootloader has passed in a partition index and MD5 hash
                    766:                 * of the MBR sector. Read the MBR of this device, calculate the
                    767:                 * hash, and compare it with the value passed in.
                    768:                 */
                    769:                rhash = fdtbus_get_prop(chosen, "netbsd,mbr", &len);
                    770:                if (rhash == NULL || len != 16)
                    771:                        return;
                    772:                of_getprop_uint32(chosen, "netbsd,partition", &part);
                    773:                if (part >= MAXPARTITIONS)
                    774:                        return;
                    775:
                    776:                vp = opendisk(dev);
                    777:                if (!vp)
                    778:                        return;
                    779:                error = vn_rdwr(UIO_READ, vp, buf, sizeof(buf), 0, UIO_SYSSPACE,
1.90      hannken   780:                    IO_NODELOCKED, NOCRED, &resid, NULL);
1.34      jmcneill  781:                VOP_CLOSE(vp, FREAD, NOCRED);
                    782:                vput(vp);
                    783:
                    784:                if (error != 0)
                    785:                        return;
                    786:
                    787:                memcpy(&mbr, buf, sizeof(mbr));
                    788:                MD5Init(&md5ctx);
                    789:                MD5Update(&md5ctx, (void *)&mbr, sizeof(mbr));
                    790:                MD5Final(hash, &md5ctx);
                    791:
                    792:                if (memcmp(rhash, hash, 16) != 0)
                    793:                        return;
                    794:
                    795:                snprintf(rootarg, sizeof(rootarg), " root=%s%c", device_xname(dev), part + 'a');
                    796:                strcat(boot_args, rootarg);
                    797:        }
1.53      jmcneill  798:
                    799:        if (of_hasprop(chosen, "netbsd,gpt-guid")) {
                    800:                char guidbuf[UUID_STR_LEN];
                    801:                const struct uuid *guid = fdtbus_get_prop(chosen, "netbsd,gpt-guid", &len);
                    802:                if (guid == NULL || len != 16)
                    803:                        return;
                    804:
                    805:                uuid_snprintf(guidbuf, sizeof(guidbuf), guid);
                    806:                snprintf(rootarg, sizeof(rootarg), " root=wedge:%s", guidbuf);
                    807:                strcat(boot_args, rootarg);
                    808:        }
                    809:
                    810:        if (of_hasprop(chosen, "netbsd,gpt-label")) {
                    811:                const char *label = fdtbus_get_string(chosen, "netbsd,gpt-label");
                    812:                if (label == NULL || *label == '\0')
                    813:                        return;
                    814:
                    815:                device_t dv = dkwedge_find_by_wname(label);
                    816:                if (dv != NULL)
                    817:                        booted_device = dv;
                    818:        }
1.55      jmcneill  819:
                    820:        if (of_hasprop(chosen, "netbsd,booted-mac-address")) {
                    821:                const uint8_t *macaddr = fdtbus_get_prop(chosen, "netbsd,booted-mac-address", &len);
                    822:                if (macaddr == NULL || len != 6)
                    823:                        return;
                    824:                int s = pserialize_read_enter();
                    825:                struct ifnet *ifp;
                    826:                IFNET_READER_FOREACH(ifp) {
                    827:                        if (memcmp(macaddr, CLLADDR(ifp->if_sadl), len) == 0) {
                    828:                                device_t dv = device_find_by_xname(ifp->if_xname);
                    829:                                if (dv != NULL)
                    830:                                        booted_device = dv;
                    831:                                break;
                    832:                        }
                    833:                }
                    834:                pserialize_read_exit(s);
                    835:        }
1.34      jmcneill  836: }
                    837:
                    838: static void
1.1       jmcneill  839: fdt_device_register(device_t self, void *aux)
                    840: {
                    841:        const struct arm_platform *plat = arm_fdt_platform();
                    842:
1.75      jmcneill  843:        if (device_is_a(self, "armfdt")) {
1.8       jmcneill  844:                fdt_setup_initrd();
                    845:
1.75      jmcneill  846: #if NWSDISPLAY > 0 && NGENFB > 0
                    847:                /*
                    848:                 * Setup framebuffer console, if present.
                    849:                 */
                    850:                arm_simplefb_preattach();
                    851: #endif
                    852:        }
                    853:
1.77      jmcneill  854: #if NWSDISPLAY > 0 && NGENFB > 0
                    855:        if (device_is_a(self, "genfb")) {
                    856:                prop_dictionary_t dict = device_properties(self);
                    857:                prop_dictionary_set_uint64(dict,
                    858:                    "simplefb-physaddr", arm_simplefb_physaddr());
                    859:        }
                    860: #endif
                    861:
1.32      skrll     862:        if (plat && plat->ap_device_register)
                    863:                plat->ap_device_register(self, aux);
1.1       jmcneill  864: }
                    865:
                    866: static void
1.39      bouyer    867: fdt_device_register_post_config(device_t self, void *aux)
                    868: {
                    869: #if NUKBD > 0 && NWSDISPLAY > 0
                    870:        if (device_is_a(self, "wsdisplay")) {
                    871:                struct wsdisplay_softc *sc = device_private(self);
                    872:                if (wsdisplay_isconsole(sc))
                    873:                        ukbd_cnattach();
                    874:        }
                    875: #endif
                    876: }
                    877:
                    878: static void
1.34      jmcneill  879: fdt_cpu_rootconf(void)
                    880: {
                    881:        device_t dev;
                    882:        deviter_t di;
                    883:        char *ptr;
                    884:
1.88      mrg       885:        if (booted_device != NULL)
                    886:                return;
                    887:
1.34      jmcneill  888:        for (dev = deviter_first(&di, 0); dev; dev = deviter_next(&di)) {
                    889:                if (device_class(dev) != DV_DISK)
                    890:                        continue;
                    891:
                    892:                if (get_bootconf_option(boot_args, "root", BOOTOPT_TYPE_STRING, &ptr) != 0)
                    893:                        break;
                    894:
1.36      jakllsch  895:                if (device_is_a(dev, "ld") || device_is_a(dev, "sd") || device_is_a(dev, "wd"))
1.34      jmcneill  896:                        fdt_detect_root_device(dev);
                    897:        }
                    898:        deviter_release(&di);
                    899: }
                    900:
                    901: static void
1.1       jmcneill  902: fdt_reset(void)
                    903: {
                    904:        const struct arm_platform *plat = arm_fdt_platform();
                    905:
                    906:        fdtbus_power_reset();
                    907:
1.32      skrll     908:        if (plat && plat->ap_reset)
                    909:                plat->ap_reset();
1.1       jmcneill  910: }
                    911:
                    912: static void
                    913: fdt_powerdown(void)
                    914: {
                    915:        fdtbus_power_poweroff();
                    916: }
1.76      rin       917:
                    918: #if BYTE_ORDER == BIG_ENDIAN
                    919: static void
                    920: fdt_update_fb_format(void)
                    921: {
                    922:        int off, len;
                    923:        const char *format, *replace;
                    924:
                    925:        off = fdt_path_offset(fdt_data, "/chosen");
                    926:        if (off < 0)
                    927:                return;
                    928:
                    929:        for (;;) {
                    930:                off = fdt_node_offset_by_compatible(fdt_data, off,
                    931:                    "simple-framebuffer");
                    932:                if (off < 0)
                    933:                        return;
                    934:
                    935:                format = fdt_getprop(fdt_data, off, "format", &len);
                    936:                if (format == NULL)
                    937:                        continue;
                    938:
                    939:                replace = NULL;
                    940:                if (strcmp(format, "a8b8g8r8") == 0)
                    941:                        replace = "r8g8b8a8";
                    942:                else if (strcmp(format, "x8r8g8b8") == 0)
                    943:                        replace = "b8g8r8x8";
                    944:                if (replace != NULL)
                    945:                        fdt_setprop(fdt_data, off, "format", replace,
                    946:                            strlen(replace) + 1);
                    947:        }
                    948: }
                    949: #endif

CVSweb <webmaster@jp.NetBSD.org>