1 1.7 mlelstv /* $NetBSD: fdt_boot.c,v 1.7 2024/12/20 07:55:45 mlelstv Exp $ */ 2 1.1 skrll 3 1.1 skrll /*- 4 1.1 skrll * Copyright (c) 2015-2017 Jared McNeill <jmcneill (at) invisible.ca> 5 1.1 skrll * All rights reserved. 6 1.1 skrll * 7 1.1 skrll * Redistribution and use in source and binary forms, with or without 8 1.1 skrll * modification, are permitted provided that the following conditions 9 1.1 skrll * are met: 10 1.1 skrll * 1. Redistributions of source code must retain the above copyright 11 1.1 skrll * notice, this list of conditions and the following disclaimer. 12 1.1 skrll * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 skrll * notice, this list of conditions and the following disclaimer in the 14 1.1 skrll * documentation and/or other materials provided with the distribution. 15 1.1 skrll * 16 1.1 skrll * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.1 skrll * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.1 skrll * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.1 skrll * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.1 skrll * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 1.1 skrll * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 1.1 skrll * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 1.1 skrll * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 1.1 skrll * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.1 skrll * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.1 skrll * SUCH DAMAGE. 27 1.1 skrll */ 28 1.1 skrll 29 1.1 skrll /*- 30 1.1 skrll * Copyright (c) 2022 The NetBSD Foundation, Inc. 31 1.1 skrll * All rights reserved. 32 1.1 skrll * 33 1.1 skrll * This code is derived from software contributed to The NetBSD Foundation 34 1.1 skrll * by Nick Hudson 35 1.1 skrll * 36 1.1 skrll * Redistribution and use in source and binary forms, with or without 37 1.1 skrll * modification, are permitted provided that the following conditions 38 1.1 skrll * are met: 39 1.1 skrll * 1. Redistributions of source code must retain the above copyright 40 1.1 skrll * notice, this list of conditions and the following disclaimer. 41 1.1 skrll * 2. Redistributions in binary form must reproduce the above copyright 42 1.1 skrll * notice, this list of conditions and the following disclaimer in the 43 1.1 skrll * documentation and/or other materials provided with the distribution. 44 1.1 skrll * 45 1.1 skrll * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 46 1.1 skrll * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 47 1.1 skrll * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 48 1.1 skrll * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 49 1.1 skrll * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 50 1.1 skrll * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 51 1.1 skrll * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 52 1.1 skrll * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 53 1.1 skrll * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 54 1.1 skrll * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 55 1.1 skrll * POSSIBILITY OF SUCH DAMAGE. 56 1.1 skrll */ 57 1.1 skrll 58 1.1 skrll #include <sys/cdefs.h> 59 1.7 mlelstv __KERNEL_RCSID(0, "$NetBSD: fdt_boot.c,v 1.7 2024/12/20 07:55:45 mlelstv Exp $"); 60 1.2 rin 61 1.2 rin #include "opt_efi.h" 62 1.2 rin #include "opt_md.h" 63 1.1 skrll 64 1.1 skrll #include <sys/param.h> 65 1.1 skrll 66 1.6 kre #include <sys/bootblock.h> 67 1.2 rin #include <sys/disk.h> 68 1.2 rin #include <sys/disklabel.h> 69 1.2 rin #include <sys/fcntl.h> 70 1.2 rin #include <sys/md5.h> 71 1.1 skrll #include <sys/optstr.h> 72 1.2 rin #include <sys/rnd.h> 73 1.2 rin #include <sys/rndsource.h> 74 1.2 rin #include <sys/uuid.h> 75 1.2 rin #include <sys/vnode.h> 76 1.2 rin 77 1.2 rin #include <net/if.h> 78 1.2 rin #include <net/if_dl.h> 79 1.2 rin 80 1.2 rin #include <uvm/uvm_extern.h> 81 1.1 skrll 82 1.1 skrll #include <libfdt.h> 83 1.1 skrll 84 1.1 skrll #include <dev/fdt/fdtvar.h> 85 1.1 skrll #include <dev/fdt/fdt_boot.h> 86 1.2 rin #include <dev/fdt/fdt_memory.h> 87 1.2 rin 88 1.3 rin #ifndef FDT_MAX_BOOT_STRING 89 1.3 rin #define FDT_MAX_BOOT_STRING 1024 90 1.3 rin #endif 91 1.3 rin static char bootargs[FDT_MAX_BOOT_STRING] = ""; 92 1.3 rin 93 1.2 rin #ifdef EFI_RUNTIME 94 1.2 rin #include <machine/efirt.h> 95 1.2 rin 96 1.2 rin void fdt_map_efi_runtime(const char *, enum cpu_efirt_mem_type); 97 1.2 rin 98 1.2 rin #endif 99 1.2 rin 100 1.2 rin #ifdef MEMORY_DISK_DYNAMIC 101 1.2 rin #include <dev/md.h> 102 1.2 rin 103 1.2 rin static uint64_t initrd_start, initrd_end; 104 1.2 rin #endif 105 1.2 rin 106 1.2 rin static uint64_t rndseed_start, rndseed_end; /* our on-disk seed */ 107 1.2 rin static uint64_t efirng_start, efirng_end; /* firmware's EFI RNG output */ 108 1.2 rin static struct krndsource efirng_source; 109 1.2 rin 110 1.2 rin 111 1.2 rin static void 112 1.2 rin fdt_probe_range(const char *startname, const char *endname, 113 1.2 rin uint64_t *pstart, uint64_t *pend) 114 1.2 rin { 115 1.2 rin int chosen, len; 116 1.2 rin const void *start_data, *end_data; 117 1.2 rin 118 1.2 rin *pstart = *pend = 0; 119 1.2 rin 120 1.2 rin chosen = OF_finddevice("/chosen"); 121 1.2 rin if (chosen < 0) 122 1.2 rin return; 123 1.2 rin 124 1.2 rin start_data = fdtbus_get_prop(chosen, startname, &len); 125 1.2 rin end_data = fdtbus_get_prop(chosen, endname, NULL); 126 1.2 rin if (start_data == NULL || end_data == NULL) 127 1.2 rin return; 128 1.2 rin 129 1.2 rin switch (len) { 130 1.2 rin case 4: 131 1.2 rin *pstart = be32dec(start_data); 132 1.2 rin *pend = be32dec(end_data); 133 1.2 rin break; 134 1.2 rin case 8: 135 1.2 rin *pstart = be64dec(start_data); 136 1.2 rin *pend = be64dec(end_data); 137 1.2 rin break; 138 1.2 rin default: 139 1.2 rin printf("Unsupported len %d for /chosen `%s'\n", 140 1.2 rin len, startname); 141 1.2 rin return; 142 1.2 rin } 143 1.2 rin } 144 1.2 rin 145 1.2 rin 146 1.2 rin static void * 147 1.2 rin fdt_map_range(uint64_t start, uint64_t end, uint64_t *psize, 148 1.2 rin const char *purpose) 149 1.2 rin { 150 1.2 rin const paddr_t startpa = trunc_page(start); 151 1.2 rin const paddr_t endpa = round_page(end); 152 1.2 rin paddr_t pa; 153 1.2 rin vaddr_t va; 154 1.2 rin void *ptr; 155 1.2 rin 156 1.2 rin *psize = end - start; 157 1.2 rin if (*psize == 0) 158 1.2 rin return NULL; 159 1.2 rin 160 1.2 rin const vaddr_t voff = start & PAGE_MASK; 161 1.2 rin 162 1.2 rin // XXX NH add an align so map_chunk works betterer? 163 1.7 mlelstv va = uvm_km_alloc(kernel_map, endpa - startpa, 0, 164 1.7 mlelstv UVM_KMF_VAONLY | UVM_KMF_NOWAIT); 165 1.2 rin if (va == 0) { 166 1.2 rin printf("Failed to allocate VA for %s\n", purpose); 167 1.2 rin return NULL; 168 1.2 rin } 169 1.2 rin ptr = (void *)(va + voff); 170 1.2 rin 171 1.2 rin // XXX NH map chunk 172 1.2 rin for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) 173 1.2 rin pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, 0); 174 1.2 rin pmap_update(pmap_kernel()); 175 1.2 rin 176 1.2 rin return ptr; 177 1.2 rin } 178 1.2 rin 179 1.2 rin static void 180 1.2 rin fdt_unmap_range(void *ptr, uint64_t size) 181 1.2 rin { 182 1.2 rin const char *start = ptr, *end = start + size; 183 1.2 rin const vaddr_t startva = trunc_page((vaddr_t)(uintptr_t)start); 184 1.2 rin const vaddr_t endva = round_page((vaddr_t)(uintptr_t)end); 185 1.2 rin const vsize_t sz = endva - startva; 186 1.2 rin 187 1.2 rin pmap_kremove(startva, sz); 188 1.2 rin pmap_update(pmap_kernel()); 189 1.2 rin 190 1.2 rin uvm_km_free(kernel_map, startva, sz, UVM_KMF_VAONLY); 191 1.2 rin } 192 1.2 rin 193 1.3 rin char * 194 1.3 rin fdt_get_bootargs(void) 195 1.3 rin { 196 1.3 rin const int chosen = OF_finddevice("/chosen"); 197 1.3 rin 198 1.3 rin if (chosen >= 0) 199 1.3 rin OF_getprop(chosen, "bootargs", bootargs, sizeof(bootargs)); 200 1.3 rin return bootargs; 201 1.3 rin } 202 1.3 rin 203 1.2 rin void 204 1.2 rin fdt_probe_initrd(void) 205 1.2 rin { 206 1.2 rin 207 1.2 rin #ifdef MEMORY_DISK_DYNAMIC 208 1.2 rin fdt_probe_range("linux,initrd-start", "linux,initrd-end", 209 1.2 rin &initrd_start, &initrd_end); 210 1.2 rin #endif 211 1.2 rin } 212 1.2 rin 213 1.2 rin void 214 1.2 rin fdt_setup_initrd(void) 215 1.2 rin { 216 1.2 rin #ifdef MEMORY_DISK_DYNAMIC 217 1.2 rin void *md_start; 218 1.2 rin uint64_t initrd_size; 219 1.2 rin 220 1.2 rin md_start = fdt_map_range(initrd_start, initrd_end, &initrd_size, 221 1.2 rin "initrd"); 222 1.2 rin if (md_start == NULL) 223 1.2 rin return; 224 1.2 rin md_root_setconf(md_start, initrd_size); 225 1.2 rin #endif 226 1.2 rin } 227 1.2 rin 228 1.2 rin void 229 1.2 rin fdt_reserve_initrd(void) 230 1.2 rin { 231 1.2 rin #ifdef MEMORY_DISK_DYNAMIC 232 1.2 rin const uint64_t initrd_size = 233 1.2 rin round_page(initrd_end) - trunc_page(initrd_start); 234 1.2 rin 235 1.2 rin if (initrd_size > 0) 236 1.2 rin fdt_memory_remove_range(trunc_page(initrd_start), initrd_size); 237 1.2 rin #endif 238 1.2 rin } 239 1.2 rin 240 1.2 rin void 241 1.2 rin fdt_probe_rndseed(void) 242 1.2 rin { 243 1.2 rin 244 1.2 rin fdt_probe_range("netbsd,rndseed-start", "netbsd,rndseed-end", 245 1.2 rin &rndseed_start, &rndseed_end); 246 1.2 rin } 247 1.2 rin 248 1.2 rin void 249 1.2 rin fdt_setup_rndseed(void) 250 1.2 rin { 251 1.2 rin uint64_t rndseed_size; 252 1.2 rin void *rndseed; 253 1.2 rin 254 1.2 rin rndseed = fdt_map_range(rndseed_start, rndseed_end, &rndseed_size, 255 1.2 rin "rndseed"); 256 1.2 rin if (rndseed == NULL) 257 1.2 rin return; 258 1.2 rin rnd_seed(rndseed, rndseed_size); 259 1.2 rin fdt_unmap_range(rndseed, rndseed_size); 260 1.2 rin } 261 1.2 rin 262 1.2 rin void 263 1.2 rin fdt_reserve_rndseed(void) 264 1.2 rin { 265 1.2 rin const uint64_t rndseed_size = 266 1.2 rin round_page(rndseed_end) - trunc_page(rndseed_start); 267 1.2 rin 268 1.2 rin if (rndseed_size > 0) 269 1.2 rin fdt_memory_remove_range(trunc_page(rndseed_start), 270 1.2 rin rndseed_size); 271 1.2 rin } 272 1.2 rin 273 1.2 rin void 274 1.2 rin fdt_probe_efirng(void) 275 1.2 rin { 276 1.2 rin 277 1.2 rin fdt_probe_range("netbsd,efirng-start", "netbsd,efirng-end", 278 1.2 rin &efirng_start, &efirng_end); 279 1.2 rin } 280 1.2 rin 281 1.2 rin void 282 1.2 rin fdt_setup_efirng(void) 283 1.2 rin { 284 1.2 rin uint64_t efirng_size; 285 1.2 rin void *efirng; 286 1.2 rin 287 1.2 rin efirng = fdt_map_range(efirng_start, efirng_end, &efirng_size, 288 1.2 rin "efirng"); 289 1.2 rin if (efirng == NULL) 290 1.2 rin return; 291 1.2 rin 292 1.2 rin rnd_attach_source(&efirng_source, "efirng", RND_TYPE_RNG, 293 1.2 rin RND_FLAG_DEFAULT); 294 1.2 rin 295 1.2 rin /* 296 1.2 rin * We don't really have specific information about the physical 297 1.2 rin * process underlying the data provided by the firmware via the 298 1.2 rin * EFI RNG API, so the entropy estimate here is heuristic. 299 1.2 rin * What efiboot provides us is up to 4096 bytes of data from 300 1.2 rin * the EFI RNG API, although in principle it may return short. 301 1.2 rin * 302 1.2 rin * The UEFI Specification (2.8 Errata A, February 2020[1]) says 303 1.2 rin * 304 1.2 rin * When a Deterministic Random Bit Generator (DRBG) is 305 1.2 rin * used on the output of a (raw) entropy source, its 306 1.2 rin * security level must be at least 256 bits. 307 1.2 rin * 308 1.2 rin * It's not entirely clear whether `it' refers to the DRBG or 309 1.2 rin * the entropy source; if it refers to the DRBG, it's not 310 1.2 rin * entirely clear how ANSI X9.31 3DES, one of the options for 311 1.2 rin * DRBG in the UEFI spec, can provide a `256-bit security 312 1.2 rin * level' because it has only 232 bits of inputs (three 56-bit 313 1.2 rin * keys and one 64-bit block). That said, even if it provides 314 1.2 rin * only 232 bits of entropy, that's enough to prevent all 315 1.2 rin * attacks and we probably get a few more bits from sampling 316 1.2 rin * the clock anyway. 317 1.2 rin * 318 1.2 rin * In the event we get raw samples, e.g. the bits sampled by a 319 1.2 rin * ring oscillator, we hope that the samples have at least half 320 1.2 rin * a bit of entropy per bit of data -- and efiboot tries to 321 1.2 rin * draw 4096 bytes to provide plenty of slop. Hence we divide 322 1.2 rin * the total number of bits by two and clamp at 256. There are 323 1.2 rin * ways this could go wrong, but on most machines it should 324 1.2 rin * behave reasonably. 325 1.2 rin * 326 1.2 rin * [1] https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_A_Feb14.pdf 327 1.2 rin */ 328 1.2 rin rnd_add_data(&efirng_source, efirng, efirng_size, 329 1.2 rin MIN(256, efirng_size*NBBY/2)); 330 1.2 rin 331 1.2 rin explicit_memset(efirng, 0, efirng_size); 332 1.2 rin fdt_unmap_range(efirng, efirng_size); 333 1.2 rin } 334 1.2 rin 335 1.2 rin void 336 1.2 rin fdt_reserve_efirng(void) 337 1.2 rin { 338 1.2 rin const uint64_t efirng_size = 339 1.2 rin round_page(efirng_end) - trunc_page(efirng_start); 340 1.2 rin 341 1.2 rin if (efirng_size > 0) 342 1.2 rin fdt_memory_remove_range(trunc_page(efirng_start), efirng_size); 343 1.2 rin } 344 1.2 rin 345 1.2 rin #ifdef EFI_RUNTIME 346 1.2 rin void 347 1.2 rin fdt_map_efi_runtime(const char *prop, enum cpu_efirt_mem_type type) 348 1.2 rin { 349 1.2 rin int len; 350 1.2 rin 351 1.2 rin const int chosen_off = fdt_path_offset(fdtbus_get_data(), "/chosen"); 352 1.2 rin if (chosen_off < 0) 353 1.2 rin return; 354 1.2 rin 355 1.2 rin const uint64_t *map = fdt_getprop(fdtbus_get_data(), chosen_off, prop, &len); 356 1.2 rin if (map == NULL) 357 1.2 rin return; 358 1.2 rin 359 1.2 rin while (len >= 24) { 360 1.2 rin const paddr_t pa = be64toh(map[0]); 361 1.2 rin const vaddr_t va = be64toh(map[1]); 362 1.2 rin const size_t sz = be64toh(map[2]); 363 1.2 rin #if 0 364 1.2 rin VPRINTF("%s: %s %#" PRIxPADDR "-%#" PRIxVADDR " (%#" PRIxVADDR 365 1.2 rin "-%#" PRIxVSIZE ")\n", __func__, prop, pa, pa + sz - 1, 366 1.2 rin va, va + sz - 1); 367 1.2 rin #endif 368 1.2 rin cpu_efirt_map_range(va, pa, sz, type); 369 1.2 rin map += 3; 370 1.2 rin len -= 24; 371 1.2 rin } 372 1.2 rin } 373 1.2 rin #endif 374 1.1 skrll 375 1.1 skrll void 376 1.1 skrll fdt_update_stdout_path(void *fdt, const char *boot_args) 377 1.1 skrll { 378 1.1 skrll const char *stdout_path; 379 1.1 skrll char buf[256]; 380 1.1 skrll 381 1.1 skrll const int chosen_off = fdt_path_offset(fdt, "/chosen"); 382 1.1 skrll if (chosen_off == -1) 383 1.1 skrll return; 384 1.1 skrll 385 1.1 skrll if (optstr_get_string(boot_args, "stdout-path", &stdout_path) == false) 386 1.1 skrll return; 387 1.1 skrll 388 1.1 skrll const char *ep = strchr(stdout_path, ' '); 389 1.1 skrll size_t stdout_path_len = ep ? (ep - stdout_path) : strlen(stdout_path); 390 1.1 skrll if (stdout_path_len >= sizeof(buf)) 391 1.1 skrll return; 392 1.1 skrll 393 1.1 skrll strncpy(buf, stdout_path, stdout_path_len); 394 1.1 skrll buf[stdout_path_len] = '\0'; 395 1.1 skrll fdt_setprop(fdt, chosen_off, "stdout-path", 396 1.1 skrll buf, stdout_path_len + 1); 397 1.1 skrll } 398 1.5 skrll 399 1.5 skrll static void 400 1.5 skrll fdt_detect_root_device(device_t dev) 401 1.5 skrll { 402 1.5 skrll int error, len; 403 1.5 skrll 404 1.5 skrll const int chosen = OF_finddevice("/chosen"); 405 1.5 skrll if (chosen < 0) 406 1.5 skrll return; 407 1.5 skrll 408 1.5 skrll if (of_hasprop(chosen, "netbsd,mbr") && 409 1.5 skrll of_hasprop(chosen, "netbsd,partition")) { 410 1.5 skrll struct mbr_sector mbr; 411 1.5 skrll uint8_t buf[DEV_BSIZE]; 412 1.5 skrll uint8_t hash[16]; 413 1.5 skrll const uint8_t *rhash; 414 1.5 skrll struct vnode *vp; 415 1.5 skrll MD5_CTX md5ctx; 416 1.5 skrll size_t resid; 417 1.5 skrll u_int part; 418 1.5 skrll 419 1.5 skrll /* 420 1.5 skrll * The bootloader has passed in a partition index and MD5 hash 421 1.5 skrll * of the MBR sector. Read the MBR of this device, calculate the 422 1.5 skrll * hash, and compare it with the value passed in. 423 1.5 skrll */ 424 1.5 skrll rhash = fdtbus_get_prop(chosen, "netbsd,mbr", &len); 425 1.5 skrll if (rhash == NULL || len != 16) 426 1.5 skrll return; 427 1.5 skrll of_getprop_uint32(chosen, "netbsd,partition", &part); 428 1.5 skrll if (part >= MAXPARTITIONS) 429 1.5 skrll return; 430 1.5 skrll 431 1.5 skrll vp = opendisk(dev); 432 1.5 skrll if (!vp) 433 1.5 skrll return; 434 1.5 skrll error = vn_rdwr(UIO_READ, vp, buf, sizeof(buf), 0, UIO_SYSSPACE, 435 1.5 skrll IO_NODELOCKED, NOCRED, &resid, NULL); 436 1.5 skrll VOP_CLOSE(vp, FREAD, NOCRED); 437 1.5 skrll vput(vp); 438 1.5 skrll 439 1.5 skrll if (error != 0) 440 1.5 skrll return; 441 1.5 skrll 442 1.5 skrll memcpy(&mbr, buf, sizeof(mbr)); 443 1.5 skrll MD5Init(&md5ctx); 444 1.5 skrll MD5Update(&md5ctx, (void *)&mbr, sizeof(mbr)); 445 1.5 skrll MD5Final(hash, &md5ctx); 446 1.5 skrll 447 1.5 skrll if (memcmp(rhash, hash, 16) == 0) { 448 1.5 skrll booted_device = dev; 449 1.5 skrll booted_partition = part; 450 1.5 skrll } 451 1.5 skrll 452 1.5 skrll return; 453 1.5 skrll } 454 1.5 skrll 455 1.5 skrll if (of_hasprop(chosen, "netbsd,gpt-guid")) { 456 1.5 skrll const struct uuid *guid = 457 1.5 skrll fdtbus_get_prop(chosen, "netbsd,gpt-guid", &len); 458 1.5 skrll 459 1.5 skrll if (guid == NULL || len != 16) 460 1.5 skrll return; 461 1.5 skrll 462 1.5 skrll char guidstr[UUID_STR_LEN]; 463 1.5 skrll uuid_snprintf(guidstr, sizeof(guidstr), guid); 464 1.5 skrll 465 1.5 skrll device_t dv = dkwedge_find_by_wname(guidstr); 466 1.5 skrll if (dv != NULL) 467 1.5 skrll booted_device = dv; 468 1.5 skrll 469 1.5 skrll return; 470 1.5 skrll } 471 1.5 skrll 472 1.5 skrll if (of_hasprop(chosen, "netbsd,gpt-label")) { 473 1.5 skrll const char *label = fdtbus_get_string(chosen, "netbsd,gpt-label"); 474 1.5 skrll if (label == NULL || *label == '\0') 475 1.5 skrll return; 476 1.5 skrll 477 1.5 skrll device_t dv = dkwedge_find_by_wname(label); 478 1.5 skrll if (dv != NULL) 479 1.5 skrll booted_device = dv; 480 1.5 skrll 481 1.5 skrll return; 482 1.5 skrll } 483 1.5 skrll 484 1.5 skrll if (of_hasprop(chosen, "netbsd,booted-mac-address")) { 485 1.5 skrll const uint8_t *macaddr = 486 1.5 skrll fdtbus_get_prop(chosen, "netbsd,booted-mac-address", &len); 487 1.5 skrll struct ifnet *ifp; 488 1.5 skrll 489 1.5 skrll if (macaddr == NULL || len != 6) 490 1.5 skrll return; 491 1.5 skrll 492 1.5 skrll int s = pserialize_read_enter(); 493 1.5 skrll IFNET_READER_FOREACH(ifp) { 494 1.5 skrll if (memcmp(macaddr, CLLADDR(ifp->if_sadl), len) == 0) { 495 1.5 skrll device_t dv = device_find_by_xname(ifp->if_xname); 496 1.5 skrll if (dv != NULL) 497 1.5 skrll booted_device = dv; 498 1.5 skrll break; 499 1.5 skrll } 500 1.5 skrll } 501 1.5 skrll pserialize_read_exit(s); 502 1.5 skrll 503 1.5 skrll return; 504 1.5 skrll } 505 1.5 skrll } 506 1.5 skrll 507 1.5 skrll void 508 1.5 skrll fdt_cpu_rootconf(void) 509 1.5 skrll { 510 1.5 skrll device_t dev; 511 1.5 skrll deviter_t di; 512 1.5 skrll 513 1.5 skrll if (booted_device != NULL) 514 1.5 skrll return; 515 1.5 skrll 516 1.5 skrll for (dev = deviter_first(&di, 0); dev; dev = deviter_next(&di)) { 517 1.5 skrll if (device_class(dev) != DV_DISK) 518 1.5 skrll continue; 519 1.5 skrll 520 1.5 skrll fdt_detect_root_device(dev); 521 1.5 skrll 522 1.5 skrll if (booted_device != NULL) 523 1.5 skrll break; 524 1.5 skrll } 525 1.5 skrll deviter_release(&di); 526 1.5 skrll } 527