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