Manually reimported XNU branch

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2009-11-09 18:43:53 +01:00
parent 32764030b5
commit 1d3c6f1de7
29 changed files with 1128 additions and 633 deletions

View file

@ -769,6 +769,20 @@
2009-08-29 Vladimir Serbinenko <phcoder@gmail.com>
* kern/misc.c (grub_utf16_to_utf8): Move from here ...
* include/grub/charset.h (grub_utf16_to_utf8): ... to here. Inlined.
All users updated.
* include/grub/misc.h (grub_utf16_to_utf8): Removed.
2009-08-28 Vladimir Serbinenko <phcoder@gmail.com>
* bus/usb/usb.c (grub_usb_get_string): Move from here ...
* commands/usbtest.c (grub_usb_get_string): ... move here.
(usb_print_str): Fix error handling.
* include/grub/usb.h (grub_usb_get_string): Remove.
2009-08-28 Vladimir Serbinenko <phcoder@gmail.com>
* include/grub/i386/xnu.h: Add license header.
include grub/err.h explicitly.
@ -1030,6 +1044,35 @@
* kern/misc.c (grub_tolower): Moved from here ...
* include/grub/misc.h (grub_tolower): ... here. Inlined.
2009-08-24 Vladimir Serbinenko <phcoder@gmail.com>
Eliminate ad-hoc tree format in XNU and EfiEmu.
* efiemu/main.c (grub_efiemu_prepare): Update comment.
* efiemu/pnvram.c: Rewritten to use environment variables.
All users updated.
* include/grub/xnu.h (grub_xnu_fill_devicetree): New prototype.
* loader/i386/xnu.c (grub_xnu_boot): Call grub_cpu_xnu_fill_devicetree
and grub_xnu_fill_devicetree.
* loader/xnu.c (grub_cmd_xnu_kernel): Don't call
grub_cpu_xnu_fill_devicetree.
(grub_xnu_parse_devtree): Removed.
(grub_cmd_xnu_devtree): Likewise.
(hextoval): New function.
(unescape): Likewise.
(grub_xnu_fill_devicetree): Likewise.
2009-08-24 Vladimir Serbinenko <phcoder@gmail.com>
UTF-8 to UTF-16 transformation.
* conf/common.rmk (pkglib_MODULES): Add utf.mod
(utf_mod_SOURCES): New variable.
(utf_mod_CFLAGS): Likewise.
(utf_mod_LDFLAGS): Likewise.
* include/grub/utf.h: New file.
* lib/utf.c: New file. (Based on grub_utf8_to_ucs4 from kern/misc.c)
2009-08-24 Vladimir Serbinenko <phcoder@gmail.com>
* script/sh/function.c (grub_script_function_find): Cut error message

0
autogen.sh Normal file → Executable file
View file

View file

@ -155,42 +155,6 @@ grub_usb_get_endpdescriptor (grub_usb_device_t usbdev, int addr)
return NULL;
}
grub_usb_err_t
grub_usb_get_string (grub_usb_device_t dev, grub_uint8_t index, int langid,
char **string)
{
struct grub_usb_desc_str descstr;
struct grub_usb_desc_str *descstrp;
grub_usb_err_t err;
/* Only get the length. */
err = grub_usb_control_msg (dev, 1 << 7,
0x06, (3 << 8) | index,
langid, 1, (char *) &descstr);
if (err)
return err;
descstrp = grub_malloc (descstr.length);
if (! descstrp)
return GRUB_USB_ERR_INTERNAL;
err = grub_usb_control_msg (dev, 1 << 7,
0x06, (3 << 8) | index,
langid, descstr.length, (char *) descstrp);
*string = grub_malloc (descstr.length / 2);
if (! *string)
{
grub_free (descstrp);
return GRUB_USB_ERR_INTERNAL;
}
grub_utf16_to_utf8 ((grub_uint8_t *) *string, descstrp->str, descstrp->length / 2 - 1);
(*string)[descstr.length / 2 - 1] = '\0';
grub_free (descstrp);
return GRUB_USB_ERR_NONE;
}
grub_usb_err_t
grub_usb_device_initialize (grub_usb_device_t dev)
{

View file

@ -19,6 +19,7 @@
#include <grub/types.h>
#include <grub/misc.h>
#include <grub/charset.h>
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/dl.h>
@ -59,18 +60,60 @@ static const char *usb_devspeed[] =
"High"
};
static grub_usb_err_t
grub_usb_get_string (grub_usb_device_t dev, grub_uint8_t index, int langid,
char **string)
{
struct grub_usb_desc_str descstr;
struct grub_usb_desc_str *descstrp;
grub_usb_err_t err;
/* Only get the length. */
err = grub_usb_control_msg (dev, 1 << 7,
0x06, (3 << 8) | index,
langid, 1, (char *) &descstr);
if (err)
return err;
descstrp = grub_malloc (descstr.length);
if (! descstrp)
return GRUB_USB_ERR_INTERNAL;
err = grub_usb_control_msg (dev, 1 << 7,
0x06, (3 << 8) | index,
langid, descstr.length, (char *) descstrp);
*string = grub_malloc (descstr.length / 2);
if (! *string)
{
grub_free (descstrp);
return GRUB_USB_ERR_INTERNAL;
}
grub_utf16_to_utf8 ((grub_uint8_t *) *string, descstrp->str, descstrp->length / 2 - 1);
(*string)[descstr.length / 2 - 1] = '\0';
grub_free (descstrp);
return GRUB_USB_ERR_NONE;
}
static void
usb_print_str (const char *description, grub_usb_device_t dev, int idx)
{
char *name;
grub_usb_err_t err;
/* XXX: LANGID */
if (! idx)
return;
grub_usb_get_string (dev, idx, 0x0409, &name);
grub_printf ("%s: `%s'\n", description, name);
grub_free (name);
err = grub_usb_get_string (dev, idx, 0x0409, &name);
if (err)
grub_printf ("Error %d retrieving %s\n", err, description);
else
{
grub_printf ("%s: `%s'\n", description, name);
grub_free (name);
}
}
static int

View file

@ -608,3 +608,8 @@ pkglib_MODULES += setjmp.mod
setjmp_mod_SOURCES = lib/$(target_cpu)/setjmp.S
setjmp_mod_ASFLAGS = $(COMMON_ASFLAGS)
setjmp_mod_LDFLAGS = $(COMMON_LDFLAGS)
pkglib_MODULES += charset.mod
charset_mod_SOURCES = lib/charset.c
charset_mod_CFLAGS = $(COMMON_CFLAGS)
charset_mod_LDFLAGS = $(COMMON_LDFLAGS)

View file

