nixos-installer/patches/gptfdisk-move-secondary-table.patch

321 lines
14 KiB
Diff
Raw Normal View History

diff --git a/gpt.cc b/gpt.cc
index 76cd9ad..d61064f 100644
--- 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
+int GPTData::MoveSecondTable(uint64_t pteSector) {
+ 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;
+} // GPTData::MoveSecondTable()
+
// 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
index 5d19372..17b3380 100644
--- 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);
+ 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);
@@ -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
index 34c9421..232285a 100644
--- 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;
@@ -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", ""},
@@ -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"},
+ {"move-backup-table", 'k', POPT_ARG_INT, &secondTableLBA, 'k', "change the start sector of the second/backup partition table", "sector"},
{"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':
+ if (MoveSecondTable(secondTableLBA)) {
+ JustLooking(0);
+ saveData = 1;
+ } else {
+ neverSaveData = 1;
+ } // if/else
+ break;
case 'l':
LoadBackupFile(backupFile, saveData, neverSaveData);
free(backupFile);
diff --git a/gpttext.cc b/gpttext.cc
index 170a169..43be9e5 100644
--- a/gpttext.cc
+++ b/gpttext.cc
@@ -197,6 +197,24 @@ void GPTDataTextUI::MoveMainTable(void) {
} // if
} // GPTDataTextUI::MoveMainTable()
+// Move the backup partition table.
+void GPTDataTextUI::MoveSecondTable(void) {
+ uint64_t newStart, pteSize = GetTableSizeInSectors();
+ uint64_t minValue = FindLastUsedLBA();
+ uint64_t maxValue = diskSize - 1 - pteSize;
+ ostringstream prompt;
+
+ cout << "Currently, backup partition table begins at sector " << secondHeader.partitionEntriesLBA
+ << " and ends at sector " << secondHeader.partitionEntriesLBA + pteSize - 1 << "\n";
+ prompt << "Enter new starting location (" << minValue << " to " << maxValue << "; default is " << minValue << "; 1 to abort): ";
+ newStart = GetNumber(1, maxValue, minValue, prompt.str());
+ if (newStart != 1) {
+ GPTData::MoveSecondTable(newStart);
+ } else {
+ cout << "Aborting change!\n";
+ } // if
+} // GPTDataTextUI::MoveSecondTable()
+
// Interactively create a partition
void GPTDataTextUI::CreatePartition(void) {
uint64_t firstBlock, firstInLargest, lastBlock, sector, origSector, lastAligned;
@@ -698,7 +716,7 @@ void GPTDataTextUI::ShowCommands(void) {
void GPTDataTextUI::RecoveryMenu(string filename) {
uint32_t numParts;
int goOn = 1, temp1;
-
+
do {
cout << "\nRecovery/transformation command (? for help): ";
switch (ReadString()[0]) {
@@ -824,7 +842,7 @@ void GPTDataTextUI::ExpertsMenu(string filename) {
string guidStr, device;
GUIDData aGUID;
ostringstream prompt;
-
+
do {
cout << "\nExpert command (? for help): ";
switch (ReadString()[0]) {
@@ -873,6 +891,9 @@ void GPTDataTextUI::ExpertsMenu(string filename) {
case 'j': case 'J':
MoveMainTable();
break;
+ case 'k': case 'K':
+ MoveSecondTable();
+ break;
case 'l': case 'L':
prompt.seekp(0);
prompt << "Enter the sector alignment value (1-" << MAX_ALIGNMENT << ", default = "
@@ -946,6 +967,7 @@ void GPTDataTextUI::ShowExpertCommands(void) {
cout << "h\trecompute CHS values in protective/hybrid MBR\n";
cout << "i\tshow detailed information on a partition\n";
cout << "j\tmove the main partition table\n";
+ cout << "k\tmove the backup partition table\n";
cout << "l\tset the sector alignment value\n";
cout << "m\treturn to main menu\n";
cout << "n\tcreate a new protective MBR\n";
@@ -1007,4 +1029,4 @@ UnicodeString ReadUString(void) {
return ReadString().c_str();
} // ReadUString()
#endif
-
+
diff --git a/gpttext.h b/gpttext.h
index 32e2f88..8ed6274 100644
--- a/gpttext.h
+++ b/gpttext.h
@@ -41,6 +41,7 @@ class GPTDataTextUI : public GPTData {
uint32_t GetPartNum(void);
void ResizePartitionTable(void);
void MoveMainTable(void);
+ void MoveSecondTable(void);
void CreatePartition(void);
void DeletePartition(void);
void ChangePartType(void);
diff --git a/sgdisk.8 b/sgdisk.8
index b966a13..6f8b375 100644
--- a/sgdisk.8
+++ b/sgdisk.8
@@ -304,13 +304,23 @@ 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
-Adjust the location of the main partition table. This value is normally 2,
+.B \-j, \-\-move\-main\-table=sector
+Sets the start sector 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
recommend against adjusting this value unless doing so is absolutely
necessary.
+.TP
+.B \-k, \-\-move\-backup\-table=sector
+Sets the start sector of the second/backup partition table. The backup table
+is usually placed just before the last sector, which holds the backup header.
+The default value is thus the size of the disk, minus one, minus the total
+size of the partition table (in sectors, usually 32).
+There are probably very few reasons to ever change this, and while the EFI
+standard does not mandate it, most tooling assumes the backup table to be at
+the very end of the disk.
+
.TP
.B \-l, \-\-load\-backup=file
Load partition data from a backup file. This option is the reverse of the
diff --git a/sgdisk.html b/sgdisk.html
index 36a28bc..98c20be 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,15 +344,26 @@ 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,
+Sets the start sector 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
recommend against adjusting this value unless doing so is absolutely
necessary.
<P>
+<DT><B>-k, --move-backup-table=sector</B>
+
+<DD>
+Sets the start sector of the second/backup partition table. The backup table
+is usually placed just before the last sector, which holds the backup header.
+The default value is thus the size of the disk, minus one, minus the total
+size of the partition table (in sectors, usually 32).
+There are probably very few reasons to ever change this, and while the EFI
+standard does not mandate it, most tooling assumes the backup table to be at
+the very end of the disk.
+<P>
<DT><B>-l, --load-backup=file</B>
<DD>