Package: grub-efi-amd64
Version: 2.02~beta2-22
Severity: wishlist
Tags: patch

Dear Debian folks,
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 supplied patch adds a command (apple_set_os) that fakes this OS 
identification to make all the hardware accessible to Linux.
So it's possible to have much better battery life and driver support by 
switching to the power saving Intel GPU instead of the discrete Nvidia GPU.

It would be great if you could apply this patch to the Debian package. I haven 
been using this patch for months and it works well.
The command should also be side-effect free as it just gets registered and then 
can be run by users who needs this quirk for their hardware. 

References:
https://lists.gnu.org/archive/html/grub-devel/2013-12/msg00442.html
https://github.com/0xbb/gpu-switch#requirements
https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/1367109
https://wiki.archlinux.org/index.php/MacBookPro11,x#Getting_the_integrated_intel_card_to_work_on_11.2C3

Greetings,
Bruno


-- Package-specific info:

*********************** BEGIN /proc/mounts
/dev/dm-1 / ext4 rw,relatime,errors=remount-ro,data=ordered 0 0
/dev/sda4 /boot ext4 rw,relatime,stripe=4,data=ordered 0 0
/dev/sda1 /boot/efi vfat 
rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=utf8,shortname=mixed,errors=remount-ro
 0 0
*********************** END /proc/mounts

*********************** BEGIN /boot/grub/grub.cfg
#
# DO NOT EDIT THIS FILE
#
# It is automatically generated by grub-mkconfig using templates
# from /etc/grub.d and settings from /etc/default/grub
#

### BEGIN /etc/grub.d/00_header ###
if [ -s $prefix/grubenv ]; then
  set have_grubenv=true
  load_env
fi
if [ "${next_entry}" ] ; then
   set default="${next_entry}"
   set next_entry=
   save_env next_entry
   set boot_once=true
else
   set default="0"
fi

if [ x"${feature_menuentry_id}" = xy ]; then
  menuentry_id_option="--id"
else
  menuentry_id_option=""
fi

export menuentry_id_option

if [ "${prev_saved_entry}" ]; then
  set saved_entry="${prev_saved_entry}"
  save_env saved_entry
  set prev_saved_entry=
  save_env prev_saved_entry
  set boot_once=true
fi

function savedefault {
  if [ -z "${boot_once}" ]; then
    saved_entry="${chosen}"
    save_env saved_entry
  fi
}
function load_video {
  if [ x$feature_all_video_module = xy ]; then
    insmod all_video
  else
    insmod efi_gop
    insmod efi_uga
    insmod ieee1275_fb
    insmod vbe
    insmod vga
    insmod video_bochs
    insmod video_cirrus
  fi
}

if [ x$feature_default_font_path = xy ] ; then
   font=unicode
else
insmod part_gpt
insmod ext2
set root='hd0,gpt4'
if [ x$feature_platform_search_hint = xy ]; then
  search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt4 
--hint-efi=hd0,gpt4 --hint-baremetal=ahci0,gpt4  
6e3b4ccf-6add-4c33-a49a-2c5d62f2fce0
else
  search --no-floppy --fs-uuid --set=root 6e3b4ccf-6add-4c33-a49a-2c5d62f2fce0
fi
    font="/grub/unicode.pf2"
fi

if loadfont $font ; then
  set gfxmode=auto
  load_video
  insmod gfxterm
  set locale_dir=$prefix/locale
  set lang=en_US
  insmod gettext
fi
terminal_output gfxterm
if [ "${recordfail}" = 1 ] ; then
  set timeout=-1
else
  if [ x$feature_timeout_style = xy ] ; then
    set timeout_style=menu
    set timeout=5
  # Fallback normal timeout code in case the timeout_style feature is
  # unavailable.
  else
    set timeout=5
  fi
fi
### END /etc/grub.d/00_header ###

### BEGIN /etc/grub.d/05_debian_theme ###
insmod part_gpt
insmod ext2
set root='hd0,gpt4'
if [ x$feature_platform_search_hint = xy ]; then
  search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt4 
