vaseboot/VasEBoot-core/loader/efi/appleloader.c

243 lines
6.6 KiB
C

/* appleloader.c - apple legacy boot loader. */
/*
* VasEBoot -- GRand Unified Bootloader
* Copyright (C) 2008,2009 Free Software Foundation, Inc.
*
* VasEBoot 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.
*
* VasEBoot 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 VasEBoot. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/loader.h>
#include <VasEBoot/err.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/efi/api.h>
#include <VasEBoot/efi/efi.h>
#include <VasEBoot/command.h>
#include <VasEBoot/i18n.h>
VasEBoot_MOD_LICENSE ("GPLv3+");
static VasEBoot_dl_t my_mod;
static VasEBoot_efi_handle_t image_handle;
static VasEBoot_efi_char16_t *cmdline;
static VasEBoot_err_t
VasEBoot_appleloader_unload (void)
{
VasEBoot_efi_boot_services_t *b;
b = VasEBoot_efi_system_table->boot_services;
efi_call_1 (b->unload_image, image_handle);
VasEBoot_free (cmdline);
cmdline = 0;
VasEBoot_dl_unref (my_mod);
return VasEBoot_ERR_NONE;
}
static VasEBoot_err_t
VasEBoot_appleloader_boot (void)
{
VasEBoot_efi_boot_services_t *b;
b = VasEBoot_efi_system_table->boot_services;
efi_call_3 (b->start_image, image_handle, 0, 0);
VasEBoot_appleloader_unload ();
return VasEBoot_errno;
}
struct piwg_full_device_path
{
struct VasEBoot_efi_memory_mapped_device_path comp1;
struct VasEBoot_efi_piwg_device_path comp2;
struct VasEBoot_efi_device_path end;
};
#define MAKE_PIWG_PATH(st, en) \
{ \
.comp1 = \
{ \
.header = { \
.type = VasEBoot_EFI_HARDWARE_DEVICE_PATH_TYPE, \
.subtype = VasEBoot_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE, \
.length = sizeof (struct VasEBoot_efi_memory_mapped_device_path) \
}, \
.memory_type = VasEBoot_EFI_MEMORY_MAPPED_IO, \
.start_address = st, \
.end_address = en \
}, \
.comp2 = \
{ \
.header = { \
.type = VasEBoot_EFI_MEDIA_DEVICE_PATH_TYPE, \
.subtype = VasEBoot_EFI_PIWG_DEVICE_PATH_SUBTYPE, \
.length = sizeof (struct VasEBoot_efi_piwg_device_path) \
}, \
.guid = VasEBoot_EFI_VENDOR_APPLE_GUID \
}, \
.end = \
{ \
.type = VasEBoot_EFI_END_DEVICE_PATH_TYPE, \
.subtype = VasEBoot_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, \
.length = sizeof (struct VasEBoot_efi_device_path) \
} \
}
/* early 2006 Core Duo / Core Solo models */
static struct piwg_full_device_path devpath_1 = MAKE_PIWG_PATH (0xffe00000,
0xfff9ffff);
/* mid-2006 Mac Pro (and probably other Core 2 models) */
static struct piwg_full_device_path devpath_2 = MAKE_PIWG_PATH (0xffe00000,
0xfff7ffff);
/* mid-2007 MBP ("Santa Rosa" based models) */
static struct piwg_full_device_path devpath_3 = MAKE_PIWG_PATH (0xffe00000,
0xfff8ffff);
/* early-2008 MBA */
static struct piwg_full_device_path devpath_4 = MAKE_PIWG_PATH (0xffc00000,
0xfff8ffff);
/* late-2008 MB/MBP (NVidia chipset) */
static struct piwg_full_device_path devpath_5 = MAKE_PIWG_PATH (0xffcb4000,
0xffffbfff);
/* mid-2010 MB/MBP (NVidia chipset) */
static struct piwg_full_device_path devpath_6 = MAKE_PIWG_PATH (0xffcc4000,
0xffffbfff);
static struct piwg_full_device_path devpath_7 = MAKE_PIWG_PATH (0xff981000,
0xffc8ffff);
/* mid-2012 MBP retina (MacBookPro10,1) */
static struct piwg_full_device_path devpath_8 = MAKE_PIWG_PATH (0xff990000,
0xffb2ffff);
struct devdata
{
const char *model;
VasEBoot_efi_device_path_t *devpath;
};
struct devdata devs[] =
{
{"Core Duo/Solo", (VasEBoot_efi_device_path_t *) &devpath_1},
{"Mac Pro", (VasEBoot_efi_device_path_t *) &devpath_2},
{"MBP", (VasEBoot_efi_device_path_t *) &devpath_3},
{"MBA", (VasEBoot_efi_device_path_t *) &devpath_4},
{"MB NV", (VasEBoot_efi_device_path_t *) &devpath_5},
{"MB NV2", (VasEBoot_efi_device_path_t *) &devpath_6},
{"MBP2011", (VasEBoot_efi_device_path_t *) &devpath_7},
{"MBP2012", (VasEBoot_efi_device_path_t *) &devpath_8},
{NULL, NULL},
};
static VasEBoot_err_t
VasEBoot_cmd_appleloader (VasEBoot_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
VasEBoot_efi_boot_services_t *b;
VasEBoot_efi_loaded_image_t *loaded_image;
struct devdata *pdev;
VasEBoot_dl_ref (my_mod);
/* Initialize some global variables. */
image_handle = 0;
b = VasEBoot_efi_system_table->boot_services;
for (pdev = devs ; pdev->devpath ; pdev++)
if (efi_call_6 (b->load_image, 0, VasEBoot_efi_image_handle, pdev->devpath,
NULL, 0, &image_handle) == VasEBoot_EFI_SUCCESS)
break;
if (! pdev->devpath)
{
VasEBoot_error (VasEBoot_ERR_BAD_OS, "can't find model");
goto fail;
}
VasEBoot_dprintf ("appleload", "Model: %s\n", pdev->model);
loaded_image = VasEBoot_efi_get_loaded_image (image_handle);
if (! loaded_image)
{
VasEBoot_error (VasEBoot_ERR_BAD_OS, "no loaded image available");
goto fail;
}
if (argc > 0)
{
int i, len;
VasEBoot_efi_char16_t *p16;
for (i = 0, len = 0; i < argc; i++)
len += VasEBoot_strlen (argv[i]) + 1;
len *= sizeof (VasEBoot_efi_char16_t);
cmdline = p16 = VasEBoot_malloc (len);
if (! cmdline)
goto fail;
for (i = 0; i < argc; i++)
{
char *p8;
p8 = argv[i];
while (*p8)
*(p16++) = *(p8++);
*(p16++) = ' ';
}
*(--p16) = 0;
loaded_image->load_options = cmdline;
loaded_image->load_options_size = len;
}
VasEBoot_loader_set (VasEBoot_appleloader_boot, VasEBoot_appleloader_unload, 0);
return 0;
fail:
VasEBoot_dl_unref (my_mod);
return VasEBoot_errno;
}
static VasEBoot_command_t cmd;
VasEBoot_MOD_INIT(appleloader)
{
cmd = VasEBoot_register_command ("appleloader", VasEBoot_cmd_appleloader,
N_("[OPTS]"),
/* TRANSLATORS: This command is used on EFI to
switch to BIOS mode and boot the OS requiring
BIOS. */
N_("Boot BIOS-based system."));
my_mod = mod;
}
VasEBoot_MOD_FINI(appleloader)
{
VasEBoot_unregister_command (cmd);
}