1 /*- 2 * Copyright (c) 1998 Robert Nordier 3 * All rights reserved. 4 * Copyright (c) 2001 Robert Drehmel 5 * All rights reserved. 6 * Copyright (c) 2014 Nathan Whitehorn 7 * All rights reserved. 8 * Copyright (c) 2015 Eric McCorkle 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms are freely 12 * permitted provided that the above copyright notice and this 13 * paragraph and the following disclaimer are duplicated in all 14 * such forms. 15 * 16 * This software is provided "AS IS" and without any express or 17 * implied warranties, including, without limitation, the implied 18 * warranties of merchantability and fitness for a particular 19 * purpose. 20 */ 21 22 #include <sys/cdefs.h> 23 24 #include <sys/param.h> 25 #include <machine/elf.h> 26 #include <machine/stdarg.h> 27 #include <stand.h> 28 29 #include <efi.h> 30 #include <eficonsctl.h> 31 32 #include <bootstrap.h> 33 #include "boot_module.h" 34 #include "paths.h" 35 36 struct arch_switch archsw; 37 struct fs_ops *file_system[] = { 38 NULL 39 }; 40 41 static const boot_module_t *boot_modules[] = 42 { 43 #ifdef EFI_ZFS_BOOT 44 &zfs_module, 45 #endif 46 #ifdef EFI_UFS_BOOT 47 &ufs_module 48 #endif 49 }; 50 51 #define NUM_BOOT_MODULES nitems(boot_modules) 52 /* The initial number of handles used to query EFI for partitions. */ 53 #define NUM_HANDLES_INIT 24 54 55 EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab); 56 57 EFI_SYSTEM_TABLE *systab; 58 EFI_BOOT_SERVICES *bs; 59 static EFI_HANDLE *image; 60 61 static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL; 62 static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL; 63 static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL; 64 static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID; 65 66 /* 67 * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures 68 * memory is correctly aligned avoiding EFI_INVALID_PARAMETER returns from 69 * EFI methods. 70 */ 71 void * 72 Malloc(size_t len, const char *file __unused, int line __unused) 73 { 74 void *out; 75 76 if (bs->AllocatePool(EfiLoaderData, len, &out) == EFI_SUCCESS) 77 return (out); 78 79 return (NULL); 80 } 81 82 void 83 Free(void *buf, const char *file __unused, int line __unused) 84 { 85 if (buf != NULL) 86 (void)bs->FreePool(buf); 87 } 88 89 /* 90 * nodes_match returns TRUE if the imgpath isn't NULL and the nodes match, 91 * FALSE otherwise. 92 */ 93 static BOOLEAN 94 nodes_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath) 95 { 96 int len; 97 98 if (imgpath == NULL || imgpath->Type != devpath->Type || 99 imgpath->SubType != devpath->SubType) 100 return (FALSE); 101 102 len = DevicePathNodeLength(imgpath); 103 if (len != DevicePathNodeLength(devpath)) 104 return (FALSE); 105 106 return (memcmp(imgpath, devpath, (size_t)len) == 0); 107 } 108 109 /* 110 * device_paths_match returns TRUE if the imgpath isn't NULL and all nodes 111 * in imgpath and devpath match up to their respective occurences of a 112 * media node, FALSE otherwise. 113 */ 114 static BOOLEAN 115 device_paths_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath) 116 { 117 118 if (imgpath == NULL) 119 return (FALSE); 120 121 while (!IsDevicePathEnd(imgpath) && !IsDevicePathEnd(devpath)) { 122 if (IsDevicePathType(imgpath, MEDIA_DEVICE_PATH) && 123 IsDevicePathType(devpath, MEDIA_DEVICE_PATH)) 124 return (TRUE); 125 126 if (!nodes_match(imgpath, devpath)) 127 return (FALSE); 128 129 imgpath = NextDevicePathNode(imgpath); 130 devpath = NextDevicePathNode(devpath); 131 } 132 133 return (FALSE); 134 } 135 136 /* 137 * devpath_last returns the last non-path end node in devpath. 138 */ 139 static EFI_DEVICE_PATH * 140 devpath_last(EFI_DEVICE_PATH *devpath) 141 { 142 143 while (!IsDevicePathEnd(NextDevicePathNode(devpath))) 144 devpath = NextDevicePathNode(devpath); 145 146 return (devpath); 147 } 148 149 /* 150 * devpath_node_str is a basic output method for a devpath node which 151 * only understands a subset of the available sub types. 152 * 153 * If we switch to UEFI 2.x then we should update it to use: 154 * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL. 155 */ 156 static int 157 devpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath) 158 { 159 160 switch (devpath->Type) { 161 case MESSAGING_DEVICE_PATH: 162 switch (devpath->SubType) { 163 case MSG_ATAPI_DP: { 164 ATAPI_DEVICE_PATH *atapi; 165 166 atapi = (ATAPI_DEVICE_PATH *)(void *)devpath; 167 return snprintf(buf, size, "ata(%s,%s,0x%x)", 168 (atapi->PrimarySecondary == 1) ? "Sec" : "Pri", 169 (atapi->SlaveMaster == 1) ? "Slave" : "Master", 170 atapi->Lun); 171 } 172 case MSG_USB_DP: { 173 USB_DEVICE_PATH *usb; 174 175 usb = (USB_DEVICE_PATH *)devpath; 176 return snprintf(buf, size, "usb(0x%02x,0x%02x)", 177 usb->ParentPortNumber, usb->InterfaceNumber); 178 } 179 case MSG_SCSI_DP: { 180 SCSI_DEVICE_PATH *scsi; 181 182 scsi = (SCSI_DEVICE_PATH *)(void *)devpath; 183 return snprintf(buf, size, "scsi(0x%02x,0x%02x)", 184 scsi->Pun, scsi->Lun); 185 } 186 case MSG_SATA_DP: { 187 SATA_DEVICE_PATH *sata; 188 189 sata = (SATA_DEVICE_PATH *)(void *)devpath; 190 return snprintf(buf, size, "sata(0x%x,0x%x,0x%x)", 191 sata->HBAPortNumber, sata->PortMultiplierPortNumber, 192 sata->Lun); 193 } 194 default: 195 return snprintf(buf, size, "msg(0x%02x)", 196 devpath->SubType); 197 } 198 break; 199 case HARDWARE_DEVICE_PATH: 200 switch (devpath->SubType) { 201 case HW_PCI_DP: { 202 PCI_DEVICE_PATH *pci; 203 204 pci = (PCI_DEVICE_PATH *)devpath; 205 return snprintf(buf, size, "pci(0x%02x,0x%02x)", 206 pci->Device, pci->Function); 207 } 208 default: 209 return snprintf(buf, size, "hw(0x%02x)", 210 devpath->SubType); 211 } 212 break; 213 case ACPI_DEVICE_PATH: { 214 ACPI_HID_DEVICE_PATH *acpi; 215 216 acpi = (ACPI_HID_DEVICE_PATH *)(void *)devpath; 217 if ((acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { 218 switch (EISA_ID_TO_NUM(acpi->HID)) { 219 case 0x0a03: 220 return snprintf(buf, size, "pciroot(0x%x)", 221 acpi->UID); 222 case 0x0a08: 223 return snprintf(buf, size, "pcieroot(0x%x)", 224 acpi->UID); 225 case 0x0604: 226 return snprintf(buf, size, "floppy(0x%x)", 227 acpi->UID); 228 case 0x0301: 229 return snprintf(buf, size, "keyboard(0x%x)", 230 acpi->UID); 231 case 0x0501: 232 return snprintf(buf, size, "serial(0x%x)", 233 acpi->UID); 234 case 0x0401: 235 return snprintf(buf, size, "parallelport(0x%x)", 236 acpi->UID); 237 default: 238 return snprintf(buf, size, "acpi(pnp%04x,0x%x)", 239 EISA_ID_TO_NUM(acpi->HID), acpi->UID); 240 } 241 } 242 243 return snprintf(buf, size, "acpi(0x%08x,0x%x)", acpi->HID, 244 acpi->UID); 245 } 246 case MEDIA_DEVICE_PATH: 247 switch (devpath->SubType) { 248 case MEDIA_CDROM_DP: { 249 CDROM_DEVICE_PATH *cdrom; 250 251 cdrom = (CDROM_DEVICE_PATH *)(void *)devpath; 252 return snprintf(buf, size, "cdrom(%x)", 253 cdrom->BootEntry); 254 } 255 case MEDIA_HARDDRIVE_DP: { 256 HARDDRIVE_DEVICE_PATH *hd; 257 258 hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath; 259 return snprintf(buf, size, "hd(%x)", 260 hd->PartitionNumber); 261 } 262 default: 263 return snprintf(buf, size, "media(0x%02x)", 264 devpath->SubType); 265 } 266 case BBS_DEVICE_PATH: 267 return snprintf(buf, size, "bbs(0x%02x)", devpath->SubType); 268 case END_DEVICE_PATH_TYPE: 269 return (0); 270 } 271 272 return snprintf(buf, size, "type(0x%02x, 0x%02x)", devpath->Type, 273 devpath->SubType); 274 } 275 276 /* 277 * devpath_strlcat appends a text description of devpath to buf but not more 278 * than size - 1 characters followed by NUL-terminator. 279 */ 280 int 281 devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath) 282 { 283 size_t len, used; 284 const char *sep; 285 286 sep = ""; 287 used = 0; 288 while (!IsDevicePathEnd(devpath)) { 289 len = snprintf(buf, size - used, "%s", sep); 290 used += len; 291 if (used > size) 292 return (used); 293 buf += len; 294 295 len = devpath_node_str(buf, size - used, devpath); 296 used += len; 297 if (used > size) 298 return (used); 299 buf += len; 300 devpath = NextDevicePathNode(devpath); 301 sep = ":"; 302 } 303 304 return (used); 305 } 306 307 /* 308 * devpath_str is convenience method which returns the text description of 309 * devpath using a static buffer, so it isn't thread safe! 310 */ 311 char * 312 devpath_str(EFI_DEVICE_PATH *devpath) 313 { 314 static char buf[256]; 315 316 devpath_strlcat(buf, sizeof(buf), devpath); 317 318 return buf; 319 } 320 321 /* 322 * load_loader attempts to load the loader image data. 323 * 324 * It tries each module and its respective devices, identified by mod->probe, 325 * in order until a successful load occurs at which point it returns EFI_SUCCESS 326 * and EFI_NOT_FOUND otherwise. 327 * 328 * Only devices which have preferred matching the preferred parameter are tried. 329 */ 330 static EFI_STATUS 331 load_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp, 332 size_t *bufsize, BOOLEAN preferred) 333 { 334 UINTN i; 335 dev_info_t *dev; 336 const boot_module_t *mod; 337 338 for (i = 0; i < NUM_BOOT_MODULES; i++) { 339 mod = boot_modules[i]; 340 for (dev = mod->devices(); dev != NULL; dev = dev->next) { 341 if (dev->preferred != preferred) 342 continue; 343 344 if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) == 345 EFI_SUCCESS) { 346 *devinfop = dev; 347 *modp = mod; 348 return (EFI_SUCCESS); 349 } 350 } 351 } 352 353 return (EFI_NOT_FOUND); 354 } 355 356 /* 357 * try_boot only returns if it fails to load the loader. If it succeeds 358 * it simply boots, otherwise it returns the status of last EFI call. 359 */ 360 static EFI_STATUS 361 try_boot(void) 362 { 363 size_t bufsize, loadersize, cmdsize; 364 void *buf, *loaderbuf; 365 char *cmd; 366 dev_info_t *dev; 367 const boot_module_t *mod; 368 EFI_HANDLE loaderhandle; 369 EFI_LOADED_IMAGE *loaded_image; 370 EFI_STATUS status; 371 372 status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE); 373 if (status != EFI_SUCCESS) { 374 status = load_loader(&mod, &dev, &loaderbuf, &loadersize, 375 FALSE); 376 if (status != EFI_SUCCESS) { 377 printf("Failed to load '%s'\n", PATH_LOADER_EFI); 378 return (status); 379 } 380 } 381 382 /* 383 * Read in and parse the command line from /boot.config or /boot/config, 384 * if present. We'll pass it the next stage via a simple ASCII 385 * string. loader.efi has a hack for ASCII strings, so we'll use that to 386 * keep the size down here. We only try to read the alternate file if 387 * we get EFI_NOT_FOUND because all other errors mean that the boot_module 388 * had troubles with the filesystem. We could return early, but we'll let 389 * loading the actual kernel sort all that out. Since these files are 390 * optional, we don't report errors in trying to read them. 391 */ 392 cmd = NULL; 393 cmdsize = 0; 394 status = mod->load(PATH_DOTCONFIG, dev, &buf, &bufsize); 395 if (status == EFI_NOT_FOUND) 396 status = mod->load(PATH_CONFIG, dev, &buf, &bufsize); 397 if (status == EFI_SUCCESS) { 398 cmdsize = bufsize + 1; 399 cmd = malloc(cmdsize); 400 if (cmd == NULL) 401 goto errout; 402 memcpy(cmd, buf, bufsize); 403 cmd[bufsize] = '\0'; 404 free(buf); 405 buf = NULL; 406 } 407 408 if ((status = bs->LoadImage(TRUE, image, devpath_last(dev->devpath), 409 loaderbuf, loadersize, &loaderhandle)) != EFI_SUCCESS) { 410 printf("Failed to load image provided by %s, size: %zu, (%lu)\n", 411 mod->name, loadersize, EFI_ERROR_CODE(status)); 412 goto errout; 413 } 414 415 if ((status = bs->HandleProtocol(loaderhandle, &LoadedImageGUID, 416 (VOID**)&loaded_image)) != EFI_SUCCESS) { 417 printf("Failed to query LoadedImage provided by %s (%lu)\n", 418 mod->name, EFI_ERROR_CODE(status)); 419 goto errout; 420 } 421 422 if (cmd != NULL) 423 printf(" command args: %s\n", cmd); 424 425 loaded_image->DeviceHandle = dev->devhandle; 426 loaded_image->LoadOptionsSize = cmdsize; 427 loaded_image->LoadOptions = cmd; 428 429 DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI); 430 DSTALL(1000000); 431 DPRINTF("."); 432 DSTALL(1000000); 433 DPRINTF("."); 434 DSTALL(1000000); 435 DPRINTF("."); 436 DSTALL(1000000); 437 DPRINTF("."); 438 DSTALL(1000000); 439 DPRINTF(".\n"); 440 441 if ((status = bs->StartImage(loaderhandle, NULL, NULL)) != 442 EFI_SUCCESS) { 443 printf("Failed to start image provided by %s (%lu)\n", 444 mod->name, EFI_ERROR_CODE(status)); 445 loaded_image->LoadOptionsSize = 0; 446 loaded_image->LoadOptions = NULL; 447 } 448 449 errout: 450 if (cmd != NULL) 451 free(cmd); 452 if (buf != NULL) 453 free(buf); 454 if (loaderbuf != NULL) 455 free(loaderbuf); 456 457 return (status); 458 } 459 460 /* 461 * probe_handle determines if the passed handle represents a logical partition 462 * if it does it uses each module in order to probe it and if successful it 463 * returns EFI_SUCCESS. 464 */ 465 static EFI_STATUS 466 probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN *preferred) 467 { 468 dev_info_t *devinfo; 469 EFI_BLOCK_IO *blkio; 470 EFI_DEVICE_PATH *devpath; 471 EFI_STATUS status; 472 UINTN i; 473 474 /* Figure out if we're dealing with an actual partition. */ 475 status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath); 476 if (status == EFI_UNSUPPORTED) 477 return (status); 478 479 if (status != EFI_SUCCESS) { 480 DPRINTF("\nFailed to query DevicePath (%lu)\n", 481 EFI_ERROR_CODE(status)); 482 return (status); 483 } 484 485 DPRINTF("probing: %s\n", devpath_str(devpath)); 486 487 status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio); 488 if (status == EFI_UNSUPPORTED) 489 return (status); 490 491 if (status != EFI_SUCCESS) { 492 DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n", 493 EFI_ERROR_CODE(status)); 494 return (status); 495 } 496 497 if (!blkio->Media->LogicalPartition) 498 return (EFI_UNSUPPORTED); 499 500 *preferred = device_paths_match(imgpath, devpath); 501 502 /* Run through each module, see if it can load this partition */ 503 for (i = 0; i < NUM_BOOT_MODULES; i++) { 504 if ((status = bs->AllocatePool(EfiLoaderData, 505 sizeof(*devinfo), (void **)&devinfo)) != 506 EFI_SUCCESS) { 507 DPRINTF("\nFailed to allocate devinfo (%lu)\n", 508 EFI_ERROR_CODE(status)); 509 continue; 510 } 511 devinfo->dev = blkio; 512 devinfo->devpath = devpath; 513 devinfo->devhandle = h; 514 devinfo->devdata = NULL; 515 devinfo->preferred = *preferred; 516 devinfo->next = NULL; 517 518 status = boot_modules[i]->probe(devinfo); 519 if (status == EFI_SUCCESS) 520 return (EFI_SUCCESS); 521 (void)bs->FreePool(devinfo); 522 } 523 524 return (EFI_UNSUPPORTED); 525 } 526 527 /* 528 * probe_handle_status calls probe_handle and outputs the returned status 529 * of the call. 530 */ 531 static void 532 probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath) 533 { 534 EFI_STATUS status; 535 BOOLEAN preferred = false; 536 537 status = probe_handle(h, imgpath, &preferred); 538 539 DPRINTF("probe: "); 540 switch (status) { 541 case EFI_UNSUPPORTED: 542 printf("."); 543 DPRINTF(" not supported\n"); 544 break; 545 case EFI_SUCCESS: 546 if (preferred) { 547 printf("%c", '*'); 548 DPRINTF(" supported (preferred)\n"); 549 } else { 550 printf("%c", '+'); 551 DPRINTF(" supported\n"); 552 } 553 break; 554 default: 555 printf("x"); 556 DPRINTF(" error (%lu)\n", EFI_ERROR_CODE(status)); 557 break; 558 } 559 DSTALL(500000); 560 } 561 562 EFI_STATUS 563 efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) 564 { 565 EFI_HANDLE *handles; 566 EFI_LOADED_IMAGE *img; 567 EFI_DEVICE_PATH *imgpath; 568 EFI_STATUS status; 569 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL; 570 SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL; 571 UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles; 572 573 /* Basic initialization*/ 574 systab = Xsystab; 575 image = Ximage; 576 bs = Xsystab->BootServices; 577 578 /* Set up the console, so printf works. */ 579 status = bs->LocateProtocol(&ConsoleControlGUID, NULL, 580 (VOID **)&ConsoleControl); 581 if (status == EFI_SUCCESS) 582 (void)ConsoleControl->SetMode(ConsoleControl, 583 EfiConsoleControlScreenText); 584 /* 585 * Reset the console and find the best text mode. 586 */ 587 conout = systab->ConOut; 588 conout->Reset(conout, TRUE); 589 max_dim = best_mode = 0; 590 for (i = 0; ; i++) { 591 status = conout->QueryMode(conout, i, &cols, &rows); 592 if (EFI_ERROR(status)) 593 break; 594 if (cols * rows > max_dim) { 595 max_dim = cols * rows; 596 best_mode = i; 597 } 598 } 599 if (max_dim > 0) 600 conout->SetMode(conout, best_mode); 601 conout->EnableCursor(conout, TRUE); 602 conout->ClearScreen(conout); 603 604 printf("\n>> illumos EFI boot block\n"); 605 printf(" Loader path: %s\n\n", PATH_LOADER_EFI); 606 printf(" Initializing modules:"); 607 for (i = 0; i < NUM_BOOT_MODULES; i++) { 608 printf(" %s", boot_modules[i]->name); 609 if (boot_modules[i]->init != NULL) 610 boot_modules[i]->init(); 611 } 612 putchar('\n'); 613 614 /* Get all the device handles */ 615 hsize = (UINTN)NUM_HANDLES_INIT * sizeof(EFI_HANDLE); 616 if ((status = bs->AllocatePool(EfiLoaderData, hsize, (void **)&handles)) 617 != EFI_SUCCESS) 618 panic("Failed to allocate %d handles (%lu)", NUM_HANDLES_INIT, 619 EFI_ERROR_CODE(status)); 620 621 status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL, 622 &hsize, handles); 623 switch (status) { 624 case EFI_SUCCESS: 625 break; 626 case EFI_BUFFER_TOO_SMALL: 627 (void)bs->FreePool(handles); 628 if ((status = bs->AllocatePool(EfiLoaderData, hsize, 629 (void **)&handles)) != EFI_SUCCESS) { 630 panic("Failed to allocate %zu handles (%lu)", hsize / 631 sizeof(*handles), EFI_ERROR_CODE(status)); 632 } 633 status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID, 634 NULL, &hsize, handles); 635 if (status != EFI_SUCCESS) 636 panic("Failed to get device handles (%lu)\n", 637 EFI_ERROR_CODE(status)); 638 break; 639 default: 640 panic("Failed to get device handles (%lu)", 641 EFI_ERROR_CODE(status)); 642 } 643 644 /* Scan all partitions, probing with all modules. */ 645 nhandles = hsize / sizeof(*handles); 646 printf(" Probing %zu block devices...", nhandles); 647 DPRINTF("\n"); 648 649 /* Determine the devpath of our image so we can prefer it. */ 650 status = bs->HandleProtocol(image, &LoadedImageGUID, (VOID**)&img); 651 imgpath = NULL; 652 if (status == EFI_SUCCESS) { 653 status = bs->HandleProtocol(img->DeviceHandle, &DevicePathGUID, 654 (void **)&imgpath); 655 if (status != EFI_SUCCESS) 656 DPRINTF("Failed to get image DevicePath (%lu)\n", 657 EFI_ERROR_CODE(status)); 658 DPRINTF("boot1 imagepath: %s\n", devpath_str(imgpath)); 659 } 660 661 for (i = 0; i < nhandles; i++) 662 probe_handle_status(handles[i], imgpath); 663 printf(" done\n"); 664 665 /* Status summary. */ 666 for (i = 0; i < NUM_BOOT_MODULES; i++) { 667 printf(" "); 668 boot_modules[i]->status(); 669 } 670 671 try_boot(); 672 673 /* If we get here, we're out of luck... */ 674 panic("No bootable partitions found!"); 675 } 676 677 /* 678 * add_device adds a device to the passed devinfo list. 679 */ 680 void 681 add_device(dev_info_t **devinfop, dev_info_t *devinfo) 682 { 683 dev_info_t *dev; 684 685 if (*devinfop == NULL) { 686 *devinfop = devinfo; 687 return; 688 } 689 690 for (dev = *devinfop; dev->next != NULL; dev = dev->next) 691 ; 692 693 dev->next = devinfo; 694 } 695 696 void 697 panic(const char *fmt, ...) 698 { 699 va_list ap; 700 701 printf("panic: "); 702 va_start(ap, fmt); 703 vprintf(fmt, ap); 704 va_end(ap); 705 printf("\n"); 706 707 while (1) {} 708 } 709 710 void 711 putchar(int c) 712 { 713 CHAR16 buf[2]; 714 715 if (c == '\n') { 716 buf[0] = '\r'; 717 buf[1] = 0; 718 systab->ConOut->OutputString(systab->ConOut, buf); 719 } 720 buf[0] = c; 721 buf[1] = 0; 722 systab->ConOut->OutputString(systab->ConOut, buf); 723 } 724 725 int 726 getchar(void) 727 { 728 EFI_INPUT_KEY key; 729 EFI_STATUS status; 730 UINTN junk; 731 732 status = systab->ConIn->ReadKeyStroke(systab->ConIn, &key); 733 if (status == EFI_NOT_READY) { 734 bs->WaitForEvent(1, &systab->ConIn->WaitForKey, &junk); 735 status = systab->ConIn->ReadKeyStroke(systab->ConIn, &key); 736 } 737 return (key.UnicodeChar); 738 } 739