On Monday, December 30, 2013, Andreas Heider wrote: 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.
Just a question: I do a lot of booting Linux on MacBooks, and I frequently suffer from this issue. How do we know that this code actually works? I'm not criticizing your code or anything, but how can you verify that identifying as Apple fixes these issues, or even that this patch works correctly. I'm only asking because I'm very interested in this if it works.
This depends, it just notifies all interested EFI drivers that they’re booting Mac OS X, so there’s no general answer. On my laptop this stops the integrated gnu from being disabled, so you could see it in lspci. But I guess you should see some difference in dmesg before and after.
There might be side effects of other things breaking in osx-mode due to the different configuration, so I implemented this as a optional command and not the default.
Also, this is just one of the ways Apple detects osx vs other operating systems, for example this does not help with acpi_osi=Darwin.
If you want to test it I’m interested if apple_set_os changes anything noteworthy on older models. They only started to support bootcamp via EFI this year, so I suspect that the hardware disabling took place in the BIOS/CSM before. --- 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;
Out of curiosity: how did you find these? + +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.";
Why are you making OS X 10.9 the default? Not every Mac can run 10.9. Ideally it would be very cool if you could figure out which version the user is running and identify as that.
AFAIK the os_version is never even read by the Apple EFI, so I just kept it as simple as possible. We could also just put GRUB as the version.
Secondly, you should include fallbacks in case this is run on a machine that isn't a Mac, as then that GUID and protocol won't be defined. It should exit gracefully, perhaps with an error message.
It should fail with "Could not locate the apple set os protocol.“. + +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
_______________________________________________ Grub-devel mailing list address@hidden https://lists.gnu.org/mailman/listinfo/grub-devel
_______________________________________________ Grub-devel mailing list address@hiddenhttps://lists.gnu.org/mailman/listinfo/grub-devel
|