All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] hfs+ uuid
@ 2009-05-03 10:42 Vladimir 'phcoder' Serbinenko
  2009-05-03 16:55 ` Pavel Roskin
  0 siblings, 1 reply; 11+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-05-03 10:42 UTC (permalink / raw)
  To: The development of GRUB 2


[-- Attachment #1.1: Type: text/plain, Size: 242 bytes --]

This is a patch to support UUIDs on HFS+. MD5 code is copied from Michael
Gorven's patch which is copied from libgcrypt nearly verbatim. Thanks for
Cris for the info about how xnu expects UUID to be

-- 
Regards
Vladimir 'phcoder' Serbinenko

[-- Attachment #1.2: Type: text/html, Size: 283 bytes --]

[-- Attachment #2: hfspuuid.diff --]
[-- Type: text/x-diff, Size: 16025 bytes --]

diff --git a/commands/xnu_uuid.c b/commands/xnu_uuid.c
new file mode 100644
index 0000000..10429d1
--- /dev/null
+++ b/commands/xnu_uuid.c
@@ -0,0 +1,436 @@
+/* xnu_uuid.c - transform 64-bit serial number 
+   to 128-bit uuid suitable for xnu. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1995,1996,1998,1999,2001,2002,
+ *                2003, 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/>.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/device.h>
+#include <grub/disk.h>
+#include <grub/fs.h>
+#include <grub/file.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+#include <grub/command.h>
+
+struct tohash
+{
+  grub_uint8_t prefix[16];
+  grub_uint64_t serial;
+} __attribute__ ((packed));
+
+/* This prefix is used by xnu and boot-132 to hash 
+   together with volume serial. */
+static grub_uint8_t hash_prefix[16] 
+  = {0xB3, 0xE2, 0x0F, 0x39, 0xF2, 0x92, 0x11, 0xD6, 
+     0x97, 0xA4, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC};
+
+#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
+#define ror(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) )
+
+typedef struct {
+  grub_uint32_t A,B,C,D;	  /* chaining variables */
+  grub_uint32_t  nblocks;
+  grub_uint8_t buf[64];
+  int  count;
+} MD5_CONTEXT;
+
+static void
+md5_init( void *context )
+{
+  MD5_CONTEXT *ctx = context;
+
+  ctx->A = 0x67452301;
+  ctx->B = 0xefcdab89;
+  ctx->C = 0x98badcfe;
+  ctx->D = 0x10325476;
+
+  ctx->nblocks = 0;
+  ctx->count = 0;
+}
+
+/* These are the four functions used in the four steps of the MD5 algorithm
+   and defined in the RFC 1321.  The first function is a little bit optimized
+   (as found in Colin Plumbs public domain implementation).  */
+/* #define FF(b, c, d) ((b & c) | (~b & d)) */
+#define FF(b, c, d) (d ^ (b & (c ^ d)))
+#define FG(b, c, d) FF (d, b, c)
+#define FH(b, c, d) (b ^ c ^ d)
+#define FI(b, c, d) (c ^ (b | ~d))
+
+
+/****************
+ * transform n*64 grub_uint8_ts
+ */
+static void
+transform ( MD5_CONTEXT *ctx, const unsigned char *data )
+{
+  grub_uint32_t correct_words[16];
+  register grub_uint32_t A = ctx->A;
+  register grub_uint32_t B = ctx->B;
+  register grub_uint32_t C = ctx->C;
+  register grub_uint32_t D = ctx->D;
+  grub_uint32_t *cwp = correct_words;
+
+#ifdef WORDS_BIGENDIAN
+  { 
+    int i;
+    grub_uint8_t *p2, *p1;
+    for(i=0, p1=data, p2=(grub_uint8_t*)correct_words; i < 16; i++, p2 += 4 )
+    {
+      p2[3] = *p1++;
+      p2[2] = *p1++;
+      p2[1] = *p1++;
+      p2[0] = *p1++;
+    }
+  }
+#else
+  memcpy( correct_words, data, 64 );
+#endif
+
+#define OP(a, b, c, d, s, T) \
+  do			         	   \
+  {					   \
+    a += FF (b, c, d) + (*cwp++) + T;    \
+    a = rol(a, s);			   \
+    a += b;				   \
+  }					   \
+  while (0)
+
+  /* Before we start, one word about the strange constants.
+     They are defined in RFC 1321 as
+
+     T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
+     */
+
+  /* Round 1.  */
+  OP (A, B, C, D,  7, 0xd76aa478);
+  OP (D, A, B, C, 12, 0xe8c7b756);
+  OP (C, D, A, B, 17, 0x242070db);
+  OP (B, C, D, A, 22, 0xc1bdceee);
+  OP (A, B, C, D,  7, 0xf57c0faf);
+  OP (D, A, B, C, 12, 0x4787c62a);
+  OP (C, D, A, B, 17, 0xa8304613);
+  OP (B, C, D, A, 22, 0xfd469501);
+  OP (A, B, C, D,  7, 0x698098d8);
+  OP (D, A, B, C, 12, 0x8b44f7af);
+  OP (C, D, A, B, 17, 0xffff5bb1);
+  OP (B, C, D, A, 22, 0x895cd7be);
+  OP (A, B, C, D,  7, 0x6b901122);
+  OP (D, A, B, C, 12, 0xfd987193);
+  OP (C, D, A, B, 17, 0xa679438e);
+  OP (B, C, D, A, 22, 0x49b40821);
+
+#undef OP
+#define OP(f, a, b, c, d, k, s, T)  \
+  do								      \
+  { 							      \
+    a += f (b, c, d) + correct_words[k] + T;		      \
+    a = rol(a, s);						      \
+    a += b; 						      \
+  } 							      \
+  while (0)
+
+  /* Round 2.  */
+  OP (FG, A, B, C, D,  1,  5, 0xf61e2562);
+  OP (FG, D, A, B, C,  6,  9, 0xc040b340);
+  OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
+  OP (FG, B, C, D, A,  0, 20, 0xe9b6c7aa);
+  OP (FG, A, B, C, D,  5,  5, 0xd62f105d);
+  OP (FG, D, A, B, C, 10,  9, 0x02441453);
+  OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
+  OP (FG, B, C, D, A,  4, 20, 0xe7d3fbc8);
+  OP (FG, A, B, C, D,  9,  5, 0x21e1cde6);
+  OP (FG, D, A, B, C, 14,  9, 0xc33707d6);
+  OP (FG, C, D, A, B,  3, 14, 0xf4d50d87);
+  OP (FG, B, C, D, A,  8, 20, 0x455a14ed);
+  OP (FG, A, B, C, D, 13,  5, 0xa9e3e905);
+  OP (FG, D, A, B, C,  2,  9, 0xfcefa3f8);
+  OP (FG, C, D, A, B,  7, 14, 0x676f02d9);
+  OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
+
+  /* Round 3.  */
+  OP (FH, A, B, C, D,  5,  4, 0xfffa3942);
+  OP (FH, D, A, B, C,  8, 11, 0x8771f681);
+  OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
+  OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
+  OP (FH, A, B, C, D,  1,  4, 0xa4beea44);
+  OP (FH, D, A, B, C,  4, 11, 0x4bdecfa9);
+  OP (FH, C, D, A, B,  7, 16, 0xf6bb4b60);
+  OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
+  OP (FH, A, B, C, D, 13,  4, 0x289b7ec6);
+  OP (FH, D, A, B, C,  0, 11, 0xeaa127fa);
+  OP (FH, C, D, A, B,  3, 16, 0xd4ef3085);
+  OP (FH, B, C, D, A,  6, 23, 0x04881d05);
+  OP (FH, A, B, C, D,  9,  4, 0xd9d4d039);
+  OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
+  OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
+  OP (FH, B, C, D, A,  2, 23, 0xc4ac5665);
+
+  /* Round 4.  */
+  OP (FI, A, B, C, D,  0,  6, 0xf4292244);
+  OP (FI, D, A, B, C,  7, 10, 0x432aff97);
+  OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
+  OP (FI, B, C, D, A,  5, 21, 0xfc93a039);
+  OP (FI, A, B, C, D, 12,  6, 0x655b59c3);
+  OP (FI, D, A, B, C,  3, 10, 0x8f0ccc92);
+  OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
+  OP (FI, B, C, D, A,  1, 21, 0x85845dd1);
+  OP (FI, A, B, C, D,  8,  6, 0x6fa87e4f);
+  OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
+  OP (FI, C, D, A, B,  6, 15, 0xa3014314);
+  OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
+  OP (FI, A, B, C, D,  4,  6, 0xf7537e82);
+  OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
+  OP (FI, C, D, A, B,  2, 15, 0x2ad7d2bb);
+  OP (FI, B, C, D, A,  9, 21, 0xeb86d391);
+
+  /* Put checksum in context given as argument.  */
+  ctx->A += A;
+  ctx->B += B;
+  ctx->C += C;
+  ctx->D += D;
+}
+
+/* The routine updates the message-digest context to
+ * account for the presence of each of the characters inBuf[0..inLen-1]
+ * in the message whose digest is being computed.
+ */
+static void
+md5_write( void *context, const void *inbuf_arg , grub_size_t inlen)
+{
+  const unsigned char *inbuf = inbuf_arg;
+  MD5_CONTEXT *hd = context;
+
+  if( hd->count == 64 )  /* flush the buffer */
+  {
+    transform( hd, hd->buf );
+    //      _gcry_burn_stack (80+6*sizeof(void*));
+    hd->count = 0;
+    hd->nblocks++;
+  }
+  if( !inbuf )
+    return;
+
+  if( hd->count )
+  {
+    for( ; inlen && hd->count < 64; inlen-- )
+      hd->buf[hd->count++] = *inbuf++;
+    md5_write( hd, NULL, 0 );
+    if( !inlen )
+      return;
+  }
+  //  _gcry_burn_stack (80+6*sizeof(void*));
+
+  while( inlen >= 64 ) 
+  {
+    transform( hd, inbuf );
+    hd->count = 0;
+    hd->nblocks++;
+    inlen -= 64;
+    inbuf += 64;
+  }
+  for( ; inlen && hd->count < 64; inlen-- )
+    hd->buf[hd->count++] = *inbuf++;
+
+}
+
+
+
+/* The routine final terminates the message-digest computation and
+ * ends with the desired message digest in mdContext->digest[0...15].
+ * The handle is prepared for a new MD5 cycle.
+ * Returns 16 grub_uint8_ts representing the digest.
+ */
+static void
+md5_final( void *context)
+{
+  MD5_CONTEXT *hd = context;
+  grub_uint32_t t, msb, lsb;
+  grub_uint8_t *p;
+
+  md5_write(hd, NULL, 0); /* flush */;
+
+  t = hd->nblocks;
+  /* multiply by 64 to make a grub_uint8_t count */
+  lsb = t << 6;
+  msb = t >> 26;
+  /* add the count */
+  t = lsb;
+  if( (lsb += hd->count) < t )
+    msb++;
+  /* multiply by 8 to make a bit count */
+  t = lsb;
+  lsb <<= 3;
+  msb <<= 3;
+  msb |= t >> 29;
+
+  if( hd->count < 56 )  /* enough room */
+  {
+    hd->buf[hd->count++] = 0x80; /* pad */
+    while( hd->count < 56 )
+      hd->buf[hd->count++] = 0;  /* pad */
+  }
+  else  /* need one extra block */
+  {
+    hd->buf[hd->count++] = 0x80; /* pad character */
+    while( hd->count < 64 )
+      hd->buf[hd->count++] = 0;
+    md5_write(hd, NULL, 0);  /* flush */;
+    grub_memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
+  }
+  /* append the 64 bit count */
+  hd->buf[56] = lsb	   ;
+  hd->buf[57] = lsb >>  8;
+  hd->buf[58] = lsb >> 16;
+  hd->buf[59] = lsb >> 24;
+  hd->buf[60] = msb	   ;
+  hd->buf[61] = msb >>  8;
+  hd->buf[62] = msb >> 16;
+  hd->buf[63] = msb >> 24;
+  transform( hd, hd->buf );
+  //  _gcry_burn_stack (80+6*sizeof(void*));
+
+  p = hd->buf;
+#ifdef WORDS_BIGENDIAN
+#define X(a) do { *p++ = hd->a      ; *p++ = hd->a >> 8;      \
+  *p++ = hd->a >> 16; *p++ = hd->a >> 24; } while(0)
+#else /* little endian */
+#define X(a) do { *(grub_uint32_t*)p = (*hd).a ; p += 4; } while(0)
+#endif
+  X(A);
+  X(B);
+  X(C);
+  X(D);
+#undef X
+
+}
+
+/**
+ * GRUB2 Crypto Interface
+ * Written by Michael Gorven
+ */
+static grub_err_t
+md5 (const char *in, grub_size_t insize, char *out)
+{
+  MD5_CONTEXT hd;
+
+  md5_init (&hd);
+  md5_write (&hd, in, insize);
+  md5_final (&hd);
+  grub_memcpy (out, hd.buf, 16);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)),
+		   int argc, char **args)
+
+{  
+  grub_device_t dev;
+  char *uuid, *ptr, *buf;
+  grub_err_t err;
+  struct tohash hashme;
+  grub_uint8_t xnu_uuid[16];
+  grub_fs_t fs;
+  char uuid_string[sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
+  char rd_string[sizeof ("rd=*uuid boot-uuid=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
+
+  if (argc < 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
+
+  ptr = args[0] + grub_strlen (args[0]) - 1;
+  if (args[0][0] == '(' && *ptr == ')')
+    {
+      *ptr = 0;
+      dev = grub_device_open (args[0] + 1);
+      *ptr =')';
+    }
+  else
+    dev = grub_device_open (args[0]);
+  if (! dev)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "couldn't open device");
+  fs = grub_fs_probe (dev);
+  if (! fs)
+    return grub_error (GRUB_ERR_UNKNOWN_FS, "unrecognised fs");
+  if (! fs->uuid)
+    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, 
+		       "uuid for this FS isn't supported yet");
+  err = fs->uuid (dev, &uuid);
+  if (err)
+    return err;
+  if (! uuid)
+    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, 
+		       "uuid for this FS isn't supported yet");
+  hashme.serial = grub_cpu_to_be64 (grub_strtoull (uuid, 0, 16));
+  grub_memcpy (hashme.prefix, hash_prefix, sizeof (hashme.prefix));
+  
+  md5 ((char *) &hashme, sizeof (hashme), (char *) xnu_uuid);
+  xnu_uuid[6] = (xnu_uuid[6] & 0xf) | 0x30;
+  xnu_uuid[8] = (xnu_uuid[8] & 0x3f) | 0x80;
+  grub_sprintf (uuid_string, 
+		"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+		(unsigned int) xnu_uuid[0], (unsigned int) xnu_uuid[1], 
+		(unsigned int) xnu_uuid[2], (unsigned int) xnu_uuid[3],
+		(unsigned int) xnu_uuid[4], (unsigned int) xnu_uuid[5], 
+		(unsigned int) ((xnu_uuid[6] & 0xf) | 0x30),
+		(unsigned int) xnu_uuid[7], 
+		(unsigned int) ((xnu_uuid[8] & 0x3f) | 0x80), 
+		(unsigned int) xnu_uuid[9], 
+		(unsigned int) xnu_uuid[10], (unsigned int) xnu_uuid[11], 
+		(unsigned int) xnu_uuid[12], (unsigned int) xnu_uuid[13], 
+		(unsigned int) xnu_uuid[14], (unsigned int) xnu_uuid[15]);
+  for (ptr = uuid_string; *ptr; ptr++)
+    if (*ptr >= 'a' && *ptr <= 'f')
+      *ptr += 'A' - 'a';
+  grub_sprintf (rd_string, "rd=*uuid boot-uuid=%s", uuid_string);
+  if (argc == 1)
+    grub_printf ("The xnu-uuid of %s is %s\n"
+		 "To use it as a root pass '%s' to the kernel\n",
+		 args[0], uuid_string, rd_string);
+  if (argc > 1)
+    grub_env_set (args[1], uuid_string);
+  if (argc > 2)
+    grub_env_set (args[2], rd_string);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_command_t cmd;
+
+
+GRUB_MOD_INIT(xnu_uuid)
+{
+  (void)mod;			/* To stop warning. */
+  cmd = grub_register_command ("xnu_uuid", grub_cmd_xnu_uuid, 
+			       "xnu_uuid DEVICE [VARNAME]",
+			       "Fetch UUID of partition in format "
+			       "suitable for xnu.");
+}
+
+GRUB_MOD_FINI(xnu_uuid)
+{
+  grub_unregister_command (cmd);
+}
+
+
diff --git a/conf/common.rmk b/conf/common.rmk
index 2335d8f..46c3bcb 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -546,3 +546,11 @@ gzio_mod_LDFLAGS = $(COMMON_LDFLAGS)
 bufio_mod_SOURCES = io/bufio.c
 bufio_mod_CFLAGS = $(COMMON_CFLAGS)
 bufio_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# Misc.
+pkglib_MODULES += xnu_uuid.mod
+
+# For elf.mod.
+xnu_uuid_mod_SOURCES = commands/xnu_uuid.c
+xnu_uuid_mod_CFLAGS = $(COMMON_CFLAGS)
+xnu_uuid_mod_LDFLAGS = $(COMMON_LDFLAGS)
diff --git a/fs/hfsplus.c b/fs/hfsplus.c
index 82ec880..6ca9218 100644
--- a/fs/hfsplus.c
+++ b/fs/hfsplus.c
@@ -61,7 +61,8 @@ struct grub_hfsplus_volheader
   grub_uint32_t utime;
   grub_uint8_t unused2[16];
   grub_uint32_t blksize;
-  grub_uint8_t unused3[68];
+  grub_uint8_t unused3[60];
+  grub_uint64_t num_serial;
   struct grub_hfsplus_forkdata allocations_file;
   struct grub_hfsplus_forkdata extents_file;
   struct grub_hfsplus_forkdata catalog_file;
@@ -983,6 +984,36 @@ grub_hfsplus_mtime (grub_device_t device, grub_int32_t *tm)
 
 }
 
+static grub_err_t
+grub_hfsplus_uuid (grub_device_t device, char **uuid)
+{
+  struct grub_hfsplus_data *data;
+  grub_disk_t disk = device->disk;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_hfsplus_mount (disk);
+  if (data)
+    {
+      *uuid = grub_malloc (16 + sizeof ('\0'));
+      grub_sprintf (*uuid, "%016llx", 
+		    (unsigned long long) 
+		    grub_be_to_cpu64 (data->volheader.num_serial));
+    }
+  else
+    *uuid = NULL;
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  grub_free (data);
+
+  return grub_errno;
+}
+
 
 \f
 static struct grub_fs grub_hfsplus_fs =
@@ -994,6 +1025,7 @@ static struct grub_fs grub_hfsplus_fs =
     .close = grub_hfsplus_close,
     .label = grub_hfsplus_label,
     .mtime = grub_hfsplus_mtime,
+    .uuid = grub_hfsplus_uuid,
     .next = 0
   };
 
diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
index a145277..10e4ea7 100644
--- a/util/grub.d/30_os-prober.in
+++ b/util/grub.d/30_os-prober.in
@@ -83,12 +83,10 @@ EOF
       done
     ;;
     macosx)
-      OSXROOT="`grub-probe --target=drive --device ${DEVICE} 2> /dev/null`"
-      # FIXME: use UUID
-      OSXDISK=disk"`echo ${OSXROOT} | awk -F , '{ print $1 ; }' | sed 's/(hd//;'`"s"`echo ${OSXROOT} | awk -F , '{ print $2 ; }' | sed 's/)//;'`"
+      OSXUUID="`grub-probe --target=fs_uuid --device ${DEVICE} 2> /dev/null`"
         cat << EOF
 menuentry "${LONGNAME} (on ${DEVICE})" {
-	set root=${OSXROOT}
+        search --fs-uuid --set ${OSXUUID}
         insmod vbe
         insmod gfxterm
         gfxmode="1024x768x32;800x600x32"
@@ -100,10 +98,11 @@ menuentry "${LONGNAME} (on ${DEVICE})" {
            fi
         fi
         if [ \$do_resume == 0 ]; then
+           xnu_uuid \$root uuid rdspec
            if [ -f /Extra/DSDT.aml ]; then
               acpi -e /Extra/DSDT.aml
            fi
-           xnu_kernel /mach_kernel rd=$OSXDISK
+           xnu_kernel /mach_kernel \${rdspec}
            if [ /System/Library/Extensions.mkext -nt /System/Library/Extensions ]; then
               xnu_mkext /System/Library/Extensions.mkext
            else

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH] hfs+ uuid
  2009-05-03 10:42 [PATCH] hfs+ uuid Vladimir 'phcoder' Serbinenko
@ 2009-05-03 16:55 ` Pavel Roskin
  2009-05-04 13:08   ` Vladimir 'phcoder' Serbinenko
  2009-06-08 20:50   ` Vladimir 'phcoder' Serbinenko
  0 siblings, 2 replies; 11+ messages in thread
