2 * Copyright (c) 2008-2010 Rui Paulo
3 * Copyright (c) 2006 Marcel Moolenaar
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
28 #include <sys/cdefs.h>
31 #include <sys/param.h>
32 #include <sys/reboot.h>
46 #include <bootstrap.h>
53 #include "loader_efi.h"
55 extern char bootprog_info
[];
57 struct arch_switch archsw
; /* MI/MD interface boundary */
59 EFI_GUID devid
= DEVICE_PATH_PROTOCOL
;
60 EFI_GUID imgid
= LOADED_IMAGE_PROTOCOL
;
61 EFI_GUID smbios
= SMBIOS_TABLE_GUID
;
62 EFI_GUID smbios3
= SMBIOS3_TABLE_GUID
;
63 EFI_GUID inputid
= SIMPLE_TEXT_INPUT_PROTOCOL
;
65 extern void acpi_detect(void);
66 extern void efi_getsmap(void);
68 static void efi_zfs_probe(void);
69 static uint64_t pool_guid
;
76 EFI_DEVICE_PATH
*path
;
77 EFI_HANDLE
*hin
, *hin_end
, *walker
;
82 * Find all the handles that support the SIMPLE_TEXT_INPUT_PROTOCOL and
83 * do the typical dance to get the right sized buffer.
87 status
= BS
->LocateHandle(ByProtocol
, &inputid
, 0, &sz
, 0);
88 if (status
== EFI_BUFFER_TOO_SMALL
) {
89 hin
= (EFI_HANDLE
*)malloc(sz
);
90 status
= BS
->LocateHandle(ByProtocol
, &inputid
, 0, &sz
,
92 if (EFI_ERROR(status
))
95 if (EFI_ERROR(status
))
99 * Look at each of the handles. If it supports the device path protocol,
100 * use it to get the device path for this handle. Then see if that
101 * device path matches either the USB device path for keyboards or the
102 * legacy device path for keyboards.
104 hin_end
= &hin
[sz
/ sizeof(*hin
)];
105 for (walker
= hin
; walker
< hin_end
; walker
++) {
106 status
= BS
->HandleProtocol(*walker
, &devid
, (VOID
**)&path
);
107 if (EFI_ERROR(status
))
110 while (!IsDevicePathEnd(path
)) {
112 * Check for the ACPI keyboard node. All PNP3xx nodes
113 * are keyboards of different flavors. Note: It is
114 * unclear of there's always a keyboard node when
115 * there's a keyboard controller, or if there's only one
116 * when a keyboard is detected at boot.
118 if (DevicePathType(path
) == ACPI_DEVICE_PATH
&&
119 (DevicePathSubType(path
) == ACPI_DP
||
120 DevicePathSubType(path
) == ACPI_EXTENDED_DP
)) {
121 ACPI_HID_DEVICE_PATH
*acpi
;
123 acpi
= (ACPI_HID_DEVICE_PATH
*)(void *)path
;
124 if ((EISA_ID_TO_NUM(acpi
->HID
) & 0xff00) == 0x300 &&
125 (acpi
->HID
& 0xffff) == PNP_EISA_ID_CONST
) {
130 * Check for USB keyboard node, if present. Unlike a
131 * PS/2 keyboard, these definitely only appear when
132 * connected to the system.
134 } else if (DevicePathType(path
) == MESSAGING_DEVICE_PATH
&&
135 DevicePathSubType(path
) == MSG_USB_CLASS_DP
) {
136 USB_CLASS_DEVICE_PATH
*usb
;
138 usb
= (USB_CLASS_DEVICE_PATH
*)(void *)path
;
139 if (usb
->DeviceClass
== 3 && /* HID */
140 usb
->DeviceSubClass
== 1 && /* Boot devices */
141 usb
->DeviceProtocol
== 1) { /* Boot keyboards */
146 path
= NextDevicePathNode(path
);
155 set_devdesc_currdev(struct devsw
*dev
, int unit
)
157 struct devdesc currdev
;
161 currdev
.d_type
= currdev
.d_dev
->dv_type
;
162 currdev
.d_unit
= unit
;
163 currdev
.d_opendata
= NULL
;
164 devname
= efi_fmtdev(&currdev
);
166 env_setenv("currdev", EV_VOLATILE
, devname
, efi_setcurrdev
,
168 env_setenv("loaddev", EV_VOLATILE
, devname
, env_noset
, env_nounset
);
172 find_currdev(EFI_LOADED_IMAGE
*img
)
174 pdinfo_list_t
*pdi_list
;
176 EFI_DEVICE_PATH
*devpath
, *copy
;
183 /* Did efi_zfs_probe() detect the boot pool? */
184 if (pool_guid
!= 0) {
185 struct zfs_devdesc currdev
;
187 currdev
.d_dev
= &zfs_dev
;
189 currdev
.d_type
= currdev
.d_dev
->dv_type
;
190 currdev
.d_opendata
= NULL
;
191 currdev
.pool_guid
= pool_guid
;
192 currdev
.root_guid
= 0;
193 devname
= efi_fmtdev(&currdev
);
195 env_setenv("currdev", EV_VOLATILE
, devname
, efi_setcurrdev
,
197 env_setenv("loaddev", EV_VOLATILE
, devname
, env_noset
,
202 /* We have device lists for hd, cd, fd, walk them all. */
203 pdi_list
= efiblk_get_pdinfo_list(&efipart_hddev
);
204 STAILQ_FOREACH(dp
, pdi_list
, pd_link
) {
205 struct disk_devdesc currdev
;
207 currdev
.d_dev
= &efipart_hddev
;
208 currdev
.d_type
= currdev
.d_dev
->dv_type
;
209 currdev
.d_unit
= dp
->pd_unit
;
210 currdev
.d_opendata
= NULL
;
211 currdev
.d_slice
= -1;
212 currdev
.d_partition
= -1;
214 if (dp
->pd_handle
== img
->DeviceHandle
) {
215 devname
= efi_fmtdev(&currdev
);
217 env_setenv("currdev", EV_VOLATILE
, devname
,
218 efi_setcurrdev
, env_nounset
);
219 env_setenv("loaddev", EV_VOLATILE
, devname
,
220 env_noset
, env_nounset
);
223 /* Assuming GPT partitioning. */
224 STAILQ_FOREACH(pp
, &dp
->pd_part
, pd_link
) {
225 if (pp
->pd_handle
== img
->DeviceHandle
) {
226 currdev
.d_slice
= pp
->pd_unit
;
227 currdev
.d_partition
= 255;
228 devname
= efi_fmtdev(&currdev
);
230 env_setenv("currdev", EV_VOLATILE
, devname
,
231 efi_setcurrdev
, env_nounset
);
232 env_setenv("loaddev", EV_VOLATILE
, devname
,
233 env_noset
, env_nounset
);
239 pdi_list
= efiblk_get_pdinfo_list(&efipart_cddev
);
240 STAILQ_FOREACH(dp
, pdi_list
, pd_link
) {
241 if (dp
->pd_handle
== img
->DeviceHandle
||
242 dp
->pd_alias
== img
->DeviceHandle
) {
243 set_devdesc_currdev(&efipart_cddev
, dp
->pd_unit
);
248 pdi_list
= efiblk_get_pdinfo_list(&efipart_fddev
);
249 STAILQ_FOREACH(dp
, pdi_list
, pd_link
) {
250 if (dp
->pd_handle
== img
->DeviceHandle
) {
251 set_devdesc_currdev(&efipart_fddev
, dp
->pd_unit
);
257 * Try the device handle from our loaded image first. If that
258 * fails, use the device path from the loaded image and see if
259 * any of the nodes in that path match one of the enumerated
262 if (efi_handle_lookup(img
->DeviceHandle
, &dev
, &unit
, &extra
) == 0) {
263 set_devdesc_currdev(dev
, unit
);
268 devpath
= efi_lookup_image_devpath(IH
);
269 while (devpath
!= NULL
) {
270 h
= efi_devpath_handle(devpath
);
277 if (efi_handle_lookup(h
, &dev
, &unit
, &extra
) == 0) {
278 set_devdesc_currdev(dev
, unit
);
282 devpath
= efi_lookup_devpath(h
);
283 if (devpath
!= NULL
) {
284 copy
= efi_devpath_trim(devpath
);
294 main(int argc
, CHAR16
*argv
[])
297 EFI_LOADED_IMAGE
*img
;
299 int i
, j
, vargood
, howto
;
304 archsw
.arch_autoload
= efi_autoload
;
305 archsw
.arch_getdev
= efi_getdev
;
306 archsw
.arch_copyin
= efi_copyin
;
307 archsw
.arch_copyout
= efi_copyout
;
308 archsw
.arch_readin
= efi_readin
;
309 archsw
.arch_loadaddr
= efi_loadaddr
;
310 archsw
.arch_free_loadaddr
= efi_free_loadaddr
;
312 /* Note this needs to be set before ZFS init. */
313 archsw
.arch_zfs_probe
= efi_zfs_probe
;
316 /* Init the time source */
319 has_kbd
= has_keyboard();
322 * XXX Chicken-and-egg problem; we want to have console output
323 * early, but some console attributes may depend on reading from
324 * eg. the boot device, which we can't do yet. We can use
325 * printf() etc. once this is done.
331 * Initialise the block cache. Set the upper limit.
333 bcache_init(32768, 512);
336 * Parse the args to set the console settings, etc
337 * boot1.efi passes these in, if it can read /boot.config or /boot/config
338 * or iPXE may be setup to pass these in.
340 * Loop through the args, and for each one that contains an '=' that is
341 * not the first character, add it to the environment. This allows
342 * loader and kernel env vars to be passed on the command line. Convert
343 * args from UCS-2 to ASCII (16 to 8 bit) as they are copied.
346 for (i
= 1; i
< argc
; i
++) {
347 if (argv
[i
][0] == '-') {
348 for (j
= 1; argv
[i
][j
] != 0; j
++) {
360 howto
|= RB_MULTIPLE
;
373 howto
|= RB_SERIAL
| RB_MULTIPLE
;
376 howto
|= RB_DFLTROOT
;
382 if (argv
[i
][j
+ 1] == 0) {
384 setenv("comconsole_speed", "115200", 1);
386 cpy16to8(&argv
[i
+ 1][0], var
,
388 setenv("comconsole_speedspeed", var
, 1);
393 cpy16to8(&argv
[i
][j
+ 1], var
,
395 setenv("comconsole_speed", var
, 1);
405 for (j
= 0; argv
[i
][j
] != 0; j
++) {
406 if (j
== sizeof(var
)) {
410 if (j
> 0 && argv
[i
][j
] == '=')
412 var
[j
] = (char)argv
[i
][j
];
420 for (i
= 0; howto_names
[i
].ev
!= NULL
; i
++)
421 if (howto
& howto_names
[i
].mask
)
422 setenv(howto_names
[i
].ev
, "YES", 1);
423 if (howto
& RB_MULTIPLE
) {
424 if (howto
& RB_SERIAL
)
425 setenv("console", "ttya text" , 1);
427 setenv("console", "text ttya" , 1);
428 } else if (howto
& RB_SERIAL
) {
429 setenv("console", "ttya" , 1);
433 * March through the device switch probing for things.
435 for (i
= 0; devsw
[i
] != NULL
; i
++)
436 if (devsw
[i
]->dv_init
!= NULL
)
437 (devsw
[i
]->dv_init
)();
439 /* Get our loaded image protocol interface structure. */
440 BS
->HandleProtocol(IH
, &imgid
, (VOID
**)&img
);
442 printf("Command line arguments:");
443 for (i
= 0; i
< argc
; i
++) {
444 printf(" %S", argv
[i
]);
448 printf("Image base: 0x%lx\n", (u_long
)img
->ImageBase
);
449 printf("EFI version: %d.%02d\n", ST
->Hdr
.Revision
>> 16,
450 ST
->Hdr
.Revision
& 0xffff);
451 printf("EFI Firmware: %S (rev %d.%02d)\n", ST
->FirmwareVendor
,
452 ST
->FirmwareRevision
>> 16, ST
->FirmwareRevision
& 0xffff);
454 printf("\n%s", bootprog_info
);
457 * Disable the watchdog timer. By default the boot manager sets
458 * the timer to 5 minutes before invoking a boot option. If we
459 * want to return to the boot manager, we have to disable the
460 * watchdog timer and since we're an interactive program, we don't
461 * want to wait until the user types "quit". The timer may have
462 * fired by then. We don't care if this fails. It does not prevent
463 * normal functioning in any way...
465 BS
->SetWatchdogTimer(0, 0, 0, NULL
);
467 if (find_currdev(img
) != 0)
468 return (EFI_NOT_FOUND
);
470 efi_init_environment();
471 setenv("ISADIR", "amd64", 1); /* we only build 64bit */
474 if ((ptr
= efi_get_table(&smbios3
)) == NULL
)
475 ptr
= efi_get_table(&smbios
);
478 interact(NULL
); /* doesn't return */
480 return (EFI_SUCCESS
); /* keep compiler happy */
483 COMMAND_SET(reboot
, "reboot", "reboot the system", command_reboot
);
486 command_reboot(int argc __unused
, char *argv
[] __unused
)
490 for (i
= 0; devsw
[i
] != NULL
; ++i
)
491 if (devsw
[i
]->dv_cleanup
!= NULL
)
492 (devsw
[i
]->dv_cleanup
)();
494 RS
->ResetSystem(EfiResetCold
, EFI_SUCCESS
, 0, NULL
);
500 COMMAND_SET(memmap
, "memmap", "print memory map", command_memmap
);
503 command_memmap(int argc __unused
, char *argv
[] __unused
)
506 EFI_MEMORY_DESCRIPTOR
*map
, *p
;
515 status
= BS
->GetMemoryMap(&sz
, 0, &key
, &dsz
, &dver
);
516 if (status
!= EFI_BUFFER_TOO_SMALL
) {
517 printf("Can't determine memory map size\n");
521 status
= BS
->GetMemoryMap(&sz
, map
, &key
, &dsz
, &dver
);
522 if (EFI_ERROR(status
)) {
523 printf("Can't read memory map\n");
528 snprintf(line
, 80, "%23s %12s %12s %8s %4s\n",
529 "Type", "Physical", "Virtual", "#Pages", "Attr");
531 rv
= pager_output(line
);
537 for (i
= 0, p
= map
; i
< ndesc
;
538 i
++, p
= NextMemoryDescriptor(p
, dsz
)) {
539 snprintf(line
, 80, "%23s %012lx %012lx %08lx ",
540 efi_memory_type(p
->Type
),
544 rv
= pager_output(line
);
548 if (p
->Attribute
& EFI_MEMORY_UC
)
550 if (p
->Attribute
& EFI_MEMORY_WC
)
552 if (p
->Attribute
& EFI_MEMORY_WT
)
554 if (p
->Attribute
& EFI_MEMORY_WB
)
556 if (p
->Attribute
& EFI_MEMORY_UCE
)
558 if (p
->Attribute
& EFI_MEMORY_WP
)
560 if (p
->Attribute
& EFI_MEMORY_RP
)
562 if (p
->Attribute
& EFI_MEMORY_XP
)
564 if (p
->Attribute
& EFI_MEMORY_NV
)
566 if (p
->Attribute
& EFI_MEMORY_MORE_RELIABLE
)
568 if (p
->Attribute
& EFI_MEMORY_RO
)
570 rv
= pager_output("\n");
579 COMMAND_SET(configuration
, "configuration", "print configuration tables",
580 command_configuration
);
583 command_configuration(int argc __unused
, char *argv
[] __unused
)
588 printf("NumberOfTableEntries=%lu\n",
589 (unsigned long)ST
->NumberOfTableEntries
);
590 for (i
= 0; i
< ST
->NumberOfTableEntries
; i
++) {
594 guid
= &ST
->ConfigurationTable
[i
].VendorGuid
;
596 if (efi_guid_to_name(guid
, &name
) == true) {
600 printf("Error while translating UUID to name");
602 printf(" at %p\n", ST
->ConfigurationTable
[i
].VendorTable
);
609 COMMAND_SET(mode
, "mode", "change or display EFI text modes", command_mode
);
612 command_mode(int argc
, char *argv
[])
620 SIMPLE_TEXT_OUTPUT_INTERFACE
*conout
;
621 extern void HO(void);
626 mode
= strtol(argv
[1], &cp
, 0);
628 printf("Invalid mode\n");
631 status
= conout
->QueryMode(conout
, mode
, &cols
, &rows
);
632 if (EFI_ERROR(status
)) {
633 printf("invalid mode %d\n", mode
);
636 status
= conout
->SetMode(conout
, mode
);
637 if (EFI_ERROR(status
)) {
638 printf("couldn't set mode %d\n", mode
);
641 sprintf(rowenv
, "%u", (unsigned)rows
);
642 setenv("LINES", rowenv
, 1);
643 sprintf(rowenv
, "%u", (unsigned)cols
);
644 setenv("COLUMNS", rowenv
, 1);
645 HO(); /* set cursor */
649 printf("Current mode: %d\n", conout
->Mode
->Mode
);
650 for (i
= 0; i
<= conout
->Mode
->MaxMode
; i
++) {
651 status
= conout
->QueryMode(conout
, i
, &cols
, &rows
);
652 if (EFI_ERROR(status
))
654 printf("Mode %d: %u columns, %u rows\n", i
, (unsigned)cols
,
659 printf("Select a mode with the command \"mode <number>\"\n");
664 COMMAND_SET(lsefi
, "lsefi", "list EFI handles", command_lsefi
);
667 command_lsefi(int argc __unused
, char *argv
[] __unused
)
670 EFI_HANDLE
*buffer
= NULL
;
672 UINTN bufsz
= 0, i
, j
;
676 status
= BS
->LocateHandle(AllHandles
, NULL
, NULL
, &bufsz
, buffer
);
677 if (status
!= EFI_BUFFER_TOO_SMALL
) {
678 snprintf(command_errbuf
, sizeof (command_errbuf
),
679 "unexpected error: %lld", (long long)status
);
682 if ((buffer
= malloc(bufsz
)) == NULL
) {
683 sprintf(command_errbuf
, "out of memory");
687 status
= BS
->LocateHandle(AllHandles
, NULL
, NULL
, &bufsz
, buffer
);
688 if (EFI_ERROR(status
)) {
690 snprintf(command_errbuf
, sizeof (command_errbuf
),
691 "LocateHandle() error: %lld", (long long)status
);
696 for (i
= 0; i
< (bufsz
/ sizeof (EFI_HANDLE
)); i
++) {
698 EFI_GUID
**protocols
= NULL
;
701 printf("Handle %p", handle
);
702 if (pager_output("\n"))
706 status
= BS
->ProtocolsPerHandle(handle
, &protocols
, &nproto
);
707 if (EFI_ERROR(status
)) {
708 snprintf(command_errbuf
, sizeof (command_errbuf
),
709 "ProtocolsPerHandle() error: %lld",
714 for (j
= 0; j
< nproto
; j
++) {
715 if (efi_guid_to_name(protocols
[j
], &name
) == true) {
719 printf("Error while translating UUID to name");
721 if ((ret
= pager_output("\n")) != 0)
724 BS
->FreePool(protocols
);
733 COMMAND_SET(lszfs
, "lszfs", "list child datasets of a zfs dataset",
737 command_lszfs(int argc
, char *argv
[])
742 command_errmsg
= "wrong number of arguments";
746 err
= zfs_list(argv
[1]);
748 command_errmsg
= strerror(err
);
755 COMMAND_SET(reloadbe
, "reloadbe", "refresh the list of ZFS Boot Environments",
759 command_reloadbe(int argc
, char *argv
[])
765 command_errmsg
= "wrong number of arguments";
770 err
= zfs_bootenv(argv
[1]);
772 root
= getenv("zfs_be_root");
776 err
= zfs_bootenv(root
);
780 command_errmsg
= strerror(err
);
786 #endif /* __FreeBSD__ */
788 #ifdef LOADER_FDT_SUPPORT
789 extern int command_fdt_internal(int argc
, char *argv
[]);
792 * Since proper fdt command handling function is defined in fdt_loader_cmd.c,
793 * and declaring it as extern is in contradiction with COMMAND_SET() macro
794 * (which uses static pointer), we're defining wrapper function, which
795 * calls the proper fdt handling routine.
798 command_fdt(int argc
, char *argv
[])
800 return (command_fdt_internal(argc
, argv
));
803 COMMAND_SET(fdt
, "fdt", "flattened device tree handling", command_fdt
);
807 * Chain load another efi loader.
810 command_chain(int argc
, char *argv
[])
812 EFI_GUID LoadedImageGUID
= LOADED_IMAGE_PROTOCOL
;
813 EFI_HANDLE loaderhandle
;
814 EFI_LOADED_IMAGE
*loaded_image
;
823 command_errmsg
= "wrong number of arguments";
829 if ((fd
= open(name
, O_RDONLY
)) < 0) {
830 command_errmsg
= "no such file";
834 if (fstat(fd
, &st
) < -1) {
835 command_errmsg
= "stat failed";
840 status
= BS
->AllocatePool(EfiLoaderCode
, (UINTN
)st
.st_size
, &buf
);
841 if (status
!= EFI_SUCCESS
) {
842 command_errmsg
= "failed to allocate buffer";
846 if (read(fd
, buf
, st
.st_size
) != st
.st_size
) {
847 command_errmsg
= "error while reading the file";
848 (void)BS
->FreePool(buf
);
853 status
= BS
->LoadImage(FALSE
, IH
, NULL
, buf
, st
.st_size
, &loaderhandle
);
854 (void)BS
->FreePool(buf
);
855 if (status
!= EFI_SUCCESS
) {
856 command_errmsg
= "LoadImage failed";
859 status
= BS
->HandleProtocol(loaderhandle
, &LoadedImageGUID
,
860 (void **)&loaded_image
);
866 for (i
= 2; i
< argc
; i
++)
867 len
+= strlen(argv
[i
]) + 1;
869 len
*= sizeof (*argp
);
870 loaded_image
->LoadOptions
= argp
= malloc (len
);
871 if (loaded_image
->LoadOptions
== NULL
) {
872 (void) BS
->UnloadImage(loaded_image
);
875 loaded_image
->LoadOptionsSize
= len
;
876 for (i
= 2; i
< argc
; i
++) {
879 *(argp
++) = *(ptr
++);
885 if (efi_getdev((void **)&dev
, name
, (const char **)&path
) == 0)
886 loaded_image
->DeviceHandle
=
887 efi_find_handle(dev
->d_dev
, dev
->d_unit
);
890 status
= BS
->StartImage(loaderhandle
, NULL
, NULL
);
891 if (status
!= EFI_SUCCESS
) {
892 command_errmsg
= "StartImage failed";
893 free(loaded_image
->LoadOptions
);
894 loaded_image
->LoadOptions
= NULL
;
895 status
= BS
->UnloadImage(loaded_image
);
899 return (CMD_ERROR
); /* not reached */
902 COMMAND_SET(chain
, "chain", "chain load file", command_chain
);
909 pdinfo_t
*hd
, *pd
= NULL
;
910 EFI_GUID imgid
= LOADED_IMAGE_PROTOCOL
;
911 EFI_LOADED_IMAGE
*img
;
912 char devname
[SPECNAMELEN
+ 1];
914 BS
->HandleProtocol(IH
, &imgid
, (VOID
**)&img
);
915 hdi
= efiblk_get_pdinfo_list(&efipart_hddev
);
918 * Find the handle for the boot device. The boot1 did find the
919 * device with loader binary, now we need to search for the
920 * same device and if it is part of the zfs pool, we record the
921 * pool GUID for currdev setup.
923 STAILQ_FOREACH(hd
, hdi
, pd_link
) {
924 STAILQ_FOREACH(pd
, &hd
->pd_part
, pd_link
) {
926 snprintf(devname
, sizeof(devname
), "%s%dp%d:",
927 efipart_hddev
.dv_name
, hd
->pd_unit
, pd
->pd_unit
);
928 if (pd
->pd_handle
== img
->DeviceHandle
)
929 (void) zfs_probe_dev(devname
, &pool_guid
);
931 (void) zfs_probe_dev(devname
, NULL
);
937 ldi_get_size(void *priv
)
939 int fd
= (uintptr_t) priv
;
942 ioctl(fd
, DIOCGMEDIASIZE
, &size
);