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