From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1bTZkx-0006YH-Na for mharc-grub-devel@gnu.org; Sat, 30 Jul 2016 15:17:07 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58503) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bTZku-0006Y8-7U for grub-devel@gnu.org; Sat, 30 Jul 2016 15:17:06 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bTZko-0002mA-UR for grub-devel@gnu.org; Sat, 30 Jul 2016 15:17:03 -0400 Received: from mail-lf0-x242.google.com ([2a00:1450:4010:c07::242]:34716) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bTZko-0002lt-IL for grub-devel@gnu.org; Sat, 30 Jul 2016 15:16:58 -0400 Received: by mail-lf0-x242.google.com with SMTP id l69so6757817lfg.1 for ; Sat, 30 Jul 2016 12:16:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=subject:to:references:cc:from:message-id:date:user-agent :mime-version:in-reply-to:content-transfer-encoding; bh=24vPZwNN5iA1fS52JKelbOmvpIo0z0e8avDggoT64eM=; b=vXillnUkI9JAeH+5JpvFx0/T8DmMXTwf/zbASk3stdIW9J9B7qx1OQ2s+dtXbMhHNG g7BjUHZWENW9GXq7B0yQrW3NZ3CpnkTibwbOR60vG5qG2bRbrQfH0pCQsV6HhCl5a8Qi C0j8kOZp50bSpPrikUiEnRplbyz5KVmSY0CzD7L5/cr+NntqhhXgp10SFhiZDcJZBQn3 GC1U7mkiXaujluWMWrpwvX8qN+N9ZDgtc/DjfvePMfL+VF2qAUMnWjvz+DsyU9zkG7ZL N2sO+uRNlk42DCZCUQVrKBPNJVBy4bE9SUiMweK7g7EEe6nApMLcuBaJ5iFNW/KBXegp Bx1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:subject:to:references:cc:from:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding; bh=24vPZwNN5iA1fS52JKelbOmvpIo0z0e8avDggoT64eM=; b=CaSwaYO56QP4dm7Lw//mW4Tk+nr21M0Q9RsMoRePpuUgMbBj4CtloOJaFC85S7HZqp HwryKpK6xZONAE08EDcOzoWvdrUNqn4j29CPy8UPfIfECIBJuYv5mNgElJqur3CwRWIx uIsecj8wnuMdESpW4uyfvsscHNVjnViWxAfH92X4eqZ4pj7gNBM3qUDJDGJ0JhSloncv CIzNym+3fVRlRBmgSMFrA0hjuEsAwxZDgHtGMNBWxs2ZDvR9xZZjSwq+d7z5uNBIpWBY AROoIFn5Xlv0UbHg13Pu3e40DqKQM7oZNerUu6a+vdl1WgYg2ptFi/qskZzvxpMpVTPv bSQg== X-Gm-Message-State: AEkoouuOU3guM3OsL2LPoNoG8/AlAF1M4k5e2ZaTqx8mEc82qvCxvf3gVJWO/0XMaj5+Gw== X-Received: by 10.25.147.197 with SMTP id v188mr17584881lfd.9.1469906216916; Sat, 30 Jul 2016 12:16:56 -0700 (PDT) Received: from [192.168.1.44] (ppp109-252-91-231.pppoe.spdop.ru. [109.252.91.231]) by smtp.gmail.com with ESMTPSA id n128sm3761997lfb.45.2016.07.30.12.16.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 30 Jul 2016 12:16:56 -0700 (PDT) Subject: Re: [PATCH 1/6] efi: Retrieve Apple device properties To: The development of GNU GRUB , linux-efi@vger.kernel.org, Matt Fleming , linux-kernel@vger.kernel.org, pjones@redhat.com References: <833d193b8a18b0afe168c515e9e56a857ece4bd1.1469616641.git.lukas@wunner.de> Cc: Andreas Noever , Pierre Moreau , x86@kernel.org, reverser@put.as From: Andrei Borzenkov Message-ID: <339ee03d-c8bb-d3c3-cf64-cc1c157ba406@gmail.com> Date: Sat, 30 Jul 2016 22:16:55 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0 MIME-Version: 1.0 In-Reply-To: <833d193b8a18b0afe168c515e9e56a857ece4bd1.1469616641.git.lukas@wunner.de> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:4010:c07::242 X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 30 Jul 2016 19:17:06 -0000 27.07.2016 14:20, Lukas Wunner пишет: > Retrieve device properties from EFI using Apple's proprietary protocol > with GUID 91BD12FE-F6C3-44FB-A5B7-5122AB303AE0, which looks like this: > > typedef struct { > unsigned long signature; /* 0x10000 */ > efi_status_t (*get) ( > IN struct apple_properties_protocol *this, > IN struct efi_generic_dev_path *device, > IN efi_char16_t *property_name, > OUT void *buffer, > IN OUT u32 *buffer_size); > /* EFI_SUCCESS, EFI_NOT_FOUND, EFI_BUFFER_TOO_SMALL */ > efi_status_t (*set) ( > IN struct apple_properties_protocol *this, > IN struct efi_generic_dev_path *device, > IN efi_char16_t *property_name, > IN void *property_value, > IN u32 property_value_len); > /* allocates copies of property name and value */ > /* EFI_SUCCESS, EFI_OUT_OF_RESOURCES */ > efi_status_t (*del) ( > IN struct apple_properties_protocol *this, > IN struct efi_generic_dev_path *device, > IN efi_char16_t *property_name); > /* EFI_SUCCESS, EFI_NOT_FOUND */ > efi_status_t (*get_all) ( > IN struct apple_properties_protocol *this, > OUT void *buffer, > IN OUT u32 *buffer_size); > /* EFI_SUCCESS, EFI_BUFFER_TOO_SMALL */ > } apple_properties_protocol; > > Apple's EFI driver implementing this protocol, "AAPL,PathProperties", > is a per-device key/value store which is populated by other EFI drivers. > On macOS, these device properties are retrieved by the bootloader > /usr/standalone/i386/boot.efi. The extension AppleACPIPlatform.kext > subsequently merges them into the I/O Kit registry (see ioreg(8)) where > they can be queried by other kernel extensions and user space. > > These device properties contain vital information which cannot be > obtained any other way (e.g. Thunderbolt Device ROM). EFI drivers also > use them to communicate the current device state so that OS drivers can > pick up where EFI drivers left (e.g. GPU mode setting). > > The get_all() function conveniently fills a buffer with all properties > in marshalled form which can be passed to the kernel as a setup_data > payload. Note that the device properties will only be available if the > kernel is booted with the efistub. Distros should adjust their > installers to always use the efistub on Macs. grub with the "linux" > directive will not work unless the functionality of this commit is > duplicated in grub. (The "linuxefi" directive should work but is not > included upstream as of this writing.) > Intention was to partially merge linuxefi functionality into "linux" by autodetecting and preferring EFI stub support. Peter, any progress on this? > Thanks to osxreverser for this blog posting which was helpful in reverse > engineering Apple's EFI drivers and bootloader: > https://reverse.put.as/2016/06/25/apple-efi-firmware-passwords-and-the-scbo-myth/ > > If someone at Apple is reading this, please note there's a memory leak > in your implementation of the del() function as the property struct is > freed but the name and value allocations are not. > > Cc: reverser@put.as > Cc: grub-devel@gnu.org > Cc: Matt Fleming > Cc: Andreas Noever > Tested-by: Lukas Wunner [MacBookPro9,1] > Tested-by: Pierre Moreau [MacBookPro11,3] > Signed-off-by: Lukas Wunner > --- > arch/x86/boot/compressed/eboot.c | 55 +++++++++++++++++++++++++++++++++++ > arch/x86/include/uapi/asm/bootparam.h | 1 + > include/linux/efi.h | 17 +++++++++++ > 3 files changed, 73 insertions(+) > > diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c > index ff574da..7262ee4 100644 > --- a/arch/x86/boot/compressed/eboot.c > +++ b/arch/x86/boot/compressed/eboot.c > @@ -571,6 +571,55 @@ free_handle: > efi_call_early(free_pool, pci_handle); > } > > +static void retrieve_apple_device_properties(struct boot_params *params) > +{ > + efi_guid_t guid = APPLE_PROPERTIES_PROTOCOL_GUID; > + struct setup_data *data, *new; > + efi_status_t status; > + void *properties; > + u32 size = 0; > + > + status = efi_early->call( > + (unsigned long)sys_table->boottime->locate_protocol, > + &guid, NULL, &properties); > + if (status != EFI_SUCCESS) > + return; > + > + do { > + status = efi_call_early(allocate_pool, EFI_LOADER_DATA, > + size + sizeof(struct setup_data), &new); > + if (status != EFI_SUCCESS) { > + efi_printk(sys_table, > + "Failed to alloc mem for properties\n"); > + return; > + } > + status = efi_early->call(efi_early->is64 ? > + ((apple_properties_protocol_64 *)properties)->get_all : > + ((apple_properties_protocol_32 *)properties)->get_all, > + properties, new->data, &size); > + if (status == EFI_BUFFER_TOO_SMALL) > + efi_call_early(free_pool, new); > + } while (status == EFI_BUFFER_TOO_SMALL); > + > + if (!size) { > + efi_call_early(free_pool, new); > + return; > + } > + > + new->type = SETUP_APPLE_PROPERTIES; > + new->len = size; > + new->next = 0; > + > + data = (struct setup_data *)(unsigned long)params->hdr.setup_data; > + if (!data) > + params->hdr.setup_data = (unsigned long)new; > + else { > + while (data->next) > + data = (struct setup_data *)(unsigned long)data->next; > + data->next = (unsigned long)new; > + } > +} > + > static efi_status_t > setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height) > { > @@ -1098,6 +1147,7 @@ free_mem_map: > struct boot_params *efi_main(struct efi_config *c, > struct boot_params *boot_params) > { > + efi_char16_t const apple[] = { 'A', 'p', 'p', 'l', 'e', 0 }; > struct desc_ptr *gdt = NULL; > efi_loaded_image_t *image; > struct setup_header *hdr = &boot_params->hdr; > @@ -1128,6 +1178,11 @@ struct boot_params *efi_main(struct efi_config *c, > > setup_efi_pci(boot_params); > > + if (!memcmp((void *)sys_table->fw_vendor, apple, sizeof(apple))) { > + if (IS_ENABLED(CONFIG_APPLE_PROPERTIES)) > + retrieve_apple_device_properties(boot_params); > + } > + > status = efi_call_early(allocate_pool, EFI_LOADER_DATA, > sizeof(*gdt), (void **)&gdt); > if (status != EFI_SUCCESS) { > diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h > index c18ce67..b10bf31 100644 > --- a/arch/x86/include/uapi/asm/bootparam.h > +++ b/arch/x86/include/uapi/asm/bootparam.h > @@ -7,6 +7,7 @@ > #define SETUP_DTB 2 > #define SETUP_PCI 3 > #define SETUP_EFI 4 > +#define SETUP_APPLE_PROPERTIES 5 > > /* ram_size flags */ > #define RAMDISK_IMAGE_START_MASK 0x07FF > diff --git a/include/linux/efi.h b/include/linux/efi.h > index 7f80a75..e53b4b2 100644 > --- a/include/linux/efi.h > +++ b/include/linux/efi.h > @@ -432,6 +432,22 @@ typedef struct { > #define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000 > #define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 0x40000 > > +typedef struct { > + u32 signature; > + u32 get; > + u32 set; > + u32 del; > + u32 get_all; > +} apple_properties_protocol_32; > + > +typedef struct { > + u64 signature; > + u64 get; > + u64 set; > + u64 del; > + u64 get_all; > +} apple_properties_protocol_64; > + > /* > * Types and defines for EFI ResetSystem > */ > @@ -580,6 +596,7 @@ void efi_native_runtime_setup(void); > #define EFI_RNG_PROTOCOL_GUID EFI_GUID(0x3152bca5, 0xeade, 0x433d, 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44) > #define EFI_MEMORY_ATTRIBUTES_TABLE_GUID EFI_GUID(0xdcfa911d, 0x26eb, 0x469f, 0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20) > #define EFI_CONSOLE_OUT_DEVICE_GUID EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) > +#define APPLE_PROPERTIES_PROTOCOL_GUID EFI_GUID(0x91bd12fe, 0xf6c3, 0x44fb, 0xa5, 0xb7, 0x51, 0x22, 0xab, 0x30, 0x3a, 0xe0) > > /* > * This GUID is used to pass to the kernel proper the struct screen_info >