From: Pavel Roskin @ 2009-05-03 16:55 UTC (permalink / raw)
  To: The development of GRUB 2

On Sun, 2009-05-03 at 12:42 +0200, Vladimir 'phcoder' Serbinenko wrote:
> This is a patch to support UUIDs on HFS+. MD5 code is copied from
> Michael Gorven's patch which is copied from libgcrypt nearly verbatim.
> Thanks for Cris for the info about how xnu expects UUID to be

I suggest that you run all new code through GNU indent.  Spacing in
"32-(n)" will probably need to be fixed manually, as it's a preprocessor
directive.

Commented out call to to _gcry_burn_stack() should probably be removed.
I would prefer that we don't use #undef.  Instead, the preprocessor
defines should use unique names that never need to be redefined.

Setting two environment variables is undocumented.  I think rd_string
should not be needed.  If you need it due to the script engine problems,
it's better to fix the script engine.  At least please mark that hack as
a hack.

Perhaps we should consider adding %X support to grub_printf().  I
realize that it will increase the core slightly, but if it's just a few
bytes, we could accept it.  Other modules may use it.  Or maybe we could
have grub_toupper(), perhaps an inline function?

Another thing to consider is whether md5 support should be in a separate
file.  It would make it possible to reuse md5 for other commands.

-- 
Regards,
Pavel Roskin



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] hfs+ uuid
  2009-05-03 16:55 ` Pavel Roskin
@ 2009-05-04 13:08   ` Vladimir 'phcoder' Serbinenko
  2009-05-04 13:22     ` Pavel Roskin
  2009-06-08 20:50   ` Vladimir 'phcoder' Serbinenko
  1 sibling, 1 reply; 11+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-05-04 13:08 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 2131 bytes --]

