diff --git a/CHANGELOG b/CHANGELOG index 10458d72644923051b24a0b6b950181d1c78963d..53d3c5cddd213ddbfb80d75565bf47d31afa8c44 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,30 @@ +0.3.4: +------ + +- Fixed bug that enabled (possibly accidental) entry of MBR type codes of + 0x00 in GPTData::MakeHybrid(). The fix also enables entry of default + type code by pressing the Enter key when prompted. Applied a similar + fix to the entry of the type code for the second protective partition, + if one is used. + +- Fixed a typo: "sectors" was spelled "sectprs" in one spot! + +- Fixed bug that caused default entry for end sector to be refused if an + initial value using a plus sign (e.g., "+20G") was also refused. + +0.3.3: +------ + +- Gave users control over the way MBR partitions are assigned to slots in a + hybrid MBR setup; the original method (putting the 0xEE partition after + the real partitions) works well for non-boot disks, but both GRUB and + GRUB2 become confused by this type of setup, so it needs changing. + +- Changed "blocks" to "sectors" in GPT and MBR table displays. + +- Added "Boot" column to MBR table display; shows an asterisk (*) when the + partition's status is bootable. + 0.3.2: ------ diff --git a/gdisk.8 b/gdisk.8 index 274a2c950e7275c5d528b2075b134c49c97b4d85..22be0122fa4ace76bc3615adc29411eb9bff092c 100644 --- a/gdisk.8 +++ b/gdisk.8 @@ -510,7 +510,7 @@ entering data. When only one option is possible, usually bypasses the prompt entirely. .SH BUGS -As of August of 2009 (version 0.3.2), +As of August of 2009 (version 0.3.3), .B gdisk should be considered early beta software. Known bugs and limitations include: diff --git a/gdisk.cc b/gdisk.cc index 44f82a85c4f19f0cae34a7b2ed5ec3547f51f0f3..80520615c840618db7ee5cb6fc9a3efaaa8a4ab4 100644 --- a/gdisk.cc +++ b/gdisk.cc @@ -24,7 +24,7 @@ int main(int argc, char* argv[]) { int doMore = 1; char* device = NULL; - printf("GPT fdisk (gdisk) version 0.3.2\n\n"); + printf("GPT fdisk (gdisk) version 0.3.4\n\n"); if (argc == 2) { // basic usage if (SizesOK()) { diff --git a/gpt.cc b/gpt.cc index b2349dba84abca90b44bac607aa3d413590eda7e..4fdc5fc4964a7fea9c43db4004f08dd5c4565bac 100644 --- a/gpt.cc +++ b/gpt.cc @@ -209,8 +209,11 @@ int GPTData::LoadPartitions(char* deviceFilename) { CheckGPTSize(); } else { allOK = 0; - fprintf(stderr, "Problem opening %s for reading!\n", - deviceFilename); + fprintf(stderr, "Problem opening %s for reading! Error is %d\n", + deviceFilename, errno); + if (errno == EACCES) { // User is probably not running as root + fprintf(stderr, "You must run this program as root or use sudo!\n"); + } // if } // if/else return (allOK); } // GPTData::LoadPartitions() @@ -466,14 +469,14 @@ void GPTData::DisplayGPTData(void) { totalFree = FindFreeBlocks(&i, &temp); printf("Total free space is %llu sectors (%s)\n", totalFree, BytesToSI(totalFree * (uint64_t) blockSize, sizeInSI)); - printf("\nNumber Start (block) End (block) Size Code Name\n"); + printf("\nNumber Start (sector) End (sector) Size Code Name\n"); for (i = 0; i < mainHeader.numParts; i++) { if (partitions[i].firstLBA != 0) { BytesToSI(blockSize * (partitions[i].lastLBA - partitions[i].firstLBA + 1), sizeInSI); - printf("%4d %14lu %14lu ", i + 1, (unsigned long) partitions[i].firstLBA, + printf("%4d %14lu %14lu", i + 1, (unsigned long) partitions[i].firstLBA, (unsigned long) partitions[i].lastLBA); - printf(" %-10s %04X ", sizeInSI, + printf(" %-10s %04X ", sizeInSI, typeHelper.GUIDToID(partitions[i].partitionType)); j = 0; while ((partitions[i].name[j] != '\0') && (j < 44)) { @@ -517,7 +520,7 @@ void GPTData::ShowPartDetails(uint32_t partNum) { partitions[partNum].lastLBA, BytesToSI(partitions[partNum].lastLBA * blockSize, temp)); size = (partitions[partNum].lastLBA - partitions[partNum].firstLBA + 1); - printf("Partition size: %llu sectprs (%s)\n", (unsigned long long) + printf("Partition size: %llu sectors (%s)\n", (unsigned long long) size, BytesToSI(size * ((uint64_t) blockSize), temp)); printf("Attribute flags: %016llx\n", (unsigned long long) partitions[partNum].attributes); @@ -1312,9 +1315,10 @@ uint64_t GPTData::FindFreeBlocks(int *numSegments, uint64_t *largestSegment) { void GPTData::MakeHybrid(void) { uint32_t partNums[3]; char line[255]; - int numParts, i, j, typeCode, bootable; + int numParts, i, j, typeCode, bootable, mbrNum; uint64_t length; char fillItUp = 'M'; // fill extra partition entries? (Yes/No/Maybe) + char eeFirst; // Whether EFI GPT (0xEE) partition comes first in table printf("\nWARNING! Hybrid MBRs are flaky and potentially dangerous! If you decide not\n" "to use one, just hit the Enter key at the below prompt and your MBR\n" @@ -1332,21 +1336,31 @@ void GPTData::MakeHybrid(void) { // alone.... protectiveMBR.EmptyMBR(0); protectiveMBR.SetDiskSize(diskSize); + printf("Place EFI GPT (0xEE) partition first in MBR (good for GRUB)? "); + eeFirst = GetYN(); } // if for (i = 0; i < numParts; i++) { j = partNums[i] - 1; - printf("Creating entry for partition #%d\n", j + 1); + printf("\nCreating entry for partition #%d\n", j + 1); if ((j >= 0) && (j < mainHeader.numParts)) { if (partitions[j].lastLBA < UINT32_MAX) { - printf("Enter an MBR hex code (suggested %02X): ", - typeHelper.GUIDToID(partitions[j].partitionType) / 256); - fgets(line, 255, stdin); - sscanf(line, "%x", &typeCode); + do { + printf("Enter an MBR hex code (default %02X): ", + typeHelper.GUIDToID(partitions[j].partitionType) / 256); + fgets(line, 255, stdin); + sscanf(line, "%x", &typeCode); + if (line[0] == '\n') + typeCode = typeHelper.GUIDToID(partitions[j].partitionType) / 256; + } while ((typeCode <= 0) || (typeCode > 255)); printf("Set the bootable flag? "); bootable = (GetYN() == 'Y'); length = partitions[j].lastLBA - partitions[j].firstLBA + UINT64_C(1); - protectiveMBR.MakePart(i, (uint32_t) partitions[j].firstLBA, + if (eeFirst == 'Y') + mbrNum = i + 1; + else + mbrNum = i; + protectiveMBR.MakePart(mbrNum, (uint32_t) partitions[j].firstLBA, (uint32_t) length, typeCode, bootable); } else { // partition out of range printf("Partition %d ends beyond the 2TiB limit of MBR partitions; omitting it.\n", @@ -1365,7 +1379,11 @@ void GPTData::MakeHybrid(void) { // gptsync utility does. This is because Windows seems to choke on // disks with a 0xEE partition in the first slot and subsequent // additional partitions, unless it boots from the disk. - protectiveMBR.MakePart(numParts, 1, protectiveMBR.FindLastInFree(1), 0xEE); + if (eeFirst == 'Y') + mbrNum = 0; + else + mbrNum = numParts; + protectiveMBR.MakePart(mbrNum, 1, protectiveMBR.FindLastInFree(1), 0xEE); // ... and for good measure, if there are any partition spaces left, // optionally create more protective EFI partitions to cover as much @@ -1373,18 +1391,20 @@ void GPTData::MakeHybrid(void) { for (i = 0; i < 4; i++) { if (protectiveMBR.GetType(i) == 0x00) { // unused entry.... if (fillItUp == 'M') { - printf("Unused partition space(s) found. Use one to protect more partitions? "); + printf("\nUnused partition space(s) found. Use one to protect more partitions? "); fillItUp = GetYN(); typeCode = 0x00; // use this to flag a need to get type code } // if if (fillItUp == 'Y') { - if (typeCode == 0x00) { - printf("Enter an MBR hex code (EE is EFI GPT, but may confuse MacOS): "); + while ((typeCode <= 0) || (typeCode > 255)) { + printf("Enter an MBR hex code (EE is EFI GPT, but may confuse MacOS): "); // Comment on above: Mac OS treats disks with more than one - // 0xEE MBR partition as MBR disks, not as GPT disks. + // 0xEE MBR partition as MBR disks, not as GPT disks. fgets(line, 255, stdin); sscanf(line, "%x", &typeCode); - } // if (typeCode == 0x00) + if (line[0] == '\n') + typeCode = 0; + } // while protectiveMBR.MakeBiggestPart(i, typeCode); // make a partition } // if (fillItUp == 'Y') } // if unused entry diff --git a/mbr.cc b/mbr.cc index 4909ebc8eef661f045b2df598c816497c69e8937..e09d6b649ef5b0706910a2da4c84cc293d328958 100644 --- a/mbr.cc +++ b/mbr.cc @@ -265,13 +265,19 @@ int MBRData::ReadLogicalPart(int fd, uint32_t extendedStart, void MBRData::DisplayMBRData(void) { int i; char tempStr[255]; + char bootCode; printf("MBR disk identifier: 0x%08X\n", (unsigned int) diskSignature); printf("MBR partitions:\n"); - printf("Number\t Start (block)\t Length (blocks)\tType\n"); + printf("Number\t Boot\t Start (sector)\t Length (sectors)\tType\n"); for (i = 0; i < 4; i++) { if (partitions[i].lengthLBA != 0) { - printf("%4d\t%13lu\t%15lu \t0x%02X\n", i + 1, (unsigned long) partitions[i].firstLBA, + if (partitions[i].status && 0x80) // it's bootable + bootCode = '*'; + else + bootCode = ' '; + printf("%4d\t %c\t%13lu\t%15lu \t0x%02X\n", i + 1, bootCode, + (unsigned long) partitions[i].firstLBA, (unsigned long) partitions[i].lengthLBA, partitions[i].partitionType); } // if } // for diff --git a/support.cc b/support.cc index d3a6357f248e495de25fb3010b4b5207d7721707..8ee5f33480575b3cb08f17a38739b8446f3f8df2 100644 --- a/support.cc +++ b/support.cc @@ -96,6 +96,7 @@ uint64_t GetLastSector(uint64_t low, uint64_t high, char prompt[]) { if (num <= 0) { response = (unsigned long long) high; suffix = ' '; + plusFlag = 0; } // if // Set multiplier based on suffix @@ -124,7 +125,7 @@ uint64_t GetLastSector(uint64_t low, uint64_t high, char prompt[]) { response *= (unsigned long long) mult; if (plusFlag == 1) { response = response + (unsigned long long) low - 1; - } // if/else + } // if } // while return ((uint64_t) response); } // GetLastSector()