~ubuntu-branches/ubuntu/vivid/parted/vivid

« back to all changes in this revision

Viewing changes to .pc/gpt-prep.patch/libparted/labels/gpt.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2014-07-21 10:23:16 UTC
  • mfrom: (7.2.32 sid)
  • Revision ID: package-import@ubuntu.com-20140721102316-jsyv3yzmbo8vlde5
Tags: 3.1-3
Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
    original version by Matt Domsch <Matt_Domsch@dell.com>
5
5
    Disclaimed into the Public Domain
6
6
 
7
 
    Portions Copyright (C) 2001-2003, 2005-2011 Free Software Foundation, Inc.
 
7
    Portions Copyright (C) 2001-2003, 2005-2012 Free Software Foundation, Inc.
8
8
 
9
9
    EFI GUID Partition Table handling
10
10
    Per Intel EFI Specification v1.02
47
47
#include <stdbool.h>
48
48
#include <errno.h>
49
49
#include "xalloc.h"
 
50
#include "verify.h"
50
51
 
51
52
#include "pt-tools.h"
52
53
 
76
77
typedef struct _PartitionRecord_t PartitionRecord_t;
77
78
typedef struct _LegacyMBR_t LegacyMBR_t;
78
79
typedef struct _GPTDiskData GPTDiskData;
 
80
 
 
81
 
79
82
typedef struct
80
83
{
81
84
  uint32_t time_low;
276
279
  PedGeometry data_area;
277
280
  int entry_count;
278
281
  efi_guid_t uuid;
 
282
  int pmbr_boot;
279
283
};
280
284
 
