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.
* 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
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)
{
#include <grub/types.h>
#include <grub/misc.h>
+#include <grub/charset.h>
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/dl.h>
"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
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)
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
}
efiemu_prepare_hooks = 0;
+ prepared = 0;
+
return GRUB_ERR_NONE;
}
{
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
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",
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)
grub_unregister_command (cmd_loadcore);
grub_unregister_command (cmd_prepare);
grub_unregister_command (cmd_unload);
- grub_efiemu_pnvram_cmd_unregister ();
}
#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>
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);
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)
+grub_err_t
+grub_efiemu_pnvram (void)
{
- 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++;
+ const char *size;
+ grub_err_t err;
- /* 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;
-}
+ nvramsize = 0;
-static grub_err_t
-grub_efiemu_make_nvram (void)
-{
- grub_err_t err;
+ size = grub_env_get ("EfiEmu.pnvram.size");
+ if (size)
+ nvramsize = grub_strtoul (size, 0, 0);
- err = grub_efiemu_autocore ();
- if (err)
- {
- grub_free (nvram);
- return err;
- }
+ 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);
= 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);
-}
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/dl.h>
+#include <grub/charset.h>
#define GRUB_FAT_DIR_ENTRY_SIZE 32
#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
disk->total_sectors = 0;
disk->id = (unsigned long) "pxe";
- disk->has_partitions = 0;
disk->data = 0;
return GRUB_ERR_NONE;
#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
#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
#include <grub/dl.h>
#include <grub/fshelp.h>
#include <grub/ntfs.h>
+#include <grub/charset.h>
static grub_dl_t my_mod;
--- /dev/null
+/*
+ * 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
#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;
#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[];
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,
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);
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;
*/
#include <grub/misc.h>
+#include <grub/charset.h>
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
#include <grub/efi/console_control.h>
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
--- /dev/null
+/*
+ * 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;
+}
#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>
#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];
{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
((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
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? */
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)
/* 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);
+}
}
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;
}
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,
}
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,
#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;
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;
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 ();
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 ();
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
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;
}
}
+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
}
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)
{
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");
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)
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 ();
}
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;
}
}
if (dev)
{
- if (dev->disk && dev->disk->has_partitions)
+ if (dev->disk)
{
if (grub_partition_iterate (dev->disk, iterate_partition))
{
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);
}
+++ /dev/null
-#!/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 ";}"