@ -39,6 +39,7 @@ grub_efi_system_table64_t *grub_efiemu_system_table64 = 0;
static struct grub_efiemu_prepare_hook *efiemu_prepare_hooks = 0;
/* Linked list of configuration tables */
static struct grub_efiemu_configuration_table *efiemu_config_tables = 0;
static int prepared = 0;
/* Free all allocated space */
grub_err_t
@ -70,6 +71,8 @@ grub_efiemu_unload (void)
}
efiemu_prepare_hooks = 0;
prepared = 0;
return GRUB_ERR_NONE;
}
@ -277,14 +280,19 @@ grub_efiemu_prepare (void)
{
grub_err_t err;
if (prepared)
return GRUB_ERR_NONE;
grub_dprintf ("efiemu", "Preparing %d-bit efiemu\n",
8 * grub_efiemu_sizeof_uintn_t ());
err = grub_efiemu_autocore ();
/* Create NVRAM if not yet done. */
/* Create NVRAM. */
grub_efiemu_pnvram ();
prepared = 1;
if (grub_efiemu_sizeof_uintn_t () == 4)
return grub_efiemu_prepare32 (efiemu_prepare_hooks, efiemu_config_tables);
else
@ -316,9 +324,6 @@ grub_cmd_efiemu_load (grub_command_t cmd __attribute__ ((unused)),
static grub_command_t cmd_loadcore, cmd_prepare, cmd_unload;
void
grub_efiemu_pnvram_cmd_register (void);
GRUB_MOD_INIT(efiemu)
{
cmd_loadcore = grub_register_command ("efiemu_loadcore",
@ -332,7 +337,6 @@ GRUB_MOD_INIT(efiemu)
cmd_unload = grub_register_command ("efiemu_unload", grub_cmd_efiemu_unload,
"efiemu_unload",
"Unload EFI emulator");
grub_efiemu_pnvram_cmd_register ();
}
GRUB_MOD_FINI(efiemu)
@ -340,5 +344,4 @@ GRUB_MOD_FINI(efiemu)
grub_unregister_command (cmd_loadcore);
grub_unregister_command (cmd_prepare);
grub_unregister_command (cmd_unload);
grub_efiemu_pnvram_cmd_unregister ();
}

View file

@ -22,6 +22,7 @@
#include <grub/normal.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/charset.h>
#include <grub/efiemu/efiemu.h>
#include <grub/efiemu/runtime.h>
#include <grub/extcmd.h>
@ -34,62 +35,181 @@ static int timezone_handle = 0;
static int accuracy_handle = 0;
static int daylight_handle = 0;
/* Temporary place */
static grub_uint8_t *nvram;
static grub_size_t nvramsize;
static grub_uint32_t high_monotonic_count;
static grub_int16_t timezone;
static grub_uint8_t daylight;
static grub_uint32_t accuracy;
static const struct grub_arg_option options[] = {
{"size", 's', 0, "number of bytes to reserve for pseudo NVRAM", 0,
ARG_TYPE_INT},
{"high-monotonic-count", 'm', 0,
"Initial value of high monotonic count", 0, ARG_TYPE_INT},
{"timezone", 't', 0,
"Timezone, offset in minutes from GMT", 0, ARG_TYPE_INT},
{"accuracy", 'a', 0,
"Accuracy of clock, in 1e-12 units", 0, ARG_TYPE_INT},
{"daylight", 'd', 0,
"Daylight value, as per EFI specifications", 0, ARG_TYPE_INT},
{0, 0, 0, 0, 0, 0}
};
/* Parse signed value */
static int
grub_strtosl (char *arg, char **end, int base)
grub_strtosl (const char *arg, char **end, int base)
{
if (arg[0] == '-')
return -grub_strtoul (arg + 1, end, base);
return grub_strtoul (arg, end, base);
}
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;
}
static inline grub_err_t
unescape (char *in, char *out, char *outmax, int *len)
{
char *ptr, *dptr;
dptr = out;
for (ptr = in; *ptr && dptr < outmax; )
if (*ptr == '%' && ptr[1] && ptr[2])
{
*dptr = (hextoval (ptr[1]) << 4) | (hextoval (ptr[2]));
ptr += 3;
dptr++;
}
else
{
*dptr = *ptr;
ptr++;
dptr++;
}
if (dptr == outmax)
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"Too many NVRAM variables for reserved variable space."
" Try increasing EfiEmu.pnvram.size.");
*len = dptr - out;
return 0;
}
/* Export stuff for efiemu */
static grub_err_t
nvram_set (void * data __attribute__ ((unused)))
{
const char *env;
/* Take definitive pointers */
grub_uint8_t *nvram_def = grub_efiemu_mm_obtain_request (nvram_handle);
char *nvram = grub_efiemu_mm_obtain_request (nvram_handle);
grub_uint32_t *nvramsize_def
= grub_efiemu_mm_obtain_request (nvramsize_handle);
grub_uint32_t *high_monotonic_count_def
grub_uint32_t *high_monotonic_count
= grub_efiemu_mm_obtain_request (high_monotonic_count_handle);
grub_int16_t *timezone_def
grub_int16_t *timezone
= grub_efiemu_mm_obtain_request (timezone_handle);
grub_uint8_t *daylight_def
grub_uint8_t *daylight
= grub_efiemu_mm_obtain_request (daylight_handle);
grub_uint32_t *accuracy_def
grub_uint32_t *accuracy
= grub_efiemu_mm_obtain_request (accuracy_handle);
char *nvramptr;
auto int iterate_env (struct grub_env_var *var);
int iterate_env (struct grub_env_var *var)
{
char *guid, *attr, *name, *varname;
struct efi_variable *efivar;
int len = 0;
if (grub_memcmp (var->name, "EfiEmu.pnvram.",
sizeof ("EfiEmu.pnvram.") - 1) != 0)
return 0;
guid = var->name + sizeof ("EfiEmu.pnvram.") - 1;
attr = grub_strchr (guid, '.');
if (!attr)
return 0;
attr++;
name = grub_strchr (attr, '.');
if (!name)
return 0;
name++;
efivar = (struct efi_variable *) nvramptr;
if (nvramptr - nvram + sizeof (struct efi_variable) > nvramsize)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY,
"Too many NVRAM variables for reserved variable space."
" Try increasing EfiEmu.pnvram.size.");
return 1;
}
nvramptr += sizeof (struct efi_variable);
efivar->guid.data1 = grub_cpu_to_le32 (grub_strtoul (guid, &guid, 16));
if (*guid != '-')
return 0;
guid++;
efivar->guid.data2 = grub_cpu_to_le16 (grub_strtoul (guid, &guid, 16));
if (*guid != '-')
return 0;
guid++;
efivar->guid.data3 = grub_cpu_to_le16 (grub_strtoul (guid, &guid, 16));
if (*guid != '-')
return 0;
guid++;
*(grub_uint64_t *) &(efivar->guid.data4)
= grub_cpu_to_be64 (grub_strtoull (guid, 0, 16));
efivar->attributes = grub_strtoull (attr, 0, 16);
varname = grub_malloc (grub_strlen (name) + 1);
if (! varname)
return 1;
if (unescape (name, varname, varname + grub_strlen (name) + 1, &len))
return 1;
len = grub_utf8_to_utf16 ((grub_uint16_t *) nvramptr,
(nvramsize - (nvramptr - nvram)) / 2,
(grub_uint8_t *) varname, len, NULL);
if (len < 0)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "Broken UTF-8 in variable name\n");
return 1;
}
nvramptr += 2 * len;
*((grub_uint16_t *) nvramptr) = 0;
nvramptr += 2;
efivar->namelen = 2 * len + 2;
if (unescape (var->value, nvramptr, nvram + nvramsize, &len))
{
efivar->namelen = 0;
return 1;
}
nvramptr += len;
efivar->size = len;
return 0;
}
/* Copy to definitive loaction */
grub_dprintf ("efiemu", "preparing pnvram\n");
grub_memcpy (nvram_def, nvram, nvramsize);
env = grub_env_get ("EfiEmu.pnvram.high_monotonic_count");
*high_monotonic_count = env ? grub_strtoul (env, 0, 0) : 1;
env = grub_env_get ("EfiEmu.pnvram.timezone");
*timezone = env ? grub_strtosl (env, 0, 0) : GRUB_EFI_UNSPECIFIED_TIMEZONE;
env = grub_env_get ("EfiEmu.pnvram.accuracy");
*accuracy = env ? grub_strtoul (env, 0, 0) : 50000000;
env = grub_env_get ("EfiEmu.pnvram.daylight");
*daylight = env ? grub_strtoul (env, 0, 0) : 0;
nvramptr = nvram;
grub_memset (nvram, 0, nvramsize);
grub_env_iterate (iterate_env);
if (grub_errno)
return grub_errno;
*nvramsize_def = nvramsize;
*high_monotonic_count_def = high_monotonic_count;
*timezone_def = timezone;
*daylight_def = daylight;
*accuracy_def = accuracy;
/* Register symbols */
grub_efiemu_register_symbol ("efiemu_variables", nvram_handle, 0);
@ -113,197 +233,27 @@ nvram_unload (void * data __attribute__ ((unused)))
grub_efiemu_mm_return_request (timezone_handle);
grub_efiemu_mm_return_request (accuracy_handle);
grub_efiemu_mm_return_request (daylight_handle);
grub_free (nvram);
nvram = 0;
}
/* Load the variables file It's in format
guid1:attr1:name1:data1;
guid2:attr2:name2:data2;
...
Where all fields are in hex
*/
static grub_err_t
read_pnvram (char *filename)
{
char *buf, *ptr, *ptr2;
grub_file_t file;
grub_size_t size;
grub_uint8_t *nvramptr = nvram;
struct efi_variable *efivar;
grub_size_t guidlen, datalen;
unsigned i, j;
file = grub_file_open (filename);
if (!file)
return grub_error (GRUB_ERR_BAD_OS, "couldn't read pnvram");
size = grub_file_size (file);
buf = grub_malloc (size + 1);
if (!buf)
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't read pnvram");
if (grub_file_read (file, buf, size) != (grub_ssize_t) size)
return grub_error (GRUB_ERR_BAD_OS, "couldn't read pnvram");
buf[size] = 0;
grub_file_close (file);
for (ptr = buf; *ptr; )
{
if (grub_isspace (*ptr))
{
ptr++;
continue;
}
efivar = (struct efi_variable *) nvramptr;
if (nvramptr - nvram + sizeof (struct efi_variable) > nvramsize)
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"file is too large for reserved variable space");
nvramptr += sizeof (struct efi_variable);
/* look ahow long guid field is*/
guidlen = 0;
for (ptr2 = ptr; (grub_isspace (*ptr2)
|| (*ptr2 >= '0' && *ptr2 <= '9')
|| (*ptr2 >= 'a' && *ptr2 <= 'f')
|| (*ptr2 >= 'A' && *ptr2 <= 'F'));
ptr2++)
if (!grub_isspace (*ptr2))
guidlen++;
guidlen /= 2;
/* Read guid */
if (guidlen != sizeof (efivar->guid))
{
grub_free (buf);
return grub_error (GRUB_ERR_BAD_OS, "can't parse %s", filename);
}
for (i = 0; i < 2 * sizeof (efivar->guid); i++)
{
int hex = 0;
while (grub_isspace (*ptr))
ptr++;
if (*ptr >= '0' && *ptr <= '9')
hex = *ptr - '0';
if (*ptr >= 'a' && *ptr <= 'f')
hex = *ptr - 'a' + 10;
if (*ptr >= 'A' && *ptr <= 'F')
hex = *ptr - 'A' + 10;
if (i%2 == 0)
((grub_uint8_t *)&(efivar->guid))[i/2] = hex << 4;
else
((grub_uint8_t *)&(efivar->guid))[i/2] |= hex;
ptr++;
}
while (grub_isspace (*ptr))
ptr++;
if (*ptr != ':')
{
grub_dprintf ("efiemu", "Not colon\n");
grub_free (buf);
return grub_error (GRUB_ERR_BAD_OS, "can't parse %s", filename);
}
ptr++;
while (grub_isspace (*ptr))
ptr++;
/* Attributes can be just parsed by existing functions */
efivar->attributes = grub_strtoul (ptr, &ptr, 16);
while (grub_isspace (*ptr))
ptr++;
if (*ptr != ':')
{
grub_dprintf ("efiemu", "Not colon\n");
grub_free (buf);
return grub_error (GRUB_ERR_BAD_OS, "can't parse %s", filename);
}
ptr++;
while (grub_isspace (*ptr))
ptr++;
/* Read name and value */
for (j = 0; j < 2; j++)
{
/* Look the length */
datalen = 0;
for (ptr2 = ptr; *ptr2 && (grub_isspace (*ptr2)
|| (*ptr2 >= '0' && *ptr2 <= '9')
|| (*ptr2 >= 'a' && *ptr2 <= 'f')
|| (*ptr2 >= 'A' && *ptr2 <= 'F'));
ptr2++)
if (!grub_isspace (*ptr2))
datalen++;
datalen /= 2;
if (nvramptr - nvram + datalen > nvramsize)
{
grub_free (buf);
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"file is too large for reserved "
" variable space");
}
for (i = 0; i < 2 * datalen; i++)
{
int hex = 0;
while (grub_isspace (*ptr))
ptr++;
if (*ptr >= '0' && *ptr <= '9')
hex = *ptr - '0';
if (*ptr >= 'a' && *ptr <= 'f')
hex = *ptr - 'a' + 10;
if (*ptr >= 'A' && *ptr <= 'F')
hex = *ptr - 'A' + 10;
if (i%2 == 0)
nvramptr[i/2] = hex << 4;
else
nvramptr[i/2] |= hex;
ptr++;
}
nvramptr += datalen;
while (grub_isspace (*ptr))
ptr++;
if (*ptr != (j ? ';' : ':'))
{
grub_free (buf);
grub_dprintf ("efiemu", j?"Not semicolon\n":"Not colon\n");
return grub_error (GRUB_ERR_BAD_OS, "can't parse %s", filename);
}
if (j)
efivar->size = datalen;
else
efivar->namelen = datalen;
ptr++;
}
}
grub_free (buf);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_efiemu_make_nvram (void)
grub_err_t
grub_efiemu_pnvram (void)
{
const char *size;
grub_err_t err;
err = grub_efiemu_autocore ();
if (err)
{
grub_free (nvram);
return err;
}
nvramsize = 0;
size = grub_env_get ("EfiEmu.pnvram.size");
if (size)
nvramsize = grub_strtoul (size, 0, 0);
if (!nvramsize)
nvramsize = 2048;
err = grub_efiemu_register_prepare_hook (nvram_set, nvram_unload, 0);
if (err)
{
grub_free (nvram);
return err;
}
return err;
nvram_handle
= grub_efiemu_request_memalign (1, nvramsize,
GRUB_EFI_RUNTIME_SERVICES_DATA);
@ -323,78 +273,5 @@ grub_efiemu_make_nvram (void)
= grub_efiemu_request_memalign (1, sizeof (grub_uint32_t),
GRUB_EFI_RUNTIME_SERVICES_DATA);
grub_efiemu_request_symbols (6);
return GRUB_ERR_NONE;
}
grub_err_t
grub_efiemu_pnvram (void)
{
if (nvram)
return GRUB_ERR_NONE;
nvramsize = 2048;
high_monotonic_count = 1;
timezone = GRUB_EFI_UNSPECIFIED_TIMEZONE;
accuracy = 50000000;
daylight = 0;
nvram = grub_zalloc (nvramsize);
if (!nvram)
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"Couldn't allocate space for temporary pnvram storage");
return grub_efiemu_make_nvram ();
}
static grub_err_t
grub_cmd_efiemu_pnvram (struct grub_extcmd *cmd,
int argc, char **args)
{
struct grub_arg_list *state = cmd->state;
grub_err_t err;
if (argc > 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "only one argument expected");
nvramsize = state[0].set ? grub_strtoul (state[0].arg, 0, 0) : 2048;
high_monotonic_count = state[1].set ? grub_strtoul (state[1].arg, 0, 0) : 1;
timezone = state[2].set ? grub_strtosl (state[2].arg, 0, 0)
: GRUB_EFI_UNSPECIFIED_TIMEZONE;
accuracy = state[3].set ? grub_strtoul (state[3].arg, 0, 0) : 50000000;
daylight = state[4].set ? grub_strtoul (state[4].arg, 0, 0) : 0;
nvram = grub_zalloc (nvramsize);
if (!nvram)
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"Couldn't allocate space for temporary pnvram storage");
if (argc == 1 && (err = read_pnvram (args[0])))
{
grub_free (nvram);
return err;
}
return grub_efiemu_make_nvram ();
}
static grub_extcmd_t cmd;
void grub_efiemu_pnvram_cmd_register (void);
void grub_efiemu_pnvram_cmd_unregister (void);
void
grub_efiemu_pnvram_cmd_register (void)
{
cmd = grub_register_extcmd ("efiemu_pnvram", grub_cmd_efiemu_pnvram,
GRUB_COMMAND_FLAG_BOTH,
"efiemu_pnvram [FILENAME]",
"Initialise pseudo-NVRAM and load variables "
"from FILE",
options);
}
void
grub_efiemu_pnvram_cmd_unregister (void)
{
grub_unregister_extcmd (cmd);
}