281
285
/* uses libparted's disk_specific field in PedPartition, to store our info */
596
600
{
597
601
  GuidPartitionTableHeader_t *pth = pth_new (dev);
598
602
 
599
 
  PED_ASSERT (pth_raw != NULL, return 0);
 
603
  PED_ASSERT (pth_raw != NULL);
600
604
 
601
605
  memcpy (pth, pth_raw, pth_get_size_static (dev));
602
606
  memcpy (pth->Reserved2, pth_raw + pth_get_size_static (dev),
610
614
{
611
615
  if (pth == NULL)
612
616
    return;
613
 
  PED_ASSERT (pth->Reserved2 != NULL, return);
 
617
  PED_ASSERT (pth->Reserved2 != NULL);
614
618
 
615
619
  free (pth->Reserved2);
616
620
  free (pth);
619
623
static uint8_t *
620
624
pth_get_raw (const PedDevice *dev, const GuidPartitionTableHeader_t *pth)
621
625
{
622
 
  PED_ASSERT (pth != NULL, return 0);
623
 
  PED_ASSERT (pth->Reserved2 != NULL, return 0);
 
626
  PED_ASSERT (pth != NULL);
 
627
  PED_ASSERT (pth->Reserved2 != NULL);
624
628
 
625
629
  int size_static = pth_get_size_static (dev);
626
630
  uint8_t *pth_raw = ped_malloc (pth_get_size (dev));
658
662
{
659
663
  efi_guid_t *guid = (efi_guid_t *) uuid;
660
664
 
661
 
  PED_ASSERT (uuid != NULL, return);
 
665
  PED_ASSERT (uuid != NULL);
662
666
  guid->time_low = PED_SWAP32 (guid->time_low);
663
667
  guid->time_mid = PED_SWAP16 (guid->time_mid);
664
668
  guid->time_hi_and_version = PED_SWAP16 (guid->time_hi_and_version);
681
685
pth_crc32 (const PedDevice *dev, const GuidPartitionTableHeader_t *pth,
682
686
           uint32_t *crc32)
683
687
{
684
 
  PED_ASSERT (dev != NULL, return 0);
685
 
  PED_ASSERT (pth != NULL, return 0);
 
688
  PED_ASSERT (dev != NULL);
 
689
  PED_ASSERT (pth != NULL);
686
690
 
687
691
  uint8_t *pth_raw = pth_get_raw (dev, pth);
688
692
  if (pth_raw == NULL)
701
705
}
702
706
 
703
707
/* checks if 'mbr' is a protective MBR partition table */
704
 
static inline int
 
708
static inline int _GL_ATTRIBUTE_PURE
705
709
_pmbr_is_valid (const LegacyMBR_t *mbr)
706
710
{
707
711
  int i;
708
712
 
709
 
  PED_ASSERT (mbr != NULL, return 0);
 
713
  PED_ASSERT (mbr != NULL);
710
714
 
711
715
  if (mbr->Signature != PED_CPU_TO_LE16 (MSDOS_MBR_SIGNATURE))
712
716
    return 0;
724
728
  GuidPartitionTableHeader_t *gpt = NULL;
725
729
  int gpt_sig_found = 0;
726
730
 
727
 
  PED_ASSERT (dev != NULL, return 0);
 
731
  PED_ASSERT (dev != NULL);
728
732
 
729
733
  if (dev->length <= 1)
730
734
    return 0;
785
789
  disk = _ped_disk_alloc ((PedDevice *) dev, &gpt_disk_type);
786
790
  if (!disk)
787
791
    goto error;
788
 
  disk->disk_specific = gpt_disk_data = ped_malloc (sizeof (GPTDiskData));
789
 
  if (!disk->disk_specific)
790
 
    goto error_free_disk;
791
792
 
792
793
  data_start = 2 + GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE / dev->sector_size;
793
794
  data_end = dev->length - 2
794
795
    - GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE / dev->sector_size;
 
796
 
 
797
  /* If the device is too small to have room for data, reject it.  */
 
798
  if (data_end <= data_start)
 
799
    goto error_free_disk;
 
800
 
 
801
  disk->disk_specific = gpt_disk_data = ped_malloc (sizeof (GPTDiskData));
 
802
  if (!disk->disk_specific)
 
803
    goto error_free_disk;
 
804
 
795
805
  ped_geometry_init (&gpt_disk_data->data_area, dev, data_start,
796
806
                     data_end - data_start + 1);
797
807
  gpt_disk_data->entry_count = GPT_DEFAULT_PARTITION_ENTRIES;
798
808
  uuid_generate ((unsigned char *) &gpt_disk_data->uuid);
799
809
  swap_uuid_and_efi_guid ((unsigned char *) (&gpt_disk_data->uuid));
 
810
  gpt_disk_data->pmbr_boot = 0;
800
811
  return disk;
801
812
 
802
813
error_free_disk:
904
915
 
905
916
  /* The SizeOfPartitionEntry must be a multiple of 8 and
906
917
     no smaller than the size of the PartitionEntry structure.
907
 
     We also require that be no larger than 1/16th of UINT32_MAX,
 
918
     We also require that it be no larger than 1/16th of UINT32_MAX,
908
919
     as an additional sanity check.  */
909
 
  uint32_t sope = PED_LE32_TO_CPU (gpt->SizeOfPartitionEntry);
910
 
  if (sope % 8 != 0
911
 
      || sope < sizeof (GuidPartitionEntry_t) || (UINT32_MAX >> 4) < sope)
 
920
  uint32_t pe_size = PED_LE32_TO_CPU (gpt->SizeOfPartitionEntry);
 
921
  if (pe_size % 8 != 0
 
922
      || ! (sizeof (GuidPartitionEntry_t) <= pe_size
 
923
            && pe_size <= (UINT32_MAX >> 4)))
912
924
    return 0;
913
925
 
914
926
  if (PED_LE64_TO_CPU (gpt->MyLBA) != my_lba)
927
939
  if (check_PE_array_CRC (disk, gpt, &crc_match) != 0 || !crc_match)
928
940
    return 0;
929
941
 
 
942
  PedSector first_usable = PED_LE64_TO_CPU (gpt->FirstUsableLBA);
 
943
  if (first_usable < 3)
 
944
    return 0;
 
945
 
930
946
  origcrc = gpt->HeaderCRC32;
931
947
  gpt->HeaderCRC32 = 0;
932
948
  if (pth_crc32 (dev, gpt, &crc) != 0)
954
970
           PED_EXCEPTION_IGNORE_CANCEL,
955
971
           _("The format of the GPT partition table is version "
956
972
             "%x, which is newer than what Parted can "
957
 
             "recognise.  Please tell us!  bug-parted@gnu.org"),
 
973
             "recognise.  Please report this!"),
958
974
           PED_LE32_TO_CPU (gpt->Revision)) != PED_EXCEPTION_IGNORE)
959
975
        return 0;
960
976
    }
981
997
    GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE / disk->dev->sector_size;
982
998
 
983
999
  if (last_usable_if_grown > last_usable_min_default)
984
 
    {
985
 
      last_usable_if_grown = last_usable_min_default;
986
 
    }
987
 
 
988
 
  PED_ASSERT (last_usable > first_usable, return 0);
989
 
  PED_ASSERT (last_usable <= disk->dev->length, return 0);
990
 
 
991
 
  PED_ASSERT (last_usable_if_grown > first_usable, return 0);
992
 
  PED_ASSERT (last_usable_if_grown <= disk->dev->length, return 0);
 
1000
    last_usable_if_grown = last_usable_min_default;
 
1001
 
 
1002
  if (last_usable <= first_usable
 
1003
      || disk->dev->length < last_usable)
 
1004
    return 0;
 
1005
 
 
1006
  if (last_usable_if_grown <= first_usable
 
1007
      || disk->dev->length < last_usable_if_grown)
 
1008
    return 0;
993
1009
 
994
1010
  if (!asked_already && last_usable < last_usable_if_grown)
995
1011
    {
996
 
 
997
1012
      PedExceptionOption q;
998
1013
 
999
1014
      q = ped_exception_throw
1021
1036
 
1022
1037
  gpt_disk_data->entry_count
1023
1038
    = PED_LE32_TO_CPU (gpt->NumberOfPartitionEntries);
1024
 
  PED_ASSERT (gpt_disk_data->entry_count > 0, return 0);
1025
 
  PED_ASSERT (gpt_disk_data->entry_count <= 8192, return 0);
 
1039
  PED_ASSERT (gpt_disk_data->entry_count > 0);
 
1040
  PED_ASSERT (gpt_disk_data->entry_count <= 8192);
1026
1041
 
1027
1042
  gpt_disk_data->uuid = gpt->DiskGUID;
1028
1043
 
1092
1107
   Return 1 if any read fails.
1093
1108
   Upon successful verification of the primary GPT, set *PRIMARY_GPT, else NULL.
1094
1109
   Upon successful verification of the backup GPT, set *BACKUP_GPT, else NULL.
1095
 
   If we've set *BACKUP_GPT to non-NULL, set *BACKUP_LBA to the sector
 
1110
   If we've set *BACKUP_GPT to non-NULL, set *BACKUP_SECTOR_NUM_P to the sector
1096
1111
   number in which it was found.  */
1097
1112
static int
1098
1113
gpt_read_headers (PedDisk const *disk,
1103
1118
  *primary_gpt = NULL;
1104
1119
  *backup_gpt = NULL;
1105
1120
  PedDevice const *dev = disk->dev;
 
1121
  GPTDiskData *gpt_disk_data = disk->disk_specific;
 
1122
  LegacyMBR_t *mbr;
 
1123
 
 
1124
  if (!ptt_read_sector (dev, 0, (void *)&mbr))
 
1125
    return 1;
 
1126
 
 
1127
  if (mbr->PartitionRecord[0].BootIndicator == 0x80)
 
1128
    gpt_disk_data->pmbr_boot = 1;
 
1129
  free (mbr);
1106
1130
 
1107
1131
  void *s1;
1108
1132
  if (!ptt_read_sector (dev, 1, &s1))
1344
1368
#ifndef DISCOVER_ONLY
1345
1369
/* Write the protective MBR (to keep DOS happy) */
1346
1370
static int
1347
 
_write_pmbr (PedDevice *dev)
 
1371
_write_pmbr (PedDevice *dev, bool pmbr_boot)
1348
1372
{
1349
1373
  /* The UEFI spec is not clear about what to do with the following
1350
1374
     elements of the Protective MBR (pmbr): BootCode (0-440B),
1369
1393
    pmbr->PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32 (0xFFFFFFFF);
1370
1394
  else
1371
1395
    pmbr->PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32 (dev->length - 1UL);
 
1396
  if (pmbr_boot)
 
1397
    pmbr->PartitionRecord[0].BootIndicator = 0x80;
1372
1398
 
1373
1399
  int write_ok = ped_device_write (dev, pmbr, GPT_PMBR_LBA,
1374
1400
                                   GPT_PMBR_SECTORS);
1522
1548
    {
1523
1549
      size_t ss = disk->dev->sector_size;
1524
1550
      PedSector ptes_bytes = (gpt_disk_data->entry_count
1525
 
                              * sizeof (GuidPartitionEntry_t));
 
1551
                              * sizeof (GuidPartitionEntry_t));
1526
1552
      PedSector ptes_sectors = (ptes_bytes + ss - 1) / ss;
1527
1553
 
1528
1554
      gpt->MyLBA = PED_CPU_TO_LE64 (disk->dev->length - 1);
1559
1585
  GPTPartitionData *gpt_part_data = part->disk_specific;
1560
1586
  unsigned int i;
1561
1587
 
1562
 
  PED_ASSERT (gpt_part_data != NULL, return);
 
1588
  PED_ASSERT (gpt_part_data != NULL);
1563
1589
 
1564
1590
  pte->PartitionTypeGuid = gpt_part_data->type;
1565
1591
  pte->UniquePartitionGuid = gpt_part_data->uuid;
1586
1612
  GuidPartitionTableHeader_t *gpt;
1587
1613
  PedPartition *part;
1588
1614
 
1589
 
  PED_ASSERT (disk != NULL, goto error);
1590
 
  PED_ASSERT (disk->dev != NULL, goto error);
1591
 
  PED_ASSERT (disk->disk_specific != NULL, goto error);
 
1615
  PED_ASSERT (disk != NULL);
 
1616
  PED_ASSERT (disk->dev != NULL);
 
1617
  PED_ASSERT (disk->disk_specific != NULL);
1592
1618
 
1593
1619
  gpt_disk_data = disk->disk_specific;
1594
1620
 
1595
1621
  size_t ptes_bytes = (gpt_disk_data->entry_count
1596
 
                       * sizeof (GuidPartitionEntry_t));
1597
 
  GuidPartitionEntry_t *ptes = malloc (ptes_bytes);
 
1622
                        * sizeof (GuidPartitionEntry_t));
 
1623
  size_t ss = disk->dev->sector_size;
 
1624
  PedSector ptes_sectors = (ptes_bytes + ss - 1) / ss;
 
1625
  /* Note that we allocate a little more than ptes_bytes,
 
1626
     when that number is not a multiple of sector size.  */
 
1627
  GuidPartitionEntry_t *ptes = calloc (ptes_sectors, ss);
1598
1628
  if (!ptes)
1599
1629
    goto error;
1600
 
  memset (ptes, 0, ptes_bytes);
1601
1630
  for (part = ped_disk_next_partition (disk, NULL); part;
1602
1631
       part = ped_disk_next_partition (disk, part))
1603
1632
    {
1614
1643
      goto error_free_ptes;
1615
1644
  } else {
1616
1645
    /* Write protective MBR */
1617
 
    if (!_write_pmbr (disk->dev))
 
1646
    if (!_write_pmbr (disk->dev, gpt_disk_data->pmbr_boot))
1618
1647
      goto error_free_ptes;
1619
1648
  }
1620
1649
 
1630
1659
  free (pth_raw);
1631
1660
  if (!write_ok)
1632
1661
    goto error_free_ptes;
1633
 
  size_t ss = disk->dev->sector_size;
1634
 
  PedSector ptes_sectors = (ptes_bytes + ss - 1) / ss;
1635
1662
  if (!ped_device_write (disk->dev, ptes, 2, ptes_sectors))
1636
1663
    goto error_free_ptes;
1637
1664
 
1666
1693
{
1667
1694
  PedPartition *part;
1668
1695
  PedConstraint *constraint_exact;
1669
 
  PED_ASSERT (disk != NULL, return 0);
 
1696
  PED_ASSERT (disk != NULL);
1670
1697
 
1671
1698
  part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL,
1672
1699
                            start, start + length - 1);
1765
1792
{
1766
1793
  if (part->type == 0)
1767
1794
    {
1768
 
      PED_ASSERT (part->disk_specific != NULL, return);
 
1795
      PED_ASSERT (part->disk_specific != NULL);
1769
1796
      free (part->disk_specific);
1770
1797
    }
1771
1798
 
1778
1805
{
1779
1806
  GPTPartitionData *gpt_part_data = part->disk_specific;
1780
1807
 
1781
 
  PED_ASSERT (gpt_part_data != NULL, return 0);
 
1808
  PED_ASSERT (gpt_part_data != NULL);
1782
1809
 
1783
1810
  part->fs_type = fs_type;
1784
1811
 
1864
1891
  PedSector gptlength, pteslength = 0;
1865
1892
  GPTDiskData *gpt_disk_data;
1866
1893
 
1867
 
  PED_ASSERT (disk != NULL, return 0);
1868
 
  PED_ASSERT (disk->dev != NULL, return 0);
1869
 
  PED_ASSERT (disk->disk_specific != NULL, return 0);
 
1894
  PED_ASSERT (disk != NULL);
 
1895
  PED_ASSERT (disk->dev != NULL);
 
1896
  PED_ASSERT (disk->disk_specific != NULL);
1870
1897
  gpt_disk_data = disk->disk_specific;
1871
1898
 
1872
1899
  gptlength = ped_div_round_up (sizeof (GuidPartitionTableHeader_t),
1908
1935
        }
1909
1936
    }
1910
1937
 
1911
 
  PED_ASSERT (0, return 0);
 
1938
  PED_ASSERT (0);
1912
1939
 
1913
1940
  return 0;                     /* used if debug is disabled */
1914
1941
}
1915
1942
 
1916
1943
static int
 
1944
gpt_disk_set_flag (PedDisk *disk, PedDiskFlag flag, int state)
 
1945
{
 
1946
  GPTDiskData *gpt_disk_data = disk->disk_specific;
 
1947
  switch (flag)
 
1948
    {
 
1949
    case PED_DISK_GPT_PMBR_BOOT:
 
1950
      gpt_disk_data->pmbr_boot = state;
 
1951
      return 1;
 
1952
    default:
 
1953
      return 0;
 
1954
    }
 
1955
}
 
1956
 
 
1957
static int
 
1958
gpt_disk_is_flag_available(const PedDisk *disk, PedDiskFlag flag)
 
1959
{
 
1960
  switch (flag)
 
1961
    {
 
1962
    case PED_DISK_GPT_PMBR_BOOT:
 
1963
      return 1;
 
1964
    default:
 
1965
      return 0;
 
1966
    }
 
1967
}
 
1968
 
 
1969
static int
 
1970
gpt_disk_get_flag (const PedDisk *disk, PedDiskFlag flag)
 
1971
{
 
1972
  GPTDiskData *gpt_disk_data = disk->disk_specific;
 
1973
  switch (flag)
 
1974
    {
 
1975
    case PED_DISK_GPT_PMBR_BOOT:
 
1976
      return gpt_disk_data->pmbr_boot;
 
1977
      break;
 
1978
    default:
 
1979
      return 0;
 
1980
    }
 
1981
}
 
1982
 
 
1983
static int
1917
1984
gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
1918
1985
{
1919
1986
  GPTPartitionData *gpt_part_data;
1920
 
  PED_ASSERT (part != NULL, return 0);
1921
 
  PED_ASSERT (part->disk_specific != NULL, return 0);
 
1987
  PED_ASSERT (part != NULL);
 
1988
  PED_ASSERT (part->disk_specific != NULL);
1922
1989
  gpt_part_data = part->disk_specific;
1923
1990
 
1924
1991
  switch (flag)
2051
2118
  return 1;
2052
2119
}
2053
2120
 
2054
 
static int
 
2121
static int _GL_ATTRIBUTE_PURE
2055
2122
gpt_partition_get_flag (const PedPartition *part, PedPartitionFlag flag)
2056
2123
{
2057
2124
  GPTPartitionData *gpt_part_data;
2058
 
  PED_ASSERT (part->disk_specific != NULL, return 0);
 
2125
  PED_ASSERT (part->disk_specific != NULL);
2059
2126
  gpt_part_data = part->disk_specific;
2060
2127
 
2061
2128
  switch (flag)
2181
2248
  if (pth == NULL)
2182
2249
    return false;
2183
2250
 
 
2251
  if (!_header_is_valid (disk, pth, 1))
 
2252
    {
 
2253
      pth->FirstUsableLBA = 34;
 
2254
      pth->SizeOfPartitionEntry
 
2255
        = PED_CPU_TO_LE32 (sizeof (GuidPartitionEntry_t));
 
2256
    }
 
2257
 
2184
2258
  *max_n = (disk->dev->sector_size * (pth->FirstUsableLBA - 2)
2185
2259
            / PED_LE32_TO_CPU (pth->SizeOfPartitionEntry));
2186
2260
  pth_free (pth);
2198
2272
static int
2199
2273
gpt_partition_align (PedPartition *part, const PedConstraint *constraint)
2200
2274
{
2201
 
  PED_ASSERT (part != NULL, return 0);
 
2275
  PED_ASSERT (part != NULL);
2202
2276
 
2203
2277
  if (_ped_partition_attempt_align (part, constraint,
2204
2278
                                    _non_metadata_constraint (part->disk)))
2222
2296
 
2223
2297
  partition_set_name:           gpt_partition_set_name,
2224
2298
  partition_get_name:           gpt_partition_get_name,
 
2299
  disk_set_flag:                gpt_disk_set_flag,
 
2300
  disk_get_flag:                gpt_disk_get_flag,
 
2301
  disk_is_flag_available:       gpt_disk_is_flag_available,
2225
2302
 
2226
2303
  PT_op_function_initializers (gpt)
2227
2304
};
2237
2314
void
2238
2315
ped_disk_gpt_init ()
2239
2316
{
2240
 
  PED_ASSERT (sizeof (GuidPartitionEntryAttributes_t) == 8, return);
2241
 
  PED_ASSERT (sizeof (GuidPartitionEntry_t) == 128, return);
2242
 
 
2243
2317
  ped_disk_type_register (&gpt_disk_type);
2244
2318
 
2245
2319
  char *force_gpt_apple = getenv ("PARTED_GPT_APPLE");
2263
2337
{
2264
2338
  ped_disk_type_unregister (&gpt_disk_type);
2265
2339
}
 
2340
 
 
2341
verify (sizeof (GuidPartitionEntryAttributes_t) == 8);
 
2342
verify (sizeof (GuidPartitionEntry_t) == 128);