/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* 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/bitmap_scale.h>
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b))
/* Aliases set for some tables. */
struct tbl_alias
{
const char *name;
};
{
{GRUB_EFI_ACPI_20_TABLE_GUID, "ACPI_20"},
{GRUB_EFI_ACPI_TABLE_GUID, "ACPI"},
};
{
int pathlen;
};
static int
{
int i;
for (i = 0; in[i]; i++);
return i;
}
/* Read frequency from a string in MHz and return it in Hz. */
static grub_uint64_t
{
int found = 0;
while (*str)
{
unsigned long digit;
if (digit > 9)
break;
found = 1;
str++;
}
num *= 1000000;
if (*str == '.')
{
str++;
while (*str)
{
unsigned long digit;
if (digit > 9)
break;
found = 1;
mul /= 10;
str++;
}
}
if (! found)
return 0;
return num;
}
/* Thanks to Kabyl for precious information about Intel architecture. */
static grub_uint64_t
guessfsb (void)
{
if (! grub_cpu_is_cpuid_supported ())
return sane_value;
#ifdef APPLE_CC
asm volatile ("movl $0, %%eax\n"
#ifdef __x86_64__
"push %%rbx\n"
#else
"push %%ebx\n"
#endif
"cpuid\n"
#ifdef __x86_64__
"pop %%rbx\n"
#else
"pop %%ebx\n"
#endif
: "=a" (max_cpuid),
/* Only Intel for now is done. */
return sane_value;
#else
asm volatile ("movl $0, %%eax\n"
"cpuid"
/* Only Intel for now is done. */
return sane_value;
#endif
/* Check Speedstep. */
if (max_cpuid < 1)
return sane_value;
#ifdef APPLE_CC
asm volatile ("movl $1, %%eax\n"
#ifdef __x86_64__
"push %%rbx\n"
#else
"push %%ebx\n"
#endif
"cpuid\n"
#ifdef __x86_64__
"pop %%rbx\n"
#else
"pop %%ebx\n"
#endif
: "=c" (capabilities):
: "%rax", "%rdx");
#else
asm volatile ("movl $1, %%eax\n"
"cpuid"
: "=c" (capabilities):
: "%rax", "%rbx", "%rdx");
#endif
return sane_value;
/* Calibrate the TSC rate. */
start_tsc = grub_get_tsc ();
grub_pit_wait (0xffff);
end_tsc = grub_get_tsc ();
/* Read the multiplier. */
asm volatile ("movl $0x198, %%ecx\n"
"rdmsr"
: "=d" (msrlow)
:
: "%ecx", "%eax");
}
struct property_descriptor
{
int name16len;
int length;
void *data;
};
char *name)
{
if (!prop)
return GRUB_ERR_NONE;
return GRUB_ERR_NONE;
}
{
void *t;
{
t = prop;
grub_free (t);
}
return GRUB_ERR_NONE;
}
struct grub_xnu_devprop_device_descriptor *
{
if (!ret)
return 0;
{
return 0;
}
return ret;
}
static grub_err_t
{
if (!prop)
return grub_errno;
{
return grub_errno;
}
GRUB_AS_LIST (prop));
return GRUB_ERR_NONE;
}
{
if (!utf8)
return grub_errno;
if (!utf16)
{
return grub_errno;
}
if (utf16len < 0)
{
return grub_errno;
}
if (err)
{
return err;
}
return GRUB_ERR_NONE;
}
{
if (!utf16)
return grub_errno;
if (!utf8)
{
return grub_errno;
}
if (err)
{
return err;
}
return GRUB_ERR_NONE;
}
static inline int
hextoval (char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'z')
return c - 'a' + 10;
if (c >= 'A' && c <= 'Z')
return c - 'A' + 10;
return 0;
}
void
grub_cpu_xnu_unload (void)
{
{
}
}
static grub_err_t
grub_cpu_xnu_fill_devprop (void)
{
void *ptr;
void *t;
int numdevs = 0;
/* The key "efi". */
if (! efikey)
return grub_errno;
{
total_length += sizeof (struct grub_xnu_devprop_device_header);
{
total_length += sizeof (grub_uint32_t);
total_length += sizeof (grub_uint16_t)
total_length += sizeof (grub_uint32_t);
}
numdevs++;
}
if (!devprop)
return grub_errno;
{
devhead->num_values = 0;
{
void *data;
+ sizeof (grub_uint32_t);
/* NUL terminator. */
*name = 0;
t = propdesc;
grub_free (t);
devhead->num_values++;
}
t = device;
grub_free (t);
}
devices = 0;
return GRUB_ERR_NONE;
}
static grub_err_t
{
unsigned i, j;
if (argc != 1)
if (! file)
return grub_error (GRUB_ERR_FILE_NOT_FOUND,
"couldn't load device-propertie dump");
if (!buf)
{
return grub_errno;
}
{
return grub_errno;
}
{
do
{
}
- (char *) dpstart);
j++)
{
void *data;
break;
break;
break;
break;
- sizeof (grub_uint16_t)) / sizeof (grub_uint16_t),
if (err)
{
return err;
}
}
}
return GRUB_ERR_NONE;
}
/* Fill device tree. */
grub_cpu_xnu_fill_devicetree (void)
{
unsigned i, j;
/* The value "model". */
/* FIXME: may this value be sometimes different? */
if (! curval)
return grub_errno;
if (! curval)
return grub_errno;
/* The key "efi". */
if (! efikey)
return grub_errno;
/* Information about firmware. */
if (! curval)
return grub_errno;
return grub_errno;
if (! curval)
return grub_errno;
return grub_errno;
if (! curval)
return grub_errno;
return grub_errno;
if (SIZEOF_OF_UINTN == 4)
else
/* The key "platform". */
"platform");
if (! platformkey)
return grub_errno;
/* Pass FSB frequency to the kernel. */
if (! curval)
return grub_errno;
return grub_errno;
/* First see if user supplies the value. */
if (! fsbvar)
else
/* Try autodetect. */
"configuration-table");
if (!cfgtablekey)
return grub_errno;
/* Fill "configuration-table" key. */
for (i = 0; i < SYSTEM_TABLE (num_table_entries); i++)
{
void *ptr;
/* Retrieve current key. */
#ifdef GRUB_MACHINE_EFI
{
ptr = (void *)
}
#else
if (SIZEOF_OF_UINTN == 4)
{
guid =
}
else
{
guid =
}
#endif
/* The name of key for new table. */
for (j = 2; j < 8; j++)
/* For some reason GUID has to be in uppercase. */
for (j = 0; guidbuf[j] ; j++)
if (! curkey)
return grub_errno;
if (! curval)
return grub_errno;
return grub_errno;
/* The value "table". */
if (! curval)
return grub_errno;
return grub_errno;
if (SIZEOF_OF_UINTN == 4)
else
/* Create alias. */
for (j = 0; j < sizeof (table_aliases) / sizeof (table_aliases[0]); j++)
break;
if (j != sizeof (table_aliases) / sizeof (table_aliases[0]))
{
if (!curval)
return grub_errno;
return grub_errno;
}
}
/* Create and fill "runtime-services" key. */
"runtime-services");
if (! runtimesrvkey)
return grub_errno;
if (! curval)
return grub_errno;
return grub_errno;
if (SIZEOF_OF_UINTN == 4)
else
return GRUB_ERR_NONE;
}
grub_xnu_boot_resume (void)
{
}
/* Setup video for xnu. */
static grub_err_t
{
int ret;
char *tmp;
const char *modevar;
void *framebuffer;
/* Consider only graphical 32-bit deep modes. */
32 << GRUB_VIDEO_MODE_TYPE_DEPTH_POS);
else
{
if (! tmp)
return grub_errno;
32 << GRUB_VIDEO_MODE_TYPE_DEPTH_POS);
}
if (err)
return err;
if (ret)
if (grub_xnu_bitmap)
{
else
}
if (bitmap)
{
else
}
if (bitmap)
{
int x, y;
x /= 2;
y /= 2;
x > 0 ? x : 0,
y > 0 ? y : 0,
x < 0 ? -x : 0,
y < 0 ? -y : 0,
}
if (err)
{
grub_print_error ();
bitmap = 0;
}
if (ret)
return GRUB_ERR_NONE;
}
/* Boot xnu. */
grub_xnu_boot (void)
{
void *bp_in;
void *memory_map;
int i;
err = grub_autoefi_prepare ();
if (err)
return err;
err = grub_cpu_xnu_fill_devprop ();
if (err)
return err;
if (err)
return err;
err = grub_xnu_fill_devicetree ();
if (err)
return err;
/* Page-align to avoid following parts to be inadvertently freed. */
if (err)
return err;
/* Pass memory map to kernel. */
memory_map_size = 0;
memory_map = 0;
map_key = 0;
descriptor_size = 0;
descriptor_version = 0;
{
grub_printf ("Press any key to launch xnu\n");
grub_getkey ();
}
/* Relocate the boot parameters to heap. */
&bp_in, &bootparams_target);
if (err)
return err;
bootparams = bp_in;
/* Set video. */
if (err != GRUB_ERR_NONE)
{
grub_print_error ();
bootparams->lfb_mode = 0;
bootparams->lfb_width = 0;
bootparams->lfb_height = 0;
bootparams->lfb_depth = 0;
bootparams->lfb_line_len = 0;
bootparams->lfb_base = 0;
}
&descriptor_version) < 0)
return grub_errno;
/* We will do few allocations later. Reserve some space for possible
memory map growth. */
if (err)
return err;
if (err)
return err;
sizeof (bootparams->cmdline));
if (err)
return err;
/ GRUB_XNU_PAGESIZE) + 20;
for (i = 0; (unsigned) i < memory_map_size / descriptor_size; i++)
{
((char *) memory_map + descriptor_size * i);
{
if (curdesc->physical_start
}
}
/* Parameters for asm helper. */
}
void
grub_cpu_xnu_init (void)
{
0, N_("Load device-properties dump."));
}
void
grub_cpu_xnu_fini (void)
{
}