View file

@ -25,6 +25,7 @@
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/charset.h>
#define GRUB_FAT_DIR_ENTRY_SIZE 32

View file

@ -28,6 +28,7 @@
#include <grub/types.h>
#include <grub/fshelp.h>
#include <grub/hfs.h>
#include <grub/charset.h>
#define GRUB_HFSPLUS_MAGIC 0x482B
#define GRUB_HFSPLUSX_MAGIC 0x4858

View file

@ -65,7 +65,6 @@ grub_pxe_open (const char *name, grub_disk_t disk)
disk->total_sectors = 0;
disk->id = (unsigned long) "pxe";
disk->has_partitions = 0;
disk->data = 0;
return GRUB_ERR_NONE;

View file

@ -26,6 +26,7 @@
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/fshelp.h>
#include <grub/charset.h>
#define GRUB_ISO9660_FSTYPE_DIR 0040000
#define GRUB_ISO9660_FSTYPE_REG 0100000

View file

@ -24,6 +24,7 @@
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/charset.h>
#define GRUB_JFS_MAX_SYMLNK_CNT 8
#define GRUB_JFS_FILETYPE_MASK 0170000

View file

@ -24,6 +24,7 @@
#include <grub/dl.h>
#include <grub/fshelp.h>
#include <grub/ntfs.h>
#include <grub/charset.h>
static grub_dl_t my_mod;

