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