]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - stand/efi/loader/main.c
MFC r336463: If rootdev is set, use it as currdev.
[FreeBSD/FreeBSD.git] / stand / efi / loader / main.c
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 __FBSDID("$FreeBSD$");
30
31 #include <stand.h>
32
33 #include <sys/disk.h>
34 #include <sys/param.h>
35 #include <sys/reboot.h>
36 #include <sys/boot.h>
37 #include <stdint.h>
38 #include <string.h>
39 #include <setjmp.h>
40 #include <disk.h>
41
42 #include <efi.h>
43 #include <efilib.h>
44
45 #include <uuid.h>
46
47 #include <bootstrap.h>
48 #include <smbios.h>
49
50 #ifdef EFI_ZFS_BOOT
51 #include <libzfs.h>
52 #include "efizfs.h"
53 #endif
54
55 #include "loader_efi.h"
56
57 struct arch_switch archsw;      /* MI/MD interface boundary */
58
59 EFI_GUID acpi = ACPI_TABLE_GUID;
60 EFI_GUID acpi20 = ACPI_20_TABLE_GUID;
61 EFI_GUID devid = DEVICE_PATH_PROTOCOL;
62 EFI_GUID imgid = LOADED_IMAGE_PROTOCOL;
63 EFI_GUID mps = MPS_TABLE_GUID;
64 EFI_GUID netid = EFI_SIMPLE_NETWORK_PROTOCOL;
65 EFI_GUID smbios = SMBIOS_TABLE_GUID;
66 EFI_GUID smbios3 = SMBIOS3_TABLE_GUID;
67 EFI_GUID dxe = DXE_SERVICES_TABLE_GUID;
68 EFI_GUID hoblist = HOB_LIST_TABLE_GUID;
69 EFI_GUID lzmadecomp = LZMA_DECOMPRESSION_GUID;
70 EFI_GUID mpcore = ARM_MP_CORE_INFO_TABLE_GUID;
71 EFI_GUID esrt = ESRT_TABLE_GUID;
72 EFI_GUID memtype = MEMORY_TYPE_INFORMATION_TABLE_GUID;
73 EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID;
74 EFI_GUID fdtdtb = FDT_TABLE_GUID;
75 EFI_GUID inputid = SIMPLE_TEXT_INPUT_PROTOCOL;
76
77 /*
78  * Number of seconds to wait for a keystroke before exiting with failure
79  * in the event no currdev is found. -2 means always break, -1 means
80  * never break, 0 means poll once and then reboot, > 0 means wait for
81  * that many seconds. "fail_timeout" can be set in the environment as
82  * well.
83  */
84 static int fail_timeout = 5;
85
86 static bool
87 has_keyboard(void)
88 {
89         EFI_STATUS status;
90         EFI_DEVICE_PATH *path;
91         EFI_HANDLE *hin, *hin_end, *walker;
92         UINTN sz;
93         bool retval = false;
94
95         /*
96          * Find all the handles that support the SIMPLE_TEXT_INPUT_PROTOCOL and
97          * do the typical dance to get the right sized buffer.
98          */
99         sz = 0;
100         hin = NULL;
101         status = BS->LocateHandle(ByProtocol, &inputid, 0, &sz, 0);
102         if (status == EFI_BUFFER_TOO_SMALL) {
103                 hin = (EFI_HANDLE *)malloc(sz);
104                 status = BS->LocateHandle(ByProtocol, &inputid, 0, &sz,
105                     hin);
106                 if (EFI_ERROR(status))
107                         free(hin);
108         }
109         if (EFI_ERROR(status))
110                 return retval;
111
112         /*
113          * Look at each of the handles. If it supports the device path protocol,
114          * use it to get the device path for this handle. Then see if that
115          * device path matches either the USB device path for keyboards or the
116          * legacy device path for keyboards.
117          */
118         hin_end = &hin[sz / sizeof(*hin)];
119         for (walker = hin; walker < hin_end; walker++) {
120                 status = BS->HandleProtocol(*walker, &devid, (VOID **)&path);
121                 if (EFI_ERROR(status))
122                         continue;
123
124                 while (!IsDevicePathEnd(path)) {
125                         /*
126                          * Check for the ACPI keyboard node. All PNP3xx nodes
127                          * are keyboards of different flavors. Note: It is
128                          * unclear of there's always a keyboard node when
129                          * there's a keyboard controller, or if there's only one
130                          * when a keyboard is detected at boot.
131                          */
132                         if (DevicePathType(path) == ACPI_DEVICE_PATH &&
133                             (DevicePathSubType(path) == ACPI_DP ||
134                                 DevicePathSubType(path) == ACPI_EXTENDED_DP)) {
135                                 ACPI_HID_DEVICE_PATH  *acpi;
136
137                                 acpi = (ACPI_HID_DEVICE_PATH *)(void *)path;
138                                 if ((EISA_ID_TO_NUM(acpi->HID) & 0xff00) == 0x300 &&
139                                     (acpi->HID & 0xffff) == PNP_EISA_ID_CONST) {
140                                         retval = true;
141                                         goto out;
142                                 }
143                         /*
144                          * Check for USB keyboard node, if present. Unlike a
145                          * PS/2 keyboard, these definitely only appear when
146                          * connected to the system.
147                          */
148                         } else if (DevicePathType(path) == MESSAGING_DEVICE_PATH &&
149                             DevicePathSubType(path) == MSG_USB_CLASS_DP) {
150                                 USB_CLASS_DEVICE_PATH *usb;
151
152                                 usb = (USB_CLASS_DEVICE_PATH *)(void *)path;
153                                 if (usb->DeviceClass == 3 && /* HID */
154                                     usb->DeviceSubClass == 1 && /* Boot devices */
155                                     usb->DeviceProtocol == 1) { /* Boot keyboards */
156                                         retval = true;
157                                         goto out;
158                                 }
159                         }
160                         path = NextDevicePathNode(path);
161                 }
162         }
163 out:
164         free(hin);
165         return retval;
166 }
167
168 static void
169 set_currdev(const char *devname)
170 {
171
172         env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev, env_nounset);
173         env_setenv("loaddev", EV_VOLATILE, devname, env_noset, env_nounset);
174 }
175
176 static void
177 set_currdev_devdesc(struct devdesc *currdev)
178 {
179         const char *devname;
180
181         devname = efi_fmtdev(currdev);
182         printf("Setting currdev to %s\n", devname);
183         set_currdev(devname);
184 }
185
186 static void
187 set_currdev_devsw(struct devsw *dev, int unit)
188 {
189         struct devdesc currdev;
190
191         currdev.d_dev = dev;
192         currdev.d_unit = unit;
193
194         set_currdev_devdesc(&currdev);
195 }
196
197 static void
198 set_currdev_pdinfo(pdinfo_t *dp)
199 {
200
201         /*
202          * Disks are special: they have partitions. if the parent
203          * pointer is non-null, we're a partition not a full disk
204          * and we need to adjust currdev appropriately.
205          */
206         if (dp->pd_devsw->dv_type == DEVT_DISK) {
207                 struct disk_devdesc currdev;
208
209                 currdev.dd.d_dev = dp->pd_devsw;
210                 if (dp->pd_parent == NULL) {
211                         currdev.dd.d_unit = dp->pd_unit;
212                         currdev.d_slice = -1;
213                         currdev.d_partition = -1;
214                 } else {
215                         currdev.dd.d_unit = dp->pd_parent->pd_unit;
216                         currdev.d_slice = dp->pd_unit;
217                         currdev.d_partition = 255;      /* Assumes GPT */
218                 }
219                 set_currdev_devdesc((struct devdesc *)&currdev);
220         } else {
221                 set_currdev_devsw(dp->pd_devsw, dp->pd_unit);
222         }
223 }
224
225 static bool
226 sanity_check_currdev(void)
227 {
228         struct stat st;
229
230         return (stat("/boot/defaults/loader.conf", &st) == 0 ||
231             stat("/boot/kernel/kernel", &st) == 0);
232 }
233
234 #ifdef EFI_ZFS_BOOT
235 static bool
236 probe_zfs_currdev(uint64_t guid)
237 {
238         char *devname;
239         struct zfs_devdesc currdev;
240
241         currdev.dd.d_dev = &zfs_dev;
242         currdev.dd.d_unit = 0;
243         currdev.pool_guid = guid;
244         currdev.root_guid = 0;
245         set_currdev_devdesc((struct devdesc *)&currdev);
246         devname = efi_fmtdev(&currdev);
247         init_zfs_bootenv(devname);
248
249         return (sanity_check_currdev());
250 }
251 #endif
252
253 static bool
254 try_as_currdev(pdinfo_t *hd, pdinfo_t *pp)
255 {
256         uint64_t guid;
257
258 #ifdef EFI_ZFS_BOOT
259         /*
260          * If there's a zpool on this device, try it as a ZFS
261          * filesystem, which has somewhat different setup than all
262          * other types of fs due to imperfect loader integration.
263          * This all stems from ZFS being both a device (zpool) and
264          * a filesystem, plus the boot env feature.
265          */
266         if (efizfs_get_guid_by_handle(pp->pd_handle, &guid))
267                 return (probe_zfs_currdev(guid));
268 #endif
269         /*
270          * All other filesystems just need the pdinfo
271          * initialized in the standard way.
272          */
273         set_currdev_pdinfo(pp);
274         return (sanity_check_currdev());
275 }
276
277 static int
278 find_currdev(EFI_LOADED_IMAGE *img)
279 {
280         pdinfo_t *dp, *pp;
281         EFI_DEVICE_PATH *devpath, *copy;
282         EFI_HANDLE h;
283         CHAR16 *text;
284         struct devsw *dev;
285         int unit;
286         uint64_t extra;
287         char *rootdev;
288
289         rootdev = getenv("rootdev");
290         if (rootdev != NULL) {
291                 printf("Setting currdev to configured rootdev %s\n", rootdev);
292                 set_currdev(rootdev);
293                 return (0);
294         }
295
296 #ifdef EFI_ZFS_BOOT
297         /*
298          * Did efi_zfs_probe() detect the boot pool? If so, use the zpool
299          * it found, if it's sane. ZFS is the only thing that looks for
300          * disks and pools to boot. This may change in the future, however,
301          * if we allow specifying which pool to boot from via UEFI variables
302          * rather than the bootenv stuff that FreeBSD uses today.
303          */
304         if (pool_guid != 0) {
305                 printf("Trying ZFS pool\n");
306                 if (probe_zfs_currdev(pool_guid))
307                         return (0);
308         }
309 #endif /* EFI_ZFS_BOOT */
310
311         /*
312          * Try to find the block device by its handle based on the
313          * image we're booting. If we can't find a sane partition,
314          * search all the other partitions of the disk. We do not
315          * search other disks because it's a violation of the UEFI
316          * boot protocol to do so. We fail and let UEFI go on to
317          * the next candidate.
318          */
319         dp = efiblk_get_pdinfo_by_handle(img->DeviceHandle);
320         if (dp != NULL) {
321                 text = efi_devpath_name(dp->pd_devpath);
322                 if (text != NULL) {
323                         printf("Trying ESP: %S\n", text);
324                         efi_free_devpath_name(text);
325                 }
326                 set_currdev_pdinfo(dp);
327                 if (sanity_check_currdev())
328                         return (0);
329                 if (dp->pd_parent != NULL) {
330                         dp = dp->pd_parent;
331                         STAILQ_FOREACH(pp, &dp->pd_part, pd_link) {
332                                 /*
333                                  * Roll up the ZFS special case
334                                  * for those partitions that have
335                                  * zpools on them 
336                                  */
337                                 if (try_as_currdev(dp, pp))
338                                         return (0);
339                         }
340                 }
341         } else {
342                 printf("Can't find device by handle\n");
343         }
344
345         /*
346          * Try the device handle from our loaded image first.  If that
347          * fails, use the device path from the loaded image and see if
348          * any of the nodes in that path match one of the enumerated
349          * handles. Currently, this handle list is only for netboot.
350          */
351         if (efi_handle_lookup(img->DeviceHandle, &dev, &unit, &extra) == 0) {
352                 set_currdev_devsw(dev, unit);
353                 if (sanity_check_currdev())
354                         return (0);
355         }
356
357         copy = NULL;
358         devpath = efi_lookup_image_devpath(IH);
359         while (devpath != NULL) {
360                 h = efi_devpath_handle(devpath);
361                 if (h == NULL)
362                         break;
363
364                 free(copy);
365                 copy = NULL;
366
367                 if (efi_handle_lookup(h, &dev, &unit, &extra) == 0) {
368                         set_currdev_devsw(dev, unit);
369                         if (sanity_check_currdev())
370                                 return (0);
371                 }
372
373                 devpath = efi_lookup_devpath(h);
374                 if (devpath != NULL) {
375                         copy = efi_devpath_trim(devpath);
376                         devpath = copy;
377                 }
378         }
379         free(copy);
380
381         return (ENOENT);
382 }
383
384 static bool
385 interactive_interrupt(const char *msg)
386 {
387         time_t now, then, last;
388
389         last = 0;
390         now = then = getsecs();
391         printf("%s\n", msg);
392         if (fail_timeout == -2)         /* Always break to OK */
393                 return (true);
394         if (fail_timeout == -1)         /* Never break to OK */
395                 return (false);
396         do {
397                 if (last != now) {
398                         printf("press any key to interrupt reboot in %d seconds\r",
399                             fail_timeout - (int)(now - then));
400                         last = now;
401                 }
402
403                 /* XXX no pause or timeout wait for char */
404                 if (ischar())
405                         return (true);
406                 now = getsecs();
407         } while (now - then < fail_timeout);
408         return (false);
409 }
410
411 static int
412 parse_args(int argc, CHAR16 *argv[])
413 {
414         int i, j, howto;
415         bool vargood;
416         char var[128];
417
418         /*
419          * Parse the args to set the console settings, etc
420          * boot1.efi passes these in, if it can read /boot.config or /boot/config
421          * or iPXE may be setup to pass these in. Or the optional argument in the
422          * boot environment was used to pass these arguments in (in which case
423          * neither /boot.config nor /boot/config are consulted).
424          *
425          * Loop through the args, and for each one that contains an '=' that is
426          * not the first character, add it to the environment.  This allows
427          * loader and kernel env vars to be passed on the command line.  Convert
428          * args from UCS-2 to ASCII (16 to 8 bit) as they are copied (though this
429          * method is flawed for non-ASCII characters).
430          */
431         howto = 0;
432         for (i = 1; i < argc; i++) {
433                 cpy16to8(argv[i], var, sizeof(var));
434                 howto |= boot_parse_arg(var);
435         }
436
437         return (howto);
438 }
439
440 /*
441  * Parse ConOut (the list of consoles active) and see if we can find a
442  * serial port and/or a video port. It would be nice to also walk the
443  * ACPI name space to map the UID for the serial port to a port. The
444  * latter is especially hard.
445  */
446 static int
447 parse_uefi_con_out(void)
448 {
449         int how, rv;
450         int vid_seen = 0, com_seen = 0, seen = 0;
451         size_t sz;
452         char buf[4096], *ep;
453         EFI_DEVICE_PATH *node;
454         ACPI_HID_DEVICE_PATH  *acpi;
455         UART_DEVICE_PATH  *uart;
456         bool pci_pending;
457
458         how = 0;
459         sz = sizeof(buf);
460         rv = efi_global_getenv("ConOut", buf, &sz);
461         if (rv != EFI_SUCCESS)
462                 goto out;
463         ep = buf + sz;
464         node = (EFI_DEVICE_PATH *)buf;
465         while ((char *)node < ep) {
466                 pci_pending = false;
467                 if (DevicePathType(node) == ACPI_DEVICE_PATH &&
468                     DevicePathSubType(node) == ACPI_DP) {
469                         /* Check for Serial node */
470                         acpi = (void *)node;
471                         if (EISA_ID_TO_NUM(acpi->HID) == 0x501)
472                                 com_seen = ++seen;
473                 } else if (DevicePathType(node) == MESSAGING_DEVICE_PATH &&
474                     DevicePathSubType(node) == MSG_UART_DP) {
475                         char bd[16];
476
477                         uart = (void *)node;
478                         snprintf(bd, sizeof(bd), "%d", uart->BaudRate);
479                         setenv("efi_com_speed", bd, 1);
480                 } else if (DevicePathType(node) == ACPI_DEVICE_PATH &&
481                     DevicePathSubType(node) == ACPI_ADR_DP) {
482                         /* Check for AcpiAdr() Node for video */
483                         vid_seen = ++seen;
484                 } else if (DevicePathType(node) == HARDWARE_DEVICE_PATH &&
485                     DevicePathSubType(node) == HW_PCI_DP) {
486                         /*
487                          * Note, vmware fusion has a funky console device
488                          *      PciRoot(0x0)/Pci(0xf,0x0)
489                          * which we can only detect at the end since we also
490                          * have to cope with:
491                          *      PciRoot(0x0)/Pci(0x1f,0x0)/Serial(0x1)
492                          * so only match it if it's last.
493                          */
494                         pci_pending = true;
495                 }
496                 node = NextDevicePathNode(node); /* Skip the end node */
497         }
498         if (pci_pending && vid_seen == 0)
499                 vid_seen = ++seen;
500
501         /*
502          * Truth table for RB_MULTIPLE | RB_SERIAL
503          * Value                Result
504          * 0                    Use only video console
505          * RB_SERIAL            Use only serial console
506          * RB_MULTIPLE          Use both video and serial console
507          *                      (but video is primary so gets rc messages)
508          * both                 Use both video and serial console
509          *                      (but serial is primary so gets rc messages)
510          *
511          * Try to honor this as best we can. If only one of serial / video
512          * found, then use that. Otherwise, use the first one we found.
513          * This also implies if we found nothing, default to video.
514          */
515         how = 0;
516         if (vid_seen && com_seen) {
517                 how |= RB_MULTIPLE;
518                 if (com_seen < vid_seen)
519                         how |= RB_SERIAL;
520         } else if (com_seen)
521                 how |= RB_SERIAL;
522 out:
523         return (how);
524 }
525
526 EFI_STATUS
527 main(int argc, CHAR16 *argv[])
528 {
529         EFI_GUID *guid;
530         int howto, i, uhowto;
531         UINTN k;
532         bool has_kbd;
533         char *s;
534         EFI_DEVICE_PATH *imgpath;
535         CHAR16 *text;
536         EFI_STATUS status;
537         UINT16 boot_current;
538         size_t sz;
539         UINT16 boot_order[100];
540         EFI_LOADED_IMAGE *img;
541
542         archsw.arch_autoload = efi_autoload;
543         archsw.arch_getdev = efi_getdev;
544         archsw.arch_copyin = efi_copyin;
545         archsw.arch_copyout = efi_copyout;
546         archsw.arch_readin = efi_readin;
547 #ifdef EFI_ZFS_BOOT
548         /* Note this needs to be set before ZFS init. */
549         archsw.arch_zfs_probe = efi_zfs_probe;
550 #endif
551
552         /* Get our loaded image protocol interface structure. */
553         BS->HandleProtocol(IH, &imgid, (VOID**)&img);
554
555 #ifdef EFI_ZFS_BOOT
556         /* Tell ZFS probe code where we booted from */
557         efizfs_set_preferred(img->DeviceHandle);
558 #endif
559         /* Init the time source */
560         efi_time_init();
561
562         has_kbd = has_keyboard();
563
564         /*
565          * XXX Chicken-and-egg problem; we want to have console output
566          * early, but some console attributes may depend on reading from
567          * eg. the boot device, which we can't do yet.  We can use
568          * printf() etc. once this is done.
569          */
570         setenv("console", "efi", 1);
571         cons_probe();
572
573         /*
574          * Initialise the block cache. Set the upper limit.
575          */
576         bcache_init(32768, 512);
577
578         howto = parse_args(argc, argv);
579         if (!has_kbd && (howto & RB_PROBE))
580                 howto |= RB_SERIAL | RB_MULTIPLE;
581         howto &= ~RB_PROBE;
582         uhowto = parse_uefi_con_out();
583
584         /*
585          * We now have two notions of console. howto should be viewed as
586          * overrides. If console is already set, don't set it again.
587          */
588 #define VIDEO_ONLY      0
589 #define SERIAL_ONLY     RB_SERIAL
590 #define VID_SER_BOTH    RB_MULTIPLE
591 #define SER_VID_BOTH    (RB_SERIAL | RB_MULTIPLE)
592 #define CON_MASK        (RB_SERIAL | RB_MULTIPLE)
593         if (strcmp(getenv("console"), "efi") == 0) {
594                 if ((howto & CON_MASK) == 0) {
595                         /* No override, uhowto is controlling and efi cons is perfect */
596                         howto = howto | (uhowto & CON_MASK);
597                         setenv("console", "efi", 1);
598                 } else if ((howto & CON_MASK) == (uhowto & CON_MASK)) {
599                         /* override matches what UEFI told us, efi console is perfect */
600                         setenv("console", "efi", 1);
601                 } else if ((uhowto & (CON_MASK)) != 0) {
602                         /*
603                          * We detected a serial console on ConOut. All possible
604                          * overrides include serial. We can't really override what efi
605                          * gives us, so we use it knowing it's the best choice.
606                          */
607                         setenv("console", "efi", 1);
608                 } else {
609                         /*
610                          * We detected some kind of serial in the override, but ConOut
611                          * has no serial, so we have to sort out which case it really is.
612                          */
613                         switch (howto & CON_MASK) {
614                         case SERIAL_ONLY:
615                                 setenv("console", "comconsole", 1);
616                                 break;
617                         case VID_SER_BOTH:
618                                 setenv("console", "efi comconsole", 1);
619                                 break;
620                         case SER_VID_BOTH:
621                                 setenv("console", "comconsole efi", 1);
622                                 break;
623                                 /* case VIDEO_ONLY can't happen -- it's the first if above */
624                         }
625                 }
626         }
627         /*
628          * howto is set now how we want to export the flags to the kernel, so
629          * set the env based on it.
630          */
631         boot_howto_to_env(howto);
632
633         if (efi_copy_init()) {
634                 printf("failed to allocate staging area\n");
635                 return (EFI_BUFFER_TOO_SMALL);
636         }
637
638         if ((s = getenv("fail_timeout")) != NULL)
639                 fail_timeout = strtol(s, NULL, 10);
640
641         /*
642          * Scan the BLOCK IO MEDIA handles then
643          * march through the device switch probing for things.
644          */
645         if ((i = efipart_inithandles()) == 0) {
646                 for (i = 0; devsw[i] != NULL; i++)
647                         if (devsw[i]->dv_init != NULL)
648                                 (devsw[i]->dv_init)();
649         } else
650                 printf("efipart_inithandles failed %d, expect failures", i);
651
652         printf("%s\n", bootprog_info);
653         printf("   Command line arguments:");
654         for (i = 0; i < argc; i++)
655                 printf(" %S", argv[i]);
656         printf("\n");
657
658         printf("   EFI version: %d.%02d\n", ST->Hdr.Revision >> 16,
659             ST->Hdr.Revision & 0xffff);
660         printf("   EFI Firmware: %S (rev %d.%02d)\n", ST->FirmwareVendor,
661             ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
662
663
664         /* Determine the devpath of our image so we can prefer it. */
665         text = efi_devpath_name(img->FilePath);
666         if (text != NULL) {
667                 printf("   Load Path: %S\n", text);
668                 efi_setenv_freebsd_wcs("LoaderPath", text);
669                 efi_free_devpath_name(text);
670         }
671
672         status = BS->HandleProtocol(img->DeviceHandle, &devid, (void **)&imgpath);
673         if (status == EFI_SUCCESS) {
674                 text = efi_devpath_name(imgpath);
675                 if (text != NULL) {
676                         printf("   Load Device: %S\n", text);
677                         efi_setenv_freebsd_wcs("LoaderDev", text);
678                         efi_free_devpath_name(text);
679                 }
680         }
681
682         boot_current = 0;
683         sz = sizeof(boot_current);
684         efi_global_getenv("BootCurrent", &boot_current, &sz);
685         printf("   BootCurrent: %04x\n", boot_current);
686
687         sz = sizeof(boot_order);
688         efi_global_getenv("BootOrder", &boot_order, &sz);
689         printf("   BootOrder:");
690         for (i = 0; i < sz / sizeof(boot_order[0]); i++)
691                 printf(" %04x%s", boot_order[i],
692                     boot_order[i] == boot_current ? "[*]" : "");
693         printf("\n");
694
695         /*
696          * Disable the watchdog timer. By default the boot manager sets
697          * the timer to 5 minutes before invoking a boot option. If we
698          * want to return to the boot manager, we have to disable the
699          * watchdog timer and since we're an interactive program, we don't
700          * want to wait until the user types "quit". The timer may have
701          * fired by then. We don't care if this fails. It does not prevent
702          * normal functioning in any way...
703          */
704         BS->SetWatchdogTimer(0, 0, 0, NULL);
705
706         /*
707          * Try and find a good currdev based on the image that was booted.
708          * It might be desirable here to have a short pause to allow falling
709          * through to the boot loader instead of returning instantly to follow
710          * the boot protocol and also allow an escape hatch for users wishing
711          * to try something different.
712          */
713         if (find_currdev(img) != 0)
714                 if (!interactive_interrupt("Failed to find bootable partition"))
715                         return (EFI_NOT_FOUND);
716
717         efi_init_environment();
718
719 #if !defined(__arm__)
720         for (k = 0; k < ST->NumberOfTableEntries; k++) {
721                 guid = &ST->ConfigurationTable[k].VendorGuid;
722                 if (!memcmp(guid, &smbios, sizeof(EFI_GUID))) {
723                         char buf[40];
724
725                         snprintf(buf, sizeof(buf), "%p",
726                             ST->ConfigurationTable[k].VendorTable);
727                         setenv("hint.smbios.0.mem", buf, 1);
728                         smbios_detect(ST->ConfigurationTable[k].VendorTable);
729                         break;
730                 }
731         }
732 #endif
733
734         interact();                     /* doesn't return */
735
736         return (EFI_SUCCESS);           /* keep compiler happy */
737 }
738
739 COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
740
741 static int
742 command_reboot(int argc, char *argv[])
743 {
744         int i;
745
746         for (i = 0; devsw[i] != NULL; ++i)
747                 if (devsw[i]->dv_cleanup != NULL)
748                         (devsw[i]->dv_cleanup)();
749
750         RS->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
751
752         /* NOTREACHED */
753         return (CMD_ERROR);
754 }
755
756 COMMAND_SET(quit, "quit", "exit the loader", command_quit);
757
758 static int
759 command_quit(int argc, char *argv[])
760 {
761         exit(0);
762         return (CMD_OK);
763 }
764
765 COMMAND_SET(memmap, "memmap", "print memory map", command_memmap);
766
767 static int
768 command_memmap(int argc, char *argv[])
769 {
770         UINTN sz;
771         EFI_MEMORY_DESCRIPTOR *map, *p;
772         UINTN key, dsz;
773         UINT32 dver;
774         EFI_STATUS status;
775         int i, ndesc;
776         char line[80];
777         static char *types[] = {
778             "Reserved",
779             "LoaderCode",
780             "LoaderData",
781             "BootServicesCode",
782             "BootServicesData",
783             "RuntimeServicesCode",
784             "RuntimeServicesData",
785             "ConventionalMemory",
786             "UnusableMemory",
787             "ACPIReclaimMemory",
788             "ACPIMemoryNVS",
789             "MemoryMappedIO",
790             "MemoryMappedIOPortSpace",
791             "PalCode"
792         };
793
794         sz = 0;
795         status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
796         if (status != EFI_BUFFER_TOO_SMALL) {
797                 printf("Can't determine memory map size\n");
798                 return (CMD_ERROR);
799         }
800         map = malloc(sz);
801         status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
802         if (EFI_ERROR(status)) {
803                 printf("Can't read memory map\n");
804                 return (CMD_ERROR);
805         }
806
807         ndesc = sz / dsz;
808         snprintf(line, sizeof(line), "%23s %12s %12s %8s %4s\n",
809             "Type", "Physical", "Virtual", "#Pages", "Attr");
810         pager_open();
811         if (pager_output(line)) {
812                 pager_close();
813                 return (CMD_OK);
814         }
815
816         for (i = 0, p = map; i < ndesc;
817              i++, p = NextMemoryDescriptor(p, dsz)) {
818                 printf("%23s %012jx %012jx %08jx ", types[p->Type],
819                     (uintmax_t)p->PhysicalStart, (uintmax_t)p->VirtualStart,
820                     (uintmax_t)p->NumberOfPages);
821                 if (p->Attribute & EFI_MEMORY_UC)
822                         printf("UC ");
823                 if (p->Attribute & EFI_MEMORY_WC)
824                         printf("WC ");
825                 if (p->Attribute & EFI_MEMORY_WT)
826                         printf("WT ");
827                 if (p->Attribute & EFI_MEMORY_WB)
828                         printf("WB ");
829                 if (p->Attribute & EFI_MEMORY_UCE)
830                         printf("UCE ");
831                 if (p->Attribute & EFI_MEMORY_WP)
832                         printf("WP ");
833                 if (p->Attribute & EFI_MEMORY_RP)
834                         printf("RP ");
835                 if (p->Attribute & EFI_MEMORY_XP)
836                         printf("XP ");
837                 if (pager_output("\n"))
838                         break;
839         }
840
841         pager_close();
842         return (CMD_OK);
843 }
844
845 COMMAND_SET(configuration, "configuration", "print configuration tables",
846     command_configuration);
847
848 static const char *
849 guid_to_string(EFI_GUID *guid)
850 {
851         static char buf[40];
852
853         sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
854             guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],
855             guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],
856             guid->Data4[5], guid->Data4[6], guid->Data4[7]);
857         return (buf);
858 }
859
860 static int
861 command_configuration(int argc, char *argv[])
862 {
863         char line[80];
864         UINTN i;
865
866         snprintf(line, sizeof(line), "NumberOfTableEntries=%lu\n",
867                 (unsigned long)ST->NumberOfTableEntries);
868         pager_open();
869         if (pager_output(line)) {
870                 pager_close();
871                 return (CMD_OK);
872         }
873
874         for (i = 0; i < ST->NumberOfTableEntries; i++) {
875                 EFI_GUID *guid;
876
877                 printf("  ");
878                 guid = &ST->ConfigurationTable[i].VendorGuid;
879                 if (!memcmp(guid, &mps, sizeof(EFI_GUID)))
880                         printf("MPS Table");
881                 else if (!memcmp(guid, &acpi, sizeof(EFI_GUID)))
882                         printf("ACPI Table");
883                 else if (!memcmp(guid, &acpi20, sizeof(EFI_GUID)))
884                         printf("ACPI 2.0 Table");
885                 else if (!memcmp(guid, &smbios, sizeof(EFI_GUID)))
886                         printf("SMBIOS Table %p",
887                             ST->ConfigurationTable[i].VendorTable);
888                 else if (!memcmp(guid, &smbios3, sizeof(EFI_GUID)))
889                         printf("SMBIOS3 Table");
890                 else if (!memcmp(guid, &dxe, sizeof(EFI_GUID)))
891                         printf("DXE Table");
892                 else if (!memcmp(guid, &hoblist, sizeof(EFI_GUID)))
893                         printf("HOB List Table");
894                 else if (!memcmp(guid, &lzmadecomp, sizeof(EFI_GUID)))
895                         printf("LZMA Compression");
896                 else if (!memcmp(guid, &mpcore, sizeof(EFI_GUID)))
897                         printf("ARM MpCore Information Table");
898                 else if (!memcmp(guid, &esrt, sizeof(EFI_GUID)))
899                         printf("ESRT Table");
900                 else if (!memcmp(guid, &memtype, sizeof(EFI_GUID)))
901                         printf("Memory Type Information Table");
902                 else if (!memcmp(guid, &debugimg, sizeof(EFI_GUID)))
903                         printf("Debug Image Info Table");
904                 else if (!memcmp(guid, &fdtdtb, sizeof(EFI_GUID)))
905                         printf("FDT Table");
906                 else
907                         printf("Unknown Table (%s)", guid_to_string(guid));
908                 snprintf(line, sizeof(line), " at %p\n",
909                     ST->ConfigurationTable[i].VendorTable);
910                 if (pager_output(line))
911                         break;
912         }
913
914         pager_close();
915         return (CMD_OK);
916 }
917
918
919 COMMAND_SET(mode, "mode", "change or display EFI text modes", command_mode);
920
921 static int
922 command_mode(int argc, char *argv[])
923 {
924         UINTN cols, rows;
925         unsigned int mode;
926         int i;
927         char *cp;
928         char rowenv[8];
929         EFI_STATUS status;
930         SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
931         extern void HO(void);
932
933         conout = ST->ConOut;
934
935         if (argc > 1) {
936                 mode = strtol(argv[1], &cp, 0);
937                 if (cp[0] != '\0') {
938                         printf("Invalid mode\n");
939                         return (CMD_ERROR);
940                 }
941                 status = conout->QueryMode(conout, mode, &cols, &rows);
942                 if (EFI_ERROR(status)) {
943                         printf("invalid mode %d\n", mode);
944                         return (CMD_ERROR);
945                 }
946                 status = conout->SetMode(conout, mode);
947                 if (EFI_ERROR(status)) {
948                         printf("couldn't set mode %d\n", mode);
949                         return (CMD_ERROR);
950                 }
951                 sprintf(rowenv, "%u", (unsigned)rows);
952                 setenv("LINES", rowenv, 1);
953                 HO();           /* set cursor */
954                 return (CMD_OK);
955         }
956
957         printf("Current mode: %d\n", conout->Mode->Mode);
958         for (i = 0; i <= conout->Mode->MaxMode; i++) {
959                 status = conout->QueryMode(conout, i, &cols, &rows);
960                 if (EFI_ERROR(status))
961                         continue;
962                 printf("Mode %d: %u columns, %u rows\n", i, (unsigned)cols,
963                     (unsigned)rows);
964         }
965
966         if (i != 0)
967                 printf("Select a mode with the command \"mode <number>\"\n");
968
969         return (CMD_OK);
970 }
971
972 #ifdef LOADER_FDT_SUPPORT
973 extern int command_fdt_internal(int argc, char *argv[]);
974
975 /*
976  * Since proper fdt command handling function is defined in fdt_loader_cmd.c,
977  * and declaring it as extern is in contradiction with COMMAND_SET() macro
978  * (which uses static pointer), we're defining wrapper function, which
979  * calls the proper fdt handling routine.
980  */
981 static int
982 command_fdt(int argc, char *argv[])
983 {
984
985         return (command_fdt_internal(argc, argv));
986 }
987
988 COMMAND_SET(fdt, "fdt", "flattened device tree handling", command_fdt);
989 #endif
990
991 /*
992  * Chain load another efi loader.
993  */
994 static int
995 command_chain(int argc, char *argv[])
996 {
997         EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
998         EFI_HANDLE loaderhandle;
999         EFI_LOADED_IMAGE *loaded_image;
1000         EFI_STATUS status;
1001         struct stat st;
1002         struct devdesc *dev;
1003         char *name, *path;
1004         void *buf;
1005         int fd;
1006
1007         if (argc < 2) {
1008                 command_errmsg = "wrong number of arguments";
1009                 return (CMD_ERROR);
1010         }
1011
1012         name = argv[1];
1013
1014         if ((fd = open(name, O_RDONLY)) < 0) {
1015                 command_errmsg = "no such file";
1016                 return (CMD_ERROR);
1017         }
1018
1019         if (fstat(fd, &st) < -1) {
1020                 command_errmsg = "stat failed";
1021                 close(fd);
1022                 return (CMD_ERROR);
1023         }
1024
1025         status = BS->AllocatePool(EfiLoaderCode, (UINTN)st.st_size, &buf);
1026         if (status != EFI_SUCCESS) {
1027                 command_errmsg = "failed to allocate buffer";
1028                 close(fd);
1029                 return (CMD_ERROR);
1030         }
1031         if (read(fd, buf, st.st_size) != st.st_size) {
1032                 command_errmsg = "error while reading the file";
1033                 (void)BS->FreePool(buf);
1034                 close(fd);
1035                 return (CMD_ERROR);
1036         }
1037         close(fd);
1038         status = BS->LoadImage(FALSE, IH, NULL, buf, st.st_size, &loaderhandle);
1039         (void)BS->FreePool(buf);
1040         if (status != EFI_SUCCESS) {
1041                 command_errmsg = "LoadImage failed";
1042                 return (CMD_ERROR);
1043         }
1044         status = BS->HandleProtocol(loaderhandle, &LoadedImageGUID,
1045             (void **)&loaded_image);
1046
1047         if (argc > 2) {
1048                 int i, len = 0;
1049                 CHAR16 *argp;
1050
1051                 for (i = 2; i < argc; i++)
1052                         len += strlen(argv[i]) + 1;
1053
1054                 len *= sizeof (*argp);
1055                 loaded_image->LoadOptions = argp = malloc (len);
1056                 loaded_image->LoadOptionsSize = len;
1057                 for (i = 2; i < argc; i++) {
1058                         char *ptr = argv[i];
1059                         while (*ptr)
1060                                 *(argp++) = *(ptr++);
1061                         *(argp++) = ' ';
1062                 }
1063                 *(--argv) = 0;
1064         }
1065
1066         if (efi_getdev((void **)&dev, name, (const char **)&path) == 0) {
1067 #ifdef EFI_ZFS_BOOT
1068                 struct zfs_devdesc *z_dev;
1069 #endif
1070                 struct disk_devdesc *d_dev;
1071                 pdinfo_t *hd, *pd;
1072
1073                 switch (dev->d_dev->dv_type) {
1074 #ifdef EFI_ZFS_BOOT
1075                 case DEVT_ZFS:
1076                         z_dev = (struct zfs_devdesc *)dev;
1077                         loaded_image->DeviceHandle =
1078                             efizfs_get_handle_by_guid(z_dev->pool_guid);
1079                         break;
1080 #endif
1081                 case DEVT_NET:
1082                         loaded_image->DeviceHandle =
1083                             efi_find_handle(dev->d_dev, dev->d_unit);
1084                         break;
1085                 default:
1086                         hd = efiblk_get_pdinfo(dev);
1087                         if (STAILQ_EMPTY(&hd->pd_part)) {
1088                                 loaded_image->DeviceHandle = hd->pd_handle;
1089                                 break;
1090                         }
1091                         d_dev = (struct disk_devdesc *)dev;
1092                         STAILQ_FOREACH(pd, &hd->pd_part, pd_link) {
1093                                 /*
1094                                  * d_partition should be 255
1095                                  */
1096                                 if (pd->pd_unit == (uint32_t)d_dev->d_slice) {
1097                                         loaded_image->DeviceHandle =
1098                                             pd->pd_handle;
1099                                         break;
1100                                 }
1101                         }
1102                         break;
1103                 }
1104         }
1105
1106         dev_cleanup();
1107         status = BS->StartImage(loaderhandle, NULL, NULL);
1108         if (status != EFI_SUCCESS) {
1109                 command_errmsg = "StartImage failed";
1110                 free(loaded_image->LoadOptions);
1111                 loaded_image->LoadOptions = NULL;
1112                 status = BS->UnloadImage(loaded_image);
1113                 return (CMD_ERROR);
1114         }
1115
1116         return (CMD_ERROR);     /* not reached */
1117 }
1118
1119 COMMAND_SET(chain, "chain", "chain load file", command_chain);