2022-06-13 21:16:20 +02:00
|
|
|
diff --git a/gpt.cc b/gpt.cc
|
2022-06-28 05:00:48 +02:00
|
|
|
index 76cd9ad..d61064f 100644
|
2022-06-13 21:16:20 +02:00
|
|
|
--- a/gpt.cc
|
|
|
|
+++ b/gpt.cc
|
|
|
|
@@ -1500,7 +1500,7 @@ int GPTData::DestroyGPT(void) {
|
|
|
|
cerr << "Warning! GPT main partition table not overwritten! Error is " << errno << "\n";
|
|
|
|
allOK = 0;
|
|
|
|
} // if write failed
|
|
|
|
- } // if
|
|
|
|
+ } // if
|
|
|
|
if (!myDisk.Seek(secondHeader.partitionEntriesLBA))
|
|
|
|
allOK = 0;
|
|
|
|
if (allOK) {
|
|
|
|
@@ -1911,6 +1911,23 @@ int GPTData::MoveMainTable(uint64_t pteSector) {
|
|
|
|
return retval;
|
|
|
|
} // GPTData::MoveMainTable()
|
|
|
|
|
|
|
|
+// Change the start sector for the secondary partition table.
|
|
|
|
+// Returns 1 on success, 0 on failure
|
2022-06-28 05:00:48 +02:00
|
|
|
+int GPTData::MoveSecondTable(uint64_t pteSector) {
|
2022-06-13 21:16:20 +02:00
|
|
|
+ uint64_t pteSize = GetTableSizeInSectors();
|
|
|
|
+ int retval = 1;
|
|
|
|
+
|
|
|
|
+ if ((pteSector > FindLastUsedLBA()) && ((pteSector + pteSize) < diskSize)) {
|
|
|
|
+ secondHeader.partitionEntriesLBA = pteSector; // (RebuildSecondHeader actually replaces this with lastUsableLBA+1)
|
|
|
|
+ mainHeader.lastUsableLBA = secondHeader.partitionEntriesLBA - UINT64_C(1);
|
|
|
|
+ RebuildSecondHeader();
|
|
|
|
+ } else {
|
|
|
|
+ cerr << "Unable to set the secondary partition table's location to " << pteSector << "!\n";
|
|
|
|
+ retval = 0;
|
|
|
|
+ } // if/else
|
|
|
|
+ return retval;
|
2022-06-28 05:00:48 +02:00
|
|
|
+} // GPTData::MoveSecondTable()
|
2022-06-13 21:16:20 +02:00
|
|
|
+
|
|
|
|
// Blank the partition array
|
|
|
|
void GPTData::BlankPartitions(void) {
|
|
|
|
uint32_t i;
|
|
|
|
@@ -2285,7 +2302,7 @@ uint64_t GPTData::FindFirstAvailable(uint64_t start) {
|
|
|
|
} // 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.
|
|
|
|
+// sector number), or UINT64_MAX if there are no partitions defined.
|
|
|
|
uint64_t GPTData::FindFirstUsedLBA(void) {
|
|
|
|
uint32_t i;
|
|
|
|
uint64_t firstFound = UINT64_MAX;
|
|
|
|
@@ -2298,6 +2315,20 @@ uint64_t GPTData::FindFirstUsedLBA(void) {
|
|
|
|
return firstFound;
|
|
|
|
} // GPTData::FindFirstUsedLBA()
|
|
|
|
|
|
|
|
+// Returns the LBA of the end of the last partition on the disk (by
|
|
|
|
+// sector number), or 0 if there are no partitions defined.
|
|
|
|
+uint64_t GPTData::FindLastUsedLBA(void) {
|
|
|
|
+ uint32_t i;
|
|
|
|
+ uint64_t lastFound = 0;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < numParts; i++) {
|
|
|
|
+ if ((partitions[i].IsUsed()) && (partitions[i].GetFirstLBA() > lastFound)) {
|
|
|
|
+ lastFound = partitions[i].GetFirstLBA();
|
|
|
|
+ } // if
|
|
|
|
+ } // for
|
|
|
|
+ return lastFound;
|
|
|
|
+} // GPTData::FindLastUsedLBA()
|
|
|
|
+
|
|
|
|
// 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) {
|
|
|
|
diff --git a/gpt.h b/gpt.h
|
2022-06-28 05:00:48 +02:00
|
|
|
index 5d19372..17b3380 100644
|
2022-06-13 21:16:20 +02:00
|
|
|
--- a/gpt.h
|
|
|
|
+++ b/gpt.h
|
|
|
|
@@ -142,6 +142,7 @@ public:
|
|
|
|
// Adjust GPT structures WITHOUT user interaction...
|
|
|
|
int SetGPTSize(uint32_t numEntries, int fillGPTSectors = 1);
|
|
|
|
int MoveMainTable(uint64_t pteSector);
|
2022-06-28 05:00:48 +02:00
|
|
|
+ int MoveSecondTable(uint64_t pteSector);
|
2022-06-13 21:16:20 +02:00
|
|
|
void BlankPartitions(void);
|
|
|
|
int DeletePartition(uint32_t partNum);
|
|
|
|
uint32_t CreatePartition(uint32_t partNum, uint64_t startSector, uint64_t endSector);
|
|
|
|
@@ -158,7 +159,7 @@ public:
|
|
|
|
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);
|
|
|
|
@@ -181,6 +182,7 @@ public:
|
|
|
|
// 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);
|
|
|
|
diff --git a/gptcl.cc b/gptcl.cc
|
2022-06-28 05:00:48 +02:00
|
|
|
index 34c9421..232285a 100644
|
2022-06-13 21:16:20 +02:00
|
|
|
--- a/gptcl.cc
|
|
|
|
+++ b/gptcl.cc
|
|
|
|
@@ -68,7 +68,7 @@ int GPTDataCL::DoOptions(int argc, char* argv[]) {
|
|
|
|
int opt, numOptions = 0, saveData = 0, neverSaveData = 0;
|
|
|
|
int partNum = 0, newPartNum = -1, saveNonGPT = 1, retval = 0, pretend = 0;
|
|
|
|
int byteSwapPartNum = 0;
|
|
|
|
- uint64_t low, high, startSector, endSector, sSize, mainTableLBA;
|
|
|
|
+ uint64_t low, high, startSector, endSector, sSize, mainTableLBA, secondTableLBA;
|
|
|
|
uint64_t temp; // temporary variable; free to use in any case
|
|
|
|
char *device;
|
|
|
|
string cmd, typeGUID, name;
|
2022-06-28 05:00:48 +02:00
|
|
|
@@ -85,7 +85,7 @@ int GPTDataCL::DoOptions(int argc, char* argv[]) {
|
|
|
|
{"recompute-chs", 'C', POPT_ARG_NONE, NULL, 'C', "recompute CHS values in protective/hybrid MBR", ""},
|
|
|
|
{"delete", 'd', POPT_ARG_INT, &deletePartNum, 'd', "delete a partition", "partnum"},
|
|
|
|
{"display-alignment", 'D', POPT_ARG_NONE, NULL, 'D', "show number of sectors per allocation block", ""},
|
|
|
|
- {"move-second-header", 'e', POPT_ARG_NONE, NULL, 'e', "move second header to end of disk", ""},
|
|
|
|
+ {"move-second-header", 'e', POPT_ARG_NONE, NULL, 'e', "move second/backup header to end of disk", ""},
|
|
|
|
{"end-of-largest", 'E', POPT_ARG_NONE, NULL, 'E', "show end of largest free block", ""},
|
|
|
|
{"first-in-largest", 'f', POPT_ARG_NONE, NULL, 'f', "show start of the largest free block", ""},
|
|
|
|
{"first-aligned-in-largest", 'F', POPT_ARG_NONE, NULL, 'F', "show start of the largest free block, aligned", ""},
|
2022-06-13 21:16:20 +02:00
|
|
|
@@ -94,7 +94,8 @@ int GPTDataCL::DoOptions(int argc, char* argv[]) {
|
|
|
|
{"hybrid", 'h', POPT_ARG_STRING, &hybrids, 'h', "create hybrid MBR", "partnum[:partnum...][:EE]"},
|
|
|
|
{"info", 'i', POPT_ARG_INT, &infoPartNum, 'i', "show detailed information on partition", "partnum"},
|
|
|
|
{"align-end", 'I', POPT_ARG_NONE, NULL, 'I', "align partition end points", ""},
|
|
|
|
- {"move-main-table", 'j', POPT_ARG_INT, &mainTableLBA, 'j', "adjust the location of the main partition table", "sector"},
|
|
|
|
+ {"move-main-table", 'j', POPT_ARG_INT, &mainTableLBA, 'j', "change the start sector of the main partition table", "sector"},
|
2022-06-28 05:00:48 +02:00
|
|
|
+ {"move-backup-table", 'k', POPT_ARG_INT, &secondTableLBA, 'k', "change the start sector of the second/backup partition table", "sector"},
|
2022-06-13 21:16:20 +02:00
|
|
|
{"load-backup", 'l', POPT_ARG_STRING, &backupFile, 'l', "load GPT backup from file", "file"},
|
|
|
|
{"list-types", 'L', POPT_ARG_NONE, NULL, 'L', "list known partition types", ""},
|
|
|
|
{"gpttombr", 'm', POPT_ARG_STRING, &mbrParts, 'm', "convert GPT to MBR", "partnum[:partnum...]"},
|
|
|
|
@@ -117,6 +118,7 @@ int GPTDataCL::DoOptions(int argc, char* argv[]) {
|
|
|
|
{"zap", 'z', POPT_ARG_NONE, NULL, 'z', "zap (destroy) GPT (but not MBR) data structures", ""},
|
|
|
|
{"zap-all", 'Z', POPT_ARG_NONE, NULL, 'Z', "zap (destroy) GPT and MBR data structures", ""},
|
|
|
|
POPT_AUTOHELP { NULL, 0, 0, NULL, 0 }
|
|
|
|
+ // TODO: Incorrect(ly documented) (long) arguments are silently swallowed and seem to take the next argument with them!
|
|
|
|
};
|
|
|
|
|
|
|
|
// Create popt context...
|
|
|
|
@@ -280,13 +282,21 @@ int GPTDataCL::DoOptions(int argc, char* argv[]) {
|
|
|
|
alignEnd = true;
|
|
|
|
break;
|
|
|
|
case 'j':
|
|
|
|
- if (MoveMainTable(mainTableLBA)) {
|
|
|
|
- JustLooking(0);
|
|
|
|
- saveData = 1;
|
|
|
|
- } else {
|
|
|
|
- neverSaveData = 1;
|
|
|
|
- } // if/else
|
|
|
|
- break;
|
|
|
|
+ if (MoveMainTable(mainTableLBA)) {
|
|
|
|
+ JustLooking(0);
|
|
|
|
+ saveData = 1;
|
|
|
|
+ } else {
|
|
|
|
+ neverSaveData = 1;
|
|
|
|
+ } // if/else
|
|
|
|
+ break;
|
|
|
|
+ case 'k':
|
2022-06-28 05:00:48 +02:00
|
|
|
+ if (MoveSecondTable(secondTableLBA)) {
|
2022-06-13 21:16:20 +02:00
|
|
|
+ JustLooking(0);
|
|
|
|
+ saveData = 1;
|
|
|
|
+ } else {
|
|
|
|
+ neverSaveData = 1;
|
|
|
|
+ } // if/else
|
|
|
|
+ break;
|
|
|
|
case 'l':
|
|
|
|
LoadBackupFile(backupFile, saveData, neverSaveData);
|
|
|
|
free(backupFile);
|
|
|
|
diff --git a/sgdisk.8 b/sgdisk.8
|
|
|
|
index b966a13..dad877b 100644
|
|
|
|
--- a/sgdisk.8
|
|
|
|
+++ b/sgdisk.8
|
|
|
|
@@ -304,7 +304,7 @@ with the current final partition being aligned, and if \fBsgdisk\fR is asked
|
|
|
|
to create a partition in that space, then it will \fBnot\fR be end\-aligned.
|
|
|
|
|
|
|
|
.TP
|
|
|
|
-.B \-j, \-\-adjust\-main\-table=sector
|
|
|
|
+.B \-j, \-\-move\-main\-table=sector
|
|
|
|
Adjust the location of the main partition table. This value is normally 2,
|
|
|
|
but it may need to be increased in some cases, such as when a
|
|
|
|
system\-on\-chip (SoC) is hard\-coded to read boot code from sector 2. I
|
|
|
|
diff --git a/sgdisk.html b/sgdisk.html
|
|
|
|
index 36a28bc..ec0f505 100644
|
|
|
|
--- a/sgdisk.html
|
|
|
|
+++ b/sgdisk.html
|
|
|
|
@@ -195,7 +195,7 @@ when using this option. The others require a partition number. The
|
|
|
|
<I>nand</I>, <I>xor</I>, <I>=</I>, <I>set</I>, <I>clear</I>, and
|
|
|
|
<I>toggle</I> options enable you to change the attribute bit value. The
|
|
|
|
<I>set</I>, <I>clear</I>, <I>toggle</I>, and <I>get</I> options work on a
|
|
|
|
-bit number; the others work on a hexadecimal bit mask. For example, type
|
|
|
|
+bit number; the others work on a hexadecimal bit mask. For example, type
|
|
|
|
<B>sgdisk -A 4:set:2 /dev/sdc</B> to set the bit 2 attribute (legacy BIOS
|
|
|
|
bootable) on partition 4 on <I>/dev/sdc</I>.
|
|
|
|
<P>
|
|
|
|
@@ -344,7 +344,7 @@ if the free space at the end of a disk is less than the alignment value,
|
|
|
|
with the current final partition being aligned, and if <B>sgdisk</B> is asked
|
|
|
|
to create a partition in that space, then it will <B>not</B> be end-aligned.
|
|
|
|
<P>
|
|
|
|
-<DT><B>-j, --adjust-main-table=sector</B>
|
|
|
|
+<DT><B>-j, --move-main-table=sector</B>
|
|
|
|
|
|
|
|
<DD>
|
|
|
|
Adjust the location of the main partition table. This value is normally 2,
|