boot/efi: Port most of our efi boot code to the EDK II headers.
[dragonfly.git] / sys / boot / efi / boot1 / boot1.c
1 /*-
2  * Copyright (c) 1998 Robert Nordier
3  * All rights reserved.
4  * Copyright (c) 2001 Robert Drehmel
5  * All rights reserved.
6  * Copyright (c) 2014 Nathan Whitehorn
7  * All rights reserved.
8  * Copyright (c) 2015 Eric McCorkle
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms are freely
12  * permitted provided that the above copyright notice and this
13  * paragraph and the following disclaimer are duplicated in all
14  * such forms.
15  *
16  * This software is provided "AS IS" and without any express or
17  * implied warranties, including, without limitation, the implied
18  * warranties of merchantability and fitness for a particular
19  * purpose.
20  *
21  * $FreeBSD: head/sys/boot/efi/boot1/boot1.c 296713 2016-03-12 06:50:16Z andrew $
22  */
23
24 #include <sys/param.h>
25 #include <machine/elf.h>
26 #include <machine/stdarg.h>
27 #include <stand.h>
28 #include <stdarg.h>
29
30 #include <efi.h>
31 #include <eficonsctl.h>
32
33 #include "boot_module.h"
34 #include "paths.h"
35
36 #define PATH_CONFIG     "/boot/config"
37 #define PATH_DOTCONFIG  "/boot.config"
38 #define PATH_LOADER     "/loader.efi"           /* /boot is dedicated */
39 #define PATH_LOADER_ALT "/boot/loader.efi"      /* /boot in root */
40
41 static const boot_module_t *boot_modules[] =
42 {
43 #ifdef EFI_UFS_BOOT
44         &ufs_module
45 #endif
46 };
47
48 #define NUM_BOOT_MODULES NELEM(boot_modules)
49 /* The initial number of handles used to query EFI for partitions. */
50 #define NUM_HANDLES_INIT        24
51
52 EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab);
53
54 EFI_SYSTEM_TABLE *systab;
55 EFI_BOOT_SERVICES *bs;
56 static EFI_HANDLE *image;
57
58 static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
59 static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
60 static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
61 static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
62
63 /*
64  * XXX DragonFly's libstand doesn't provide a way to override the malloc
65  *     implementation yet.
66  */
67 #if 0
68
69 /*
70  * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures
71  * memory is correctly aligned avoiding EFI_INVALID_PARAMETER returns from
72  * EFI methods.
73  */
74 void *
75 Malloc(size_t len, const char *file __unused, int line __unused)
76 {
77         void *out;
78
79         if (bs->AllocatePool(EfiLoaderData, len, &out) == EFI_SUCCESS)
80                 return (out);
81
82         return (NULL);
83 }
84
85 void
86 Free(void *buf, const char *file __unused, int line __unused)
87 {
88         (void)bs->FreePool(buf);
89 }
90
91 #endif
92
93 /*
94  * nodes_match returns TRUE if the imgpath isn't NULL and the nodes match,
95  * FALSE otherwise.
96  */
97 static BOOLEAN
98 nodes_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath)
99 {
100         int len;
101
102         if (imgpath == NULL || imgpath->Type != devpath->Type ||
103             imgpath->SubType != devpath->SubType)
104                 return (FALSE);
105
106         len = DevicePathNodeLength(imgpath);
107         if (len != DevicePathNodeLength(devpath))
108                 return (FALSE);
109
110         return (memcmp(imgpath, devpath, (size_t)len) == 0);
111 }
112
113 /*
114  * device_paths_match returns TRUE if the imgpath isn't NULL and all nodes
115  * in imgpath and devpath match up to their respect occurances of a media
116  * node, FALSE otherwise.
117  */
118 static BOOLEAN
119 device_paths_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath)
120 {
121
122         if (imgpath == NULL)
123                 return (FALSE);
124
125         while (!IsDevicePathEnd(imgpath) && !IsDevicePathEnd(devpath)) {
126                 if (IsDevicePathType(imgpath, MEDIA_DEVICE_PATH) &&
127                     IsDevicePathType(devpath, MEDIA_DEVICE_PATH))
128                         return (TRUE);
129
130                 if (!nodes_match(imgpath, devpath))
131                         return (FALSE);
132
133                 imgpath = NextDevicePathNode(imgpath);
134                 devpath = NextDevicePathNode(devpath);
135         }
136
137         return (FALSE);
138 }
139
140 /*
141  * devpath_last returns the last non-path end node in devpath.
142  */
143 static EFI_DEVICE_PATH *
144 devpath_last(EFI_DEVICE_PATH *devpath)
145 {
146
147         while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
148                 devpath = NextDevicePathNode(devpath);
149
150         return (devpath);
151 }
152
153 /*
154  * devpath_node_str is a basic output method for a devpath node which
155  * only understands a subset of the available sub types.
156  *
157  * If we switch to UEFI 2.x then we should update it to use:
158  * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL.
159  */
160 static int
161 devpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
162 {
163
164         switch (devpath->Type) {
165         case MESSAGING_DEVICE_PATH:
166                 switch (devpath->SubType) {
167                 case MSG_ATAPI_DP: {
168                         ATAPI_DEVICE_PATH *atapi;
169
170                         atapi = (ATAPI_DEVICE_PATH *)(void *)devpath;
171                         return snprintf(buf, size, "ata(%s,%s,0x%x)",
172                             (atapi->PrimarySecondary == 1) ?  "Sec" : "Pri",
173                             (atapi->SlaveMaster == 1) ?  "Slave" : "Master",
174                             atapi->Lun);
175                 }
176                 case MSG_USB_DP: {
177                         USB_DEVICE_PATH *usb;
178
179                         usb = (USB_DEVICE_PATH *)devpath;
180                         return snprintf(buf, size, "usb(0x%02x,0x%02x)",
181                             usb->ParentPortNumber, usb->InterfaceNumber);
182                 }
183                 case MSG_SCSI_DP: {
184                         SCSI_DEVICE_PATH *scsi;
185
186                         scsi = (SCSI_DEVICE_PATH *)(void *)devpath;
187                         return snprintf(buf, size, "scsi(0x%02x,0x%02x)",
188                             scsi->Pun, scsi->Lun);
189                 }
190                 case MSG_SATA_DP: {
191                         SATA_DEVICE_PATH *sata;
192
193                         sata = (SATA_DEVICE_PATH *)(void *)devpath;
194                         return snprintf(buf, size, "sata(0x%x,0x%x,0x%x)",
195                             sata->HBAPortNumber, sata->PortMultiplierPortNumber,
196                             sata->Lun);
197                 }
198                 default:
199                         return snprintf(buf, size, "msg(0x%02x)",
200                             devpath->SubType);
201                 }
202                 break;
203         case HARDWARE_DEVICE_PATH:
204                 switch (devpath->SubType) {
205                 case HW_PCI_DP: {
206                         PCI_DEVICE_PATH *pci;
207
208                         pci = (PCI_DEVICE_PATH *)devpath;
209                         return snprintf(buf, size, "pci(0x%02x,0x%02x)",
210                             pci->Device, pci->Function);
211                 }
212                 default:
213                         return snprintf(buf, size, "hw(0x%02x)",
214                             devpath->SubType);
215                 }
216                 break;
217         case ACPI_DEVICE_PATH: {
218                 ACPI_HID_DEVICE_PATH *acpi;
219
220                 acpi = (ACPI_HID_DEVICE_PATH *)(void *)devpath;
221                 if ((acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
222                         switch (EISA_ID_TO_NUM(acpi->HID)) {
223                         case 0x0a03:
224                                 return snprintf(buf, size, "pciroot(0x%x)",
225                                     acpi->UID);
226                         case 0x0a08:
227                                 return snprintf(buf, size, "pcieroot(0x%x)",
228                                     acpi->UID);
229                         case 0x0604:
230                                 return snprintf(buf, size, "floppy(0x%x)",
231                                     acpi->UID);
232                         case 0x0301:
233                                 return snprintf(buf, size, "keyboard(0x%x)",
234                                     acpi->UID);
235                         case 0x0501:
236                                 return snprintf(buf, size, "serial(0x%x)",
237                                     acpi->UID);
238                         case 0x0401:
239                                 return snprintf(buf, size, "parallelport(0x%x)",
240                                     acpi->UID);
241                         default:
242                                 return snprintf(buf, size, "acpi(pnp%04x,0x%x)",
243                                     EISA_ID_TO_NUM(acpi->HID), acpi->UID);
244                         }
245                 }
246
247                 return snprintf(buf, size, "acpi(0x%08x,0x%x)", acpi->HID,
248                     acpi->UID);
249         }
250         case MEDIA_DEVICE_PATH:
251                 switch (devpath->SubType) {
252                 case MEDIA_CDROM_DP: {
253                         CDROM_DEVICE_PATH *cdrom;
254
255                         cdrom = (CDROM_DEVICE_PATH *)(void *)devpath;
256                         return snprintf(buf, size, "cdrom(%x)",
257                             cdrom->BootEntry);
258                 }
259                 case MEDIA_HARDDRIVE_DP: {
260                         HARDDRIVE_DEVICE_PATH *hd;
261
262                         hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath;
263                         return snprintf(buf, size, "hd(%x)",
264                             hd->PartitionNumber);
265                 }
266                 default:
267                         return snprintf(buf, size, "media(0x%02x)",
268                             devpath->SubType);
269                 }
270         case BBS_DEVICE_PATH:
271                 return snprintf(buf, size, "bbs(0x%02x)", devpath->SubType);
272         case END_DEVICE_PATH_TYPE:
273                 return (0);
274         }
275
276         return snprintf(buf, size, "type(0x%02x, 0x%02x)", devpath->Type,
277             devpath->SubType);
278 }
279
280 /*
281  * devpath_strlcat appends a text description of devpath to buf but not more
282  * than size - 1 characters followed by NUL-terminator.
283  */
284 int
285 devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
286 {
287         size_t len, used;
288         const char *sep;
289
290         sep = "";
291         used = 0;
292         while (!IsDevicePathEnd(devpath)) {
293                 len = snprintf(buf, size - used, "%s", sep);
294                 used += len;
295                 if (used > size)
296                         return (used);
297                 buf += len;
298
299                 len = devpath_node_str(buf, size - used, devpath);
300                 used += len;
301                 if (used > size)
302                         return (used);
303                 buf += len;
304                 devpath = NextDevicePathNode(devpath);
305                 sep = ":";
306         }
307
308         return (used);
309 }
310
311 /*
312  * devpath_str is convenience method which returns the text description of
313  * devpath using a static buffer, so it isn't thread safe!
314  */
315 char *
316 devpath_str(EFI_DEVICE_PATH *devpath)
317 {
318         static char buf[256];
319
320         devpath_strlcat(buf, sizeof(buf), devpath);
321
322         return buf;
323 }
324
325 /*
326  * load_loader attempts to load the loader image data.
327  *
328  * It tries each module and its respective devices, identified by mod->probe,
329  * in order until a successful load occurs at which point it returns EFI_SUCCESS
330  * and EFI_NOT_FOUND otherwise.
331  *
332  * Only devices which have preferred matching the preferred parameter are tried.
333  */
334 static EFI_STATUS
335 load_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp,
336     size_t *bufsize, BOOLEAN preferred)
337 {
338         UINTN i;
339         dev_info_t *dev;
340         const boot_module_t *mod;
341         EFI_STATUS status;
342
343         for (i = 0; i < NUM_BOOT_MODULES; i++) {
344                 if (boot_modules[i] == NULL)
345                         continue;
346                 mod = boot_modules[i];
347                 for (dev = mod->devices(); dev != NULL; dev = dev->next) {
348                         if (dev->preferred != preferred)
349                                 continue;
350
351                         status = mod->load(PATH_LOADER, dev, bufp, bufsize);
352                         if (status == EFI_NOT_FOUND) {
353                                 status = mod->load(PATH_LOADER_ALT, dev, bufp,
354                                     bufsize);
355                         }
356                         if (status == EFI_SUCCESS) {
357                                 *devinfop = dev;
358                                 *modp = mod;
359                                 return (EFI_SUCCESS);
360                         }
361                 }
362         }
363
364         return (EFI_NOT_FOUND);
365 }
366
367 /*
368  * try_boot only returns if it fails to load the loader. If it succeeds
369  * it simply boots, otherwise it returns the status of last EFI call.
370  */
371 static EFI_STATUS
372 try_boot(void)
373 {
374         size_t bufsize, loadersize, cmdsize;
375         void *buf, *loaderbuf;
376         char *cmd;
377         dev_info_t *dev;
378         const boot_module_t *mod;
379         EFI_HANDLE loaderhandle;
380         EFI_LOADED_IMAGE *loaded_image;
381         EFI_STATUS status;
382
383         status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE);
384         if (status != EFI_SUCCESS) {
385                 status = load_loader(&mod, &dev, &loaderbuf, &loadersize,
386                     FALSE);
387                 if (status != EFI_SUCCESS) {
388                         printf("Failed to load '%s' or '%s'\n",
389                             PATH_LOADER, PATH_LOADER_ALT);
390                         return (status);
391                 }
392         }
393
394         /*
395          * Read in and parse the command line from /boot.config or /boot/config,
396          * if present. We'll pass it the next stage via a simple ASCII
397          * string. loader.efi has a hack for ASCII strings, so we'll use that to
398          * keep the size down here. We only try to read the alternate file if
399          * we get EFI_NOT_FOUND because all other errors mean that the boot_module
400          * had troubles with the filesystem. We could return early, but we'll let
401          * loading the actual kernel sort all that out. Since these files are
402          * optional, we don't report errors in trying to read them.
403          */
404         cmd = NULL;
405         cmdsize = 0;
406         status = mod->load(PATH_DOTCONFIG, dev, &buf, &bufsize);
407         if (status == EFI_NOT_FOUND)
408                 status = mod->load(PATH_CONFIG, dev, &buf, &bufsize);
409         if (status == EFI_SUCCESS) {
410                 cmdsize = bufsize + 1;
411                 cmd = malloc(cmdsize);
412                 if (cmd == NULL)
413                         goto errout;
414                 memcpy(cmd, buf, bufsize);
415                 cmd[bufsize] = '\0';
416                 free(buf);
417                 buf = NULL;
418         }
419
420         if ((status = bs->LoadImage(TRUE, image, devpath_last(dev->devpath),
421             loaderbuf, loadersize, &loaderhandle)) != EFI_SUCCESS) {
422                 printf("Failed to load image provided by %s, size: %zu, (%llu)\n",
423                      mod->name, loadersize, status);
424                 goto errout;
425         }
426
427         if ((status = bs->HandleProtocol(loaderhandle, &LoadedImageGUID,
428             (VOID**)&loaded_image)) != EFI_SUCCESS) {
429                 printf("Failed to query LoadedImage provided by %s (%llu)\n",
430                     mod->name, status);
431                 goto errout;
432         }
433
434         if (cmd != NULL)
435                 printf("    command args: %s\n", cmd);
436
437         loaded_image->DeviceHandle = dev->devhandle;
438         loaded_image->LoadOptionsSize = cmdsize;
439         loaded_image->LoadOptions = cmd;
440
441         DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI);
442         DSTALL(1000000);
443         DPRINTF(".");
444         DSTALL(1000000);
445         DPRINTF(".");
446         DSTALL(1000000);
447         DPRINTF(".");
448         DSTALL(1000000);
449         DPRINTF(".");
450         DSTALL(1000000);
451         DPRINTF(".\n");
452
453         if ((status = bs->StartImage(loaderhandle, NULL, NULL)) !=
454             EFI_SUCCESS) {
455                 printf("Failed to start image provided by %s (%llu)\n",
456                     mod->name, status);
457                 loaded_image->LoadOptionsSize = 0;
458                 loaded_image->LoadOptions = NULL;
459         }
460
461 errout:
462         if (cmd != NULL)
463                 free(cmd);
464         if (buf != NULL)
465                 free(buf);
466         if (loaderbuf != NULL)
467                 free(loaderbuf);
468
469         return (status);
470 }
471
472 /*
473  * probe_handle determines if the passed handle represents a logical partition
474  * if it does it uses each module in order to probe it and if successful it
475  * returns EFI_SUCCESS.
476  */
477 static EFI_STATUS
478 probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN *preferred)
479 {
480         dev_info_t *devinfo;
481         EFI_BLOCK_IO *blkio;
482         EFI_DEVICE_PATH *devpath;
483         EFI_STATUS status;
484         UINTN i;
485
486         /* Figure out if we're dealing with an actual partition. */
487         status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
488         if (status == EFI_UNSUPPORTED)
489                 return (status);
490
491         if (status != EFI_SUCCESS) {
492                 DPRINTF("\nFailed to query DevicePath (%llu)\n",
493                     status);
494                 return (status);
495         }
496
497         DPRINTF("probing: %s\n", devpath_str(devpath));
498
499         status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
500         if (status == EFI_UNSUPPORTED)
501                 return (status);
502
503         if (status != EFI_SUCCESS) {
504                 DPRINTF("\nFailed to query BlockIoProtocol (%llu)\n",
505                     status);
506                 return (status);
507         }
508
509         if (!blkio->Media->LogicalPartition)
510                 return (EFI_UNSUPPORTED);
511
512         *preferred = device_paths_match(imgpath, devpath);
513
514         /* Run through each module, see if it can load this partition */
515         for (i = 0; i < NUM_BOOT_MODULES; i++) {
516                 if (boot_modules[i] == NULL)
517                         continue;
518
519                 if ((status = bs->AllocatePool(EfiLoaderData,
520                     sizeof(*devinfo), (void **)&devinfo)) !=
521                     EFI_SUCCESS) {
522                         DPRINTF("\nFailed to allocate devinfo (%llu)\n",
523                             status);
524                         continue;
525                 }
526                 devinfo->dev = blkio;
527                 devinfo->devpath = devpath;
528                 devinfo->devhandle = h;
529                 devinfo->devdata = NULL;
530                 devinfo->preferred = *preferred;
531                 devinfo->next = NULL;
532
533                 status = boot_modules[i]->probe(devinfo);
534                 if (status == EFI_SUCCESS)
535                         return (EFI_SUCCESS);
536                 (void)bs->FreePool(devinfo);
537         }
538
539         return (EFI_UNSUPPORTED);
540 }
541
542 /*
543  * probe_handle_status calls probe_handle and outputs the returned status
544  * of the call.
545  */
546 static void
547 probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath)
548 {
549         EFI_STATUS status;
550         BOOLEAN preferred;
551
552         preferred = FALSE;
553         status = probe_handle(h, imgpath, &preferred);
554
555         DPRINTF("probe: ");
556         switch (status) {
557         case EFI_UNSUPPORTED:
558                 printf(".");
559                 DPRINTF(" not supported\n");
560                 break;
561         case EFI_SUCCESS:
562                 if (preferred) {
563                         printf("%c", '*');
564                         DPRINTF(" supported (preferred)\n");
565                 } else {
566                         printf("%c", '+');
567                         DPRINTF(" supported\n");
568                 }
569                 break;
570         default:
571                 printf("x");
572                 DPRINTF(" error (%llu)\n", status);
573                 break;
574         }
575         DSTALL(500000);
576 }
577
578 EFI_STATUS
579 efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
580 {
581         EFI_HANDLE *handles;
582         EFI_LOADED_IMAGE *img;
583         EFI_DEVICE_PATH *imgpath;
584         EFI_STATUS status;
585         EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
586         SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
587         UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles;
588
589         /* Basic initialization*/
590         systab = Xsystab;
591         image = Ximage;
592         bs = Xsystab->BootServices;
593
594         /* Set up the console, so printf works. */
595         status = bs->LocateProtocol(&ConsoleControlGUID, NULL,
596             (VOID **)&ConsoleControl);
597         if (status == EFI_SUCCESS)
598                 (void)ConsoleControl->SetMode(ConsoleControl,
599                     EfiConsoleControlScreenText);
600         /*
601          * Reset the console and find the best text mode.
602          */
603         conout = systab->ConOut;
604         conout->Reset(conout, TRUE);
605         max_dim = best_mode = 0;
606         for (i = 0; ; i++) {
607                 status = conout->QueryMode(conout, i, &cols, &rows);
608                 if (EFI_ERROR(status)) {
609                         /* Mode 1 (80x50) can be unsupported on some hw. */
610                         if (i == 1)
611                                 continue;
612                         else
613                                 break;
614                 }
615                 if (cols * rows > max_dim) {
616                         max_dim = cols * rows;
617                         best_mode = i;
618                 }
619         }
620         if (max_dim > 0)
621                 conout->SetMode(conout, best_mode);
622         conout->EnableCursor(conout, TRUE);
623         conout->ClearScreen(conout);
624
625         printf("\n>> DragonFly EFI boot block\n");
626         printf("   Loader path: %s:%s\n\n", PATH_LOADER, PATH_LOADER_ALT);
627         printf("   Initializing modules:");
628         for (i = 0; i < NUM_BOOT_MODULES; i++) {
629                 if (boot_modules[i] == NULL)
630                         continue;
631
632                 printf(" %s", boot_modules[i]->name);
633                 if (boot_modules[i]->init != NULL)
634                         boot_modules[i]->init();
635         }
636         putchar('\n');
637
638         /* Get all the device handles */
639         hsize = (UINTN)NUM_HANDLES_INIT * sizeof(EFI_HANDLE);
640         if ((status = bs->AllocatePool(EfiLoaderData, hsize, (void **)&handles))
641             != EFI_SUCCESS)
642                 panic("Failed to allocate %d handles (%llu)", NUM_HANDLES_INIT,
643                     status);
644
645         status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL,
646             &hsize, handles);
647         switch (status) {
648         case EFI_SUCCESS:
649                 break;
650         case EFI_BUFFER_TOO_SMALL:
651                 (void)bs->FreePool(handles);
652                 if ((status = bs->AllocatePool(EfiLoaderData, hsize,
653                     (void **)&handles)) != EFI_SUCCESS) {
654                         panic("Failed to allocate %llu handles (%llu)", hsize /
655                             sizeof(*handles), status);
656                 }
657                 status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID,
658                     NULL, &hsize, handles);
659                 if (status != EFI_SUCCESS)
660                         panic("Failed to get device handles (%llu)\n",
661                             status);
662                 break;
663         default:
664                 panic("Failed to get device handles (%llu)",
665                     status);
666         }
667
668         /* Scan all partitions, probing with all modules. */
669         nhandles = hsize / sizeof(*handles);
670         printf("   Probing %llu block devices...", nhandles);
671         DPRINTF("\n");
672
673         /* Determine the devpath of our image so we can prefer it. */
674         status = bs->HandleProtocol(image, &LoadedImageGUID, (VOID**)&img);
675         imgpath = NULL;
676         if (status == EFI_SUCCESS) {
677                 status = bs->HandleProtocol(img->DeviceHandle, &DevicePathGUID,
678                     (void **)&imgpath);
679                 if (status != EFI_SUCCESS)
680                         DPRINTF("Failed to get image DevicePath (%llu)\n",
681                             status);
682                 DPRINTF("boot1 imagepath: %s\n", devpath_str(imgpath));
683         }
684
685         for (i = 0; i < nhandles; i++)
686                 probe_handle_status(handles[i], imgpath);
687         printf(" done\n");
688
689         /* Status summary. */
690         for (i = 0; i < NUM_BOOT_MODULES; i++) {
691                 if (boot_modules[i] != NULL) {
692                         printf("    ");
693                         boot_modules[i]->status();
694                 }
695         }
696
697         try_boot();
698
699         /* If we get here, we're out of luck... */
700         panic("No bootable partitions found!");
701 }
702
703 /*
704  * add_device adds a device to the passed devinfo list.
705  */
706 void
707 add_device(dev_info_t **devinfop, dev_info_t *devinfo)
708 {
709         dev_info_t *dev;
710
711         if (*devinfop == NULL) {
712                 *devinfop = devinfo;
713                 return;
714         }
715
716         for (dev = *devinfop; dev->next != NULL; dev = dev->next)
717                 ;
718
719         dev->next = devinfo;
720 }
721
722 void
723 panic(const char *fmt, ...)
724 {
725         va_list ap;
726
727         printf("panic: ");
728         va_start(ap, fmt);
729         vprintf(fmt, ap);
730         va_end(ap);
731         printf("\n");
732
733         while (1) {}
734 }
735
736 void
737 putchar(int c)
738 {
739         CHAR16 buf[2];
740
741         if (c == '\n') {
742                 buf[0] = '\r';
743                 buf[1] = 0;
744                 systab->ConOut->OutputString(systab->ConOut, buf);
745         }
746         buf[0] = c;
747         buf[1] = 0;
748         systab->ConOut->OutputString(systab->ConOut, buf);
749 }