2 * Copyright (c) 1998 Robert Nordier
4 * Copyright (c) 2001 Robert Drehmel
6 * Copyright (c) 2014 Nathan Whitehorn
8 * Copyright (c) 2015 Eric McCorkle
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
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
22 #include <sys/cdefs.h>
24 #include <sys/param.h>
25 #include <machine/elf.h>
26 #include <machine/stdarg.h>
30 #include <eficonsctl.h>
32 #include <bootstrap.h>
33 #include "boot_module.h"
36 struct arch_switch archsw
;
37 struct fs_ops
*file_system
[] = {
41 static const boot_module_t
*boot_modules
[] =
51 #define NUM_BOOT_MODULES nitems(boot_modules)
52 /* The initial number of handles used to query EFI for partitions. */
53 #define NUM_HANDLES_INIT 24
55 EFI_SYSTEM_TABLE
*systab
;
56 EFI_BOOT_SERVICES
*bs
;
57 static EFI_HANDLE
*image
;
59 static EFI_GUID BlockIoProtocolGUID
= BLOCK_IO_PROTOCOL
;
60 static EFI_GUID DevicePathGUID
= DEVICE_PATH_PROTOCOL
;
61 static EFI_GUID LoadedImageGUID
= LOADED_IMAGE_PROTOCOL
;
62 static EFI_GUID ConsoleControlGUID
= EFI_CONSOLE_CONTROL_PROTOCOL_GUID
;
65 * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures
66 * memory is correctly aligned avoiding EFI_INVALID_PARAMETER returns from
70 Malloc(size_t len
, const char *file __unused
, int line __unused
)
74 if (bs
->AllocatePool(EfiLoaderData
, len
, &out
) == EFI_SUCCESS
)
81 Free(void *buf
, const char *file __unused
, int line __unused
)
84 (void)bs
->FreePool(buf
);
88 * nodes_match returns TRUE if the imgpath isn't NULL and the nodes match,
92 nodes_match(EFI_DEVICE_PATH
*imgpath
, EFI_DEVICE_PATH
*devpath
)
96 if (imgpath
== NULL
|| imgpath
->Type
!= devpath
->Type
||
97 imgpath
->SubType
!= devpath
->SubType
)
100 len
= DevicePathNodeLength(imgpath
);
101 if (len
!= DevicePathNodeLength(devpath
))
104 return (memcmp(imgpath
, devpath
, (size_t)len
) == 0);
108 * device_paths_match returns TRUE if the imgpath isn't NULL and all nodes
109 * in imgpath and devpath match up to their respective occurences of a
110 * media node, FALSE otherwise.
113 device_paths_match(EFI_DEVICE_PATH
*imgpath
, EFI_DEVICE_PATH
*devpath
)
119 while (!IsDevicePathEnd(imgpath
) && !IsDevicePathEnd(devpath
)) {
120 if (IsDevicePathType(imgpath
, MEDIA_DEVICE_PATH
) &&
121 IsDevicePathType(devpath
, MEDIA_DEVICE_PATH
))
124 if (!nodes_match(imgpath
, devpath
))
127 imgpath
= NextDevicePathNode(imgpath
);
128 devpath
= NextDevicePathNode(devpath
);
135 * devpath_last returns the last non-path end node in devpath.
137 static EFI_DEVICE_PATH
*
138 devpath_last(EFI_DEVICE_PATH
*devpath
)
141 while (!IsDevicePathEnd(NextDevicePathNode(devpath
)))
142 devpath
= NextDevicePathNode(devpath
);
148 * devpath_node_str is a basic output method for a devpath node which
149 * only understands a subset of the available sub types.
151 * If we switch to UEFI 2.x then we should update it to use:
152 * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL.
155 devpath_node_str(char *buf
, size_t size
, EFI_DEVICE_PATH
*devpath
)
158 switch (devpath
->Type
) {
159 case MESSAGING_DEVICE_PATH
:
160 switch (devpath
->SubType
) {
162 ATAPI_DEVICE_PATH
*atapi
;
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",
171 USB_DEVICE_PATH
*usb
;
173 usb
= (USB_DEVICE_PATH
*)devpath
;
174 return snprintf(buf
, size
, "usb(0x%02x,0x%02x)",
175 usb
->ParentPortNumber
, usb
->InterfaceNumber
);
178 SCSI_DEVICE_PATH
*scsi
;
180 scsi
= (SCSI_DEVICE_PATH
*)(void *)devpath
;
181 return snprintf(buf
, size
, "scsi(0x%02x,0x%02x)",
182 scsi
->Pun
, scsi
->Lun
);
185 SATA_DEVICE_PATH
*sata
;
187 sata
= (SATA_DEVICE_PATH
*)(void *)devpath
;
188 return snprintf(buf
, size
, "sata(0x%x,0x%x,0x%x)",
189 sata
->HBAPortNumber
, sata
->PortMultiplierPortNumber
,
193 return snprintf(buf
, size
, "msg(0x%02x)",
197 case HARDWARE_DEVICE_PATH
:
198 switch (devpath
->SubType
) {
200 PCI_DEVICE_PATH
*pci
;
202 pci
= (PCI_DEVICE_PATH
*)devpath
;
203 return snprintf(buf
, size
, "pci(0x%02x,0x%02x)",
204 pci
->Device
, pci
->Function
);
207 return snprintf(buf
, size
, "hw(0x%02x)",
211 case ACPI_DEVICE_PATH
: {
212 ACPI_HID_DEVICE_PATH
*acpi
;
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
)) {
218 return snprintf(buf
, size
, "pciroot(0x%x)",
221 return snprintf(buf
, size
, "pcieroot(0x%x)",
224 return snprintf(buf
, size
, "floppy(0x%x)",
227 return snprintf(buf
, size
, "keyboard(0x%x)",
230 return snprintf(buf
, size
, "serial(0x%x)",
233 return snprintf(buf
, size
, "parallelport(0x%x)",
236 return snprintf(buf
, size
, "acpi(pnp%04x,0x%x)",
237 EISA_ID_TO_NUM(acpi
->HID
), acpi
->UID
);
241 return snprintf(buf
, size
, "acpi(0x%08x,0x%x)", acpi
->HID
,
244 case MEDIA_DEVICE_PATH
:
245 switch (devpath
->SubType
) {
246 case MEDIA_CDROM_DP
: {
247 CDROM_DEVICE_PATH
*cdrom
;
249 cdrom
= (CDROM_DEVICE_PATH
*)(void *)devpath
;
250 return snprintf(buf
, size
, "cdrom(%x)",
253 case MEDIA_HARDDRIVE_DP
: {
254 HARDDRIVE_DEVICE_PATH
*hd
;
256 hd
= (HARDDRIVE_DEVICE_PATH
*)(void *)devpath
;
257 return snprintf(buf
, size
, "hd(%x)",
258 hd
->PartitionNumber
);
261 return snprintf(buf
, size
, "media(0x%02x)",
264 case BBS_DEVICE_PATH
:
265 return snprintf(buf
, size
, "bbs(0x%02x)", devpath
->SubType
);
266 case END_DEVICE_PATH_TYPE
:
270 return snprintf(buf
, size
, "type(0x%02x, 0x%02x)", devpath
->Type
,
275 * devpath_strlcat appends a text description of devpath to buf but not more
276 * than size - 1 characters followed by NUL-terminator.
279 devpath_strlcat(char *buf
, size_t size
, EFI_DEVICE_PATH
*devpath
)
286 while (!IsDevicePathEnd(devpath
)) {
287 len
= snprintf(buf
, size
- used
, "%s", sep
);
293 len
= devpath_node_str(buf
, size
- used
, devpath
);
298 devpath
= NextDevicePathNode(devpath
);
306 * devpath_str is convenience method which returns the text description of
307 * devpath using a static buffer, so it isn't thread safe!
310 devpath_str(EFI_DEVICE_PATH
*devpath
)
312 static char buf
[256];
314 devpath_strlcat(buf
, sizeof(buf
), devpath
);
320 * load_loader attempts to load the loader image data.
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.
326 * Only devices which have preferred matching the preferred parameter are tried.
329 load_loader(const boot_module_t
**modp
, dev_info_t
**devinfop
, void **bufp
,
330 size_t *bufsize
, BOOLEAN preferred
)
334 const boot_module_t
*mod
;
336 for (i
= 0; i
< NUM_BOOT_MODULES
; i
++) {
337 mod
= boot_modules
[i
];
338 for (dev
= mod
->devices(); dev
!= NULL
; dev
= dev
->next
) {
339 if (dev
->preferred
!= preferred
)
342 if (mod
->load(PATH_LOADER_EFI
, dev
, bufp
, bufsize
) ==
346 return (EFI_SUCCESS
);
351 return (EFI_NOT_FOUND
);
355 * try_boot only returns if it fails to load the loader. If it succeeds
356 * it simply boots, otherwise it returns the status of last EFI call.
361 size_t bufsize
, loadersize
, cmdsize
;
362 void *buf
, *loaderbuf
;
365 const boot_module_t
*mod
;
366 EFI_HANDLE loaderhandle
;
367 EFI_LOADED_IMAGE
*loaded_image
;
370 status
= load_loader(&mod
, &dev
, &loaderbuf
, &loadersize
, TRUE
);
371 if (status
!= EFI_SUCCESS
) {
372 status
= load_loader(&mod
, &dev
, &loaderbuf
, &loadersize
,
374 if (status
!= EFI_SUCCESS
) {
375 printf("Failed to load '%s'\n", PATH_LOADER_EFI
);
381 * Read in and parse the command line from /boot.config or /boot/config,
382 * if present. We'll pass it the next stage via a simple ASCII
383 * string. loader.efi has a hack for ASCII strings, so we'll use that to
384 * keep the size down here. We only try to read the alternate file if
385 * we get EFI_NOT_FOUND because all other errors mean that the boot_module
386 * had troubles with the filesystem. We could return early, but we'll let
387 * loading the actual kernel sort all that out. Since these files are
388 * optional, we don't report errors in trying to read them.
392 status
= mod
->load(PATH_DOTCONFIG
, dev
, &buf
, &bufsize
);
393 if (status
== EFI_NOT_FOUND
)
394 status
= mod
->load(PATH_CONFIG
, dev
, &buf
, &bufsize
);
395 if (status
== EFI_SUCCESS
) {
396 cmdsize
= bufsize
+ 1;
397 cmd
= malloc(cmdsize
);
400 memcpy(cmd
, buf
, bufsize
);
406 if ((status
= bs
->LoadImage(TRUE
, image
, devpath_last(dev
->devpath
),
407 loaderbuf
, loadersize
, &loaderhandle
)) != EFI_SUCCESS
) {
408 printf("Failed to load image provided by %s, size: %zu, (%lu)\n",
409 mod
->name
, loadersize
, EFI_ERROR_CODE(status
));
413 if ((status
= bs
->HandleProtocol(loaderhandle
, &LoadedImageGUID
,
414 (VOID
**)&loaded_image
)) != EFI_SUCCESS
) {
415 printf("Failed to query LoadedImage provided by %s (%lu)\n",
416 mod
->name
, EFI_ERROR_CODE(status
));
421 printf(" command args: %s\n", cmd
);
423 loaded_image
->DeviceHandle
= dev
->devhandle
;
424 loaded_image
->LoadOptionsSize
= cmdsize
;
425 loaded_image
->LoadOptions
= cmd
;
427 DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI
);
439 if ((status
= bs
->StartImage(loaderhandle
, NULL
, NULL
)) !=
441 printf("Failed to start image provided by %s (%lu)\n",
442 mod
->name
, EFI_ERROR_CODE(status
));
443 loaded_image
->LoadOptionsSize
= 0;
444 loaded_image
->LoadOptions
= NULL
;
452 if (loaderbuf
!= NULL
)
459 * probe_handle determines if the passed handle represents a logical partition
460 * if it does it uses each module in order to probe it and if successful it
461 * returns EFI_SUCCESS.
464 probe_handle(EFI_HANDLE h
, EFI_DEVICE_PATH
*imgpath
, BOOLEAN
*preferred
)
468 EFI_DEVICE_PATH
*devpath
;
472 /* Figure out if we're dealing with an actual partition. */
473 status
= bs
->HandleProtocol(h
, &DevicePathGUID
, (void **)&devpath
);
474 if (status
== EFI_UNSUPPORTED
)
477 if (status
!= EFI_SUCCESS
) {
478 DPRINTF("\nFailed to query DevicePath (%lu)\n",
479 EFI_ERROR_CODE(status
));
483 DPRINTF("probing: %s\n", devpath_str(devpath
));
485 status
= bs
->HandleProtocol(h
, &BlockIoProtocolGUID
, (void **)&blkio
);
486 if (status
== EFI_UNSUPPORTED
)
489 if (status
!= EFI_SUCCESS
) {
490 DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n",
491 EFI_ERROR_CODE(status
));
495 if (!blkio
->Media
->LogicalPartition
)
496 return (EFI_UNSUPPORTED
);
498 *preferred
= device_paths_match(imgpath
, devpath
);
500 /* Run through each module, see if it can load this partition */
501 for (i
= 0; i
< NUM_BOOT_MODULES
; i
++) {
502 if ((status
= bs
->AllocatePool(EfiLoaderData
,
503 sizeof(*devinfo
), (void **)&devinfo
)) !=
505 DPRINTF("\nFailed to allocate devinfo (%lu)\n",
506 EFI_ERROR_CODE(status
));
509 devinfo
->dev
= blkio
;
510 devinfo
->devpath
= devpath
;
511 devinfo
->devhandle
= h
;
512 devinfo
->devdata
= NULL
;
513 devinfo
->preferred
= *preferred
;
514 devinfo
->next
= NULL
;
516 status
= boot_modules
[i
]->probe(devinfo
);
517 if (status
== EFI_SUCCESS
)
518 return (EFI_SUCCESS
);
519 (void)bs
->FreePool(devinfo
);
522 return (EFI_UNSUPPORTED
);
526 * probe_handle_status calls probe_handle and outputs the returned status
530 probe_handle_status(EFI_HANDLE h
, EFI_DEVICE_PATH
*imgpath
)
533 BOOLEAN preferred
= false;
535 status
= probe_handle(h
, imgpath
, &preferred
);
539 case EFI_UNSUPPORTED
:
541 DPRINTF(" not supported\n");
546 DPRINTF(" supported (preferred)\n");
549 DPRINTF(" supported\n");
554 DPRINTF(" error (%lu)\n", EFI_ERROR_CODE(status
));
561 efi_main(EFI_HANDLE Ximage
, EFI_SYSTEM_TABLE
*Xsystab
)
564 EFI_LOADED_IMAGE
*img
;
565 EFI_DEVICE_PATH
*imgpath
;
567 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
= NULL
;
568 SIMPLE_TEXT_OUTPUT_INTERFACE
*conout
= NULL
;
569 UINTN i
, max_dim
, best_mode
, cols
, rows
, hsize
, nhandles
;
571 /* Basic initialization*/
574 bs
= Xsystab
->BootServices
;
576 /* Set up the console, so printf works. */
577 status
= bs
->LocateProtocol(&ConsoleControlGUID
, NULL
,
578 (VOID
**)&ConsoleControl
);
579 if (status
== EFI_SUCCESS
)
580 (void)ConsoleControl
->SetMode(ConsoleControl
,
581 EfiConsoleControlScreenText
);
583 * Reset the console and find the best text mode.
585 conout
= systab
->ConOut
;
586 conout
->Reset(conout
, TRUE
);
587 max_dim
= best_mode
= 0;
589 status
= conout
->QueryMode(conout
, i
, &cols
, &rows
);
590 if (EFI_ERROR(status
))
592 if (cols
* rows
> max_dim
) {
593 max_dim
= cols
* rows
;
598 conout
->SetMode(conout
, best_mode
);
599 conout
->EnableCursor(conout
, TRUE
);
600 conout
->ClearScreen(conout
);
602 printf("\n>> illumos EFI boot block\n");
603 printf(" Loader path: %s\n\n", PATH_LOADER_EFI
);
604 printf(" Initializing modules:");
605 for (i
= 0; i
< NUM_BOOT_MODULES
; i
++) {
606 printf(" %s", boot_modules
[i
]->name
);
607 if (boot_modules
[i
]->init
!= NULL
)
608 boot_modules
[i
]->init();
612 /* Get all the device handles */
613 hsize
= (UINTN
)NUM_HANDLES_INIT
* sizeof(EFI_HANDLE
);
614 if ((status
= bs
->AllocatePool(EfiLoaderData
, hsize
, (void **)&handles
))
616 panic("Failed to allocate %d handles (%lu)", NUM_HANDLES_INIT
,
617 EFI_ERROR_CODE(status
));
619 status
= bs
->LocateHandle(ByProtocol
, &BlockIoProtocolGUID
, NULL
,
624 case EFI_BUFFER_TOO_SMALL
:
625 (void)bs
->FreePool(handles
);
626 if ((status
= bs
->AllocatePool(EfiLoaderData
, hsize
,
627 (void **)&handles
)) != EFI_SUCCESS
) {
628 panic("Failed to allocate %zu handles (%lu)", hsize
/
629 sizeof(*handles
), EFI_ERROR_CODE(status
));
631 status
= bs
->LocateHandle(ByProtocol
, &BlockIoProtocolGUID
,
632 NULL
, &hsize
, handles
);
633 if (status
!= EFI_SUCCESS
)
634 panic("Failed to get device handles (%lu)\n",
635 EFI_ERROR_CODE(status
));
638 panic("Failed to get device handles (%lu)",
639 EFI_ERROR_CODE(status
));
642 /* Scan all partitions, probing with all modules. */
643 nhandles
= hsize
/ sizeof(*handles
);
644 printf(" Probing %zu block devices...", nhandles
);
647 /* Determine the devpath of our image so we can prefer it. */
648 status
= bs
->HandleProtocol(image
, &LoadedImageGUID
, (VOID
**)&img
);
650 if (status
== EFI_SUCCESS
) {
651 status
= bs
->HandleProtocol(img
->DeviceHandle
, &DevicePathGUID
,
653 if (status
!= EFI_SUCCESS
)
654 DPRINTF("Failed to get image DevicePath (%lu)\n",
655 EFI_ERROR_CODE(status
));
656 DPRINTF("boot1 imagepath: %s\n", devpath_str(imgpath
));
659 for (i
= 0; i
< nhandles
; i
++)
660 probe_handle_status(handles
[i
], imgpath
);
663 /* Status summary. */
664 for (i
= 0; i
< NUM_BOOT_MODULES
; i
++) {
666 boot_modules
[i
]->status();
671 /* If we get here, we're out of luck... */
672 panic("No bootable partitions found!");
676 * add_device adds a device to the passed devinfo list.
679 add_device(dev_info_t
**devinfop
, dev_info_t
*devinfo
)
683 if (*devinfop
== NULL
) {
688 for (dev
= *devinfop
; dev
->next
!= NULL
; dev
= dev
->next
)
695 panic(const char *fmt
, ...)
716 systab
->ConOut
->OutputString(systab
->ConOut
, buf
);
720 systab
->ConOut
->OutputString(systab
->ConOut
, buf
);
730 status
= systab
->ConIn
->ReadKeyStroke(systab
->ConIn
, &key
);
731 if (status
== EFI_NOT_READY
) {
732 bs
->WaitForEvent(1, &systab
->ConIn
->WaitForKey
, &junk
);
733 status
= systab
->ConIn
->ReadKeyStroke(systab
->ConIn
, &key
);
735 return (key
.UnicodeChar
);