From 1f2fcbbca18176e2e6c862774428dad878bbac51 Mon Sep 17 00:00:00 2001 From: Michael Marineau Date: Sun, 30 Mar 2014 13:01:35 -0700 Subject: [PATCH] efi: Identify as OS X to EFI drivers before booting. This prevents the firmware from powering down the integrated graphics card on some recent 2013 Macbook Pro laptops. The trick was originally posted as a command for GRUB2 by Andreas Heider. http://lists.gnu.org/archive/html/grub-devel/2013-12/msg00442.html --- arch/x86/boot/compressed/eboot.c | 62 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index 1acf605..419b368 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -1374,6 +1374,66 @@ free_mem_map: return status; } +#define APPLE_SET_OS_PROTOCOL_GUID \ + EFI_GUID(0xc5c5da95, 0x7d5c, 0x45e6, 0xb2, 0xf1, 0x3f, 0xd5, 0x2b, 0xb1, 0x00, 0x77) + +typedef struct { + u64 version; + void (*set_os_version) (const char *os_version); + void (*set_os_vendor) (const char *os_vendor); +} apple_set_os_interface_t; + +static efi_status_t apple_set_os() +{ + apple_set_os_interface_t *set_os; + efi_guid_t set_os_guid = APPLE_SET_OS_PROTOCOL_GUID; + efi_status_t status; + void **handles; + unsigned long i, nr_handles, size = 0; + + status = efi_call_early(locate_handle, EFI_LOCATE_BY_PROTOCOL, + &set_os_guid, NULL, &size, handles); + + if (status == EFI_BUFFER_TOO_SMALL) { + status = efi_call_early(allocate_pool, EFI_LOADER_DATA, + size, &handles); + + if (status != EFI_SUCCESS) + return status; + + status = efi_call_early(locate_handle, EFI_LOCATE_BY_PROTOCOL, + &set_os_guid, NULL, &size, handles); + } + + if (status != EFI_SUCCESS) + goto free_handle; + + nr_handles = size / sizeof(void *); + for (i = 0; i < nr_handles; i++) { + void *h = handles[i]; + + status = efi_call_early(handle_protocol, h, + &set_os_guid, &set_os); + + if (status != EFI_SUCCESS || !set_os) + continue; + + if (set_os->version > 0) { + efi_early->call((unsigned long)set_os->set_os_version, + "Mac OS X 10.9"); + } + + if (set_os->version >= 2) { + efi_early->call((unsigned long)set_os->set_os_vendor, + "Apple Inc."); + } + } + +free_handle: + efi_call_early(free_pool, handles); + return status; +} + /* * On success we return a pointer to a boot_params structure, and NULL * on failure. @@ -1445,6 +1505,8 @@ struct boot_params *efi_main(struct efi_config *c, hdr->code32_start = bzimage_addr; } + apple_set_os(); + status = exit_boot(boot_params, handle, is64); if (status != EFI_SUCCESS) { efi_printk(sys_table, "exit_boot() failed!\n"); -- 2.0.4