--hint-efi=hd0,gpt4 --hint-baremetal=ahci0,gpt4  
6e3b4ccf-6add-4c33-a49a-2c5d62f2fce0
else
  search --no-floppy --fs-uuid --set=root 6e3b4ccf-6add-4c33-a49a-2c5d62f2fce0
fi
insmod png
if background_image /grub/.background_cache.png; then
  set color_normal=white/black
  set color_highlight=black/white
else
  set menu_color_normal=cyan/blue
  set menu_color_highlight=white/blue
fi
### END /etc/grub.d/05_debian_theme ###

### BEGIN /etc/grub.d/10_linux ###
function gfxmode {
        set gfxpayload="${1}"
}
set linux_gfx_mode=
export linux_gfx_mode
menuentry 'Debian GNU/Linux' --class debian --class gnu-linux --class gnu 
--class os $menuentry_id_option 
'gnulinux-simple-111886d7-b6a2-4840-94cb-525ebc62603f' {
        load_video
        insmod gzio
        if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
        insmod part_gpt
        insmod ext2
        set root='hd0,gpt4'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt4 
--hint-efi=hd0,gpt4 --hint-baremetal=ahci0,gpt4  
6e3b4ccf-6add-4c33-a49a-2c5d62f2fce0
        else
          search --no-floppy --fs-uuid --set=root 
6e3b4ccf-6add-4c33-a49a-2c5d62f2fce0
        fi
        echo    'Loading Linux 3.19.0 ...'
        linux   /vmlinuz-3.19.0 root=/dev/mapper/crypto_group-root ro  quiet 
libata.force=noncq
        echo    'Loading initial ramdisk ...'
        initrd  /initrd.img-3.19.0
}
submenu 'Advanced options for Debian GNU/Linux' $menuentry_id_option 
'gnulinux-advanced-111886d7-b6a2-4840-94cb-525ebc62603f' {
        menuentry 'Debian GNU/Linux, with Linux 3.19.0' --class debian --class 
gnu-linux --class gnu --class os $menuentry_id_option 
'gnulinux-3.19.0-advanced-111886d7-b6a2-4840-94cb-525ebc62603f' {
                load_video
                insmod gzio
                if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; 
fi
                insmod part_gpt
                insmod ext2
                set root='hd0,gpt4'
                if [ x$feature_platform_search_hint = xy ]; then
                  search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt4 
--hint-efi=hd0,gpt4 --hint-baremetal=ahci0,gpt4  
6e3b4ccf-6add-4c33-a49a-2c5d62f2fce0
                else
                  search --no-floppy --fs-uuid --set=root 
6e3b4ccf-6add-4c33-a49a-2c5d62f2fce0
                fi
                echo    'Loading Linux 3.19.0 ...'
                linux   /vmlinuz-3.19.0 root=/dev/mapper/crypto_group-root ro  
quiet libata.force=noncq
                echo    'Loading initial ramdisk ...'
                initrd  /initrd.img-3.19.0
        }
        menuentry 'Debian GNU/Linux, with Linux 3.19.0 (recovery mode)' --class 
debian --class gnu-linux --class gnu --class os $menuentry_id_option 
'gnulinux-3.19.0-recovery-111886d7-b6a2-4840-94cb-525ebc62603f' {
                load_video
                insmod gzio
                if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; 
fi
                insmod part_gpt
                insmod ext2
                set root='hd0,gpt4'
                if [ x$feature_platform_search_hint = xy ]; then
                  search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt4 
--hint-efi=hd0,gpt4 --hint-baremetal=ahci0,gpt4  
6e3b4ccf-6add-4c33-a49a-2c5d62f2fce0
                else
                  search --no-floppy --fs-uuid --set=root 
6e3b4ccf-6add-4c33-a49a-2c5d62f2fce0
                fi
                echo    'Loading Linux 3.19.0 ...'
                linux   /vmlinuz-3.19.0 root=/dev/mapper/crypto_group-root ro 
single 
                echo    'Loading initial ramdisk ...'
                initrd  /initrd.img-3.19.0
        }
        menuentry 'Debian GNU/Linux, with Linux 3.16.0-4-amd64' --class debian 
--class gnu-linux --class gnu --class os $menuentry_id_option 
'gnulinux-3.16.0-4-amd64-advanced-111886d7-b6a2-4840-94cb-525ebc62603f' {
                load_video
                insmod gzio
                if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; 
fi
                insmod part_gpt
                insmod ext2
                set root='hd0,gpt4'
                if [ x$feature_platform_search_hint = xy ]; then
                  search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt4 
--hint-efi=hd0,gpt4 --hint-baremetal=ahci0,gpt4  
6e3b4ccf-6add-4c33-a49a-2c5d62f2fce0
                else
                  search --no-floppy --fs-uuid --set=root 
6e3b4ccf-6add-4c33-a49a-2c5d62f2fce0
                fi
                echo    'Loading Linux 3.16.0-4-amd64 ...'
                linux   /vmlinuz-3.16.0-4-amd64 
root=/dev/mapper/crypto_group-root ro  quiet libata.force=noncq
                echo    'Loading initial ramdisk ...'
                initrd  /initrd.img-3.16.0-4-amd64
        }
        menuentry 'Debian GNU/Linux, with Linux 3.16.0-4-amd64 (recovery mode)' 
--class debian --class gnu-linux --class gnu --class os $menuentry_id_option 
'gnulinux-3.16.0-4-amd64-recovery-111886d7-b6a2-4840-94cb-525ebc62603f' {
                load_video
                insmod gzio
                if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; 
fi
                insmod part_gpt
                insmod ext2
                set root='hd0,gpt4'
                if [ x$feature_platform_search_hint = xy ]; then
                  search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt4 
--hint-efi=hd0,gpt4 --hint-baremetal=ahci0,gpt4  
6e3b4ccf-6add-4c33-a49a-2c5d62f2fce0
                else
                  search --no-floppy --fs-uuid --set=root 
6e3b4ccf-6add-4c33-a49a-2c5d62f2fce0
                fi
                echo    'Loading Linux 3.16.0-4-amd64 ...'
                linux   /vmlinuz-3.16.0-4-amd64 
root=/dev/mapper/crypto_group-root ro single 
                echo    'Loading initial ramdisk ...'
                initrd  /initrd.img-3.16.0-4-amd64
        }
}

