xref: /illumos-gate/usr/src/boot/efi/loader/main.c (revision 2a347f24)
1 /*
2  * Copyright (c) 2008-2010 Rui Paulo
3  * Copyright (c) 2006 Marcel Moolenaar
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 
30 #include <sys/disk.h>
31 #include <sys/param.h>
32 #include <sys/reboot.h>
33 #include <sys/boot.h>
34 #include <sys/consplat.h>
35 #include <sys/zfs_bootenv.h>
36 #include <stand.h>
37 #include <inttypes.h>
38 #include <string.h>
39 #include <setjmp.h>
40 #include <disk.h>
41 
42 #include <efi.h>
43 #include <efilib.h>
44 #include <efigpt.h>
45 #include <efichar.h>
46 
47 #include <uuid.h>
48 
49 #include <bootstrap.h>
50 #include <gfx_fb.h>
51 #include <smbios.h>
52 
53 #include <libzfs.h>
54 #include <efizfs.h>
55 
56 #include "loader_efi.h"
57 
58 struct arch_switch archsw;	/* MI/MD interface boundary */
59 
60 EFI_GUID devid = DEVICE_PATH_PROTOCOL;
61 EFI_GUID imgid = LOADED_IMAGE_PROTOCOL;
62 EFI_GUID smbios = SMBIOS_TABLE_GUID;
63 EFI_GUID smbios3 = SMBIOS3_TABLE_GUID;
64 EFI_GUID inputid = SIMPLE_TEXT_INPUT_PROTOCOL;
65 EFI_GUID serialio = SERIAL_IO_PROTOCOL;
66 
67 extern void acpi_detect(void);
68 extern void efi_getsmap(void);
69 
70 static EFI_LOADED_IMAGE *img;
71 
72 /*
73  * Number of seconds to wait for a keystroke before exiting with failure
74  * in the event no currdev is found. -2 means always break, -1 means
75  * never break, 0 means poll once and then reboot, > 0 means wait for
76  * that many seconds. "fail_timeout" can be set in the environment as
77  * well.
78  */
79 static int fail_timeout = 5;
80 
81 bool
82 efi_zfs_is_preferred(EFI_HANDLE *h)
83 {
84 	EFI_DEVICE_PATH *devpath, *dp, *node;
85 	HARDDRIVE_DEVICE_PATH *hd;
86 	bool ret;
87 	extern UINT64 start_sector;	/* from mb_header.S */
88 
89 	/* This check is true for chainloader case. */
90 	if (h == img->DeviceHandle)
91 		return (true);
92 
93 	/*
94 	 * Make sure the image was loaded from the hard disk.
95 	 */
96 	devpath = efi_lookup_devpath(img->DeviceHandle);
97 	if (devpath == NULL)
98 		return (false);
99 	node = efi_devpath_last_node(devpath);
100 	if (node == NULL)
101 		return (false);
102 	if (DevicePathType(node) != MEDIA_DEVICE_PATH ||
103 	    (DevicePathSubType(node) != MEDIA_FILEPATH_DP &&
104 	    DevicePathSubType(node) != MEDIA_HARDDRIVE_DP)) {
105 		return (false);
106 	}
107 
108 	/*
109 	 * XXX We ignore the MEDIA_FILEPATH_DP here for now as it is
110 	 * used on arm and we do not support arm.
111 	 */
112 	ret = false;
113 	dp = efi_devpath_trim(devpath);
114 	devpath = NULL;
115 	if (dp == NULL)
116 		goto done;
117 
118 	devpath = efi_lookup_devpath(h);
119 	if (devpath == NULL)
120 		goto done;
121 	hd = (HARDDRIVE_DEVICE_PATH *)efi_devpath_last_node(devpath);
122 	if (hd == NULL) {
123 		devpath = NULL;
124 		goto done;
125 	}
126 	devpath = efi_devpath_trim(devpath);
127 	if (devpath == NULL)
128 		goto done;
129 
130 	if (!efi_devpath_match(dp, devpath))
131 		goto done;
132 
133 	/* It is the same disk, do we have partition start? */
134 	if (start_sector == 0)
135 		ret = true;
136 	else if (start_sector == hd->PartitionStart)
137 		ret = true;
138 
139 done:
140 	free(dp);
141 	free(devpath);
142 	return (ret);
143 }
144 
145 static bool
146 has_keyboard(void)
147 {
148 	EFI_STATUS status;
149 	EFI_DEVICE_PATH *path;
150 	EFI_HANDLE *hin, *hin_end, *walker;
151 	UINTN sz;
152 	bool retval = false;
153 
154 	/*
155 	 * Find all the handles that support the SIMPLE_TEXT_INPUT_PROTOCOL and
156 	 * do the typical dance to get the right sized buffer.
157 	 */
158 	sz = 0;
159 	hin = NULL;
160 	status = BS->LocateHandle(ByProtocol, &inputid, 0, &sz, 0);
161 	if (status == EFI_BUFFER_TOO_SMALL) {
162 		hin = (EFI_HANDLE *)malloc(sz);
163 		status = BS->LocateHandle(ByProtocol, &inputid, 0, &sz,
164 		    hin);
165 		if (EFI_ERROR(status))
166 			free(hin);
167 	}
168 	if (EFI_ERROR(status))
169 		return (retval);
170 
171 	/*
172 	 * Look at each of the handles. If it supports the device path protocol,
173 	 * use it to get the device path for this handle. Then see if that
174 	 * device path matches either the USB device path for keyboards or the
175 	 * legacy device path for keyboards.
176 	 */
177 	hin_end = &hin[sz / sizeof (*hin)];
178 	for (walker = hin; walker < hin_end; walker++) {
179 		status = OpenProtocolByHandle(*walker, &devid, (void **)&path);
180 		if (EFI_ERROR(status))
181 			continue;
182 
183 		while (!IsDevicePathEnd(path)) {
184 			/*
185 			 * Check for the ACPI keyboard node. All PNP3xx nodes
186 			 * are keyboards of different flavors. Note: It is
187 			 * unclear of there's always a keyboard node when
188 			 * there's a keyboard controller, or if there's only one
189 			 * when a keyboard is detected at boot.
190 			 */
191 			if (DevicePathType(path) == ACPI_DEVICE_PATH &&
192 			    (DevicePathSubType(path) == ACPI_DP ||
193 			    DevicePathSubType(path) == ACPI_EXTENDED_DP)) {
194 				ACPI_HID_DEVICE_PATH  *acpi;
195 
196 				acpi = (ACPI_HID_DEVICE_PATH *)(void *)path;
197 				if ((EISA_ID_TO_NUM(acpi->HID) & 0xff00) ==
198 				    0x300 &&
199 				    (acpi->HID & 0xffff) == PNP_EISA_ID_CONST) {
200 					retval = true;
201 					goto out;
202 				}
203 			/*
204 			 * Check for USB keyboard node, if present. Unlike a
205 			 * PS/2 keyboard, these definitely only appear when
206 			 * connected to the system.
207 			 */
208 			} else if (DevicePathType(path) ==
209 			    MESSAGING_DEVICE_PATH &&
210 			    DevicePathSubType(path) == MSG_USB_CLASS_DP) {
211 				USB_CLASS_DEVICE_PATH *usb;
212 
213 				/*
214 				 * Check for:
215 				 * DeviceClass: HID
216 				 * DeviceSubClass: Boot devices
217 				 * DeviceProtocol: Boot keyboards
218 				 */
219 				usb = (USB_CLASS_DEVICE_PATH *)(void *)path;
220 				if (usb->DeviceClass == 3 &&
221 				    usb->DeviceSubClass == 1 &&
222 				    usb->DeviceProtocol == 1) {
223 					retval = true;
224 					goto out;
225 				}
226 			}
227 			path = NextDevicePathNode(path);
228 		}
229 	}
230 out:
231 	free(hin);
232 	return (retval);
233 }
234 
235 static void
236 set_currdev(const char *devname)
237 {
238 
239 	/*
240 	 * Don't execute hooks here; we may need to try setting these more than
241 	 * once here if we're probing for the ZFS pool we're supposed to boot.
242 	 * The currdev hook is intended to just validate user input anyways,
243 	 * while the loaddev hook makes it immutable once we've determined what
244 	 * the proper currdev is.
245 	 */
246 	env_setenv("currdev", EV_VOLATILE | EV_NOHOOK, devname, efi_setcurrdev,
247 	    env_nounset);
248 	env_setenv("loaddev", EV_VOLATILE | EV_NOHOOK, devname, env_noset,
249 	    env_nounset);
250 }
251 
252 static void
253 set_currdev_devdesc(struct devdesc *currdev)
254 {
255 	char *devname;
256 
257 	devname = efi_fmtdev(currdev);
258 
259 	printf("Setting currdev to %s\n", devname);
260 	set_currdev(devname);
261 }
262 
263 static void
264 set_currdev_devsw(struct devsw *dev, int unit)
265 {
266 	struct devdesc currdev;
267 
268 	currdev.d_dev = dev;
269 	currdev.d_unit = unit;
270 
271 	set_currdev_devdesc(&currdev);
272 }
273 
274 static void
275 set_currdev_pdinfo(pdinfo_t *dp)
276 {
277 
278 	/*
279 	 * Disks are special: they have partitions. if the parent
280 	 * pointer is non-null, we're a partition not a full disk
281 	 * and we need to adjust currdev appropriately.
282 	 */
283 	if (dp->pd_devsw->dv_type == DEVT_DISK) {
284 		struct disk_devdesc currdev;
285 
286 		currdev.dd.d_dev = dp->pd_devsw;
287 		if (dp->pd_parent == NULL) {
288 			currdev.dd.d_unit = dp->pd_unit;
289 			currdev.d_slice = D_SLICENONE;
290 			currdev.d_partition = D_PARTNONE;
291 		} else {
292 			currdev.dd.d_unit = dp->pd_parent->pd_unit;
293 			currdev.d_slice = dp->pd_unit;
294 			currdev.d_partition = D_PARTISGPT; /* Assumes GPT */
295 		}
296 		set_currdev_devdesc((struct devdesc *)&currdev);
297 	} else {
298 		set_currdev_devsw(dp->pd_devsw, dp->pd_unit);
299 	}
300 }
301 
302 static bool
303 sanity_check_currdev(void)
304 {
305 	struct stat st;
306 
307 	return (stat("/boot/defaults/loader.conf", &st) == 0);
308 }
309 
310 static bool
311 probe_zfs_currdev(uint64_t guid)
312 {
313 	struct zfs_devdesc currdev;
314 	char *bootonce;
315 	bool rv;
316 
317 	currdev.dd.d_dev = &zfs_dev;
318 	currdev.dd.d_unit = 0;
319 	currdev.pool_guid = guid;
320 	currdev.root_guid = 0;
321 	set_currdev_devdesc((struct devdesc *)&currdev);
322 
323 	rv = sanity_check_currdev();
324 	if (rv) {
325 		bootonce = malloc(VDEV_PAD_SIZE);
326 		if (bootonce != NULL) {
327 			if (zfs_get_bootonce(&currdev, OS_BOOTONCE, bootonce,
328 			    VDEV_PAD_SIZE) == 0) {
329 				printf("zfs bootonce: %s\n", bootonce);
330 				set_currdev(bootonce);
331 				setenv("zfs-bootonce", bootonce, 1);
332 			}
333 			free(bootonce);
334 			(void) zfs_attach_nvstore(&currdev);
335 		} else {
336 			printf("Failed to process bootonce data: %s\n",
337 			    strerror(errno));
338 		}
339 	}
340 	return (rv);
341 }
342 
343 static bool
344 try_as_currdev(pdinfo_t *pp)
345 {
346 	uint64_t guid;
347 
348 	/*
349 	 * If there's a zpool on this device, try it as a ZFS
350 	 * filesystem, which has somewhat different setup than all
351 	 * other types of fs due to imperfect loader integration.
352 	 * This all stems from ZFS being both a device (zpool) and
353 	 * a filesystem, plus the boot env feature.
354 	 */
355 	if (efizfs_get_guid_by_handle(pp->pd_handle, &guid))
356 		return (probe_zfs_currdev(guid));
357 
358 	/*
359 	 * All other filesystems just need the pdinfo
360 	 * initialized in the standard way.
361 	 */
362 	set_currdev_pdinfo(pp);
363 	return (sanity_check_currdev());
364 }
365 
366 static bool
367 find_currdev(EFI_LOADED_IMAGE *img)
368 {
369 	pdinfo_t *dp, *pp;
370 	EFI_DEVICE_PATH *devpath, *copy;
371 	EFI_HANDLE h;
372 	CHAR16 *text;
373 	struct devsw *dev;
374 	int unit;
375 	uint64_t extra;
376 
377 	/*
378 	 * Did efi_zfs_probe() detect the boot pool? If so, use the zpool
379 	 * it found, if it's sane. ZFS is the only thing that looks for
380 	 * disks and pools to boot.
381 	 */
382 	if (pool_guid != 0) {
383 		printf("Trying ZFS pool\n");
384 		if (probe_zfs_currdev(pool_guid))
385 			return (true);
386 	}
387 
388 	/*
389 	 * Try to find the block device by its handle based on the
390 	 * image we're booting. If we can't find a sane partition,
391 	 * search all the other partitions of the disk. We do not
392 	 * search other disks because it's a violation of the UEFI
393 	 * boot protocol to do so. We fail and let UEFI go on to
394 	 * the next candidate.
395 	 */
396 	dp = efiblk_get_pdinfo_by_handle(img->DeviceHandle);
397 	if (dp != NULL) {
398 		text = efi_devpath_name(dp->pd_devpath);
399 		if (text != NULL) {
400 			printf("Trying ESP: %S\n", text);
401 			efi_free_devpath_name(text);
402 		}
403 		set_currdev_pdinfo(dp);
404 		if (sanity_check_currdev())
405 			return (true);
406 		if (dp->pd_parent != NULL) {
407 			dp = dp->pd_parent;
408 			STAILQ_FOREACH(pp, &dp->pd_part, pd_link) {
409 				text = efi_devpath_name(pp->pd_devpath);
410 				if (text != NULL) {
411 					printf("And now the part: %S\n", text);
412 					efi_free_devpath_name(text);
413 				}
414 				/*
415 				 * Roll up the ZFS special case
416 				 * for those partitions that have
417 				 * zpools on them
418 				 */
419 				if (try_as_currdev(pp))
420 					return (true);
421 			}
422 		}
423 	} else {
424 		printf("Can't find device by handle\n");
425 	}
426 
427 	/*
428 	 * Try the device handle from our loaded image first.  If that
429 	 * fails, use the device path from the loaded image and see if
430 	 * any of the nodes in that path match one of the enumerated
431 	 * handles. Currently, this handle list is only for netboot.
432 	 */
433 	if (efi_handle_lookup(img->DeviceHandle, &dev, &unit, &extra) == 0) {
434 		set_currdev_devsw(dev, unit);
435 		if (sanity_check_currdev())
436 			return (true);
437 	}
438 
439 	copy = NULL;
440 	devpath = efi_lookup_image_devpath(IH);
441 	while (devpath != NULL) {
442 		h = efi_devpath_handle(devpath);
443 		if (h == NULL)
444 			break;
445 
446 		free(copy);
447 		copy = NULL;
448 
449 		if (efi_handle_lookup(h, &dev, &unit, &extra) == 0) {
450 			set_currdev_devsw(dev, unit);
451 			if (sanity_check_currdev())
452 				return (true);
453 		}
454 
455 		devpath = efi_lookup_devpath(h);
456 		if (devpath != NULL) {
457 			copy = efi_devpath_trim(devpath);
458 			devpath = copy;
459 		}
460 	}
461 	free(copy);
462 
463 	return (false);
464 }
465 
466 static bool
467 interactive_interrupt(const char *msg)
468 {
469 	time_t now, then, last;
470 
471 	last = 0;
472 	now = then = getsecs();
473 	printf("%s\n", msg);
474 	if (fail_timeout == -2)			/* Always break to OK */
475 		return (true);
476 	if (fail_timeout == -1)			/* Never break to OK */
477 		return (false);
478 	do {
479 		if (last != now) {
480 			printf("press any key to interrupt reboot "
481 			    "in %d seconds\r",
482 			    fail_timeout - (int)(now - then));
483 			last = now;
484 		}
485 
486 		/* XXX no pause or timeout wait for char */
487 		if (ischar())
488 			return (true);
489 		now = getsecs();
490 	} while (now - then < fail_timeout);
491 	return (false);
492 }
493 
494 static void
495 setenv_int(const char *key, int val)
496 {
497 	char buf[20];
498 
499 	(void) snprintf(buf, sizeof (buf), "%d", val);
500 	(void) setenv(key, buf, 1);
501 }
502 
503 /*
504  * Parse ConOut (the list of consoles active) and see if we can find a
505  * serial port and/or a video port. It would be nice to also walk the
506  * ACPI name space to map the UID for the serial port to a port. The
507  * latter is especially hard.
508  */
509 static int
510 parse_uefi_con_out(void)
511 {
512 	int how, rv;
513 	int vid_seen = 0, com_seen = 0, seen = 0;
514 	size_t sz;
515 	char buf[4096], *ep;
516 	EFI_DEVICE_PATH *node;
517 	ACPI_HID_DEVICE_PATH *acpi;
518 	UART_DEVICE_PATH *uart;
519 	bool pci_pending = false;
520 
521 	how = 0;
522 	sz = sizeof (buf);
523 	rv = efi_global_getenv("ConOut", buf, &sz);
524 	if (rv != EFI_SUCCESS)
525 		rv = efi_global_getenv("ConOutDev", buf, &sz);
526 	if (rv != EFI_SUCCESS) {
527 		/*
528 		 * If we don't have any ConOut default to video.
529 		 * non-server systems may not have serial.
530 		 */
531 		goto out;
532 	}
533 	ep = buf + sz;
534 	node = (EFI_DEVICE_PATH *)buf;
535 	while ((char *)node < ep) {
536 		if (IsDevicePathEndType(node)) {
537 			if (pci_pending && vid_seen == 0)
538 				vid_seen = ++seen;
539 		}
540 		pci_pending = false;
541 		if (DevicePathType(node) == ACPI_DEVICE_PATH &&
542 		    (DevicePathSubType(node) == ACPI_DP ||
543 		    DevicePathSubType(node) == ACPI_EXTENDED_DP)) {
544 			/* Check for Serial node */
545 			acpi = (void *)node;
546 			if (EISA_ID_TO_NUM(acpi->HID) == 0x501) {
547 				setenv_int("efi_8250_uid", acpi->UID);
548 				com_seen = ++seen;
549 			}
550 		} else if (DevicePathType(node) == MESSAGING_DEVICE_PATH &&
551 		    DevicePathSubType(node) == MSG_UART_DP) {
552 			com_seen = ++seen;
553 			uart = (void *)node;
554 			setenv_int("efi_com_speed", uart->BaudRate);
555 		} else if (DevicePathType(node) == ACPI_DEVICE_PATH &&
556 		    DevicePathSubType(node) == ACPI_ADR_DP) {
557 			/* Check for AcpiAdr() Node for video */
558 			vid_seen = ++seen;
559 		} else if (DevicePathType(node) == HARDWARE_DEVICE_PATH &&
560 		    DevicePathSubType(node) == HW_PCI_DP) {
561 			/*
562 			 * Note, vmware fusion has a funky console device
563 			 *	PciRoot(0x0)/Pci(0xf,0x0)
564 			 * which we can only detect at the end since we also
565 			 * have to cope with:
566 			 *	PciRoot(0x0)/Pci(0x1f,0x0)/Serial(0x1)
567 			 * so only match it if it's last.
568 			 */
569 			pci_pending = true;
570 		}
571 		node = NextDevicePathNode(node); /* Skip the end node */
572 	}
573 
574 	/*
575 	 * Truth table for RB_MULTIPLE | RB_SERIAL
576 	 * Value		Result
577 	 * 0			Use only video console
578 	 * RB_SERIAL		Use only serial console
579 	 * RB_MULTIPLE		Use both video and serial console
580 	 *			(but video is primary so gets rc messages)
581 	 * both			Use both video and serial console
582 	 *			(but serial is primary so gets rc messages)
583 	 *
584 	 * Try to honor this as best we can. If only one of serial / video
585 	 * found, then use that. Otherwise, use the first one we found.
586 	 * This also implies if we found nothing, default to video.
587 	 */
588 	how = 0;
589 	if (vid_seen && com_seen) {
590 		how |= RB_MULTIPLE;
591 		if (com_seen < vid_seen)
592 			how |= RB_SERIAL;
593 	} else if (com_seen)
594 		how |= RB_SERIAL;
595 out:
596 	return (how);
597 }
598 
599 caddr_t
600 ptov(uintptr_t x)
601 {
602 	return ((caddr_t)x);
603 }
604 
605 static int
606 efi_serial_get_uid(EFI_DEVICE_PATH *devpath)
607 {
608 	ACPI_HID_DEVICE_PATH  *acpi;
609 
610 	while (!IsDevicePathEnd(devpath)) {
611 		if (DevicePathType(devpath) == ACPI_DEVICE_PATH &&
612 		    (DevicePathSubType(devpath) == ACPI_DP ||
613 		    DevicePathSubType(devpath) == ACPI_EXTENDED_DP)) {
614 			acpi = (ACPI_HID_DEVICE_PATH *)devpath;
615 			if (EISA_ID_TO_NUM(acpi->HID) == 0x501) {
616 				return (acpi->UID);
617 			}
618 		}
619 
620 		devpath = NextDevicePathNode(devpath);
621 	}
622 	return (-1);
623 }
624 
625 /*
626  * Walk serialio protocol handle array and find index for serial console
627  * device. The problem is, we check for acpi UID value, but we can not be sure,
628  * if it will start from 0 or 1.
629  */
630 static const char *
631 uefi_serial_console(void)
632 {
633 	UINTN bufsz;
634 	EFI_STATUS status;
635 	EFI_HANDLE *handles;
636 	int i, nhandles;
637 	unsigned long uid, lowest;
638 	char *env, *ep;
639 	extern struct console ttya;
640 	extern struct console ttyb;
641 	extern struct console ttyc;
642 	extern struct console ttyd;
643 
644 	env = getenv("efi_8250_uid");
645 	if (env == NULL)
646 		return (NULL);
647 	(void) unsetenv("efi_8250_uid");
648 	errno = 0;
649 	uid = strtoul(env, &ep, 10);
650 	if (errno != 0 || *ep != '\0')
651 		return (NULL);
652 
653 	/* if uid is 0, this is first serial port */
654 	if (uid == 0)
655 		return (ttya.c_name);
656 
657 	/*
658 	 * get buffer size
659 	 */
660 	bufsz = 0;
661 	handles = NULL;
662 	status = BS->LocateHandle(ByProtocol, &serialio, NULL, &bufsz, handles);
663 	if (status != EFI_BUFFER_TOO_SMALL)
664 		return (NULL);
665 	if ((handles = malloc(bufsz)) == NULL)
666 		return (NULL);
667 
668 	/*
669 	 * get handle array
670 	 */
671 	status = BS->LocateHandle(ByProtocol, &serialio, NULL, &bufsz, handles);
672 	if (EFI_ERROR(status)) {
673 		free(handles);
674 		return (NULL);
675 	}
676 	nhandles = (int)(bufsz / sizeof (EFI_HANDLE));
677 
678 	lowest = 255;	/* high enough value */
679 	for (i = 0; i < nhandles; i++) {
680 		EFI_DEVICE_PATH *devpath;
681 		unsigned long _uid;
682 
683 		devpath = efi_lookup_devpath(handles[i]);
684 		_uid = efi_serial_get_uid(devpath);
685 		if (_uid < lowest)
686 			lowest = _uid;
687 	}
688 	free(handles);
689 	switch (uid - lowest) {
690 	case 0:
691 		return (ttya.c_name);
692 	case 1:
693 		return (ttyb.c_name);
694 	case 2:
695 		return (ttyc.c_name);
696 	case 3:
697 		return (ttyd.c_name);
698 	}
699 	return (NULL);
700 }
701 
702 EFI_STATUS
703 main(int argc, CHAR16 *argv[])
704 {
705 	char var[128];
706 	int i, j, howto;
707 	bool vargood;
708 	void *ptr;
709 	bool has_kbd;
710 	char *s;
711 	const char *serial;
712 	EFI_DEVICE_PATH *imgpath;
713 	CHAR16 *text;
714 	EFI_STATUS status;
715 	UINT16 boot_current;
716 	size_t sz;
717 	UINT16 boot_order[100];
718 
719 	archsw.arch_autoload = efi_autoload;
720 	archsw.arch_getdev = efi_getdev;
721 	archsw.arch_copyin = efi_copyin;
722 	archsw.arch_copyout = efi_copyout;
723 	archsw.arch_readin = efi_readin;
724 	archsw.arch_loadaddr = efi_loadaddr;
725 	archsw.arch_free_loadaddr = efi_free_loadaddr;
726 #if defined(__amd64) || defined(__i386)
727 	archsw.arch_hypervisor = x86_hypervisor;
728 #endif
729 	/* Note this needs to be set before ZFS init. */
730 	archsw.arch_zfs_probe = efi_zfs_probe;
731 
732 	/* Get our loaded image protocol interface structure. */
733 	(void) OpenProtocolByHandle(IH, &imgid, (void **)&img);
734 
735 	/*
736 	 * XXX Chicken-and-egg problem; we want to have console output
737 	 * early, but some console attributes may depend on reading from
738 	 * eg. the boot device, which we can't do yet.  We can use
739 	 * printf() etc. once this is done.
740 	 */
741 	setenv("console", "text", 1);
742 	howto = parse_uefi_con_out();
743 	serial = uefi_serial_console();
744 	cons_probe();
745 	efi_getsmap();
746 
747 	if ((s = getenv("efi_com_speed")) != NULL) {
748 		char *name;
749 
750 		(void) snprintf(var, sizeof (var), "%s,8,n,1,-", s);
751 		if (asprintf(&name, "%s-mode", serial) > 0) {
752 			(void) setenv(name, var, 1);
753 			free(name);
754 		}
755 		if (asprintf(&name, "%s-spcr-mode", serial) > 0) {
756 			(void) setenv(name, var, 1);
757 			free(name);
758 		}
759 		(void) unsetenv("efi_com_speed");
760 	}
761 
762 	/* Init the time source */
763 	efi_time_init();
764 
765 	/*
766 	 * Initialise the block cache. Set the upper limit.
767 	 */
768 	bcache_init(32768, 512);
769 
770 	has_kbd = has_keyboard();
771 
772 	/*
773 	 * Parse the args to set the console settings, etc
774 	 * iPXE may be setup to pass these in. Or the optional argument in the
775 	 * boot environment was used to pass these arguments in (in which case
776 	 * neither /boot.config nor /boot/config are consulted).
777 	 *
778 	 * Loop through the args, and for each one that contains an '=' that is
779 	 * not the first character, add it to the environment.  This allows
780 	 * loader and kernel env vars to be passed on the command line.  Convert
781 	 * args from UCS-2 to ASCII (16 to 8 bit) as they are copied (though
782 	 * this method is flawed for non-ASCII characters).
783 	 */
784 	for (i = 1; i < argc; i++) {
785 		if (argv[i][0] == '-') {
786 			for (j = 1; argv[i][j] != 0; j++) {
787 				int ch;
788 
789 				ch = argv[i][j];
790 				switch (ch) {
791 				case 'a':
792 					howto |= RB_ASKNAME;
793 					break;
794 				case 'd':
795 					howto |= RB_KDB;
796 					break;
797 				case 'D':
798 					howto |= RB_MULTIPLE;
799 					break;
800 				case 'h':
801 					howto |= RB_SERIAL;
802 					break;
803 				case 'm':
804 					howto |= RB_MUTE;
805 					break;
806 				case 'p':
807 					howto |= RB_PAUSE;
808 					break;
809 				case 'P':
810 					if (!has_kbd) {
811 						howto |= RB_SERIAL;
812 						howto |= RB_MULTIPLE;
813 					}
814 					break;
815 				case 'r':
816 					howto |= RB_DFLTROOT;
817 					break;
818 				case 's':
819 					howto |= RB_SINGLE;
820 					break;
821 				case 'S':
822 					if (argv[i][j + 1] == 0) {
823 						if (i + 1 == argc) {
824 							strncpy(var, "115200",
825 							    sizeof (var));
826 						} else {
827 							CHAR16 *ptr;
828 							ptr = &argv[i + 1][0];
829 							cpy16to8(ptr, var,
830 							    sizeof (var));
831 						}
832 						i++;
833 					} else {
834 						cpy16to8(&argv[i][j + 1], var,
835 						    sizeof (var));
836 					}
837 					strncat(var, ",8,n,1,-", sizeof (var));
838 					setenv("ttya-mode", var, 1);
839 					break;
840 				case 'v':
841 					howto |= RB_VERBOSE;
842 					break;
843 				}
844 			}
845 		} else {
846 			vargood = false;
847 			for (j = 0; argv[i][j] != 0; j++) {
848 				if (j == sizeof (var)) {
849 					vargood = false;
850 					break;
851 				}
852 				if (j > 0 && argv[i][j] == '=')
853 					vargood = true;
854 				var[j] = (char)argv[i][j];
855 			}
856 			if (vargood) {
857 				var[j] = 0;
858 				putenv(var);
859 			}
860 		}
861 	}
862 	for (i = 0; howto_names[i].ev != NULL; i++)
863 		if (howto & howto_names[i].mask)
864 			setenv(howto_names[i].ev, "YES", 1);
865 
866 	/*
867 	 * XXX we need fallback to this stuff after looking at the ConIn,
868 	 * ConOut and ConErr variables.
869 	 */
870 	if (howto & RB_MULTIPLE) {
871 		if (howto & RB_SERIAL)
872 			(void) snprintf(var, sizeof (var), "%s text", serial);
873 		else
874 			(void) snprintf(var, sizeof (var), "text %s", serial);
875 	} else if (howto & RB_SERIAL) {
876 		(void) snprintf(var, sizeof (var), "%s", serial);
877 	} else {
878 		(void) snprintf(var, sizeof (var), "text");
879 	}
880 	(void) setenv("console", var, 1);
881 
882 	if ((s = getenv("fail_timeout")) != NULL)
883 		fail_timeout = strtol(s, NULL, 10);
884 
885 	/*
886 	 * Scan the BLOCK IO MEDIA handles then
887 	 * march through the device switch probing for things.
888 	 */
889 	if ((i = efipart_inithandles()) == 0) {
890 		for (i = 0; devsw[i] != NULL; i++)
891 			if (devsw[i]->dv_init != NULL)
892 				(devsw[i]->dv_init)();
893 	} else
894 		printf("efipart_inithandles failed %d, expect failures", i);
895 
896 	printf("Command line arguments:");
897 	for (i = 0; i < argc; i++) {
898 		printf(" %S", argv[i]);
899 	}
900 	printf("\n");
901 
902 	printf("Image base: 0x%lx\n", (unsigned long)img->ImageBase);
903 	printf("EFI version: %d.%02d\n", ST->Hdr.Revision >> 16,
904 	    ST->Hdr.Revision & 0xffff);
905 	printf("EFI Firmware: %S (rev %d.%02d)\n", ST->FirmwareVendor,
906 	    ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
907 
908 	printf("\n%s", bootprog_info);
909 
910 	/* Determine the devpath of our image so we can prefer it. */
911 	text = efi_devpath_name(img->FilePath);
912 	if (text != NULL) {
913 		printf("   Load Path: %S\n", text);
914 		efi_setenv_illumos_wcs("LoaderPath", text);
915 		efi_free_devpath_name(text);
916 	}
917 
918 	status = OpenProtocolByHandle(img->DeviceHandle, &devid,
919 	    (void **)&imgpath);
920 	if (status == EFI_SUCCESS) {
921 		text = efi_devpath_name(imgpath);
922 		if (text != NULL) {
923 			printf("   Load Device: %S\n", text);
924 			efi_setenv_illumos_wcs("LoaderDev", text);
925 			efi_free_devpath_name(text);
926 		}
927 	}
928 
929 	boot_current = 0;
930 	sz = sizeof (boot_current);
931 	efi_global_getenv("BootCurrent", &boot_current, &sz);
932 	printf("   BootCurrent: %04x\n", boot_current);
933 
934 	sz = sizeof (boot_order);
935 	efi_global_getenv("BootOrder", &boot_order, &sz);
936 	printf("   BootOrder:");
937 	for (i = 0; i < sz / sizeof (boot_order[0]); i++)
938 		printf(" %04x%s", boot_order[i],
939 		    boot_order[i] == boot_current ? "[*]" : "");
940 	printf("\n");
941 
942 	/*
943 	 * Disable the watchdog timer. By default the boot manager sets
944 	 * the timer to 5 minutes before invoking a boot option. If we
945 	 * want to return to the boot manager, we have to disable the
946 	 * watchdog timer and since we're an interactive program, we don't
947 	 * want to wait until the user types "quit". The timer may have
948 	 * fired by then. We don't care if this fails. It does not prevent
949 	 * normal functioning in any way...
950 	 */
951 	BS->SetWatchdogTimer(0, 0, 0, NULL);
952 
953 	/*
954 	 * Try and find a good currdev based on the image that was booted.
955 	 * It might be desirable here to have a short pause to allow falling
956 	 * through to the boot loader instead of returning instantly to follow
957 	 * the boot protocol and also allow an escape hatch for users wishing
958 	 * to try something different.
959 	 */
960 	if (!find_currdev(img))
961 		if (!interactive_interrupt("Failed to find bootable partition"))
962 			return (EFI_NOT_FOUND);
963 
964 	autoload_font(false);		/* Set up the font list for console. */
965 	efi_init_environment();
966 	setenv("ISADIR", "amd64", 1);	/* we only build 64bit */
967 	bi_isadir();			/* set ISADIR */
968 	acpi_detect();
969 
970 	if ((ptr = efi_get_table(&smbios3)) == NULL)
971 		ptr = efi_get_table(&smbios);
972 	smbios_detect(ptr);
973 
974 	interact(NULL);			/* doesn't return */
975 
976 	return (EFI_SUCCESS);		/* keep compiler happy */
977 }
978 
979 COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
980 
981 static void
982 fw_setup(void)
983 {
984 	uint64_t os_indications;
985 	size_t size;
986 	EFI_STATUS status;
987 
988 	size = sizeof (os_indications);
989 	status = efi_global_getenv("OsIndicationsSupported",
990 	    &os_indications, &size);
991 	if (EFI_ERROR(status) || size != sizeof (os_indications) ||
992 	    (os_indications & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) == 0) {
993 		printf("Booting to Firmware UI is not supported in "
994 		    "this system.");
995 		for (int i = 0; i < 3; i++) {
996 			delay(1000 * 1000); /* 1 second */
997 			if (ischar())
998 				break;
999 		}
1000 		return;
1001 	}
1002 
1003 	os_indications = EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
1004 
1005 	status = efi_global_setenv("OsIndications", &os_indications,
1006 	    sizeof (os_indications));
1007 }
1008 
1009 static int
1010 command_reboot(int argc, char *argv[])
1011 {
1012 	int i, ch;
1013 	bool fw = false;
1014 
1015 	optind = 1;
1016 	optreset = 1;
1017 
1018 	while ((ch = getopt(argc, argv, "fh")) != -1) {
1019 		switch (ch) {
1020 		case 'f':
1021 			fw = true;
1022 			break;
1023 		case 'h':
1024 			printf("Usage: reboot [-f]\n");
1025 			return (CMD_OK);
1026 		case '?':
1027 		default:
1028 			return (CMD_OK);
1029 		}
1030 	}
1031 
1032 	if (fw || getenv("BOOT_TO_FW_UI") != NULL)
1033 		fw_setup();
1034 
1035 	for (i = 0; devsw[i] != NULL; ++i)
1036 		if (devsw[i]->dv_cleanup != NULL)
1037 			(devsw[i]->dv_cleanup)();
1038 
1039 	RS->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
1040 
1041 	/* NOTREACHED */
1042 	return (CMD_ERROR);
1043 }
1044 
1045 COMMAND_SET(poweroff, "poweroff", "power off the system", command_poweroff);
1046 
1047 static int
1048 command_poweroff(int argc __unused, char *argv[] __unused)
1049 {
1050 	int i;
1051 
1052 	for (i = 0; devsw[i] != NULL; ++i)
1053 		if (devsw[i]->dv_cleanup != NULL)
1054 			(devsw[i]->dv_cleanup)();
1055 
1056 	RS->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL);
1057 
1058 	/* NOTREACHED */
1059 	return (CMD_ERROR);
1060 }
1061 
1062 COMMAND_SET(memmap, "memmap", "print memory map", command_memmap);
1063 
1064 static int
1065 command_memmap(int argc __unused, char *argv[] __unused)
1066 {
1067 	UINTN sz;
1068 	EFI_MEMORY_DESCRIPTOR *map, *p;
1069 	UINTN key, dsz;
1070 	UINT32 dver;
1071 	EFI_STATUS status;
1072 	int i, ndesc;
1073 	int rv = 0;
1074 	char line[80];
1075 
1076 	sz = 0;
1077 	status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
1078 	if (status != EFI_BUFFER_TOO_SMALL) {
1079 		printf("Can't determine memory map size\n");
1080 		return (CMD_ERROR);
1081 	}
1082 	map = malloc(sz);
1083 	status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
1084 	if (EFI_ERROR(status)) {
1085 		printf("Can't read memory map\n");
1086 		return (CMD_ERROR);
1087 	}
1088 
1089 	ndesc = sz / dsz;
1090 	snprintf(line, 80, "%23s %12s %12s %8s %4s\n",
1091 	    "Type", "Physical", "Virtual", "#Pages", "Attr");
1092 	pager_open();
1093 	rv = pager_output(line);
1094 	if (rv) {
1095 		pager_close();
1096 		return (CMD_OK);
1097 	}
1098 
1099 	for (i = 0, p = map; i < ndesc;
1100 	    i++, p = NextMemoryDescriptor(p, dsz)) {
1101 		snprintf(line, 80, "%23s %012jx %012jx %08jx ",
1102 		    efi_memory_type(p->Type), p->PhysicalStart,
1103 		    p->VirtualStart, p->NumberOfPages);
1104 		rv = pager_output(line);
1105 		if (rv)
1106 			break;
1107 
1108 		if (p->Attribute & EFI_MEMORY_UC)
1109 			printf("UC ");
1110 		if (p->Attribute & EFI_MEMORY_WC)
1111 			printf("WC ");
1112 		if (p->Attribute & EFI_MEMORY_WT)
1113 			printf("WT ");
1114 		if (p->Attribute & EFI_MEMORY_WB)
1115 			printf("WB ");
1116 		if (p->Attribute & EFI_MEMORY_UCE)
1117 			printf("UCE ");
1118 		if (p->Attribute & EFI_MEMORY_WP)
1119 			printf("WP ");
1120 		if (p->Attribute & EFI_MEMORY_RP)
1121 			printf("RP ");
1122 		if (p->Attribute & EFI_MEMORY_XP)
1123 			printf("XP ");
1124 		if (p->Attribute & EFI_MEMORY_NV)
1125 			printf("NV ");
1126 		if (p->Attribute & EFI_MEMORY_MORE_RELIABLE)
1127 			printf("MR ");
1128 		if (p->Attribute & EFI_MEMORY_RO)
1129 			printf("RO ");
1130 		rv = pager_output("\n");
1131 		if (rv)
1132 			break;
1133 	}
1134 
1135 	pager_close();
1136 	return (CMD_OK);
1137 }
1138 
1139 COMMAND_SET(configuration, "configuration", "print configuration tables",
1140     command_configuration);
1141 
1142 static int
1143 command_configuration(int argc __unused, char *argv[] __unused)
1144 {
1145 	UINTN i;
1146 	char *name;
1147 
1148 	printf("NumberOfTableEntries=%lu\n",
1149 	    (unsigned long)ST->NumberOfTableEntries);
1150 	for (i = 0; i < ST->NumberOfTableEntries; i++) {
1151 		EFI_GUID *guid;
1152 
1153 		printf("  ");
1154 		guid = &ST->ConfigurationTable[i].VendorGuid;
1155 
1156 		if (efi_guid_to_name(guid, &name) == true) {
1157 			printf(name);
1158 			free(name);
1159 		} else {
1160 			printf("Error while translating UUID to name");
1161 		}
1162 		printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
1163 	}
1164 
1165 	return (CMD_OK);
1166 }
1167 
1168 
1169 COMMAND_SET(mode, "mode", "change or display EFI text modes", command_mode);
1170 
1171 static int
1172 command_mode(int argc, char *argv[])
1173 {
1174 	UINTN cols, rows;
1175 	unsigned int mode;
1176 	int i;
1177 	char *cp;
1178 	EFI_STATUS status;
1179 	SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
1180 	EFI_CONSOLE_CONTROL_SCREEN_MODE sm;
1181 
1182 	if (plat_stdout_is_framebuffer())
1183 		sm = EfiConsoleControlScreenGraphics;
1184 	else
1185 		sm = EfiConsoleControlScreenText;
1186 
1187 	conout = ST->ConOut;
1188 
1189 	if (argc > 1) {
1190 		mode = strtol(argv[1], &cp, 0);
1191 		if (cp[0] != '\0') {
1192 			printf("Invalid mode\n");
1193 			return (CMD_ERROR);
1194 		}
1195 		status = conout->QueryMode(conout, mode, &cols, &rows);
1196 		if (EFI_ERROR(status)) {
1197 			printf("invalid mode %d\n", mode);
1198 			return (CMD_ERROR);
1199 		}
1200 		status = conout->SetMode(conout, mode);
1201 		if (EFI_ERROR(status)) {
1202 			printf("couldn't set mode %d\n", mode);
1203 			return (CMD_ERROR);
1204 		}
1205 		plat_cons_update_mode(sm);
1206 		return (CMD_OK);
1207 	}
1208 
1209 	printf("Current mode: %d\n", conout->Mode->Mode);
1210 	for (i = 0; i <= conout->Mode->MaxMode; i++) {
1211 		status = conout->QueryMode(conout, i, &cols, &rows);
1212 		if (EFI_ERROR(status))
1213 			continue;
1214 		printf("Mode %d: %u columns, %u rows\n", i, (unsigned)cols,
1215 		    (unsigned)rows);
1216 	}
1217 
1218 	if (i != 0)
1219 		printf("Select a mode with the command \"mode <number>\"\n");
1220 
1221 	return (CMD_OK);
1222 }
1223 
1224 COMMAND_SET(lsefi, "lsefi", "list EFI handles", command_lsefi);
1225 
1226 static int
1227 command_lsefi(int argc __unused, char *argv[] __unused)
1228 {
1229 	char *name;
1230 	EFI_HANDLE *buffer = NULL;
1231 	EFI_HANDLE handle;
1232 	UINTN bufsz = 0, i, j;
1233 	EFI_STATUS status;
1234 	int ret = 0;
1235 
1236 	status = BS->LocateHandle(AllHandles, NULL, NULL, &bufsz, buffer);
1237 	if (status != EFI_BUFFER_TOO_SMALL) {
1238 		snprintf(command_errbuf, sizeof (command_errbuf),
1239 		    "unexpected error: %lld", (long long)status);
1240 		return (CMD_ERROR);
1241 	}
1242 	if ((buffer = malloc(bufsz)) == NULL) {
1243 		sprintf(command_errbuf, "out of memory");
1244 		return (CMD_ERROR);
1245 	}
1246 
1247 	status = BS->LocateHandle(AllHandles, NULL, NULL, &bufsz, buffer);
1248 	if (EFI_ERROR(status)) {
1249 		free(buffer);
1250 		snprintf(command_errbuf, sizeof (command_errbuf),
1251 		    "LocateHandle() error: %lld", (long long)status);
1252 		return (CMD_ERROR);
1253 	}
1254 
1255 	pager_open();
1256 	for (i = 0; i < (bufsz / sizeof (EFI_HANDLE)); i++) {
1257 		UINTN nproto = 0;
1258 		EFI_GUID **protocols = NULL;
1259 		EFI_DEVICE_PATH *dp;
1260 		CHAR16 *text;
1261 
1262 		handle = buffer[i];
1263 		printf("Handle %p", handle);
1264 		if (pager_output("\n"))
1265 			break;
1266 
1267 		ret = 0;
1268 		dp = efi_lookup_devpath(handle);
1269 		if (dp != NULL) {
1270 			text = efi_devpath_name(dp);
1271 			if (text != NULL) {
1272 				printf("  %S", text);
1273 				efi_free_devpath_name(text);
1274 				ret = pager_output("\n");
1275 			}
1276 			efi_close_devpath(handle);
1277 		}
1278 		if (ret != 0)
1279 			break;
1280 
1281 		status = BS->ProtocolsPerHandle(handle, &protocols, &nproto);
1282 		if (EFI_ERROR(status)) {
1283 			snprintf(command_errbuf, sizeof (command_errbuf),
1284 			    "ProtocolsPerHandle() error: %lld",
1285 			    (long long)status);
1286 			continue;
1287 		}
1288 
1289 		for (j = 0; j < nproto; j++) {
1290 			if (efi_guid_to_name(protocols[j], &name) == true) {
1291 				printf("  %s", name);
1292 				free(name);
1293 			} else {
1294 				printf("Error while translating UUID to name");
1295 			}
1296 			if ((ret = pager_output("\n")) != 0)
1297 				break;
1298 		}
1299 		BS->FreePool(protocols);
1300 		if (ret != 0)
1301 			break;
1302 	}
1303 	pager_close();
1304 	free(buffer);
1305 	return (CMD_OK);
1306 }
1307 
1308 #ifdef LOADER_FDT_SUPPORT
1309 extern int command_fdt_internal(int argc, char *argv[]);
1310 
1311 /*
1312  * Since proper fdt command handling function is defined in fdt_loader_cmd.c,
1313  * and declaring it as extern is in contradiction with COMMAND_SET() macro
1314  * (which uses static pointer), we're defining wrapper function, which
1315  * calls the proper fdt handling routine.
1316  */
1317 static int
1318 command_fdt(int argc, char *argv[])
1319 {
1320 	return (command_fdt_internal(argc, argv));
1321 }
1322 
1323 COMMAND_SET(fdt, "fdt", "flattened device tree handling", command_fdt);
1324 #endif
1325 
1326 /*
1327  * Chain load another efi loader.
1328  */
1329 static int
1330 command_chain(int argc, char *argv[])
1331 {
1332 	EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
1333 	EFI_HANDLE loaderhandle;
1334 	EFI_LOADED_IMAGE *loaded_image;
1335 	EFI_STATUS status;
1336 	struct stat st;
1337 	struct devdesc *dev;
1338 	char *name, *path;
1339 	void *buf;
1340 	int fd;
1341 
1342 	if (argc < 2) {
1343 		command_errmsg = "wrong number of arguments";
1344 		return (CMD_ERROR);
1345 	}
1346 
1347 	name = argv[1];
1348 
1349 	if ((fd = open(name, O_RDONLY)) < 0) {
1350 		command_errmsg = "no such file";
1351 		return (CMD_ERROR);
1352 	}
1353 
1354 	if (fstat(fd, &st) < -1) {
1355 		command_errmsg = "stat failed";
1356 		close(fd);
1357 		return (CMD_ERROR);
1358 	}
1359 
1360 	status = BS->AllocatePool(EfiLoaderCode, (UINTN)st.st_size, &buf);
1361 	if (status != EFI_SUCCESS) {
1362 		command_errmsg = "failed to allocate buffer";
1363 		close(fd);
1364 		return (CMD_ERROR);
1365 	}
1366 	if (read(fd, buf, st.st_size) != st.st_size) {
1367 		command_errmsg = "error while reading the file";
1368 		(void) BS->FreePool(buf);
1369 		close(fd);
1370 		return (CMD_ERROR);
1371 	}
1372 	close(fd);
1373 	status = BS->LoadImage(FALSE, IH, NULL, buf, st.st_size, &loaderhandle);
1374 	(void) BS->FreePool(buf);
1375 	if (status != EFI_SUCCESS) {
1376 		command_errmsg = "LoadImage failed";
1377 		return (CMD_ERROR);
1378 	}
1379 	status = OpenProtocolByHandle(loaderhandle, &LoadedImageGUID,
1380 	    (void **)&loaded_image);
1381 
1382 	if (argc > 2) {
1383 		int i, len = 0;
1384 		CHAR16 *argp;
1385 
1386 		for (i = 2; i < argc; i++)
1387 			len += strlen(argv[i]) + 1;
1388 
1389 		len *= sizeof (*argp);
1390 		loaded_image->LoadOptions = argp = malloc(len);
1391 		if (loaded_image->LoadOptions == NULL) {
1392 			(void) BS->UnloadImage(loaded_image);
1393 			return (CMD_ERROR);
1394 		}
1395 		loaded_image->LoadOptionsSize = len;
1396 		for (i = 2; i < argc; i++) {
1397 			char *ptr = argv[i];
1398 			while (*ptr)
1399 				*(argp++) = *(ptr++);
1400 			*(argp++) = ' ';
1401 		}
1402 		*(--argv) = 0;
1403 	}
1404 
1405 	if (efi_getdev((void **)&dev, name, (const char **)&path) == 0) {
1406 		struct zfs_devdesc *z_dev;
1407 		struct disk_devdesc *d_dev;
1408 		pdinfo_t *hd, *pd;
1409 
1410 		switch (dev->d_dev->dv_type) {
1411 		case DEVT_ZFS:
1412 			z_dev = (struct zfs_devdesc *)dev;
1413 			loaded_image->DeviceHandle =
1414 			    efizfs_get_handle_by_guid(z_dev->pool_guid);
1415 			break;
1416 		case DEVT_NET:
1417 			loaded_image->DeviceHandle =
1418 			    efi_find_handle(dev->d_dev, dev->d_unit);
1419 			break;
1420 		default:
1421 			hd = efiblk_get_pdinfo(dev);
1422 			if (STAILQ_EMPTY(&hd->pd_part)) {
1423 				loaded_image->DeviceHandle = hd->pd_handle;
1424 				break;
1425 			}
1426 			d_dev = (struct disk_devdesc *)dev;
1427 			STAILQ_FOREACH(pd, &hd->pd_part, pd_link) {
1428 				/*
1429 				 * d_partition should be 255
1430 				 */
1431 				if (pd->pd_unit == d_dev->d_slice) {
1432 					loaded_image->DeviceHandle =
1433 					    pd->pd_handle;
1434 					break;
1435 				}
1436 			}
1437 			break;
1438 		}
1439 	}
1440 
1441 	dev_cleanup();
1442 	status = BS->StartImage(loaderhandle, NULL, NULL);
1443 	if (status != EFI_SUCCESS) {
1444 		command_errmsg = "StartImage failed";
1445 		free(loaded_image->LoadOptions);
1446 		loaded_image->LoadOptions = NULL;
1447 		status = BS->UnloadImage(loaded_image);
1448 		return (CMD_ERROR);
1449 	}
1450 
1451 	return (CMD_ERROR);	/* not reached */
1452 }
1453 
1454 COMMAND_SET(chain, "chain", "chain load file", command_chain);
1455