grub-devel.gnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Add apple_set_os command
@ 2013-12-30 16:04 Andreas Heider
  2013-12-30 23:11 ` SevenBits
  2014-01-07 13:38 ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 2 replies; 13+ messages in thread
From: Andreas Heider @ 2013-12-30 16:04 UTC (permalink / raw)
  To: grub-devel; +Cc: Andreas Heider

The EFI on current macbooks configures hardware differently depending
on wether it is booting Mac OS X or a different os, for example
disabling the internal GPU completely on some models.

Mac OS X identifies itself using a custom EFI protocol.

This adds a command that fakes the os identification, making all
hardware accessible.
---
 grub-core/Makefile.core.def         |  6 +++
 grub-core/commands/efi/applesetos.c | 82 +++++++++++++++++++++++++++++++++++++
 2 files changed, 88 insertions(+)
 create mode 100644 grub-core/commands/efi/applesetos.c

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 42443bc..dc9c4de 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -742,6 +742,12 @@ module = {
 };
 
 module = {
+  name = applesetos;
+  common = commands/efi/applesetos.c;
+  enable = efi;
+};
+
+module = {
   name = blocklist;
   common = commands/blocklist.c;
 };
diff --git a/grub-core/commands/efi/applesetos.c b/grub-core/commands/efi/applesetos.c
new file mode 100644
index 0000000..9464307
--- /dev/null
+++ b/grub-core/commands/efi/applesetos.c
@@ -0,0 +1,82 @@
+/* applesetos.c - Pretend to be Mac OS X. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/command.h>
+/* For NULL.  */
+#include <grub/mm.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#define GRUB_EFI_APPLE_SET_OS_PROTOCOL_GUID  \
+  { 0xc5c5da95, 0x7d5c, 0x45e6, \
+    { 0xb2, 0xf1, 0x3f, 0xd5, 0x2b, 0xb1, 0x00, 0x77 } \
+  }
+
+struct grub_efi_apple_set_os_interface
+{
+  grub_efi_uint64_t version;
+  void (*set_os_version) (const grub_efi_char8_t *os_version);
+  void (*set_os_vendor) (const grub_efi_char8_t *os_vendor);
+};
+typedef struct grub_efi_apple_set_os_interface grub_efi_apple_set_os_interface_t;
+
+static const grub_efi_char8_t apple_os_version[] = "Mac OS X 10.9";
+static const grub_efi_char8_t apple_os_vendor[]  = "Apple Inc.";
+
+static grub_err_t
+grub_cmd_apple_set_os (grub_command_t cmd __attribute__ ((unused)),
+                       int argc __attribute__ ((unused)),
+                       char **args __attribute__ ((unused)))
+{
+  grub_efi_guid_t apple_set_os_guid = GRUB_EFI_APPLE_SET_OS_PROTOCOL_GUID;
+  grub_efi_apple_set_os_interface_t *set_os;
+  set_os = grub_efi_locate_protocol (&apple_set_os_guid, 0);
+  if (!set_os) {
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND,
+                       "Could not locate the apple set os protocol.");
+  }
+
+  if (set_os->version != 0)
+    {
+      efi_call_1 (set_os->set_os_version, apple_os_version);
+      grub_printf("Set os version to %s\n", apple_os_version);
+    }
+
+  if (set_os->version == 2)
+    {
+      efi_call_1 (set_os->set_os_vendor, apple_os_vendor);
+      grub_printf("Set os vendor to %s\n", apple_os_vendor);
+    }
+
+  return 0;
+}
+
+static grub_command_t cmd;
+
+GRUB_MOD_INIT(applesetos)
+{
+  cmd = grub_register_command ("apple_set_os", grub_cmd_apple_set_os, NULL,
+                               "Register as Apple Inc. Mac OS X 10.9.");
+}
+
+GRUB_MOD_FINI(applesetos)
+{
+  grub_unregister_command (cmd);
+}
-- 
1.8.5.2



^ permalink raw reply related	[flat|nested] 13+ messages in thread
* Re: [PATCH] Add apple_set_os command
@ 2014-11-13  6:57 Michael Marineau
  0 siblings, 0 replies; 13+ messages in thread
From: Michael Marineau @ 2014-11-13  6:57 UTC (permalink / raw)
  To: andreas; +Cc: grub-devel

[-- Attachment #1: Type: text/plain, Size: 898 bytes --]

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

[-- Attachment #2: 0001-efi-Identify-as-OS-X-to-EFI-drivers-before-booting.patch --]
[-- Type: text/x-patch, Size: 2727 bytes --]

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


^ permalink raw reply related	[flat|nested] 13+ messages in thread
* [PATCH] Add apple_set_os command
@ 2015-04-09 10:50 Bruno Bierbaumer
  0 siblings, 0 replies; 13+ messages in thread
From: Bruno Bierbaumer @ 2015-04-09 10:50 UTC (permalink / raw)
  To: grub-devel

Hello!
I wanted to bring some attention to this patch:
https://lists.gnu.org/archive/html/grub-devel/2013-12/msg00442.html
I haven been using this patch for months and it works well.

The current generation of dual GPU Macbook Pros turn off the integrated
Intel GPU when any other OS than Mac OS X is booted.
This works by MAC OS X identifying itself as a custom EFI protocol.
The mentioned patch adds a command (apple_set_os) that fakes this OS
identification to make all the hardware accessible.

It would be great if that patch could be merged so that distributions
will contain the command without manually patching grub.
I think the command is side-effect free as it just gets registered and
then can be run by users who need this quirk for their hardware.

References:
https://github.com/0xbb/gpu-switch#requirements
https://wiki.archlinux.org/index.php/MacBookPro11,x#Getting_the_integrated_intel_card_to_work_on_11.2C3
https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/1367109
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=781843

Greetings,
Bruno


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2015-04-09 10:50 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-30 16:04 [PATCH] Add apple_set_os command Andreas Heider
2013-12-30 23:11 ` SevenBits
2013-12-31  5:19   ` Andreas Heider
2014-01-03  6:46   ` Vladimir 'φ-coder/phcoder' Serbinenko
2014-01-03 17:26     ` SevenBits
2014-01-03 18:38     ` SevenBits
2014-01-07 15:19       ` andreas
2014-01-07 23:04         ` SevenBits
2014-01-07 13:38 ` Vladimir 'φ-coder/phcoder' Serbinenko
2014-01-07 14:46   ` Andrey Borzenkov
2014-01-07 14:58   ` andreas
  -- strict thread matches above, loose matches on Subject: below --
2014-11-13  6:57 Michael Marineau
2015-04-09 10:50 Bruno Bierbaumer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).