### END /etc/grub.d/10_linux ###

### BEGIN /etc/grub.d/20_linux_xen ###

### END /etc/grub.d/20_linux_xen ###

### BEGIN /etc/grub.d/30_os-prober ###
### END /etc/grub.d/30_os-prober ###

### BEGIN /etc/grub.d/30_uefi-firmware ###
### END /etc/grub.d/30_uefi-firmware ###

### BEGIN /etc/grub.d/40_custom ###
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.
apple_set_os
### END /etc/grub.d/40_custom ###

### BEGIN /etc/grub.d/41_custom ###
if [ -f  ${config_directory}/custom.cfg ]; then
  source ${config_directory}/custom.cfg
elif [ -z "${config_directory}" -a -f  $prefix/custom.cfg ]; then
  source $prefix/custom.cfg;
fi
### END /etc/grub.d/41_custom ###
*********************** END /boot/grub/grub.cfg

*********************** BEGIN /proc/mdstat
cat: /proc/mdstat: No such file or directory
*********************** END /proc/mdstat

*********************** BEGIN /dev/disk/by-id
total 0
lrwxrwxrwx 1 root root  9 Apr  3 19:03 ata-APPLE_SSD_SM0512F_S1K5NYAD922851 -> 
../../sda
lrwxrwxrwx 1 root root 10 Apr  3 19:03 
ata-APPLE_SSD_SM0512F_S1K5NYAD922851-part1 -> ../../sda1
lrwxrwxrwx 1 root root 10 Apr  3 19:03 
ata-APPLE_SSD_SM0512F_S1K5NYAD922851-part2 -> ../../sda2
lrwxrwxrwx 1 root root 10 Apr  3 19:03 
ata-APPLE_SSD_SM0512F_S1K5NYAD922851-part3 -> ../../sda3
lrwxrwxrwx 1 root root 10 Apr  3 19:03 
ata-APPLE_SSD_SM0512F_S1K5NYAD922851-part4 -> ../../sda4
lrwxrwxrwx 1 root root 10 Apr  3 19:03 
ata-APPLE_SSD_SM0512F_S1K5NYAD922851-part5 -> ../../sda5
lrwxrwxrwx 1 root root 10 Apr  3 19:03 dm-name-crypto_group-root -> ../../dm-1
lrwxrwxrwx 1 root root 10 Apr  3 19:03 dm-name-crypto_group-swap -> ../../dm-2
lrwxrwxrwx 1 root root 10 Apr  3 19:03 dm-name-sda5_crypt -> ../../dm-0
lrwxrwxrwx 1 root root 10 Apr  3 19:03 
dm-uuid-CRYPT-LUKS1-8080b74f9f214875b10abc54ae48a9b8-sda5_crypt -> ../../dm-0
lrwxrwxrwx 1 root root 10 Apr  3 19:03 
dm-uuid-LVM-rk9Q42ForQmUZBCtStbEYFT2ITsYEXj86eBbzwcnHGtuOMAwOXTnmaKh8qtFd9Tm -> 
../../dm-1
lrwxrwxrwx 1 root root 10 Apr  3 19:03 
dm-uuid-LVM-rk9Q42ForQmUZBCtStbEYFT2ITsYEXj8OzItKN3I1jfeU4jMilJ5E0lYfg3BXGg0 -> 
../../dm-2
lrwxrwxrwx 1 root root 10 Apr  3 19:03 
lvm-pv-uuid-22MXpL-Z0cx-Z6E0-YmYi-SLJG-ubt3-VlwyQO -> ../../dm-0
lrwxrwxrwx 1 root root  9 Apr  3 19:03 wwn-0x5002538655584d30 -> ../../sda
lrwxrwxrwx 1 root root 10 Apr  3 19:03 wwn-0x5002538655584d30-part1 -> 
../../sda1
lrwxrwxrwx 1 root root 10 Apr  3 19:03 wwn-0x5002538655584d30-part2 -> 
../../sda2
lrwxrwxrwx 1 root root 10 Apr  3 19:03 wwn-0x5002538655584d30-part3 -> 
../../sda3
lrwxrwxrwx 1 root root 10 Apr  3 19:03 wwn-0x5002538655584d30-part4 -> 
../../sda4
lrwxrwxrwx 1 root root 10 Apr  3 19:03 wwn-0x5002538655584d30-part5 -> 
../../sda5
*********************** END /dev/disk/by-id

