[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.89

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

CVSweb <webmaster@jp.NetBSD.org>