diff options
-rw-r--r-- | NEWS | 16 | ||||
-rw-r--r-- | gptcl.cc | 5 | ||||
-rw-r--r-- | gptpart.cc | 12 | ||||
-rw-r--r-- | gptpart.h | 5 | ||||
-rw-r--r-- | gpttext.cc | 43 | ||||
-rw-r--r-- | gpttext.h | 3 | ||||
-rw-r--r-- | support.h | 2 |
7 files changed, 68 insertions, 18 deletions
@@ -9,12 +9,16 @@ hybridized partition when creating a hybrid MBR. - Fixed bug that caused gdisk and sgdisk to create hybridized partitions - that ended above the 2^32 sector point with incorrect end values. The - program now refuses to create such hybridized partitions at all. (A case - could be made for allowing creation of such partitions so long as the - start sector is below 2^32 and the size is under 2^32, but as a practical - matter, many OSes flake out with such partitions, so I'm erring on the - side of caution on this one.) + that ended at or above the 2^32 sector point with incorrect end values. + The behavior now varies between gdisk and sgdisk: gdisk now creates + hybrid partitions that begin below 2^32 sectors and that are smaller than + 2^32 sectors, since this is technically legal; but gdisk displays a + warning, because some OSes (such as DOS, Windows XP, OS/2, and BeOS) + misbehave with such partitions. AFAIK, only Linux, FreeBSD, and Windows 7 + work properly with such partitions. Because of this fact and because + sgdisk is a more automated tool, it's stricter in how it handles things: + It refuses to create a hybrid partition if the original ends at or above + the 2^32 sector mark. 0.8.9 (2/17/2014): ------------------ @@ -474,7 +474,7 @@ int GPTDataCL::BuildMBR(char* argument, int isHybrid) { newMBR.SetDisk(GetDisk()); for (i = 0; i < numParts; i++) { origPartNum = GetInt(argument, i + 1) - 1; - if (IsUsedPartNum(origPartNum) && partitions[origPartNum].IsSizedForMBR()) { + if (IsUsedPartNum(origPartNum) && (partitions[origPartNum].IsSizedForMBR() == MBR_SIZED_GOOD)) { newPart.SetInclusion(PRIMARY); newPart.SetLocation(operator[](origPartNum).GetFirstLBA(), operator[](origPartNum).GetLengthLBA()); @@ -493,7 +493,8 @@ int GPTDataCL::BuildMBR(char* argument, int isHybrid) { newPart.SetType(0xEE); newMBR.AddPart(0, newPart); } // if - SetProtectiveMBR(newMBR); + if (allOK) + SetProtectiveMBR(newMBR); } else allOK = 0; } else allOK = 0; if (!allOK) @@ -138,9 +138,17 @@ int GPTPart::IsUsed(void) { return (partitionType != GUIDData("0x00")); } // GPTPart::IsUsed() -// Returns 1 if the partition's end point is under (2^32 - 1) sectors, 0 if it's over that value. +// Returns MBR_SIZED_GOOD, MBR_SIZED_IFFY, or MBR_SIZED_BAD; see comments +// in header file for details. int GPTPart::IsSizedForMBR(void) { - return (lastLBA < UINT32_MAX); + int retval = MBR_SIZED_GOOD; + + if ((firstLBA > UINT32_MAX) || ((lastLBA - firstLBA) > UINT32_MAX) || (firstLBA > lastLBA)) + retval = MBR_SIZED_BAD; + else if (lastLBA > UINT32_MAX) + retval = MBR_SIZED_IFFY; + + return (retval); } // GPTPart::IsSizedForMBR() // Set the type code to the specified one. Also changes the partition @@ -25,6 +25,11 @@ using namespace std; +// Values returned by GPTPart::IsSizedForMBR() +#define MBR_SIZED_GOOD 0 /* Whole partition under 2^32 sectors */ +#define MBR_SIZED_IFFY 1 /* Partition starts under 2^32 & is less than 2^32, but ends over 2^32 */ +#define MBR_SIZED_BAD 2 /* Partition starts over 2^32, is bigger than 2^32, or otherwise bad */ + /**************************************** * * * GPTPart class and related structures * @@ -394,9 +394,9 @@ void GPTDataTextUI::ShowDetails(void) { // Create a hybrid MBR -- an ugly, funky thing that helps GPT work with // OSes that don't understand GPT. void GPTDataTextUI::MakeHybrid(void) { - uint32_t partNums[3]; + uint32_t partNums[3] = {0, 0, 0}; string line; - int numPartsToCvt = 0, i, j, mbrNum = 0; + int numPartsToCvt = 0, numConverted = 0, i, j, mbrNum = 0; unsigned int hexCode = 0; MBRPart hybridPart; MBRData hybridMBR; @@ -418,7 +418,9 @@ void GPTDataTextUI::MakeHybrid(void) { line = ReadString(); istringstream inLine(line); do { - inLine >> partNums[numPartsToCvt++]; + inLine >> partNums[numPartsToCvt]; + if (partNums[numPartsToCvt] > 0) + numPartsToCvt++; } while (!inLine.eof() && (numPartsToCvt < 3)); if (numPartsToCvt > 0) { @@ -428,7 +430,7 @@ void GPTDataTextUI::MakeHybrid(void) { for (i = 0; i < numPartsToCvt; i++) { j = partNums[i] - 1; - if (partitions[j].IsUsed() && partitions[j].IsSizedForMBR()) { + if (partitions[j].IsUsed() && (partitions[j].IsSizedForMBR() != MBR_SIZED_BAD)) { mbrNum = i + (eeFirst == 'Y'); cout << "\nCreating entry for GPT partition #" << j + 1 << " (MBR partition #" << mbrNum + 1 << ")\n"; @@ -441,13 +443,16 @@ void GPTDataTextUI::MakeHybrid(void) { else hybridPart.SetStatus(0x00); hybridPart.SetInclusion(PRIMARY); + if (partitions[j].IsSizedForMBR() == MBR_SIZED_IFFY) + WarnAboutIffyMBRPart(j + 1); + numConverted++; } else { cerr << "\nGPT partition #" << j + 1 << " does not exist or is too big; skipping.\n"; } // if/else hybridMBR.AddPart(mbrNum, hybridPart); } // for - if (numPartsToCvt > 0) { // User opted to create a hybrid MBR.... + if (numConverted > 0) { // User opted to create a hybrid MBR.... // Create EFI protective partition that covers the start of the disk. // If this location (covering the main GPT data structures) is omitted, // Linux won't find any partitions on the disk. @@ -459,7 +464,7 @@ void GPTDataTextUI::MakeHybrid(void) { if (eeFirst == 'Y') { hybridMBR.AddPart(0, hybridPart); } else { - hybridMBR.AddPart(numPartsToCvt, hybridPart); + hybridMBR.AddPart(numConverted, hybridPart); } // else hybridMBR.SetHybrid(); @@ -477,7 +482,9 @@ void GPTDataTextUI::MakeHybrid(void) { } // if (GetYN() == 'Y') } // if unused entry protectiveMBR = hybridMBR; - } // if (numPartsToCvt > 0) + } else { + cout << "\nNo partitions converted; original protective/hybrid MBR is unmodified!\n"; + } // if/else (numConverted > 0) } // GPTDataTextUI::MakeHybrid() // Convert the GPT to MBR form, storing partitions in the protectiveMBR @@ -494,6 +501,10 @@ int GPTDataTextUI::XFormToMBR(void) { protectiveMBR.EmptyMBR(0); for (i = 0; i < numParts; i++) { if (partitions[i].IsUsed()) { + if (partitions[i].IsSizedForMBR() == MBR_SIZED_IFFY) + WarnAboutIffyMBRPart(i + 1); + // Note: MakePart() checks for oversized partitions, so don't + // bother checking other IsSizedForMBR() return values.... protectiveMBR.MakePart(i, partitions[i].GetFirstLBA(), partitions[i].GetLengthLBA(), partitions[i].GetHexType() / 0x0100, 0); @@ -503,6 +514,24 @@ int GPTDataTextUI::XFormToMBR(void) { return protectiveMBR.DoMenu(); } // GPTDataTextUI::XFormToMBR() +/****************************************************** + * * + * Display informational messages for the user.... * + * * + ******************************************************/ + +// Although an MBR partition that begins below sector 2^32 and is less than 2^32 sectors in +// length is technically legal even if it ends above the 2^32-sector mark, such a partition +// tends to confuse a lot of OSes, so warn the user about such partitions. This function is +// called by XFormToMBR() and MakeHybrid(); it's a separate function just to consolidate the +// lengthy message in one place. +void GPTDataTextUI::WarnAboutIffyMBRPart(int partNum) { + cout << "\a\nWarning! GPT partition " << partNum << " ends after the 2^32 sector mark! The partition\n" + << "begins before this point, and is smaller than 2^32 sectors. This is technically\n" + << "legal, but will confuse some OSes. The partition IS being added to the MBR, but\n" + << "if your OS misbehaves or can't see the partition, the partition may simply be\n" + << "unusable in that OS and may need to be resized or omitted from the MBR.\n\n"; +} // GPTDataTextUI::WarnAboutIffyMBRPart() /********************************************************************* * * @@ -54,6 +54,9 @@ class GPTDataTextUI : public GPTData { void MakeHybrid(void); int XFormToMBR(void); // convert GPT to MBR, wiping GPT afterwards. Returns 1 if successful + // An informational function.... + void WarnAboutIffyMBRPart(int partNum); + // Main menu functions void MainMenu(string filename); void ShowCommands(void); @@ -8,7 +8,7 @@ #ifndef __GPTSUPPORT #define __GPTSUPPORT -#define GPTFDISK_VERSION "0.8.9.1" +#define GPTFDISK_VERSION "0.8.9.2" #if defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__) // Darwin (Mac OS) & FreeBSD: disk IOCTLs are different, and there is no lseek64 |