diff --git a/grub-core/partmap/gpt.c b/grub-core/partmap/gpt.c
index 83bcba7..beaf25d 100644
--- a/grub-core/partmap/gpt.c
+++ b/grub-core/partmap/gpt.c
@@ -99,6 +99,8 @@ grub_gpt_partition_map_iterate (grub_disk_t disk,
       if (grub_memcmp (&grub_gpt_partition_type_empty, &entry.type,
 		       sizeof (grub_gpt_partition_type_empty)))
 	{
+          grub_memcpy(part.guid.gpt, entry.guid, sizeof(part.guid.gpt));
+
 	  /* Calculate the first block and the size of the partition.  */
 	  part.start = grub_le_to_cpu64 (entry.start) << sector_log;
 	  part.len = (grub_le_to_cpu64 (entry.end)
diff --git a/grub-core/partmap/msdos.c b/grub-core/partmap/msdos.c
index 6d4b455..fb5ef81 100644
--- a/grub-core/partmap/msdos.c
+++ b/grub-core/partmap/msdos.c
@@ -169,6 +169,13 @@ grub_partition_msdos_iterate (grub_disk_t disk,
 	if (mbr.entries[i].flag & 0x7f)
 	  return grub_error (GRUB_ERR_BAD_PART_TABLE, "bad boot flag");
 
+      /*
+       * Copy off the NT Disk signature.  Linux uses this to compute the
+       * PARTUUID.  The disk signature is 440 bytes in and 4 bytes long.
+       */
+      if (p.offset == 0)
+        grub_memcpy(p.guid.mbr, mbr.code + 440, sizeof(p.guid.mbr));
+
       /* Analyze DOS partitions.  */
       for (p.index = 0; p.index < 4; p.index++)
 	{
@@ -191,7 +198,7 @@ grub_partition_msdos_iterate (grub_disk_t disk,
 	  if (! grub_msdos_partition_is_empty (e->type)
 	      && ! grub_msdos_partition_is_extended (e->type))
 	    {
-	      p.number++;
+	      p.guid.mbr[4] = ++p.number;
 
 	      if (hook (disk, &p, hook_data))
 		return grub_errno;
@@ -199,7 +206,7 @@ grub_partition_msdos_iterate (grub_disk_t disk,
 	  else if (p.number < 3)
 	    /* If this partition is a logical one, shouldn't increase the
 	       partition number.  */
-	    p.number++;
+	    p.guid.mbr[4] = ++p.number;
 	}
 
       /* Find an extended partition.  */
@@ -209,6 +216,7 @@ grub_partition_msdos_iterate (grub_disk_t disk,
 
 	  if (grub_msdos_partition_is_extended (e->type))
 	    {
+              p.guid.mbr[4] = 4 + i; // logical partitions start with 4.
 	      p.offset = ext_offset
 		+ (grub_le_to_cpu32 (e->start)
 		   << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
diff --git a/include/grub/partition.h b/include/grub/partition.h
index 7adb7ec..00d2477 100644
--- a/include/grub/partition.h
+++ b/include/grub/partition.h
@@ -66,6 +66,13 @@ struct grub_partition
   /* The partition number.  */
   int number;
 
+  /* Unique partition GUID. */
+  union
+  {
+      grub_uint8_t gpt[16];
+      grub_uint8_t mbr[5];
+  } guid;
+
   /* The start sector (relative to parent).  */
   grub_disk_addr_t start;
 
@@ -84,7 +87,7 @@ struct grub_partition
   /* The type partition map.  */
   grub_partition_map_t partmap;
 
-  /* The type of partition whne it's on MSDOS.
+  /* The type of partition when it's on MSDOS.
      Used for embedding detection.  */
   grub_uint8_t msdostype;
 };
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index 203b076..7f5451b 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -134,6 +134,7 @@ fi
 # Device containing our userland.  Typically used for root= parameter.
 GRUB_DEVICE="`${grub_probe} --target=device /`"
 GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true
+GRUB_DEVICE_PARTUUID="`${grub_probe} --device ${GRUB_DEVICE} --target=partuuid 2> /dev/null`" || true
 
 # Device containing our /boot partition.  Usually the same as GRUB_DEVICE.
 GRUB_DEVICE_BOOT="`${grub_probe} --target=device /boot`"
@@ -182,6 +183,7 @@ if [ "x${GRUB_ACTUAL_DEFAULT}" = "xsaved" ] ; then GRUB_ACTUAL_DEFAULT="`"${grub
 # override them.
 export GRUB_DEVICE \
   GRUB_DEVICE_UUID \
+  GRUB_DEVICE_PARTUUID \
   GRUB_DEVICE_BOOT \
   GRUB_DEVICE_BOOT_UUID \
   GRUB_FS \
diff --git a/util/grub-probe.c b/util/grub-probe.c
index 8ac527d..bd91a94 100644
--- a/util/grub-probe.c
+++ b/util/grub-probe.c
@@ -62,6 +62,7 @@ enum {
   PRINT_DRIVE,
   PRINT_DEVICE,
   PRINT_PARTMAP,
+  PRINT_PARTUUID,
   PRINT_ABSTRACTION,
   PRINT_CRYPTODISK_UUID,
   PRINT_HINT_STR,
@@ -85,6 +86,7 @@ static const char *targets[] =
     [PRINT_DRIVE]              = "drive",
     [PRINT_DEVICE]             = "device",
     [PRINT_PARTMAP]            = "partmap",
+    [PRINT_PARTUUID]           = "partuuid",
     [PRINT_ABSTRACTION]        = "abstraction",
     [PRINT_CRYPTODISK_UUID]    = "cryptodisk_uuid",
     [PRINT_HINT_STR]           = "hints_string",
@@ -617,6 +619,62 @@ probe (const char *path, char **device_names, char delim)
       else if (print == PRINT_CRYPTODISK_UUID)
 	probe_cryptodisk_uuid (dev->disk, delim);
 
+      else if (print == PRINT_PARTUUID && dev->disk->partition)
+        {
+          grub_uint8_t be_guid[16];
+          int i;
+          int guid_len;
+          if (strcmp(dev->disk->partition->partmap->name, "gpt") == 0)
+            {
+              guid_len = sizeof(dev->disk->partition->guid.gpt);
+              /**
+               * The GUID disk format is LE(4) LE(2) LE(2) BE(8).
+               * where LE(n) means n-bytes little-endian formatted and
+               * BE(n) means n-bytes big-endian formatted.
+               */
+              for(i = 3; i >= 0; i--)
+                {
+                  be_guid[3 - i] = dev->disk->partition->guid.gpt[i];
+                }
+              for (i = 1; i >= 0; i--)
+                {
+                  be_guid[5 - i] = dev->disk->partition->guid.gpt[i + 4];
+                  be_guid[7 - i] = dev->disk->partition->guid.gpt[i + 6];
+                }
+              for (i = 7; i >= 0; i--)
+                {
+                  be_guid[i + 8] = dev->disk->partition->guid.gpt[i + 8];
+                }
+            }
+          else if (strcmp(dev->disk->partition->partmap->name, "msdos") == 0)
+            {
+              guid_len = sizeof(dev->disk->partition->guid.mbr);
+              /*
+               * First 4 bytes are in LE order and need to be swapped them to BE
+               * order.
+               */
+              for(i = 3; i >= 0; i--)
+                {
+                  be_guid[3 - i] = dev->disk->partition->guid.mbr[i];
+                }
+                /* Adjust the last number so that it is 1-indexed. */
+                be_guid[4] = dev->disk->partition->guid.mbr[4] + 1;
+            }
+            for (i = 0; i < guid_len; i++)
+              {
+                switch(i)
+                  {
+                  case 4:
+                  case 6:
+                  case 8:
+                  case 10:
+                    printf("-");
+                  default:
+                    printf("%02x", be_guid[i]);
+                  }
+              }
+          putchar(delim);
+        }
       else if (print == PRINT_PARTMAP)
 	/* Check if dev->disk itself is contained in a partmap.  */
 	probe_partmap (dev->disk, delim);
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 5a78513..dc9bab0 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -223,8 +223,15 @@ while [ "x$list" != "x" ] ; do
     gettext_printf "Found initrd image: %s\n" "${dirname}/${initrd}" >&2
   elif test -z "${initramfs}" ; then
     # "UUID=" and "ZFS=" magic is parsed by initrd or initramfs.  Since there's
-    # no initrd or builtin initramfs, it can't work here.
-    linux_root_device_thisversion=${GRUB_DEVICE}
+    # no initrd or builtin initramfs, it can't work here.  However, if
+    # GRUB_DEVICE_PARTUUID is not empty we can use that here if
+    # GRUD_DISABLE_LINUX_UUID is not set to true.
+    if [ "x${GRUB_DISABLE_LINUX_UUID}" != "xtrue" ]
+        && [ "x${GRUB_DEVICE_PARTUUID}" != "x" ]; then
+        linux_root_device_thisversion="PARTUUID=${GRUB_DEVICE_PARTUUID}"
+    else
+        linux_root_device_thisversion=${GRUB_DEVICE}
+    fi
   fi
 
   if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xy ]; then
