summaryrefslogtreecommitdiff
path: root/mbr.cc
diff options
context:
space:
mode:
authorsrs5694 <srs5694@users.sourceforge.net>2009-08-20 21:35:25 -0400
committersrs5694 <srs5694@users.sourceforge.net>2009-08-20 21:35:25 -0400
commitc0ca8f877e775a54008b27d92deefdb41bfaea5d (patch)
tree99efc1510662b612904f10733ba89ab4aafb0a9e /mbr.cc
parent7f244babbe6c792379fa8d812701637e1541e8b7 (diff)
downloadsgdisk-c0ca8f877e775a54008b27d92deefdb41bfaea5d.tar.gz
Added hybrid MBR and destroy-GPT options
Diffstat (limited to 'mbr.cc')
-rw-r--r--mbr.cc100
1 files changed, 94 insertions, 6 deletions
diff --git a/mbr.cc b/mbr.cc
index e692adc..4909ebc 100644
--- a/mbr.cc
+++ b/mbr.cc
@@ -52,14 +52,22 @@ MBRData::MBRData(char *filename) {
MBRData::~MBRData(void) {
} // MBRData destructor
-// Empty all data. Meant mainly for calling by constructors
-void MBRData::EmptyMBR(void) {
+// Empty all data. Meant mainly for calling by constructors, but it's also
+// used by the hybrid MBR functions in the GPTData class.
+void MBRData::EmptyMBR(int clearBootloader) {
int i;
- for (i = 0; i < 440; i++)
- code[i] = 0;
- diskSignature = (uint32_t) rand();
- nulls = 0;
+ // 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++)
+ code[i] = 0;
+ diskSignature = (uint32_t) rand();
+ nulls = 0;
+ } // if
+
+ // Blank out the partitions
for (i = 0; i < 4; i++) {
partitions[i].status = UINT8_C(0);
partitions[i].firstSector[0] = UINT8_C(0);
@@ -343,6 +351,39 @@ void MBRData::MakeProtectiveMBR(void) {
state = gpt;
} // 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
// the partition is out of range....
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;
} // 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) {
MBRRecord* thePart;
uint8_t retval;