On Sun, May 3, 2009 at 6:55 PM, Pavel Roskin <proski@gnu.org> wrote:

> On Sun, 2009-05-03 at 12:42 +0200, Vladimir 'phcoder' Serbinenko wrote:
> > This is a patch to support UUIDs on HFS+. MD5 code is copied from
> > Michael Gorven's patch which is copied from libgcrypt nearly verbatim.
> > Thanks for Cris for the info about how xnu expects UUID to be
>
> I suggest that you run all new code through GNU indent.  Spacing in
> "32-(n)" will probably need to be fixed manually, as it's a preprocessor
> directive.
>
> Commented out call to to _gcry_burn_stack() should probably be removed.
> I would prefer that we don't use #undef.  Instead, the preprocessor
> defines should use unique names that never need to be redefined.
>
This part is temporary copied here till Michael Gorven's patch is merged.

>
> Setting two environment variables is undocumented.  I think rd_string
> should not be needed.  If you need it due to the script engine problems,
> it's better to fix the script engine.

I'm looking how to do it. The corresponding part to support foo=$bar  is
here but commented out.

>  At least please mark that hack as
> a hack.
>
> Perhaps we should consider adding %X support to grub_printf().  I
> realize that it will increase the core slightly, but if it's just a few
> bytes, we could accept it.  Other modules may use it.

 Let me think a bit about it. Unfortunately what seems to be few bytes in a
first glance may be up to 100 bytes once implemented

>  Or maybe we could
> have grub_toupper(), perhaps an inline function?
>
If it's an inline then it's ok.

>
> Another thing to consider is whether md5 support should be in a separate
> file.  It would make it possible to reuse md5 for other commands.
>
Actually  md5 is a part of Michael Gorven patch where it's exported nicely
but since his patch is pending I temporary copied it to this file. So I
think it's unnecessary to

>
> --
> Regards,
> Pavel Roskin
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>



-- 
Regards
Vladimir 'phcoder' Serbinenko

