1 /* $OpenBSD: efiboot.c,v 1.50 2024/02/23 21:52:12 kettenis Exp $ */ 2 3 /* 4 * Copyright (c) 2015 YASUOKA Masahiko <yasuoka@yasuoka.net> 5 * Copyright (c) 2016 Mark Kettenis 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/param.h> 21 #include <sys/queue.h> 22 #include <sys/stat.h> 23 #include <dev/cons.h> 24 #include <sys/disklabel.h> 25 26 #include <efi.h> 27 #include <efiapi.h> 28 #include <efiprot.h> 29 #include <eficonsctl.h> 30 31 #include <dev/biovar.h> 32 #include <dev/softraidvar.h> 33 34 #include <lib/libkern/libkern.h> 35 #include <lib/libsa/softraid.h> 36 #include <stand/boot/cmd.h> 37 38 #include "libsa.h" 39 #include "disk.h" 40 #include "softraid_arm64.h" 41 42 #include "efidev.h" 43 #include "efiboot.h" 44 #include "fdt.h" 45 46 EFI_SYSTEM_TABLE *ST; 47 EFI_BOOT_SERVICES *BS; 48 EFI_RUNTIME_SERVICES *RS; 49 EFI_HANDLE IH, efi_bootdp; 50 void *fdt_sys = NULL; 51 void *fdt_override = NULL; 52 size_t fdt_override_size; 53 void *smbios = NULL; 54 55 EFI_PHYSICAL_ADDRESS heap; 56 UINTN heapsiz = 1 * 1024 * 1024; 57 EFI_MEMORY_DESCRIPTOR *mmap; 58 UINTN mmap_key; 59 UINTN mmap_ndesc; 60 UINTN mmap_descsiz; 61 UINT32 mmap_version; 62 63 static EFI_GUID imgp_guid = LOADED_IMAGE_PROTOCOL; 64 static EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL; 65 static EFI_GUID devp_guid = DEVICE_PATH_PROTOCOL; 66 static EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; 67 static EFI_GUID fdt_guid = FDT_TABLE_GUID; 68 static EFI_GUID smbios_guid = SMBIOS_TABLE_GUID; 69 static EFI_GUID smbios3_guid = SMBIOS3_TABLE_GUID; 70 71 #define efi_guidcmp(_a, _b) memcmp((_a), (_b), sizeof(EFI_GUID)) 72 73 int efi_device_path_depth(EFI_DEVICE_PATH *dp, int); 74 int efi_device_path_ncmp(EFI_DEVICE_PATH *, EFI_DEVICE_PATH *, int); 75 static void efi_heap_init(void); 76 static void efi_memprobe_internal(void); 77 static void efi_timer_init(void); 78 static void efi_timer_cleanup(void); 79 static EFI_STATUS efi_memprobe_find(UINTN, UINTN, EFI_MEMORY_TYPE, 80 EFI_PHYSICAL_ADDRESS *); 81 void *efi_fdt(void); 82 int fdt_load_override(char *); 83 extern void smbios_init(void *); 84 85 EFI_STATUS 86 efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) 87 { 88 extern char *progname; 89 EFI_LOADED_IMAGE *imgp; 90 EFI_DEVICE_PATH *dp = NULL; 91 EFI_STATUS status; 92 int i; 93 94 ST = systab; 95 BS = ST->BootServices; 96 RS = ST->RuntimeServices; 97 IH = image; 98 99 /* disable reset by watchdog after 5 minutes */ 100 BS->SetWatchdogTimer(0, 0, 0, NULL); 101 102 status = BS->HandleProtocol(image, &imgp_guid, 103 (void **)&imgp); 104 if (status == EFI_SUCCESS) 105 status = BS->HandleProtocol(imgp->DeviceHandle, &devp_guid, 106 (void **)&dp); 107 if (status == EFI_SUCCESS) 108 efi_bootdp = dp; 109 110 for (i = 0; i < ST->NumberOfTableEntries; i++) { 111 if (efi_guidcmp(&fdt_guid, 112 &ST->ConfigurationTable[i].VendorGuid) == 0) 113 fdt_sys = ST->ConfigurationTable[i].VendorTable; 114 if (efi_guidcmp(&smbios_guid, 115 &ST->ConfigurationTable[i].VendorGuid) == 0) 116 smbios = ST->ConfigurationTable[i].VendorTable; 117 if (efi_guidcmp(&smbios3_guid, 118 &ST->ConfigurationTable[i].VendorGuid) == 0) 119 smbios = ST->ConfigurationTable[i].VendorTable; 120 } 121 fdt_init(fdt_sys); 122 123 progname = "BOOTAA64"; 124 125 boot(0); 126 127 return (EFI_SUCCESS); 128 } 129 130 static SIMPLE_TEXT_OUTPUT_INTERFACE *conout; 131 static SIMPLE_INPUT_INTERFACE *conin; 132 133 /* 134 * The device majors for these don't match the ones used by the 135 * kernel. That's fine. They're just used as an index into the cdevs 136 * array and never passed on to the kernel. 137 */ 138 static dev_t serial = makedev(1, 0); 139 static dev_t framebuffer = makedev(2, 0); 140 141 static char framebuffer_path[128]; 142 143 void 144 efi_cons_probe(struct consdev *cn) 145 { 146 cn->cn_pri = CN_MIDPRI; 147 cn->cn_dev = makedev(0, 0); 148 } 149 150 void 151 efi_cons_init(struct consdev *cp) 152 { 153 conin = ST->ConIn; 154 conout = ST->ConOut; 155 } 156 157 int 158 efi_cons_getc(dev_t dev) 159 { 160 EFI_INPUT_KEY key; 161 EFI_STATUS status; 162 #if 0 163 UINTN dummy; 164 #endif 165 static int lastchar = 0; 166 167 if (lastchar) { 168 int r = lastchar; 169 if ((dev & 0x80) == 0) 170 lastchar = 0; 171 return (r); 172 } 173 174 status = conin->ReadKeyStroke(conin, &key); 175 while (status == EFI_NOT_READY || key.UnicodeChar == 0) { 176 if (dev & 0x80) 177 return (0); 178 /* 179 * XXX The implementation of WaitForEvent() in U-boot 180 * is broken and neverreturns. 181 */ 182 #if 0 183 BS->WaitForEvent(1, &conin->WaitForKey, &dummy); 184 #endif 185 status = conin->ReadKeyStroke(conin, &key); 186 } 187 188 if (dev & 0x80) 189 lastchar = key.UnicodeChar; 190 191 return (key.UnicodeChar); 192 } 193 194 void 195 efi_cons_putc(dev_t dev, int c) 196 { 197 CHAR16 buf[2]; 198 199 if (c == '\n') 200 efi_cons_putc(dev, '\r'); 201 202 buf[0] = c; 203 buf[1] = 0; 204 205 conout->OutputString(conout, buf); 206 } 207 208 void 209 efi_com_probe(struct consdev *cn) 210 { 211 cn->cn_pri = CN_LOWPRI; 212 cn->cn_dev = serial; 213 } 214 215 void 216 efi_com_init(struct consdev *cn) 217 { 218 conin = ST->ConIn; 219 conout = ST->ConOut; 220 } 221 222 int 223 efi_com_getc(dev_t dev) 224 { 225 return efi_cons_getc(dev); 226 } 227 228 void 229 efi_com_putc(dev_t dev, int c) 230 { 231 efi_cons_putc(dev, c); 232 } 233 234 void 235 efi_fb_probe(struct consdev *cn) 236 { 237 cn->cn_pri = CN_LOWPRI; 238 cn->cn_dev = framebuffer; 239 } 240 241 void 242 efi_fb_init(struct consdev *cn) 243 { 244 conin = ST->ConIn; 245 conout = ST->ConOut; 246 } 247 248 int 249 efi_fb_getc(dev_t dev) 250 { 251 return efi_cons_getc(dev); 252 } 253 254 void 255 efi_fb_putc(dev_t dev, int c) 256 { 257 efi_cons_putc(dev, c); 258 } 259 260 static void 261 efi_heap_init(void) 262 { 263 EFI_STATUS status; 264 265 status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, 266 EFI_SIZE_TO_PAGES(heapsiz), &heap); 267 if (status != EFI_SUCCESS) 268 panic("BS->AllocatePages()"); 269 } 270 271 struct disklist_lh disklist; 272 struct diskinfo *bootdev_dip; 273 274 void 275 efi_diskprobe(void) 276 { 277 int i, bootdev = 0, depth = -1; 278 UINTN sz; 279 EFI_STATUS status; 280 EFI_HANDLE *handles = NULL; 281 EFI_BLOCK_IO *blkio; 282 EFI_BLOCK_IO_MEDIA *media; 283 struct diskinfo *di; 284 EFI_DEVICE_PATH *dp; 285 286 TAILQ_INIT(&disklist); 287 288 sz = 0; 289 status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz, 0); 290 if (status == EFI_BUFFER_TOO_SMALL) { 291 handles = alloc(sz); 292 status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz, 293 handles); 294 } 295 if (handles == NULL || EFI_ERROR(status)) 296 return; 297 298 if (efi_bootdp != NULL) 299 depth = efi_device_path_depth(efi_bootdp, MEDIA_DEVICE_PATH); 300 301 /* 302 * U-Boot incorrectly represents devices with a single 303 * MEDIA_DEVICE_PATH component. In that case include that 304 * component into the matching, otherwise we'll blindly select 305 * the first device. 306 */ 307 if (depth == 0) 308 depth = 1; 309 310 for (i = 0; i < sz / sizeof(EFI_HANDLE); i++) { 311 status = BS->HandleProtocol(handles[i], &blkio_guid, 312 (void **)&blkio); 313 if (EFI_ERROR(status)) 314 panic("BS->HandleProtocol() returns %d", status); 315 316 media = blkio->Media; 317 if (media->LogicalPartition || !media->MediaPresent) 318 continue; 319 di = alloc(sizeof(struct diskinfo)); 320 efid_init(di, blkio); 321 322 if (efi_bootdp == NULL || depth == -1 || bootdev != 0) 323 goto next; 324 status = BS->HandleProtocol(handles[i], &devp_guid, 325 (void **)&dp); 326 if (EFI_ERROR(status)) 327 goto next; 328 if (efi_device_path_ncmp(efi_bootdp, dp, depth) == 0) { 329 TAILQ_INSERT_HEAD(&disklist, di, list); 330 bootdev_dip = di; 331 bootdev = 1; 332 continue; 333 } 334 next: 335 TAILQ_INSERT_TAIL(&disklist, di, list); 336 } 337 338 free(handles, sz); 339 340 /* Print available disks and probe for softraid. */ 341 i = 0; 342 printf("disks:"); 343 TAILQ_FOREACH(di, &disklist, list) { 344 printf(" sd%d%s", i, di == bootdev_dip ? "*" : ""); 345 i++; 346 } 347 srprobe(); 348 printf("\n"); 349 } 350 351 /* 352 * Determine the number of nodes up to, but not including, the first 353 * node of the specified type. 354 */ 355 int 356 efi_device_path_depth(EFI_DEVICE_PATH *dp, int dptype) 357 { 358 int i; 359 360 for (i = 0; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp), i++) { 361 if (DevicePathType(dp) == dptype) 362 return (i); 363 } 364 365 return (i); 366 } 367 368 int 369 efi_device_path_ncmp(EFI_DEVICE_PATH *dpa, EFI_DEVICE_PATH *dpb, int deptn) 370 { 371 int i, cmp; 372 373 for (i = 0; i < deptn; i++) { 374 if (IsDevicePathEnd(dpa) || IsDevicePathEnd(dpb)) 375 return ((IsDevicePathEnd(dpa) && IsDevicePathEnd(dpb)) 376 ? 0 : (IsDevicePathEnd(dpa))? -1 : 1); 377 cmp = DevicePathNodeLength(dpa) - DevicePathNodeLength(dpb); 378 if (cmp) 379 return (cmp); 380 cmp = memcmp(dpa, dpb, DevicePathNodeLength(dpa)); 381 if (cmp) 382 return (cmp); 383 dpa = NextDevicePathNode(dpa); 384 dpb = NextDevicePathNode(dpb); 385 } 386 387 return (0); 388 } 389 390 void 391 efi_framebuffer(void) 392 { 393 EFI_GRAPHICS_OUTPUT *gop; 394 EFI_STATUS status; 395 void *node, *child; 396 uint32_t acells, scells; 397 uint64_t base, size; 398 uint32_t reg[4]; 399 uint32_t width, height, stride; 400 char *format; 401 char *prop; 402 403 /* 404 * Don't create a "simple-framebuffer" node if we already have 405 * one. Besides "/chosen", we also check under "/" since that 406 * is where the Raspberry Pi firmware puts it. 407 */ 408 node = fdt_find_node("/chosen"); 409 for (child = fdt_child_node(node); child; 410 child = fdt_next_node(child)) { 411 if (!fdt_node_is_compatible(child, "simple-framebuffer")) 412 continue; 413 if (!fdt_node_property(child, "status", &prop) || 414 strcmp(prop, "okay") == 0) { 415 strlcpy(framebuffer_path, "/chosen/", 416 sizeof(framebuffer_path)); 417 strlcat(framebuffer_path, fdt_node_name(child), 418 sizeof(framebuffer_path)); 419 return; 420 } 421 } 422 node = fdt_find_node("/"); 423 for (child = fdt_child_node(node); child; 424 child = fdt_next_node(child)) { 425 if (!fdt_node_is_compatible(child, "simple-framebuffer")) 426 continue; 427 if (!fdt_node_property(child, "status", &prop) || 428 strcmp(prop, "okay") == 0) { 429 strlcpy(framebuffer_path, "/", 430 sizeof(framebuffer_path)); 431 strlcat(framebuffer_path, fdt_node_name(child), 432 sizeof(framebuffer_path)); 433 return; 434 } 435 } 436 437 status = BS->LocateProtocol(&gop_guid, NULL, (void **)&gop); 438 if (status != EFI_SUCCESS) 439 return; 440 441 /* Paranoia! */ 442 if (gop == NULL || gop->Mode == NULL || gop->Mode->Info == NULL) 443 return; 444 445 /* We only support 32-bit pixel modes for now. */ 446 switch (gop->Mode->Info->PixelFormat) { 447 case PixelRedGreenBlueReserved8BitPerColor: 448 format = "x8b8g8r8"; 449 break; 450 case PixelBlueGreenRedReserved8BitPerColor: 451 format = "x8r8g8b8"; 452 break; 453 default: 454 return; 455 } 456 457 base = gop->Mode->FrameBufferBase; 458 size = gop->Mode->FrameBufferSize; 459 width = htobe32(gop->Mode->Info->HorizontalResolution); 460 height = htobe32(gop->Mode->Info->VerticalResolution); 461 stride = htobe32(gop->Mode->Info->PixelsPerScanLine * 4); 462 463 node = fdt_find_node("/"); 464 if (fdt_node_property_int(node, "#address-cells", &acells) != 1) 465 acells = 1; 466 if (fdt_node_property_int(node, "#size-cells", &scells) != 1) 467 scells = 1; 468 if (acells > 2 || scells > 2) 469 return; 470 if (acells >= 1) 471 reg[0] = htobe32(base); 472 if (acells == 2) { 473 reg[1] = reg[0]; 474 reg[0] = htobe32(base >> 32); 475 } 476 if (scells >= 1) 477 reg[acells] = htobe32(size); 478 if (scells == 2) { 479 reg[acells + 1] = reg[acells]; 480 reg[acells] = htobe32(size >> 32); 481 } 482 483 node = fdt_find_node("/chosen"); 484 fdt_node_add_node(node, "framebuffer", &child); 485 fdt_node_add_property(child, "status", "okay", strlen("okay") + 1); 486 fdt_node_add_property(child, "format", format, strlen(format) + 1); 487 fdt_node_add_property(child, "stride", &stride, 4); 488 fdt_node_add_property(child, "height", &height, 4); 489 fdt_node_add_property(child, "width", &width, 4); 490 fdt_node_add_property(child, "reg", reg, (acells + scells) * 4); 491 fdt_node_add_property(child, "compatible", 492 "simple-framebuffer", strlen("simple-framebuffer") + 1); 493 494 strlcpy(framebuffer_path, "/chosen/framebuffer", 495 sizeof(framebuffer_path)); 496 } 497 498 void 499 efi_console(void) 500 { 501 void *node; 502 503 if (major(cn_tab->cn_dev) == major(serial)) { 504 char *serial_path; 505 char alias[16]; 506 int len; 507 508 /* Construct alias and resolve it. */ 509 snprintf(alias, sizeof(alias), "serial%d", 510 minor(cn_tab->cn_dev)); 511 node = fdt_find_node("/aliases"); 512 len = fdt_node_property(node, alias, &serial_path); 513 if (len <= 0) 514 return; 515 516 /* Point stdout-path at the serial node. */ 517 node = fdt_find_node("/chosen"); 518 fdt_node_add_property(node, "stdout-path", 519 serial_path, strlen(serial_path) + 1); 520 } else if (major(cn_tab->cn_dev) == major(framebuffer)) { 521 if (strlen(framebuffer_path) == 0) 522 return; 523 524 /* Point stdout-path at the framebuffer node. */ 525 node = fdt_find_node("/chosen"); 526 fdt_node_add_property(node, "stdout-path", 527 framebuffer_path, strlen(framebuffer_path) + 1); 528 } 529 } 530 531 uint64_t dma_constraint[2] = { 0, -1 }; 532 533 void 534 efi_dma_constraint(void) 535 { 536 void *node; 537 char *prop; 538 uint32_t *propint; 539 uint64_t base, size; 540 uint32_t pacells, pscells; 541 uint32_t acells, scells; 542 int len; 543 544 node = fdt_find_node("/"); 545 if (fdt_node_property_int(node, "#address-cells", &pacells) != 1) 546 pacells = 1; 547 if (fdt_node_property_int(node, "#size-cells", &pscells) != 1) 548 pscells = 1; 549 if (pacells > 2 || pscells > 2) 550 return; 551 552 node = fdt_find_node("/soc"); 553 if (node != NULL) { 554 if (fdt_node_property_int(node, "#address-cells", &acells) != 1) 555 acells = pacells; 556 if (fdt_node_property_int(node, "#size-cells", &scells) != 1) 557 scells = pscells; 558 if (acells > 2 || scells > 2) 559 return; 560 561 len = fdt_node_property(node, "dma-ranges", &prop); 562 propint = (uint32_t *)prop; 563 if (len == (acells + pacells + scells) * sizeof(uint32_t)) { 564 base = betoh32(propint[acells]); 565 if (pacells == 2) 566 base = (base << 32) | 567 betoh32(propint[acells + 1]); 568 size = betoh32(propint[acells + pacells]); 569 if (scells == 2) 570 size = (size << 32) | 571 betoh32(propint[acells + pacells + 1]); 572 573 dma_constraint[0] = htobe64(base); 574 dma_constraint[1] = htobe64(base + size - 1); 575 } 576 } 577 578 /* 579 * Some SoC's have DMA constraints that aren't explicitly 580 * advertised. 581 */ 582 node = fdt_find_node("/"); 583 if (fdt_node_is_compatible(node, "brcm,bcm2711")) 584 dma_constraint[1] = htobe64(0x3bffffff); 585 if (fdt_node_is_compatible(node, "rockchip,rk3566") || 586 fdt_node_is_compatible(node, "rockchip,rk3568") || 587 fdt_node_is_compatible(node, "rockchip,rk3588") || 588 fdt_node_is_compatible(node, "rockchip,rk3588s")) 589 dma_constraint[1] = htobe64(0xffffffff); 590 if (fdt_node_is_compatible(node, "lenovo,thinkpad-x13s")) 591 dma_constraint[1] = htobe64(0xffffffff); 592 593 /* Pass DMA constraint. */ 594 node = fdt_find_node("/chosen"); 595 fdt_node_add_property(node, "openbsd,dma-constraint", 596 dma_constraint, sizeof(dma_constraint)); 597 } 598 599 int acpi = 0; 600 char *bootmac = NULL; 601 602 void * 603 efi_makebootargs(char *bootargs, int howto) 604 { 605 struct sr_boot_volume *bv; 606 u_char bootduid[8]; 607 u_char zero[8] = { 0 }; 608 uint64_t uefi_system_table = htobe64((uintptr_t)ST); 609 uint32_t boothowto = htobe32(howto); 610 EFI_PHYSICAL_ADDRESS addr; 611 void *node, *fdt; 612 size_t len; 613 614 fdt = efi_fdt(); 615 if (fdt == NULL || acpi) 616 fdt = efi_acpi(); 617 618 if (!fdt_get_size(fdt)) 619 return NULL; 620 621 len = roundup(fdt_get_size(fdt) + PAGE_SIZE, PAGE_SIZE); 622 if (BS->AllocatePages(AllocateAnyPages, EfiLoaderData, 623 EFI_SIZE_TO_PAGES(len), &addr) == EFI_SUCCESS) { 624 memcpy((void *)addr, fdt, fdt_get_size(fdt)); 625 ((struct fdt_head *)addr)->fh_size = htobe32(len); 626 fdt = (void *)addr; 627 } 628 629 if (!fdt_init(fdt)) 630 return NULL; 631 632 /* Create common nodes which might not exist when using mach dtb */ 633 node = fdt_find_node("/aliases"); 634 if (node == NULL) 635 fdt_node_add_node(fdt_find_node("/"), "aliases", &node); 636 node = fdt_find_node("/chosen"); 637 if (node == NULL) 638 fdt_node_add_node(fdt_find_node("/"), "chosen", &node); 639 640 node = fdt_find_node("/chosen"); 641 len = strlen(bootargs) + 1; 642 fdt_node_add_property(node, "bootargs", bootargs, len); 643 fdt_node_add_property(node, "openbsd,boothowto", 644 &boothowto, sizeof(boothowto)); 645 646 /* Pass DUID of the boot disk. */ 647 if (bootdev_dip) { 648 memcpy(&bootduid, bootdev_dip->disklabel.d_uid, 649 sizeof(bootduid)); 650 if (memcmp(bootduid, zero, sizeof(bootduid)) != 0) { 651 fdt_node_add_property(node, "openbsd,bootduid", 652 bootduid, sizeof(bootduid)); 653 } 654 655 if (bootdev_dip->sr_vol != NULL) { 656 bv = bootdev_dip->sr_vol; 657 fdt_node_add_property(node, "openbsd,sr-bootuuid", 658 &bv->sbv_uuid, sizeof(bv->sbv_uuid)); 659 if (bv->sbv_maskkey != NULL) 660 fdt_node_add_property(node, 661 "openbsd,sr-bootkey", bv->sbv_maskkey, 662 SR_CRYPTO_MAXKEYBYTES); 663 } 664 } 665 666 sr_clear_keys(); 667 668 /* Pass netboot interface address. */ 669 if (bootmac) 670 fdt_node_add_property(node, "openbsd,bootmac", bootmac, 6); 671 672 /* Pass EFI system table. */ 673 fdt_node_add_property(node, "openbsd,uefi-system-table", 674 &uefi_system_table, sizeof(uefi_system_table)); 675 676 /* Placeholders for EFI memory map. */ 677 fdt_node_add_property(node, "openbsd,uefi-mmap-start", zero, 8); 678 fdt_node_add_property(node, "openbsd,uefi-mmap-size", zero, 4); 679 fdt_node_add_property(node, "openbsd,uefi-mmap-desc-size", zero, 4); 680 fdt_node_add_property(node, "openbsd,uefi-mmap-desc-ver", zero, 4); 681 682 efi_framebuffer(); 683 efi_console(); 684 efi_dma_constraint(); 685 686 fdt_finalize(); 687 688 return fdt; 689 } 690 691 void 692 efi_updatefdt(void) 693 { 694 uint64_t uefi_mmap_start = htobe64((uintptr_t)mmap); 695 uint32_t uefi_mmap_size = htobe32(mmap_ndesc * mmap_descsiz); 696 uint32_t uefi_mmap_desc_size = htobe32(mmap_descsiz); 697 uint32_t uefi_mmap_desc_ver = htobe32(mmap_version); 698 void *node; 699 700 node = fdt_find_node("/chosen"); 701 if (!node) 702 return; 703 704 /* Pass EFI memory map. */ 705 fdt_node_set_property(node, "openbsd,uefi-mmap-start", 706 &uefi_mmap_start, sizeof(uefi_mmap_start)); 707 fdt_node_set_property(node, "openbsd,uefi-mmap-size", 708 &uefi_mmap_size, sizeof(uefi_mmap_size)); 709 fdt_node_set_property(node, "openbsd,uefi-mmap-desc-size", 710 &uefi_mmap_desc_size, sizeof(uefi_mmap_desc_size)); 711 fdt_node_set_property(node, "openbsd,uefi-mmap-desc-ver", 712 &uefi_mmap_desc_ver, sizeof(uefi_mmap_desc_ver)); 713 714 fdt_finalize(); 715 } 716 717 u_long efi_loadaddr; 718 719 void 720 machdep(void) 721 { 722 EFI_PHYSICAL_ADDRESS addr; 723 724 cninit(); 725 efi_heap_init(); 726 smbios_init(smbios); 727 728 /* 729 * The kernel expects to be loaded into a block of memory aligned 730 * on a 2MB boundary. We allocate a block of 64MB of memory, which 731 * gives us plenty of room for growth. 732 */ 733 if (efi_memprobe_find(EFI_SIZE_TO_PAGES(64 * 1024 * 1024), 734 0x200000, EfiLoaderCode, &addr) != EFI_SUCCESS) 735 printf("Can't allocate memory\n"); 736 efi_loadaddr = addr; 737 738 efi_timer_init(); 739 efi_diskprobe(); 740 efi_pxeprobe(); 741 } 742 743 void 744 efi_cleanup(void) 745 { 746 int retry; 747 EFI_STATUS status; 748 749 efi_timer_cleanup(); 750 751 /* retry once in case of failure */ 752 for (retry = 1; retry >= 0; retry--) { 753 efi_memprobe_internal(); /* sync the current map */ 754 efi_updatefdt(); 755 status = BS->ExitBootServices(IH, mmap_key); 756 if (status == EFI_SUCCESS) 757 break; 758 if (retry == 0) 759 panic("ExitBootServices failed (%d)", status); 760 } 761 } 762 763 void 764 _rtt(void) 765 { 766 #ifdef EFI_DEBUG 767 printf("Hit any key to reboot\n"); 768 efi_cons_getc(0); 769 #endif 770 RS->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); 771 for (;;) 772 continue; 773 } 774 775 /* 776 * U-Boot only implements the GetTime() Runtime Service if it has been 777 * configured with CONFIG_DM_RTC. Most board configurations don't 778 * include that option, so we can't use it to implement our boot 779 * prompt timeout. Instead we use timer events to simulate a clock 780 * that ticks ever second. 781 */ 782 783 EFI_EVENT timer; 784 int ticks; 785 786 static VOID 787 efi_timer(EFI_EVENT event, VOID *context) 788 { 789 ticks++; 790 } 791 792 static void 793 efi_timer_init(void) 794 { 795 EFI_STATUS status; 796 797 status = BS->CreateEvent(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, 798 efi_timer, NULL, &timer); 799 if (status == EFI_SUCCESS) 800 status = BS->SetTimer(timer, TimerPeriodic, 10000000); 801 if (EFI_ERROR(status)) 802 printf("Can't create timer\n"); 803 } 804 805 static void 806 efi_timer_cleanup(void) 807 { 808 BS->CloseEvent(timer); 809 } 810 811 time_t 812 getsecs(void) 813 { 814 return ticks; 815 } 816 817 /* 818 * Various device-related bits. 819 */ 820 821 void 822 devboot(dev_t dev, char *p) 823 { 824 struct sr_boot_volume *bv; 825 struct sr_boot_chunk *bc; 826 struct diskinfo *dip; 827 int sd_boot_vol = 0; 828 int sr_boot_vol = -1; 829 int part_type = FS_UNUSED; 830 831 if (bootdev_dip == NULL) { 832 strlcpy(p, "tftp0a", 7); 833 return; 834 } 835 836 /* 837 * If there is no BSD disklabel on the boot device, boot from 838 * the ESP instead. 839 */ 840 if ((bootdev_dip->flags & DISKINFO_FLAG_GOODLABEL) == 0) { 841 strlcpy(p, "esp0a", 6); 842 return; 843 } 844 845 TAILQ_FOREACH(dip, &disklist, list) { 846 if (bootdev_dip == dip) 847 break; 848 sd_boot_vol++; 849 } 850 851 /* 852 * Determine the partition type for the 'a' partition of the 853 * boot device. 854 */ 855 part_type = bootdev_dip->disklabel.d_partitions[0].p_fstype; 856 857 /* 858 * See if we booted from a disk that is a member of a bootable 859 * softraid volume. 860 */ 861 SLIST_FOREACH(bv, &sr_volumes, sbv_link) { 862 SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link) 863 if (bc->sbc_diskinfo == bootdev_dip) 864 sr_boot_vol = bv->sbv_unit; 865 if (sr_boot_vol != -1) 866 break; 867 } 868 869 if (sr_boot_vol != -1 && part_type != FS_BSDFFS) { 870 strlcpy(p, "sr0a", 5); 871 p[2] = '0' + sr_boot_vol; 872 return; 873 } 874 875 strlcpy(p, "sd0a", 5); 876 p[2] = '0' + sd_boot_vol; 877 } 878 879 const char cdevs[][4] = { "cons", "com", "fb" }; 880 const int ncdevs = nitems(cdevs); 881 882 int 883 cnspeed(dev_t dev, int sp) 884 { 885 return 115200; 886 } 887 888 char ttyname_buf[8]; 889 890 char * 891 ttyname(int fd) 892 { 893 snprintf(ttyname_buf, sizeof ttyname_buf, "%s%d", 894 cdevs[major(cn_tab->cn_dev)], minor(cn_tab->cn_dev)); 895 896 return ttyname_buf; 897 } 898 899 dev_t 900 ttydev(char *name) 901 { 902 int i, unit = -1; 903 char *no = name + strlen(name) - 1; 904 905 while (no >= name && *no >= '0' && *no <= '9') 906 unit = (unit < 0 ? 0 : (unit * 10)) + *no-- - '0'; 907 if (no < name || unit < 0) 908 return NODEV; 909 for (i = 0; i < ncdevs; i++) 910 if (strncmp(name, cdevs[i], no - name + 1) == 0) 911 return makedev(i, unit); 912 return NODEV; 913 } 914 915 #define MAXDEVNAME 16 916 917 /* 918 * Parse a device spec. 919 * 920 * [A-Za-z]*[0-9]*[A-Za-z]:file 921 * dev uint part 922 */ 923 int 924 devparse(const char *fname, int *dev, int *unit, int *part, const char **file) 925 { 926 const char *s; 927 928 *unit = 0; /* default to wd0a */ 929 *part = 0; 930 *dev = 0; 931 932 s = strchr(fname, ':'); 933 if (s != NULL) { 934 int devlen; 935 int i, u, p = 0; 936 struct devsw *dp; 937 char devname[MAXDEVNAME]; 938 939 devlen = s - fname; 940 if (devlen > MAXDEVNAME) 941 return (EINVAL); 942 943 /* extract device name */ 944 for (i = 0; isalpha(fname[i]) && (i < devlen); i++) 945 devname[i] = fname[i]; 946 devname[i] = 0; 947 948 if (!isdigit(fname[i])) 949 return (EUNIT); 950 951 /* device number */ 952 for (u = 0; isdigit(fname[i]) && (i < devlen); i++) 953 u = u * 10 + (fname[i] - '0'); 954 955 if (!isalpha(fname[i])) 956 return (EPART); 957 958 /* partition number */ 959 if (i < devlen) 960 p = fname[i++] - 'a'; 961 962 if (i != devlen) 963 return (ENXIO); 964 965 /* check device name */ 966 for (dp = devsw, i = 0; i < ndevs; dp++, i++) { 967 if (dp->dv_name && !strcmp(devname, dp->dv_name)) 968 break; 969 } 970 971 if (i >= ndevs) 972 return (ENXIO); 973 974 *unit = u; 975 *part = p; 976 *dev = i; 977 fname = ++s; 978 } 979 980 *file = fname; 981 982 return (0); 983 } 984 985 int 986 devopen(struct open_file *f, const char *fname, char **file) 987 { 988 struct devsw *dp; 989 int dev, unit, part, error; 990 991 error = devparse(fname, &dev, &unit, &part, (const char **)file); 992 if (error) 993 return (error); 994 995 dp = &devsw[dev]; 996 f->f_dev = dp; 997 998 if (strcmp("tftp", dp->dv_name) != 0) { 999 /* 1000 * Clear bootmac, to signal that we loaded this file from a 1001 * non-network device. 1002 */ 1003 bootmac = NULL; 1004 } 1005 1006 return (*dp->dv_open)(f, unit, part); 1007 } 1008 1009 static void 1010 efi_memprobe_internal(void) 1011 { 1012 EFI_STATUS status; 1013 UINTN mapkey, mmsiz, siz; 1014 UINT32 mmver; 1015 EFI_MEMORY_DESCRIPTOR *mm; 1016 int n; 1017 1018 free(mmap, mmap_ndesc * mmap_descsiz); 1019 1020 siz = 0; 1021 status = BS->GetMemoryMap(&siz, NULL, &mapkey, &mmsiz, &mmver); 1022 if (status != EFI_BUFFER_TOO_SMALL) 1023 panic("cannot get the size of memory map"); 1024 mm = alloc(siz); 1025 status = BS->GetMemoryMap(&siz, mm, &mapkey, &mmsiz, &mmver); 1026 if (status != EFI_SUCCESS) 1027 panic("cannot get the memory map"); 1028 n = siz / mmsiz; 1029 mmap = mm; 1030 mmap_key = mapkey; 1031 mmap_ndesc = n; 1032 mmap_descsiz = mmsiz; 1033 mmap_version = mmver; 1034 } 1035 1036 /* 1037 * 64-bit ARMs can have a much wider memory mapping, as in somewhere 1038 * after the 32-bit region. To cope with our alignment requirement, 1039 * use the memory table to find a place where we can fit. 1040 */ 1041 static EFI_STATUS 1042 efi_memprobe_find(UINTN pages, UINTN align, EFI_MEMORY_TYPE type, 1043 EFI_PHYSICAL_ADDRESS *addr) 1044 { 1045 EFI_MEMORY_DESCRIPTOR *mm; 1046 int i, j; 1047 1048 if (align < EFI_PAGE_SIZE) 1049 return EFI_INVALID_PARAMETER; 1050 1051 efi_memprobe_internal(); /* sync the current map */ 1052 1053 for (i = 0, mm = mmap; i < mmap_ndesc; 1054 i++, mm = NextMemoryDescriptor(mm, mmap_descsiz)) { 1055 if (mm->Type != EfiConventionalMemory) 1056 continue; 1057 1058 if (mm->NumberOfPages < pages) 1059 continue; 1060 1061 for (j = 0; j < mm->NumberOfPages; j++) { 1062 EFI_PHYSICAL_ADDRESS paddr; 1063 1064 if (mm->NumberOfPages - j < pages) 1065 break; 1066 1067 paddr = mm->PhysicalStart + (j * EFI_PAGE_SIZE); 1068 if (paddr & (align - 1)) 1069 continue; 1070 1071 if (BS->AllocatePages(AllocateAddress, type, 1072 pages, &paddr) == EFI_SUCCESS) { 1073 *addr = paddr; 1074 return EFI_SUCCESS; 1075 } 1076 } 1077 } 1078 return EFI_OUT_OF_RESOURCES; 1079 } 1080 1081 int 1082 mdrandom(char *buf, size_t buflen) 1083 { 1084 char *random; 1085 void *node; 1086 int i, len, ret = -1; 1087 1088 node = fdt_find_node("/chosen"); 1089 if (!node) 1090 return -1; 1091 1092 len = fdt_node_property(node, "rng-seed", &random); 1093 if (len > 0) { 1094 for (i = 0; i < buflen; i++) 1095 buf[i] ^= random[i % len]; 1096 ret = 0; 1097 } 1098 1099 len = fdt_node_property(node, "kaslr-seed", &random); 1100 if (len > 0) { 1101 for (i = 0; i < buflen; i++) 1102 buf[i] ^= random[i % len]; 1103 ret = 0; 1104 } 1105 1106 return ret; 1107 } 1108 1109 #define FW_PATH "/etc/firmware/dtb/" 1110 1111 void * 1112 efi_fdt(void) 1113 { 1114 extern char *hw_vendor, *hw_prod; 1115 1116 /* 'mach dtb' has precedence */ 1117 if (fdt_override != NULL) 1118 return fdt_override; 1119 1120 /* Return system provided one */ 1121 if (hw_vendor == NULL || hw_prod == NULL) 1122 return fdt_sys; 1123 1124 if (strcmp(hw_vendor, "LENOVO") == 0) { 1125 if (strncmp(hw_prod, "21BX", 4) == 0 || 1126 strncmp(hw_prod, "21BY", 4) == 0) { 1127 fdt_load_override(FW_PATH 1128 "qcom/sc8280xp-lenovo-thinkpad-x13s.dtb"); 1129 /* TODO: find a better mechanism */ 1130 cnset(ttydev("fb0")); 1131 } 1132 } 1133 1134 return fdt_override ? fdt_override : fdt_sys; 1135 } 1136 1137 int 1138 fdt_load_override(char *file) 1139 { 1140 EFI_PHYSICAL_ADDRESS addr; 1141 char path[MAXPATHLEN]; 1142 struct stat sb; 1143 int fd; 1144 1145 if (file == NULL && fdt_override) { 1146 BS->FreePages((uint64_t)fdt_override, 1147 EFI_SIZE_TO_PAGES(fdt_override_size)); 1148 fdt_override = NULL; 1149 fdt_init(fdt_sys); 1150 return 0; 1151 } 1152 1153 snprintf(path, sizeof(path), "%s:%s", cmd.bootdev, file); 1154 1155 fd = open(path, O_RDONLY); 1156 if (fd < 0 || fstat(fd, &sb) == -1) { 1157 printf("cannot open %s\n", path); 1158 return 0; 1159 } 1160 if (efi_memprobe_find(EFI_SIZE_TO_PAGES(sb.st_size), 1161 PAGE_SIZE, EfiLoaderData, &addr) != EFI_SUCCESS) { 1162 printf("cannot allocate memory for %s\n", path); 1163 return 0; 1164 } 1165 if (read(fd, (void *)addr, sb.st_size) != sb.st_size) { 1166 printf("cannot read from %s\n", path); 1167 return 0; 1168 } 1169 1170 if (!fdt_init((void *)addr)) { 1171 printf("invalid device tree\n"); 1172 BS->FreePages(addr, EFI_SIZE_TO_PAGES(sb.st_size)); 1173 return 0; 1174 } 1175 1176 if (fdt_override) { 1177 BS->FreePages((uint64_t)fdt_override, 1178 EFI_SIZE_TO_PAGES(fdt_override_size)); 1179 fdt_override = NULL; 1180 } 1181 1182 fdt_override = (void *)addr; 1183 fdt_override_size = sb.st_size; 1184 return 0; 1185 } 1186 1187 /* 1188 * Commands 1189 */ 1190 1191 int Xacpi_efi(void); 1192 int Xdtb_efi(void); 1193 int Xexit_efi(void); 1194 int Xpoweroff_efi(void); 1195 1196 const struct cmd_table cmd_machine[] = { 1197 { "acpi", CMDT_CMD, Xacpi_efi }, 1198 { "dtb", CMDT_CMD, Xdtb_efi }, 1199 { "exit", CMDT_CMD, Xexit_efi }, 1200 { "poweroff", CMDT_CMD, Xpoweroff_efi }, 1201 { NULL, 0 } 1202 }; 1203 1204 int 1205 Xacpi_efi(void) 1206 { 1207 acpi = 1; 1208 return (0); 1209 } 1210 1211 int 1212 Xdtb_efi(void) 1213 { 1214 if (cmd.argc == 1) { 1215 fdt_load_override(NULL); 1216 return (0); 1217 } 1218 1219 if (cmd.argc != 2) { 1220 printf("dtb file\n"); 1221 return (0); 1222 } 1223 1224 return fdt_load_override(cmd.argv[1]); 1225 } 1226 1227 int 1228 Xexit_efi(void) 1229 { 1230 BS->Exit(IH, 0, 0, NULL); 1231 for (;;) 1232 continue; 1233 return (0); 1234 } 1235 1236 int 1237 Xpoweroff_efi(void) 1238 { 1239 RS->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL); 1240 return (0); 1241 } 1242