This is a long belated reply to an old thread:
https://lists.gnu.org/archive/html/grub-devel/2014-01/msg00017.html

I just wanted to note that I made a quick implementation of this a
while back for Linux's EFI-stub which may be useful to folks
interested in this issue. Revisiting it now since the current 3.18-rc
development tree has enough other fixes that using this trick with my
particular laptop (MacBookPro11,3) is nearly practical. My current
patch is certainly not suitable for upstream but my hunch is that
handling quirks like this makes a lot more sense in Linux than GRUB.
That would require GRUB to adopt launching Linux via the 'chainloader'
command (admittedly I haven't tried this) or the currently unmerged
'linuxefi'  command from Fedora:
http://lists.gnu.org/archive/html/grub-devel/2014-01/msg00120.html

The attached patch for Linux is against 3.18-rc4+

-- 
Michael Marineau
From 1f2fcbbca18176e2e6c862774428dad878bbac51 Mon Sep 17 00:00:00 2001
From: Michael Marineau <m...@marineau.org>
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

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to