[-- Attachment #2: Type: text/html, Size: 3543 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] hfs+ uuid
  2009-05-04 13:08   ` Vladimir 'phcoder' Serbinenko
@ 2009-05-04 13:22     ` Pavel Roskin
  2009-05-04 15:52       ` Vladimir 'phcoder' Serbinenko
  0 siblings, 1 reply; 11+ messages in thread
From: Pavel Roskin @ 2009-05-04 13:22 UTC (permalink / raw)
  To: The development of GRUB 2

On Mon, 2009-05-04 at 15:08 +0200, Vladimir 'phcoder' Serbinenko wrote:

>         Setting two environment variables is undocumented.  I think
>         rd_string
>         should not be needed.  If you need it due to the script engine
>         problems,
>         it's better to fix the script engine.
> I'm looking how to do it. The corresponding part to support foo=$bar
> is here but commented out.

The changes to fs/hfsplus.c look rather uncontroversial.  Maybe you
could apply that part first?  And then we could deal with the xnu
related stuff separately.

-- 
Regards,
Pavel Roskin



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] hfs+ uuid
  2009-05-04 13:22     ` Pavel Roskin
@ 2009-05-04 15:52       ` Vladimir 'phcoder' Serbinenko
  0 siblings, 0 replies; 11+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-05-04 15:52 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 901 bytes --]

commited

On Mon, May 4, 2009 at 3:22 PM, Pavel Roskin <proski@gnu.org> wrote:

> On Mon, 2009-05-04 at 15:08 +0200, Vladimir 'phcoder' Serbinenko wrote:
>
> >         Setting two environment variables is undocumented.  I think
> >         rd_string
> >         should not be needed.  If you need it due to the script engine
> >         problems,
> >         it's better to fix the script engine.
> > I'm looking how to do it. The corresponding part to support foo=$bar
> > is here but commented out.
>
> The changes to fs/hfsplus.c look rather uncontroversial.  Maybe you
> could apply that part first?  And then we could deal with the xnu
> related stuff separately.
>
> --
> Regards,
> Pavel Roskin
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>



-- 
Regards
Vladimir 'phcoder' Serbinenko

[-- Attachment #2: Type: text/html, Size: 1512 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] hfs+ uuid
  2009-05-03 16:55 ` Pavel Roskin
  2009-05-04 13:08   ` Vladimir 'phcoder' Serbinenko
@ 2009-06-08 20:50   ` Vladimir 'phcoder' Serbinenko
  2009-06-08 20:50     ` Vladimir 'phcoder' Serbinenko
  2009-06-08 22:01     ` Pavel Roskin
  1 sibling, 2 replies; 11+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-06-08 20:50 UTC (permalink / raw)
  To: The development of GRUB 2

On Sun, May 3, 2009 at 6:55 PM, Pavel Roskin<proski@gnu.org> wrote:
> On Sun, 2009-05-03 at 12:42 +0200, Vladimir 'phcoder' Serbinenko wrote:
>> This is a patch to support UUIDs on HFS+. MD5 code is copied from
>> Michael Gorven's patch which is copied from libgcrypt nearly verbatim.
>> Thanks for Cris for the info about how xnu expects UUID to be
>
> I suggest that you run all new code through GNU indent.  Spacing in
> "32-(n)" will probably need to be fixed manually, as it's a preprocessor
> directive.
>
> Commented out call to to _gcry_burn_stack() should probably be removed.
> I would prefer that we don't use #undef.  Instead, the preprocessor
> defines should use unique names that never need to be redefined.
>
> Setting two environment variables is undocumented.  I think rd_string
> should not be needed.  If you need it due to the script engine problems,
> it's better to fix the script engine.  At least please mark that hack as
> a hack.
>
> Perhaps we should consider adding %X support to grub_printf().  I
> realize that it will increase the core slightly, but if it's just a few
> bytes, we could accept it.  Other modules may use it.  Or maybe we could
> have grub_toupper(), perhaps an inline function?
>
> Another thing to consider is whether md5 support should be in a separate
> file.  It would make it possible to reuse md5 for other commands.
Here is the improved patch. I deliberately ignored md5 comments
because this part will be gone anyway whel Michael Gorven signs his
copyright assignment and we incorporate luks patches
>
> --
> Regards,
> Pavel Roskin
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>



-- 
Regards
Vladimir 'phcoder' Serbinenko



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] hfs+ uuid
  2009-06-08 20:50   ` Vladimir 'phcoder' Serbinenko
@ 2009-06-08 20:50     ` Vladimir 'phcoder' Serbinenko
  2009-06-08 22:01     ` Pavel Roskin
  1 sibling, 0 replies; 11+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-06-08 20:50 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 2057 bytes --]

Attachement forgotten

On Mon, Jun 8, 2009 at 10:50 PM, Vladimir 'phcoder'
Serbinenko<phcoder@gmail.com> wrote:
> On Sun, May 3, 2009 at 6:55 PM, Pavel Roskin<proski@gnu.org> wrote:
>> On Sun, 2009-05-03 at 12:42 +0200, Vladimir 'phcoder' Serbinenko wrote:
>>> This is a patch to support UUIDs on HFS+. MD5 code is copied from
>>> Michael Gorven's patch which is copied from libgcrypt nearly verbatim.
>>> Thanks for Cris for the info about how xnu expects UUID to be
>>
>> I suggest that you run all new code through GNU indent.  Spacing in
>> "32-(n)" will probably need to be fixed manually, as it's a preprocessor
>> directive.
>>
>> Commented out call to to _gcry_burn_stack() should probably be removed.
>> I would prefer that we don't use #undef.  Instead, the preprocessor
>> defines should use unique names that never need to be redefined.
>>
>> Setting two environment variables is undocumented.  I think rd_string
>> should not be needed.  If you need it due to the script engine problems,
>> it's better to fix the script engine.  At least please mark that hack as
>> a hack.
>>
>> Perhaps we should consider adding %X support to grub_printf().  I
>> realize that it will increase the core slightly, but if it's just a few
>> bytes, we could accept it.  Other modules may use it.  Or maybe we could
>> have grub_toupper(), perhaps an inline function?
>>
>> Another thing to consider is whether md5 support should be in a separate
>> file.  It would make it possible to reuse md5 for other commands.
> Here is the improved patch. I deliberately ignored md5 comments
> because this part will be gone anyway whel Michael Gorven signs his
> copyright assignment and we incorporate luks patches
>>
>> --
>> Regards,
>> Pavel Roskin
>>
>>
>> _______________________________________________
>> Grub-devel mailing list
>> Grub-devel@gnu.org
>> http://lists.gnu.org/mailman/listinfo/grub-devel
>>
>
>
>
> --
> Regards
> Vladimir 'phcoder' Serbinenko
>



-- 
Regards
Vladimir 'phcoder' Serbinenko

[-- Attachment #2: hfspuuid.diff --]
[-- Type: text/x-diff, Size: 15125 bytes --]

diff --git a/commands/xnu_uuid.c b/commands/xnu_uuid.c
new file mode 100644
index 0000000..51b7ca7
--- /dev/null
+++ b/commands/xnu_uuid.c
@@ -0,0 +1,433 @@
+/* xnu_uuid.c - transform 64-bit serial number 
+   to 128-bit uuid suitable for xnu. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1995,1996,1998,1999,2001,2002,
+ *                2003, 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/>.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/device.h>
+#include <grub/disk.h>
+#include <grub/fs.h>
+#include <grub/file.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+#include <grub/command.h>
+
+struct tohash
+{
+  grub_uint8_t prefix[16];
+  grub_uint64_t serial;
+} __attribute__ ((packed));
+
+/* This prefix is used by xnu and boot-132 to hash 
+   together with volume serial. */
+static grub_uint8_t hash_prefix[16] 
+  = {0xB3, 0xE2, 0x0F, 0x39, 0xF2, 0x92, 0x11, 0xD6, 
+     0x97, 0xA4, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC};
+
+#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
+#define ror(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) )
+
+typedef struct {
+  grub_uint32_t A,B,C,D;	  /* chaining variables */
+  grub_uint32_t  nblocks;
+  grub_uint8_t buf[64];
+  int  count;
+} MD5_CONTEXT;
+
+static void
+md5_init( void *context )
+{
+  MD5_CONTEXT *ctx = context;
+
+  ctx->A = 0x67452301;
+  ctx->B = 0xefcdab89;
+  ctx->C = 0x98badcfe;
+  ctx->D = 0x10325476;
+
+  ctx->nblocks = 0;
+  ctx->count = 0;
+}
+
+/* These are the four functions used in the four steps of the MD5 algorithm
+   and defined in the RFC 1321.  The first function is a little bit optimized
+   (as found in Colin Plumbs public domain implementation).  */
+/* #define FF(b, c, d) ((b & c) | (~b & d)) */
+#define FF(b, c, d) (d ^ (b & (c ^ d)))
+#define FG(b, c, d) FF (d, b, c)
+#define FH(b, c, d) (b ^ c ^ d)
+#define FI(b, c, d) (c ^ (b | ~d))
+
+
+/****************
+ * transform n*64 grub_uint8_ts
+ */
+static void
+transform ( MD5_CONTEXT *ctx, const unsigned char *data )
+{
+  grub_uint32_t correct_words[16];
+  register grub_uint32_t A = ctx->A;
+  register grub_uint32_t B = ctx->B;
+  register grub_uint32_t C = ctx->C;
+  register grub_uint32_t D = ctx->D;
+  grub_uint32_t *cwp = correct_words;
+
+#ifdef WORDS_BIGENDIAN
+  { 
+    int i;
+    grub_uint8_t *p2, *p1;
+    for(i=0, p1=data, p2=(grub_uint8_t*)correct_words; i < 16; i++, p2 += 4 )
+    {
+      p2[3] = *p1++;
+      p2[2] = *p1++;
+      p2[1] = *p1++;
+      p2[0] = *p1++;
+    }
+  }
+#else
+  memcpy( correct_words, data, 64 );
+#endif
+
+#define OP(a, b, c, d, s, T) \
+  do			         	   \
+  {					   \
+    a += FF (b, c, d) + (*cwp++) + T;    \
+    a = rol(a, s);			   \
+    a += b;				   \
+  }					   \
+  while (0)
+
+  /* Before we start, one word about the strange constants.
+     They are defined in RFC 1321 as
+
+     T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
+     */
+
+  /* Round 1.  */
+  OP (A, B, C, D,  7, 0xd76aa478);
+  OP (D, A, B, C, 12, 0xe8c7b756);
+  OP (C, D, A, B, 17, 0x242070db);
+  OP (B, C, D, A, 22, 0xc1bdceee);
+  OP (A, B, C, D,  7, 0xf57c0faf);
+  OP (D, A, B, C, 12, 0x4787c62a);
+  OP (C, D, A, B, 17, 0xa8304613);
+  OP (B, C, D, A, 22, 0xfd469501);
+  OP (A, B, C, D,  7, 0x698098d8);
+  OP (D, A, B, C, 12, 0x8b44f7af);
+  OP (C, D, A, B, 17, 0xffff5bb1);
+  OP (B, C, D, A, 22, 0x895cd7be);
+  OP (A, B, C, D,  7, 0x6b901122);
+  OP (D, A, B, C, 12, 0xfd987193);
+  OP (C, D, A, B, 17, 0xa679438e);
+  OP (B, C, D, A, 22, 0x49b40821);
+
+#undef OP
+#define OP(f, a, b, c, d, k, s, T)  \
+  do								      \
+  { 							      \
+    a += f (b, c, d) + correct_words[k] + T;		      \
+    a = rol(a, s);						      \
+    a += b; 						      \
+  } 							      \
+  while (0)
+
+  /* Round 2.  */
+  OP (FG, A, B, C, D,  1,  5, 0xf61e2562);
+  OP (FG, D, A, B, C,  6,  9, 0xc040b340);
+  OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
+  OP (FG, B, C, D, A,  0, 20, 0xe9b6c7aa);
+  OP (FG, A, B, C, D,  5,  5, 0xd62f105d);
+  OP (FG, D, A, B, C, 10,  9, 0x02441453);
+  OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
+  OP (FG, B, C, D, A,  4, 20, 0xe7d3fbc8);
+  OP (FG, A, B, C, D,  9,  5, 0x21e1cde6);
+  OP (FG, D, A, B, C, 14,  9, 0xc33707d6);
+  OP (FG, C, D, A, B,  3, 14, 0xf4d50d87);
+  OP (FG, B, C, D, A,  8, 20, 0x455a14ed);
+  OP (FG, A, B, C, D, 13,  5, 0xa9e3e905);
+  OP (FG, D, A, B, C,  2,  9, 0xfcefa3f8);
+  OP (FG, C, D, A, B,  7, 14, 0x676f02d9);
+  OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
+
+  /* Round 3.  */
+  OP (FH, A, B, C, D,  5,  4, 0xfffa3942);
+  OP (FH, D, A, B, C,  8, 11, 0x8771f681);
+  OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
+  OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
+  OP (FH, A, B, C, D,  1,  4, 0xa4beea44);
+  OP (FH, D, A, B, C,  4, 11, 0x4bdecfa9);
+  OP (FH, C, D, A, B,  7, 16, 0xf6bb4b60);
+  OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
+  OP (FH, A, B, C, D, 13,  4, 0x289b7ec6);
+  OP (FH, D, A, B, C,  0, 11, 0xeaa127fa);
+  OP (FH, C, D, A, B,  3, 16, 0xd4ef3085);
+  OP (FH, B, C, D, A,  6, 23, 0x04881d05);
+  OP (FH, A, B, C, D,  9,  4, 0xd9d4d039);
+  OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
+  OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
+  OP (FH, B, C, D, A,  2, 23, 0xc4ac5665);
+
+  /* Round 4.  */
+  OP (FI, A, B, C, D,  0,  6, 0xf4292244);
+  OP (FI, D, A, B, C,  7, 10, 0x432aff97);
+  OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
+  OP (FI, B, C, D, A,  5, 21, 0xfc93a039);
+  OP (FI, A, B, C, D, 12,  6, 0x655b59c3);
+  OP (FI, D, A, B, C,  3, 10, 0x8f0ccc92);
+  OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
+  OP (FI, B, C, D, A,  1, 21, 0x85845dd1);
+  OP (FI, A, B, C, D,  8,  6, 0x6fa87e4f);
+  OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
+  OP (FI, C, D, A, B,  6, 15, 0xa3014314);
+  OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
+  OP (FI, A, B, C, D,  4,  6, 0xf7537e82);
+  OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
+  OP (FI, C, D, A, B,  2, 15, 0x2ad7d2bb);
+  OP (FI, B, C, D, A,  9, 21, 0xeb86d391);
+
+  /* Put checksum in context given as argument.  */
+  ctx->A += A;
+  ctx->B += B;
+  ctx->C += C;
+  ctx->D += D;
+}
+
+/* The routine updates the message-digest context to
+ * account for the presence of each of the characters inBuf[0..inLen-1]
+ * in the message whose digest is being computed.
+ */
+static void
+md5_write( void *context, const void *inbuf_arg , grub_size_t inlen)
+{
+  const unsigned char *inbuf = inbuf_arg;
+  MD5_CONTEXT *hd = context;
+
+  if( hd->count == 64 )  /* flush the buffer */
+  {
+    transform( hd, hd->buf );
+    //      _gcry_burn_stack (80+6*sizeof(void*));
+    hd->count = 0;
+    hd->nblocks++;
+  }
+  if( !inbuf )
+    return;
+
+  if( hd->count )
+  {
+    for( ; inlen && hd->count < 64; inlen-- )
+      hd->buf[hd->count++] = *inbuf++;
+    md5_write( hd, NULL, 0 );
+    if( !inlen )
+      return;
+  }
+  //  _gcry_burn_stack (80+6*sizeof(void*));
+
+  while( inlen >= 64 ) 
+  {
+    transform( hd, inbuf );
+    hd->count = 0;
+    hd->nblocks++;
+    inlen -= 64;
+    inbuf += 64;
+  }
+  for( ; inlen && hd->count < 64; inlen-- )
+    hd->buf[hd->count++] = *inbuf++;
+
+}
+
+
+
+/* The routine final terminates the message-digest computation and
+ * ends with the desired message digest in mdContext->digest[0...15].
+ * The handle is prepared for a new MD5 cycle.
+ * Returns 16 grub_uint8_ts representing the digest.
+ */
+static void
+md5_final( void *context)
+{
+  MD5_CONTEXT *hd = context;
+  grub_uint32_t t, msb, lsb;
+  grub_uint8_t *p;
+
+  md5_write(hd, NULL, 0); /* flush */;
+
+  t = hd->nblocks;
+  /* multiply by 64 to make a grub_uint8_t count */
+  lsb = t << 6;
+  msb = t >> 26;
+  /* add the count */
+  t = lsb;
+  if( (lsb += hd->count) < t )
+    msb++;
+  /* multiply by 8 to make a bit count */
+  t = lsb;
+  lsb <<= 3;
+  msb <<= 3;
+  msb |= t >> 29;
+
+  if( hd->count < 56 )  /* enough room */
+  {
+    hd->buf[hd->count++] = 0x80; /* pad */
+    while( hd->count < 56 )
+      hd->buf[hd->count++] = 0;  /* pad */
+  }
+  else  /* need one extra block */
+  {
+    hd->buf[hd->count++] = 0x80; /* pad character */
+    while( hd->count < 64 )
+      hd->buf[hd->count++] = 0;
+    md5_write(hd, NULL, 0);  /* flush */;
+    grub_memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
+  }
+  /* append the 64 bit count */
+  hd->buf[56] = lsb	   ;
+  hd->buf[57] = lsb >>  8;
+  hd->buf[58] = lsb >> 16;
+  hd->buf[59] = lsb >> 24;
+  hd->buf[60] = msb	   ;
+  hd->buf[61] = msb >>  8;
+  hd->buf[62] = msb >> 16;
+  hd->buf[63] = msb >> 24;
+  transform( hd, hd->buf );
+  //  _gcry_burn_stack (80+6*sizeof(void*));
+
+  p = hd->buf;
+#ifdef WORDS_BIGENDIAN
+#define X(a) do { *p++ = hd->a      ; *p++ = hd->a >> 8;      \
+  *p++ = hd->a >> 16; *p++ = hd->a >> 24; } while(0)
+#else /* little endian */
+#define X(a) do { *(grub_uint32_t*)p = (*hd).a ; p += 4; } while(0)
+#endif
+  X(A);
+  X(B);
+  X(C);
+  X(D);
+#undef X
+
+}
+
+/**
+ * GRUB2 Crypto Interface
+ * Written by Michael Gorven
+ */
+static grub_err_t
+md5 (const char *in, grub_size_t insize, char *out)
+{
+  MD5_CONTEXT hd;
+
+  md5_init (&hd);
+  md5_write (&hd, in, insize);
+  md5_final (&hd);
+  grub_memcpy (out, hd.buf, 16);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)),
+		   int argc, char **args)
+
+{  
+  grub_device_t dev;
+  char *uuid, *ptr, *buf;
+  grub_err_t err;
+  struct tohash hashme;
+  grub_uint8_t xnu_uuid[16];
+  grub_fs_t fs;
+  char uuid_string[sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
+
+  if (argc < 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
+
+  ptr = args[0] + grub_strlen (args[0]) - 1;
+  if (args[0][0] == '(' && *ptr == ')')
+    {
+      *ptr = 0;
+      dev = grub_device_open (args[0] + 1);
+      *ptr =')';
+    }
+  else
+    dev = grub_device_open (args[0]);
+  if (! dev)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "couldn't open device");
+  fs = grub_fs_probe (dev);
+  if (! fs)
+    return grub_error (GRUB_ERR_UNKNOWN_FS, "unrecognised fs");
+  if (! fs->uuid)
+    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, 
+		       "uuid for this FS isn't supported yet");
+  err = fs->uuid (dev, &uuid);
+  if (err)
+    return err;
+  if (! uuid)
+    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, 
+		       "uuid for this FS isn't supported yet");
+  hashme.serial = grub_cpu_to_be64 (grub_strtoull (uuid, 0, 16));
+  grub_memcpy (hashme.prefix, hash_prefix, sizeof (hashme.prefix));
+  
+  md5 ((char *) &hashme, sizeof (hashme), (char *) xnu_uuid);
+  xnu_uuid[6] = (xnu_uuid[6] & 0xf) | 0x30;
+  xnu_uuid[8] = (xnu_uuid[8] & 0x3f) | 0x80;
+  grub_sprintf (uuid_string, 
+		"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+		(unsigned int) xnu_uuid[0], (unsigned int) xnu_uuid[1], 
+		(unsigned int) xnu_uuid[2], (unsigned int) xnu_uuid[3],
+		(unsigned int) xnu_uuid[4], (unsigned int) xnu_uuid[5], 
+		(unsigned int) ((xnu_uuid[6] & 0xf) | 0x30),
+		(unsigned int) xnu_uuid[7], 
+		(unsigned int) ((xnu_uuid[8] & 0x3f) | 0x80), 
+		(unsigned int) xnu_uuid[9], 
+		(unsigned int) xnu_uuid[10], (unsigned int) xnu_uuid[11], 
+		(unsigned int) xnu_uuid[12], (unsigned int) xnu_uuid[13], 
+		(unsigned int) xnu_uuid[14], (unsigned int) xnu_uuid[15]);
+  for (ptr = uuid_string; *ptr; ptr++)
+    if (*ptr >= 'a' && *ptr <= 'f')
+      *ptr = grub_toupper (*ptr);
+  if (argc == 1)
+    grub_printf ("The xnu-uuid of %s is %s\n"
+		 "To use it as a root pass 'rd=*uuid boot-uuid=%s' "
+		 "to the kernel\n",
+		 args[0], uuid_string, uuid_string);
+  if (argc > 1)
+    grub_env_set (args[1], uuid_string);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_command_t cmd;
+
+
+GRUB_MOD_INIT(xnu_uuid)
+{
+  (void)mod;			/* To stop warning. */
+  cmd = grub_register_command ("xnu_uuid", grub_cmd_xnu_uuid, 
+			       "xnu_uuid DEVICE [VARNAME]",
+			       "Fetch UUID of partition in format "
+			       "suitable for xnu.");
+}
+
+GRUB_MOD_FINI(xnu_uuid)
+{
+  grub_unregister_command (cmd);
+}
+
+
diff --git a/conf/common.rmk b/conf/common.rmk
index 9780341..8e6d450 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -585,3 +585,11 @@ gzio_mod_LDFLAGS = $(COMMON_LDFLAGS)
 bufio_mod_SOURCES = io/bufio.c
 bufio_mod_CFLAGS = $(COMMON_CFLAGS)
 bufio_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# Misc.
+pkglib_MODULES += xnu_uuid.mod
+
+# For elf.mod.
+xnu_uuid_mod_SOURCES = commands/xnu_uuid.c
+xnu_uuid_mod_CFLAGS = $(COMMON_CFLAGS)
+xnu_uuid_mod_LDFLAGS = $(COMMON_LDFLAGS)
diff --git a/include/grub/misc.h b/include/grub/misc.h
index 23e0ce6..e229062 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -61,6 +61,15 @@ int EXPORT_FUNC(grub_isalpha) (int c);
 int EXPORT_FUNC(grub_isgraph) (int c);
 int EXPORT_FUNC(grub_isdigit) (int c);
 int EXPORT_FUNC(grub_tolower) (int c);
+static inline int
+grub_toupper (int c)
+{
+  if (c >= 'a' && c <= 'z')
+    return c - 'a' + 'A';
+
+  return c;
+}
+
 unsigned long EXPORT_FUNC(grub_strtoul) (const char *str, char **end, int base);
 unsigned long long EXPORT_FUNC(grub_strtoull) (const char *str, char **end, int base);
 char *EXPORT_FUNC(grub_strdup) (const char *s);
diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
index 7d4d17e..af936e8 100644
--- a/util/grub.d/30_os-prober.in
+++ b/util/grub.d/30_os-prober.in
@@ -83,12 +83,10 @@ EOF
       done
     ;;
     macosx)
-      OSXROOT="`grub-probe --target=drive --device ${DEVICE} 2> /dev/null`"
-      # FIXME: use UUID
-      OSXDISK=disk"`echo ${OSXROOT} | awk -F , '{ print $1 ; }' | sed 's/(hd//;'`"s"`echo ${OSXROOT} | awk -F , '{ print $2 ; }' | sed 's/)//;'`"
+      OSXUUID="`grub-probe --target=fs_uuid --device ${DEVICE} 2> /dev/null`"
         cat << EOF
 menuentry "${LONGNAME} (on ${DEVICE})" {
-	set root=${OSXROOT}
+        search --fs-uuid --set ${OSXUUID}
         insmod vbe
         do_resume=0
         if [ /var/vm/sleepimage -nt10 / ]; then
@@ -97,10 +95,11 @@ menuentry "${LONGNAME} (on ${DEVICE})" {
            fi
         fi
         if [ \$do_resume == 0 ]; then
+           xnu_uuid \$root uuid
            if [ -f /Extra/DSDT.aml ]; then
               acpi -e /Extra/DSDT.aml
            fi
-           xnu_kernel /mach_kernel rd=$OSXDISK
+           xnu_kernel /mach_kernel boot-uuid=\${uuid} rd=*uuid
            if [ /System/Library/Extensions.mkext -nt /System/Library/Extensions ]; then
               xnu_mkext /System/Library/Extensions.mkext
            else

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH] hfs+ uuid
  2009-06-08 20:50   ` Vladimir 'phcoder' Serbinenko
  2009-06-08 20:50     ` Vladimir 'phcoder' Serbinenko
@ 2009-06-08 22:01     ` Pavel Roskin
  2009-06-10  8:17       ` Vladimir 'phcoder' Serbinenko
  1 sibling, 1 reply; 11+ messages in thread
From: Pavel Roskin @ 2009-06-08 22:01 UTC (permalink / raw)
  To: The development of GRUB 2

On Mon, 2009-06-08 at 22:50 +0200, Vladimir 'phcoder' Serbinenko wrote:

> Here is the improved patch. I deliberately ignored md5 comments
> because this part will be gone anyway whel Michael Gorven signs his
> copyright assignment and we incorporate luks patches

Please consider if it would be better to supply the filesystem UUID on
the command line rather than the device name.  That would make xnu_uuid
leaner and more flexible.  I think we need the "uuid" command that would
get the uuid and the "xnu_uuid" command that would convert it.

It would be great if you run xnu_uuid.c through indent.  The coding
style is quite different from that used elsewhere in GRUB.  Or at least
please strip trailing spaces.

"file name required" is a wrong error message.  It should be "device
file required".  I think it would be better to expand "fs" and "FS" in
error messages as "filesystem".

If the variable name is not specified, I think xnu_uuid should just
output the UUID without any explanations.  Explanations belong to the
help, not to the normal output.

"(void)mod;" is not needed.  The "buf" variable in grub_cmd_xnu_uuid()
is unused.

-- 
Regards,
Pavel Roskin



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] hfs+ uuid
  2009-06-08 22:01     ` Pavel Roskin
