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