boot/efi: Port most of our efi boot code to the EDK II headers.
[dragonfly.git] / sys / boot / efi / boot1 / boot1.c
blobf078d3b40bb678b6113b040e6506b0027b858698
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.
21 * $FreeBSD: head/sys/boot/efi/boot1/boot1.c 296713 2016-03-12 06:50:16Z andrew $
24 #include <sys/param.h>
25 #include <machine/elf.h>
26 #include <machine/stdarg.h>
27 #include <stand.h>
28 #include <stdarg.h>
30 #include <efi.h>
31 #include <eficonsctl.h>
33 #include "boot_module.h"
34 #include "paths.h"
36 #define PATH_CONFIG "/boot/config"
37 #define PATH_DOTCONFIG "/boot.config"
38 #define PATH_LOADER "/loader.efi" /* /boot is dedicated */
39 #define PATH_LOADER_ALT "/boot/loader.efi" /* /boot in root */
41 static const boot_module_t *boot_modules[] =
43 #ifdef EFI_UFS_BOOT
44 &ufs_module
45 #endif
48 #define NUM_BOOT_MODULES NELEM(boot_modules)
49 /* The initial number of handles used to query EFI for partitions. */
50 #define NUM_HANDLES_INIT 24
52 EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab);
54 EFI_SYSTEM_TABLE *systab;
55 EFI_BOOT_SERVICES *bs;
56 static EFI_HANDLE *image;
58 static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
59 static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
60 static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
61 static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
64 * XXX DragonFly's libstand doesn't provide a way to override the malloc
65 * implementation yet.
67 #if 0
70 * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures
71 * memory is correctly aligned avoiding EFI_INVALID_PARAMETER returns from
72 * EFI methods.
74 void *
75 Malloc(size_t len, const char *file __unused, int line __unused)
77 void *out;
79 if (bs->AllocatePool(EfiLoaderData, len, &out) == EFI_SUCCESS)
80 return (out);
82 return (NULL);
85 void
86 Free(void *buf, const char *file __unused, int line __unused)
88 (void)bs->FreePool(buf);
91 #endif
94 * nodes_match returns TRUE if the imgpath isn't NULL and the nodes match,
95 * FALSE otherwise.
97 static BOOLEAN
98 nodes_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath)
100 int len;
102 if (imgpath == NULL || imgpath->Type != devpath->Type ||
103 imgpath->SubType != devpath->SubType)
104 return (FALSE);
106 len = DevicePathNodeLength(imgpath);
107 if (len != DevicePathNodeLength(devpath))
108 return (FALSE);
110 return (memcmp(imgpath, devpath, (size_t)len) == 0);
114 * device_paths_match returns TRUE if the imgpath isn't NULL and all nodes
115 * in imgpath and devpath match up to their respect occurances of a media
116 * node, FALSE otherwise.
118 static BOOLEAN
119 device_paths_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath)
122 if (imgpath == NULL)
123 return (FALSE);
125 while (!IsDevicePathEnd(imgpath) && !IsDevicePathEnd(devpath)) {
126 if (IsDevicePathType(imgpath, MEDIA_DEVICE_PATH) &&
127 IsDevicePathType(devpath, MEDIA_DEVICE_PATH))
128 return (TRUE);
130 if (!nodes_match(imgpath, devpath))
131 return (FALSE);
133 imgpath = NextDevicePathNode(imgpath);
134 devpath = NextDevicePathNode(devpath);
137 return (FALSE);
141 * devpath_last returns the last non-path end node in devpath.
143 static EFI_DEVICE_PATH *
144 devpath_last(EFI_DEVICE_PATH *devpath)
147 while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
148 devpath = NextDevicePathNode(devpath);
150 return (devpath);
154 * devpath_node_str is a basic output method for a devpath node which
155 * only understands a subset of the available sub types.
157 * If we switch to UEFI 2.x then we should update it to use:
158 * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL.
160 static int
161 devpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
164 switch (devpath->Type) {
165 case MESSAGING_DEVICE_PATH:
166 switch (devpath->SubType) {
167 case MSG_ATAPI_DP: {
168 ATAPI_DEVICE_PATH *atapi;
170 atapi = (ATAPI_DEVICE_PATH *)(void *)devpath;
171 return snprintf(buf, size, "ata(%s,%s,0x%x)",
172 (atapi->PrimarySecondary == 1) ? "Sec" : "Pri",
173 (atapi->SlaveMaster == 1) ? "Slave" : "Master",
174 atapi->Lun);
176 case MSG_USB_DP: {
177 USB_DEVICE_PATH *usb;
179 usb = (USB_DEVICE_PATH *)devpath;
180 return snprintf(buf, size, "usb(0x%02x,0x%02x)",
181 usb->ParentPortNumber, usb->InterfaceNumber);
183 case MSG_SCSI_DP: {
184 SCSI_DEVICE_PATH *scsi;
186 scsi = (SCSI_DEVICE_PATH *)(void *)devpath;
187 return snprintf(buf, size, "scsi(0x%02x,0x%02x)",
188 scsi->Pun, scsi->Lun);
190 case MSG_SATA_DP: {
191 SATA_DEVICE_PATH *sata;
193 sata = (SATA_DEVICE_PATH *)(void *)devpath;
194 return snprintf(buf, size, "sata(0x%x,0x%x,0x%x)",
195 sata->HBAPortNumber, sata->PortMultiplierPortNumber,
196 sata->Lun);
198 default:
199 return snprintf(buf, size, "msg(0x%02x)",
200 devpath->SubType);
202 break;
203 case HARDWARE_DEVICE_PATH:
204 switch (devpath->SubType) {
205 case HW_PCI_DP: {
206 PCI_DEVICE_PATH *pci;
208 pci = (PCI_DEVICE_PATH *)devpath;
209 return snprintf(buf, size, "pci(0x%02x,0x%02x)",
210 pci->Device, pci->Function);
212 default:
213 return snprintf(buf, size, "hw(0x%02x)",
214 devpath->SubType);
216 break;
217 case ACPI_DEVICE_PATH: {
218 ACPI_HID_DEVICE_PATH *acpi;
220 acpi = (ACPI_HID_DEVICE_PATH *)(void *)devpath;
221 if ((acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
222 switch (EISA_ID_TO_NUM(acpi->HID)) {
223 case 0x0a03:
224 return snprintf(buf, size, "pciroot(0x%x)",
225 acpi->UID);
226 case 0x0a08:
227 return snprintf(buf, size, "pcieroot(0x%x)",
228 acpi->UID);
229 case 0x0604:
230 return snprintf(buf, size, "floppy(0x%x)",
231 acpi->UID);
232 case 0x0301:
233 return snprintf(buf, size, "keyboard(0x%x)",
234 acpi->UID);
235 case 0x0501:
236 return snprintf(buf, size, "serial(0x%x)",
237 acpi->UID);
238 case 0x0401:
239 return snprintf(buf, size, "parallelport(0x%x)",
240 acpi->UID);
241 default:
242 return snprintf(buf, size, "acpi(pnp%04x,0x%x)",
243 EISA_ID_TO_NUM(acpi->HID), acpi->UID);
247 return snprintf(buf, size, "acpi(0x%08x,0x%x)", acpi->HID,
248 acpi->UID);
250 case MEDIA_DEVICE_PATH:
251 switch (devpath->SubType) {
252 case MEDIA_CDROM_DP: {
253 CDROM_DEVICE_PATH *cdrom;
255 cdrom = (CDROM_DEVICE_PATH *)(void *)devpath;
256 return snprintf(buf, size, "cdrom(%x)",
257 cdrom->BootEntry);
259 case MEDIA_HARDDRIVE_DP: {
260 HARDDRIVE_DEVICE_PATH *hd;
262 hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath;
263 return snprintf(buf, size, "hd(%x)",
264 hd->PartitionNumber);
266 default:
267 return snprintf(buf, size, "media(0x%02x)",
268 devpath->SubType);
270 case BBS_DEVICE_PATH:
271 return snprintf(buf, size, "bbs(0x%02x)", devpath->SubType);
272 case END_DEVICE_PATH_TYPE:
273 return (0);
276 return snprintf(buf, size, "type(0x%02x, 0x%02x)", devpath->Type,
277 devpath->SubType);
281 * devpath_strlcat appends a text description of devpath to buf but not more
282 * than size - 1 characters followed by NUL-terminator.
285 devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
287 size_t len, used;
288 const char *sep;
290 sep = "";
291 used = 0;
292 while (!IsDevicePathEnd(devpath)) {
293 len = snprintf(buf, size - used, "%s", sep);
294 used += len;
295 if (used > size)
296 return (used);
297 buf += len;
299 len = devpath_node_str(buf, size - used, devpath);
300 used += len;
301 if (used > size)
302 return (used);
303 buf += len;
304 devpath = NextDevicePathNode(devpath);
305 sep = ":";
308 return (used);
312 * devpath_str is convenience method which returns the text description of
313 * devpath using a static buffer, so it isn't thread safe!
315 char *
316 devpath_str(EFI_DEVICE_PATH *devpath)
318 static char buf[256];
320 devpath_strlcat(buf, sizeof(buf), devpath);
322 return buf;
326 * load_loader attempts to load the loader image data.
328 * It tries each module and its respective devices, identified by mod->probe,
329 * in order until a successful load occurs at which point it returns EFI_SUCCESS
330 * and EFI_NOT_FOUND otherwise.
332 * Only devices which have preferred matching the preferred parameter are tried.
334 static EFI_STATUS
335 load_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp,
336 size_t *bufsize, BOOLEAN preferred)
338 UINTN i;
339 dev_info_t *dev;
340 const boot_module_t *mod;
341 EFI_STATUS status;
343 for (i = 0; i < NUM_BOOT_MODULES; i++) {
344 if (boot_modules[i] == NULL)
345 continue;
346 mod = boot_modules[i];
347 for (dev = mod->devices(); dev != NULL; dev = dev->next) {
348 if (dev->preferred != preferred)
349 continue;
351 status = mod->load(PATH_LOADER, dev, bufp, bufsize);
352 if (status == EFI_NOT_FOUND) {
353 status = mod->load(PATH_LOADER_ALT, dev, bufp,
354 bufsize);
356 if (status == EFI_SUCCESS) {
357 *devinfop = dev;
358 *modp = mod;
359 return (EFI_SUCCESS);
364 return (EFI_NOT_FOUND);
368 * try_boot only returns if it fails to load the loader. If it succeeds
369 * it simply boots, otherwise it returns the status of last EFI call.
371 static EFI_STATUS
372 try_boot(void)
374 size_t bufsize, loadersize, cmdsize;
375 void *buf, *loaderbuf;
376 char *cmd;
377 dev_info_t *dev;
378 const boot_module_t *mod;
379 EFI_HANDLE loaderhandle;
380 EFI_LOADED_IMAGE *loaded_image;
381 EFI_STATUS status;
383 status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE);
384 if (status != EFI_SUCCESS) {
385 status = load_loader(&mod, &dev, &loaderbuf, &loadersize,
386 FALSE);
387 if (status != EFI_SUCCESS) {
388 printf("Failed to load '%s' or '%s'\n",
389 PATH_LOADER, PATH_LOADER_ALT);
390 return (status);
395 * Read in and parse the command line from /boot.config or /boot/config,
396 * if present. We'll pass it the next stage via a simple ASCII
397 * string. loader.efi has a hack for ASCII strings, so we'll use that to
398 * keep the size down here. We only try to read the alternate file if
399 * we get EFI_NOT_FOUND because all other errors mean that the boot_module
400 * had troubles with the filesystem. We could return early, but we'll let
401 * loading the actual kernel sort all that out. Since these files are
402 * optional, we don't report errors in trying to read them.
404 cmd = NULL;
405 cmdsize = 0;
406 status = mod->load(PATH_DOTCONFIG, dev, &buf, &bufsize);
407 if (status == EFI_NOT_FOUND)
408 status = mod->load(PATH_CONFIG, dev, &buf, &bufsize);
409 if (status == EFI_SUCCESS) {
410 cmdsize = bufsize + 1;
411 cmd = malloc(cmdsize);
412 if (cmd == NULL)
413 goto errout;
414 memcpy(cmd, buf, bufsize);
415 cmd[bufsize] = '\0';
416 free(buf);
417 buf = NULL;
420 if ((status = bs->LoadImage(TRUE, image, devpath_last(dev->devpath),
421 loaderbuf, loadersize, &loaderhandle)) != EFI_SUCCESS) {
422 printf("Failed to load image provided by %s, size: %zu, (%llu)\n",
423 mod->name, loadersize, status);
424 goto errout;
427 if ((status = bs->HandleProtocol(loaderhandle, &LoadedImageGUID,
428 (VOID**)&loaded_image)) != EFI_SUCCESS) {
429 printf("Failed to query LoadedImage provided by %s (%llu)\n",
430 mod->name, status);
431 goto errout;
434 if (cmd != NULL)
435 printf(" command args: %s\n", cmd);
437 loaded_image->DeviceHandle = dev->devhandle;
438 loaded_image->LoadOptionsSize = cmdsize;
439 loaded_image->LoadOptions = cmd;
441 DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI);
442 DSTALL(1000000);
443 DPRINTF(".");
444 DSTALL(1000000);
445 DPRINTF(".");
446 DSTALL(1000000);
447 DPRINTF(".");
448 DSTALL(1000000);
449 DPRINTF(".");
450 DSTALL(1000000);
451 DPRINTF(".\n");
453 if ((status = bs->StartImage(loaderhandle, NULL, NULL)) !=
454 EFI_SUCCESS) {
455 printf("Failed to start image provided by %s (%llu)\n",
456 mod->name, status);
457 loaded_image->LoadOptionsSize = 0;
458 loaded_image->LoadOptions = NULL;
461 errout:
462 if (cmd != NULL)
463 free(cmd);
464 if (buf != NULL)
465 free(buf);
466 if (loaderbuf != NULL)
467 free(loaderbuf);
469 return (status);
473 * probe_handle determines if the passed handle represents a logical partition
474 * if it does it uses each module in order to probe it and if successful it
475 * returns EFI_SUCCESS.
477 static EFI_STATUS
478 probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN *preferred)
480 dev_info_t *devinfo;
481 EFI_BLOCK_IO *blkio;
482 EFI_DEVICE_PATH *devpath;
483 EFI_STATUS status;
484 UINTN i;
486 /* Figure out if we're dealing with an actual partition. */
487 status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
488 if (status == EFI_UNSUPPORTED)
489 return (status);
491 if (status != EFI_SUCCESS) {
492 DPRINTF("\nFailed to query DevicePath (%llu)\n",
493 status);
494 return (status);
497 DPRINTF("probing: %s\n", devpath_str(devpath));
499 status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
500 if (status == EFI_UNSUPPORTED)
501 return (status);
503 if (status != EFI_SUCCESS) {
504 DPRINTF("\nFailed to query BlockIoProtocol (%llu)\n",
505 status);
506 return (status);
509 if (!blkio->Media->LogicalPartition)
510 return (EFI_UNSUPPORTED);
512 *preferred = device_paths_match(imgpath, devpath);
514 /* Run through each module, see if it can load this partition */
515 for (i = 0; i < NUM_BOOT_MODULES; i++) {
516 if (boot_modules[i] == NULL)
517 continue;
519 if ((status = bs->AllocatePool(EfiLoaderData,
520 sizeof(*devinfo), (void **)&devinfo)) !=
521 EFI_SUCCESS) {
522 DPRINTF("\nFailed to allocate devinfo (%llu)\n",
523 status);
524 continue;
526 devinfo->dev = blkio;
527 devinfo->devpath = devpath;
528 devinfo->devhandle = h;
529 devinfo->devdata = NULL;
530 devinfo->preferred = *preferred;
531 devinfo->next = NULL;
533 status = boot_modules[i]->probe(devinfo);
534 if (status == EFI_SUCCESS)
535 return (EFI_SUCCESS);
536 (void)bs->FreePool(devinfo);
539 return (EFI_UNSUPPORTED);
543 * probe_handle_status calls probe_handle and outputs the returned status
544 * of the call.
546 static void
547 probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath)
549 EFI_STATUS status;
550 BOOLEAN preferred;
552 preferred = FALSE;
553 status = probe_handle(h, imgpath, &preferred);
555 DPRINTF("probe: ");
556 switch (status) {
557 case EFI_UNSUPPORTED:
558 printf(".");
559 DPRINTF(" not supported\n");
560 break;
561 case EFI_SUCCESS:
562 if (preferred) {
563 printf("%c", '*');
564 DPRINTF(" supported (preferred)\n");
565 } else {
566 printf("%c", '+');
567 DPRINTF(" supported\n");
569 break;
570 default:
571 printf("x");
572 DPRINTF(" error (%llu)\n", status);
573 break;
575 DSTALL(500000);
578 EFI_STATUS
579 efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
581 EFI_HANDLE *handles;
582 EFI_LOADED_IMAGE *img;
583 EFI_DEVICE_PATH *imgpath;
584 EFI_STATUS status;
585 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
586 SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
587 UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles;
589 /* Basic initialization*/
590 systab = Xsystab;
591 image = Ximage;
592 bs = Xsystab->BootServices;
594 /* Set up the console, so printf works. */
595 status = bs->LocateProtocol(&ConsoleControlGUID, NULL,
596 (VOID **)&ConsoleControl);
597 if (status == EFI_SUCCESS)
598 (void)ConsoleControl->SetMode(ConsoleControl,
599 EfiConsoleControlScreenText);
601 * Reset the console and find the best text mode.
603 conout = systab->ConOut;
604 conout->Reset(conout, TRUE);
605 max_dim = best_mode = 0;
606 for (i = 0; ; i++) {
607 status = conout->QueryMode(conout, i, &cols, &rows);
608 if (EFI_ERROR(status)) {
609 /* Mode 1 (80x50) can be unsupported on some hw. */
610 if (i == 1)
611 continue;
612 else
613 break;
615 if (cols * rows > max_dim) {
616 max_dim = cols * rows;
617 best_mode = i;
620 if (max_dim > 0)
621 conout->SetMode(conout, best_mode);
622 conout->EnableCursor(conout, TRUE);
623 conout->ClearScreen(conout);
625 printf("\n>> DragonFly EFI boot block\n");
626 printf(" Loader path: %s:%s\n\n", PATH_LOADER, PATH_LOADER_ALT);
627 printf(" Initializing modules:");
628 for (i = 0; i < NUM_BOOT_MODULES; i++) {
629 if (boot_modules[i] == NULL)
630 continue;
632 printf(" %s", boot_modules[i]->name);
633 if (boot_modules[i]->init != NULL)
634 boot_modules[i]->init();
636 putchar('\n');
638 /* Get all the device handles */
639 hsize = (UINTN)NUM_HANDLES_INIT * sizeof(EFI_HANDLE);
640 if ((status = bs->AllocatePool(EfiLoaderData, hsize, (void **)&handles))
641 != EFI_SUCCESS)
642 panic("Failed to allocate %d handles (%llu)", NUM_HANDLES_INIT,
643 status);
645 status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL,
646 &hsize, handles);
647 switch (status) {
648 case EFI_SUCCESS:
649 break;
650 case EFI_BUFFER_TOO_SMALL:
651 (void)bs->FreePool(handles);
652 if ((status = bs->AllocatePool(EfiLoaderData, hsize,
653 (void **)&handles)) != EFI_SUCCESS) {
654 panic("Failed to allocate %llu handles (%llu)", hsize /
655 sizeof(*handles), status);
657 status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID,
658 NULL, &hsize, handles);
659 if (status != EFI_SUCCESS)
660 panic("Failed to get device handles (%llu)\n",
661 status);
662 break;
663 default:
664 panic("Failed to get device handles (%llu)",
665 status);
668 /* Scan all partitions, probing with all modules. */
669 nhandles = hsize / sizeof(*handles);
670 printf(" Probing %llu block devices...", nhandles);
671 DPRINTF("\n");
673 /* Determine the devpath of our image so we can prefer it. */
674 status = bs->HandleProtocol(image, &LoadedImageGUID, (VOID**)&img);
675 imgpath = NULL;
676 if (status == EFI_SUCCESS) {
677 status = bs->HandleProtocol(img->DeviceHandle, &DevicePathGUID,
678 (void **)&imgpath);
679 if (status != EFI_SUCCESS)
680 DPRINTF("Failed to get image DevicePath (%llu)\n",
681 status);
682 DPRINTF("boot1 imagepath: %s\n", devpath_str(imgpath));
685 for (i = 0; i < nhandles; i++)
686 probe_handle_status(handles[i], imgpath);
687 printf(" done\n");
689 /* Status summary. */
690 for (i = 0; i < NUM_BOOT_MODULES; i++) {
691 if (boot_modules[i] != NULL) {
692 printf(" ");
693 boot_modules[i]->status();
697 try_boot();
699 /* If we get here, we're out of luck... */
700 panic("No bootable partitions found!");
704 * add_device adds a device to the passed devinfo list.
706 void
707 add_device(dev_info_t **devinfop, dev_info_t *devinfo)
709 dev_info_t *dev;
711 if (*devinfop == NULL) {
712 *devinfop = devinfo;
713 return;
716 for (dev = *devinfop; dev->next != NULL; dev = dev->next)
719 dev->next = devinfo;
722 void
723 panic(const char *fmt, ...)
725 va_list ap;
727 printf("panic: ");
728 va_start(ap, fmt);
729 vprintf(fmt, ap);
730 va_end(ap);
731 printf("\n");
733 while (1) {}
736 void
737 putchar(int c)
739 CHAR16 buf[2];
741 if (c == '\n') {
742 buf[0] = '\r';
743 buf[1] = 0;
744 systab->ConOut->OutputString(systab->ConOut, buf);
746 buf[0] = c;
747 buf[1] = 0;
748 systab->ConOut->OutputString(systab->ConOut, buf);