0
gendistlist.sh Normal file → Executable file
View file

112
include/grub/charset.h Normal file
View file

@ -0,0 +1,112 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 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/>.
*/
#ifndef GRUB_CHARSET_HEADER
#define GRUB_CHARSET_HEADER 1
#include <grub/types.h>
#define GRUB_UINT8_1_LEADINGBIT 0x80
#define GRUB_UINT8_2_LEADINGBITS 0xc0
#define GRUB_UINT8_3_LEADINGBITS 0xe0
#define GRUB_UINT8_4_LEADINGBITS 0xf0
#define GRUB_UINT8_5_LEADINGBITS 0xf8
#define GRUB_UINT8_6_LEADINGBITS 0xfc
#define GRUB_UINT8_7_LEADINGBITS 0xfe
#define GRUB_UINT8_1_TRAILINGBIT 0x01
#define GRUB_UINT8_2_TRAILINGBITS 0x03
#define GRUB_UINT8_3_TRAILINGBITS 0x07
#define GRUB_UINT8_4_TRAILINGBITS 0x0f
#define GRUB_UINT8_5_TRAILINGBITS 0x1f
#define GRUB_UINT8_6_TRAILINGBITS 0x3f
#define GRUB_UCS2_LIMIT 0x10000
#define GRUB_UTF16_UPPER_SURROGATE(code) \
(0xD800 + ((((code) - GRUB_UCS2_LIMIT) >> 12) & 0xfff))
#define GRUB_UTF16_LOWER_SURROGATE(code) \
(0xDC00 + (((code) - GRUB_UCS2_LIMIT) & 0xfff))
grub_ssize_t
grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize,
const grub_uint8_t *src, grub_size_t srcsize,
const grub_uint8_t **srcend);
/* Convert UTF-16 to UTF-8. */
static inline grub_uint8_t *
grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src,
grub_size_t size)
{
grub_uint32_t code_high = 0;
while (size--)
{
grub_uint32_t code = *src++;
if (code_high)
{
if (code >= 0xDC00 && code <= 0xDFFF)
{
/* Surrogate pair. */
code = ((code_high - 0xD800) << 12) + (code - 0xDC00) + 0x10000;
*dest++ = (code >> 18) | 0xF0;
*dest++ = ((code >> 12) & 0x3F) | 0x80;
*dest++ = ((code >> 6) & 0x3F) | 0x80;
*dest++ = (code & 0x3F) | 0x80;
}
else
{
/* Error... */
*dest++ = '?';
}
code_high = 0;
}
else
{
if (code <= 0x007F)
*dest++ = code;
else if (code <= 0x07FF)
{
*dest++ = (code >> 6) | 0xC0;
*dest++ = (code & 0x3F) | 0x80;
}
else if (code >= 0xD800 && code <= 0xDBFF)
{
code_high = code;
continue;
}
else if (code >= 0xDC00 && code <= 0xDFFF)
{
/* Error... */
*dest++ = '?';
}
else
{
*dest++ = (code >> 12) | 0xE0;
*dest++ = ((code >> 6) & 0x3F) | 0x80;
*dest++ = (code & 0x3F) | 0x80;
}
}
}
return dest;
}
#endif

View file

@ -20,6 +20,7 @@
#define GRUB_CPU_XNU_H 1
#include <grub/err.h>
#include <grub/efi/api.h>
#define GRUB_XNU_PAGESIZE 4096
typedef grub_uint32_t grub_xnu_ptr_t;
@ -67,13 +68,52 @@ struct grub_xnu_boot_params
#define GRUB_XNU_BOOTARGS_VERMINOR 5
#define GRUB_XNU_BOOTARGS_VERMAJOR 1
struct grub_xnu_devprop_header
{
grub_uint32_t length;
/* Always set to 1. Version? */
grub_uint32_t alwaysone;
grub_uint32_t num_devices;
};
struct grub_xnu_devprop_device_header
{
grub_uint32_t length;
grub_uint32_t num_values;
};
void grub_cpu_xnu_unload (void);
struct grub_xnu_devprop_device_descriptor;
struct grub_xnu_devprop_device_descriptor *
grub_xnu_devprop_add_device (struct grub_efi_device_path *path, int length);
grub_err_t
grub_xnu_devprop_remove_device (struct grub_xnu_devprop_device_descriptor *dev);
grub_err_t
grub_xnu_devprop_remove_property (struct grub_xnu_devprop_device_descriptor *dev,
char *name);
grub_err_t
grub_xnu_devprop_add_property_utf8 (struct grub_xnu_devprop_device_descriptor *dev,
char *name, void *data, int datalen);
grub_err_t
grub_xnu_devprop_add_property_utf16 (struct grub_xnu_devprop_device_descriptor *dev,
grub_uint16_t *name, int namelen,
void *data, int datalen);
grub_err_t
grub_xnu_devprop_remove_property_utf8 (struct grub_xnu_devprop_device_descriptor *dev,
char *name);
void grub_cpu_xnu_init (void);
void grub_cpu_xnu_fini (void);
extern grub_uint32_t grub_xnu_entry_point;
extern grub_uint32_t grub_xnu_stack;
extern grub_uint32_t grub_xnu_arg1;
extern char grub_xnu_cmdline[1024];
grub_err_t grub_xnu_boot (void);
grub_err_t grub_cpu_xnu_fill_devicetree (void);
grub_err_t grub_xnu_set_video (struct grub_xnu_boot_params *bootparams_relloc);
grub_err_t
grub_cpu_xnu_fill_devicetree (void);
extern grub_uint32_t grub_xnu_heap_will_be_at;
extern grub_uint8_t grub_xnu_launcher_start[];
extern grub_uint8_t grub_xnu_launcher_end[];

View file

