EFI: retrieve and expose Apple device properties Apple's EFI drivers supply device properties which are needed to support Macs optimally. They contain vital information which cannot be obtained any other way (e.g. Thunderbolt Device ROM). They're also used to convey the current device state so that OS drivers can pick up where EFI drivers left (e.g. GPU mode setting). Reference: Linux commit 58c5475aba67706b31d9237808d5d3d54074e5ea (see there for the full original commit message, only the initial part of which is being reproduced above) Signed-off-by: Jan Beulich --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -38,6 +38,8 @@ { 0xf2fd1544, 0x9794, 0x4a2c, {0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94} } #define SHIM_LOCK_PROTOCOL_GUID \ { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} } +#define APPLE_PROPERTIES_PROTOCOL_GUID \ + { 0x91bd12fe, 0xf6c3, 0x44fb, { 0xa5, 0xb7, 0x51, 0x22, 0xab, 0x30, 0x3a, 0xe0} } typedef EFI_STATUS (/* _not_ EFIAPI */ *EFI_SHIM_LOCK_VERIFY) ( @@ -48,6 +50,44 @@ typedef struct { EFI_SHIM_LOCK_VERIFY Verify; } EFI_SHIM_LOCK_PROTOCOL; +struct _EFI_APPLE_PROPERTIES; + +typedef EFI_STATUS +(EFIAPI *EFI_APPLE_PROPERTIES_GET) ( + IN struct _EFI_APPLE_PROPERTIES *This, + IN const EFI_DEVICE_PATH *Device, + IN const CHAR16 *PropertyName, + OUT VOID *Buffer, + IN OUT UINT32 *BufferSize); + +typedef EFI_STATUS +(EFIAPI *EFI_APPLE_PROPERTIES_SET) ( + IN struct _EFI_APPLE_PROPERTIES *This, + IN const EFI_DEVICE_PATH *Device, + IN const CHAR16 *PropertyName, + IN const VOID *Value, + IN UINT32 ValueLen); + +typedef EFI_STATUS +(EFIAPI *EFI_APPLE_PROPERTIES_DELETE) ( + IN struct _EFI_APPLE_PROPERTIES *This, + IN const EFI_DEVICE_PATH *Device, + IN const CHAR16 *PropertyName); + +typedef EFI_STATUS +(EFIAPI *EFI_APPLE_PROPERTIES_GETALL) ( + IN struct _EFI_APPLE_PROPERTIES *This, + OUT VOID *Buffer, + IN OUT UINT32 *BufferSize); + +typedef struct _EFI_APPLE_PROPERTIES { + UINTN Version; /* 0x10000 */ + EFI_APPLE_PROPERTIES_GET Get; + EFI_APPLE_PROPERTIES_SET Set; + EFI_APPLE_PROPERTIES_DELETE Delete; + EFI_APPLE_PROPERTIES_GETALL GetAll; +} EFI_APPLE_PROPERTIES; + union string { CHAR16 *w; char *s; @@ -900,6 +940,46 @@ static void __init efi_variables(void) } } +static void __init efi_get_apple_properties(void) +{ + static EFI_GUID __initdata props_guid = APPLE_PROPERTIES_PROTOCOL_GUID; + EFI_APPLE_PROPERTIES *props; + UINT32 size = 0; + VOID *data; + EFI_STATUS status; + + if ( efi_bs->LocateProtocol(&props_guid, NULL, + (void **)&props) != EFI_SUCCESS ) + return; + if ( props->Version != 0x10000 ) + { + PrintStr(L"Warning: Unsupported Apple device properties version: "); + DisplayUint(props->Version, 0); + PrintStr(newline); + return; + } + + props->GetAll(props, NULL, &size); + if ( !size || + efi_bs->AllocatePool(EfiRuntimeServicesData, size, + &data) != EFI_SUCCESS ) + return; + + status = props->GetAll(props, data, &size); + if ( status == EFI_SUCCESS ) + { + efi_apple_properties_addr = (UINTN)data; + efi_apple_properties_len = size; + } + else + { + efi_bs->FreePool(data); + PrintStr(L"Warning: Could not query Apple device properties: "); + DisplayUint(status, 0); + PrintStr(newline); + } +} + static void __init efi_set_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, UINTN gop_mode) { EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info; @@ -1208,6 +1288,9 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY /* Get snapshot of variable store parameters. */ efi_variables(); + /* Collect Apple device properties, if any. */ + efi_get_apple_properties(); + efi_arch_memory_setup(); if ( gop ) --- a/xen/common/efi/efi.h +++ b/xen/common/efi/efi.h @@ -36,3 +36,6 @@ extern const struct efi_pci_rom *efi_pci extern UINT64 efi_boot_max_var_store_size, efi_boot_remain_var_store_size, efi_boot_max_var_size; + +extern UINT64 efi_apple_properties_addr; +extern UINTN efi_apple_properties_len; --- a/xen/common/efi/runtime.c +++ b/xen/common/efi/runtime.c @@ -56,6 +56,9 @@ UINT64 __read_mostly efi_boot_max_var_st UINT64 __read_mostly efi_boot_remain_var_store_size; UINT64 __read_mostly efi_boot_max_var_size; +UINT64 __read_mostly efi_apple_properties_addr; +UINTN __read_mostly efi_apple_properties_len; + /* Bit field representing available EFI features/properties. */ unsigned int efi_flags; @@ -271,6 +274,14 @@ int efi_get_info(uint32_t idx, union xen } return -ESRCH; } + + case XEN_FW_EFI_APPLE_PROPERTIES: + if ( !efi_apple_properties_len ) + return -ENODATA; + info->apple_properties.address = efi_apple_properties_addr; + info->apple_properties.size = efi_apple_properties_len; + break; + default: return -EINVAL; } --- a/xen/include/public/platform.h +++ b/xen/include/public/platform.h @@ -240,6 +240,7 @@ DEFINE_XEN_GUEST_HANDLE(xenpf_efi_runtim #define XEN_FW_EFI_MEM_INFO 3 #define XEN_FW_EFI_RT_VERSION 4 #define XEN_FW_EFI_PCI_ROM 5 +#define XEN_FW_EFI_APPLE_PROPERTIES 6 #define XEN_FW_KBD_SHIFT_FLAGS 5 struct xenpf_firmware_info { /* IN variables. */ @@ -299,6 +300,11 @@ struct xenpf_firmware_info { uint64_t address; xen_ulong_t size; } pci_rom; + struct { + /* OUT variables */ + uint64_t address; + xen_ulong_t size; + } apple_properties; } efi_info; /* XEN_FW_EFI_INFO */ /* Int16, Fn02: Get keyboard shift flags. */