xref: /dragonfly/stand/boot/efi/boot1/boot1.c (revision 17183580)
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 	char *cmd;
370 	void *buf;
371 	void *loaderbuf;
372 	dev_info_t *dev;
373 	const boot_module_t *mod;
374 	EFI_HANDLE loaderhandle;
375 	EFI_LOADED_IMAGE *loaded_image;
376 	EFI_STATUS status;
377 
378 	loaderbuf = NULL;
379 	loadersize = 0;
380 
381 	status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE);
382 	if (status != EFI_SUCCESS) {
383 		status = load_loader(&mod, &dev, &loaderbuf,
384 				     &loadersize, FALSE);
385 		if (status != EFI_SUCCESS) {
386 			printf("Failed to load '%s' or '%s'\n",
387 			       PATH_LOADER, PATH_LOADER_ALT);
388 			return (status);
389 		}
390 	}
391 
392 	/*
393 	 * Funcions might not initialize response variables on error, make
394 	 * sure we have sanity.
395 	 */
396 	cmd = NULL;
397 	buf = NULL;
398 	cmdsize = 0;
399 	bufsize = 0;
400 
401 	/*
402 	 * Read in and parse the command line from /boot.config or
403 	 * /boot/config, if present.  We'll pass it the next stage via a
404 	 * simple ASCII string. loader.efi has a hack for ASCII strings, so
405 	 * we'll use that to keep the size down here. We only try to read the
406 	 * alternate file if we get EFI_NOT_FOUND because all other errors
407 	 * mean that the boot_module had troubles with the filesystem. We
408 	 * could return early, but we'll let loading the actual kernel sort
409 	 * all that out. Since these files are optional, we don't report
410 	 * errors in trying to read them.
411 	 */
412 	status = mod->load(PATH_DOTCONFIG, dev, &buf, &bufsize);
413 	if (status == EFI_NOT_FOUND)
414 		status = mod->load(PATH_CONFIG, dev, &buf, &bufsize);
415 	if (status == EFI_SUCCESS) {
416 		cmdsize = bufsize + 1;
417 		cmd = malloc(cmdsize);
418 		if (cmd == NULL)
419 			goto errout;
420 		memcpy(cmd, buf, bufsize);
421 		cmd[bufsize] = '\0';
422 		free(buf);
423 		buf = NULL;
424 	}
425 
426 	status = BS->LoadImage(TRUE, IH, devpath_last(dev->devpath),
427 			       loaderbuf, loadersize, &loaderhandle);
428 	if (status != EFI_SUCCESS) {
429 		printf("Failed to load image provided by %s, "
430 		       "size: %zu, (0x%llx)\n",
431 		       mod->name, loadersize, status);
432 		goto errout;
433 	}
434 
435 	status = OpenProtocolByHandle(loaderhandle, &LoadedImageGUID,
436 				      (VOID**)&loaded_image);
437 	if (status != EFI_SUCCESS) {
438 		printf("Failed to query LoadedImage provided by %s (0x%llx)\n",
439 		    mod->name, status);
440 		goto errout;
441 	}
442 
443 	if (cmd != NULL)
444 		printf("    command args: %s\n", cmd);
445 
446 	loaded_image->DeviceHandle = dev->devhandle;
447 	loaded_image->LoadOptionsSize = cmdsize;
448 	loaded_image->LoadOptions = cmd;
449 
450 	DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI);
451 	DSTALL(1000000);
452 	DPRINTF(".");
453 	DSTALL(1000000);
454 	DPRINTF(".");
455 	DSTALL(1000000);
456 	DPRINTF(".");
457 	DSTALL(1000000);
458 	DPRINTF(".");
459 	DSTALL(1000000);
460 	DPRINTF(".\n");
461 
462 	status = BS->StartImage(loaderhandle, NULL, NULL);
463 	if (status != EFI_SUCCESS) {
464 		printf("Failed to start image provided by %s (0x%llx)\n",
465 		       mod->name, status);
466 		loaded_image->LoadOptionsSize = 0;
467 		loaded_image->LoadOptions = NULL;
468 	}
469 
470 	/*
471 	 * Note that buf and loaderbuf were allocated via boot services,
472 	 * not our local allocator.
473 	 */
474 errout:
475 	if (cmd != NULL)
476 		free(cmd);
477 	if (buf != NULL)
478 		 (void)BS->FreePool(buf);
479 	if (loaderbuf != NULL)
480 		 (void)BS->FreePool(loaderbuf);
481 
482 	return (status);
483 }
484 
485 /*
486  * probe_handle determines if the passed handle represents a logical partition
487  * if it does it uses each module in order to probe it and if successful it
488  * returns EFI_SUCCESS.
489  */
490 static EFI_STATUS
491 probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN *preferred)
492 {
493 	dev_info_t *devinfo;
494 	EFI_BLOCK_IO *blkio;
495 	EFI_DEVICE_PATH *devpath;
496 	EFI_STATUS status;
497 	UINTN i;
498 
499 	/* Figure out if we're dealing with an actual partition. */
500 	status = OpenProtocolByHandle(h, &DevicePathGUID, (void **)&devpath);
501 	if (status == EFI_UNSUPPORTED)
502 		return (status);
503 
504 	if (status != EFI_SUCCESS) {
505 		DPRINTF("\nFailed to query DevicePath (0x%llx)\n",
506 		    status);
507 		return (status);
508 	}
509 
510 	DPRINTF("probing: %s\n", devpath_str(devpath));
511 
512 	status = OpenProtocolByHandle(h, &BlockIoProtocolGUID,
513 				      (void **)&blkio);
514 	if (status == EFI_UNSUPPORTED)
515 		return (status);
516 
517 	if (status != EFI_SUCCESS) {
518 		DPRINTF("\nFailed to query BlockIoProtocol (0x%llx)\n",
519 		    status);
520 		return (status);
521 	}
522 
523 	if (!blkio->Media->LogicalPartition)
524 		return (EFI_UNSUPPORTED);
525 
526 	*preferred = device_paths_match(imgpath, devpath);
527 
528 	/* Run through each module, see if it can load this partition */
529 	for (i = 0; i < NUM_BOOT_MODULES; i++) {
530 		if (boot_modules[i] == NULL)
531 			continue;
532 
533 		status = BS->AllocatePool(EfiLoaderData, sizeof(*devinfo),
534 					  (void **)&devinfo);
535 		if (status != EFI_SUCCESS) {
536 			DPRINTF("\nFailed to allocate devinfo (0x%llx)\n",
537 			    status);
538 			continue;
539 		}
540 		devinfo->dev = blkio;
541 		devinfo->devpath = devpath;
542 		devinfo->devhandle = h;
543 		devinfo->devdata = NULL;
544 		devinfo->preferred = *preferred;
545 		devinfo->next = NULL;
546 
547 		status = boot_modules[i]->probe(devinfo);
548 		if (status == EFI_SUCCESS)
549 			return (EFI_SUCCESS);
550 		(void)BS->FreePool(devinfo);
551 	}
552 
553 	return (EFI_UNSUPPORTED);
554 }
555 
556 /*
557  * probe_handle_status calls probe_handle and outputs the returned status
558  * of the call.
559  */
560 static void
561 probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath)
562 {
563 	EFI_STATUS status;
564 	BOOLEAN preferred;
565 
566 	preferred = FALSE;
567 	status = probe_handle(h, imgpath, &preferred);
568 
569 	DPRINTF("probe: ");
570 	switch (status) {
571 	case EFI_UNSUPPORTED:
572 		printf(".");
573 		DPRINTF(" not supported\n");
574 		break;
575 	case EFI_SUCCESS:
576 		if (preferred) {
577 			printf("%c", '*');
578 			DPRINTF(" supported (preferred)\n");
579 		} else {
580 			printf("%c", '+');
581 			DPRINTF(" supported\n");
582 		}
583 		break;
584 	default:
585 		printf("x");
586 		DPRINTF(" error (0x%llx)\n", status);
587 		break;
588 	}
589 	DSTALL(500000);
590 }
591 
592 EFI_STATUS
593 efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
594 {
595 	EFI_HANDLE *handles;
596 	EFI_LOADED_IMAGE *img;
597 	EFI_DEVICE_PATH *imgpath;
598 	EFI_STATUS status;
599 	EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
600 	SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
601 	UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles;
602 
603 	/* Basic initialization*/
604 	ST = Xsystab;
605 	IH = Ximage;
606 	BS = ST->BootServices;
607 	RS = ST->RuntimeServices;
608 
609 	/* Set up the console, so printf works. */
610 	status = BS->LocateProtocol(&ConsoleControlGUID, NULL,
611 	    (VOID **)&ConsoleControl);
612 	if (status == EFI_SUCCESS)
613 		(void)ConsoleControl->SetMode(ConsoleControl,
614 		    EfiConsoleControlScreenText);
615 	/*
616 	 * Reset the console and find the best text mode.
617 	 */
618 	conout = ST->ConOut;
619 	conout->Reset(conout, TRUE);
620 	max_dim = best_mode = 0;
621 	for (i = 0; ; i++) {
622 		status = conout->QueryMode(conout, i, &cols, &rows);
623 		if (EFI_ERROR(status)) {
624 			/* Mode 1 (80x50) can be unsupported on some hw. */
625 			if (i == 1)
626 				continue;
627 			else
628 				break;
629 		}
630 		if (cols * rows > max_dim) {
631 			max_dim = cols * rows;
632 			best_mode = i;
633 		}
634 	}
635 	if (max_dim > 0)
636 		conout->SetMode(conout, best_mode);
637 	conout->EnableCursor(conout, TRUE);
638 	conout->ClearScreen(conout);
639 
640 	printf("\n>> DragonFly EFI boot block\n");
641 	printf("   Loader path: %s:%s\n\n", PATH_LOADER, PATH_LOADER_ALT);
642 	printf("   Initializing modules:");
643 	for (i = 0; i < NUM_BOOT_MODULES; i++) {
644 		if (boot_modules[i] == NULL)
645 			continue;
646 
647 		printf(" %s", boot_modules[i]->name);
648 		if (boot_modules[i]->init != NULL)
649 			boot_modules[i]->init();
650 	}
651 	putchar('\n');
652 
653 	/* Get all the device handles */
654 	hsize = (UINTN)NUM_HANDLES_INIT * sizeof(EFI_HANDLE);
655 	if ((status = BS->AllocatePool(EfiLoaderData, hsize, (void **)&handles))
656 	    != EFI_SUCCESS)
657 		panic("Failed to allocate %d handles (0x%llx)", NUM_HANDLES_INIT,
658 		    status);
659 
660 	status = BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL,
661 	    &hsize, handles);
662 	switch (status) {
663 	case EFI_SUCCESS:
664 		break;
665 	case EFI_BUFFER_TOO_SMALL:
666 		(void)BS->FreePool(handles);
667 		if ((status = BS->AllocatePool(EfiLoaderData, hsize,
668 		    (void **)&handles)) != EFI_SUCCESS) {
669 			panic("Failed to allocate %llu handles (0x%llx)", hsize /
670 			    sizeof(*handles), status);
671 		}
672 		status = BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID,
673 		    NULL, &hsize, handles);
674 		if (status != EFI_SUCCESS)
675 			panic("Failed to get device handles (0x%llx)\n",
676 			    status);
677 		break;
678 	default:
679 		panic("Failed to get device handles (0x%llx)",
680 		    status);
681 	}
682 
683 	/* Scan all partitions, probing with all modules. */
684 	nhandles = hsize / sizeof(*handles);
685 	printf("   Probing %llu block devices...", nhandles);
686 	DPRINTF("\n");
687 
688 	/* Determine the devpath of our image so we can prefer it. */
689 	status = OpenProtocolByHandle(IH, &LoadedImageGUID, (VOID**)&img);
690 	imgpath = NULL;
691 	if (status == EFI_SUCCESS) {
692 		status = OpenProtocolByHandle(img->DeviceHandle,
693 					      &DevicePathGUID,
694 					      (void **)&imgpath);
695 		if (status != EFI_SUCCESS) {
696 			DPRINTF("Failed to get image DevicePath (0x%llx)\n",
697 			    status);
698 		}
699 		DPRINTF("boot1 imagepath: %s\n", devpath_str(imgpath));
700 	}
701 
702 	for (i = 0; i < nhandles; i++)
703 		probe_handle_status(handles[i], imgpath);
704 	printf(" done\n");
705 
706 	/* Status summary. */
707 	for (i = 0; i < NUM_BOOT_MODULES; i++) {
708 		if (boot_modules[i] != NULL) {
709 			printf("    ");
710 			boot_modules[i]->status();
711 		}
712 	}
713 
714 	try_boot();
715 
716 	/* If we get here, we're out of luck... */
717 	panic("No bootable partitions found!");
718 }
719 
720 /*
721  * add_device adds a device to the passed devinfo list.
722  */
723 void
724 add_device(dev_info_t **devinfop, dev_info_t *devinfo)
725 {
726 	dev_info_t *dev;
727 
728 	if (*devinfop == NULL) {
729 		*devinfop = devinfo;
730 		return;
731 	}
732 
733 	for (dev = *devinfop; dev->next != NULL; dev = dev->next)
734 		;
735 
736 	dev->next = devinfo;
737 }
738 
739 void
740 panic(const char *fmt, ...)
741 {
742 	va_list ap;
743 
744 	printf("panic: ");
745 	va_start(ap, fmt);
746 	vprintf(fmt, ap);
747 	va_end(ap);
748 	printf("\n");
749 
750 	while (1) {}
751 }
752 
753 void
754 putchar(int c)
755 {
756 	CHAR16 buf[2];
757 
758 	if (c == '\n') {
759 		buf[0] = '\r';
760 		buf[1] = 0;
761 		ST->ConOut->OutputString(ST->ConOut, buf);
762 	}
763 	buf[0] = c;
764 	buf[1] = 0;
765 	ST->ConOut->OutputString(ST->ConOut, buf);
766 }
767