Added hybrid MBR and destroy-GPT options
This commit is contained in:
18
CHANGELOG
18
CHANGELOG
@@ -3,6 +3,19 @@
|
|||||||
|
|
||||||
- Changed __DARWIN_UNIX03 to __APPLE__ as code to enable MacOS X support.
|
- Changed __DARWIN_UNIX03 to __APPLE__ as code to enable MacOS X support.
|
||||||
|
|
||||||
|
- Added the ability to create a hybrid MBR ('h' on experts' menu). This was
|
||||||
|
motivated by my discovery that Windows 7 remains brain-dead when it comes
|
||||||
|
to the ability to boot from a GPT disk, at least on BIOS-based machines.
|
||||||
|
|
||||||
|
- Added 'z' option to experts' menu, to destroy GPT data structures and
|
||||||
|
exit. The intent is to use this feature to enable subsequent partitioning
|
||||||
|
of the disk using fdisk or other GPT-unaware tools. (GNU Parted will wipe
|
||||||
|
the GPT data structures itself when you create a new MBR ["msdos
|
||||||
|
disklabel," in Parted parlance], so using Parted is another option.)
|
||||||
|
|
||||||
|
- Slightly altered the effect of the 'o' command on the main menu. It now
|
||||||
|
blanks out the protective MBR, as well as the GPT data.
|
||||||
|
|
||||||
0.3.1:
|
0.3.1:
|
||||||
------
|
------
|
||||||
|
|
||||||
@@ -15,11 +28,6 @@
|
|||||||
work OK on my Mac OS test system and on both 32- and 64-bit Linux
|
work OK on my Mac OS test system and on both 32- and 64-bit Linux
|
||||||
systems.
|
systems.
|
||||||
|
|
||||||
- Added test for writability when opening a disk for reading. If the
|
|
||||||
test fails, a warning message is displayed. (The test simply opens
|
|
||||||
the disk for writing and then closes it before writing any data,
|
|
||||||
so the test shouldn't cause problems.)
|
|
||||||
|
|
||||||
- Fixed off-by-one bug in GPTData::FindLastAvailable().
|
- Fixed off-by-one bug in GPTData::FindLastAvailable().
|
||||||
|
|
||||||
- Fixed bug that caused display of options after a disk-write error.
|
- Fixed bug that caused display of options after a disk-write error.
|
||||||
|
|||||||
35
gdisk.8
35
gdisk.8
@@ -405,12 +405,14 @@ there will be no backup partition table on disk.
|
|||||||
Use main GPT header and rebuild the backup. This option is likely to be
|
Use main GPT header and rebuild the backup. This option is likely to be
|
||||||
useful if the backup GPT header has been damaged or destroyed.
|
useful if the backup GPT header has been damaged or destroyed.
|
||||||
.TP
|
.TP
|
||||||
|
|
||||||
.B e
|
.B e
|
||||||
Load main partition table. This option reloads the main partition table
|
Load main partition table. This option reloads the main partition table
|
||||||
from disk. It's only likely to be useful if you've tried to use the backup
|
from disk. It's only likely to be useful if you've tried to use the backup
|
||||||
partition table (via 'c') but it's in worse shape then the main partition
|
partition table (via 'c') but it's in worse shape then the main partition
|
||||||
table.
|
table.
|
||||||
.TP
|
.TP
|
||||||
|
|
||||||
.B f
|
.B f
|
||||||
Change partition GUID. You can enter a custom unique GUID for a partition
|
Change partition GUID. You can enter a custom unique GUID for a partition
|
||||||
using this option. (Note this refers to the GUID that uniquely identifies a
|
using this option. (Note this refers to the GUID that uniquely identifies a
|
||||||
@@ -424,6 +426,16 @@ Change disk GUID. Each disk has a unique GUID code, which
|
|||||||
.B gdisk
|
.B gdisk
|
||||||
assigns randomly upon creation of the GPT data structures. You can generate
|
assigns randomly upon creation of the GPT data structures. You can generate
|
||||||
a fresh random GUID or enter one manually with this option.
|
a fresh random GUID or enter one manually with this option.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B h
|
||||||
|
Create a hybrid MBR. This is an ugly workaround that enables GPT-unaware
|
||||||
|
OSes, or that that can't boot from a GPT disk, to access up to three of
|
||||||
|
the partitions on the disk by creating MBR entries for them. Note that
|
||||||
|
these hybrid MBR entries are not updated when you make subsequent changes
|
||||||
|
to the GPT entries, so you must re-run this option whenever you make
|
||||||
|
changes that would affect the hybridized partitions.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B i
|
.B i
|
||||||
Show detailed partition information. This option is identical to the 'i'
|
Show detailed partition information. This option is identical to the 'i'
|
||||||
@@ -480,6 +492,16 @@ Verify disk. This option is identical to the 'v' option in the main menu.
|
|||||||
.B w
|
.B w
|
||||||
Write table to disk and exit. This option is identical to the 'w' option in
|
Write table to disk and exit. This option is identical to the 'w' option in
|
||||||
the main menu.
|
the main menu.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B z
|
||||||
|
Destroy the GPT data structures and exit. Use this option if you want to
|
||||||
|
repartition a GPT disk using
|
||||||
|
.B "fdisk"
|
||||||
|
or some other GPT-unaware program.
|
||||||
|
You'll be given the choice of preserving the existing MBR, in case it's a
|
||||||
|
hybrid MBR with salvageable partitions.
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
|
|
||||||
In many cases, you can press the Enter key to select a default option when
|
In many cases, you can press the Enter key to select a default option when
|
||||||
@@ -488,7 +510,7 @@ entering data. When only one option is possible,
|
|||||||
usually bypasses the prompt entirely.
|
usually bypasses the prompt entirely.
|
||||||
|
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
As of August of 2009 (version 0.3.1),
|
As of August of 2009 (version 0.3.2),
|
||||||
.B gdisk
|
.B gdisk
|
||||||
should be considered early beta software. Known bugs and
|
should be considered early beta software. Known bugs and
|
||||||
limitations include:
|
limitations include:
|
||||||
@@ -506,12 +528,6 @@ The program compiles correctly only on Linux and Mac OS X. Both 64-bit
|
|||||||
more thoroughly than the latter. The Mac OS X support was added with
|
more thoroughly than the latter. The Mac OS X support was added with
|
||||||
version 0.3.1 and has not been thoroughly tested.
|
version 0.3.1 and has not been thoroughly tested.
|
||||||
|
|
||||||
.TP
|
|
||||||
.B *
|
|
||||||
Under Mac OS X, the program will only save a partition table if no
|
|
||||||
partitions from the disk are currently mounted. (This limitation does not
|
|
||||||
exist in the Linux version of the program.)
|
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B *
|
.B *
|
||||||
The fields used to display the start and end sector numbers for partitions
|
The fields used to display the start and end sector numbers for partitions
|
||||||
@@ -571,7 +587,10 @@ get appropriate GUID type codes at all.
|
|||||||
Booting after converting an MBR disk may be disrupted. Sometimes
|
Booting after converting an MBR disk may be disrupted. Sometimes
|
||||||
re-installing a boot loader will fix the problem, but other times you may
|
re-installing a boot loader will fix the problem, but other times you may
|
||||||
need to switch boot loaders. Except on EFI-based platforms, Windows through
|
need to switch boot loaders. Except on EFI-based platforms, Windows through
|
||||||
Vista doesn't support booting from GPT disks.
|
at least Windows 7 RC doesn't support booting from GPT disks. Creating a
|
||||||
|
hybrid MBR (using the 'h' option on the experts' menu) or abandoning GPT in
|
||||||
|
favor of MBR may be your only options in this case.
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
|
|
||||||
.SH AUTHORS
|
.SH AUTHORS
|
||||||
|
|||||||
17
gdisk.cc
17
gdisk.cc
@@ -24,7 +24,7 @@ int main(int argc, char* argv[]) {
|
|||||||
int doMore = 1;
|
int doMore = 1;
|
||||||
char* device = NULL;
|
char* device = NULL;
|
||||||
|
|
||||||
printf("GPT fdisk (gdisk) version 0.3.1\n\n");
|
printf("GPT fdisk (gdisk) version 0.3.2\n\n");
|
||||||
|
|
||||||
if (argc == 2) { // basic usage
|
if (argc == 2) { // basic usage
|
||||||
if (SizesOK()) {
|
if (SizesOK()) {
|
||||||
@@ -88,7 +88,7 @@ int DoCommand(char* filename, struct GPTData* theGPT) {
|
|||||||
break;
|
break;
|
||||||
case 'o': case 'O':
|
case 'o': case 'O':
|
||||||
theGPT->ClearGPTData();
|
theGPT->ClearGPTData();
|
||||||
// theGPT->protectiveMBR.MakeProtectiveMBR();
|
theGPT->MakeProtectiveMBR();
|
||||||
// theGPT->BlankPartitions();
|
// theGPT->BlankPartitions();
|
||||||
break;
|
break;
|
||||||
case 'p': case 'P':
|
case 'p': case 'P':
|
||||||
@@ -192,9 +192,9 @@ int ExpertsMenu(char* filename, struct GPTData* theGPT) {
|
|||||||
printf("Enter the disk's unique GUID:\n");
|
printf("Enter the disk's unique GUID:\n");
|
||||||
theGPT->SetDiskGUID(GetGUID());
|
theGPT->SetDiskGUID(GetGUID());
|
||||||
break;
|
break;
|
||||||
/* case 'h': case 'H':
|
case 'h': case 'H':
|
||||||
theGPT->MakeHybrid();
|
theGPT->MakeHybrid();
|
||||||
break; */
|
break;
|
||||||
case 'i': case 'I':
|
case 'i': case 'I':
|
||||||
theGPT->ShowDetails();
|
theGPT->ShowDetails();
|
||||||
break;
|
break;
|
||||||
@@ -238,6 +238,12 @@ int ExpertsMenu(char* filename, struct GPTData* theGPT) {
|
|||||||
goOn = 0;
|
goOn = 0;
|
||||||
} // if
|
} // if
|
||||||
break;
|
break;
|
||||||
|
case 'z': case 'Z':
|
||||||
|
if (theGPT->DestroyGPT() == 1) {
|
||||||
|
retval = 0;
|
||||||
|
goOn = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ShowExpertCommands();
|
ShowExpertCommands();
|
||||||
break;
|
break;
|
||||||
@@ -254,7 +260,7 @@ void ShowExpertCommands(void) {
|
|||||||
printf("e\tload main partition table from disk (rebuilding backup)\n");
|
printf("e\tload main partition table from disk (rebuilding backup)\n");
|
||||||
printf("f\tchange partition GUID\n");
|
printf("f\tchange partition GUID\n");
|
||||||
printf("g\tchange disk GUID\n");
|
printf("g\tchange disk GUID\n");
|
||||||
// printf("h\tmake hybrid MBR\n");
|
printf("h\tmake hybrid MBR\n");
|
||||||
printf("i\tshow detailed information on a partition\n");
|
printf("i\tshow detailed information on a partition\n");
|
||||||
printf("k\tsave partition data to a backup file\n");
|
printf("k\tsave partition data to a backup file\n");
|
||||||
printf("l\tload partition data from a backup file\n");
|
printf("l\tload partition data from a backup file\n");
|
||||||
@@ -267,4 +273,5 @@ void ShowExpertCommands(void) {
|
|||||||
printf("s\tresize partition table\n");
|
printf("s\tresize partition table\n");
|
||||||
printf("v\tverify disk\n");
|
printf("v\tverify disk\n");
|
||||||
printf("w\twrite table to disk and exit\n");
|
printf("w\twrite table to disk and exit\n");
|
||||||
|
printf("z\tDestroy GPT data structures and exit\n");
|
||||||
} // ShowExpertCommands()
|
} // ShowExpertCommands()
|
||||||
|
|||||||
107
gpt.cc
107
gpt.cc
@@ -1307,7 +1307,6 @@ uint64_t GPTData::FindFreeBlocks(int *numSegments, uint64_t *largestSegment) {
|
|||||||
return totalFound;
|
return totalFound;
|
||||||
} // GPTData::FindFreeBlocks()
|
} // GPTData::FindFreeBlocks()
|
||||||
|
|
||||||
/*
|
|
||||||
// Create a hybrid MBR -- an ugly, funky thing that helps GPT work with
|
// Create a hybrid MBR -- an ugly, funky thing that helps GPT work with
|
||||||
// OSes that don't understand GPT.
|
// OSes that don't understand GPT.
|
||||||
void GPTData::MakeHybrid(void) {
|
void GPTData::MakeHybrid(void) {
|
||||||
@@ -1315,16 +1314,26 @@ void GPTData::MakeHybrid(void) {
|
|||||||
char line[255];
|
char line[255];
|
||||||
int numParts, i, j, typeCode, bootable;
|
int numParts, i, j, typeCode, bootable;
|
||||||
uint64_t length;
|
uint64_t length;
|
||||||
|
char fillItUp = 'M'; // fill extra partition entries? (Yes/No/Maybe)
|
||||||
|
|
||||||
// First, rebuild the protective MBR...
|
printf("\nWARNING! Hybrid MBRs are flaky and potentially dangerous! If you decide not\n"
|
||||||
protectiveMBR.MakeProtectiveMBR();
|
"to use one, just hit the Enter key at the below prompt and your MBR\n"
|
||||||
|
"partition table will be untouched.\n\n\a");
|
||||||
|
|
||||||
// Now get the numbers of up to three partitions to add to the
|
// Now get the numbers of up to three partitions to add to the
|
||||||
// hybrid MBR....
|
// hybrid MBR....
|
||||||
printf("Type from one to three partition numbers to be added to the hybrid MBR, in\n"
|
printf("Type from one to three GPT partition numbers, separated by spaces, to be\n"
|
||||||
"sequence: ");
|
"added to the hybrid MBR, in sequence: ");
|
||||||
fgets(line, 255, stdin);
|
fgets(line, 255, stdin);
|
||||||
numParts = sscanf(line, "%d %d %d", &partNums[0], &partNums[1], &partNums[2]);
|
numParts = sscanf(line, "%d %d %d", &partNums[0], &partNums[1], &partNums[2]);
|
||||||
|
|
||||||
|
if (numParts > 0) {
|
||||||
|
// Blank out the protective MBR, but leave the boot loader code
|
||||||
|
// alone....
|
||||||
|
protectiveMBR.EmptyMBR(0);
|
||||||
|
protectiveMBR.SetDiskSize(diskSize);
|
||||||
|
} // if
|
||||||
|
|
||||||
for (i = 0; i < numParts; i++) {
|
for (i = 0; i < numParts; i++) {
|
||||||
j = partNums[i] - 1;
|
j = partNums[i] - 1;
|
||||||
printf("Creating entry for partition #%d\n", j + 1);
|
printf("Creating entry for partition #%d\n", j + 1);
|
||||||
@@ -1337,7 +1346,7 @@ void GPTData::MakeHybrid(void) {
|
|||||||
printf("Set the bootable flag? ");
|
printf("Set the bootable flag? ");
|
||||||
bootable = (GetYN() == 'Y');
|
bootable = (GetYN() == 'Y');
|
||||||
length = partitions[j].lastLBA - partitions[j].firstLBA + UINT64_C(1);
|
length = partitions[j].lastLBA - partitions[j].firstLBA + UINT64_C(1);
|
||||||
protectiveMBR.MakePart(i + 1, (uint32_t) partitions[j].firstLBA,
|
protectiveMBR.MakePart(i, (uint32_t) partitions[j].firstLBA,
|
||||||
(uint32_t) length, typeCode, bootable);
|
(uint32_t) length, typeCode, bootable);
|
||||||
} else { // partition out of range
|
} else { // partition out of range
|
||||||
printf("Partition %d ends beyond the 2TiB limit of MBR partitions; omitting it.\n",
|
printf("Partition %d ends beyond the 2TiB limit of MBR partitions; omitting it.\n",
|
||||||
@@ -1347,8 +1356,46 @@ void GPTData::MakeHybrid(void) {
|
|||||||
printf("Partition %d is out of range; omitting it.\n", j + 1);
|
printf("Partition %d is out of range; omitting it.\n", j + 1);
|
||||||
} // if/else
|
} // if/else
|
||||||
} // for
|
} // for
|
||||||
|
|
||||||
|
if (numParts > 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. Note that this is
|
||||||
|
// NUMBERED AFTER the hybrid partitions, contrary to what the
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// ... and for good measure, if there are any partition spaces left,
|
||||||
|
// optionally create more protective EFI partitions to cover as much
|
||||||
|
// space as possible....
|
||||||
|
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? ");
|
||||||
|
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): ");
|
||||||
|
// Comment on above: Mac OS treats disks with more than one
|
||||||
|
// 0xEE MBR partition as MBR disks, not as GPT disks.
|
||||||
|
fgets(line, 255, stdin);
|
||||||
|
sscanf(line, "%x", &typeCode);
|
||||||
|
} // if (typeCode == 0x00)
|
||||||
|
protectiveMBR.MakeBiggestPart(i, typeCode); // make a partition
|
||||||
|
} // if (fillItUp == 'Y')
|
||||||
|
} // if unused entry
|
||||||
|
} // for (i = 0; i < 4; i++)
|
||||||
|
} // if (numParts > 0)
|
||||||
} // GPTData::MakeHybrid()
|
} // GPTData::MakeHybrid()
|
||||||
*/
|
|
||||||
|
// Create a fresh protective MBR.
|
||||||
|
void GPTData::MakeProtectiveMBR(void) {
|
||||||
|
protectiveMBR.MakeProtectiveMBR();
|
||||||
|
} // GPTData::MakeProtectiveMBR(void)
|
||||||
|
|
||||||
// Writes GPT (and protective MBR) to disk. Returns 1 on successful
|
// Writes GPT (and protective MBR) to disk. Returns 1 on successful
|
||||||
// write, 0 if there was a problem.
|
// write, 0 if there was a problem.
|
||||||
@@ -1609,6 +1656,52 @@ int GPTData::LoadGPTBackup(char* filename) {
|
|||||||
return allOK;
|
return allOK;
|
||||||
} // GPTData::LoadGPTBackup()
|
} // GPTData::LoadGPTBackup()
|
||||||
|
|
||||||
|
// This function destroys the on-disk GPT structures. Returns 1 if the
|
||||||
|
// user confirms destruction, 0 if the user aborts.
|
||||||
|
int GPTData::DestroyGPT(void) {
|
||||||
|
int fd, i, doMore;
|
||||||
|
char blankSector[512], goOn;
|
||||||
|
|
||||||
|
for (i = 0; i < 512; i++) {
|
||||||
|
blankSector[i] = '\0';
|
||||||
|
} // for
|
||||||
|
|
||||||
|
printf("\a\aAbout to wipe out GPT on %s. Proceed? ", device);
|
||||||
|
goOn = GetYN();
|
||||||
|
if (goOn == 'Y') {
|
||||||
|
fd = open(device, O_WRONLY);
|
||||||
|
#ifdef __APPLE__
|
||||||
|
// MacOS X requires a shared lock under some circumstances....
|
||||||
|
if (fd < 0) {
|
||||||
|
fd = open(device, O_WRONLY|O_SHLOCK);
|
||||||
|
} // if
|
||||||
|
#endif
|
||||||
|
if (fd != -1) {
|
||||||
|
lseek64(fd, mainHeader.currentLBA * 512, SEEK_SET); // seek to GPT header
|
||||||
|
write(fd, blankSector, 512); // blank it out
|
||||||
|
lseek64(fd, mainHeader.partitionEntriesLBA * 512, SEEK_SET); // seek to partition table
|
||||||
|
for (i = 0; i < GetBlocksInPartTable(); i++)
|
||||||
|
write(fd, blankSector, 512);
|
||||||
|
lseek64(fd, secondHeader.partitionEntriesLBA * 512, SEEK_SET); // seek to partition table
|
||||||
|
for (i = 0; i < GetBlocksInPartTable(); i++)
|
||||||
|
write(fd, blankSector, 512);
|
||||||
|
lseek64(fd, secondHeader.currentLBA * 512, SEEK_SET); // seek to GPT header
|
||||||
|
write(fd, blankSector, 512); // blank it out
|
||||||
|
printf("Blank out MBR? ");
|
||||||
|
if (GetYN() == 'Y') {
|
||||||
|
lseek64(fd, 0, SEEK_SET);
|
||||||
|
write(fd, blankSector, 512); // blank it out
|
||||||
|
} // if blank MBR
|
||||||
|
close(fd);
|
||||||
|
printf("GPT data structures destroyed! You may now partition the disk using fdisk or\n"
|
||||||
|
"other utilities. Program will now terminate.\n");
|
||||||
|
} else {
|
||||||
|
printf("Problem opening %s for writing! Program will now terminate.\n");
|
||||||
|
} // if/else (fd != -1)
|
||||||
|
} // if (goOn == 'Y')
|
||||||
|
return (goOn == 'Y');
|
||||||
|
} // GPTData::DestroyGPT()
|
||||||
|
|
||||||
// Check to be sure that data type sizes are correct. The basic types (uint*_t) should
|
// Check to be sure that data type sizes are correct. The basic types (uint*_t) should
|
||||||
// never fail these tests, but the struct types may fail depending on compile options.
|
// never fail these tests, but the struct types may fail depending on compile options.
|
||||||
// Specifically, the -fpack-struct option to gcc may be required to ensure proper structure
|
// Specifically, the -fpack-struct option to gcc may be required to ensure proper structure
|
||||||
|
|||||||
5
gpt.h
5
gpt.h
@@ -126,11 +126,12 @@ public:
|
|||||||
void RebuildSecondHeader(void);
|
void RebuildSecondHeader(void);
|
||||||
void LoadSecondTableAsMain(void);
|
void LoadSecondTableAsMain(void);
|
||||||
uint64_t FindFreeBlocks(int *numSegments, uint64_t *largestSegment);
|
uint64_t FindFreeBlocks(int *numSegments, uint64_t *largestSegment);
|
||||||
// void MakeHybrid(void);
|
void MakeHybrid(void);
|
||||||
void MakeProtectiveMBR(void) {return protectiveMBR.MakeProtectiveMBR();}
|
void MakeProtectiveMBR(void);
|
||||||
int SaveGPTData(void);
|
int SaveGPTData(void);
|
||||||
int SaveGPTBackup(char* filename);
|
int SaveGPTBackup(char* filename);
|
||||||
int LoadGPTBackup(char* filename);
|
int LoadGPTBackup(char* filename);
|
||||||
|
int DestroyGPT(void); // Returns 1 if user proceeds
|
||||||
|
|
||||||
// Return data about the GPT structures....
|
// Return data about the GPT structures....
|
||||||
uint32_t GetNumParts(void) {return mainHeader.numParts;}
|
uint32_t GetNumParts(void) {return mainHeader.numParts;}
|
||||||
|
|||||||
92
mbr.cc
92
mbr.cc
@@ -52,14 +52,22 @@ MBRData::MBRData(char *filename) {
|
|||||||
MBRData::~MBRData(void) {
|
MBRData::~MBRData(void) {
|
||||||
} // MBRData destructor
|
} // MBRData destructor
|
||||||
|
|
||||||
// Empty all data. Meant mainly for calling by constructors
|
// Empty all data. Meant mainly for calling by constructors, but it's also
|
||||||
void MBRData::EmptyMBR(void) {
|
// used by the hybrid MBR functions in the GPTData class.
|
||||||
|
void MBRData::EmptyMBR(int clearBootloader) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
// Zero out the boot loader section, the disk signature, and the
|
||||||
|
// 2-byte nulls area only if requested to do so. (This is the
|
||||||
|
// default.)
|
||||||
|
if (clearBootloader == 1) {
|
||||||
for (i = 0; i < 440; i++)
|
for (i = 0; i < 440; i++)
|
||||||
code[i] = 0;
|
code[i] = 0;
|
||||||
diskSignature = (uint32_t) rand();
|
diskSignature = (uint32_t) rand();
|
||||||
nulls = 0;
|
nulls = 0;
|
||||||
|
} // if
|
||||||
|
|
||||||
|
// Blank out the partitions
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
partitions[i].status = UINT8_C(0);
|
partitions[i].status = UINT8_C(0);
|
||||||
partitions[i].firstSector[0] = UINT8_C(0);
|
partitions[i].firstSector[0] = UINT8_C(0);
|
||||||
@@ -343,6 +351,39 @@ void MBRData::MakeProtectiveMBR(void) {
|
|||||||
state = gpt;
|
state = gpt;
|
||||||
} // MBRData::MakeProtectiveMBR()
|
} // MBRData::MakeProtectiveMBR()
|
||||||
|
|
||||||
|
// Create a partition that fills the most available space. Returns
|
||||||
|
// 1 if partition was created, 0 otherwise. Intended for use in
|
||||||
|
// creating hybrid MBRs.
|
||||||
|
int MBRData::MakeBiggestPart(int i, int type) {
|
||||||
|
uint32_t start = UINT32_C(1); // starting point for each search
|
||||||
|
uint32_t firstBlock; // first block in a segment
|
||||||
|
uint32_t lastBlock; // last block in a segment
|
||||||
|
uint32_t segmentSize; // size of segment in blocks
|
||||||
|
uint32_t selectedSegment = UINT32_C(0); // location of largest segment
|
||||||
|
uint32_t selectedSize = UINT32_C(0); // size of largest segment in blocks
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
firstBlock = FindFirstAvailable(start);
|
||||||
|
if (firstBlock != UINT32_C(0)) { // something's free...
|
||||||
|
lastBlock = FindLastInFree(firstBlock);
|
||||||
|
segmentSize = lastBlock - firstBlock + UINT32_C(1);
|
||||||
|
if (segmentSize > selectedSize) {
|
||||||
|
selectedSize = segmentSize;
|
||||||
|
selectedSegment = firstBlock;
|
||||||
|
} // if
|
||||||
|
start = lastBlock + 1;
|
||||||
|
} // if
|
||||||
|
} while (firstBlock != 0);
|
||||||
|
if ((selectedSize > UINT32_C(0)) && ((uint64_t) selectedSize < diskSize)) {
|
||||||
|
found = 1;
|
||||||
|
MakePart(i, selectedSegment, selectedSize, type, 0);
|
||||||
|
} else {
|
||||||
|
found = 0;
|
||||||
|
} // if/else
|
||||||
|
return found;
|
||||||
|
} // MBRData::MakeBiggestPart(int i)
|
||||||
|
|
||||||
// Return a pointer to a primary or logical partition, or NULL if
|
// Return a pointer to a primary or logical partition, or NULL if
|
||||||
// the partition is out of range....
|
// the partition is out of range....
|
||||||
struct MBRRecord* MBRData::GetPartition(int i) {
|
struct MBRRecord* MBRData::GetPartition(int i) {
|
||||||
@@ -398,6 +439,53 @@ void MBRData::MakePart(int num, uint32_t start, uint32_t length, int type,
|
|||||||
partitions[num].lengthLBA = length;
|
partitions[num].lengthLBA = length;
|
||||||
} // MakePart()
|
} // MakePart()
|
||||||
|
|
||||||
|
// Finds the first free space on the disk from start onward; returns 0
|
||||||
|
// if none available....
|
||||||
|
uint32_t MBRData::FindFirstAvailable(uint32_t start) {
|
||||||
|
uint32_t first;
|
||||||
|
uint32_t i;
|
||||||
|
int firstMoved = 0;
|
||||||
|
|
||||||
|
first = start;
|
||||||
|
|
||||||
|
// ...now search through all partitions; if first is within an
|
||||||
|
// existing partition, move it to the next sector after that
|
||||||
|
// partition and repeat. If first was moved, set firstMoved
|
||||||
|
// flag; repeat until firstMoved is not set, so as to catch
|
||||||
|
// cases where partitions are out of sequential order....
|
||||||
|
do {
|
||||||
|
firstMoved = 0;
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
// Check if it's in the existing partition
|
||||||
|
if ((first >= partitions[i].firstLBA) &&
|
||||||
|
(first < (partitions[i].firstLBA + partitions[i].lengthLBA))) {
|
||||||
|
first = partitions[i].firstLBA + partitions[i].lengthLBA;
|
||||||
|
firstMoved = 1;
|
||||||
|
} // if
|
||||||
|
} // for
|
||||||
|
} while (firstMoved == 1);
|
||||||
|
if (first >= diskSize)
|
||||||
|
first = 0;
|
||||||
|
return (first);
|
||||||
|
} // MBRData::FindFirstAvailable()
|
||||||
|
|
||||||
|
uint32_t MBRData::FindLastInFree(uint32_t start) {
|
||||||
|
uint32_t nearestStart;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
if (diskSize <= UINT32_MAX)
|
||||||
|
nearestStart = diskSize - 1;
|
||||||
|
else
|
||||||
|
nearestStart = UINT32_MAX - 1;
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
if ((nearestStart > partitions[i].firstLBA) &&
|
||||||
|
(partitions[i].firstLBA > start)) {
|
||||||
|
nearestStart = partitions[i].firstLBA - 1;
|
||||||
|
} // if
|
||||||
|
} // for
|
||||||
|
return (nearestStart);
|
||||||
|
} // MBRData::FindLastInFree
|
||||||
|
|
||||||
uint8_t MBRData::GetStatus(int i) {
|
uint8_t MBRData::GetStatus(int i) {
|
||||||
MBRRecord* thePart;
|
MBRRecord* thePart;
|
||||||
uint8_t retval;
|
uint8_t retval;
|
||||||
|
|||||||
9
mbr.h
9
mbr.h
@@ -71,7 +71,9 @@ public:
|
|||||||
MBRData(void);
|
MBRData(void);
|
||||||
MBRData(char* deviceFilename);
|
MBRData(char* deviceFilename);
|
||||||
~MBRData(void);
|
~MBRData(void);
|
||||||
void EmptyMBR(void);
|
// Pass EmptyMBR 1 to clear the boot loader code, 0 to leave it intact
|
||||||
|
void EmptyMBR(int clearBootloader = 1);
|
||||||
|
void SetDiskSize(uint64_t ds) {diskSize = ds;}
|
||||||
int ReadMBRData(char* deviceFilename);
|
int ReadMBRData(char* deviceFilename);
|
||||||
void ReadMBRData(int fd);
|
void ReadMBRData(int fd);
|
||||||
int WriteMBRData(void);
|
int WriteMBRData(void);
|
||||||
@@ -84,6 +86,11 @@ public:
|
|||||||
void ShowState(void);
|
void ShowState(void);
|
||||||
void MakePart(int num, uint32_t startLBA, uint32_t lengthLBA, int type = 0x07,
|
void MakePart(int num, uint32_t startLBA, uint32_t lengthLBA, int type = 0x07,
|
||||||
int bootable = 0);
|
int bootable = 0);
|
||||||
|
int MakeBiggestPart(int i, int type); // Make partition filling most space
|
||||||
|
|
||||||
|
// Functions to find information on free space....
|
||||||
|
uint32_t FindFirstAvailable(uint32_t start = 1);
|
||||||
|
uint32_t FindLastInFree(uint32_t start);
|
||||||
|
|
||||||
// Functions to extract data on specific partitions....
|
// Functions to extract data on specific partitions....
|
||||||
uint8_t GetStatus(int i);
|
uint8_t GetStatus(int i);
|
||||||
|
|||||||
Reference in New Issue
Block a user