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