]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Manually reimported XNU branch
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 9 Nov 2009 17:43:53 +0000 (18:43 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 9 Nov 2009 17:43:53 +0000 (18:43 +0100)
29 files changed:
ChangeLog
autogen.sh [changed mode: 0644->0755]
bus/usb/usb.c
commands/usbtest.c
conf/common.rmk
efiemu/main.c
efiemu/pnvram.c
fs/fat.c
fs/hfsplus.c
fs/i386/pc/pxe.c
fs/iso9660.c
fs/jfs.c
fs/ntfs.c
gendistlist.sh [changed mode: 0644->0755]
include/grub/charset.h [new file with mode: 0644]
include/grub/i386/xnu.h
include/grub/misc.h
include/grub/usb.h
include/grub/xnu.h
kern/efi/efi.c
kern/misc.c
lib/charset.c [new file with mode: 0644]
loader/efi/chainloader.c
loader/i386/xnu.c
loader/machoXX.c
loader/xnu.c
normal/completion.c
normal/misc.c
util/i386/efi/grub-dumpdevtree [deleted file]

index ea21457705e6d5ed7d7e73cf56aaee58bc017fc3..3aecde16f52e0d40bd0458a6b9494fa149145172 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 
 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
old mode 100644 (file)
new mode 100755 (executable)
index 310b8cc6a97564bfa2758f292c3034f6beff6cec..8289185da67da45cf6df8ddb6d561768d7247bc3 100644 (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)
 {
index 018c1a25bb63f4375d9f3e4af907084972085adf..3405c3b4dc0ee50bb67af900653a11eacf38eaf8 100644 (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
index c1f0bbdcf6a83d4082626da3b6e43b53517edcc2..99af0662a8a00842d5b69beb246725c0ebe13f2a 100644 (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)
index b5608e666bccfab8b4e8ccc2716eec78a785d65e..05787284d009bd972105c6f3579db9961a73c7bc 100644 (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 ();
 }
index 04ad6e28433775a83e14ee6271ae7b20e02d9f8a..ede59ede106efc8457af5e8d93a55e814ef23507 100644 (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)
+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);
@@ -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);
-}
index e7f01629e4721ba81c6633e6e27db97fedcc6008..ab84ee49a727ea88db405f1e4b6674709e3e6eb0 100644 (file)
--- a/fs/fat.c
+++ b/fs/fat.c
@@ -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
 
index b306e8d6a8953786e44b795a3db7899cd6d3b439..71910330f004185cc5a53d8b15281838a28a8353 100644 (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
index 4032e12542455085e05451876821bc605a34c41b..1a99ad466fa45fab1696a1fa67bf8150deba9714 100644 (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;
index 9b7ce765b32b9e7416029c8e8bc7364873642946..976222a4581b4efccc8eeba56cbeade54695f6fb 100644 (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
index b73f9bdd47065093dd7cca4b3bf5304397fed9f1..589b6ae5ac43c0132f4a2752a45d92b3eafb7612 100644 (file)
--- a/fs/jfs.c
+++ b/fs/jfs.c
@@ -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
index 163f3e0a83aa83a591c3cfaa73efaec5d57e5c29..495cdd1593a16d5e0e480af83ad16fb57baefccb 100644 (file)
--- a/fs/ntfs.c
+++ b/fs/ntfs.c
@@ -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;
 
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/include/grub/charset.h b/include/grub/charset.h
new file mode 100644 (file)
index 0000000..f85862f
--- /dev/null
@@ -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
index 57ba0f0b6fbc5cdcab144f58ff0587012c5bfc0f..a05d67fc34a5f2bcef3ff00b0d2480fd83572b8b 100644 (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[];
index faa2d5c42ad9c1d3c7cb57979dd347793df969f7..1939becbd0816033ebe22dcc69e6e1fc9e551147 100644 (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,
index 8dd3b6e2ec8d03d1807a1cb7e50bd0b9a49e968f..dc90e787921dc268cc77726f1d4a4cb3db97f398 100644 (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);
index 29689479b6be784cfdb93f52c37b7b0a7e34acef..b0146728c5b32655398099c9fee33b7a9681d026 100644 (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;
index 279d1d61b8b37a260ba18102722b65583bf6c2af..501ab45780253be100c3fc64e1db2d602737023a 100644 (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>
index cacfbc7532416d6e6048b75ad80ac061c128c2ba..a1a998eeb32681b9968364a7e8bcdd88fc62b2fc 100644 (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
diff --git a/lib/charset.c b/lib/charset.c
new file mode 100644 (file)
index 0000000..8bc5b91
--- /dev/null
@@ -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;
+}
index 01acc41352a7e2860cc019f3ca56b6eb46b895a6..9c833e9b92f0dee08ceb9522b90373342e9f4b7e 100644 (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>
index 35f2beb23c2a7f619adb13079aeef18718683112..857d6b63cb640f858ce203d54ab4dd4c1e6073a8 100644 (file)
 #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);
+}
index d42dd8b55f4928b796cfbc2434744ba3c6d0e239..01e6879ea76fa37c70b66e7f74a62bbe4e092292 100644 (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,
index 2ebca321807ea2c59ec9e2d5474e34d79a20721f..523443a1ca2303fe284aa46a8538eafbc057887a 100644 (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 ();
 }
index 4b38e334debd69b89b6242ab59c055032a09d59f..7b3de449c7582ba7479d2ddcbc01e72bd965cc82 100644 (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))
                {
index 0a1a2f052de3b03cf13bdc533be211b39425ce95..cddd1d3d3218f46055c68472d56afb4a81338f58 100644 (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);
     }
diff --git a/util/i386/efi/grub-dumpdevtree b/util/i386/efi/grub-dumpdevtree
deleted file mode 100644 (file)
index bc13e3c..0000000
+++ /dev/null
@@ -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 ";}"