Splitted. Another split part is in thread UTF-8 to UTF-16

On Sun, Aug 23, 2009 at 1:11 PM, Vladimir 'phcoder'
Serbinenko<phco...@gmail.com> wrote:
> On Sun, Aug 23, 2009 at 12:57 PM, Robert Millan<r...@aybabtu.com> wrote:
>> On Sat, Aug 22, 2009 at 04:33:13PM +0200, Vladimir 'phcoder' Serbinenko 
>> wrote:
>>> [...]
>>> +
>>> +pkglib_MODULES += utf.mod
>>> +utf_mod_SOURCES = lib/utf.c
>>> +utf_mod_CFLAGS = $(COMMON_CFLAGS)
>>> +utf_mod_LDFLAGS = $(COMMON_LDFLAGS)
>>> [...]
>>> +#include <grub/utf.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)
>>> +{
>>
>> This was moved from another file, right?  Please could you send it as a
>> separate patch?
> Nope, it's a new function. But I'm ok with splitting patches.
>>
>> Also, please remember to include a ChangeLog entry.
>>
>> --
>> Robert Millan
>>
>>  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
>>  how) you may access your data; but nobody's threatening your freedom: we
>>  still allow you to remove your data and not access it at all."
>>
>>
>> _______________________________________________
>> Grub-devel mailing list
>> Grub-devel@gnu.org
>> http://lists.gnu.org/mailman/listinfo/grub-devel
>>
>
>
>
> --
> Regards
> Vladimir 'phcoder' Serbinenko
>
> Personal git repository: http://repo.or.cz/w/grub2/phcoder.git
>



-- 
Regards
Vladimir 'phcoder' Serbinenko

Personal git repository: http://repo.or.cz/w/grub2/phcoder.git
diff --git a/ChangeLog b/ChangeLog
index aa2b0f5..50c48e6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,23 @@
 2009-08-24  Vladimir Serbinenko  <phco...@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  <phco...@gmail.com>
+
        UTF-8 to UTF-16 transformation.
 
        * conf/common.rmk (pkglib_MODULES): Add utf.mod
diff --git a/efiemu/main.c b/efiemu/main.c
index b5608e6..25d449c 100644
--- a/efiemu/main.c
+++ b/efiemu/main.c
@@ -282,7 +282,7 @@ grub_efiemu_prepare (void)
 
   err = grub_efiemu_autocore ();
 
-  /* Create NVRAM if not yet done. */
+  /* Create NVRAM. */
   grub_efiemu_pnvram ();
 
   if (grub_efiemu_sizeof_uintn_t () == 4)
@@ -316,9 +316,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 +329,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 +336,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 ();
 }
diff --git a/efiemu/pnvram.c b/efiemu/pnvram.c
index 04ad6e2..8e2c4aa 100644
--- a/efiemu/pnvram.c
+++ b/efiemu/pnvram.c
@@ -18,6 +18,7 @@
  */
 
 #include <grub/file.h>
+#include <grub/utf.h>
 #include <grub/err.h>
 #include <grub/normal.h>
 #include <grub/mm.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);
@@ -326,75 +276,3 @@ grub_efiemu_make_nvram (void)
   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);
-}
diff --git a/include/grub/xnu.h b/include/grub/xnu.h
index c3902e6..2abafac 100644
--- a/include/grub/xnu.h
+++ b/include/grub/xnu.h
@@ -100,6 +100,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;
diff --git a/loader/i386/xnu.c b/loader/i386/xnu.c
index 06e375c..686634b 100644
--- a/loader/i386/xnu.c
+++ b/loader/i386/xnu.c
@@ -439,6 +439,14 @@ grub_xnu_boot (void)
   grub_size_t devtreelen;
   int i;
 
+  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)
diff --git a/loader/xnu.c b/loader/xnu.c
index aac4ae3..87574fd 100644
--- a/loader/xnu.c
+++ b/loader/xnu.c
@@ -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;
@@ -436,10 +437,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 ();
@@ -739,135 +736,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
@@ -1164,53 +1032,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;
@@ -1271,6 +1092,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
@@ -1317,7 +1239,7 @@ grub_xnu_unlock ()
 }
 
 static grub_command_t cmd_kernel, cmd_mkext, cmd_kext, cmd_kextdir,
-  cmd_ramdisk, cmd_devtree, cmd_resume, cmd_splash;
+  cmd_ramdisk, cmd_resume, cmd_splash;
 
 GRUB_MOD_INIT(xnu)
 {
@@ -1333,8 +1255,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");
 
@@ -1353,7 +1273,6 @@ 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_splash);
diff --git a/util/i386/efi/grub-dumpdevtree b/util/i386/efi/grub-dumpdevtree
index bc13e3c..ce46f55 100644
--- a/util/i386/efi/grub-dumpdevtree
+++ b/util/i386/efi/grub-dumpdevtree
@@ -15,11 +15,9 @@
 # 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'
-}
+string=`ioreg -lw0 -p IODeviceTree -n efi -r -x |grep device-properties | sed 
's/.*<//;s/>.*//;'`
+astring=;
+l=0
+while [ "x${string:l:2}" != x ]; do astring="$astring%${string:l:2}"; 
l=$((l+2)); done
 
-echo "`hexify efi`{    `hexify device-properties`:"
-ioreg -lw0 -p IODeviceTree -n efi -r -x |grep device-properties | sed 
's/.*<//;s/>.*//;'
-echo ";}"
+echo "set XNU.DeviceTree.efi.device-properties=$astring"
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to