nixos-installer/patches/gptfdisk-move-secondary-table.patch
Niklas Gollenstede b51cf19f4a make partitioning reproducible, add sgdisk patch,
do partitioning during build instead of install,
fix qemu's efi vars,
add config.wip.dropbear.hostKeys
2022-06-13 21:16:20 +02:00

192 lines
8.5 KiB
Diff

diff --git a/gpt.cc b/gpt.cc
index 76cd9ad..375c216 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::MoveSecondaryTable(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::MoveSecondaryTable()
+
// 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..c272d65 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 MoveSecondaryTable(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..f6517e4 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;
@@ -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-secondary-table", 'k', POPT_ARG_INT, &secondTableLBA, 'k', "change the start sector of the secondary 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 (MoveSecondaryTable(secondTableLBA)) {
+ 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,