8919 loader.efi: remove efi_main() from libefi
[unleashed.git] / usr / src / boot / sys / boot / efi / boot1 / boot1.c
blob37529a991292c83862df632463ce30e9e6479aa0
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.
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.
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.
22 #include <sys/cdefs.h>
24 #include <sys/param.h>
25 #include <machine/elf.h>
26 #include <machine/stdarg.h>
27 #include <stand.h>
29 #include <efi.h>
30 #include <eficonsctl.h>
32 #include <bootstrap.h>
33 #include "boot_module.h"
34 #include "paths.h"
36 struct arch_switch archsw;
37 struct fs_ops *file_system[] = {
38 NULL
41 static const boot_module_t *boot_modules[] =
43 #ifdef EFI_ZFS_BOOT
44 &zfs_module,
45 #endif
46 #ifdef EFI_UFS_BOOT
47 &ufs_module
48 #endif
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
55 EFI_SYSTEM_TABLE *systab;
56 EFI_BOOT_SERVICES *bs;
57 static EFI_HANDLE *image;
59 static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
60 static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
61 static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
62 static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
65 * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures
66 * memory is correctly aligned avoiding EFI_INVALID_PARAMETER returns from
67 * EFI methods.
69 void *
70 Malloc(size_t len, const char *file __unused, int line __unused)
72 void *out;
74 if (bs->AllocatePool(EfiLoaderData, len, &out) == EFI_SUCCESS)
75 return (out);
77 return (NULL);
80 void
81 Free(void *buf, const char *file __unused, int line __unused)
83 if (buf != NULL)
84 (void)bs->FreePool(buf);
88 * nodes_match returns TRUE if the imgpath isn't NULL and the nodes match,
89 * FALSE otherwise.
91 static BOOLEAN
92 nodes_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath)
94 size_t len;
96 if (imgpath == NULL || imgpath->Type != devpath->Type ||
97 imgpath->SubType != devpath->SubType)
98 return (FALSE);
100 len = DevicePathNodeLength(imgpath);
101 if (len != DevicePathNodeLength(devpath))
102 return (FALSE);
104 return (memcmp(imgpath, devpath, (size_t)len) == 0);
108 * device_paths_match returns TRUE if the imgpath isn't NULL and all nodes
109 * in imgpath and devpath match up to their respective occurences of a
110 * media node, FALSE otherwise.
112 static BOOLEAN
113 device_paths_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath)
116 if (imgpath == NULL)
117 return (FALSE);
119 while (!IsDevicePathEnd(imgpath) && !IsDevicePathEnd(devpath)) {
120 if (IsDevicePathType(imgpath, MEDIA_DEVICE_PATH) &&
121 IsDevicePathType(devpath, MEDIA_DEVICE_PATH))
122 return (TRUE);
124 if (!nodes_match(imgpath, devpath))
125 return (FALSE);
127 imgpath = NextDevicePathNode(imgpath);
128 devpath = NextDevicePathNode(devpath);
131 return (FALSE);
135 * devpath_last returns the last non-path end node in devpath.
137 static EFI_DEVICE_PATH *
138 devpath_last(EFI_DEVICE_PATH *devpath)
141 while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
142 devpath = NextDevicePathNode(devpath);
144 return (devpath);
148 * devpath_node_str is a basic output method for a devpath node which
149 * only understands a subset of the available sub types.
151 * If we switch to UEFI 2.x then we should update it to use:
152 * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL.
154 static int
155 devpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
158 switch (devpath->Type) {
159 case MESSAGING_DEVICE_PATH:
160 switch (devpath->SubType) {
161 case MSG_ATAPI_DP: {
162 ATAPI_DEVICE_PATH *atapi;
164 atapi = (ATAPI_DEVICE_PATH *)(void *)devpath;
165 return snprintf(buf, size, "ata(%s,%s,0x%x)",
166 (atapi->PrimarySecondary == 1) ? "Sec" : "Pri",
167 (atapi->SlaveMaster == 1) ? "Slave" : "Master",
168 atapi->Lun);
170 case MSG_USB_DP: {
171 USB_DEVICE_PATH *usb;
173 usb = (USB_DEVICE_PATH *)devpath;
174 return snprintf(buf, size, "usb(0x%02x,0x%02x)",
175 usb->ParentPortNumber, usb->InterfaceNumber);
177 case MSG_SCSI_DP: {
178 SCSI_DEVICE_PATH *scsi;
180 scsi = (SCSI_DEVICE_PATH *)(void *)devpath;
181 return snprintf(buf, size, "scsi(0x%02x,0x%02x)",
182 scsi->Pun, scsi->Lun);
184 case MSG_SATA_DP: {
185 SATA_DEVICE_PATH *sata;
187 sata = (SATA_DEVICE_PATH *)(void *)devpath;
188 return snprintf(buf, size, "sata(0x%x,0x%x,0x%x)",
189 sata->HBAPortNumber, sata->PortMultiplierPortNumber,
190 sata->Lun);
192 default:
193 return snprintf(buf, size, "msg(0x%02x)",
194 devpath->SubType);
196 break;
197 case HARDWARE_DEVICE_PATH:
198 switch (devpath->SubType) {
199 case HW_PCI_DP: {
200 PCI_DEVICE_PATH *pci;
202 pci = (PCI_DEVICE_PATH *)devpath;
203 return snprintf(buf, size, "pci(0x%02x,0x%02x)",
204 pci->Device, pci->Function);
206 default:
207 return snprintf(buf, size, "hw(0x%02x)",
208 devpath->SubType);
210 break;
211 case ACPI_DEVICE_PATH: {
212 ACPI_HID_DEVICE_PATH *acpi;
214 acpi = (ACPI_HID_DEVICE_PATH *)(void *)devpath;
215 if ((acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
216 switch (EISA_ID_TO_NUM(acpi->HID)) {
217 case 0x0a03:
218 return snprintf(buf, size, "pciroot(0x%x)",
219 acpi->UID);
220 case 0x0a08:
221 return snprintf(buf, size, "pcieroot(0x%x)",
222 acpi->UID);
223 case 0x0604:
224 return snprintf(buf, size, "floppy(0x%x)",
225 acpi->UID);
226 case 0x0301:
227 return snprintf(buf, size, "keyboard(0x%x)",
228 acpi->UID);
229 case 0x0501:
230 return snprintf(buf, size, "serial(0x%x)",
231 acpi->UID);
232 case 0x0401:
233 return snprintf(buf, size, "parallelport(0x%x)",
234 acpi->UID);
235 default:
236 return snprintf(buf, size, "acpi(pnp%04x,0x%x)",
237 EISA_ID_TO_NUM(acpi->HID), acpi->UID);
241 return snprintf(buf, size, "acpi(0x%08x,0x%x)", acpi->HID,
242 acpi->UID);
244 case MEDIA_DEVICE_PATH:
245 switch (devpath->SubType) {
246 case MEDIA_CDROM_DP: {
247 CDROM_DEVICE_PATH *cdrom;
249 cdrom = (CDROM_DEVICE_PATH *)(void *)devpath;
250 return snprintf(buf, size, "cdrom(%x)",
251 cdrom->BootEntry);
253 case MEDIA_HARDDRIVE_DP: {
254 HARDDRIVE_DEVICE_PATH *hd;
256 hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath;
257 return snprintf(buf, size, "hd(%x)",
258 hd->PartitionNumber);
260 default:
261 return snprintf(buf, size, "media(0x%02x)",
262 devpath->SubType);
264 case BBS_DEVICE_PATH:
265 return snprintf(buf, size, "bbs(0x%02x)", devpath->SubType);
266 case END_DEVICE_PATH_TYPE:
267 return (0);
270 return snprintf(buf, size, "type(0x%02x, 0x%02x)", devpath->Type,
271 devpath->SubType);
275 * devpath_strlcat appends a text description of devpath to buf but not more
276 * than size - 1 characters followed by NUL-terminator.
279 devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
281 size_t len, used;
282 const char *sep;
284 sep = "";
285 used = 0;
286 while (!IsDevicePathEnd(devpath)) {
287 len = snprintf(buf, size - used, "%s", sep);
288 used += len;
289 if (used > size)
290 return (used);
291 buf += len;
293 len = devpath_node_str(buf, size - used, devpath);
294 used += len;
295 if (used > size)
296 return (used);
297 buf += len;
298 devpath = NextDevicePathNode(devpath);
299 sep = ":";
302 return (used);
306 * devpath_str is convenience method which returns the text description of
307 * devpath using a static buffer, so it isn't thread safe!
309 char *
310 devpath_str(EFI_DEVICE_PATH *devpath)
312 static char buf[256];
314 devpath_strlcat(buf, sizeof(buf), devpath);
316 return buf;
320 * load_loader attempts to load the loader image data.
322 * It tries each module and its respective devices, identified by mod->probe,
323 * in order until a successful load occurs at which point it returns EFI_SUCCESS
324 * and EFI_NOT_FOUND otherwise.
326 * Only devices which have preferred matching the preferred parameter are tried.
328 static EFI_STATUS
329 load_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp,
330 size_t *bufsize, BOOLEAN preferred)
332 UINTN i;
333 dev_info_t *dev;
334 const boot_module_t *mod;
336 for (i = 0; i < NUM_BOOT_MODULES; i++) {
337 mod = boot_modules[i];
338 for (dev = mod->devices(); dev != NULL; dev = dev->next) {
339 if (dev->preferred != preferred)
340 continue;
342 if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) ==
343 EFI_SUCCESS) {
344 *devinfop = dev;
345 *modp = mod;
346 return (EFI_SUCCESS);
351 return (EFI_NOT_FOUND);
355 * try_boot only returns if it fails to load the loader. If it succeeds
356 * it simply boots, otherwise it returns the status of last EFI call.
358 static EFI_STATUS
359 try_boot(void)
361 size_t bufsize, loadersize, cmdsize;
362 void *buf, *loaderbuf;
363 char *cmd;
364 dev_info_t *dev;
365 const boot_module_t *mod;
366 EFI_HANDLE loaderhandle;
367 EFI_LOADED_IMAGE *loaded_image;
368 EFI_STATUS status;
370 status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE);
371 if (status != EFI_SUCCESS) {
372 status = load_loader(&mod, &dev, &loaderbuf, &loadersize,
373 FALSE);
374 if (status != EFI_SUCCESS) {
375 printf("Failed to load '%s'\n", PATH_LOADER_EFI);
376 return (status);
381 * Read in and parse the command line from /boot.config or /boot/config,
382 * if present. We'll pass it the next stage via a simple ASCII
383 * string. loader.efi has a hack for ASCII strings, so we'll use that to
384 * keep the size down here. We only try to read the alternate file if
385 * we get EFI_NOT_FOUND because all other errors mean that the boot_module
386 * had troubles with the filesystem. We could return early, but we'll let
387 * loading the actual kernel sort all that out. Since these files are
388 * optional, we don't report errors in trying to read them.
390 cmd = NULL;
391 cmdsize = 0;
392 status = mod->load(PATH_DOTCONFIG, dev, &buf, &bufsize);
393 if (status == EFI_NOT_FOUND)
394 status = mod->load(PATH_CONFIG, dev, &buf, &bufsize);
395 if (status == EFI_SUCCESS) {
396 cmdsize = bufsize + 1;
397 cmd = malloc(cmdsize);
398 if (cmd == NULL)
399 goto errout;
400 memcpy(cmd, buf, bufsize);
401 cmd[bufsize] = '\0';
402 free(buf);
403 buf = NULL;
406 if ((status = bs->LoadImage(TRUE, image, devpath_last(dev->devpath),
407 loaderbuf, loadersize, &loaderhandle)) != EFI_SUCCESS) {
408 printf("Failed to load image provided by %s, size: %zu, (%lu)\n",
409 mod->name, loadersize, EFI_ERROR_CODE(status));
410 goto errout;
413 if ((status = bs->HandleProtocol(loaderhandle, &LoadedImageGUID,
414 (VOID**)&loaded_image)) != EFI_SUCCESS) {
415 printf("Failed to query LoadedImage provided by %s (%lu)\n",
416 mod->name, EFI_ERROR_CODE(status));
417 goto errout;
420 if (cmd != NULL)
421 printf(" command args: %s\n", cmd);
423 loaded_image->DeviceHandle = dev->devhandle;
424 loaded_image->LoadOptionsSize = cmdsize;
425 loaded_image->LoadOptions = cmd;
427 DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI);
428 DSTALL(1000000);
429 DPRINTF(".");
430 DSTALL(1000000);
431 DPRINTF(".");
432 DSTALL(1000000);
433 DPRINTF(".");
434 DSTALL(1000000);
435 DPRINTF(".");
436 DSTALL(1000000);
437 DPRINTF(".\n");
439 if ((status = bs->StartImage(loaderhandle, NULL, NULL)) !=
440 EFI_SUCCESS) {
441 printf("Failed to start image provided by %s (%lu)\n",
442 mod->name, EFI_ERROR_CODE(status));
443 loaded_image->LoadOptionsSize = 0;
444 loaded_image->LoadOptions = NULL;
447 errout:
448 if (cmd != NULL)
449 free(cmd);
450 if (buf != NULL)
451 free(buf);
452 if (loaderbuf != NULL)
453 free(loaderbuf);
455 return (status);
459 * probe_handle determines if the passed handle represents a logical partition
460 * if it does it uses each module in order to probe it and if successful it
461 * returns EFI_SUCCESS.
463 static EFI_STATUS
464 probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN *preferred)
466 dev_info_t *devinfo;
467 EFI_BLOCK_IO *blkio;
468 EFI_DEVICE_PATH *devpath;
469 EFI_STATUS status;
470 UINTN i;
472 /* Figure out if we're dealing with an actual partition. */
473 status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
474 if (status == EFI_UNSUPPORTED)
475 return (status);
477 if (status != EFI_SUCCESS) {
478 DPRINTF("\nFailed to query DevicePath (%lu)\n",
479 EFI_ERROR_CODE(status));
480 return (status);
483 DPRINTF("probing: %s\n", devpath_str(devpath));
485 status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
486 if (status == EFI_UNSUPPORTED)
487 return (status);
489 if (status != EFI_SUCCESS) {
490 DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n",
491 EFI_ERROR_CODE(status));
492 return (status);
495 if (!blkio->Media->LogicalPartition)
496 return (EFI_UNSUPPORTED);
498 *preferred = device_paths_match(imgpath, devpath);
500 /* Run through each module, see if it can load this partition */
501 for (i = 0; i < NUM_BOOT_MODULES; i++) {
502 if ((status = bs->AllocatePool(EfiLoaderData,
503 sizeof(*devinfo), (void **)&devinfo)) !=
504 EFI_SUCCESS) {
505 DPRINTF("\nFailed to allocate devinfo (%lu)\n",
506 EFI_ERROR_CODE(status));
507 continue;
509 devinfo->dev = blkio;
510 devinfo->devpath = devpath;
511 devinfo->devhandle = h;
512 devinfo->devdata = NULL;
513 devinfo->preferred = *preferred;
514 devinfo->next = NULL;
516 status = boot_modules[i]->probe(devinfo);
517 if (status == EFI_SUCCESS)
518 return (EFI_SUCCESS);
519 (void)bs->FreePool(devinfo);
522 return (EFI_UNSUPPORTED);
526 * probe_handle_status calls probe_handle and outputs the returned status
527 * of the call.
529 static void
530 probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath)
532 EFI_STATUS status;
533 BOOLEAN preferred = false;
535 status = probe_handle(h, imgpath, &preferred);
537 DPRINTF("probe: ");
538 switch (status) {
539 case EFI_UNSUPPORTED:
540 printf(".");
541 DPRINTF(" not supported\n");
542 break;
543 case EFI_SUCCESS:
544 if (preferred) {
545 printf("%c", '*');
546 DPRINTF(" supported (preferred)\n");
547 } else {
548 printf("%c", '+');
549 DPRINTF(" supported\n");
551 break;
552 default:
553 printf("x");
554 DPRINTF(" error (%lu)\n", EFI_ERROR_CODE(status));
555 break;
557 DSTALL(500000);
560 EFI_STATUS
561 efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
563 EFI_HANDLE *handles;
564 EFI_LOADED_IMAGE *img;
565 EFI_DEVICE_PATH *imgpath;
566 EFI_STATUS status;
567 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
568 SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
569 UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles;
571 /* Basic initialization*/
572 systab = Xsystab;
573 image = Ximage;
574 bs = Xsystab->BootServices;
576 /* Set up the console, so printf works. */
577 status = bs->LocateProtocol(&ConsoleControlGUID, NULL,
578 (VOID **)&ConsoleControl);
579 if (status == EFI_SUCCESS)
580 (void)ConsoleControl->SetMode(ConsoleControl,
581 EfiConsoleControlScreenText);
583 * Reset the console and find the best text mode.
585 conout = systab->ConOut;
586 conout->Reset(conout, TRUE);
587 max_dim = best_mode = 0;
588 for (i = 0; ; i++) {
589 status = conout->QueryMode(conout, i, &cols, &rows);
590 if (EFI_ERROR(status))
591 break;
592 if (cols * rows > max_dim) {
593 max_dim = cols * rows;
594 best_mode = i;
597 if (max_dim > 0)
598 conout->SetMode(conout, best_mode);
599 conout->EnableCursor(conout, TRUE);
600 conout->ClearScreen(conout);
602 printf("\n>> illumos EFI boot block\n");
603 printf(" Loader path: %s\n\n", PATH_LOADER_EFI);
604 printf(" Initializing modules:");
605 for (i = 0; i < NUM_BOOT_MODULES; i++) {
606 printf(" %s", boot_modules[i]->name);
607 if (boot_modules[i]->init != NULL)
608 boot_modules[i]->init();
610 putchar('\n');
612 /* Get all the device handles */
613 hsize = (UINTN)NUM_HANDLES_INIT * sizeof(EFI_HANDLE);
614 if ((status = bs->AllocatePool(EfiLoaderData, hsize, (void **)&handles))
615 != EFI_SUCCESS)
616 panic("Failed to allocate %d handles (%lu)", NUM_HANDLES_INIT,
617 EFI_ERROR_CODE(status));
619 status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL,
620 &hsize, handles);
621 switch (status) {
622 case EFI_SUCCESS:
623 break;
624 case EFI_BUFFER_TOO_SMALL:
625 (void)bs->FreePool(handles);
626 if ((status = bs->AllocatePool(EfiLoaderData, hsize,
627 (void **)&handles)) != EFI_SUCCESS) {
628 panic("Failed to allocate %zu handles (%lu)", hsize /
629 sizeof(*handles), EFI_ERROR_CODE(status));
631 status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID,
632 NULL, &hsize, handles);
633 if (status != EFI_SUCCESS)
634 panic("Failed to get device handles (%lu)\n",
635 EFI_ERROR_CODE(status));
636 break;
637 default:
638 panic("Failed to get device handles (%lu)",
639 EFI_ERROR_CODE(status));
642 /* Scan all partitions, probing with all modules. */
643 nhandles = hsize / sizeof(*handles);
644 printf(" Probing %zu block devices...", nhandles);
645 DPRINTF("\n");
647 /* Determine the devpath of our image so we can prefer it. */
648 status = bs->HandleProtocol(image, &LoadedImageGUID, (VOID**)&img);
649 imgpath = NULL;
650 if (status == EFI_SUCCESS) {
651 status = bs->HandleProtocol(img->DeviceHandle, &DevicePathGUID,
652 (void **)&imgpath);
653 if (status != EFI_SUCCESS)
654 DPRINTF("Failed to get image DevicePath (%lu)\n",
655 EFI_ERROR_CODE(status));
656 DPRINTF("boot1 imagepath: %s\n", devpath_str(imgpath));
659 for (i = 0; i < nhandles; i++)
660 probe_handle_status(handles[i], imgpath);
661 printf(" done\n");
663 /* Status summary. */
664 for (i = 0; i < NUM_BOOT_MODULES; i++) {
665 printf(" ");
666 boot_modules[i]->status();
669 try_boot();
671 /* If we get here, we're out of luck... */
672 panic("No bootable partitions found!");
676 * add_device adds a device to the passed devinfo list.
678 void
679 add_device(dev_info_t **devinfop, dev_info_t *devinfo)
681 dev_info_t *dev;
683 if (*devinfop == NULL) {
684 *devinfop = devinfo;
685 return;
688 for (dev = *devinfop; dev->next != NULL; dev = dev->next)
691 dev->next = devinfo;
694 void
695 panic(const char *fmt, ...)
697 va_list ap;
699 printf("panic: ");
700 va_start(ap, fmt);
701 vprintf(fmt, ap);
702 va_end(ap);
703 printf("\n");
705 while (1) {}
708 void
709 putchar(int c)
711 CHAR16 buf[2];
713 if (c == '\n') {
714 buf[0] = '\r';
715 buf[1] = 0;
716 systab->ConOut->OutputString(systab->ConOut, buf);
718 buf[0] = c;
719 buf[1] = 0;
720 systab->ConOut->OutputString(systab->ConOut, buf);
724 getchar(void)
726 EFI_INPUT_KEY key;
727 EFI_STATUS status;
728 UINTN junk;
730 status = systab->ConIn->ReadKeyStroke(systab->ConIn, &key);
731 if (status == EFI_NOT_READY) {
732 bs->WaitForEvent(1, &systab->ConIn->WaitForKey, &junk);
733 status = systab->ConIn->ReadKeyStroke(systab->ConIn, &key);
735 return (key.UnicodeChar);