@ -180,9 +180,6 @@ int EXPORT_FUNC(grub_sprintf) (char *str, const char *fmt, ...) __attribute__ ((
int EXPORT_FUNC(grub_vsprintf) (char *str, const char *fmt, va_list args);
void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn));
void EXPORT_FUNC(grub_abort) (void) __attribute__ ((noreturn));
grub_uint8_t *EXPORT_FUNC(grub_utf16_to_utf8) (grub_uint8_t *dest,
grub_uint16_t *src,
grub_size_t size);
grub_ssize_t EXPORT_FUNC(grub_utf8_to_ucs4) (grub_uint32_t *dest,
grub_size_t destsize,
const grub_uint8_t *src,

View file

@ -64,9 +64,6 @@ grub_usb_err_t grub_usb_clear_halt (grub_usb_device_t dev, int endpoint);
grub_usb_err_t grub_usb_set_configuration (grub_usb_device_t dev,
int configuration);
grub_usb_err_t grub_usb_get_string (grub_usb_device_t dev, grub_uint8_t index,
int langid, char **string);
void grub_usb_controller_dev_register (grub_usb_controller_dev_t usb);
void grub_usb_controller_dev_unregister (grub_usb_controller_dev_t usb);

View file

@ -102,6 +102,7 @@ grub_err_t grub_xnu_scan_dir_for_kexts (char *dirname, char *osbundlerequired,
grub_err_t grub_xnu_load_kext_from_dir (char *dirname, char *osbundlerequired,
int maxrecursion);
void *grub_xnu_heap_malloc (int size);
grub_err_t grub_xnu_fill_devicetree (void);
extern grub_uint32_t grub_xnu_heap_real_start;
extern grub_size_t grub_xnu_heap_size;
extern char *grub_xnu_heap_start;

View file

@ -18,6 +18,7 @@
*/
#include <grub/misc.h>
#include <grub/charset.h>
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
#include <grub/efi/console_control.h>

View file

@ -837,68 +837,6 @@ grub_sprintf (char *str, const char *fmt, ...)
return ret;
}
/* Convert UTF-16 to UTF-8. */
grub_uint8_t *
grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src,
grub_size_t size)
{
grub_uint32_t code_high = 0;
while (size--)
{
grub_uint32_t code = *src++;
if (code_high)
{
if (code >= 0xDC00 && code <= 0xDFFF)
{
/* Surrogate pair. */
code = ((code_high - 0xD800) << 12) + (code - 0xDC00) + 0x10000;
*dest++ = (code >> 18) | 0xF0;
*dest++ = ((code >> 12) & 0x3F) | 0x80;
*dest++ = ((code >> 6) & 0x3F) | 0x80;
*dest++ = (code & 0x3F) | 0x80;
}
else
{
/* Error... */
*dest++ = '?';
}
code_high = 0;
}
else
{
if (code <= 0x007F)
*dest++ = code;
else if (code <= 0x07FF)
{
*dest++ = (code >> 6) | 0xC0;
*dest++ = (code & 0x3F) | 0x80;
}
else if (code >= 0xD800 && code <= 0xDBFF)
{
code_high = code;
continue;
}
else if (code >= 0xDC00 && code <= 0xDFFF)
{
/* Error... */
*dest++ = '?';
}
else
{
*dest++ = (code >> 12) | 0xE0;
*dest++ = ((code >> 6) & 0x3F) | 0x80;
*dest++ = (code & 0x3F) | 0x80;
}
}
}
return dest;
}
/* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE
bytes (if SRCSIZE is -1, it is ignored) in length to a UCS-4 string.
Return the number of characters converted. DEST must be able to hold

116
lib/charset.c Normal file
View file

@ -0,0 +1,116 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 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/>.
*/
/* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE
bytes (if SRCSIZE is -1, it is ignored) in length to a UTF-16 string.
Return the number of characters converted. DEST must be able to hold
at least DESTSIZE characters. If an invalid sequence is found, return -1.
If SRCEND is not NULL, then *SRCEND is set to the next byte after the
last byte used in SRC. */
#include <grub/charset.h>
grub_ssize_t
grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize,
const grub_uint8_t *src, grub_size_t srcsize,
const grub_uint8_t **srcend)
{
grub_uint16_t *p = dest;
int count = 0;
grub_uint32_t code = 0;
if (srcend)
*srcend = src;
while (srcsize && destsize)
{
grub_uint32_t c = *src++;
if (srcsize != (grub_size_t)-1)
srcsize--;
if (count)
{
if ((c & GRUB_UINT8_2_LEADINGBITS) != GRUB_UINT8_1_LEADINGBIT)
{
/* invalid */
return -1;
}
else
{
code <<= 6;
code |= (c & GRUB_UINT8_6_TRAILINGBITS);
count--;
}
}
else
{
if (c == 0)
break;
if ((c & GRUB_UINT8_1_LEADINGBIT) == 0)
code = c;
else if ((c & GRUB_UINT8_3_LEADINGBITS) == GRUB_UINT8_2_LEADINGBITS)
{
count = 1;
code = c & GRUB_UINT8_5_TRAILINGBITS;
}
else if ((c & GRUB_UINT8_4_LEADINGBITS) == GRUB_UINT8_3_LEADINGBITS)
{
count = 2;
code = c & GRUB_UINT8_4_TRAILINGBITS;
}
else if ((c & GRUB_UINT8_5_LEADINGBITS) == GRUB_UINT8_4_LEADINGBITS)
{
count = 3;
code = c & GRUB_UINT8_3_TRAILINGBITS;
}
else if ((c & GRUB_UINT8_6_LEADINGBITS) == GRUB_UINT8_5_LEADINGBITS)
{
count = 4;
code = c & GRUB_UINT8_2_TRAILINGBITS;
}
else if ((c & GRUB_UINT8_7_LEADINGBITS) == GRUB_UINT8_6_LEADINGBITS)
{
count = 5;
code = c & GRUB_UINT8_1_TRAILINGBIT;
}
else
return -1;
}
if (count == 0)
{
if (destsize < 2 && code >= GRUB_UCS2_LIMIT)
break;
if (code >= GRUB_UCS2_LIMIT)
{
*p++ = GRUB_UTF16_UPPER_SURROGATE (code);
*p++ = GRUB_UTF16_LOWER_SURROGATE (code);
destsize -= 2;
}
else
{
*p++ = code;
destsize--;
}
}
}
if (srcend)
*srcend = src;
return p - dest;
}

View file

@ -25,6 +25,7 @@
#include <grub/device.h>
#include <grub/disk.h>
#include <grub/misc.h>
#include <grub/charset.h>
#include <grub/mm.h>
#include <grub/types.h>
#include <grub/dl.h>

View file

