OSDN Git Service

gpt: add partition attribute bits: NoBlockIOProtocol, LegacyBIOSBootable
[android-x86/external-parted.git] / libparted / labels / gpt.c
index 5037d9b..46e6077 100644 (file)
@@ -4,7 +4,7 @@
     original version by Matt Domsch <Matt_Domsch@dell.com>
     Disclaimed into the Public Domain
 
-    Portions Copyright (C) 2001-2003, 2005-2009 Free Software Foundation, Inc.
+    Portions Copyright (C) 2001-2003, 2005-2010 Free Software Foundation, Inc.
 
     EFI GUID Partition Table handling
     Per Intel EFI Specification v1.02
@@ -40,6 +40,7 @@
 #include <stdbool.h>
 #include <errno.h>
 #include "xalloc.h"
+#include "verify.h"
 
 #include "pt-tools.h"
 
@@ -69,6 +70,8 @@ typedef struct _GuidPartitionEntry_t GuidPartitionEntry_t;
 typedef struct _PartitionRecord_t PartitionRecord_t;
 typedef struct _LegacyMBR_t LegacyMBR_t;
 typedef struct _GPTDiskData GPTDiskData;
+
+
 typedef struct
 {
   uint32_t time_low;
@@ -103,6 +106,10 @@ typedef struct
     ((efi_guid_t) { PED_CPU_TO_LE32 (0xE3C9E316), PED_CPU_TO_LE16 (0x0B5C), \
                     PED_CPU_TO_LE16 (0x4DB8), 0x81, 0x7D, \
                     { 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE }})
+#define PARTITION_MSFT_RECOVERY \
+    ((efi_guid_t) { PED_CPU_TO_LE32 (0xDE94BBA4), PED_CPU_TO_LE16 (0x06D1), \
+                    PED_CPU_TO_LE16 (0x4D40), 0xA1, 0x6A, \
+                    { 0xBF, 0xD5, 0x01, 0x79, 0xD6, 0xAC }})
 #define PARTITION_BASIC_DATA_GUID \
     ((efi_guid_t) { PED_CPU_TO_LE32 (0xEBD0A0A2), PED_CPU_TO_LE16 (0xB9E5), \
                     PED_CPU_TO_LE16 (0x4433), 0x87, 0xC0, \
@@ -131,6 +138,10 @@ typedef struct
     ((efi_guid_t) { PED_CPU_TO_LE32 (0x48465300), PED_CPU_TO_LE16 (0x0000), \
                     PED_CPU_TO_LE16 (0x11AA), 0xaa, 0x11, \
                     { 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC }})
+#define PARTITION_APPLE_TV_RECOVERY_GUID \
+    ((efi_guid_t) { PED_CPU_TO_LE32 (0x5265636F), PED_CPU_TO_LE16 (0x7665), \
+                    PED_CPU_TO_LE16 (0x11AA), 0xaa, 0x11, \
+                    { 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC }})
 
 struct __attribute__ ((packed)) _GuidPartitionTableHeader_t
 {
@@ -155,12 +166,16 @@ struct __attribute__ ((packed)) _GuidPartitionEntryAttributes_t
 {
 #ifdef __GNUC__                        /* XXX narrow this down to !TinyCC */
   uint64_t RequiredToFunction:1;
-  uint64_t Reserved:47;
+  uint64_t NoBlockIOProtocol:1;
+  uint64_t LegacyBIOSBootable:1;
+  uint64_t Reserved:45;
   uint64_t GuidSpecific:16;
 #else
 #       warning "Using crippled partition entry type"
   uint32_t RequiredToFunction:1;
-  uint32_t Reserved:32;
+  uint32_t NoBlockIOProtocol:1;
+  uint32_t LegacyBIOSBootable:1;
+  uint32_t Reserved:30;
   uint32_t LOST:5;
   uint32_t GuidSpecific:16;
 #endif
@@ -264,6 +279,8 @@ typedef struct _GPTPartitionData
   int hp_service;
   int hidden;
   int msftres;
+  int atvrecv;
+  int msftrecv;
 } GPTPartitionData;
 
 static PedDiskType gpt_disk_type;
@@ -439,11 +456,14 @@ static int
 gpt_probe (const PedDevice *dev)
 {
   GuidPartitionTableHeader_t *gpt = NULL;
-  uint8_t *pth_raw = ped_malloc (pth_get_size (dev));
   int gpt_sig_found = 0;
 
   PED_ASSERT (dev != NULL, return 0);
 
+  if (dev->length <= 1)
+    return 0;
+
+  void *pth_raw = ped_malloc (pth_get_size (dev));
   if (ped_device_read (dev, pth_raw, 1, GPT_HEADER_SECTORS)
       || ped_device_read (dev, pth_raw, dev->length - 1, GPT_HEADER_SECTORS))
     {
@@ -486,57 +506,6 @@ gpt_probe (const PedDevice *dev)
   return ok;
 }
 
-#ifndef DISCOVER_ONLY
-/* writes zeros to the PMBR and the primary and alternate GPTHs and PTEs */
-static int
-gpt_clobber (PedDevice *dev)
-{
-  uint8_t *pth_raw = ped_malloc (pth_get_size (dev));
-  GuidPartitionTableHeader_t *gpt;
-
-  PED_ASSERT (dev != NULL, return 0);
-
-  /*
-   * TO DISCUSS: check whether checksum is correct?
-   * If not, we might get a wrong AlternateLBA field and destroy
-   * one sector of random data.
-   */
-  if (!ped_device_read (dev, pth_raw,
-                        GPT_PRIMARY_HEADER_LBA, GPT_HEADER_SECTORS))
-    {
-      free (pth_raw);
-      return 0;
-    }
-
-  gpt = pth_new_from_raw (dev, pth_raw);
-  free (pth_raw);
-
-  if (!ptt_clear_sectors (dev, GPT_PMBR_LBA, GPT_PMBR_SECTORS))
-    goto error_free_with_gpt;
-  if (!ptt_clear_sectors (dev, GPT_PRIMARY_HEADER_LBA, GPT_HEADER_SECTORS))
-    goto error_free_with_gpt;
-  if (!ptt_clear_sectors (dev, dev->length - GPT_HEADER_SECTORS,
-                          GPT_HEADER_SECTORS))
-    goto error_free_with_gpt;
-
-  if ((PedSector) PED_LE64_TO_CPU (gpt->AlternateLBA) < dev->length - 1)
-    {
-      if (!ped_device_write (dev, gpt,
-                             PED_LE64_TO_CPU (gpt->AlternateLBA),
-                             GPT_HEADER_SECTORS))
-        return 0;
-    }
-
-  pth_free (gpt);
-
-  return 1;
-
-error_free_with_gpt:
-  pth_free (gpt);
-  return 0;
-}
-#endif /* !DISCOVER_ONLY */
-
 static PedDisk *
 gpt_alloc (const PedDevice *dev)
 {
@@ -717,7 +686,7 @@ _parse_header (PedDisk *disk, const GuidPartitionTableHeader_t *gpt,
            PED_EXCEPTION_IGNORE_CANCEL,
            _("The format of the GPT partition table is version "
              "%x, which is newer than what Parted can "
-             "recognise.  Please tell us!  bug-parted@gnu.org"),
+             "recognise.  Please report this!"),
            PED_LE32_TO_CPU (gpt->Revision)) != PED_EXCEPTION_IGNORE)
         return 0;
     }
@@ -816,7 +785,8 @@ _parse_part_entry (PedDisk *disk, GuidPartitionEntry_t *pte)
   gpt_part_data->lvm = gpt_part_data->raid
     = gpt_part_data->boot = gpt_part_data->hp_service
     = gpt_part_data->hidden = gpt_part_data->msftres
-    = gpt_part_data->bios_grub = 0;
+    = gpt_part_data->msftrecv
+    = gpt_part_data->bios_grub = gpt_part_data->atvrecv = 0;
 
   if (pte->Attributes.RequiredToFunction & 0x1)
     gpt_part_data->hidden = 1;
@@ -833,6 +803,10 @@ _parse_part_entry (PedDisk *disk, GuidPartitionEntry_t *pte)
     gpt_part_data->hp_service = 1;
   else if (!guid_cmp (gpt_part_data->type, PARTITION_MSFT_RESERVED_GUID))
     gpt_part_data->msftres = 1;
+  else if (!guid_cmp (gpt_part_data->type, PARTITION_MSFT_RECOVERY))
+    gpt_part_data->msftrecv = 1;
+  else if (!guid_cmp (gpt_part_data->type, PARTITION_APPLE_TV_RECOVERY_GUID))
+    gpt_part_data->atvrecv = 1;
 
   return part;
 }
@@ -925,7 +899,7 @@ gpt_read (PedDisk *disk)
   GPTDiskData *gpt_disk_data = disk->disk_specific;
   int i;
 #ifndef DISCOVER_ONLY
-  int write_back = 1;
+  int write_back = 0;
 #endif
 
   ped_disk_delete_all (disk);
@@ -959,9 +933,9 @@ gpt_read (PedDisk *disk)
   if (primary_gpt && backup_gpt)
     {
       /* Both are valid.  */
+#ifndef DISCOVER_ONLY
       if (PED_LE64_TO_CPU (primary_gpt->AlternateLBA) < disk->dev->length - 1)
         {
-#ifndef DISCOVER_ONLY
           switch (ped_exception_throw
                   (PED_EXCEPTION_ERROR,
                    (PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL
@@ -976,13 +950,13 @@ gpt_read (PedDisk *disk)
             case PED_EXCEPTION_FIX:
               ptt_clear_sectors (disk->dev,
                                  PED_LE64_TO_CPU (primary_gpt->AlternateLBA), 1);
+              write_back = 1;
               break;
             default:
-              write_back = 0;
               break;
             }
-#endif /* !DISCOVER_ONLY */
         }
+#endif /* !DISCOVER_ONLY */
       gpt = primary_gpt;
       pth_free (backup_gpt);
     }
@@ -1047,7 +1021,6 @@ gpt_read (PedDisk *disk)
       GuidPartitionEntry_t *pte
         = (GuidPartitionEntry_t *) ((char *) ptes + i * p_ent_size);
       PedPartition *part;
-      PedConstraint *constraint_exact;
 
       if (!guid_cmp (pte->PartitionTypeGuid, UNUSED_ENTRY_GUID))
         continue;
@@ -1059,9 +1032,10 @@ gpt_read (PedDisk *disk)
       part->fs_type = ped_file_system_probe (&part->geom);
       part->num = i + 1;
 
-      constraint_exact = ped_constraint_exact (&part->geom);
+      PedConstraint *constraint_exact = ped_constraint_exact (&part->geom);
       if (!ped_disk_add_partition (disk, part, constraint_exact))
         {
+          ped_constraint_destroy (constraint_exact);
           ped_partition_destroy (part);
           goto error_delete_all;
         }
@@ -1235,12 +1209,14 @@ gpt_write (const PedDisk *disk)
     goto error_free_ptes;
 
   /* Write PTH and PTEs */
+  /* FIXME: Caution: this code is nearly identical to what's just below. */
   if (_generate_header (disk, 0, ptes_crc, &gpt) != 0)
     goto error_free_ptes;
-  if ((pth_raw = pth_get_raw (disk->dev, gpt)) == NULL)
-    goto error_free_ptes;
+  pth_raw = pth_get_raw (disk->dev, gpt);
   pth_free (gpt);
-  bool write_ok = ped_device_write (disk->dev, pth_raw, 1, 1);
+  if (pth_raw == NULL)
+    goto error_free_ptes;
+  int write_ok = ped_device_write (disk->dev, pth_raw, 1, 1);
   free (pth_raw);
   if (!write_ok)
     goto error_free_ptes;
@@ -1249,11 +1225,13 @@ gpt_write (const PedDisk *disk)
     goto error_free_ptes;
 
   /* Write Alternate PTH & PTEs */
+  /* FIXME: Caution: this code is nearly identical to what's just above. */
   if (_generate_header (disk, 1, ptes_crc, &gpt) != 0)
     goto error_free_ptes;
-  if ((pth_raw = pth_get_raw (disk->dev, gpt)) == NULL)
-    goto error_free_ptes;
+  pth_raw = pth_get_raw (disk->dev, gpt);
   pth_free (gpt);
+  if (pth_raw == NULL)
+    goto error_free_ptes;
   write_ok = ped_device_write (disk->dev, pth_raw, disk->dev->length - 1, 1);
   free (pth_raw);
   if (!write_ok)
@@ -1267,7 +1245,6 @@ gpt_write (const PedDisk *disk)
   free (ptes);
   return ped_device_sync (disk->dev);
 
-  free (pth_raw);
 error_free_ptes:
   free (ptes);
 error:
@@ -1329,6 +1306,8 @@ gpt_partition_new (const PedDisk *disk,
   gpt_part_data->hp_service = 0;
   gpt_part_data->hidden = 0;
   gpt_part_data->msftres = 0;
+  gpt_part_data->msftrecv = 0;
+  gpt_part_data->atvrecv = 0;
   uuid_generate ((unsigned char *) &gpt_part_data->uuid);
   swap_uuid_and_efi_guid ((unsigned char *) (&gpt_part_data->uuid));
   memset (gpt_part_data->name, 0, sizeof gpt_part_data->name);
@@ -1424,6 +1403,16 @@ gpt_partition_set_system (PedPartition *part,
       gpt_part_data->type = PARTITION_MSFT_RESERVED_GUID;
       return 1;
     }
+  if (gpt_part_data->msftrecv)
+    {
+      gpt_part_data->type = PARTITION_MSFT_RECOVERY;
+      return 1;
+    }
+  if (gpt_part_data->atvrecv)
+    {
+      gpt_part_data->type = PARTITION_APPLE_TV_RECOVERY_GUID;
+      return 1;
+    }
 
   if (fs_type)
     {
@@ -1521,7 +1510,10 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
         gpt_part_data->raid
           = gpt_part_data->lvm
           = gpt_part_data->bios_grub
-          = gpt_part_data->hp_service = gpt_part_data->msftres = 0;
+          = gpt_part_data->hp_service
+          = gpt_part_data->msftres
+          = gpt_part_data->msftrecv
+          = gpt_part_data->atvrecv = 0;
       return gpt_partition_set_system (part, part->fs_type);
     case PED_PARTITION_BIOS_GRUB:
       gpt_part_data->bios_grub = state;
@@ -1529,7 +1521,10 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
         gpt_part_data->raid
           = gpt_part_data->lvm
           = gpt_part_data->boot
-          = gpt_part_data->hp_service = gpt_part_data->msftres = 0;
+          = gpt_part_data->hp_service
+          = gpt_part_data->msftres
+          = gpt_part_data->msftrecv
+          = gpt_part_data->atvrecv = 0;
       return gpt_partition_set_system (part, part->fs_type);
     case PED_PARTITION_RAID:
       gpt_part_data->raid = state;
@@ -1537,7 +1532,10 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
         gpt_part_data->boot
           = gpt_part_data->lvm
           = gpt_part_data->bios_grub
-          = gpt_part_data->hp_service = gpt_part_data->msftres = 0;
+          = gpt_part_data->hp_service
+          = gpt_part_data->msftres
+          = gpt_part_data->msftrecv
+          = gpt_part_data->atvrecv = 0;
       return gpt_partition_set_system (part, part->fs_type);
     case PED_PARTITION_LVM:
       gpt_part_data->lvm = state;
@@ -1545,7 +1543,10 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
         gpt_part_data->boot
           = gpt_part_data->raid
           = gpt_part_data->bios_grub
-          = gpt_part_data->hp_service = gpt_part_data->msftres = 0;
+          = gpt_part_data->hp_service
+          = gpt_part_data->msftres
+          = gpt_part_data->msftrecv
+          = gpt_part_data->atvrecv = 0;
       return gpt_partition_set_system (part, part->fs_type);
     case PED_PARTITION_HPSERVICE:
       gpt_part_data->hp_service = state;
@@ -1553,7 +1554,10 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
         gpt_part_data->boot
           = gpt_part_data->raid
           = gpt_part_data->lvm
-          = gpt_part_data->bios_grub = gpt_part_data->msftres = 0;
+          = gpt_part_data->bios_grub
+          = gpt_part_data->msftres
+          = gpt_part_data->msftrecv
+          = gpt_part_data->atvrecv = 0;
       return gpt_partition_set_system (part, part->fs_type);
     case PED_PARTITION_MSFT_RESERVED:
       gpt_part_data->msftres = state;
@@ -1561,7 +1565,32 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
         gpt_part_data->boot
           = gpt_part_data->raid
           = gpt_part_data->lvm
-          = gpt_part_data->bios_grub = gpt_part_data->hp_service = 0;
+          = gpt_part_data->bios_grub
+          = gpt_part_data->hp_service
+          = gpt_part_data->msftrecv
+          = gpt_part_data->atvrecv = 0;
+      return gpt_partition_set_system (part, part->fs_type);
+    case PED_PARTITION_DIAG:
+      gpt_part_data->msftrecv = state;
+      if (state)
+        gpt_part_data->boot
+          = gpt_part_data->raid
+          = gpt_part_data->lvm
+          = gpt_part_data->bios_grub
+          = gpt_part_data->hp_service
+          = gpt_part_data->msftres
+          = gpt_part_data->atvrecv = 0;
+      return gpt_partition_set_system (part, part->fs_type);
+    case PED_PARTITION_APPLE_TV_RECOVERY:
+      gpt_part_data->atvrecv = state;
+      if (state)
+        gpt_part_data->boot
+          = gpt_part_data->raid
+          = gpt_part_data->lvm
+          = gpt_part_data->bios_grub
+          = gpt_part_data->hp_service
+          = gpt_part_data->msftres
+          = gpt_part_data->msftrecv = 0;
       return gpt_partition_set_system (part, part->fs_type);
     case PED_PARTITION_HIDDEN:
       gpt_part_data->hidden = state;
@@ -1596,6 +1625,10 @@ gpt_partition_get_flag (const PedPartition *part, PedPartitionFlag flag)
       return gpt_part_data->hp_service;
     case PED_PARTITION_MSFT_RESERVED:
       return gpt_part_data->msftres;
+    case PED_PARTITION_DIAG:
+      return gpt_part_data->msftrecv;
+    case PED_PARTITION_APPLE_TV_RECOVERY:
+      return gpt_part_data->atvrecv;
     case PED_PARTITION_HIDDEN:
       return gpt_part_data->hidden;
     case PED_PARTITION_SWAP:
@@ -1619,6 +1652,8 @@ gpt_partition_is_flag_available (const PedPartition *part,
     case PED_PARTITION_BIOS_GRUB:
     case PED_PARTITION_HPSERVICE:
     case PED_PARTITION_MSFT_RESERVED:
+    case PED_PARTITION_DIAG:
+    case PED_PARTITION_APPLE_TV_RECOVERY:
     case PED_PARTITION_HIDDEN:
       return 1;
     case PED_PARTITION_SWAP:
@@ -1724,42 +1759,18 @@ gpt_partition_align (PedPartition *part, const PedConstraint *constraint)
   return 0;
 }
 
-static bool
-gpt_partition_check (const PedPartition *part)
-{
-  return true;
-}
-
-#ifdef DISCOVER_ONLY
-# define NULL_IF_DISCOVER_ONLY(val) NULL
-#else
-# define NULL_IF_DISCOVER_ONLY(val) val
-#endif
+#include "pt-common.h"
+PT_define_limit_functions (gpt)
 
 static PedDiskOps gpt_disk_ops =
 {
-  probe:                       gpt_probe,
-  clobber:                     NULL_IF_DISCOVER_ONLY (gpt_clobber),
-  alloc:                       gpt_alloc,
-  duplicate:                   gpt_duplicate,
-  free:                                gpt_free,
-  read:                                gpt_read,
+  clobber:                     NULL,
   write:                       NULL_IF_DISCOVER_ONLY (gpt_write),
-  partition_new:               gpt_partition_new,
-  partition_duplicate:         gpt_partition_duplicate,
-  partition_destroy:           gpt_partition_destroy,
-  partition_set_system:                gpt_partition_set_system,
-  partition_set_flag:          gpt_partition_set_flag,
-  partition_get_flag:          gpt_partition_get_flag,
-  partition_is_flag_available: gpt_partition_is_flag_available,
+
   partition_set_name:          gpt_partition_set_name,
   partition_get_name:          gpt_partition_get_name,
-  partition_align:             gpt_partition_align,
-  partition_enumerate:         gpt_partition_enumerate,
-  partition_check:             gpt_partition_check,
-  alloc_metadata:              gpt_alloc_metadata,
-  get_max_primary_partition_count: gpt_get_max_primary_partition_count,
-  get_max_supported_partition_count: gpt_get_max_supported_partition_count
+
+  PT_op_function_initializers (gpt)
 };
 
 static PedDiskType gpt_disk_type =
@@ -1773,9 +1784,6 @@ static PedDiskType gpt_disk_type =
 void
 ped_disk_gpt_init ()
 {
-  PED_ASSERT (sizeof (GuidPartitionEntryAttributes_t) == 8, return);
-  PED_ASSERT (sizeof (GuidPartitionEntry_t) == 128, return);
-
   ped_disk_type_register (&gpt_disk_type);
 }
 
@@ -1784,3 +1792,6 @@ ped_disk_gpt_done ()
 {
   ped_disk_type_unregister (&gpt_disk_type);
 }
+
+verify (sizeof (GuidPartitionEntryAttributes_t) == 8);
+verify (sizeof (GuidPartitionEntry_t) == 128);