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