@ -25,9 +25,13 @@
#include <grub/loader.h>
#include <grub/autoefi.h>
#include <grub/i386/tsc.h>
#include <grub/efi/api.h>
#include <grub/i386/pit.h>
#include <grub/misc.h>
#include <grub/charset.h>
#include <grub/term.h>
#include <grub/command.h>
#include <grub/gzio.h>
char grub_xnu_cmdline[1024];
@ -44,6 +48,14 @@ struct tbl_alias table_aliases[] =
{GRUB_EFI_ACPI_TABLE_GUID, "ACPI"},
};
struct grub_xnu_devprop_device_descriptor
{
struct grub_xnu_devprop_device_descriptor *next;
struct property_descriptor *properties;
struct grub_efi_device_path *path;
int pathlen;
};
/* The following function is used to be able to debug xnu loader
with grub-emu. */
#ifdef GRUB_UTIL
@ -205,6 +217,417 @@ guessfsb (void)
((msrlow >> 7) & 0x3e) + ((msrlow >> 14) & 1), 0);
}
struct property_descriptor
{
struct property_descriptor *next;
grub_uint8_t *name;
grub_uint16_t *name16;
int name16len;
int length;
void *data;
};
struct grub_xnu_devprop_device_descriptor *devices = 0;
grub_err_t
grub_xnu_devprop_remove_property (struct grub_xnu_devprop_device_descriptor *dev,
char *name)
{
struct property_descriptor *prop;
prop = grub_named_list_find (GRUB_AS_NAMED_LIST_P (&dev->properties), name);
if (!prop)
return GRUB_ERR_NONE;
grub_free (prop->name);
grub_free (prop->name16);
grub_free (prop->data);
grub_list_remove (GRUB_AS_LIST_P (&dev->properties), GRUB_AS_LIST (prop));
return GRUB_ERR_NONE;
}
grub_err_t
grub_xnu_devprop_remove_device (struct grub_xnu_devprop_device_descriptor *dev)
{
void *t;
struct property_descriptor *prop;
grub_list_remove (GRUB_AS_LIST_P (&devices), GRUB_AS_LIST (dev));
for (prop = dev->properties; prop; )
{
grub_free (prop->name);
grub_free (prop->name16);
grub_free (prop->data);
t = prop;
prop = prop->next;
grub_free (t);
}
grub_free (dev->path);
grub_free (dev);
return GRUB_ERR_NONE;
}
struct grub_xnu_devprop_device_descriptor *
grub_xnu_devprop_add_device (struct grub_efi_device_path *path, int length)
{
struct grub_xnu_devprop_device_descriptor *ret;
ret = grub_zalloc (sizeof (*ret));
if (!ret)
return 0;
ret->path = grub_malloc (length);
if (!ret->path)
{
grub_free (ret);
return 0;
}
ret->pathlen = length;
grub_memcpy (ret->path, path, length);
grub_list_push (GRUB_AS_LIST_P (&devices), GRUB_AS_LIST (ret));
return ret;
}
static grub_err_t
grub_xnu_devprop_add_property (struct grub_xnu_devprop_device_descriptor *dev,
grub_uint8_t *utf8, grub_uint16_t *utf16,
int utf16len, void *data, int datalen)
{
struct property_descriptor *prop;
prop = grub_malloc (sizeof (*prop));
if (!prop)
return grub_errno;
prop->name = utf8;
prop->name16 = utf16;
prop->name16len = utf16len;
prop->length = datalen;
prop->data = grub_malloc (prop->length);
if (!prop->data)
{
grub_free (prop);
grub_free (prop->name);
grub_free (prop->name16);
return grub_errno;
}
grub_memcpy (prop->data, data, prop->length);
grub_list_push (GRUB_AS_LIST_P (&dev->properties),
GRUB_AS_LIST (prop));
return GRUB_ERR_NONE;
}
grub_err_t
grub_xnu_devprop_add_property_utf8 (struct grub_xnu_devprop_device_descriptor *dev,
char *name, void *data, int datalen)
{
grub_uint8_t *utf8;
grub_uint16_t *utf16;
int len, utf16len;
grub_err_t err;
utf8 = (grub_uint8_t *) grub_strdup (name);
if (!utf8)
return grub_errno;
len = grub_strlen (name);
utf16 = grub_malloc (sizeof (grub_uint16_t) * len);
if (!utf16)
{
grub_free (utf8);
return grub_errno;
}
utf16len = grub_utf8_to_utf16 (utf16, len, utf8, len, NULL);
if (utf16len < 0)
{
grub_free (utf8);
grub_free (utf16);
return grub_errno;
}
err = grub_xnu_devprop_add_property (dev, utf8, utf16,
utf16len, data, datalen);
if (err)
{
grub_free (utf8);
grub_free (utf16);
return err;
}
return GRUB_ERR_NONE;
}
grub_err_t
grub_xnu_devprop_add_property_utf16 (struct grub_xnu_devprop_device_descriptor *dev,
grub_uint16_t *name, int namelen,
void *data, int datalen)
{
grub_uint8_t *utf8;
grub_uint16_t *utf16;
grub_err_t err;
utf16 = grub_malloc (sizeof (grub_uint16_t) * namelen);
if (!utf16)
return grub_errno;
grub_memcpy (utf16, name, sizeof (grub_uint16_t) * namelen);
utf8 = grub_malloc (namelen * 4 + 1);
if (!utf8)
{
grub_free (utf8);
return grub_errno;
}
*grub_utf16_to_utf8 ((grub_uint8_t *) utf8, name, namelen) = '\0';
err = grub_xnu_devprop_add_property (dev, utf8, utf16,
namelen, data, datalen);
if (err)
{
grub_free (utf8);
grub_free (utf16);
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)
{
struct grub_xnu_devprop_device_descriptor *dev1, *dev2;
for (dev1 = devices; dev1; )
{
dev2 = dev1->next;
grub_xnu_devprop_remove_device (dev1);
dev1 = dev2;
}
}
static grub_err_t
grub_cpu_xnu_fill_devprop (void)
{
struct grub_xnu_devtree_key *efikey;
int total_length = sizeof (struct grub_xnu_devprop_header);
struct grub_xnu_devtree_key *devprop;
struct grub_xnu_devprop_device_descriptor *device;
void *ptr;
struct grub_xnu_devprop_header *head;
void *t;
int numdevs = 0;
/* The key "efi". */
efikey = grub_xnu_create_key (&grub_xnu_devtree_root, "efi");
if (! efikey)
return grub_errno;
for (device = devices; device; device = device->next)
{
struct property_descriptor *propdesc;
total_length += sizeof (struct grub_xnu_devprop_device_header);
total_length += device->pathlen;
for (propdesc = device->properties; propdesc; propdesc = propdesc->next)
{
total_length += sizeof (grub_uint32_t);
total_length += sizeof (grub_uint16_t)
* (propdesc->name16len + 1);
total_length += sizeof (grub_uint32_t);
total_length += propdesc->length;
}
numdevs++;
}
devprop = grub_xnu_create_value (&(efikey->first_child), "device-properties");
if (devprop)
{
devprop->data = grub_malloc (total_length);
devprop->datasize = total_length;
}
ptr = devprop->data;
head = ptr;
ptr = head + 1;
head->length = total_length;
head->alwaysone = 1;
head->num_devices = numdevs;
for (device = devices; device; )
{
struct grub_xnu_devprop_device_header *devhead;
struct property_descriptor *propdesc;
devhead = ptr;
devhead->num_values = 0;
ptr = devhead + 1;
grub_memcpy (ptr, device->path, device->pathlen);
ptr = (char *) ptr + device->pathlen;
for (propdesc = device->properties; propdesc; )
{
grub_uint32_t *len;
grub_uint16_t *name;
void *data;
len = ptr;
*len = 2 * propdesc->name16len + sizeof (grub_uint16_t)
+ sizeof (grub_uint32_t);
ptr = len + 1;
name = ptr;
grub_memcpy (name, propdesc->name16, 2 * propdesc->name16len);
name += propdesc->name16len;
/* NUL terminator. */
*name = 0;
ptr = name + 1;
len = ptr;
*len = propdesc->length + sizeof (grub_uint32_t);
data = len + 1;
ptr = data;
grub_memcpy (ptr, propdesc->data, propdesc->length);
ptr = (char *) ptr + propdesc->length;
grub_free (propdesc->name);
grub_free (propdesc->name16);
grub_free (propdesc->data);
t = propdesc;
propdesc = propdesc->next;
grub_free (t);
devhead->num_values++;
}
devhead->length = (char *) ptr - (char *) devhead;
t = device;
device = device->next;
grub_free (t);
}
devices = 0;
return GRUB_ERR_NONE;
}
static grub_err_t
grub_cmd_devprop_load (grub_command_t cmd __attribute__ ((unused)),
int argc, char *args[])
{
grub_file_t file;
void *buf, *bufstart, *bufend;
struct grub_xnu_devprop_header *head;
grub_size_t size;
unsigned i, j;
if (argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "File name required. ");
file = grub_gzfile_open (args[0], 1);
if (! file)
return grub_error (GRUB_ERR_FILE_NOT_FOUND,
"Couldn't load device-propertie dump. ");
size = grub_file_size (file);
buf = grub_malloc (size);
if (!buf)
{
grub_file_close (file);
return grub_errno;
}
if (grub_file_read (file, buf, size) != (grub_ssize_t) size)
{
grub_file_close (file);
return grub_errno;
}
grub_file_close (file);
bufstart = buf;
bufend = (char *) buf + size;
head = buf;
buf = head + 1;
for (i = 0; i < grub_le_to_cpu32 (head->num_devices) && buf < bufend; i++)
{
struct grub_efi_device_path *dp, *dpstart;
struct grub_xnu_devprop_device_descriptor *dev;
struct grub_xnu_devprop_device_header *devhead;
devhead = buf;
buf = devhead + 1;
dpstart = buf;
do
{
dp = buf;
buf = (char *) buf + GRUB_EFI_DEVICE_PATH_LENGTH (dp);
}
while (!GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp) && buf < bufend);
dev = grub_xnu_devprop_add_device (dpstart, (char *) buf
- (char *) dpstart);
for (j = 0; j < grub_le_to_cpu32 (devhead->num_values) && buf < bufend;
j++)
{
grub_uint32_t *namelen;
grub_uint32_t *datalen;
grub_uint16_t *utf16;
void *data;
grub_err_t err;
namelen = buf;
buf = namelen + 1;
if (buf >= bufend)
break;
utf16 = buf;
buf = (char *) buf + *namelen - sizeof (grub_uint32_t);
if (buf >= bufend)
break;
datalen = buf;
buf = datalen + 1;
if (buf >= bufend)
break;
data = buf;
buf = (char *) buf + *datalen - sizeof (grub_uint32_t);
if (buf >= bufend)
break;
err = grub_xnu_devprop_add_property_utf16
(dev, utf16, (*namelen - sizeof (grub_uint32_t)
- sizeof (grub_uint16_t)) / sizeof (grub_uint16_t),
data, *datalen - sizeof (grub_uint32_t));
if (err)
{
grub_free (bufstart);
return err;
}
}
}
grub_free (bufstart);
return GRUB_ERR_NONE;
}
/* Fill device tree. */
/* FIXME: some entries may be platform-agnostic. Move them to loader/xnu.c. */
grub_err_t
@ -216,11 +639,6 @@ grub_cpu_xnu_fill_devicetree (void)
struct grub_xnu_devtree_key *runtimesrvkey;
struct grub_xnu_devtree_key *platformkey;
unsigned i, j;
grub_err_t err;
err = grub_autoefi_prepare ();
if (err)
return err;
/* The value "model". */
/* FIXME: may this value be sometimes different? */
@ -436,6 +854,22 @@ grub_xnu_boot (void)
grub_size_t devtreelen;
int i;
err = grub_autoefi_prepare ();
if (err)
return err;
err = grub_cpu_xnu_fill_devprop ();
if (err)
return err;
err = grub_cpu_xnu_fill_devicetree ();
if (err)
return err;
err = grub_xnu_fill_devicetree ();
if (err)
return err;
/* Page-align to avoid following parts to be inadvertently freed. */
err = grub_xnu_align_heap (GRUB_XNU_PAGESIZE);
if (err)
@ -590,3 +1024,19 @@ grub_xnu_boot (void)
/* Never reaches here. */
return 0;
}
static grub_command_t cmd_devprop_load;
void
grub_cpu_xnu_init (void)
{
cmd_devprop_load = grub_register_command ("xnu_devprop_load",
grub_cmd_devprop_load,
0, "Load device-properties dump.");
}
void
grub_cpu_xnu_fini (void)
{
grub_unregister_command (cmd_devprop_load);
}

