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
[] =
47 #define NUM_BOOT_MODULES nitems(boot_modules)
48 /* The initial number of handles used to query EFI for partitions. */
49 #define NUM_HANDLES_INIT 24
51 static EFI_GUID BlockIoProtocolGUID
= BLOCK_IO_PROTOCOL
;
52 static EFI_GUID DevicePathGUID
= DEVICE_PATH_PROTOCOL
;
53 static EFI_GUID LoadedImageGUID
= LOADED_IMAGE_PROTOCOL
;
54 static EFI_GUID ConsoleControlGUID
= EFI_CONSOLE_CONTROL_PROTOCOL_GUID
;
57 * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures
58 * memory is correctly aligned avoiding EFI_INVALID_PARAMETER returns from
62 Malloc(size_t len
, const char *file __unused
, int line __unused
)
66 if (BS
->AllocatePool(EfiLoaderData
, len
, &out
) == EFI_SUCCESS
)
73 Free(void *buf
, const char *file __unused
, int line __unused
)
76 (void)BS
->FreePool(buf
);
80 * nodes_match returns TRUE if the imgpath isn't NULL and the nodes match,
84 nodes_match(EFI_DEVICE_PATH
*imgpath
, EFI_DEVICE_PATH
*devpath
)
88 if (imgpath
== NULL
|| imgpath
->Type
!= devpath
->Type
||
89 imgpath
->SubType
!= devpath
->SubType
)
92 len
= DevicePathNodeLength(imgpath
);
93 if (len
!= DevicePathNodeLength(devpath
))
96 return (memcmp(imgpath
, devpath
, (size_t)len
) == 0);
100 * device_paths_match returns TRUE if the imgpath isn't NULL and all nodes
101 * in imgpath and devpath match up to their respective occurences of a
102 * media node, FALSE otherwise.
105 device_paths_match(EFI_DEVICE_PATH
*imgpath
, EFI_DEVICE_PATH
*devpath
)
111 while (!IsDevicePathEnd(imgpath
) && !IsDevicePathEnd(devpath
)) {
112 if (IsDevicePathType(imgpath
, MEDIA_DEVICE_PATH
) &&
113 IsDevicePathType(devpath
, MEDIA_DEVICE_PATH
))
116 if (!nodes_match(imgpath
, devpath
))
119 imgpath
= NextDevicePathNode(imgpath
);
120 devpath
= NextDevicePathNode(devpath
);
127 * devpath_last returns the last non-path end node in devpath.
129 static EFI_DEVICE_PATH
*
130 devpath_last(EFI_DEVICE_PATH
*devpath
)
133 while (!IsDevicePathEnd(NextDevicePathNode(devpath
)))
134 devpath
= NextDevicePathNode(devpath
);
140 * devpath_node_str is a basic output method for a devpath node which
141 * only understands a subset of the available sub types.
143 * If we switch to UEFI 2.x then we should update it to use:
144 * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL.
147 devpath_node_str(char *buf
, size_t size
, EFI_DEVICE_PATH
*devpath
)
150 switch (devpath
->Type
) {
151 case MESSAGING_DEVICE_PATH
:
152 switch (devpath
->SubType
) {
154 ATAPI_DEVICE_PATH
*atapi
;
156 atapi
= (ATAPI_DEVICE_PATH
*)(void *)devpath
;
157 return snprintf(buf
, size
, "ata(%s,%s,0x%x)",
158 (atapi
->PrimarySecondary
== 1) ? "Sec" : "Pri",
159 (atapi
->SlaveMaster
== 1) ? "Slave" : "Master",
163 USB_DEVICE_PATH
*usb
;
165 usb
= (USB_DEVICE_PATH
*)devpath
;
166 return snprintf(buf
, size
, "usb(0x%02x,0x%02x)",
167 usb
->ParentPortNumber
, usb
->InterfaceNumber
);
170 SCSI_DEVICE_PATH
*scsi
;
172 scsi
= (SCSI_DEVICE_PATH
*)(void *)devpath
;
173 return snprintf(buf
, size
, "scsi(0x%02x,0x%02x)",
174 scsi
->Pun
, scsi
->Lun
);
177 SATA_DEVICE_PATH
*sata
;
179 sata
= (SATA_DEVICE_PATH
*)(void *)devpath
;
180 return snprintf(buf
, size
, "sata(0x%x,0x%x,0x%x)",
181 sata
->HBAPortNumber
, sata
->PortMultiplierPortNumber
,
185 return snprintf(buf
, size
, "msg(0x%02x)",
189 case HARDWARE_DEVICE_PATH
:
190 switch (devpath
->SubType
) {
192 PCI_DEVICE_PATH
*pci
;
194 pci
= (PCI_DEVICE_PATH
*)devpath
;
195 return snprintf(buf
, size
, "pci(0x%02x,0x%02x)",
196 pci
->Device
, pci
->Function
);
199 return snprintf(buf
, size
, "hw(0x%02x)",
203 case ACPI_DEVICE_PATH
: {
204 ACPI_HID_DEVICE_PATH
*acpi
;
206 acpi
= (ACPI_HID_DEVICE_PATH
*)(void *)devpath
;
207 if ((acpi
->HID
& PNP_EISA_ID_MASK
) == PNP_EISA_ID_CONST
) {
208 switch (EISA_ID_TO_NUM(acpi
->HID
)) {
210 return snprintf(buf
, size
, "pciroot(0x%x)",
213 return snprintf(buf
, size
, "pcieroot(0x%x)",
216 return snprintf(buf
, size
, "floppy(0x%x)",
219 return snprintf(buf
, size
, "keyboard(0x%x)",
222 return snprintf(buf
, size
, "serial(0x%x)",
225 return snprintf(buf
, size
, "parallelport(0x%x)",
228 return snprintf(buf
, size
, "acpi(pnp%04x,0x%x)",
229 EISA_ID_TO_NUM(acpi
->HID
), acpi
->UID
);
233 return snprintf(buf
, size
, "acpi(0x%08x,0x%x)", acpi
->HID
,
236 case MEDIA_DEVICE_PATH
:
237 switch (devpath
->SubType
) {
238 case MEDIA_CDROM_DP
: {
239 CDROM_DEVICE_PATH
*cdrom
;
241 cdrom
= (CDROM_DEVICE_PATH
*)(void *)devpath
;
242 return snprintf(buf
, size
, "cdrom(%x)",
245 case MEDIA_HARDDRIVE_DP
: {
246 HARDDRIVE_DEVICE_PATH
*hd
;
248 hd
= (HARDDRIVE_DEVICE_PATH
*)(void *)devpath
;
249 return snprintf(buf
, size
, "hd(%x)",
250 hd
->PartitionNumber
);
253 return snprintf(buf
, size
, "media(0x%02x)",
256 case BBS_DEVICE_PATH
:
257 return snprintf(buf
, size
, "bbs(0x%02x)", devpath
->SubType
);
258 case END_DEVICE_PATH_TYPE
:
262 return snprintf(buf
, size
, "type(0x%02x, 0x%02x)", devpath
->Type
,
267 * devpath_strlcat appends a text description of devpath to buf but not more
268 * than size - 1 characters followed by NUL-terminator.
271 devpath_strlcat(char *buf
, size_t size
, EFI_DEVICE_PATH
*devpath
)
278 while (!IsDevicePathEnd(devpath
)) {
279 len
= snprintf(buf
, size
- used
, "%s", sep
);
285 len
= devpath_node_str(buf
, size
- used
, devpath
);
290 devpath
= NextDevicePathNode(devpath
);
298 * devpath_str is convenience method which returns the text description of
299 * devpath using a static buffer, so it isn't thread safe!
302 devpath_str(EFI_DEVICE_PATH
*devpath
)
304 static char buf
[256];
306 devpath_strlcat(buf
, sizeof(buf
), devpath
);
312 * load_loader attempts to load the loader image data.
314 * It tries each module and its respective devices, identified by mod->probe,
315 * in order until a successful load occurs at which point it returns EFI_SUCCESS
316 * and EFI_NOT_FOUND otherwise.
318 * Only devices which have preferred matching the preferred parameter are tried.
321 load_loader(const boot_module_t
**modp
, dev_info_t
**devinfop
, void **bufp
,
322 size_t *bufsize
, BOOLEAN preferred
)
326 const boot_module_t
*mod
;
328 for (i
= 0; i
< NUM_BOOT_MODULES
; i
++) {
329 mod
= boot_modules
[i
];
330 for (dev
= mod
->devices(); dev
!= NULL
; dev
= dev
->next
) {
331 if (dev
->preferred
!= preferred
)
334 if (mod
->load(PATH_LOADER_EFI
, dev
, bufp
, bufsize
) ==
338 return (EFI_SUCCESS
);
343 return (EFI_NOT_FOUND
);
347 * try_boot only returns if it fails to load the loader. If it succeeds
348 * it simply boots, otherwise it returns the status of last EFI call.
353 size_t bufsize
, loadersize
, cmdsize
;
354 void *buf
, *loaderbuf
;
357 const boot_module_t
*mod
;
358 EFI_HANDLE loaderhandle
;
359 EFI_LOADED_IMAGE
*loaded_image
;
362 status
= load_loader(&mod
, &dev
, &loaderbuf
, &loadersize
, TRUE
);
363 if (status
!= EFI_SUCCESS
) {
364 status
= load_loader(&mod
, &dev
, &loaderbuf
, &loadersize
,
366 if (status
!= EFI_SUCCESS
) {
367 printf("Failed to load '%s'\n", PATH_LOADER_EFI
);
373 * Read in and parse the command line from /boot.config or /boot/config,
374 * if present. We'll pass it the next stage via a simple ASCII
375 * string. loader.efi has a hack for ASCII strings, so we'll use that to
376 * keep the size down here. We only try to read the alternate file if
377 * we get EFI_NOT_FOUND because all other errors mean that the boot_module
378 * had troubles with the filesystem. We could return early, but we'll let
379 * loading the actual kernel sort all that out. Since these files are
380 * optional, we don't report errors in trying to read them.
384 status
= mod
->load(PATH_DOTCONFIG
, dev
, &buf
, &bufsize
);
385 if (status
== EFI_NOT_FOUND
)
386 status
= mod
->load(PATH_CONFIG
, dev
, &buf
, &bufsize
);
387 if (status
== EFI_SUCCESS
) {
388 cmdsize
= bufsize
+ 1;
389 cmd
= malloc(cmdsize
);
392 memcpy(cmd
, buf
, bufsize
);
398 if ((status
= BS
->LoadImage(TRUE
, IH
, devpath_last(dev
->devpath
),
399 loaderbuf
, loadersize
, &loaderhandle
)) != EFI_SUCCESS
) {
400 printf("Failed to load image provided by %s, size: %zu, (%lu)\n",
401 mod
->name
, loadersize
, EFI_ERROR_CODE(status
));
405 if ((status
= BS
->HandleProtocol(loaderhandle
, &LoadedImageGUID
,
406 (VOID
**)&loaded_image
)) != EFI_SUCCESS
) {
407 printf("Failed to query LoadedImage provided by %s (%lu)\n",
408 mod
->name
, EFI_ERROR_CODE(status
));
413 printf(" command args: %s\n", cmd
);
415 loaded_image
->DeviceHandle
= dev
->devhandle
;
416 loaded_image
->LoadOptionsSize
= cmdsize
;
417 loaded_image
->LoadOptions
= cmd
;
419 DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI
);
431 if ((status
= BS
->StartImage(loaderhandle
, NULL
, NULL
)) !=
433 printf("Failed to start image provided by %s (%lu)\n",
434 mod
->name
, EFI_ERROR_CODE(status
));
435 loaded_image
->LoadOptionsSize
= 0;
436 loaded_image
->LoadOptions
= NULL
;
444 if (loaderbuf
!= NULL
)
451 * probe_handle determines if the passed handle represents a logical partition
452 * if it does it uses each module in order to probe it and if successful it
453 * returns EFI_SUCCESS.
456 probe_handle(EFI_HANDLE h
, EFI_DEVICE_PATH
*imgpath
, BOOLEAN
*preferred
)
459 EFI_BLOCK_IO
*blkio
= NULL
;
460 EFI_DEVICE_PATH
*devpath
, *dp
;
461 HARDDRIVE_DEVICE_PATH
*hd
;
463 extern UINT64 start_sector
; /* from multiboot.S */
466 /* Figure out if we're dealing with an actual partition. */
467 status
= BS
->HandleProtocol(h
, &DevicePathGUID
, (void **)&devpath
);
468 if (status
== EFI_UNSUPPORTED
)
471 if (status
!= EFI_SUCCESS
) {
472 DPRINTF("\nFailed to query DevicePath (%lu)\n",
473 EFI_ERROR_CODE(status
));
477 DPRINTF("probing: %s\n", devpath_str(devpath
));
479 status
= BS
->HandleProtocol(h
, &BlockIoProtocolGUID
, (void **)&blkio
);
480 if (status
== EFI_UNSUPPORTED
)
483 if (status
!= EFI_SUCCESS
) {
484 DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n",
485 EFI_ERROR_CODE(status
));
489 if (!blkio
->Media
->LogicalPartition
)
490 return (EFI_UNSUPPORTED
);
492 *preferred
= device_paths_match(imgpath
, devpath
);
495 * This is the boot device. Check for the start of the partition.
496 * If it does not match what is specified in the stage1 loader then
497 * this is not our preferred device.
499 if (*preferred
== TRUE
&& start_sector
!= 0) {
500 dp
= devpath_last(devpath
);
503 dp
->Type
== MEDIA_DEVICE_PATH
&&
504 dp
->SubType
== MEDIA_HARDDRIVE_DP
) {
505 hd
= (HARDDRIVE_DEVICE_PATH
*)dp
;
506 if (hd
->PartitionStart
!= start_sector
)
511 /* Run through each module, see if it can load this partition */
512 for (i
= 0; i
< NUM_BOOT_MODULES
; i
++) {
513 if ((status
= BS
->AllocatePool(EfiLoaderData
,
514 sizeof(*devinfo
), (void **)&devinfo
)) !=
516 DPRINTF("\nFailed to allocate devinfo (%lu)\n",
517 EFI_ERROR_CODE(status
));
520 devinfo
->dev
= blkio
;
521 devinfo
->devpath
= devpath
;
522 devinfo
->devhandle
= h
;
523 devinfo
->devdata
= NULL
;
524 devinfo
->preferred
= *preferred
;
525 devinfo
->next
= NULL
;
527 status
= boot_modules
[i
]->probe(devinfo
);
528 if (status
== EFI_SUCCESS
)
529 return (EFI_SUCCESS
);
530 (void)BS
->FreePool(devinfo
);
533 return (EFI_UNSUPPORTED
);
537 * probe_handle_status calls probe_handle and outputs the returned status
541 probe_handle_status(EFI_HANDLE h
, EFI_DEVICE_PATH
*imgpath
)
544 BOOLEAN preferred
= false;
546 status
= probe_handle(h
, imgpath
, &preferred
);
550 case EFI_UNSUPPORTED
:
552 DPRINTF(" not supported\n");
557 DPRINTF(" supported (preferred)\n");
560 DPRINTF(" supported\n");
565 DPRINTF(" error (%lu)\n", EFI_ERROR_CODE(status
));
572 efi_main(EFI_HANDLE Ximage
, EFI_SYSTEM_TABLE
*Xsystab
)
575 EFI_LOADED_IMAGE
*img
;
576 EFI_DEVICE_PATH
*imgpath
;
578 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
= NULL
;
579 SIMPLE_TEXT_OUTPUT_INTERFACE
*conout
= NULL
;
580 UINTN i
, max_dim
, best_mode
, cols
, rows
, hsize
, nhandles
;
582 /* Basic initialization*/
585 BS
= Xsystab
->BootServices
;
586 RS
= Xsystab
->RuntimeServices
;
588 /* Set up the console, so printf works. */
589 status
= BS
->LocateProtocol(&ConsoleControlGUID
, NULL
,
590 (VOID
**)&ConsoleControl
);
591 if (status
== EFI_SUCCESS
)
592 (void)ConsoleControl
->SetMode(ConsoleControl
,
593 EfiConsoleControlScreenText
);
595 * Reset the console and find the best text mode.
598 conout
->Reset(conout
, TRUE
);
599 max_dim
= best_mode
= 0;
601 status
= conout
->QueryMode(conout
, i
, &cols
, &rows
);
602 if (EFI_ERROR(status
))
604 if (cols
* rows
> max_dim
) {
605 max_dim
= cols
* rows
;
610 conout
->SetMode(conout
, best_mode
);
611 conout
->EnableCursor(conout
, TRUE
);
612 conout
->ClearScreen(conout
);
614 printf("\n>> illumos EFI boot block\n");
615 printf(" Loader path: %s\n\n", PATH_LOADER_EFI
);
616 printf(" Initializing modules:");
617 for (i
= 0; i
< NUM_BOOT_MODULES
; i
++) {
618 printf(" %s", boot_modules
[i
]->name
);
619 if (boot_modules
[i
]->init
!= NULL
)
620 boot_modules
[i
]->init();
624 /* Get all the device handles */
625 hsize
= (UINTN
)NUM_HANDLES_INIT
* sizeof(EFI_HANDLE
);
626 if ((status
= BS
->AllocatePool(EfiLoaderData
, hsize
, (void **)&handles
))
628 panic("Failed to allocate %d handles (%lu)", NUM_HANDLES_INIT
,
629 EFI_ERROR_CODE(status
));
631 status
= BS
->LocateHandle(ByProtocol
, &BlockIoProtocolGUID
, NULL
,
636 case EFI_BUFFER_TOO_SMALL
:
637 (void)BS
->FreePool(handles
);
638 if ((status
= BS
->AllocatePool(EfiLoaderData
, hsize
,
639 (void **)&handles
)) != EFI_SUCCESS
) {
640 panic("Failed to allocate %zu handles (%lu)", hsize
/
641 sizeof(*handles
), EFI_ERROR_CODE(status
));
643 status
= BS
->LocateHandle(ByProtocol
, &BlockIoProtocolGUID
,
644 NULL
, &hsize
, handles
);
645 if (status
!= EFI_SUCCESS
)
646 panic("Failed to get device handles (%lu)\n",
647 EFI_ERROR_CODE(status
));
650 panic("Failed to get device handles (%lu)",
651 EFI_ERROR_CODE(status
));
654 /* Scan all partitions, probing with all modules. */
655 nhandles
= hsize
/ sizeof(*handles
);
656 printf(" Probing %zu block devices...", nhandles
);
659 /* Determine the devpath of our image so we can prefer it. */
660 status
= BS
->HandleProtocol(IH
, &LoadedImageGUID
, (VOID
**)&img
);
662 if (status
== EFI_SUCCESS
) {
663 status
= BS
->HandleProtocol(img
->DeviceHandle
, &DevicePathGUID
,
665 if (status
!= EFI_SUCCESS
)
666 DPRINTF("Failed to get image DevicePath (%lu)\n",
667 EFI_ERROR_CODE(status
));
668 DPRINTF("boot1 imagepath: %s\n", devpath_str(imgpath
));
671 for (i
= 0; i
< nhandles
; i
++)
672 probe_handle_status(handles
[i
], imgpath
);
675 /* Status summary. */
676 for (i
= 0; i
< NUM_BOOT_MODULES
; i
++) {
678 boot_modules
[i
]->status();
683 /* If we get here, we're out of luck... */
684 panic("No bootable partitions found!");
688 * add_device adds a device to the passed devinfo list.
691 add_device(dev_info_t
**devinfop
, dev_info_t
*devinfo
)
695 if (*devinfop
== NULL
) {
700 for (dev
= *devinfop
; dev
->next
!= NULL
; dev
= dev
->next
)
707 panic(const char *fmt
, ...)
728 ST
->ConOut
->OutputString(ST
->ConOut
, buf
);
732 ST
->ConOut
->OutputString(ST
->ConOut
, buf
);
742 status
= ST
->ConIn
->ReadKeyStroke(ST
->ConIn
, &key
);
743 if (status
== EFI_NOT_READY
) {
744 BS
->WaitForEvent(1, &ST
->ConIn
->WaitForKey
, &junk
);
745 status
= ST
->ConIn
->ReadKeyStroke(ST
->ConIn
, &key
);
747 return (key
.UnicodeChar
);