*********************** BEGIN /dev/disk/by-uuid
total 0
lrwxrwxrwx 1 root root 10 Apr  3 19:03 111886d7-b6a2-4840-94cb-525ebc62603f -> 
../../dm-1
lrwxrwxrwx 1 root root 10 Apr  3 19:03 65052daa-16b1-310d-8b32-1fa553ef10eb -> 
../../sda3
lrwxrwxrwx 1 root root 10 Apr  3 19:03 67E3-17ED -> ../../sda1
lrwxrwxrwx 1 root root 10 Apr  3 19:03 6e3b4ccf-6add-4c33-a49a-2c5d62f2fce0 -> 
../../sda4
lrwxrwxrwx 1 root root 10 Apr  3 19:03 7efe7022-70c6-49a0-a0e6-bdea0038e8ad -> 
../../dm-2
lrwxrwxrwx 1 root root 10 Apr  3 19:03 8080b74f-9f21-4875-b10a-bc54ae48a9b8 -> 
../../sda5
*********************** END /dev/disk/by-uuid

-- System Information:
Debian Release: 8.0
  APT prefers testing-updates
  APT policy: (500, 'testing-updates'), (500, 'testing'), (102, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.19.0 (SMP w/8 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

Versions of packages grub-efi-amd64 depends on:
ii  debconf [debconf-2.0]  1.5.56
ii  grub-common            2.02~beta2-22
ii  grub-efi-amd64-bin     2.02~beta2-22
ii  grub2-common           2.02~beta2-22
ii  ucf                    3.0030

grub-efi-amd64 recommends no packages.

grub-efi-amd64 suggests no packages.

-- debconf information excluded
---
 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);
+}

Reply via email to