forked from extern/nixos-installer
321 lines
14 KiB
Diff
321 lines
14 KiB
Diff
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>
|