7846 loader: UEFI variable support development
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Dan McDonald <danmcd@joyent.com>
diff --git a/usr/src/boot/sys/boot/efi/loader/main.c b/usr/src/boot/sys/boot/efi/loader/main.c
index cf689b8..22fd9e9 100644
--- a/usr/src/boot/sys/boot/efi/loader/main.c
+++ b/usr/src/boot/sys/boot/efi/loader/main.c
@@ -32,6 +32,7 @@
#include <sys/reboot.h>
#include <sys/boot.h>
#include <stand.h>
+#include <inttypes.h>
#include <string.h>
#include <setjmp.h>
@@ -39,6 +40,9 @@
#include <efilib.h>
#include <efigpt.h>
+#include <uuid.h>
+#include <stdbool.h>
+
#include <bootstrap.h>
#include <smbios.h>
@@ -52,19 +56,10 @@
struct arch_switch archsw; /* MI/MD interface boundary */
-EFI_GUID acpi = ACPI_TABLE_GUID;
-EFI_GUID acpi20 = ACPI_20_TABLE_GUID;
EFI_GUID devid = DEVICE_PATH_PROTOCOL;
EFI_GUID imgid = LOADED_IMAGE_PROTOCOL;
-EFI_GUID mps = MPS_TABLE_GUID;
-EFI_GUID netid = EFI_SIMPLE_NETWORK_PROTOCOL;
EFI_GUID smbios = SMBIOS_TABLE_GUID;
EFI_GUID smbios3 = SMBIOS3_TABLE_GUID;
-EFI_GUID dxe = DXE_SERVICES_TABLE_GUID;
-EFI_GUID hoblist = HOB_LIST_TABLE_GUID;
-EFI_GUID memtype = MEMORY_TYPE_INFORMATION_TABLE_GUID;
-EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID;
-EFI_GUID fdtdtb = FDT_TABLE_GUID;
EFI_GUID inputid = SIMPLE_TEXT_INPUT_PROTOCOL;
EFI_GUID serial_io = SERIAL_IO_PROTOCOL;
@@ -74,29 +69,6 @@
static void efi_zfs_probe(void);
#endif
-/*
- * Need this because EFI uses UTF-16 unicode string constants, but we
- * use UTF-8. We can't use printf due to the possibility of \0 and we
- * don't support wide characters either.
- */
-static void
-print_str16(const CHAR16 *str)
-{
- int i;
-
- for (i = 0; str[i]; i++)
- printf("%c", (char)str[i]);
-}
-
-static void
-cp16to8(const CHAR16 *src, char *dst, size_t len)
-{
- size_t i;
-
- for (i = 0; i < len && src[i]; i++)
- dst[i] = (char)src[i];
-}
-
static int
has_keyboard(void)
{
@@ -311,14 +283,14 @@
if (i + 1 == argc) {
setenv("comconsole_speed", "115200", 1);
} else {
- cp16to8(&argv[i + 1][0], var,
+ cpy16to8(&argv[i + 1][0], var,
sizeof(var));
setenv("comconsole_speedspeed", var, 1);
}
i++;
break;
} else {
- cp16to8(&argv[i][j + 1], var,
+ cpy16to8(&argv[i][j + 1], var,
sizeof(var));
setenv("comconsole_speed", var, 1);
break;
@@ -374,19 +346,15 @@
printf("Command line arguments:");
for (i = 0; i < argc; i++) {
- printf(" ");
- print_str16(argv[i]);
+ printf(" %S", argv[i]);
}
printf("\n");
printf("Image base: 0x%lx\n", (u_long)img->ImageBase);
printf("EFI version: %d.%02d\n", ST->Hdr.Revision >> 16,
ST->Hdr.Revision & 0xffff);
- printf("EFI Firmware: ");
- /* printf doesn't understand EFI Unicode */
- ST->ConOut->OutputString(ST->ConOut, ST->FirmwareVendor);
- printf(" (rev %d.%02d)\n", ST->FirmwareRevision >> 16,
- ST->FirmwareRevision & 0xffff);
+ printf("EFI Firmware: %S (rev %d.%02d)\n", ST->FirmwareVendor,
+ ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
printf("\n%s", bootprog_info);
@@ -440,6 +408,7 @@
}
}
+ efi_init_environment();
setenv("LINES", "24", 1); /* optional */
setenv("COLUMNS", "80", 1); /* optional */
setenv("ISADIR", "amd64", 1); /* we only build 64bit */
@@ -487,22 +456,6 @@
int i, ndesc;
int rv = 0;
char line[80];
- static const char *types[] = {
- "Reserved",
- "LoaderCode",
- "LoaderData",
- "BootServicesCode",
- "BootServicesData",
- "RuntimeServicesCode",
- "RuntimeServicesData",
- "ConventionalMemory",
- "UnusableMemory",
- "ACPIReclaimMemory",
- "ACPIMemoryNVS",
- "MemoryMappedIO",
- "MemoryMappedIOPortSpace",
- "PalCode"
- };
sz = 0;
status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
@@ -530,7 +483,7 @@
for (i = 0, p = map; i < ndesc;
i++, p = NextMemoryDescriptor(p, dsz)) {
snprintf(line, 80, "%23s %012lx %012lx %08lx ",
- types[p->Type],
+ efi_memory_type(p->Type),
p->PhysicalStart,
p->VirtualStart,
p->NumberOfPages);
@@ -554,6 +507,12 @@
printf("RP ");
if (p->Attribute & EFI_MEMORY_XP)
printf("XP ");
+ if (p->Attribute & EFI_MEMORY_NV)
+ printf("NV ");
+ if (p->Attribute & EFI_MEMORY_MORE_RELIABLE)
+ printf("MR ");
+ if (p->Attribute & EFI_MEMORY_RO)
+ printf("RO ");
rv = pager_output("\n");
if (rv)
break;
@@ -566,23 +525,12 @@
COMMAND_SET(configuration, "configuration", "print configuration tables",
command_configuration);
-static const char *
-guid_to_string(EFI_GUID *guid)
-{
- static char buf[40];
-
- sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],
- guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],
- guid->Data4[5], guid->Data4[6], guid->Data4[7]);
- return (buf);
-}
-
static int
command_configuration(int argc __attribute((unused)),
char *argv[] __attribute((unused)))
{
UINTN i;
+ char *name;
printf("NumberOfTableEntries=%lu\n",
(unsigned long)ST->NumberOfTableEntries);
@@ -591,28 +539,13 @@
printf(" ");
guid = &ST->ConfigurationTable[i].VendorGuid;
- if (!memcmp(guid, &mps, sizeof(EFI_GUID)))
- printf("MPS Table");
- else if (!memcmp(guid, &acpi, sizeof(EFI_GUID)))
- printf("ACPI Table");
- else if (!memcmp(guid, &acpi20, sizeof(EFI_GUID)))
- printf("ACPI 2.0 Table");
- else if (!memcmp(guid, &smbios, sizeof(EFI_GUID)))
- printf("SMBIOS Table");
- else if (!memcmp(guid, &smbios3, sizeof(EFI_GUID)))
- printf("SMBIOS3 Table");
- else if (!memcmp(guid, &dxe, sizeof(EFI_GUID)))
- printf("DXE Table");
- else if (!memcmp(guid, &hoblist, sizeof(EFI_GUID)))
- printf("HOB List Table");
- else if (!memcmp(guid, &memtype, sizeof(EFI_GUID)))
- printf("Memory Type Information Table");
- else if (!memcmp(guid, &debugimg, sizeof(EFI_GUID)))
- printf("Debug Image Info Table");
- else if (!memcmp(guid, &fdtdtb, sizeof(EFI_GUID)))
- printf("FDT Table");
- else
- printf("Unknown Table (%s)", guid_to_string(guid));
+
+ if (efi_guid_to_name(guid, &name) == true) {
+ printf(name);
+ free(name);
+ } else {
+ printf("Error while translating UUID to name");
+ }
printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
}
@@ -675,209 +608,18 @@
return (CMD_OK);
}
-
-COMMAND_SET(nvram, "nvram", "get NVRAM variables", command_nvram);
-
-static int
-command_nvram(int argc __attribute((unused)),
- char *argv[] __attribute((unused)))
-{
- CHAR16 var[128];
- UINT8 *data; /* value is in bytes */
- EFI_STATUS status;
- EFI_GUID varguid = { 0,0,0,{0,0,0,0,0,0,0,0} };
- UINTN varsz, datasz, i;
- UINT32 attr;
- SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
-
- conout = ST->ConOut;
-
- pager_open();
- var[0] = 0; /* Initiate the enumeration */
- varsz = 128;
-
- for (status = RS->GetNextVariableName(&varsz, var, &varguid);
- status != EFI_NOT_FOUND;
- status = RS->GetNextVariableName(&varsz, var, &varguid)) {
-
- /*
- * as term emu is keeping track on cursor, use putchar().
- */
- for (i = 0; var[i] != 0; i++)
- putchar(var[i]);
- varsz = 128; /* GetNextVariableName() did change it. */
-
- printf(": Attributes:");
- datasz = 0;
- status = RS->GetVariable(var, &varguid, &attr, &datasz, NULL);
- if ((data = malloc(datasz)) == NULL)
- break;
- status = RS->GetVariable(var, &varguid, &attr, &datasz, data);
- if (EFI_ERROR(status))
- printf("<error retrieving variable>");
- else {
- if (attr & EFI_VARIABLE_NON_VOLATILE)
- printf(" NV");
- if (attr & EFI_VARIABLE_BOOTSERVICE_ACCESS)
- printf(" BS");
- if (attr & EFI_VARIABLE_RUNTIME_ACCESS)
- printf(" RS");
- if (attr & EFI_VARIABLE_HARDWARE_ERROR_RECORD)
- printf(" HR");
- if (attr & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)
- printf(" AW");
- if (attr &
- EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
- printf(" TW");
-
- printf(": DataLength: %lld", (long long)datasz);
- }
- free(data);
- if (pager_output("\n"))
- break;
- }
-
- pager_close();
- return (CMD_OK);
-}
-
-struct protocol_name {
- EFI_GUID guid;
- const char *name;
-} proto_names[] = {
- { DEVICE_PATH_PROTOCOL, "device path" },
- { BLOCK_IO_PROTOCOL, "block io" },
- { DISK_IO_PROTOCOL, "disk io" },
- { EFI_DISK_INFO_PROTOCOL_GUID, "disk info" },
- { SIMPLE_FILE_SYSTEM_PROTOCOL, "simple fs" },
- { LOAD_FILE_PROTOCOL, "load file" },
- { DEVICE_IO_PROTOCOL, "device io" },
- { UNICODE_COLLATION_PROTOCOL, "unicode collation" },
- { EFI_UNICODE_COLLATION2_PROTOCOL_GUID, "unicode collation2" },
- { EFI_SIMPLE_NETWORK_PROTOCOL, "simple network" },
- { SIMPLE_TEXT_OUTPUT_PROTOCOL, "simple text output" },
- { SIMPLE_TEXT_INPUT_PROTOCOL, "simple text input" },
- { EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID, "simple text ex input" },
- { EFI_CONSOLE_CONTROL_PROTOCOL_GUID, "console control" },
- { EFI_CONSOLE_IN_DEVICE_GUID, "stdin" },
- { EFI_CONSOLE_OUT_DEVICE_GUID, "stdout" },
- { EFI_STANDARD_ERROR_DEVICE_GUID, "stderr" },
- { EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, "GOP" },
- { EFI_UGA_DRAW_PROTOCOL_GUID, "UGA draw" },
- { EFI_PXE_BASE_CODE_PROTOCOL, "PXE base code" },
- { EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL, "PXE base code callback" },
- { SERIAL_IO_PROTOCOL, "serial io" },
- { LOADED_IMAGE_PROTOCOL, "loaded image" },
- { EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID,
- "loaded image device path" },
- { EFI_ISA_IO_PROTOCOL_GUID, "ISA io" },
- { EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID, "IDE controller init" },
- { EFI_ISA_ACPI_PROTOCOL_GUID, "ISA ACPI" },
- { EFI_PCI_IO_PROTOCOL_GUID, "PCI" },
- { EFI_PCI_ROOT_IO_GUID, "PCI root" },
- { EFI_PCI_ENUMERATION_COMPLETE_GUID, "PCI enumeration" },
- { EFI_DRIVER_DIAGNOSTICS_PROTOCOL_GUID, "Driver diagnostics" },
- { EFI_DRIVER_DIAGNOSTICS2_PROTOCOL_GUID, "Driver diagnostics2" },
- { EFI_SIMPLE_POINTER_PROTOCOL_GUID, "simple pointer" },
- { EFI_ABSOLUTE_POINTER_PROTOCOL_GUID, "absolute pointer" },
- { EFI_VLAN_CONFIG_PROTOCOL_GUID, "VLAN config" },
- { EFI_ARP_SERVICE_BINDING_PROTOCOL_GUID, "ARP service binding" },
- { EFI_ARP_PROTOCOL_GUID, "ARP" },
- { EFI_IP4_SERVICE_BINDING_PROTOCOL, "IPv4 service binding" },
- { EFI_IP4_PROTOCOL, "IPv4" },
- { EFI_IP4_CONFIG_PROTOCOL_GUID, "IPv4 config" },
- { EFI_IP6_SERVICE_BINDING_PROTOCOL, "IPv6 service binding" },
- { EFI_IP6_PROTOCOL, "IPv6" },
- { EFI_IP6_CONFIG_PROTOCOL_GUID, "IPv6 config" },
- { EFI_UDP4_PROTOCOL, "UDPv4" },
- { EFI_UDP4_SERVICE_BINDING_PROTOCOL, "UDPv4 service binding" },
- { EFI_UDP6_PROTOCOL, "UDPv6" },
- { EFI_UDP6_SERVICE_BINDING_PROTOCOL, "UDPv6 service binding" },
- { EFI_TCP4_PROTOCOL, "TCPv4" },
- { EFI_TCP4_SERVICE_BINDING_PROTOCOL, "TCPv4 service binding" },
- { EFI_TCP6_PROTOCOL, "TCPv6" },
- { EFI_TCP6_SERVICE_BINDING_PROTOCOL, "TCPv6 service binding" },
- { EFI_PART_TYPE_EFI_SYSTEM_PART_GUID, "EFI System partition" },
- { EFI_PART_TYPE_LEGACY_MBR_GUID, "MBR legacy" },
- { EFI_DEVICE_TREE_GUID, "device tree" },
- { EFI_USB_IO_PROTOCOL_GUID, "USB io" },
- { EFI_USB2_HC_PROTOCOL_GUID, "USB2 HC" },
- { EFI_COMPONENT_NAME_PROTOCOL_GUID, "component name" },
- { EFI_COMPONENT_NAME2_PROTOCOL_GUID, "component name2" },
- { EFI_DRIVER_BINDING_PROTOCOL_GUID, "driver binding" },
- { EFI_DRIVER_CONFIGURATION_PROTOCOL_GUID, "driver configuration" },
- { EFI_DRIVER_CONFIGURATION2_PROTOCOL_GUID, "driver configuration2" },
- { EFI_DECOMPRESS_PROTOCOL_GUID, "decompress" },
- { EFI_EBC_INTERPRETER_PROTOCOL_GUID, "ebc interpreter" },
- { EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL,
- "network interface identifier" },
- { EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_31,
- "network interface identifier_31" },
- { EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL_GUID,
- "managed network service binding" },
- { EFI_MANAGED_NETWORK_PROTOCOL_GUID, "managed network" },
- { EFI_FORM_BROWSER2_PROTOCOL_GUID, "form browser" },
- { EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID, "HII config routing" },
- { EFI_HII_DATABASE_PROTOCOL_GUID, "HII database" },
- { EFI_HII_STRING_PROTOCOL_GUID, "HII string" },
- { EFI_HII_IMAGE_PROTOCOL_GUID, "HII image" },
- { EFI_HII_FONT_PROTOCOL_GUID, "HII font" },
- { EFI_HII_CONFIGURATION_ACCESS_PROTOCOL_GUID, "HII config" },
- { EFI_MTFTP4_SERVICE_BINDING_PROTOCOL_GUID, "MTFTP4 service binding" },
- { EFI_MTFTP4_PROTOCOL_GUID, "MTFTP4" },
- { EFI_MTFTP6_SERVICE_BINDING_PROTOCOL_GUID, "MTFTP6 service binding" },
- { EFI_MTFTP6_PROTOCOL_GUID, "MTFTP6" },
- { EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID, "DHCP4 service binding" },
- { EFI_DHCP4_PROTOCOL_GUID, "DHCP4" },
- { EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID, "DHCP6 service binding" },
- { EFI_DHCP6_PROTOCOL_GUID, "DHCP6" },
- { EFI_SCSI_IO_PROTOCOL_GUID, "SCSI io" },
- { EFI_SCSI_PASS_THRU_PROTOCOL_GUID, "SCSI pass thru" },
- { EFI_EXT_SCSI_PASS_THRU_PROTOCOL_GUID, "SCSI pass thru ext" },
- { EFI_CAPSULE_ARCH_PROTOCOL_GUID, "Capsule arch" },
- { EFI_MONOTONIC_COUNTER_ARCH_PROTOCOL_GUID, "monotonic counter arch" },
- { EFI_REALTIME_CLOCK_ARCH_PROTOCOL_GUID, "realtime clock arch" },
- { EFI_VARIABLE_ARCH_PROTOCOL_GUID, "variable arch" },
- { EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID, "variable write arch" },
- { EFI_WATCHDOG_TIMER_ARCH_PROTOCOL_GUID, "watchdog timer arch" },
- { EFI_MP_SERVICES_PROTOCOL_GUID, "MP services" },
- { EFI_ACPI_SUPPORT_PROTOCOL_GUID, "ACPI support" },
- { EFI_BDS_ARCH_PROTOCOL_GUID, "BDS arch" },
- { EFI_METRONOME_ARCH_PROTOCOL_GUID, "metronome arch" },
- { EFI_TIMER_ARCH_PROTOCOL_GUID, "timer arch" },
- { EFI_DPC_PROTOCOL_GUID, "DPC" },
- { EFI_PRINT2_PROTOCOL_GUID, "print2" },
- { EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID, "device path to text" },
- { EFI_RESET_ARCH_PROTOCOL_GUID, "reset arch" },
- { EFI_CPU_ARCH_PROTOCOL_GUID, "CPU arch" },
- { EFI_CPU_IO2_PROTOCOL_GUID, "CPU IO2" },
- { EFI_LEGACY_8259_PROTOCOL_GUID, "Legacy 8259" },
- { EFI_SECURITY_ARCH_PROTOCOL_GUID, "Security arch" },
- { EFI_SECURITY2_ARCH_PROTOCOL_GUID, "Security2 arch" },
- { EFI_RUNTIME_ARCH_PROTOCOL_GUID, "Runtime arch" },
- { EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID, "status code runtime" },
- { EFI_DATA_HUB_PROTOCOL_GUID, "data hub" },
- { PCD_PROTOCOL_GUID, "PCD" },
- { EFI_PCD_PROTOCOL_GUID, "EFI PCD" },
- { EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID, "firmware volume block" },
- { EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID, "firmware volume2" },
- { EFI_FIRMWARE_VOLUME_DISPATCH_PROTOCOL_GUID,
- "firmware volume dispatch" },
- { LZMA_COMPRESS_GUID, "lzma compress" },
- { { 0,0,0,{0,0,0,0,0,0,0,0} }, NULL } /* must be last entry */
-};
-
COMMAND_SET(lsefi, "lsefi", "list EFI handles", command_lsefi);
static int
command_lsefi(int argc __attribute((unused)),
char *argv[] __attribute((unused)))
{
+ char *name;
EFI_HANDLE *buffer = NULL;
EFI_HANDLE handle;
UINTN bufsz = 0, i, j;
EFI_STATUS status;
- int k, ret;
+ int ret;
status = BS->LocateHandle(AllHandles, NULL, NULL, &bufsz, buffer);
if (status != EFI_BUFFER_TOO_SMALL) {
@@ -916,21 +658,19 @@
(long long)status);
continue;
}
+
for (j = 0; j < nproto; j++) {
- for (k = 0; proto_names[k].name != NULL; k++)
- if (memcmp(protocols[j], &proto_names[k].guid,
- sizeof (proto_names[k].guid)) == 0)
- break;
- if (proto_names[k].name != NULL)
- printf(" %s", proto_names[k].name);
- else
- printf(" %s", guid_to_string(protocols[j]));
- ret = pager_output("\n");
- if (ret)
+ if (efi_guid_to_name(protocols[j], &name) == true) {
+ printf(" %s", name);
+ free(name);
+ } else {
+ printf("Error while translating UUID to name");
+ }
+ if ((ret = pager_output("\n")) != 0)
break;
}
BS->FreePool(protocols);
- if (ret)
+ if (ret != 0)
break;
}
pager_close();
@@ -938,7 +678,6 @@
return (CMD_OK);
}
-#ifdef EFI_ZFS_BOOT
COMMAND_SET(lszfs, "lszfs", "list child datasets of a zfs dataset",
command_lszfs);
@@ -993,7 +732,6 @@
return (CMD_OK);
}
#endif /* __FreeBSD__ */
-#endif
void
efi_serial_init(void)