summaryrefslogtreecommitdiff
path: root/gpt.cc
diff options
context:
space:
mode:
authorRod Smith <rodsmith@rodsbooks.com>2017-07-21 21:48:13 -0400
committerRod Smith <rodsmith@rodsbooks.com>2017-07-21 21:48:13 -0400
commit503e9ada12d38394381442a944d5c9da847800b6 (patch)
tree9ee8654a5dd22cea6fb0cf0d0b161c4bb764400e /gpt.cc
parente7452642ac5fa514bd359bc3f93b6b46b1714213 (diff)
downloadsgdisk-503e9ada12d38394381442a944d5c9da847800b6.tar.gz
Initial commit of support for moving main partition table to arbitrary
location on disk (within limits based on existing partitions).
Diffstat (limited to 'gpt.cc')
-rw-r--r--gpt.cc56
1 files changed, 53 insertions, 3 deletions
diff --git a/gpt.cc b/gpt.cc
index d0a46c6..44f5fb4 100644
--- a/gpt.cc
+++ b/gpt.cc
@@ -276,6 +276,23 @@ int GPTData::Verify(void) {
<< "The 'e' option on the experts' menu may fix this problem.\n";
} // if
+ // Check the main and backup partition tables for overlap with things
+ if (mainHeader.partitionEntriesLBA + GetTableSizeInSectors() > mainHeader.firstUsableLBA) {
+ problems++;
+ cout << "\nProblem: Main partition table extends past the first usable LBA.\n"
+ << "Using 'j' on the experts' menu may enable fixing this problem.\n";
+ } // if
+ if (mainHeader.partitionEntriesLBA < 2) {
+ problems++;
+ cout << "\nProblem: Main partition table appears impossibly early on the disk.\n"
+ << "Using 'j' on the experts' menu may enable fixing this problem.\n";
+ } // if
+ if (secondHeader.partitionEntriesLBA + GetTableSizeInSectors() > secondHeader.currentLBA) {
+ problems++;
+ cout << "\nProblem: The backup partition table overlaps the backup header.\n"
+ << "Using 'e' on the experts' menu may fix this problem.\n";
+ } // if
+
if ((mainHeader.lastUsableLBA >= diskSize) || (mainHeader.lastUsableLBA > mainHeader.backupLBA)) {
problems++;
cout << "\nProblem: GPT claims the disk is larger than it is! (Claimed last usable\n"
@@ -552,8 +569,8 @@ void GPTData::RebuildMainHeader(void) {
mainHeader.firstUsableLBA = secondHeader.firstUsableLBA;
mainHeader.lastUsableLBA = secondHeader.lastUsableLBA;
mainHeader.diskGUID = secondHeader.diskGUID;
- mainHeader.partitionEntriesLBA = UINT64_C(2);
mainHeader.numParts = secondHeader.numParts;
+ mainHeader.partitionEntriesLBA = secondHeader.firstUsableLBA - GetTableSizeInSectors();
mainHeader.sizeOfPartitionEntries = secondHeader.sizeOfPartitionEntries;
mainHeader.partitionEntriesCRC = secondHeader.partitionEntriesCRC;
memcpy(mainHeader.reserved2, secondHeader.reserved2, sizeof(mainHeader.reserved2));
@@ -658,7 +675,7 @@ int GPTData::FindInsanePartitions(void) {
} // if
if (partitions[i].GetLastLBA() >= diskSize) {
problems++;
- cout << "\nProblem: partition " << i + 1 << " is too big for the disk.\n";
+ cout << "\nProblem: partition " << i + 1 << " is too big for the disk.\n";
} // if
} // if
} // for
@@ -1441,6 +1458,8 @@ void GPTData::DisplayGPTData(void) {
cout << "Logical sector size: " << blockSize << " bytes\n";
cout << "Disk identifier (GUID): " << mainHeader.diskGUID << "\n";
cout << "Partition table holds up to " << numParts << " entries\n";
+ cout << "Main partition table begins at sector " << mainHeader.partitionEntriesLBA
+ << " and ends at sector " << mainHeader.partitionEntriesLBA + GetTableSizeInSectors() - 1 << "\n";
cout << "First usable sector is " << mainHeader.firstUsableLBA
<< ", last usable sector is " << mainHeader.lastUsableLBA << "\n";
totalFree = FindFreeBlocks(&i, &temp);
@@ -1732,7 +1751,7 @@ int GPTData::SetGPTSize(uint32_t numEntries, int fillGPTSectors) {
partitions = newParts;
} // if/else existing partitions
numParts = numEntries;
- mainHeader.firstUsableLBA = ((numEntries * GPT_SIZE) / blockSize) + (((numEntries * GPT_SIZE) % blockSize) != 0) + 2 ;
+ mainHeader.firstUsableLBA = GetTableSizeInSectors() + mainHeader.partitionEntriesLBA;
secondHeader.firstUsableLBA = mainHeader.firstUsableLBA;
MoveSecondHeaderToEnd();
if (diskSize > 0)
@@ -1747,6 +1766,23 @@ int GPTData::SetGPTSize(uint32_t numEntries, int fillGPTSectors) {
return (allOK);
} // GPTData::SetGPTSize()
+// Change the start sector for the main partition table.
+// Returns 1 on success, 0 on failure
+int GPTData::MoveMainTable(uint64_t pteSector) {
+ uint64_t pteSize = GetTableSizeInSectors();
+ int retval = 1;
+
+ if ((pteSector >= 2) && ((pteSector + pteSize) <= FindFirstUsedLBA())) {
+ mainHeader.partitionEntriesLBA = pteSector;
+ mainHeader.firstUsableLBA = pteSector + pteSize;
+ RebuildSecondHeader();
+ } else {
+ cerr << "Unable to set the main partition table's location to " << pteSector << "!\n";
+ retval = 0;
+ } // if/else
+ return retval;
+} // GPTData::MoveMainTable()
+
// Blank the partition array
void GPTData::BlankPartitions(void) {
uint32_t i;
@@ -2121,6 +2157,20 @@ uint64_t GPTData::FindFirstAvailable(uint64_t start) {
return (first);
} // GPTData::FindFirstAvailable()
+// Returns the LBA of the start of the first partition on the disk (by
+// sector number), or 0 if there are no partitions defined.
+uint64_t GPTData::FindFirstUsedLBA(void) {
+ uint32_t i;
+ uint64_t firstFound = UINT64_MAX;
+
+ for (i = 0; i < numParts; i++) {
+ if ((partitions[i].IsUsed()) && (partitions[i].GetFirstLBA() < firstFound)) {
+ firstFound = partitions[i].GetFirstLBA();
+ } // if
+ } // for
+ return firstFound;
+} // GPTData::FindFirstUsedLBA()
+
// Finds the first available sector in the largest block of unallocated
// space on the disk. Returns 0 if there are no available blocks left
uint64_t GPTData::FindFirstInLargest(void) {