--- /dev/null
+diff -burN parted-1.4.16/AUTHORS parted-1.4.16-gpt/AUTHORS
+--- parted-1.4.16/AUTHORS Fri Jun 29 02:57:09 2001
++++ parted-1.4.16-gpt/AUTHORS Wed Jul 18 16:10:31 2001
+@@ -96,3 +96,8 @@
+ Thomas Roelz <tom@suse.de>
+ * misc bug fixes
+
++Matt Domsch <Matt_Domsch@dell.com>
++ * GUID Partition Table (GPT) support (disk_gpt.[ch],
++ device_diskioctl.[ch],
++ crc32.[ch])
++ * misc bug fixes
+diff -burN parted-1.4.16/include/parted/Makefile.am parted-1.4.16-gpt/include/parted/Makefile.am
+--- parted-1.4.16/include/parted/Makefile.am Sat Apr 7 17:04:39 2001
++++ parted-1.4.16-gpt/include/parted/Makefile.am Wed Jul 18 16:10:31 2001
+@@ -6,6 +6,7 @@
+ exception.h \
+ filesys.h \
+ natmath.h \
++ crc32.h \
+ parted.h
+
+ noinst_HEADERS = disk_bsd.h \
+@@ -13,6 +14,7 @@
+ disk_loop.h \
+ disk_mac.h \
+ disk_pc98.h \
++ disk_gpt.h \
+ disk_sun.h \
+ endian.h
+
+diff -burN parted-1.4.16/include/parted/crc32.h parted-1.4.16-gpt/include/parted/crc32.h
+--- parted-1.4.16/include/parted/crc32.h Wed Dec 31 18:00:00 1969
++++ parted-1.4.16-gpt/include/parted/crc32.h Wed Jul 18 16:10:31 2001
+@@ -0,0 +1,35 @@
++/*
++ libparted - a library for manipulating disk partitions
++ Copyright (C) 1998-2000 Free Software Foundation, Inc.
++
++ crc32.h
++
++ This program 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 2 of the License, or
++ (at your option) any later version.
++
++ This program 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 this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++*/
++
++#ifndef _CRC32_H
++#define _CRC32_H
++
++#include <stdint.h>
++
++/*
++ * This computes a 32 bit CRC of the data in the buffer, and returns the CRC.
++ * The polynomial used is 0xedb88320.
++ */
++
++extern uint32_t __efi_crc32 (const void *buf, unsigned long len,
++ uint32_t seed);
++
++#endif /* _CRC32_H */
+diff -burN parted-1.4.16/include/parted/device_diskioctl.h parted-1.4.16-gpt/include/parted/device_diskioctl.h
+--- parted-1.4.16/include/parted/device_diskioctl.h Wed Dec 31 18:00:00 1969
++++ parted-1.4.16-gpt/include/parted/device_diskioctl.h Wed Jul 18 16:10:31 2001
+@@ -0,0 +1,30 @@
++/*
++ libparted - a library for manipulating disk partitions
++
++ device_diskioctl.[ch] by Matt Domsch <Matt_Domsch@dell.com>
++ Disclaimed into the Public Domain
++
++ This program 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 2 of the License, or
++ (at your option) any later version.
++
++ This program 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 this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++*/
++
++#include "parted/device.h"
++
++int
++ped_device_read_lastoddsector (const PedDevice* dev, void* buffer,
++ PedSector start, PedSector count);
++int
++ped_device_write_lastoddsector (PedDevice* dev, const void* buffer,
++ PedSector start, PedSector count);
++
+diff -burN parted-1.4.16/include/parted/disk_gpt.h parted-1.4.16-gpt/include/parted/disk_gpt.h
+--- parted-1.4.16/include/parted/disk_gpt.h Wed Dec 31 18:00:00 1969
++++ parted-1.4.16-gpt/include/parted/disk_gpt.h Wed Jul 18 16:10:31 2001
+@@ -0,0 +1,204 @@
++/*
++ libparted - a library for manipulating disk partitions
++
++ disk_gpt.[ch] by Matt Domsch <Matt_Domsch@dell.com>
++ Disclaimed into the Public Domain
++
++ EFI GUID Partition Table handling
++ Per Intel EFI Specification v1.02
++ http://developer.intel.com/technology/efi/efi.htm
++
++ This program 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 2 of the License, or
++ (at your option) any later version.
++
++ This program 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 this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++*/
++
++#ifndef EFI_GPT_H
++#define EFI_GPT_H
++
++
++#include <stdint.h>
++
++#define EFI_PMBR_OSTYPE_EFI 0xEF
++#define EFI_PMBR_OSTYPE_EFI_GPT 0xEE
++#define MSDOS_MBR_SIGNATURE 0xaa55
++#define GUID_PT_BLOCK_SIZE 512
++
++
++#define GUID_PT_HEADER_SIGNATURE 0x5452415020494645
++#define GUID_PT_HEADER_REVISION_V1_02 0x00010200
++#define GUID_PT_HEADER_REVISION_V1_00 0x00010000
++#define GUID_PT_HEADER_REVISION_V0_99 0x00009900
++
++typedef uint16_t efi_char16_t; /* UNICODE character */
++
++typedef struct {
++ uint32_t time_low;
++ uint16_t time_mid;
++ uint16_t time_hi_and_version;
++ uint8_t clock_seq_hi_and_reserved;
++ uint8_t clock_seq_low;
++ uint8_t node[6];
++} __attribute__ ((packed)) efi_guid_t;
++
++
++#define UNUSED_ENTRY_GUID \
++ ((efi_guid_t) { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }})
++#define PARTITION_SYSTEM_GUID \
++ ((efi_guid_t) { 0xC12A7328, 0xF81F, 0x11d2, 0xBA, 0x4B, { 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B }})
++#define LEGACY_MBR_PARTITION_GUID \
++ ((efi_guid_t) { 0x024DEE41, 0x33E7, 0x11d3, 0x9D, 0x69, { 0x00, 0x08, 0xC7, 0x81, 0xF3, 0x9F }})
++#define PARTITION_MSFT_RESERVED_GUID \
++ ((efi_guid_t) { 0xE3C9E316, 0x0B5C, 0x4DB8, 0x81, 0x7D, { 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE }})
++#define PARTITION_BASIC_DATA_GUID \
++ ((efi_guid_t) { 0xEBD0A0A2, 0xB9E5, 0x4433, 0x87, 0xC0, { 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 }})
++#define PARTITION_RAID_GUID \
++ ((efi_guid_t) { 0xa19d880f, 0x05fc, 0x4d3b, 0xa0, 0x06, { 0x74, 0x3f, 0x0f, 0x84, 0x91, 0x1e }})
++#define PARTITION_SWAP_GUID \
++ ((efi_guid_t) { 0x0657fd6d, 0xa4ab, 0x43c4, 0x84, 0xe5, { 0x09, 0x33, 0xc8, 0x4b, 0x4f, 0x4f }})
++#define PARTITION_LVM_GUID \
++ ((efi_guid_t) { 0xe6d6d379, 0xf507, 0x44c2, 0xa2, 0x3c, { 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28 }})
++#define PARTITION_RESERVED_GUID \
++ ((efi_guid_t) { 0x8da63339, 0x0007, 0x60c0, 0xc4, 0x36, { 0x08, 0x3a, 0xc8, 0x23, 0x09, 0x08 }})
++
++typedef struct _GuidPartitionTableHeader_t {
++ uint64_t Signature;
++ uint32_t Revision;
++ uint32_t HeaderSize;
++ uint32_t HeaderCRC32;
++ uint32_t Reserved1;
++ uint64_t MyLBA;
++ uint64_t AlternateLBA;
++ uint64_t FirstUsableLBA;
++ uint64_t LastUsableLBA;
++ efi_guid_t DiskGUID;
++ uint64_t PartitionEntryLBA;
++ uint32_t NumberOfPartitionEntries;
++ uint32_t SizeOfPartitionEntry;
++ uint32_t PartitionEntryArrayCRC32;
++ uint8_t Reserved2[GUID_PT_BLOCK_SIZE - 92];
++} __attribute__ ((packed)) GuidPartitionTableHeader_t;
++
++typedef struct _GuidPartitionEntryAttributes_t {
++ uint64_t RequiredToFunction:1;
++ uint64_t Reserved:47;
++ uint64_t GuidSpecific:16;
++} __attribute__ ((packed)) GuidPartitionEntryAttributes_t;
++
++typedef struct _GuidPartitionEntry_t {
++ efi_guid_t PartitionTypeGuid;
++ efi_guid_t UniquePartitionGuid;
++ uint64_t StartingLBA;
++ uint64_t EndingLBA;
++ GuidPartitionEntryAttributes_t Attributes;
++ efi_char16_t PartitionName[72 / sizeof(efi_char16_t)];
++} __attribute__ ((packed)) GuidPartitionEntry_t;
++
++
++#define GPT_PMBR_LBA 0
++#define GPT_PMBR_SECTORS 1
++#define GPT_PRIMARY_HEADER_LBA 1
++#define GPT_HEADER_SECTORS 1
++#define GPT_PRIMARY_PART_TABLE_LBA 2
++
++/*
++ These values are only defaults. The actual on-disk structures
++ may define different sizes, so use those unless creating a new GPT disk!
++*/
++
++#define GPT_DEFAULT_RESERVED_PARTITION_ENTRY_ARRAY_SIZE 16384
++/*
++ Number of actual partition entries should be calculated
++ as:
++*/
++#define GPT_DEFAULT_RESERVED_PARTITION_ENTRIES \
++ (GPT_DEFAULT_RESERVED_PARTITION_ENTRY_ARRAY_SIZE / \
++ sizeof(GuidPartitionEntry_t))
++
++
++typedef struct _PartitionRecord_t {
++ uint8_t BootIndicator; /* Not used by EFI firmware. Set to 0x80 to indicate that this
++ is the bootable legacy partition. */
++ uint8_t StartHead; /* Start of partition in CHS address, not used by EFI firmware. */
++ uint8_t StartSector; /* Start of partition in CHS address, not used by EFI firmware. */
++ uint8_t StartTrack; /* Start of partition in CHS address, not used by EFI firmware. */
++ uint8_t OSType; /* OS type. A value of 0xEF defines an EFI system partition.
++ Other values are reserved for legacy operating systems, and
++ allocated independently of the EFI specification. */
++ uint8_t EndHead; /* End of partition in CHS address, not used by EFI firmware. */
++ uint8_t EndSector; /* End of partition in CHS address, not used by EFI firmware. */
++ uint8_t EndTrack; /* End of partition in CHS address, not used by EFI firmware. */
++ uint32_t StartingLBA; /* Starting LBA address of the partition on the disk. Used by
++ EFI firmware to define the start of the partition. */
++ uint32_t SizeInLBA; /* Size of partition in LBA. Used by EFI firmware to determine
++ the size of the partition. */
++} __attribute__ ((packed)) PartitionRecord_t;
++
++/* Protected Master Boot Record & Legacy MBR share same structure */
++/* Needs to be packed because the u16s force misalignment. */
++
++typedef struct _LegacyMBR_t {
++ uint8_t BootCode[440];
++ uint32_t UniqueMBRSignature;
++ uint16_t Unknown;
++ PartitionRecord_t PartitionRecord[4];
++ uint16_t Signature;
++} __attribute__ ((packed)) LegacyMBR_t;
++
++
++
++
++
++
++
++/* Parted has a PedDisk field disk_specific that we'll keep
++ our own useful info in.
++*/
++typedef struct _GPTDiskData {
++ GuidPartitionTableHeader_t *pgpt;
++ GuidPartitionTableHeader_t *agpt;
++ GuidPartitionEntry_t *ptes;
++} GPTDiskData;
++
++/* Parted has a PedPartition field disk_specific that we'll keep
++ our own useful info in.
++*/
++typedef struct _GPTPartitionData {
++ GuidPartitionEntry_t * pte;
++} GPTPartitionData;
++
++
++#define GPT_NAME "GPT"
++void ped_disk_gpt_init();
++void ped_disk_gpt_done();
++
++#endif
++
++/*
++ * Overrides for Emacs so that we follow Linus's tabbing style.
++ * Emacs will notice this stuff at the end of the file and automatically
++ * adjust the settings for this buffer only. This must remain at the end
++ * of the file.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-indent-level: 4
++ * c-brace-imaginary-offset: 0
++ * c-brace-offset: -4
++ * c-argdecl-indent: 4
++ * c-label-offset: -4
++ * c-continued-statement-offset: 4
++ * c-continued-brace-offset: 0
++ * indent-tabs-mode: nil
++ * tab-width: 8
++ * End:
++ */
+diff -burN parted-1.4.16/libparted/Makefile.am parted-1.4.16-gpt/libparted/Makefile.am
+--- parted-1.4.16/libparted/Makefile.am Sun Jul 15 01:19:45 2001
++++ parted-1.4.16-gpt/libparted/Makefile.am Wed Jul 18 16:10:31 2001
+@@ -30,11 +30,15 @@
+ llseek.c \
+ llseek.h \
+ natmath.c \
++ crc32.c \
+ disk.c \
+ disk_bsd.c \
+ disk_dos.c \
+ disk_loop.c \
+ disk_mac.c \
++ disk_gpt.c \
++ device_diskioctl.c \
++ device_diskioctl.h \
+ disk_sun.c
+
+ if PC98
+diff -burN parted-1.4.16/libparted/crc32.c parted-1.4.16-gpt/libparted/crc32.c
+--- parted-1.4.16/libparted/crc32.c Wed Dec 31 18:00:00 1969
++++ parted-1.4.16-gpt/libparted/crc32.c Wed Jul 18 16:10:31 2001
+@@ -0,0 +1,125 @@
++/*
++ * Dec 5, 2000 Matt Domsch <Matt_Domsch@dell.com>
++ * - Copied crc32.c from the linux/drivers/net/cipe directory.
++ * - Now pass seed as an arg
++ * - changed unsigned long to uint32_t, added #include<stdint.h>
++ * - changed len to be an unsigned long
++ * - changed crc32val to be a register
++ * - License remains unchanged! It's still GPL-compatable!
++ */
++
++ /* ============================================================= */
++ /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or */
++ /* code or tables extracted from it, as desired without restriction. */
++ /* */
++ /* First, the polynomial itself and its table of feedback terms. The */
++ /* polynomial is */
++ /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
++ /* */
++ /* Note that we take it "backwards" and put the highest-order term in */
++ /* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
++ /* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
++ /* the MSB being 1. */
++ /* */
++ /* Note that the usual hardware shift register implementation, which */
++ /* is what we're using (we're merely optimizing it by doing eight-bit */
++ /* chunks at a time) shifts bits into the lowest-order term. In our */
++ /* implementation, that means shifting towards the right. Why do we */
++ /* do it this way? Because the calculated CRC must be transmitted in */
++ /* order from highest-order term to lowest-order term. UARTs transmit */
++ /* characters in order from LSB to MSB. By storing the CRC this way, */
++ /* we hand it to the UART in the order low-byte to high-byte; the UART */
++ /* sends each low-bit to hight-bit; and the result is transmission bit */
++ /* by bit from highest- to lowest-order term without requiring any bit */
++ /* shuffling on our part. Reception works similarly. */
++ /* */
++ /* The feedback terms table consists of 256, 32-bit entries. Notes: */
++ /* */
++ /* The table can be generated at runtime if desired; code to do so */
++ /* is shown later. It might not be obvious, but the feedback */
++ /* terms simply represent the results of eight shift/xor opera- */
++ /* tions for all combinations of data and CRC register values. */
++ /* */
++ /* The values must be right-shifted by eight bits by the "updcrc" */
++ /* logic; the shift must be unsigned (bring in zeroes). On some */
++ /* hardware you could probably optimize the shift in assembler by */
++ /* using byte-swap instructions. */
++ /* polynomial $edb88320 */
++ /* */
++ /* -------------------------------------------------------------------- */
++
++#include<stdint.h>
++
++static uint32_t crc32_tab[] = {
++ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
++ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
++ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
++ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
++ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
++ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
++ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
++ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
++ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
++ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
++ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
++ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
++ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
++ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
++ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
++ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
++ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
++ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
++ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
++ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
++ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
++ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
++ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
++ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
++ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
++ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
++ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
++ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
++ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
++ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
++ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
++ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
++ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
++ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
++ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
++ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
++ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
++ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
++ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
++ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
++ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
++ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
++ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
++ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
++ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
++ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
++ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
++ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
++ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
++ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
++ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
++ 0x2d02ef8dL
++ };
++
++/* Return a 32-bit CRC of the contents of the buffer. */
++
++uint32_t
++__efi_crc32(const void *buf, unsigned long len, uint32_t seed)
++{
++ unsigned long i;
++ register uint32_t crc32val;
++ const unsigned char *s = buf;
++
++ crc32val = seed;
++ for (i = 0; i < len; i ++)
++ {
++ crc32val =
++ crc32_tab[(crc32val ^ s[i]) & 0xff] ^
++ (crc32val >> 8);
++ }
++ return crc32val;
++}
+diff -burN parted-1.4.16/libparted/device.c parted-1.4.16-gpt/libparted/device.c
+--- parted-1.4.16/libparted/device.c Thu Jul 5 16:46:36 2001
++++ parted-1.4.16-gpt/libparted/device.c Wed Jul 18 16:10:31 2001
+@@ -41,6 +41,7 @@
+ #include <scsi/scsi.h>
+
+ #include <parted/parted.h>
++#include <parted/device_diskioctl.h>
+
+ #ifndef SCSI_IOCTL_SEND_COMMAND
+ #define SCSI_IOCTL_SEND_COMMAND 1
+@@ -905,6 +906,19 @@
+ PED_ASSERT (!dev->external_mode, return 0);
+ PED_ASSERT (buffer != NULL, return 0);
+
++#ifdef linux
++ /* Kludge. This is necessary to read/write the last
++ block of an odd-sized disk, until Linux 2.5.x kernel fixes.
++ This is only used by disk_gpt.c, and only to read/write
++ one sector, so we don't have to be fancy.
++ */
++
++ if ((dev->length & 1) &&
++ (count == 1) &&
++ start == dev->length - 1) {
++ return ped_device_read_lastoddsector(dev, buffer, start, count);
++ }
++#endif
+ while (1) {
+ if (ped_device_seek (dev, start))
+ break;
+@@ -1024,6 +1038,19 @@
+ else
+ return 1;
+ }
++
++#ifdef linux
++ /* Kludge. This is necessary to read/write the last
++ block of an odd-sized disk, until Linux 2.5.x kernel fixes.
++ This is only used by disk_gpt.c, and only to read/write
++ one sector, so we don't have to be fancy.
++ */
++ if ((dev->length & 1) &&
++ (count == 1) &&
++ start == dev->length - 1) {
++ return ped_device_write_lastoddsector(dev, buffer, start, count);
++ }
++#endif
+
+ while (1) {
+ if (ped_device_seek (dev, start))
+diff -burN parted-1.4.16/libparted/device_diskioctl.c parted-1.4.16-gpt/libparted/device_diskioctl.c
+--- parted-1.4.16/libparted/device_diskioctl.c Wed Dec 31 18:00:00 1969
++++ parted-1.4.16-gpt/libparted/device_diskioctl.c Wed Jul 18 16:10:31 2001
+@@ -0,0 +1,81 @@
++/*
++ libparted - a library for manipulating disk partitions
++
++ device_diskioctl.[ch] by Matt Domsch <Matt_Domsch@dell.com>
++ Disclaimed into the Public Domain
++
++ This program 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 2 of the License, or
++ (at your option) any later version.
++
++ This program 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 this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++*/
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <fcntl.h>
++#include <errno.h>
++
++#include <parted/parted.h>
++#include <sys/ioctl.h>
++
++#define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */
++#define BLKSETLASTSECT _IO(0x12,109) /* get last sector of block device */
++
++struct blkdev_ioctl_param {
++ unsigned int block;
++ size_t content_length;
++ char * block_contents;
++};
++
++int
++ped_device_read_lastoddsector (const PedDevice* dev, void* buffer,
++ PedSector start, PedSector count)
++{
++ int rc;
++ struct blkdev_ioctl_param ioctl_param;
++
++ PED_ASSERT(dev != NULL, return 0);
++ PED_ASSERT(buffer != NULL, return 0);
++ PED_ASSERT(count == 1, return 0);
++
++ ioctl_param.block = 0; /* read the last sector */
++ ioctl_param.content_length = dev->sector_size;
++ ioctl_param.block_contents = buffer;
++
++ rc = ioctl(dev->fd, BLKGETLASTSECT, &ioctl_param);
++ if (rc == -1) perror("read failed");
++
++ return !rc;
++}
++
++int
++ped_device_write_lastoddsector (PedDevice* dev, const void* buffer,
++ PedSector start, PedSector count)
++{
++ int rc;
++ struct blkdev_ioctl_param ioctl_param;
++
++ PED_ASSERT(dev != NULL, return 0);
++ PED_ASSERT(buffer != NULL, return 0);
++ PED_ASSERT(count == 1, return 0);
++
++ ioctl_param.block = 0; /* write the last sector */
++ ioctl_param.block_contents = (char *)buffer;
++ ioctl_param.content_length = dev->sector_size;
++
++ rc = ioctl(dev->fd, BLKSETLASTSECT, &ioctl_param);
++ if (rc == -1) perror("write failed");
++
++ return !rc;
++
++}
+diff -burN parted-1.4.16/libparted/disk.c parted-1.4.16-gpt/libparted/disk.c
+--- parted-1.4.16/libparted/disk.c Tue Jun 12 05:09:29 2001
++++ parted-1.4.16-gpt/libparted/disk.c Wed Jul 18 16:10:31 2001
+@@ -182,6 +182,7 @@
+ disk->dev = dev;
+ disk->type = disk_type;
+ disk->update_mode = 0;
++ disk->disk_specific = NULL;
+
+ disk->part_list = ped_partition_new (
+ disk, PED_PARTITION_FREESPACE, NULL,
+@@ -591,6 +592,7 @@
+ part->type = type;
+ part->part_list = NULL;
+ part->fs_type = fs_type;
++ part->disk_specific = NULL;
+
+ return part;
+
+@@ -609,6 +611,8 @@
+ PedPartition* part;
+
+ PED_ASSERT (disk != NULL, return NULL);
++ PED_ASSERT (disk->type != NULL, return NULL);
++ PED_ASSERT (disk->type->ops != NULL, return NULL);
+ PED_ASSERT (disk->type->ops->partition_new != NULL, return NULL);
+
+ supports_extended = ped_disk_type_check_feature (disk->type,
+@@ -1374,10 +1378,10 @@
+ PED_ASSERT (part != NULL, return 0);
+
+ #ifdef VERBOSE
+- printf ("ped_disk_add_partition (dev=\"%s\", start=%d, end=%d,"
++ printf ("ped_disk_add_partition (dev=\"%s\", start=%llx, end=%llx,"
+ " type=%x)\n",
+- disk->dev->path, (int) part->geom.start, (int) part->geom.end,
+- (int) part->system);
++ disk->dev->path, part->geom.start, part->geom.end,
++ part->type);
+ #endif
+
+ if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)
+diff -burN parted-1.4.16/libparted/disk_dos.c parted-1.4.16-gpt/libparted/disk_dos.c
+--- parted-1.4.16/libparted/disk_dos.c Sat Jul 14 21:12:22 2001
++++ parted-1.4.16-gpt/libparted/disk_dos.c Wed Jul 18 16:10:31 2001
+@@ -266,6 +266,12 @@
+ }
+ }
+
++ /* If this is a GPT disk, fail here */
++ for (i = 0; i < 4; i++) {
++ if (part_table.partitions[i].type == 0xEE)
++ return 0;
++ }
++
+ /* HACK: it's impossible to tell PC98 and msdos disk labels apart.
+ * Someone made the signatures the same (very clever). Since
+ * PC98 has some idiosyncracies with it's boot-loader, it's detection
+diff -burN parted-1.4.16/libparted/disk_gpt.c parted-1.4.16-gpt/libparted/disk_gpt.c
+--- parted-1.4.16/libparted/disk_gpt.c Wed Dec 31 18:00:00 1969
++++ parted-1.4.16-gpt/libparted/disk_gpt.c Wed Jul 18 16:10:40 2001
+@@ -0,0 +1,1721 @@
++/*
++ libparted - a library for manipulating disk partitions
++
++ disk_gpt.[ch] by Matt Domsch <Matt_Domsch@dell.com>
++ Disclaimed into the Public Domain
++
++ EFI GUID Partition Table handling
++ Per Intel EFI Specification v1.02
++ http://developer.intel.com/technology/efi/efi.htm
++
++ This program 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 2 of the License, or
++ (at your option) any later version.
++
++ This program 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 this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++*/
++
++/*
++ TODO:
++ - Make partition labels get/set properly
++*/
++
++#include "config.h"
++
++#include <parted/parted.h>
++#include <parted/endian.h>
++#include <parted/crc32.h>
++#include <parted/disk_gpt.h>
++#include <parted/natmath.h>
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++#include <sys/types.h>
++#include <sys/ioctl.h>
++#include <fcntl.h>
++#include <unistd.h>
++#include <uuid/uuid.h>
++
++#include <libintl.h>
++#if ENABLE_NLS
++# define _(String) gettext (String)
++#else
++# define _(String) (String)
++#endif /* ENABLE_NLS */
++
++static int gpt_probe(const PedDevice * dev);
++static PedDisk *gpt_open(PedDevice * dev);
++static PedDisk *gpt_create(PedDevice * dev);
++static int gpt_clobber(PedDevice * dev);
++static int gpt_close(PedDisk * disk);
++static int gpt_read(PedDisk * disk);
++static int gpt_write(PedDisk * disk);
++
++
++static PedPartition *gpt_partition_new(const PedDisk *disk,
++ PedPartitionType part_type,
++ const PedFileSystemType* fs_type,
++ PedSector start,
++ PedSector end);
++static void gpt_partition_destroy(PedPartition *part);
++static int gpt_partition_set_flag(PedPartition *part,
++ PedPartitionFlag flag,
++ int state);
++static int gpt_partition_get_flag(const PedPartition *part,
++ PedPartitionFlag flag);
++static int gpt_partition_is_flag_available(const PedPartition * part,
++ PedPartitionFlag flag);
++static void gpt_partition_set_name(PedPartition *part,
++ const char *name);
++static const char * gpt_partition_get_name (const PedPartition * part);
++static int gpt_partition_align(PedPartition * part,
++ const PedConstraint * constraint);
++static int gpt_partition_enumerate(PedPartition * part);
++
++static int gpt_alloc_metadata(PedDisk * disk);
++static int gpt_get_max_primary_partition_count(const PedDisk *disk);
++
++/* gpt private function */
++static PedDisk * gpt_new(PedDisk * disk);
++
++static PedDiskOps gpt_disk_ops = {
++ probe : gpt_probe,
++ open : gpt_open,
++ create : gpt_create,
++ clobber : gpt_clobber,
++ close : gpt_close,
++ read : gpt_read,
++ write : gpt_write,
++ partition_new : gpt_partition_new,
++ partition_destroy : gpt_partition_destroy,
++ 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_set_extended_system : NULL,
++ alloc_metadata : gpt_alloc_metadata,
++ get_max_primary_partition_count : gpt_get_max_primary_partition_count
++
++};
++
++static PedDiskType gpt_disk_type = {
++ next:NULL,
++ name:GPT_NAME,
++ ops:&gpt_disk_ops,
++ features: PED_DISK_TYPE_PARTITION_NAME
++};
++
++
++
++static void
++gpt_le_guid_to_cpu(efi_guid_t *guid)
++{
++ guid->time_low = PED_LE32_TO_CPU(guid->time_low);
++ guid->time_mid = PED_LE16_TO_CPU(guid->time_mid);
++ guid->time_hi_and_version = PED_LE16_TO_CPU(guid->time_hi_and_version);
++ /* no need to change clock_seq and node[6].
++ They're already arrays of chars */
++ return;
++}
++
++static void
++gpt_cpu_to_le_guid(efi_guid_t *guid)
++{
++ guid->time_low = PED_CPU_TO_LE32(guid->time_low);
++ guid->time_mid = PED_CPU_TO_LE16(guid->time_mid);
++ guid->time_hi_and_version = PED_CPU_TO_LE16(guid->time_hi_and_version);
++ /* no need to change clock_seq and node[6].
++ They're already arrays of chars */
++ return;
++}
++
++static void
++gpt_le_part_attributes_to_cpu(GuidPartitionEntryAttributes_t *a)
++{
++ uint64_t *b = (uint64_t *)a;
++ *b = PED_LE64_TO_CPU(*b);
++}
++
++static void
++gpt_cpu_to_le_part_attributes(GuidPartitionEntryAttributes_t *a)
++{
++ uint64_t *b = (uint64_t *)a;
++ *b = PED_CPU_TO_LE64(*b);
++}
++
++
++/************************************************************
++ * efi_crc32()
++ * Requires:
++ * - a buffer of length len
++ * Modifies: nothing
++ * Returns:
++ * EFI-style CRC32 value for buf
++ *
++ * This function uses the crc32 function by Gary S. Brown,
++ * but seeds the function with ~0, and xor's with ~0 at the end.
++ ************************************************************/
++
++static inline uint32_t
++efi_crc32(const void *buf, unsigned long len)
++{
++ return (__efi_crc32(buf, len, ~0L) ^ ~0L);
++}
++
++
++static inline int
++is_legacy_mbr_valid(LegacyMBR_t * mbr)
++{
++ return (mbr ? (mbr->Signature == MSDOS_MBR_SIGNATURE) : 0);
++}
++
++static inline int
++efi_guidcmp(efi_guid_t left, efi_guid_t right)
++{
++ return memcmp(&left, &right, sizeof(efi_guid_t));
++}
++
++
++/************************************************************
++ * last_lba()
++ * Requires:
++ * - dev
++ * Modifies: nothing
++ * Returns:
++ * Last LBA value on success
++ * 0 on error
++ ************************************************************/
++
++
++static uint64_t
++last_lba(const PedDevice * dev)
++{
++ PED_ASSERT(dev != NULL, return 0);
++ return dev->length - 1;
++}
++
++/************************************************************
++ * gpt_read_part_entries()
++ * Requires:
++ * - dev
++ * - lba is the Logical Block Address of the partition table
++ * - gpt is a buffer into which the GPT will be put
++ * Modifies:
++ * - dev
++ * - gpt
++ * Returns:
++ * pte on success
++ * NULL on error
++ * Notes: remember to free pte when you're done!
++ ************************************************************/
++static GuidPartitionEntry_t *
++gpt_read_part_entries(const PedDevice * dev,
++ GuidPartitionTableHeader_t * gpt)
++{
++ GuidPartitionEntry_t *ptes;
++ unsigned int i, j;
++
++ PED_ASSERT(dev != NULL, return NULL);
++ PED_ASSERT(dev->sector_size != 0, return NULL);
++ PED_ASSERT(gpt != NULL, return NULL);
++
++ ptes = (GuidPartitionEntry_t *)
++ ped_malloc(gpt->NumberOfPartitionEntries *
++ gpt->SizeOfPartitionEntry);
++
++ PED_ASSERT(ptes != NULL, return NULL);
++
++ memset(ptes, 0, gpt->NumberOfPartitionEntries *
++ gpt->SizeOfPartitionEntry);
++
++
++ if (!ped_device_read(dev, ptes, gpt->PartitionEntryLBA,
++ gpt->NumberOfPartitionEntries *
++ gpt->SizeOfPartitionEntry / dev->sector_size)) {
++ ped_free(ptes);
++ return NULL;
++ }
++
++ /* Fixup endianness */
++ for (i=0; i<gpt->NumberOfPartitionEntries; i++) {
++ gpt_le_guid_to_cpu(&ptes[i].PartitionTypeGuid);
++ gpt_le_guid_to_cpu(&ptes[i].UniquePartitionGuid);
++ ptes[i].StartingLBA = PED_LE64_TO_CPU(ptes[i].StartingLBA);
++ ptes[i].EndingLBA = PED_LE64_TO_CPU(ptes[i].EndingLBA);
++ gpt_le_part_attributes_to_cpu(&ptes[i].Attributes);
++ for (j=0; j<(72/sizeof(efi_char16_t)); j++) {
++ ptes[i].PartitionName[j] = (efi_char16_t)(PED_LE16_TO_CPU((uint16_t)(ptes[i].PartitionName[j])));
++ }
++ }
++
++ return ptes;
++}
++
++/************************************************************
++ * gpt_write_part_entries()
++ * Requires:
++ * - PedDevice *dev
++ * - gpt
++ * - pte is a buffer that will be written
++ * Modifies:
++ * - dev
++ * - gpt
++ * Returns:
++ * pte on success
++ * NULL on error
++ * Notes: remember to free pte when you're done!
++ ************************************************************/
++static GuidPartitionEntry_t *
++gpt_write_part_entries(PedDevice * dev,
++ GuidPartitionTableHeader_t * gpt,
++ GuidPartitionEntry_t *ptes)
++{
++ GuidPartitionEntry_t *new_ptes;
++ unsigned long ptes_size;
++ int rc;
++ unsigned int i, j;
++
++ PED_ASSERT(gpt != NULL, return NULL);
++ PED_ASSERT(ptes != NULL, return NULL);
++ PED_ASSERT(dev != NULL, return NULL);
++ PED_ASSERT(dev->sector_size != 0, return NULL);
++
++ ptes_size = gpt->NumberOfPartitionEntries *
++ gpt->SizeOfPartitionEntry;
++
++ new_ptes = ped_malloc(ptes_size);
++ if (!new_ptes) return NULL;
++ memcpy(new_ptes, ptes, ptes_size);
++
++ /* Fixup endianness */
++ for (i=0; i<gpt->NumberOfPartitionEntries; i++) {
++ gpt_cpu_to_le_guid(&new_ptes->PartitionTypeGuid);
++ gpt_cpu_to_le_guid(&new_ptes->UniquePartitionGuid);
++ new_ptes[i].StartingLBA = PED_CPU_TO_LE64(new_ptes[i].StartingLBA);
++ new_ptes[i].EndingLBA = PED_CPU_TO_LE64(new_ptes[i].EndingLBA);
++ gpt_cpu_to_le_part_attributes(&new_ptes[i].Attributes);
++
++ for (j=0; j<(72/sizeof(efi_char16_t)); j++) {
++ new_ptes[i].PartitionName[j] = (efi_char16_t)(PED_CPU_TO_LE16((uint16_t)(new_ptes[i].PartitionName[j])));
++ }
++ }
++
++ rc = ped_device_write(dev, new_ptes, gpt->PartitionEntryLBA,
++ ptes_size / dev->sector_size);
++ ped_free(new_ptes);
++ if (!rc) return NULL;
++ return ptes;
++}
++
++
++static void
++gpt_print_part_entry(GuidPartitionEntry_t * pte, int i)
++{
++ efi_guid_t unused_guid = UNUSED_ENTRY_GUID;
++ char uuid_buffer[40];
++ uuid_t uuid;
++ PED_ASSERT(pte != NULL, return);
++ if (!efi_guidcmp(pte->PartitionTypeGuid, unused_guid)) {
++ // printf("UNUSED_ENTRY_GUID\n");
++ return;
++ }
++ printf("GUID Partition Entry %d:\n", i);
++ memcpy(uuid, &pte->PartitionTypeGuid, sizeof(uuid_t));
++ uuid_unparse(uuid, uuid_buffer);
++ printf("\tPartitionTypeGuid : %s\n", uuid_buffer);
++ memcpy(uuid, &pte->UniquePartitionGuid, sizeof(uuid_t));
++ uuid_unparse(uuid, uuid_buffer);
++ printf("\tUniquePartitionGuid : %s\n", uuid_buffer);
++ printf("\tStartingLBA : %llx\n", pte->StartingLBA);
++ printf("\tEndingLBA : %llx\n", pte->EndingLBA);
++ printf("\tAttributes : ");
++ printf("\tRequiredToFunction: %x",
++ pte->Attributes.RequiredToFunction);
++ printf("\tGuidSpecific: %x\n",
++ pte->Attributes.GuidSpecific);
++
++ // printf("\tPartitionName : Unicode string.\n");
++ return;
++}
++
++static void
++gpt_print_header(GuidPartitionTableHeader_t * gpt)
++{
++ char uuid_buffer[40];
++ uuid_t uuid;
++ printf("GUID Partition Table Header\n");
++ PED_ASSERT(gpt != NULL, return);
++ printf("Signature : 0x%llx\n", gpt->Signature);
++ printf("Revision : 0x%x\n", gpt->Revision);
++ printf("HeaderSize : 0x%x\n", gpt->HeaderSize);
++ printf("HeaderCRC32 : 0x%x\n", gpt->HeaderCRC32);
++ printf("MyLBA : 0x%llx\n", gpt->MyLBA);
++ printf("AlternateLBA : 0x%llx\n", gpt->AlternateLBA);
++ printf("FirstUsableLBA : 0x%llx\n", gpt->FirstUsableLBA);
++ printf("LastUsableLBA : 0x%llx\n", gpt->LastUsableLBA);
++ memcpy(uuid, &gpt->DiskGUID, sizeof(uuid_t));
++ uuid_unparse(uuid, uuid_buffer);
++ printf("DiskGUID : %s\n", uuid_buffer);
++ printf("PartitionEntryLBA : %llx\n", gpt->PartitionEntryLBA);
++ printf("NumberOfPartitionEntries : %x\n",
++ gpt->NumberOfPartitionEntries);
++ printf("SizeOfPartitionEntry : %x\n", gpt->SizeOfPartitionEntry);
++ printf("PartitionEntryArrayCRC32 : %x\n",
++ gpt->PartitionEntryArrayCRC32); return;
++}
++
++
++/************************************************************
++ * gpt_read_header()
++ * Requires:
++ * - dev
++ * - lba is the Logical Block Address of the partition table
++ * Modifies:
++ * - dev
++ * Returns:
++ * GPTH on success
++ * NULL on error
++ ************************************************************/
++static GuidPartitionTableHeader_t *
++gpt_read_header(const PedDevice * dev,
++ uint64_t lba)
++{
++ GuidPartitionTableHeader_t *gpt;
++ PED_ASSERT(dev != NULL, return 0);
++ gpt = (GuidPartitionTableHeader_t *)
++ ped_malloc(sizeof(GuidPartitionTableHeader_t));
++ if (!gpt) return NULL;
++ memset(gpt, 0, sizeof (*gpt));
++ if (!ped_device_read(dev, gpt, lba, 1)) {
++ ped_free(gpt);
++ return NULL;
++ }
++
++
++ /* Fixup endianness */
++ gpt->Signature = PED_LE64_TO_CPU(gpt->Signature);
++ gpt->Revision = PED_LE32_TO_CPU(gpt->Revision);
++ gpt->HeaderSize = PED_LE32_TO_CPU(gpt->HeaderSize);
++ gpt->HeaderCRC32 = PED_LE32_TO_CPU(gpt->HeaderCRC32);
++ gpt->Reserved1 = PED_LE32_TO_CPU(gpt->Reserved1);
++ gpt->MyLBA = PED_LE64_TO_CPU(gpt->MyLBA);
++ gpt->AlternateLBA = PED_LE64_TO_CPU(gpt->AlternateLBA);
++ gpt->FirstUsableLBA = PED_LE64_TO_CPU(gpt->FirstUsableLBA);
++ gpt->LastUsableLBA = PED_LE64_TO_CPU(gpt->LastUsableLBA);
++ gpt->PartitionEntryLBA = PED_LE64_TO_CPU(gpt->PartitionEntryLBA);
++ gpt->NumberOfPartitionEntries = PED_LE32_TO_CPU(gpt->NumberOfPartitionEntries);
++ gpt->SizeOfPartitionEntry = PED_LE32_TO_CPU(gpt->SizeOfPartitionEntry);
++ gpt->PartitionEntryArrayCRC32 = PED_LE32_TO_CPU(gpt->PartitionEntryArrayCRC32);
++ gpt_le_guid_to_cpu(&gpt->DiskGUID);
++ /* Ignore the reserved bytes */
++
++ return gpt;
++}
++
++/************************************************************
++ * gpt_write_header()
++ * Requires:
++ * - dev
++ * - lba is the Logical Block Address of the partition table
++ * - gpt is a buffer into which the GPT will be put
++ * Modifies:
++ * - dev
++ * Returns:
++ * 1 on success
++ * 0 on error
++ ************************************************************/
++static int
++gpt_write_header(PedDevice *dev,
++ GuidPartitionTableHeader_t * gpt)
++{
++ GuidPartitionTableHeader_t *new_gpt;
++ int rc;
++
++ PED_ASSERT(gpt != NULL, return 0);
++
++ new_gpt = ped_malloc(sizeof(*gpt));
++ if (!new_gpt) return 0;
++ memcpy(new_gpt, gpt, sizeof(*gpt));
++
++ /* Fixup endianness */
++ new_gpt->Signature = PED_CPU_TO_LE64(gpt->Signature);
++ new_gpt->Revision = PED_CPU_TO_LE32(gpt->Revision);
++ new_gpt->HeaderSize = PED_CPU_TO_LE32(gpt->HeaderSize);
++ new_gpt->HeaderCRC32 = PED_CPU_TO_LE32(gpt->HeaderCRC32);
++ new_gpt->Reserved1 = PED_CPU_TO_LE32(gpt->Reserved1);
++ new_gpt->MyLBA = PED_CPU_TO_LE64(gpt->MyLBA);
++ new_gpt->AlternateLBA = PED_CPU_TO_LE64(gpt->AlternateLBA);
++ new_gpt->FirstUsableLBA = PED_CPU_TO_LE64(gpt->FirstUsableLBA);
++ new_gpt->LastUsableLBA = PED_CPU_TO_LE64(gpt->LastUsableLBA);
++ new_gpt->PartitionEntryLBA = PED_CPU_TO_LE64(gpt->PartitionEntryLBA);
++ new_gpt->NumberOfPartitionEntries = PED_CPU_TO_LE32(gpt->NumberOfPartitionEntries);
++ new_gpt->SizeOfPartitionEntry = PED_CPU_TO_LE32(gpt->SizeOfPartitionEntry);
++ new_gpt->PartitionEntryArrayCRC32 = PED_CPU_TO_LE32(gpt->PartitionEntryArrayCRC32);
++ gpt_cpu_to_le_guid(&new_gpt->DiskGUID);
++ /* Ignore the reserved bytes */
++
++ rc = ped_device_write(dev, new_gpt, gpt->MyLBA, GPT_HEADER_SECTORS);
++ ped_free(new_gpt);
++ return rc;
++}
++
++
++/************************************************************
++ * gpt_is_valid()
++ * Requires:
++ * - dev
++ * - lba is the Logical Block Address of the partition table
++ * Modifies:
++ * - dev
++ * - gpt - reads data into gpt
++ * - ptes - reads data into ptes
++ * Returns:
++ * 1 if valid
++ * 0 on error
++ ************************************************************/
++
++
++static int
++gpt_is_valid(const PedDevice * dev, uint64_t lba,
++ GuidPartitionTableHeader_t ** gpt,
++ GuidPartitionEntry_t ** ptes)
++{
++ int rc = 0; /* default to not valid */
++ uint32_t crc, origcrc;
++ PED_ASSERT(gpt != NULL, return 0);
++ PED_ASSERT(ptes != NULL, return 0);
++ // printf("IsGuidPartitionTableValid(%llx)\n", lba);
++ if (!(*gpt = gpt_read_header(dev, lba)))
++ return rc;
++ /* Check the GUID Partition Table Signature */
++ if ((*gpt)->Signature != GUID_PT_HEADER_SIGNATURE) {
++ /*
++ printf("GUID Partition Table Header Signature is wrong: %llx != %llx\n",
++ (*gpt)->Signature, GUID_PT_HEADER_SIGNATURE);
++ */
++ ped_free(*gpt);
++ *gpt = NULL;
++ return rc;
++ }
++
++ /* Check the GUID Partition Table Header CRC */
++ origcrc = (*gpt)->HeaderCRC32;
++ (*gpt)->HeaderCRC32 = 0;
++ crc = efi_crc32(*gpt, (*gpt)->HeaderSize);
++ if (crc != origcrc) {
++ printf( "GPT Header CRC check failed, %x != %x.\n", origcrc, crc);
++ (*gpt)->HeaderCRC32 = origcrc;
++ gpt_print_header(*gpt);
++ ped_free(*gpt);
++ *gpt = NULL;
++ return rc;
++ }
++ (*gpt)->HeaderCRC32 = origcrc;
++ /* Check that the MyLBA entry points to the LBA
++ that contains the GPT we read */
++ if ((*gpt)->MyLBA != lba) {
++ // printf( "MyLBA %llx != lba %llx.\n", (*gpt)->MyLBA, lba);
++ ped_free(*gpt);
++ *gpt = NULL;
++ return rc;
++ }
++
++ if (!(*ptes = gpt_read_part_entries(dev, *gpt))) {
++ ped_free(*gpt);
++ *gpt = NULL;
++ return rc;
++ }
++
++
++ /* Check the GUID Partition Entry Array CRC */
++ crc = efi_crc32(*ptes, (*gpt)->NumberOfPartitionEntries *
++ (*gpt)->SizeOfPartitionEntry);
++ if (crc != (*gpt)->PartitionEntryArrayCRC32) {
++ // printf("GUID Partitition Entry Array CRC check failed.\n");
++ ped_free(*gpt);
++ *gpt = NULL;
++ ped_free(*ptes);
++ *ptes = NULL;
++ return rc;
++ }
++
++ /* We're done, all's well */
++ return 1;
++}
++
++/************************************************************
++ * gpt_write_pmbr()
++ * Requires:
++ * - dev
++ * Modifies:
++ * - dev
++ * Returns:
++ * 1 on success
++ * 0 on error
++ ************************************************************/
++
++
++static int
++gpt_write_pmbr(PedDevice * dev)
++{
++ LegacyMBR_t pmbr;
++ memset(&pmbr, 0, sizeof(pmbr));
++ pmbr.Signature = PED_CPU_TO_LE16(MSDOS_MBR_SIGNATURE);
++ pmbr.PartitionRecord[0].OSType = EFI_PMBR_OSTYPE_EFI_GPT;
++ pmbr.PartitionRecord[0].EndHead = 0xFE;
++ pmbr.PartitionRecord[0].EndSector = 0xFF;
++ pmbr.PartitionRecord[0].EndTrack = 0xFF;
++ pmbr.PartitionRecord[0].StartingLBA = PED_CPU_TO_LE32(1);
++ pmbr.PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32(last_lba(dev));
++
++ return ped_device_write(dev, &pmbr, GPT_PMBR_LBA, GPT_PMBR_SECTORS);
++}
++
++
++
++/************************************************************n
++ * gpt_update_headers()
++ * Updates the CRC fields for both primary and alternate GPTs
++ *
++ */
++static int
++gpt_update_headers(GuidPartitionTableHeader_t *pgpt,
++ GuidPartitionTableHeader_t *agpt,
++ GuidPartitionEntry_t *ptes)
++{
++
++ // printf("in UpdateGuidPartitionTableHeaders()\n");
++ PED_ASSERT(pgpt != NULL, return 0);
++ PED_ASSERT(agpt != NULL, return 0);
++ PED_ASSERT(ptes != NULL, return 0);
++
++ pgpt->PartitionEntryArrayCRC32 =
++ agpt->PartitionEntryArrayCRC32 =
++ efi_crc32(ptes, pgpt->NumberOfPartitionEntries *
++ pgpt->SizeOfPartitionEntry);
++
++ pgpt->HeaderCRC32 = 0;
++ pgpt->HeaderCRC32 = efi_crc32(pgpt, pgpt->HeaderSize);
++ agpt->HeaderCRC32 = 0;
++ agpt->HeaderCRC32 = efi_crc32(agpt, agpt->HeaderSize);
++ return 1;
++}
++
++
++
++static int
++gpt_write_new(PedDevice *dev)
++{
++ uint64_t size;
++ uuid_t uuid;
++ GuidPartitionTableHeader_t gpt, agpt;
++ GuidPartitionEntry_t ptes[GPT_DEFAULT_RESERVED_PARTITION_ENTRIES];
++ int count;
++
++ // printf("in CreateNewGuidPartitionTableHeader()\n");
++ memset(&gpt, 0, sizeof(gpt));
++ gpt.Signature = GUID_PT_HEADER_SIGNATURE;
++ gpt.Revision = GUID_PT_HEADER_REVISION_V1_02;
++ gpt.HeaderSize = 92; /* per 1.02 spec */
++ gpt.MyLBA = 1;
++ gpt.AlternateLBA = last_lba(dev);
++ gpt.FirstUsableLBA = (GPT_DEFAULT_RESERVED_PARTITION_ENTRY_ARRAY_SIZE /
++ dev->sector_size) + 2;
++ gpt.LastUsableLBA =
++ gpt.AlternateLBA -
++ (GPT_DEFAULT_RESERVED_PARTITION_ENTRY_ARRAY_SIZE /
++ dev->sector_size) - 1;
++ uuid_generate(uuid);
++ memcpy(&(gpt.DiskGUID), uuid, sizeof(uuid));
++ gpt.PartitionEntryLBA = 2;
++ gpt.NumberOfPartitionEntries = GPT_DEFAULT_RESERVED_PARTITION_ENTRIES;
++ gpt.SizeOfPartitionEntry = sizeof(GuidPartitionEntry_t);
++
++ memset(ptes, 0,
++ gpt.NumberOfPartitionEntries * gpt.SizeOfPartitionEntry);
++
++ /* Fix up Alternate GPT */
++ memcpy(&agpt, &gpt, sizeof(gpt));
++ agpt.MyLBA = gpt.AlternateLBA;
++ agpt.AlternateLBA = gpt.MyLBA;
++ agpt.PartitionEntryLBA = agpt.MyLBA -
++ (GPT_DEFAULT_RESERVED_PARTITION_ENTRY_ARRAY_SIZE /
++ dev->sector_size);
++
++ if (!gpt_update_headers(&gpt, &agpt, ptes))
++ return 0;
++
++ /* Before the writes */
++ /* Write PTH and PTEs */
++ if (!gpt_write_header(dev, &gpt))
++ return 0;
++ if (!gpt_write_part_entries(dev, &gpt, ptes))
++ return 0;
++
++
++ /* Write Alternate PTH & PTEs */
++ if (!gpt_write_part_entries(dev, &agpt, ptes))
++ return 0;
++ if (!gpt_write_header(dev, &agpt))
++ return 0;
++
++ return 1;
++}
++
++
++
++static int
++gpt_write_new_disk(PedDevice * dev)
++{
++ if (!gpt_write_pmbr(dev))
++ return 0;
++ if (!gpt_write_new(dev))
++ return 0;
++ return 1;
++}
++
++
++/************************************************************
++ * gpt_fix_broken_header()
++ * Uses values from alternate GPT and puts them in primary GPT.
++ * Requires:
++ * pgpt, agpt, ptes.
++ *
++ * Modifies:
++ * pgpt
++ *
++ * Returns:
++ * 1 if valid
++ * 0 on error
++ ************************************************************/
++
++static int
++gpt_fix_broken_header(PedDevice *dev,
++ GuidPartitionTableHeader_t **badgpt,
++ GuidPartitionTableHeader_t *goodgpt,
++ GuidPartitionEntry_t *ptes)
++{
++
++ PED_ASSERT(badgpt != NULL, return 0);
++ PED_ASSERT(goodgpt != NULL, return 0);
++ PED_ASSERT(ptes != NULL, return 0);
++
++ printf("GPT: Fixing broken header.\n");
++
++ *badgpt = (GuidPartitionTableHeader_t *)
++ ped_malloc(sizeof(GuidPartitionTableHeader_t));
++ if (!*badgpt) return 0;
++ memset(*badgpt, 0, sizeof(**badgpt));
++
++ memcpy(*badgpt, goodgpt, sizeof(*goodgpt));
++
++ /* Change badgpt values */
++ (*badgpt)->MyLBA = goodgpt->AlternateLBA;
++ (*badgpt)->AlternateLBA = goodgpt->MyLBA;
++
++
++ if ((*badgpt)->MyLBA == 1)
++ (*badgpt)->PartitionEntryLBA = (*badgpt)->MyLBA + 1;
++ else
++ (*badgpt)->PartitionEntryLBA = (*badgpt)->MyLBA -
++ (GPT_DEFAULT_RESERVED_PARTITION_ENTRY_ARRAY_SIZE /
++ dev->sector_size);
++
++ return gpt_update_headers(*badgpt, goodgpt, ptes);
++}
++
++
++
++
++static void
++gpt_print_legacy_part(PartitionRecord_t * pr, int i)
++{
++ if (!pr)
++ return;
++ if (!(pr->OSType))
++ return;
++ printf("Legacy Partition Record %d\n", i);
++ printf("\tBootInd %02x", pr->BootIndicator);
++ printf("\tSHead %02x", pr->StartHead);
++ printf("\tSSector %02x", pr->StartSector);
++ printf("\tSTrack %02x\n", pr->StartTrack);
++ printf("\tOSType %02x", pr->OSType);
++ printf("\tEHead %02x", pr->EndHead);
++ printf("\tESector %02x", pr->EndSector);
++ printf("\tETrack %02x\n", pr->EndTrack);
++ printf("\tStartingLBA : %x", pr->StartingLBA);
++ printf("\tSizeInLBA : %x\n", pr->SizeInLBA);
++ return;
++}
++
++static void
++gpt_print_mbr(LegacyMBR_t * mbr)
++{
++ int i;
++ if (!mbr)
++ return;
++ if (!is_legacy_mbr_valid(mbr)) {
++ printf("MBR is invalid.\n");
++ return;
++ }
++
++ printf("UniqueMBRSignature: %x\n", mbr->UniqueMBRSignature);
++ for (i = 0; i < 4; i++)
++ gpt_print_legacy_part(&(mbr->PartitionRecord[i]), i);
++ printf("Signature: %x\n", mbr->Signature);
++ return;
++}
++
++
++
++/************************************************************
++ * gpt_find_valid()
++ * Requires:
++ * - dev
++ * - pgpt is a GPTH if it's valid
++ * - agpt is a GPTH if it's valid
++ * - ptes is a PTE
++ * Modifies:
++ * - gpt & ptes
++ * Returns:
++ * 1 if valid
++ * 0 on error
++ ************************************************************/
++static int
++gpt_find_valid(const PedDevice * dev,
++ GuidPartitionTableHeader_t ** pgpt,
++ GuidPartitionTableHeader_t ** agpt,
++ GuidPartitionEntry_t ** ptes)
++{
++ int rc = 0;
++ GuidPartitionEntry_t *pptes = NULL, *aptes = NULL;
++ uint64_t lastlba;
++
++ PED_ASSERT(dev != NULL, return 0);
++ PED_ASSERT(pgpt != NULL, return 0);
++ PED_ASSERT(agpt != NULL, return 0);
++ PED_ASSERT(ptes != NULL, return 0);
++
++ lastlba = last_lba(dev);
++ /* Check the Primary GPT */
++ rc = gpt_is_valid(dev, 1, pgpt, &pptes);
++ if (rc) {
++ /* Primary GPT is OK, check the alternate and warn if bad */
++ rc = gpt_is_valid(dev, (*pgpt)->AlternateLBA,
++ agpt, &aptes);
++
++ if (!rc) {
++ *agpt = NULL;
++ printf("Alternate GPT is invalid, using primary GPT.\n");
++ }
++ if (aptes) ped_free(aptes);
++ *ptes = pptes;
++ return 1;
++ } /* if primary is valid */
++ else {
++ /* Primary GPT is bad, check the Alternate GPT */
++ *pgpt = NULL;
++ rc = gpt_is_valid(dev, lastlba,
++ agpt, &aptes);
++ if (rc) {
++ /* Primary is bad, alternate is good.
++ Return values from the alternate and warn.
++ */
++ printf
++ ("Primary GPT is invalid, using alternate GPT.\n");
++ *ptes = aptes;
++ return 1;
++ }
++ }
++ /* Both primary and alternate GPTs are bad.
++ * This isn't our disk, return 0.
++ */
++ *pgpt = NULL;
++ *agpt = NULL;
++ *ptes = NULL;
++ return 0;
++}
++
++#ifdef GPT_DEBUG
++static void
++print_disk_info(PedDevice *dev)
++{
++ unsigned int i;
++ LegacyMBR_t mbr;
++ GuidPartitionTableHeader_t *pgpt = NULL, *agpt = NULL, *gpt = NULL;
++ GuidPartitionEntry_t *pte = NULL, zeropte;
++
++ memset(&zeropte, 0, sizeof(zeropte));
++ if (!ped_device_read(dev, &mbr, GPT_PMBR_LBA, GPT_PMBR_SECTORS)) {
++ printf("print_disk_info error: ped_device_read(mbr) error.\n");
++ return;
++ }
++
++ if (mbr.PartitionRecord[0].OSType == EFI_PMBR_OSTYPE_EFI_GPT) {
++ /* This is an EFI GPT disk */
++ if (!ped_device_read(dev, &pgpt,
++ GPT_PRIMARY_HEADER_LBA,
++ GPT_HEADER_SECTORS)) {
++ printf("print_disk_info error: ped_device_read(gpt) error.\n");
++ return;
++ }
++ printf("This is an EFI GPT disk.\n");
++ if (gpt_find_valid(dev, &pgpt, &agpt, &pte)) {
++ if (pgpt) gpt = pgpt;
++ else if (agpt) gpt = agpt;
++ }
++ else {
++ printf("GUID Partition Table is invalid.\n");
++ return;
++ }
++ for (i = 0; pte && i < gpt->NumberOfPartitionEntries; i++) {
++ /* Partition entry is unused if all bytes are 0 */
++ if (memcmp(&zeropte, &pte[i], sizeof(zeropte)))
++ gpt_print_part_entry(&pte[i], i);
++ }
++ if (pgpt) ped_free(pgpt);
++ if (agpt) ped_free(agpt);
++ if (pte) ped_free(pte);
++ } else {
++ printf("This is not an EFI GPT disk. Try using vanilla msdos partition tables.\n");
++ }
++ return;
++}
++#endif
++
++
++
++
++
++void
++ped_disk_gpt_init()
++{
++ PED_ASSERT(sizeof(GuidPartitionTableHeader_t) == 512, return);
++ PED_ASSERT(sizeof(GuidPartitionEntryAttributes_t) == 8, return);
++ PED_ASSERT(sizeof(GuidPartitionEntry_t) == 128, return);
++
++ ped_register_disk_type(&gpt_disk_type);
++}
++
++void
++ped_disk_gpt_done()
++{
++ ped_unregister_disk_type(&gpt_disk_type);
++}
++
++static int
++gpt_probe(const PedDevice * dev)
++{
++ GuidPartitionTableHeader_t *pgpt = NULL, *agpt = NULL;
++ GuidPartitionEntry_t *ptes = NULL;
++
++ PED_ASSERT(dev != NULL, return 0);
++
++ if (!ped_device_open((PedDevice *) dev))
++ return 0;
++
++ if (!(gpt_find_valid(dev, &pgpt, &agpt, &ptes))) {
++ ped_device_close((PedDevice *) dev);
++ return 0;
++ }
++
++ ped_device_close((PedDevice *) dev);
++
++ if (pgpt) ped_free(pgpt);
++ if (agpt) ped_free(agpt);
++ if (ptes) ped_free(ptes);
++ return 1;
++}
++
++static PedDisk *
++gpt_open(PedDevice * dev)
++{
++ PedDisk *disk;
++
++ PED_ASSERT(dev != NULL, return 0);
++
++ if (!gpt_probe(dev))
++ goto error;
++
++
++ ped_device_open((PedDevice *) dev);
++
++ disk = ped_disk_alloc(dev, &gpt_disk_type);
++
++ if (!disk)
++ goto error;
++
++ if (!gpt_read(disk))
++ goto error_free_disk_specific;
++
++ return disk;
++
++ error_free_disk_specific:
++ ped_free(disk->disk_specific);
++ error_free_disk:
++ ped_free(disk);
++ error:
++ return NULL;
++}
++
++static PedDisk *
++gpt_create(PedDevice * dev)
++{
++ PedDisk *newdisk;
++ PED_ASSERT(dev != NULL, return 0);
++
++ if (!ped_device_open(dev))
++ goto error;
++
++
++ gpt_write_new_disk(dev);
++
++ if (!ped_device_sync(dev))
++ goto error_close_dev;
++
++ ped_device_close(dev);
++ newdisk = gpt_open(dev);
++ return newdisk;
++
++ error_close_dev:
++ ped_device_close(dev);
++ error:
++ return 0;
++}
++
++static int
++gpt_close(PedDisk * disk)
++{
++ PED_ASSERT(disk != NULL, return 0);
++
++ ped_device_close(disk->dev);
++ ped_disk_delete_all(disk);
++ if (disk->disk_specific) ped_free(disk->disk_specific);
++ ped_free(disk);
++ return 1;
++}
++
++
++
++
++
++
++static int
++gpt_read(PedDisk * disk)
++{
++ PedPartition *part;
++ unsigned int i;
++ GPTDiskData *gpt_disk_data;
++ GPTPartitionData *gpt_part_data;
++ PedConstraint* constraint_exact;
++ efi_guid_t unused = UNUSED_ENTRY_GUID;
++
++ PED_ASSERT(disk != NULL, return 0);
++ PED_ASSERT(disk->dev != NULL, return 0);
++
++
++ ped_disk_delete_all(disk);
++
++ if (!disk->disk_specific) gpt_new(disk);
++ PED_ASSERT(disk->disk_specific != NULL, return 0);
++ gpt_disk_data = disk->disk_specific;
++
++
++ if (!gpt_find_valid(disk->dev, &(gpt_disk_data->pgpt), &(gpt_disk_data->agpt), &(gpt_disk_data->ptes)))
++ return 0;
++
++ /* If one of the gpts are broken, fix it. */
++ if (!gpt_disk_data->pgpt) {
++ gpt_fix_broken_header(disk->dev,
++ &gpt_disk_data->pgpt,
++ gpt_disk_data->agpt,
++ gpt_disk_data->ptes);
++ }
++ else if (!gpt_disk_data->agpt) {
++ gpt_fix_broken_header(disk->dev,
++ &gpt_disk_data->agpt,
++ gpt_disk_data->pgpt,
++ gpt_disk_data->ptes);
++ }
++
++ for (i = 0; i < gpt_disk_data->pgpt->NumberOfPartitionEntries; i++) {
++
++ if (!efi_guidcmp(gpt_disk_data->ptes[i].PartitionTypeGuid,
++ unused)) continue;
++
++ part = ped_partition_alloc(disk, PED_PARTITION_PRIMARY, NULL,
++ gpt_disk_data->ptes[i].StartingLBA,
++ gpt_disk_data->ptes[i].EndingLBA);
++ if (!part)
++ return 0;
++
++ part->fs_type = ped_file_system_probe(&part->geom);
++ part->num = i+1;
++
++ gpt_part_data = part->disk_specific =
++ ped_malloc(sizeof(GPTPartitionData));
++ if (!gpt_part_data) {
++ ped_free(part);
++ return 0;
++ }
++ memset(gpt_part_data, 0, sizeof(*gpt_part_data));
++
++ gpt_part_data->pte = &(gpt_disk_data->ptes[i]);
++
++ constraint_exact = ped_constraint_exact (&part->geom);
++ if (!ped_disk_add_partition(disk, part, constraint_exact)) {
++ ped_free(gpt_part_data);
++ ped_free(part);
++ return 0;
++ }
++ ped_constraint_destroy (constraint_exact);
++
++ }
++ return 1;
++}
++
++
++static int
++gpt_write(PedDisk * disk)
++{
++
++ GPTDiskData *gpt_disk_data;
++ PedPartition *part = NULL;
++
++ PED_ASSERT(disk != NULL, return 0);
++ PED_ASSERT(disk->dev != NULL, return 0);
++ PED_ASSERT(disk->disk_specific != NULL, return 0);
++ gpt_disk_data = disk->disk_specific;
++
++ if (!gpt_write_pmbr(disk->dev)) return 0;
++
++ gpt_update_headers(gpt_disk_data->pgpt,
++ gpt_disk_data->agpt,
++ gpt_disk_data->ptes);
++
++ /* Write PTH and PTEs */
++ if (!gpt_write_header(disk->dev, gpt_disk_data->pgpt))
++ return 0;
++ if (!gpt_write_part_entries(disk->dev, gpt_disk_data->pgpt, gpt_disk_data->ptes))
++ return 0;
++
++
++ /* Write Alternate PTH & PTEs */
++ if (!gpt_write_part_entries(disk->dev, gpt_disk_data->agpt, gpt_disk_data->ptes))
++ return 0;
++ if (!gpt_write_header(disk->dev, gpt_disk_data->agpt))
++ return 0;
++
++ if (!ped_device_sync(disk->dev))
++ return 0;
++
++ return 1;
++}
++
++
++
++static int
++add_metadata_part(PedDisk * disk, PedPartitionType type, PedSector start,
++ PedSector length)
++{
++ PedPartition *new_part;
++ PedConstraint * constraint_exact;
++ PED_ASSERT(disk != NULL, return 0);
++
++
++ new_part =
++ ped_partition_new(disk, type | PED_PARTITION_METADATA, NULL,
++ start, start + length - 1);
++ if (!new_part)
++ goto error;
++
++ constraint_exact = ped_constraint_exact (&new_part->geom);
++
++ if (!ped_disk_add_partition(disk, new_part, constraint_exact))
++ goto error_destroy_new_part;
++
++ return 1;
++
++ error_destroy_new_part:
++ ped_partition_destroy(new_part);
++ error:
++ return 0;
++}
++
++static PedPartition *
++gpt_partition_new(const PedDisk *disk,
++ PedPartitionType part_type,
++ const PedFileSystemType* fs_type,
++ PedSector start,
++ PedSector end)
++{
++ unsigned int i;
++ uuid_t uuid;
++ efi_guid_t unused_entry_guid = UNUSED_ENTRY_GUID;
++ GPTDiskData *gpt_disk_data;
++ GPTPartitionData *gpt_part_data;
++ PedPartition *part;
++
++ PED_ASSERT(disk != NULL, return NULL);
++
++
++ part = ped_partition_alloc (disk, part_type, fs_type, start, end);
++ if (!part) return NULL;
++
++ if (part_type != PED_PARTITION_PRIMARY)
++ return part;
++
++#if 0
++ if (!ped_disk_check_overlap(disk, part)) {
++ ped_exception_throw (
++ PED_EXCEPTION_ERROR,
++ PED_EXCEPTION_CANCEL,
++ _("The new partition overlaps with another "
++ "partition."));
++ ped_free(part);
++ return NULL;
++ }
++#endif
++
++ PED_ASSERT(disk->disk_specific != NULL, return NULL);
++
++ gpt_disk_data = disk->disk_specific;
++
++
++ PED_ASSERT(gpt_disk_data->pgpt != NULL, return NULL);
++ PED_ASSERT(gpt_disk_data->agpt != NULL, return NULL);
++ PED_ASSERT(gpt_disk_data->ptes != NULL, return NULL);
++
++
++ for (i = 0; i < gpt_disk_data->pgpt->NumberOfPartitionEntries; i++) {
++ if (!efi_guidcmp
++ (gpt_disk_data->ptes[i].PartitionTypeGuid, unused_entry_guid)) {
++ break;
++ }
++ }
++ /* No unused entries */
++ if (i == gpt_disk_data->pgpt->NumberOfPartitionEntries){
++ ped_free(part);
++ return NULL;
++ }
++
++ part->num = i + 1;
++ gpt_disk_data->ptes[i].StartingLBA = part->geom.start;
++ gpt_disk_data->ptes[i].EndingLBA = part->geom.end;
++ uuid_generate(uuid);
++ memcpy(&(gpt_disk_data->ptes[i].UniquePartitionGuid), uuid, sizeof(uuid));
++
++ gpt_disk_data->ptes[i].PartitionTypeGuid = PARTITION_BASIC_DATA_GUID;
++
++ if (fs_type && fs_type->name && !strcmp(fs_type->name, "linux-swap"))
++ gpt_disk_data->ptes[i].PartitionTypeGuid =
++ PARTITION_SWAP_GUID;
++
++
++ gpt_part_data = part->disk_specific =
++ ped_malloc(sizeof(GPTPartitionData));
++ if (!gpt_part_data) return part;
++ memset(gpt_part_data, 0, sizeof(*gpt_part_data));
++
++ gpt_part_data->pte = &(gpt_disk_data->ptes[i]);
++
++ return part;
++}
++
++static void
++gpt_partition_destroy(PedPartition *part)
++{
++ GPTPartitionData *gpt_part_data;
++
++ PED_ASSERT(part != NULL, return);
++
++ if (part->type != PED_PARTITION_PRIMARY)
++ return;
++
++ PED_ASSERT(part->disk_specific != NULL, return);
++ gpt_part_data = part->disk_specific;
++ if (gpt_part_data->pte)
++ memset(gpt_part_data->pte, 0, sizeof(*(gpt_part_data->pte)));
++
++ ped_free(part->disk_specific);
++ part->disk_specific = NULL;
++ ped_free(part);
++}
++
++/**********************************************************
++ * Allocate metadata partitions for the GPTH and PTES.
++ *
++ */
++static int
++_alloc_metadata_unknown(PedDisk * disk)
++{
++ uint64_t pte_reserved_blocks;
++ PED_ASSERT(disk != NULL, return 0);
++ PED_ASSERT(disk->dev != NULL, return 0);
++
++ pte_reserved_blocks =
++ (GPT_DEFAULT_RESERVED_PARTITION_ENTRY_ARRAY_SIZE /
++ disk->dev->sector_size);
++
++
++ /* metadata at the start of the disk includes the MBR */
++ if (!add_metadata_part(disk, PED_PARTITION_PRIMARY,
++ GPT_PMBR_LBA,
++ GPT_PMBR_SECTORS
++ + GPT_HEADER_SECTORS
++ + pte_reserved_blocks))
++ return 0;
++
++ /* metadata at the end of the disk */
++ if (!add_metadata_part(disk, PED_PARTITION_PRIMARY,
++ last_lba(disk->dev) -
++ pte_reserved_blocks,
++ GPT_HEADER_SECTORS
++ + pte_reserved_blocks))
++ return 0;
++
++ return 1;
++}
++
++
++/**********************************************************
++ * Allocate metadata partitions for the GPTH and PTES
++ * when we know the actual metadata size
++ */
++static int
++_alloc_metadata_known(PedDisk * disk)
++{
++ int i;
++ PedSector gptlength, pteslength = 0;
++ GPTDiskData *gpt_disk_data;
++
++ PED_ASSERT(disk != NULL, return 0);
++ PED_ASSERT(disk->dev != NULL, return 0);
++ PED_ASSERT(disk->disk_specific != NULL, return 0);
++ gpt_disk_data = disk->disk_specific;
++
++ /* allocate space for the header */
++ gptlength = gpt_disk_data->pgpt->HeaderSize / disk->dev->sector_size;
++ if (gpt_disk_data->pgpt->HeaderSize % disk->dev->sector_size)
++ gptlength++;
++ /* allocate space for the ptes */
++ pteslength =
++ (gpt_disk_data->pgpt->NumberOfPartitionEntries *
++ gpt_disk_data->pgpt->SizeOfPartitionEntry) /
++ disk->dev->sector_size;
++ if ((gpt_disk_data->pgpt->NumberOfPartitionEntries *
++ gpt_disk_data->pgpt->SizeOfPartitionEntry) %
++ disk->dev->sector_size)
++ pteslength++;
++
++ /* metadata at the start of the disk includes the MBR */
++ if (!add_metadata_part(disk, PED_PARTITION_PRIMARY,
++ GPT_PMBR_LBA,
++ GPT_PMBR_SECTORS + gptlength + pteslength))
++ return 0;
++
++ /* metadata at the end of the disk */
++ if (!add_metadata_part(disk, PED_PARTITION_PRIMARY,
++ last_lba(disk->dev) - gptlength - pteslength + 1,
++ gptlength + pteslength))
++ return 0;
++
++ return 1;
++}
++
++
++
++
++/**********************************************************
++ * Allocate metadata partitions for the GPTH and PTES.
++ *
++ */
++static int
++gpt_alloc_metadata(PedDisk * disk)
++{
++ GPTDiskData *gpt_disk_data;
++ PED_ASSERT(disk != NULL, return 0);
++ PED_ASSERT(disk->dev != NULL, return 0);
++
++ gpt_disk_data = disk->disk_specific;
++
++ if (!gpt_disk_data ||
++ !gpt_disk_data->pgpt ||
++ !gpt_disk_data->agpt ||
++ !gpt_disk_data->ptes)
++ return _alloc_metadata_unknown(disk);
++
++ return _alloc_metadata_known(disk);
++}
++
++/************************************************************
++ * gpt_partition_enumerate()
++ * Requires:
++ * - part
++ * Modifies:
++ * - part->num
++ * Returns:
++ * 1 if valid
++ * 0 on error
++ * Actions:
++ * Does nothing, as the read/new/destroy functions maintain
++ * part->num.
++ *
++ *
++ ************************************************************/
++static int
++gpt_partition_enumerate(PedPartition * part)
++{
++ return 1;
++}
++
++
++/************************************************************
++ * gpt_clobber()
++ * Requires:
++ * - dev
++ * Modifies:
++ * - dev
++ * Returns: (per gpt_msdos.c)
++ * 1 if valid
++ * 0 on error
++ * Actions:
++ * This writes zeros to the PMBR and the primary and
++ * alternate GPTHs and PTEs.
++ ************************************************************/
++static int
++gpt_clobber(PedDevice * dev)
++{
++ LegacyMBR_t pmbr;
++ GuidPartitionTableHeader_t gpt;
++ GuidPartitionEntry_t ptes[GPT_DEFAULT_RESERVED_PARTITION_ENTRIES];
++ uint64_t lastLBA, pte_sectors;
++
++
++ PED_ASSERT (dev != NULL, return 0);
++ PED_ASSERT (gpt_probe(dev), return 0);
++
++ if (!ped_device_open(dev)) return 0;
++
++ PED_ASSERT(dev->sector_size != 0, return 0);
++ pte_sectors = GPT_DEFAULT_RESERVED_PARTITION_ENTRY_ARRAY_SIZE /
++ dev->sector_size;
++
++
++ memset(&pmbr, 0, sizeof(pmbr));
++ memset(&gpt, 0, sizeof(gpt));
++ memset(ptes, 0, sizeof(ptes));
++
++ lastLBA = last_lba(dev);
++
++ if (!ped_device_write(dev, &pmbr, GPT_PMBR_LBA, GPT_PMBR_SECTORS)) {
++ printf("gpt_clobber(): Unable to write empty PMBR.\n");
++ return 0;
++ }
++ if (!ped_device_write(dev, &gpt,
++ GPT_PRIMARY_HEADER_LBA,
++ GPT_HEADER_SECTORS)) {
++ printf("gpt_clobber(): Unable to write empty PGPTH.\n");
++ return 0;
++ }
++ if (!ped_device_write(dev, &ptes,
++ GPT_PRIMARY_PART_TABLE_LBA,
++ pte_sectors)) {
++ printf("gpt_clobber(): Unable to write empty PPTES.\n");
++ return 0;
++ }
++
++
++ if (!ped_device_write(dev, &ptes, lastLBA - pte_sectors,
++ pte_sectors)) {
++ printf("gpt_clobber(): Unable to write empty APTES.\n");
++ return 0;
++ }
++
++ if (!ped_device_write(dev, &gpt, lastLBA, GPT_HEADER_SECTORS)) {
++ printf("gpt_clobber(): Unable to write empty AGPTH.\n");
++ return 0;
++ }
++ return 1;
++}
++
++
++static int
++gpt_partition_set_flag(PedPartition *part,
++ PedPartitionFlag flag,
++ int state)
++{
++ GPTPartitionData *gpt_part_data;
++ PED_ASSERT(part != NULL, return 0);
++ PED_ASSERT(part->disk_specific != NULL, return 0);
++ gpt_part_data = part->disk_specific;
++ PED_ASSERT(gpt_part_data->pte != NULL, return 0);
++
++
++ switch (flag) {
++ case PED_PARTITION_RAID:
++ if (state)
++ gpt_part_data->pte->PartitionTypeGuid =
++ PARTITION_RAID_GUID;
++ else
++ gpt_part_data->pte->PartitionTypeGuid =
++ PARTITION_BASIC_DATA_GUID;
++ break;
++ case PED_PARTITION_LVM:
++ if (state)
++ gpt_part_data->pte->PartitionTypeGuid =
++ PARTITION_LVM_GUID;
++ else
++ gpt_part_data->pte->PartitionTypeGuid =
++ PARTITION_BASIC_DATA_GUID;
++
++ break;
++ case PED_PARTITION_BOOT:
++ if (state)
++ gpt_part_data->pte->PartitionTypeGuid =
++ PARTITION_SYSTEM_GUID;
++ else
++ gpt_part_data->pte->PartitionTypeGuid =
++ PARTITION_BASIC_DATA_GUID;
++
++ break;
++ case PED_PARTITION_LBA:
++ if (!state) return 0;
++ break;
++ case PED_PARTITION_HIDDEN:
++ default:
++ return 0;
++ }
++
++ if (part->fs_type && part->fs_type->name &&
++ !strcmp(part->fs_type->name, "linux-swap"))
++ gpt_part_data->pte->PartitionTypeGuid =
++ PARTITION_SWAP_GUID;
++
++
++ return 1;
++}
++
++static int
++gpt_partition_get_flag(const PedPartition *part,
++ PedPartitionFlag flag)
++{
++ GPTPartitionData *gpt_part_data = NULL;
++ PED_ASSERT(part->disk_specific != NULL, return 0);
++ gpt_part_data = part->disk_specific;
++
++ switch (flag) {
++ case PED_PARTITION_RAID:
++ return (!efi_guidcmp(gpt_part_data->pte->PartitionTypeGuid,
++ PARTITION_RAID_GUID));
++ case PED_PARTITION_LVM:
++ return (!efi_guidcmp(gpt_part_data->pte->PartitionTypeGuid,
++ PARTITION_LVM_GUID));
++ case PED_PARTITION_BOOT:
++ return (!efi_guidcmp(gpt_part_data->pte->PartitionTypeGuid,
++ PARTITION_SYSTEM_GUID));
++ case PED_PARTITION_LBA:
++ return 1;
++ case PED_PARTITION_HIDDEN:
++ default:
++ return 0;
++ }
++ return 0;
++}
++
++static int
++gpt_partition_is_flag_available(const PedPartition * part,
++ PedPartitionFlag flag)
++{
++ switch (flag) {
++ case PED_PARTITION_RAID:
++ case PED_PARTITION_LVM:
++ case PED_PARTITION_LBA:
++ case PED_PARTITION_BOOT:
++ return 1;
++ case PED_PARTITION_HIDDEN:
++ default:
++ return 0;
++ }
++ return 0;
++}
++
++static void
++gpt_partition_set_name(PedPartition *part,
++ const char *name)
++{
++ unsigned int i;
++ GPTPartitionData *gpt_part_data = NULL;
++ PED_ASSERT(part->disk_specific != NULL, return);
++ gpt_part_data = part->disk_specific;
++
++ if (!gpt_part_data->pte) return;
++
++ memset(gpt_part_data->pte->PartitionName, 0, sizeof(gpt_part_data->pte->PartitionName));
++
++ for (i=0; i < (72 / sizeof(efi_char16_t)) && i < strlen(name); i++) {
++ gpt_part_data->pte->PartitionName[i] = name[i];
++ }
++ return;
++}
++static const char *
++gpt_partition_get_name (const PedPartition * part)
++{
++ /* The name is stored in Unicode in the GPT entry */
++ char *name;
++ unsigned int i, namelen = (72 / sizeof(efi_char16_t));
++ GPTPartitionData *gpt_part_data = NULL;
++ PED_ASSERT(part->disk_specific != NULL, return 0);
++ gpt_part_data = part->disk_specific;
++
++ if (!gpt_part_data->pte) return NULL;
++
++ name = ped_malloc(namelen);
++ if (!name) return NULL;
++
++ memset(name, 0, namelen);
++
++ for (i=0; i < namelen ; i++) {
++ name[i] = gpt_part_data->pte->PartitionName[i];
++ }
++
++ return name;
++}
++
++
++static int
++gpt_get_max_primary_partition_count(const PedDisk *disk)
++{
++ int rc = GPT_DEFAULT_RESERVED_PARTITION_ENTRIES; /* 128 */
++ GPTDiskData *gpt_disk_data;
++ PED_ASSERT(disk != NULL, return 0);
++ gpt_disk_data = disk->disk_specific;
++
++ if (gpt_disk_data && gpt_disk_data->pgpt)
++ rc = gpt_disk_data->pgpt->NumberOfPartitionEntries;
++ return rc;
++}
++
++
++static PedConstraint*
++_non_metadata_constraint (PedDisk* disk)
++{
++ PedAlignment start_align;
++ PedAlignment end_align;
++ PedGeometry max_geom;
++ GPTDiskData *gpt_disk_data;
++ GuidPartitionTableHeader_t *gpt;
++
++ PED_ASSERT(disk != NULL, return 0);
++ PED_ASSERT(disk->dev != NULL, return 0);
++ PED_ASSERT(disk->disk_specific != NULL, return 0);
++ gpt_disk_data = disk->disk_specific;
++ PED_ASSERT(gpt_disk_data->pgpt != NULL, return 0);
++ gpt = gpt_disk_data->pgpt;
++
++ /* Alignments can be on any sector */
++ if (!ped_alignment_init (&start_align, 0, 1))
++ return NULL;
++ if (!ped_alignment_init (&end_align, 0, 1))
++ return NULL;
++ /* Geometry must reside within the usable LBAs */
++ if (!ped_geometry_init (&max_geom, disk,
++ gpt->FirstUsableLBA,
++ gpt->LastUsableLBA - gpt->FirstUsableLBA + 1))
++ return NULL;
++
++ return ped_constraint_new (&start_align, &end_align, &max_geom,
++ &max_geom, 1);
++}
++
++/* _try_constraint() copied verbatim from disk_mac.c
++ * per Clausen's recommendation
++ */
++
++static int
++_try_constraint (PedPartition* part, const PedConstraint* external,
++ PedConstraint* internal)
++{
++ PedConstraint* intersection;
++ PedGeometry* solution;
++
++ intersection = ped_constraint_intersect (external, internal);
++ ped_constraint_destroy (internal);
++ if (!intersection)
++ goto fail;
++
++ solution = ped_constraint_solve_nearest (intersection, &part->geom);
++ if (!solution)
++ goto fail_free_intersection;
++ ped_geometry_set (&part->geom, solution->start, solution->length);
++ ped_geometry_destroy (solution);
++ ped_constraint_destroy (intersection);
++ return 1;
++
++fail_free_intersection:
++ ped_constraint_destroy (intersection);
++fail:
++ return 0;
++}
++
++
++static int
++gpt_partition_align(PedPartition * part,
++ const PedConstraint * constraint)
++{
++ PED_ASSERT (part != NULL, return 0);
++
++ if (!_try_constraint (part, constraint,
++ _non_metadata_constraint (part->geom.disk))) {
++ ped_exception_throw (
++ PED_EXCEPTION_ERROR,
++ PED_EXCEPTION_CANCEL,
++ _("Unable to align partition."));
++ return 0;
++ }
++
++ return 1;
++}
++
++static PedDisk *
++gpt_new(PedDisk * disk)
++{
++ PED_ASSERT(disk != NULL, return NULL);
++ if (disk->disk_specific) return disk;
++
++ disk->disk_specific = ped_malloc(sizeof(GPTDiskData));
++ PED_ASSERT(disk->disk_specific != NULL, return NULL);
++ memset(disk->disk_specific, 0, sizeof(GPTDiskData));
++ return disk;
++}
++
++
++/*
++ * Overrides for Emacs so that we follow Linus's tabbing style.
++ * Emacs will notice this stuff at the end of the file and automatically
++ * adjust the settings for this buffer only. This must remain at the end
++ * of the file.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-indent-level: 4
++ * c-brace-imaginary-offset: 0
++ * c-brace-offset: -4
++ * c-argdecl-indent: 4
++ * c-label-offset: -4
++ * c-continued-statement-offset: 4
++ * c-continued-brace-offset: 0
++ * indent-tabs-mode: nil
++ * tab-width: 8
++ * End:
++ */
+diff -burN parted-1.4.16/libparted/fs_ext2/interface.c parted-1.4.16-gpt/libparted/fs_ext2/interface.c
+--- parted-1.4.16/libparted/fs_ext2/interface.c Tue Jul 3 05:59:30 2001
++++ parted-1.4.16-gpt/libparted/fs_ext2/interface.c Wed Jul 18 16:10:32 2001
+@@ -31,6 +31,7 @@
+ #include <parted/disk_pc98.h>
+ #include <parted/disk_mac.h>
+ #include <parted/disk_bsd.h>
++#include <parted/disk_gpt.h>
+ #include <parted/disk_sun.h>
+
+ #include <string.h>
+@@ -387,6 +388,15 @@
+ if (strcmp (disk_type->name, BSD_NAME) == 0) {
+ BSDPartitionData* bsd_data = part->disk_specific;
+ bsd_data->type = 0x8;
++ return 1;
++ }
++
++ if (strcmp (disk_type->name, GPT_NAME) == 0) {
++ GPTPartitionData *gpt_part_data = part->disk_specific;
++ PED_ASSERT(gpt_part_data != NULL, return 0);
++ PED_ASSERT(gpt_part_data->pte != NULL, return 0);
++ gpt_part_data->pte->PartitionTypeGuid =
++ PARTITION_BASIC_DATA_GUID;
+ return 1;
+ }
+
+diff -burN parted-1.4.16/libparted/fs_fat/fat.c parted-1.4.16-gpt/libparted/fs_fat/fat.c
+--- parted-1.4.16/libparted/fs_fat/fat.c Sat Apr 7 17:04:38 2001
++++ parted-1.4.16-gpt/libparted/fs_fat/fat.c Wed Jul 18 16:10:32 2001
+@@ -24,6 +24,7 @@
+ #include <parted/disk_loop.h>
+ #include <parted/disk_pc98.h>
+ #include <parted/disk_mac.h>
++#include <parted/disk_gpt.h>
+
+ #include "fat.h"
+ #include "calc.h"
+@@ -767,6 +768,15 @@
+ else
+ strcpy (mac_data->system_name, "FAT");
+ mac_data->status = 0x33;
++ return 1;
++ }
++
++ if (strcmp (disk_type->name, GPT_NAME) == 0) {
++ GPTPartitionData *gpt_part_data = part->disk_specific;
++ PED_ASSERT(gpt_part_data != NULL, return 0);
++ PED_ASSERT(gpt_part_data->pte != NULL, return 0);
++ gpt_part_data->pte->PartitionTypeGuid =
++ PARTITION_BASIC_DATA_GUID;
+ return 1;
+ }
+
+diff -burN parted-1.4.16/libparted/fs_hfs/hfs.c parted-1.4.16-gpt/libparted/fs_hfs/hfs.c
+--- parted-1.4.16/libparted/fs_hfs/hfs.c Sat Apr 7 17:04:38 2001
++++ parted-1.4.16-gpt/libparted/fs_hfs/hfs.c Wed Jul 18 16:10:32 2001
+@@ -25,6 +25,7 @@
+ #include <parted/disk_loop.h>
+ #include <parted/disk_pc98.h>
+ #include <parted/disk_mac.h>
++#include <parted/disk_gpt.h>
+
+ #include <libintl.h>
+ #if ENABLE_NLS
+@@ -34,7 +35,6 @@
+ #endif /* ENABLE_NLS */
+
+ #include <unistd.h>
+-#include <asm/page.h>
+ #include <string.h>
+
+ #define HFS_SIGNATURE 0x4244
+@@ -151,6 +151,15 @@
+ strcpy (mac_data->system_name, "Apple_HFS");
+ mac_data->status |= 0x7f;
+ }
++ return 1;
++ }
++
++ if (strcmp (disk_type->name, GPT_NAME) == 0) {
++ GPTPartitionData *gpt_part_data = part->disk_specific;
++ PED_ASSERT(gpt_part_data != NULL, return 0);
++ PED_ASSERT(gpt_part_data->pte != NULL, return 0);
++ gpt_part_data->pte->PartitionTypeGuid =
++ PARTITION_BASIC_DATA_GUID;
+ return 1;
+ }
+
+diff -burN parted-1.4.16/libparted/fs_jfs/jfs.c parted-1.4.16-gpt/libparted/fs_jfs/jfs.c
+--- parted-1.4.16/libparted/fs_jfs/jfs.c Sun Jul 15 01:00:24 2001
++++ parted-1.4.16-gpt/libparted/fs_jfs/jfs.c Wed Jul 18 16:10:32 2001
+@@ -25,6 +25,7 @@
+ #include <parted/disk_loop.h>
+ #include <parted/disk_mac.h>
+ #include <parted/disk_pc98.h>
++#include <parted/disk_gpt.h>
+
+ #define _JFS_UTILITY
+ #include "jfs_types.h"
+@@ -157,6 +158,18 @@
+ mac_data->status = 0x33;
+ return 1;
+ }
++
++ if (strcmp (disk_type->name, GPT_NAME) == 0) {
++ GPTPartitionData *gpt_part_data = part->disk_specific;
++ PED_ASSERT(gpt_part_data != NULL, return 0);
++ PED_ASSERT(gpt_part_data->pte != NULL, return 0);
++ gpt_part_data->pte->PartitionTypeGuid =
++ PARTITION_BASIC_DATA_GUID;
++ return 1;
++ }
++
++
++
+
+ return 0;
+ }
+diff -burN parted-1.4.16/libparted/fs_linux_swap/linux_swap.c parted-1.4.16-gpt/libparted/fs_linux_swap/linux_swap.c
+--- parted-1.4.16/libparted/fs_linux_swap/linux_swap.c Sat Apr 7 17:04:38 2001
++++ parted-1.4.16-gpt/libparted/fs_linux_swap/linux_swap.c Wed Jul 18 16:10:32 2001
+@@ -28,6 +28,7 @@
+ #include <parted/disk_pc98.h>
+ #include <parted/disk_mac.h>
+ #include <parted/disk_bsd.h>
++#include <parted/disk_gpt.h>
+ #include <parted/disk_sun.h>
+
+ #include <libintl.h>
+@@ -38,7 +39,6 @@
+ #endif /* ENABLE_NLS */
+
+ #include <unistd.h>
+-#include <asm/page.h>
+ #include <string.h>
+
+ #define SWAP_SPECIFIC(fs) ((SwapSpecific*) (fs->type_specific))
+@@ -563,6 +563,15 @@
+ if (strcmp (disk_type->name, BSD_NAME) == 0) {
+ BSDPartitionData* bsd_data = part->disk_specific;
+ bsd_data->type = 0x1;
++ return 1;
++ }
++
++ if (strcmp (disk_type->name, GPT_NAME) == 0) {
++ GPTPartitionData* gpt_part_data = part->disk_specific;
++ PED_ASSERT(gpt_part_data != NULL, return 0);
++ PED_ASSERT(gpt_part_data->pte != NULL, return 0);
++ gpt_part_data->pte->PartitionTypeGuid =
++ PARTITION_SWAP_GUID;
+ return 1;
+ }
+
+diff -burN parted-1.4.16/libparted/fs_ntfs/ntfs.c parted-1.4.16-gpt/libparted/fs_ntfs/ntfs.c
+--- parted-1.4.16/libparted/fs_ntfs/ntfs.c Sat Apr 7 17:04:38 2001
++++ parted-1.4.16-gpt/libparted/fs_ntfs/ntfs.c Wed Jul 18 16:10:32 2001
+@@ -25,6 +25,7 @@
+ #include <parted/disk_loop.h>
+ #include <parted/disk_pc98.h>
+ #include <parted/disk_mac.h>
++#include <parted/disk_gpt.h>
+
+ #include <libintl.h>
+ #if ENABLE_NLS
+@@ -34,7 +35,6 @@
+ #endif /* ENABLE_NLS */
+
+ #include <unistd.h>
+-#include <asm/page.h>
+ #include <string.h>
+
+ #define NTFS_SIGNATURE "NTFS"
+@@ -147,6 +147,15 @@
+ else
+ strcpy (mac_data->system_name, "Apple_UNIX_SVR2");
+ mac_data->status = 0x33;
++ return 1;
++ }
++
++ if (strcmp (disk_type->name, GPT_NAME) == 0) {
++ GPTPartitionData *gpt_part_data = part->disk_specific;
++ PED_ASSERT(gpt_part_data != NULL, return 0);
++ PED_ASSERT(gpt_part_data->pte != NULL, return 0);
++ gpt_part_data->pte->PartitionTypeGuid =
++ PARTITION_BASIC_DATA_GUID;
+ return 1;
+ }
+
+diff -burN parted-1.4.16/libparted/fs_reiserfs/reiserfs.c parted-1.4.16-gpt/libparted/fs_reiserfs/reiserfs.c
+--- parted-1.4.16/libparted/fs_reiserfs/reiserfs.c Sat Apr 7 17:04:38 2001
++++ parted-1.4.16-gpt/libparted/fs_reiserfs/reiserfs.c Wed Jul 18 16:10:32 2001
+@@ -25,6 +25,7 @@
+ #include <parted/disk_loop.h>
+ #include <parted/disk_pc98.h>
+ #include <parted/disk_mac.h>
++#include <parted/disk_gpt.h>
+
+ #include <libintl.h>
+ #if ENABLE_NLS
+@@ -34,7 +35,6 @@
+ #endif /* ENABLE_NLS */
+
+ #include <unistd.h>
+-#include <asm/page.h>
+ #include <string.h>
+
+ #define REISERFS_SIGNATURE "ReIsErFs"
+@@ -181,6 +181,15 @@
+ else
+ strcpy (mac_data->system_name, "Apple_UNIX_SVR2");
+ mac_data->status = 0x33;
++ return 1;
++ }
++
++ if (strcmp (disk_type->name, GPT_NAME) == 0) {
++ GPTPartitionData *gpt_part_data = part->disk_specific;
++ PED_ASSERT(gpt_part_data != NULL, return 0);
++ PED_ASSERT(gpt_part_data->pte != NULL, return 0);
++ gpt_part_data->pte->PartitionTypeGuid =
++ PARTITION_BASIC_DATA_GUID;
+ return 1;
+ }
+
+diff -burN parted-1.4.16/libparted/fs_ufs/ufs.c parted-1.4.16-gpt/libparted/fs_ufs/ufs.c
+--- parted-1.4.16/libparted/fs_ufs/ufs.c Sat Apr 7 17:04:39 2001
++++ parted-1.4.16-gpt/libparted/fs_ufs/ufs.c Wed Jul 18 16:10:32 2001
+@@ -24,6 +24,7 @@
+ #include <parted/parted.h>
+ #include <parted/endian.h>
+ #include <parted/disk_sun.h>
++#include <parted/disk_gpt.h>
+
+ #include <libintl.h>
+ #if ENABLE_NLS
+@@ -202,6 +203,17 @@
+ sun_data->type = 0x6;
+ return 1;
+ }
++
++ if (strcmp (disk_type->name, GPT_NAME) == 0) {
++ GPTPartitionData *gpt_part_data = part->disk_specific;
++ PED_ASSERT(gpt_part_data != NULL, return 0);
++ PED_ASSERT(gpt_part_data->pte != NULL, return 0);
++ gpt_part_data->pte->PartitionTypeGuid =
++ PARTITION_BASIC_DATA_GUID;
++ return 1;
++ }
++
++
+
+ return 0;
+ }
+diff -burN parted-1.4.16/libparted/fs_xfs/xfs.c parted-1.4.16-gpt/libparted/fs_xfs/xfs.c
+--- parted-1.4.16/libparted/fs_xfs/xfs.c Sun Jul 15 01:07:01 2001
++++ parted-1.4.16-gpt/libparted/fs_xfs/xfs.c Wed Jul 18 16:10:32 2001
+@@ -25,6 +25,7 @@
+ #include <parted/disk_loop.h>
+ #include <parted/disk_mac.h>
+ #include <parted/disk_pc98.h>
++#include <parted/disk_gpt.h>
+
+ #include <libintl.h>
+ #if ENABLE_NLS
+@@ -158,6 +159,16 @@
+ return 1;
+ }
+
++ if (strcmp (disk_type->name, GPT_NAME) == 0) {
++ GPTPartitionData *gpt_part_data = part->disk_specific;
++ PED_ASSERT(gpt_part_data != NULL, return 0);
++ PED_ASSERT(gpt_part_data->pte != NULL, return 0);
++ gpt_part_data->pte->PartitionTypeGuid =
++ PARTITION_BASIC_DATA_GUID;
++ return 1;
++ }
++
++
+ return 0;
+ }
+
+diff -burN parted-1.4.16/libparted/libparted.c parted-1.4.16-gpt/libparted/libparted.c
+--- parted-1.4.16/libparted/libparted.c Sun Jul 15 01:11:51 2001
++++ parted-1.4.16-gpt/libparted/libparted.c Wed Jul 18 16:10:32 2001
+@@ -26,6 +26,7 @@
+ #include <parted/disk_mac.h>
+ #include <parted/disk_pc98.h>
+ #include <parted/disk_sun.h>
++#include <parted/disk_gpt.h>
+
+ #include <grp.h>
+ #include <pwd.h>
+@@ -104,6 +105,7 @@
+ #endif
+ ped_disk_mac_init ();
+ ped_disk_bsd_init ();
++ ped_disk_gpt_init ();
+ ped_disk_sun_init ();
+ }
+
+@@ -147,6 +149,7 @@
+ ped_disk_loop_done ();
+ ped_disk_mac_done ();
+ ped_disk_bsd_done ();
++ ped_disk_gpt_done ();
+ ped_disk_sun_done ();
+ }
+