1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
|
/* gpt.h -- GPT and data structure definitions, types, and
functions */
/* This program is copyright (c) 2009-2022 by Roderick W. Smith. It is distributed
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
#ifndef __GPTSTRUCTS
#define __GPTSTRUCTS
#include <stdint.h>
#include <sys/types.h>
#include "gptpart.h"
#include "support.h"
#include "mbr.h"
#include "bsd.h"
#include "gptpart.h"
// Default values for sector alignment
#define DEFAULT_ALIGNMENT 2048
#define MAX_ALIGNMENT 65536
#define MIN_AF_ALIGNMENT 8
// Below constant corresponds to a ~279GiB (300GB) disk, since the
// smallest Advanced Format drive I know of is 320GB in size
#define SMALLEST_ADVANCED_FORMAT UINT64_C(585937500)
/****************************************
* *
* GPTData class and related structures *
* *
****************************************/
// Validity state of GPT data
enum GPTValidity {gpt_valid, gpt_corrupt, gpt_invalid};
// Which set of partition data to use
enum WhichToUse {use_gpt, use_mbr, use_bsd, use_new, use_abort};
// Header (first 512 bytes) of GPT table
#pragma pack(1)
struct GPTHeader {
uint64_t signature;
uint32_t revision;
uint32_t headerSize;
uint32_t headerCRC;
uint32_t reserved;
uint64_t currentLBA;
uint64_t backupLBA;
uint64_t firstUsableLBA;
uint64_t lastUsableLBA;
GUIDData diskGUID;
uint64_t partitionEntriesLBA;
uint32_t numParts;
uint32_t sizeOfPartitionEntries;
uint32_t partitionEntriesCRC;
unsigned char reserved2[GPT_RESERVED];
}; // struct GPTHeader
#pragma pack ()
// Data in GPT format
class GPTData {
protected:
struct GPTHeader mainHeader;
GPTPart *partitions;
uint32_t numParts; // # of partitions the table can hold
struct GPTHeader secondHeader;
MBRData protectiveMBR;
std::string device; // device filename
DiskIO myDisk;
uint32_t blockSize; // device logical block size
uint32_t physBlockSize; // device physical block size (or 0 if it can't be determined)
uint64_t diskSize; // size of device, in logical blocks
GPTValidity state; // is GPT valid?
int justLooking; // Set to 1 if program launched with "-l" or if read-only
int mainCrcOk;
int secondCrcOk;
int mainPartsCrcOk;
int secondPartsCrcOk;
int apmFound; // set to 1 if APM detected
int bsdFound; // set to 1 if BSD disklabel detected in MBR
uint32_t sectorAlignment; // Start partitions at multiples of sectorAlignment
int beQuiet;
WhichToUse whichWasUsed;
int LoadHeader(struct GPTHeader *header, DiskIO & disk, uint64_t sector, int *crcOk);
int LoadPartitionTable(const struct GPTHeader & header, DiskIO & disk, uint64_t sector = 0);
int CheckTable(struct GPTHeader *header);
int SaveHeader(struct GPTHeader *header, DiskIO & disk, uint64_t sector);
int SavePartitionTable(DiskIO & disk, uint64_t sector);
public:
// Basic necessary functions....
GPTData(void);
GPTData(const GPTData &);
GPTData(std::string deviceFilename);
virtual ~GPTData(void);
GPTData & operator=(const GPTData & orig);
// Verify (or update) data integrity
int Verify(void);
int CheckGPTSize(void);
int CheckHeaderValidity(void);
int CheckHeaderCRC(struct GPTHeader* header, int warn = 0);
void RecomputeCRCs(void);
void RebuildMainHeader(void);
void RebuildSecondHeader(void);
int VerifyMBR(void) {return protectiveMBR.FindOverlaps();}
int FindHybridMismatches(void);
int FindOverlaps(void);
int FindInsanePartitions(void);
// Load or save data from/to disk
int SetDisk(const std::string & deviceFilename);
DiskIO* GetDisk(void) {return &myDisk;}
int LoadMBR(const std::string & f) {return protectiveMBR.ReadMBRData(f);}
int WriteProtectiveMBR(void) {return protectiveMBR.WriteMBRData(&myDisk);}
void PartitionScan(void);
int LoadPartitions(const std::string & deviceFilename);
int ForceLoadGPTData(void);
int LoadMainTable(void);
int LoadSecondTableAsMain(void);
int SaveGPTData(int quiet = 0);
int SaveGPTBackup(const std::string & filename);
int LoadGPTBackup(const std::string & filename);
int SaveMBR(void);
int DestroyGPT(void);
int DestroyMBR(void);
// Display data....
void ShowAPMState(void);
void ShowGPTState(void);
void DisplayGPTData(void);
void DisplayMBRData(void) {protectiveMBR.DisplayMBRData();}
void ShowPartDetails(uint32_t partNum);
// Convert between GPT and other formats
virtual WhichToUse UseWhichPartitions(void);
void XFormPartitions(void);
int XFormDisklabel(uint32_t partNum);
int XFormDisklabel(BSDData* disklabel);
int OnePartToMBR(uint32_t gptPart, int mbrPart); // add one partition to MBR. Returns 1 if successful
// Adjust GPT structures WITHOUT user interaction...
int SetGPTSize(uint32_t numEntries, int fillGPTSectors = 1);
int MoveMainTable(uint64_t pteSector);
int MoveSecondTable(uint64_t pteSector);
void BlankPartitions(void);
int DeletePartition(uint32_t partNum);
uint32_t CreatePartition(uint32_t partNum, uint64_t startSector, uint64_t endSector);
void SortGPT(void);
int SwapPartitions(uint32_t partNum1, uint32_t partNum2);
int ClearGPTData(void);
void MoveSecondHeaderToEnd();
int SetName(uint32_t partNum, const UnicodeString & theName);
void SetDiskGUID(GUIDData newGUID);
int SetPartitionGUID(uint32_t pn, GUIDData theGUID);
void RandomizeGUIDs(void);
int ChangePartType(uint32_t pn, PartType theGUID);
void MakeProtectiveMBR(void) {protectiveMBR.MakeProtectiveMBR();}
void RecomputeCHS(void);
int Align(uint64_t* sector);
void SetProtectiveMBR(BasicMBRData & newMBR) {protectiveMBR = newMBR;}
// Return data about the GPT structures....
WhichToUse GetState(void) {return whichWasUsed;}
int GetPartRange(uint32_t* low, uint32_t* high);
int FindFirstFreePart(void);
uint32_t GetNumParts(void) {return mainHeader.numParts;}
uint64_t GetTableSizeInSectors(void) {return (((numParts * GPT_SIZE) / blockSize) +
(((numParts * GPT_SIZE) % blockSize) != 0)); }
uint64_t GetMainHeaderLBA(void) {return mainHeader.currentLBA;}
uint64_t GetSecondHeaderLBA(void) {return secondHeader.currentLBA;}
uint64_t GetMainPartsLBA(void) {return mainHeader.partitionEntriesLBA;}
uint64_t GetSecondPartsLBA(void) {return secondHeader.partitionEntriesLBA;}
uint64_t GetFirstUsableLBA(void) {return mainHeader.firstUsableLBA;}
uint64_t GetLastUsableLBA(void) {return mainHeader.lastUsableLBA;}
uint32_t CountParts(void);
bool ValidPartNum (const uint32_t partNum);
const GPTPart & operator[](uint32_t partNum) const;
const GUIDData & GetDiskGUID(void) const;
uint32_t GetBlockSize(void) {return blockSize;}
// Find information about free space
uint64_t FindFirstAvailable(uint64_t start = 0);
uint64_t FindFirstUsedLBA(void);
uint64_t FindLastUsedLBA(void);
uint64_t FindFirstInLargest(void);
uint64_t FindLastAvailable();
uint64_t FindLastInFree(uint64_t start, bool align = false);
uint64_t FindFreeBlocks(uint32_t *numSegments, uint64_t *largestSegment);
int IsFree(uint64_t sector, uint32_t *partNum = NULL);
int IsFreePartNum(uint32_t partNum);
int IsUsedPartNum(uint32_t partNum);
// Change how functions work, or return information on same
void SetAlignment(uint32_t n);
uint32_t ComputeAlignment(void); // Set alignment based on current partitions
uint32_t GetAlignment(void) {return sectorAlignment;}
void JustLooking(int i = 1) {justLooking = i;}
void BeQuiet(int i = 1) {beQuiet = i;}
WhichToUse WhichWasUsed(void) {return whichWasUsed;}
// Endianness functions
void ReverseHeaderBytes(struct GPTHeader* header);
void ReversePartitionBytes(); // for endianness
// Attributes functions
int ManageAttributes(int partNum, const std::string & command, const std::string & bits);
void ShowAttributes(const uint32_t partNum);
void GetAttribute(const uint32_t partNum, const std::string& attributeBits);
}; // class GPTData
// Function prototypes....
int SizesOK(void);
#endif
|