View file

@ -31,7 +31,7 @@ SUFFIX (grub_macho_parse) (grub_macho_t macho)
}
if (head.magic != GRUB_MACHO_MAGIC)
{
grub_error (GRUB_ERR_BAD_OS, "Invalid Mach-O " XX "-bit header.");
grub_error (GRUB_ERR_BAD_OS, "Invalid Mach-O 32-bit header.");
macho->offsetXX = -1;
return;
}
@ -94,7 +94,7 @@ SUFFIX (grub_macho_readfile) (grub_macho_t macho, void *dest)
return grub_error (GRUB_ERR_BAD_OS,
"Couldn't read architecture-specific part");
if (grub_file_seek (macho->file, macho->offsetXX) == (grub_off_t) -1)
if (grub_file_seek (macho->file, macho->offset32) == (grub_off_t) -1)
{
grub_error_push ();
return grub_error (GRUB_ERR_BAD_OS,
@ -102,8 +102,8 @@ SUFFIX (grub_macho_readfile) (grub_macho_t macho, void *dest)
}
read = grub_file_read (macho->file, dest,
macho->endXX - macho->offsetXX);
if (read != (grub_ssize_t) (macho->endXX - macho->offsetXX))
macho->end32 - macho->offset32);
if (read != (grub_ssize_t) (macho->end32 - macho->offset32))
{
grub_error_push ();
return grub_error (GRUB_ERR_BAD_OS,

View file

@ -31,6 +31,7 @@
#include <grub/gzio.h>
#include <grub/command.h>
#include <grub/misc.h>
#include <grub/env.h>
struct grub_xnu_devtree_key *grub_xnu_devtree_root = 0;
static int driverspackagenum = 0;
@ -334,6 +335,8 @@ grub_xnu_create_value (struct grub_xnu_devtree_key **parent, char *name)
static grub_err_t
grub_xnu_unload (void)
{
grub_cpu_xnu_unload ();
grub_xnu_free_devtree (grub_xnu_devtree_root);
grub_xnu_devtree_root = 0;
@ -437,10 +440,6 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)),
if (ptr != grub_xnu_cmdline)
*(ptr - 1) = 0;
err = grub_cpu_xnu_fill_devicetree ();
if (err)
return err;
grub_loader_set (grub_xnu_boot, grub_xnu_unload, 0);
grub_xnu_lock ();
@ -542,10 +541,6 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)),
if (ptr != grub_xnu_cmdline)
*(ptr - 1) = 0;
err = grub_cpu_xnu_fill_devicetree ();
if (err)
return err;
grub_loader_set (grub_xnu_boot, grub_xnu_unload, 0);
grub_xnu_lock ();
@ -907,135 +902,6 @@ grub_cmd_xnu_ramdisk (grub_command_t cmd __attribute__ ((unused)),
return grub_xnu_register_memory ("RAMDisk", 0, loadto, size);
}
/* Parse a devtree file. It uses the following format:
valuename:valuedata;
keyname{
contents
}
keyname, valuename and valuedata are in hex.
*/
static char *
grub_xnu_parse_devtree (struct grub_xnu_devtree_key **parent,
char *start, char *end)
{
char *ptr, *ptr2;
char *name, *data;
int namelen, datalen, i;
for (ptr = start; ptr && ptr < end; )
{
if (grub_isspace (*ptr))
{
ptr++;
continue;
}
if (*ptr == '}')
return ptr + 1;
namelen = 0;
/* Parse the name. */
for (ptr2 = ptr; ptr2 < end && (grub_isspace (*ptr2)
|| (*ptr2 >= '0' && *ptr2 <= '9')
|| (*ptr2 >= 'a' && *ptr2 <= 'f')
|| (*ptr2 >= 'A' && *ptr2 <= 'F'));
ptr2++)
if (! grub_isspace (*ptr2))
namelen++;
if (ptr2 == end)
return 0;
namelen /= 2;
name = grub_malloc (namelen + 1);
if (!name)
return 0;
for (i = 0; i < 2 * namelen; i++)
{
int hex = 0;
while (grub_isspace (*ptr))
ptr++;
if (*ptr >= '0' && *ptr <= '9')
hex = *ptr - '0';
if (*ptr >= 'a' && *ptr <= 'f')
hex = *ptr - 'a' + 10;
if (*ptr >= 'A' && *ptr <= 'F')
hex = *ptr - 'A' + 10;
if (i % 2 == 0)
name[i / 2] = hex << 4;
else
name[i / 2] |= hex;
ptr++;
}
name [namelen] = 0;
while (grub_isspace (*ptr))
ptr++;
/* If it describes a key recursively invoke the function. */
if (*ptr == '{')
{
struct grub_xnu_devtree_key *newkey
= grub_xnu_create_key (parent, name);
grub_free (name);
if (! newkey)
return 0;
ptr = grub_xnu_parse_devtree (&(newkey->first_child), ptr + 1, end);
continue;
}
/* Parse the data. */
if (*ptr != ':')
return 0;
ptr++;
datalen = 0;
for (ptr2 = ptr; ptr2 < end && (grub_isspace (*ptr2)
|| (*ptr2 >= '0' && *ptr2 <= '9')
|| (*ptr2 >= 'a' && *ptr2 <= 'f')
|| (*ptr2 >= 'A' && *ptr2 <= 'F'));
ptr2++)
if (! grub_isspace (*ptr2))
datalen++;
if (ptr2 == end)
return 0;
datalen /= 2;
data = grub_malloc (datalen);
if (! data)
return 0;
for (i = 0; i < 2 * datalen; i++)
{
int hex = 0;
while (grub_isspace (*ptr))
ptr++;
if (*ptr >= '0' && *ptr <= '9')
hex = *ptr - '0';
if (*ptr >= 'a' && *ptr <= 'f')
hex = *ptr - 'a' + 10;
if (*ptr >= 'A' && *ptr <= 'F')
hex = *ptr - 'A' + 10;
if (i % 2 == 0)
data[i / 2] = hex << 4;
else
data[i / 2] |= hex;
ptr++;
}
while (ptr < end && grub_isspace (*ptr))
ptr++;
{
struct grub_xnu_devtree_key *newkey
= grub_xnu_create_value (parent, name);
grub_free (name);
if (! newkey)
return 0;
newkey->datasize = datalen;
newkey->data = data;
}
if (*ptr != ';')
return 0;
ptr++;
}
if (ptr >= end && *parent != grub_xnu_devtree_root)
return 0;
return ptr;
}
/* Returns true if the kext should be loaded according to plist
and osbundlereq. Also fill BINNAME. */
static int
@ -1332,53 +1198,6 @@ grub_xnu_load_kext_from_dir (char *dirname, char *osbundlerequired,
return GRUB_ERR_NONE;
}
/* Load devtree file. */
static grub_err_t
grub_cmd_xnu_devtree (grub_command_t cmd __attribute__ ((unused)),
int argc, char *args[])
{
grub_file_t file;
char *data, *endret;
grub_size_t datalen;
if (argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Filename required");
if (! grub_xnu_heap_size)
return grub_error (GRUB_ERR_BAD_OS, "no xnu kernel loaded");
/* Load the file. */
file = grub_gzfile_open (args[0], 1);
if (! file)
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load device tree");
datalen = grub_file_size (file);
data = grub_malloc (datalen + 1);
if (! data)
{
grub_file_close (file);
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"Could load device tree into memory");
}
if (grub_file_read (file, data, datalen) != (grub_ssize_t) datalen)
{
grub_file_close (file);
grub_free (data);
grub_error_push ();
return grub_error (GRUB_ERR_BAD_OS, "Couldn't read file %s", args[0]);
}
grub_file_close (file);
data[datalen] = 0;
/* Parse the file. */
endret = grub_xnu_parse_devtree (&grub_xnu_devtree_root,
data, data + datalen);
grub_free (data);
if (! endret)
return grub_error (GRUB_ERR_BAD_OS, "Couldn't parse devtree");
return GRUB_ERR_NONE;
}
static int locked=0;
static grub_dl_t my_mod;
@ -1439,6 +1258,107 @@ grub_cmd_xnu_kextdir (grub_command_t cmd __attribute__ ((unused)),
}
}
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;
}
static inline void
unescape (char *name, char *curdot, char *nextdot, int *len)
{
char *ptr, *dptr;
dptr = name;
for (ptr = curdot; ptr < nextdot;)
if (ptr + 2 < nextdot && *ptr == '%')
{
*dptr = (hextoval (ptr[1]) << 4) | (hextoval (ptr[2]));
ptr += 3;
dptr++;
}
else
{
*dptr = *ptr;
ptr++;
dptr++;
}
*len = dptr - name;
}
grub_err_t
grub_xnu_fill_devicetree (void)
{
auto int iterate_env (struct grub_env_var *var);
int iterate_env (struct grub_env_var *var)
{
char *nextdot = 0, *curdot;
struct grub_xnu_devtree_key **curkey = &grub_xnu_devtree_root;
struct grub_xnu_devtree_key *curvalue;
char *name = 0, *data;
int len;
if (grub_memcmp (var->name, "XNU.DeviceTree.",
sizeof ("XNU.DeviceTree.") - 1) != 0)
return 0;
curdot = var->name + sizeof ("XNU.DeviceTree.") - 1;
nextdot = grub_strchr (curdot, '.');
if (nextdot)
nextdot++;
while (nextdot)
{
name = grub_realloc (name, nextdot - curdot + 1);
if (!name)
return 1;
unescape (name, curdot, nextdot, &len);
name[len - 1] = 0;
curkey = &(grub_xnu_create_key (curkey, name)->first_child);
curdot = nextdot;
nextdot = grub_strchr (nextdot, '.');
if (nextdot)
nextdot++;
}
nextdot = curdot + grub_strlen (curdot) + 1;
name = grub_realloc (name, nextdot - curdot + 1);
if (!name)
return 1;
unescape (name, curdot, nextdot, &len);
name[len] = 0;
curvalue = grub_xnu_create_value (curkey, name);
grub_free (name);
data = grub_malloc (grub_strlen (var->value) + 1);
if (!data)
return 1;
unescape (data, var->value, var->value + grub_strlen (var->value),
&len);
curvalue->datasize = len;
curvalue->data = data;
return 0;
}
grub_env_iterate (iterate_env);
return grub_errno;
}
struct grub_video_bitmap *grub_xnu_bitmap = 0;
static grub_err_t
@ -1485,8 +1405,7 @@ grub_xnu_unlock ()
}
static grub_command_t cmd_kernel64, cmd_kernel, cmd_mkext, cmd_kext;
static grub_command_t cmd_kextdir, cmd_ramdisk, cmd_devtree, cmd_resume;
static grub_command_t cmd_splash;
static grub_command_t cmd_kextdir, cmd_ramdisk, cmd_resume, cmd_splash;
GRUB_MOD_INIT(xnu)
{
@ -1504,8 +1423,6 @@ GRUB_MOD_INIT(xnu)
cmd_ramdisk = grub_register_command ("xnu_ramdisk", grub_cmd_xnu_ramdisk, 0,
"Load XNU ramdisk. "
"It will be seen as md0");
cmd_devtree = grub_register_command ("xnu_devtree", grub_cmd_xnu_devtree, 0,
"Load XNU devtree");
cmd_splash = grub_register_command ("xnu_splash", grub_cmd_xnu_splash, 0,
"Load a splash image for XNU");
@ -1513,7 +1430,10 @@ GRUB_MOD_INIT(xnu)
cmd_resume = grub_register_command ("xnu_resume", grub_cmd_xnu_resume,
0, "Load XNU hibernate image.");
#endif
my_mod=mod;
grub_cpu_xnu_init ();
my_mod = mod;
}
GRUB_MOD_FINI(xnu)
@ -1524,9 +1444,10 @@ GRUB_MOD_FINI(xnu)
grub_unregister_command (cmd_mkext);
grub_unregister_command (cmd_kext);
grub_unregister_command (cmd_kextdir);
grub_unregister_command (cmd_devtree);
grub_unregister_command (cmd_ramdisk);
grub_unregister_command (cmd_kernel);
grub_unregister_command (cmd_kernel64);
grub_unregister_command (cmd_splash);
grub_cpu_xnu_fini ();
}

