Changeset View
Standalone View
sys/boot/efi/loader/main.c
Context not available. | |||||
#include <smbios.h> | #include <smbios.h> | ||||
#include "loader_efi.h" | #include "loader_efi.h" | ||||
#include "libzfs.h" | |||||
extern char bootprog_name[]; | extern char bootprog_name[]; | ||||
extern char bootprog_rev[]; | extern char bootprog_rev[]; | ||||
Context not available. | |||||
extern char bootprog_date[]; | extern char bootprog_date[]; | ||||
extern char bootprog_maker[]; | extern char bootprog_maker[]; | ||||
struct devdesc currdev; /* our current device */ | /* our current device */ | ||||
struct arch_switch archsw; /* MI/MD interface boundary */ | /* MI/MD interface boundary */ | ||||
struct arch_switch archsw; | |||||
EFI_GUID acpi = ACPI_TABLE_GUID; | EFI_GUID acpi = ACPI_TABLE_GUID; | ||||
EFI_GUID acpi20 = ACPI_20_TABLE_GUID; | EFI_GUID acpi20 = ACPI_20_TABLE_GUID; | ||||
Context not available. | |||||
EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID; | EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID; | ||||
EFI_GUID fdtdtb = FDT_TABLE_GUID; | EFI_GUID fdtdtb = FDT_TABLE_GUID; | ||||
static void efi_zfs_probe(void); | |||||
/* | |||||
delphij: Perhaps comment here that we didn't use printf("%s") because there are potential \0's, and we… | |||||
* Need this because EFI uses UTF-16 unicode string constants, but we | |||||
* use UTF-8. | |||||
*/ | |||||
static void | |||||
print_str16(const CHAR16 *str) | |||||
Not Done Inline ActionsI'd explicitly truncate str[i] to char here but consider this optional. delphij: I'd explicitly truncate str[i] to char here but consider this optional. | |||||
{ | |||||
int i; | |||||
for(i = 0; str[i]; i++) | |||||
delphijUnsubmitted Not Done Inline ActionsBlank line before this, space before (. delphij: Blank line before this, space before (. | |||||
{ | |||||
delphijUnsubmitted Not Done Inline Actions{ } should not be used here per style(9). delphij: { } should not be used here per style(9). | |||||
printf("%c", str[i]); | |||||
} | |||||
} | |||||
EFI_STATUS | EFI_STATUS | ||||
main(int argc, CHAR16 *argv[]) | main(int argc, CHAR16 *argv[]) | ||||
{ | { | ||||
Context not available. | |||||
EFI_GUID *guid; | EFI_GUID *guid; | ||||
int i; | int i; | ||||
archsw.arch_autoload = efi_autoload; | |||||
archsw.arch_getdev = efi_getdev; | |||||
archsw.arch_copyin = efi_copyin; | |||||
archsw.arch_copyout = efi_copyout; | |||||
archsw.arch_readin = efi_readin; | |||||
// Note this needs to be set before ZFS init | |||||
archsw.arch_zfs_probe = efi_zfs_probe; | |||||
/* | /* | ||||
* XXX Chicken-and-egg problem; we want to have console output | * XXX Chicken-and-egg problem; we want to have console output | ||||
* early, but some console attributes may depend on reading from | * early, but some console attributes may depend on reading from | ||||
Context not available. | |||||
* March through the device switch probing for things. | * March through the device switch probing for things. | ||||
*/ | */ | ||||
for (i = 0; devsw[i] != NULL; i++) | for (i = 0; devsw[i] != NULL; i++) | ||||
if (devsw[i]->dv_init != NULL) | if (devsw[i]->dv_init != NULL) | ||||
(devsw[i]->dv_init)(); | (devsw[i]->dv_init)(); | ||||
/* Get our loaded image protocol interface structure. */ | /* Get our loaded image protocol interface structure. */ | ||||
BS->HandleProtocol(IH, &imgid, (VOID**)&img); | BS->HandleProtocol(IH, &imgid, (VOID**)&img); | ||||
printf("Command line arguments:"); | |||||
for(i = 0; i < argc; i++) { | |||||
printf(" "); | |||||
print_str16(argv[i]); | |||||
} | |||||
printf("\n"); | |||||
printf("Image base: 0x%lx\n", (u_long)img->ImageBase); | printf("Image base: 0x%lx\n", (u_long)img->ImageBase); | ||||
printf("EFI version: %d.%02d\n", ST->Hdr.Revision >> 16, | printf("EFI version: %d.%02d\n", ST->Hdr.Revision >> 16, | ||||
ST->Hdr.Revision & 0xffff); | ST->Hdr.Revision & 0xffff); | ||||
Context not available. | |||||
printf("%s, Revision %s\n", bootprog_name, bootprog_rev); | printf("%s, Revision %s\n", bootprog_name, bootprog_rev); | ||||
printf("(%s, %s)\n", bootprog_maker, bootprog_date); | printf("(%s, %s)\n", bootprog_maker, bootprog_date); | ||||
efi_handle_lookup(img->DeviceHandle, &currdev.d_dev, &currdev.d_unit); | |||||
currdev.d_type = currdev.d_dev->dv_type; | |||||
/* | /* | ||||
* Disable the watchdog timer. By default the boot manager sets | * Disable the watchdog timer. By default the boot manager sets | ||||
* the timer to 5 minutes before invoking a boot option. If we | * the timer to 5 minutes before invoking a boot option. If we | ||||
Context not available. | |||||
*/ | */ | ||||
BS->SetWatchdogTimer(0, 0, 0, NULL); | BS->SetWatchdogTimer(0, 0, 0, NULL); | ||||
env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev), | struct devsw *dev; | ||||
efi_setcurrdev, env_nounset); | int unit; | ||||
env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset, | uint64_t pool_guid; | ||||
andrewUnsubmitted Not Done Inline ActionsThese should be at the top of the function andrew: These should be at the top of the function | |||||
env_nounset); | efi_handle_lookup(img->DeviceHandle, &dev, &unit, &pool_guid); | ||||
switch (dev->dv_type) { | |||||
case DEVT_ZFS: { | |||||
delphijUnsubmitted Not Done Inline Actions{ should not be used here. delphij: { should not be used here. | |||||
struct zfs_devdesc currdev; | |||||
currdev.d_dev = dev; | |||||
delphijUnsubmitted Not Done Inline ActionsBlank line. delphij: Blank line. | |||||
currdev.d_unit = unit; | |||||
currdev.d_type = currdev.d_dev->dv_type; | |||||
currdev.d_opendata = NULL; | |||||
currdev.pool_guid = pool_guid; | |||||
currdev.root_guid = 0; | |||||
env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev), | |||||
efi_setcurrdev, env_nounset); | |||||
env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset, | |||||
env_nounset); | |||||
} break; | |||||
delphijUnsubmitted Not Done Inline ActionsDon't use } here. delphij: Don't use } here. | |||||
default: { | |||||
delphijUnsubmitted Not Done Inline ActionsNo { here. Indent break;. delphij: No { here. Indent break;. | |||||
struct devdesc currdev; | |||||
currdev.d_dev = dev; | |||||
currdev.d_unit = unit; | |||||
currdev.d_opendata = NULL; | |||||
currdev.d_type = currdev.d_dev->dv_type; | |||||
env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev), | |||||
efi_setcurrdev, env_nounset); | |||||
env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset, | |||||
env_nounset); | |||||
} break; | |||||
delphijUnsubmitted Not Done Inline ActionsNo } here, indent break. delphij: No } here, indent break. | |||||
} | |||||
setenv("LINES", "24", 1); /* optional */ | setenv("LINES", "24", 1); /* optional */ | ||||
archsw.arch_autoload = efi_autoload; | |||||
archsw.arch_getdev = efi_getdev; | |||||
archsw.arch_copyin = efi_copyin; | |||||
archsw.arch_copyout = efi_copyout; | |||||
archsw.arch_readin = efi_readin; | |||||
for (i = 0; i < ST->NumberOfTableEntries; i++) { | for (i = 0; i < ST->NumberOfTableEntries; i++) { | ||||
guid = &ST->ConfigurationTable[i].VendorGuid; | guid = &ST->ConfigurationTable[i].VendorGuid; | ||||
if (!memcmp(guid, &smbios, sizeof(EFI_GUID))) { | if (!memcmp(guid, &smbios, sizeof(EFI_GUID))) { | ||||
Context not available. | |||||
return (CMD_OK); | return (CMD_OK); | ||||
} | } | ||||
COMMAND_SET(lszfs, "lszfs", "list child datasets of a zfs dataset", | |||||
command_lszfs); | |||||
static int | |||||
command_lszfs(int argc, char *argv[]) | |||||
{ | |||||
int err; | |||||
if (argc != 2) { | |||||
command_errmsg = "wrong number of arguments"; | |||||
return (CMD_ERROR); | |||||
} | |||||
err = zfs_list(argv[1]); | |||||
if (err != 0) { | |||||
command_errmsg = strerror(err); | |||||
return (CMD_ERROR); | |||||
} | |||||
return (CMD_OK); | |||||
} | |||||
#ifdef LOADER_FDT_SUPPORT | #ifdef LOADER_FDT_SUPPORT | ||||
extern int command_fdt_internal(int argc, char *argv[]); | extern int command_fdt_internal(int argc, char *argv[]); | ||||
Context not available. | |||||
COMMAND_SET(fdt, "fdt", "flattened device tree handling", command_fdt); | COMMAND_SET(fdt, "fdt", "flattened device tree handling", command_fdt); | ||||
#endif | #endif | ||||
static void | |||||
efi_zfs_probe(void) | |||||
{ | |||||
EFI_BLOCK_IO *blkio; | |||||
EFI_HANDLE h; | |||||
EFI_STATUS status; | |||||
u_int unit = 0; | |||||
char devname[32]; | |||||
uint64_t pool_guid; | |||||
for (int i = 0, h = efi_find_handle(&efipart_dev, 0); | |||||
h != NULL; h = efi_find_handle(&efipart_dev, ++i)) { | |||||
andrewUnsubmitted Not Done Inline ActionsThere is a style bug here, the int i declaration should be in the group above. There is a second subtle issue. You are redefining h to be an int. efi_find_handle returns an EFI_HANDLE, aka a void *. On a 64-bit machine this will truncate the pointer. When used later it will be sign extended. This is an issue if the handle has bit 31 set (as is the case on my laptop) as the handle will have the top 32 bits set incorrectly. It would also be an issue if any of the top bits were used in the handle. The fix for this is the same as the style issue. andrew: There is a style bug here, the `int i` declaration should be in the group above.
There is a… | |||||
snprintf(devname, sizeof devname, "%s%d:", | |||||
efipart_dev.dv_name, i); | |||||
if(0 == zfs_probe_dev(devname, &pool_guid)) { | |||||
andrewUnsubmitted Not Done Inline Actionsif (zfs_probe_dev(..) == 0) { andrew: `if (zfs_probe_dev(..) == 0) {` | |||||
efi_handle_update_dev(h, &zfs_dev, unit++, pool_guid); | |||||
} | |||||
} | |||||
} | |||||
Context not available. |
Perhaps comment here that we didn't use printf("%s") because there are potential \0's, and we don't support real wide character either?