@ 2009-06-10  8:17       ` Vladimir 'phcoder' Serbinenko
  2009-06-12  1:11         ` Pavel Roskin
  0 siblings, 1 reply; 11+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-06-10  8:17 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 1790 bytes --]

On Tue, Jun 9, 2009 at 12:01 AM, Pavel Roskin<proski@gnu.org> wrote:
> On Mon, 2009-06-08 at 22:50 +0200, Vladimir 'phcoder' Serbinenko wrote:
>
>> Here is the improved patch. I deliberately ignored md5 comments
>> because this part will be gone anyway whel Michael Gorven signs his
>> copyright assignment and we incorporate luks patches
>
> Please consider if it would be better to supply the filesystem UUID on
> the command line rather than the device name.  That would make xnu_uuid
> leaner and more flexible.  I think we need the "uuid" command that would
> get the uuid and the "xnu_uuid" command that would convert it.
>
> It would be great if you run xnu_uuid.c through indent.  The coding
> style is quite different from that used elsewhere in GRUB.  Or at least
> please strip trailing spaces.
>
> "file name required" is a wrong error message.  It should be "device
> file required".  I think it would be better to expand "fs" and "FS" in
> error messages as "filesystem".
>
> If the variable name is not specified, I think xnu_uuid should just
> output the UUID without any explanations.  Explanations belong to the
> help, not to the normal output.
GRUB2 becomes increasingly more complex. We try to document it on
grub.enbug.org but when user needs the info the most his only system
is unbootable. Perhaps we should incorporate a more extensive help
into grub2 itself. man format looks rather easy to parse
>
> "(void)mod;" is not needed.  The "buf" variable in grub_cmd_xnu_uuid()
> is unused.
>
> --
> Regards,
> Pavel Roskin
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>