View file

@ -161,14 +161,23 @@ iterate_dev (const char *devname)
if (dev)
{
if (dev->disk && dev->disk->has_partitions)
char tmp[grub_strlen (devname) + sizeof (",")];
grub_memcpy (tmp, devname, grub_strlen (devname));
if (grub_strcmp (devname, current_word) == 0)
{
if (add_completion (devname, ",", GRUB_COMPLETION_TYPE_DEVICE))
if (add_completion (devname, ")", GRUB_COMPLETION_TYPE_PARTITION))
return 1;
if (dev->disk)
if (grub_partition_iterate (dev->disk, iterate_partition))
return 1;
}
else
{
if (add_completion (devname, ")", GRUB_COMPLETION_TYPE_DEVICE))
grub_memcpy (tmp + grub_strlen (devname), "", sizeof (""));
if (add_completion (tmp, "", GRUB_COMPLETION_TYPE_DEVICE))
return 1;
}
}
@ -216,7 +225,7 @@ complete_device (void)
if (dev)
{
if (dev->disk && dev->disk->has_partitions)
if (dev->disk)
{
if (grub_partition_iterate (dev->disk, iterate_partition))
{

View file

@ -94,10 +94,8 @@ grub_normal_print_device_info (const char *name)
grub_errno = GRUB_ERR_NONE;
}
}
else if (! dev->disk->has_partitions || dev->disk->partition)
grub_printf ("Unknown filesystem");
else
grub_printf ("Partition table");
grub_printf ("Unknown filesystem");
grub_device_close (dev);
}

View file

@ -1,25 +0,0 @@
#!/bin/sh
#
# Copyright (C) 2009 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/>.
hexify()
{
echo -n "$@" | od -A n -t x1 - | sed -e 's/ //g' | tr '\n' '\0'
}
echo "`hexify efi`{ `hexify device-properties`:"
ioreg -lw0 -p IODeviceTree -n efi -r -x |grep device-properties | sed 's/.*<//;s/>.*//;'
echo ";}"