-- 
Regards
Vladimir 'phcoder' Serbinenko

[-- Attachment #2: hfspuuid.diff --]
[-- Type: text/x-patch, Size: 17879 bytes --]

diff --git a/ChangeLog b/ChangeLog
index 556b17d..65a859d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
 2009-06-08  Vladimir Serbinenko  <phcoder@gmail.com>
 
+	xnu_uuid command
+
+	* commands/xnu_uuid.c: new file
+	* conf/common.rmk (pkglib_MODULES): add xnu_uuid.mod
+	(xnu_uuid_mod_SOURCES): new variable
+	(xnu_uuid_mod_CFLAGS): likewise
+	(xnu_uuid_mod_LDFLAGS): likewise
+	* conf/i386-coreboot.rmk (grub_emu_SOURCES): add commands/probe.c
+	* conf/i386-ieee1275.rmk: likewise
+	* conf/i386-pc.rmk: likewise
+	* conf/powerpc-ieee1275.rmk: likewise
+	* conf/sparc64-ieee1275.rmk: likewise
+	* util/grub.d/30_os-prober.in: use UUID for Mac OS X/Darwin
+
+2009-06-08  Vladimir Serbinenko  <phcoder@gmail.com>
+
 	probe command
 
 	* commands/probe.c: new file
diff --git a/commands/xnu_uuid.c b/commands/xnu_uuid.c
new file mode 100644
index 0000000..1302881
--- /dev/null
+++ b/commands/xnu_uuid.c
@@ -0,0 +1,399 @@
+/* xnu_uuid.c - transform 64-bit serial number 
+   to 128-bit uuid suitable for xnu. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1995,1996,1998,1999,2001,2002,
+ *                2003, 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/>.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/device.h>
+#include <grub/disk.h>
+#include <grub/fs.h>
+#include <grub/file.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+#include <grub/command.h>
+
+struct tohash
+{
+  grub_uint8_t prefix[16];
+  grub_uint64_t serial;
+} __attribute__ ((packed));
+
+/* This prefix is used by xnu and boot-132 to hash 
+   together with volume serial. */
+static grub_uint8_t hash_prefix[16] 
+  = {0xB3, 0xE2, 0x0F, 0x39, 0xF2, 0x92, 0x11, 0xD6, 
+     0x97, 0xA4, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC};
+
+#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
+#define ror(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) )
+
+typedef struct {
+  grub_uint32_t A,B,C,D;	  /* chaining variables */
+  grub_uint32_t  nblocks;
+  grub_uint8_t buf[64];
+  int  count;
+} MD5_CONTEXT;
+
+static void
+md5_init( void *context )
+{
+  MD5_CONTEXT *ctx = context;
+
+  ctx->A = 0x67452301;
+  ctx->B = 0xefcdab89;
+  ctx->C = 0x98badcfe;
+  ctx->D = 0x10325476;
+
+  ctx->nblocks = 0;
+  ctx->count = 0;
+}
+
+/* These are the four functions used in the four steps of the MD5 algorithm
+   and defined in the RFC 1321.  The first function is a little bit optimized
+   (as found in Colin Plumbs public domain implementation).  */
+/* #define FF(b, c, d) ((b & c) | (~b & d)) */
+#define FF(b, c, d) (d ^ (b & (c ^ d)))
+#define FG(b, c, d) FF (d, b, c)
+#define FH(b, c, d) (b ^ c ^ d)
+#define FI(b, c, d) (c ^ (b | ~d))
+
+
+/****************
+ * transform n*64 grub_uint8_ts
+ */
+static void
+transform ( MD5_CONTEXT *ctx, const unsigned char *data )
+{
+  grub_uint32_t correct_words[16];
+  register grub_uint32_t A = ctx->A;
+  register grub_uint32_t B = ctx->B;
+  register grub_uint32_t C = ctx->C;
+  register grub_uint32_t D = ctx->D;
+  grub_uint32_t *cwp = correct_words;
+
+#ifdef WORDS_BIGENDIAN
+  { 
+    int i;
+    grub_uint8_t *p2, *p1;
+    for(i=0, p1=data, p2=(grub_uint8_t*)correct_words; i < 16; i++, p2 += 4 )
+    {
+      p2[3] = *p1++;
+      p2[2] = *p1++;
+      p2[1] = *p1++;
+      p2[0] = *p1++;
+    }
+  }
+#else
+  memcpy( correct_words, data, 64 );
+#endif
+
+#define OP(a, b, c, d, s, T) \
+  do			         	   \
+  {					   \
+    a += FF (b, c, d) + (*cwp++) + T;    \
+    a = rol(a, s);			   \
+    a += b;				   \
+  }					   \
+  while (0)
+
+  /* Before we start, one word about the strange constants.
+     They are defined in RFC 1321 as
+
+     T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
+     */
+
+  /* Round 1.  */
+  OP (A, B, C, D,  7, 0xd76aa478);
+  OP (D, A, B, C, 12, 0xe8c7b756);
+  OP (C, D, A, B, 17, 0x242070db);
+  OP (B, C, D, A, 22, 0xc1bdceee);
+  OP (A, B, C, D,  7, 0xf57c0faf);
+  OP (D, A, B, C, 12, 0x4787c62a);
+  OP (C, D, A, B, 17, 0xa8304613);
+  OP (B, C, D, A, 22, 0xfd469501);
+  OP (A, B, C, D,  7, 0x698098d8);
+  OP (D, A, B, C, 12, 0x8b44f7af);
+  OP (C, D, A, B, 17, 0xffff5bb1);
+  OP (B, C, D, A, 22, 0x895cd7be);
+  OP (A, B, C, D,  7, 0x6b901122);
+  OP (D, A, B, C, 12, 0xfd987193);
+  OP (C, D, A, B, 17, 0xa679438e);
+  OP (B, C, D, A, 22, 0x49b40821);
+
+#undef OP
+#define OP(f, a, b, c, d, k, s, T)  \
+  do								      \
+  { 							      \
+    a += f (b, c, d) + correct_words[k] + T;		      \
+    a = rol(a, s);						      \
+    a += b; 						      \
+  } 							      \
+  while (0)
+
+  /* Round 2.  */
+  OP (FG, A, B, C, D,  1,  5, 0xf61e2562);
+  OP (FG, D, A, B, C,  6,  9, 0xc040b340);
+  OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
+  OP (FG, B, C, D, A,  0, 20, 0xe9b6c7aa);
+  OP (FG, A, B, C, D,  5,  5, 0xd62f105d);
+  OP (FG, D, A, B, C, 10,  9, 0x02441453);
+  OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
+  OP (FG, B, C, D, A,  4, 20, 0xe7d3fbc8);
+  OP (FG, A, B, C, D,  9,  5, 0x21e1cde6);
+  OP (FG, D, A, B, C, 14,  9, 0xc33707d6);
+  OP (FG, C, D, A, B,  3, 14, 0xf4d50d87);
+  OP (FG, B, C, D, A,  8, 20, 0x455a14ed);
+  OP (FG, A, B, C, D, 13,  5, 0xa9e3e905);
+  OP (FG, D, A, B, C,  2,  9, 0xfcefa3f8);
+  OP (FG, C, D, A, B,  7, 14, 0x676f02d9);
+  OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
+
+  /* Round 3.  */
+  OP (FH, A, B, C, D,  5,  4, 0xfffa3942);
+  OP (FH, D, A, B, C,  8, 11, 0x8771f681);
+  OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
+  OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
+  OP (FH, A, B, C, D,  1,  4, 0xa4beea44);
+  OP (FH, D, A, B, C,  4, 11, 0x4bdecfa9);
+  OP (FH, C, D, A, B,  7, 16, 0xf6bb4b60);
+  OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
+  OP (FH, A, B, C, D, 13,  4, 0x289b7ec6);
+  OP (FH, D, A, B, C,  0, 11, 0xeaa127fa);
+  OP (FH, C, D, A, B,  3, 16, 0xd4ef3085);
+  OP (FH, B, C, D, A,  6, 23, 0x04881d05);
+  OP (FH, A, B, C, D,  9,  4, 0xd9d4d039);
+  OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
+  OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
+  OP (FH, B, C, D, A,  2, 23, 0xc4ac5665);
+
+  /* Round 4.  */
+  OP (FI, A, B, C, D,  0,  6, 0xf4292244);
+  OP (FI, D, A, B, C,  7, 10, 0x432aff97);
+  OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
+  OP (FI, B, C, D, A,  5, 21, 0xfc93a039);
+  OP (FI, A, B, C, D, 12,  6, 0x655b59c3);
+  OP (FI, D, A, B, C,  3, 10, 0x8f0ccc92);
+  OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
+  OP (FI, B, C, D, A,  1, 21, 0x85845dd1);
+  OP (FI, A, B, C, D,  8,  6, 0x6fa87e4f);
+  OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
+  OP (FI, C, D, A, B,  6, 15, 0xa3014314);
+  OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
+  OP (FI, A, B, C, D,  4,  6, 0xf7537e82);
+  OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
+  OP (FI, C, D, A, B,  2, 15, 0x2ad7d2bb);
+  OP (FI, B, C, D, A,  9, 21, 0xeb86d391);
+
+  /* Put checksum in context given as argument.  */
+  ctx->A += A;
+  ctx->B += B;
+  ctx->C += C;
+  ctx->D += D;
+}
+
+/* The routine updates the message-digest context to
+ * account for the presence of each of the characters inBuf[0..inLen-1]
+ * in the message whose digest is being computed.
+ */
+static void
+md5_write( void *context, const void *inbuf_arg , grub_size_t inlen)
+{
+  const unsigned char *inbuf = inbuf_arg;
+  MD5_CONTEXT *hd = context;
+
+  if( hd->count == 64 )  /* flush the buffer */
+  {
+    transform( hd, hd->buf );
+    //      _gcry_burn_stack (80+6*sizeof(void*));
+    hd->count = 0;
+    hd->nblocks++;
+  }
+  if( !inbuf )
+    return;
+
+  if( hd->count )
+  {
+    for( ; inlen && hd->count < 64; inlen-- )
+      hd->buf[hd->count++] = *inbuf++;
+    md5_write( hd, NULL, 0 );
+    if( !inlen )
+      return;
+  }
+  //  _gcry_burn_stack (80+6*sizeof(void*));
+
+  while( inlen >= 64 ) 
+  {
+    transform( hd, inbuf );
+    hd->count = 0;
+    hd->nblocks++;
+    inlen -= 64;
+    inbuf += 64;
+  }
+  for( ; inlen && hd->count < 64; inlen-- )
+    hd->buf[hd->count++] = *inbuf++;
+
+}
+
+
+
+/* The routine final terminates the message-digest computation and
+ * ends with the desired message digest in mdContext->digest[0...15].
+ * The handle is prepared for a new MD5 cycle.
+ * Returns 16 grub_uint8_ts representing the digest.
+ */
+static void
+md5_final( void *context)
+{
+  MD5_CONTEXT *hd = context;
+  grub_uint32_t t, msb, lsb;
+  grub_uint8_t *p;
+
+  md5_write(hd, NULL, 0); /* flush */;
+
+  t = hd->nblocks;
+  /* multiply by 64 to make a grub_uint8_t count */
+  lsb = t << 6;
+  msb = t >> 26;
+  /* add the count */
+  t = lsb;
+  if( (lsb += hd->count) < t )
+    msb++;
+  /* multiply by 8 to make a bit count */
+  t = lsb;
+  lsb <<= 3;
+  msb <<= 3;
+  msb |= t >> 29;
+
+  if( hd->count < 56 )  /* enough room */
+  {
+    hd->buf[hd->count++] = 0x80; /* pad */
+    while( hd->count < 56 )
+      hd->buf[hd->count++] = 0;  /* pad */
+  }
+  else  /* need one extra block */
+  {
+    hd->buf[hd->count++] = 0x80; /* pad character */
+    while( hd->count < 64 )
+      hd->buf[hd->count++] = 0;
+    md5_write(hd, NULL, 0);  /* flush */;
+    grub_memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
+  }
+  /* append the 64 bit count */
+  hd->buf[56] = lsb	   ;
+  hd->buf[57] = lsb >>  8;
+  hd->buf[58] = lsb >> 16;
+  hd->buf[59] = lsb >> 24;
+  hd->buf[60] = msb	   ;
+  hd->buf[61] = msb >>  8;
+  hd->buf[62] = msb >> 16;
+  hd->buf[63] = msb >> 24;
+  transform( hd, hd->buf );
+  //  _gcry_burn_stack (80+6*sizeof(void*));
+
+  p = hd->buf;
+#ifdef WORDS_BIGENDIAN
+#define X(a) do { *p++ = hd->a      ; *p++ = hd->a >> 8;      \
+  *p++ = hd->a >> 16; *p++ = hd->a >> 24; } while(0)
+#else /* little endian */
+#define X(a) do { *(grub_uint32_t*)p = (*hd).a ; p += 4; } while(0)
+#endif
+  X(A);
+  X(B);
+  X(C);
+  X(D);
+#undef X
+
+}
+
+/**
+ * GRUB2 Crypto Interface
+ * Written by Michael Gorven
+ */
+static grub_err_t
+md5 (const char *in, grub_size_t insize, char *out)
+{
+  MD5_CONTEXT hd;
+
+  md5_init (&hd);
+  md5_write (&hd, in, insize);
+  md5_final (&hd);
+  grub_memcpy (out, hd.buf, 16);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)),
+		   int argc, char **args)
+{
+  struct tohash hashme;
+  grub_uint8_t xnu_uuid[16];
+  char uuid_string[sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
+  char *ptr;
+
+  if (argc < 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "UUID required");
+
+  hashme.serial = grub_cpu_to_be64 (grub_strtoull (args[0], 0, 16));
+  grub_memcpy (hashme.prefix, hash_prefix, sizeof (hashme.prefix));
+
+  md5 ((char *) &hashme, sizeof (hashme), (char *) xnu_uuid);
+  xnu_uuid[6] = (xnu_uuid[6] & 0xf) | 0x30;
+  xnu_uuid[8] = (xnu_uuid[8] & 0x3f) | 0x80;
+  grub_sprintf (uuid_string,
+		"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+		(unsigned int) xnu_uuid[0], (unsigned int) xnu_uuid[1],
+		(unsigned int) xnu_uuid[2], (unsigned int) xnu_uuid[3],
+		(unsigned int) xnu_uuid[4], (unsigned int) xnu_uuid[5],
+		(unsigned int) ((xnu_uuid[6] & 0xf) | 0x30),
+		(unsigned int) xnu_uuid[7],
+		(unsigned int) ((xnu_uuid[8] & 0x3f) | 0x80),
+		(unsigned int) xnu_uuid[9],
+		(unsigned int) xnu_uuid[10], (unsigned int) xnu_uuid[11],
+		(unsigned int) xnu_uuid[12], (unsigned int) xnu_uuid[13],
+		(unsigned int) xnu_uuid[14], (unsigned int) xnu_uuid[15]);
+  for (ptr = uuid_string; *ptr; ptr++)
+    *ptr = grub_toupper (*ptr);
+  if (argc == 1)
+    grub_printf ("%s", uuid_string);
+  if (argc > 1)
+    grub_env_set (args[1], uuid_string);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_command_t cmd;
+
+
+GRUB_MOD_INIT (xnu_uuid)
+{
+  cmd = grub_register_command ("xnu_uuid", grub_cmd_xnu_uuid,
+			       "xnu_uuid GRUBUUID [VARNAME]",
+			       "Transform 64-bit UUID to format "
+			       "suitable for xnu.");
+}
+
+GRUB_MOD_FINI (xnu_uuid)
+{
+  grub_unregister_command (cmd);
+}
diff --git a/conf/common.rmk b/conf/common.rmk
index b75f50e..584450f 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -591,3 +591,10 @@ bufio_mod_SOURCES = io/bufio.c
 bufio_mod_CFLAGS = $(COMMON_CFLAGS)
 bufio_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# Misc.
+pkglib_MODULES += xnu_uuid.mod
+
+# For elf.mod.
+xnu_uuid_mod_SOURCES = commands/xnu_uuid.c
+xnu_uuid_mod_CFLAGS = $(COMMON_CFLAGS)
+xnu_uuid_mod_LDFLAGS = $(COMMON_LDFLAGS)
diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk
index f2e0dc6..e1fcc46 100644
--- a/conf/i386-coreboot.rmk
+++ b/conf/i386-coreboot.rmk
@@ -61,7 +61,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	commands/configfile.c commands/echo.c commands/help.c		\
 	commands/handler.c commands/ls.c commands/test.c 		\
 	commands/search.c commands/blocklist.c commands/hexdump.c	\
-	commands/gptsync.c commands/probe.c				\
+	commands/gptsync.c commands/probe.c commands/xnu_uuid.c		\
 	lib/hexdump.c commands/i386/cpuid.c				\
 	disk/host.c disk/loopback.c					\
 	\
diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
index 817a266..7231d28 100644
--- a/conf/i386-ieee1275.rmk
+++ b/conf/i386-ieee1275.rmk
@@ -61,7 +61,8 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	commands/handler.c commands/ls.c commands/test.c 		\
 	commands/search.c commands/blocklist.c commands/hexdump.c	\
 	lib/hexdump.c commands/halt.c commands/reboot.c			\
-	commands/gptsync.c commands/probe.c commands/i386/cpuid.c	\
+	commands/gptsync.c commands/probe.c  commands/xnu_uuid.c	\
+	commands/i386/cpuid.c	\
 	disk/host.c disk/loopback.c					\
 	\
 	fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c			\
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index e9496f6..80e8067 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -127,7 +127,8 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	commands/handler.c commands/ls.c commands/test.c 		\
 	commands/search.c commands/blocklist.c commands/hexdump.c	\
 	lib/hexdump.c commands/i386/pc/halt.c commands/reboot.c		\
-	commands/gptsync.c commands/probe.c commands/i386/cpuid.c	\
+	commands/gptsync.c commands/probe.c commands/xnu_uuid.c		\
+	commands/i386/cpuid.c	\
 	disk/host.c disk/loopback.c disk/scsi.c				\
 	fs/fshelp.c 	\
 	\
diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk
index b8a0309..4cb8f04 100644
--- a/conf/powerpc-ieee1275.rmk
+++ b/conf/powerpc-ieee1275.rmk
@@ -45,7 +45,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	commands/search.c commands/handler.c commands/test.c 		\
 	commands/ls.c commands/blocklist.c commands/hexdump.c		\
 	lib/hexdump.c commands/halt.c commands/reboot.c 		\
-	commands/gptsync.c commands/probe.c 			\
+	commands/gptsync.c commands/probe.c commands/xnu_uuid.c		\
 	disk/loopback.c							\
 	\
 	fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c			\
diff --git a/conf/sparc64-ieee1275.rmk b/conf/sparc64-ieee1275.rmk
index 5700937..82e9b73 100644
--- a/conf/sparc64-ieee1275.rmk
+++ b/conf/sparc64-ieee1275.rmk
@@ -101,7 +101,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c 	\
 	commands/configfile.c commands/help.c				\
 	commands/search.c commands/handler.c commands/test.c 		\
 	commands/ls.c commands/blocklist.c commands/hexdump.c		\
-	commands/probe.c						\
+	commands/probe.c commands/xnu_uuid.c				\
 	lib/hexdump.c commands/halt.c commands/reboot.c			\
 	disk/loopback.c							\
 	\
diff --git a/include/grub/misc.h b/include/grub/misc.h
index 23e0ce6..e229062 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -61,6 +61,15 @@ int EXPORT_FUNC(grub_isalpha) (int c);
 int EXPORT_FUNC(grub_isgraph) (int c);
 int EXPORT_FUNC(grub_isdigit) (int c);
 int EXPORT_FUNC(grub_tolower) (int c);
+static inline int
+grub_toupper (int c)
+{
+  if (c >= 'a' && c <= 'z')
+    return c - 'a' + 'A';
+
+  return c;
+}
+
 unsigned long EXPORT_FUNC(grub_strtoul) (const char *str, char **end, int base);
 unsigned long long EXPORT_FUNC(grub_strtoull) (const char *str, char **end, int base);
 char *EXPORT_FUNC(grub_strdup) (const char *s);
diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
index 7d4d17e..753a367 100644
--- a/util/grub.d/30_os-prober.in
+++ b/util/grub.d/30_os-prober.in
@@ -83,12 +83,10 @@ EOF
       done
     ;;
     macosx)
-      OSXROOT="`grub-probe --target=drive --device ${DEVICE} 2> /dev/null`"
-      # FIXME: use UUID
-      OSXDISK=disk"`echo ${OSXROOT} | awk -F , '{ print $1 ; }' | sed 's/(hd//;'`"s"`echo ${OSXROOT} | awk -F , '{ print $2 ; }' | sed 's/)//;'`"
+      OSXUUID="`grub-probe --target=fs_uuid --device ${DEVICE} 2> /dev/null`"
         cat << EOF
 menuentry "${LONGNAME} (on ${DEVICE})" {
-	set root=${OSXROOT}
+        search --fs-uuid --set ${OSXUUID}
         insmod vbe
         do_resume=0
         if [ /var/vm/sleepimage -nt10 / ]; then
@@ -97,10 +95,11 @@ menuentry "${LONGNAME} (on ${DEVICE})" {
            fi
         fi
         if [ \$do_resume == 0 ]; then
+           xnu_uuid ${OSXUUID} uuid
            if [ -f /Extra/DSDT.aml ]; then
               acpi -e /Extra/DSDT.aml
            fi
-           xnu_kernel /mach_kernel rd=$OSXDISK
+           xnu_kernel /mach_kernel boot-uuid=\${uuid} rd=*uuid
            if [ /System/Library/Extensions.mkext -nt /System/Library/Extensions ]; then
               xnu_mkext /System/Library/Extensions.mkext
            else

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH] hfs+ uuid
  2009-06-10  8:17       ` Vladimir 'phcoder' Serbinenko
@ 2009-06-12  1:11         ` Pavel Roskin
  2009-06-15 23:26           ` Vladimir 'phcoder' Serbinenko
  0 siblings, 1 reply; 11+ messages in thread
From: Pavel Roskin @ 2009-06-12  1:11 UTC (permalink / raw)
  To: grub-devel

Quoting Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>:

>> If the variable name is not specified, I think xnu_uuid should just
>> output the UUID without any explanations.  Explanations belong to the
>> help, not to the normal output.
> GRUB2 becomes increasingly more complex. We try to document it on
> grub.enbug.org but when user needs the info the most his only system
> is unbootable. Perhaps we should incorporate a more extensive help
> into grub2 itself. man format looks rather easy to parse

My point is that commands shouldn't be outputting any help text unless  
the user requests it.

-- 
Regards,
Pavel Roskin



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] hfs+ uuid
  2009-06-12  1:11         ` Pavel Roskin
@ 2009-06-15 23:26           ` Vladimir 'phcoder' Serbinenko
  0 siblings, 0 replies; 11+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-06-15 23:26 UTC (permalink / raw)
  To: The development of GRUB 2

comitted

On Fri, Jun 12, 2009 at 3:11 AM, Pavel Roskin<proski@gnu.org> wrote:
> Quoting Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>:
>
>>> If the variable name is not specified, I think xnu_uuid should just
>>> output the UUID without any explanations.  Explanations belong to the
>>> help, not to the normal output.
>>
>> GRUB2 becomes increasingly more complex. We try to document it on
>> grub.enbug.org but when user needs the info the most his only system
>> is unbootable. Perhaps we should incorporate a more extensive help
>> into grub2 itself. man format looks rather easy to parse
>
> My point is that commands shouldn't be outputting any help text unless the
> user requests it.
>
> --
> Regards,
> Pavel Roskin
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>



-- 
Regards
Vladimir 'phcoder' Serbinenko



^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2009-06-15 23:26 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-03 10:42 [PATCH] hfs+ uuid Vladimir 'phcoder' Serbinenko
2009-05-03 16:55 ` Pavel Roskin
2009-05-04 13:08   ` Vladimir 'phcoder' Serbinenko
2009-05-04 13:22     ` Pavel Roskin
2009-05-04 15:52       ` Vladimir 'phcoder' Serbinenko
2009-06-08 20:50   ` Vladimir 'phcoder' Serbinenko
2009-06-08 20:50     ` Vladimir 'phcoder' Serbinenko
2009-06-08 22:01     ` Pavel Roskin
2009-06-10  8:17       ` Vladimir 'phcoder' Serbinenko
2009-06-12  1:11         ` Pavel Roskin
2009-06-15 23:26           ` Vladimir 'phcoder' Serbinenko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.