1cf200d32Sopenharmony_ci/* basicmbr.cc -- Functions for loading, saving, and manipulating legacy MBR partition 2cf200d32Sopenharmony_ci data. */ 3cf200d32Sopenharmony_ci 4cf200d32Sopenharmony_ci/* Initial coding by Rod Smith, January to February, 2009 */ 5cf200d32Sopenharmony_ci 6cf200d32Sopenharmony_ci/* This program is copyright (c) 2009-2013 by Roderick W. Smith. It is distributed 7cf200d32Sopenharmony_ci under the terms of the GNU GPL version 2, as detailed in the COPYING file. */ 8cf200d32Sopenharmony_ci 9cf200d32Sopenharmony_ci#define __STDC_LIMIT_MACROS 10cf200d32Sopenharmony_ci#ifndef __STDC_CONSTANT_MACROS 11cf200d32Sopenharmony_ci#define __STDC_CONSTANT_MACROS 12cf200d32Sopenharmony_ci#endif 13cf200d32Sopenharmony_ci 14cf200d32Sopenharmony_ci#include <stdio.h> 15cf200d32Sopenharmony_ci#include <stdlib.h> 16cf200d32Sopenharmony_ci#include <stdint.h> 17cf200d32Sopenharmony_ci#include <fcntl.h> 18cf200d32Sopenharmony_ci#include <string.h> 19cf200d32Sopenharmony_ci#include <time.h> 20cf200d32Sopenharmony_ci#include <sys/stat.h> 21cf200d32Sopenharmony_ci#include <errno.h> 22cf200d32Sopenharmony_ci#include <iostream> 23cf200d32Sopenharmony_ci#include <algorithm> 24cf200d32Sopenharmony_ci#include "mbr.h" 25cf200d32Sopenharmony_ci#include "support.h" 26cf200d32Sopenharmony_ci 27cf200d32Sopenharmony_ciusing namespace std; 28cf200d32Sopenharmony_ci 29cf200d32Sopenharmony_ci/**************************************** 30cf200d32Sopenharmony_ci * * 31cf200d32Sopenharmony_ci * MBRData class and related structures * 32cf200d32Sopenharmony_ci * * 33cf200d32Sopenharmony_ci ****************************************/ 34cf200d32Sopenharmony_ci 35cf200d32Sopenharmony_ciBasicMBRData::BasicMBRData(void) { 36cf200d32Sopenharmony_ci blockSize = SECTOR_SIZE; 37cf200d32Sopenharmony_ci diskSize = 0; 38cf200d32Sopenharmony_ci device = ""; 39cf200d32Sopenharmony_ci state = invalid; 40cf200d32Sopenharmony_ci numHeads = MAX_HEADS; 41cf200d32Sopenharmony_ci numSecspTrack = MAX_SECSPERTRACK; 42cf200d32Sopenharmony_ci myDisk = NULL; 43cf200d32Sopenharmony_ci canDeleteMyDisk = 0; 44cf200d32Sopenharmony_ci// memset(&EbrLocations, 0, MAX_MBR_PARTS * sizeof(uint32_t)); 45cf200d32Sopenharmony_ci EmptyMBR(); 46cf200d32Sopenharmony_ci} // BasicMBRData default constructor 47cf200d32Sopenharmony_ci 48cf200d32Sopenharmony_ciBasicMBRData::BasicMBRData(const BasicMBRData & orig) { 49cf200d32Sopenharmony_ci int i; 50cf200d32Sopenharmony_ci 51cf200d32Sopenharmony_ci if (&orig != this) { 52cf200d32Sopenharmony_ci memcpy(code, orig.code, 440); 53cf200d32Sopenharmony_ci diskSignature = orig.diskSignature; 54cf200d32Sopenharmony_ci nulls = orig.nulls; 55cf200d32Sopenharmony_ci MBRSignature = orig.MBRSignature; 56cf200d32Sopenharmony_ci blockSize = orig.blockSize; 57cf200d32Sopenharmony_ci diskSize = orig.diskSize; 58cf200d32Sopenharmony_ci numHeads = orig.numHeads; 59cf200d32Sopenharmony_ci numSecspTrack = orig.numSecspTrack; 60cf200d32Sopenharmony_ci canDeleteMyDisk = orig.canDeleteMyDisk; 61cf200d32Sopenharmony_ci device = orig.device; 62cf200d32Sopenharmony_ci state = orig.state; 63cf200d32Sopenharmony_ci 64cf200d32Sopenharmony_ci myDisk = new DiskIO; 65cf200d32Sopenharmony_ci if (myDisk == NULL) { 66cf200d32Sopenharmony_ci cerr << "Unable to allocate memory in BasicMBRData copy constructor! Terminating!\n"; 67cf200d32Sopenharmony_ci exit(1); 68cf200d32Sopenharmony_ci } // if 69cf200d32Sopenharmony_ci if (orig.myDisk != NULL) 70cf200d32Sopenharmony_ci myDisk->OpenForRead(orig.myDisk->GetName()); 71cf200d32Sopenharmony_ci 72cf200d32Sopenharmony_ci for (i = 0; i < MAX_MBR_PARTS; i++) { 73cf200d32Sopenharmony_ci partitions[i] = orig.partitions[i]; 74cf200d32Sopenharmony_ci } // for 75cf200d32Sopenharmony_ci } // if 76cf200d32Sopenharmony_ci} // BasicMBRData copy constructor 77cf200d32Sopenharmony_ci 78cf200d32Sopenharmony_ciBasicMBRData::BasicMBRData(string filename) { 79cf200d32Sopenharmony_ci blockSize = SECTOR_SIZE; 80cf200d32Sopenharmony_ci diskSize = 0; 81cf200d32Sopenharmony_ci device = filename; 82cf200d32Sopenharmony_ci state = invalid; 83cf200d32Sopenharmony_ci numHeads = MAX_HEADS; 84cf200d32Sopenharmony_ci numSecspTrack = MAX_SECSPERTRACK; 85cf200d32Sopenharmony_ci myDisk = NULL; 86cf200d32Sopenharmony_ci canDeleteMyDisk = 0; 87cf200d32Sopenharmony_ci// memset(&EbrLocations, 0, MAX_MBR_PARTS * sizeof(uint32_t)); 88cf200d32Sopenharmony_ci 89cf200d32Sopenharmony_ci // Try to read the specified partition table, but if it fails.... 90cf200d32Sopenharmony_ci if (!ReadMBRData(filename)) { 91cf200d32Sopenharmony_ci EmptyMBR(); 92cf200d32Sopenharmony_ci device = ""; 93cf200d32Sopenharmony_ci } // if 94cf200d32Sopenharmony_ci} // BasicMBRData(string filename) constructor 95cf200d32Sopenharmony_ci 96cf200d32Sopenharmony_ci// Free space used by myDisk only if that's OK -- sometimes it will be 97cf200d32Sopenharmony_ci// copied from an outside source, in which case that source should handle 98cf200d32Sopenharmony_ci// it! 99cf200d32Sopenharmony_ciBasicMBRData::~BasicMBRData(void) { 100cf200d32Sopenharmony_ci if (canDeleteMyDisk) 101cf200d32Sopenharmony_ci delete myDisk; 102cf200d32Sopenharmony_ci} // BasicMBRData destructor 103cf200d32Sopenharmony_ci 104cf200d32Sopenharmony_ci// Assignment operator -- copy entire set of MBR data. 105cf200d32Sopenharmony_ciBasicMBRData & BasicMBRData::operator=(const BasicMBRData & orig) { 106cf200d32Sopenharmony_ci int i; 107cf200d32Sopenharmony_ci 108cf200d32Sopenharmony_ci if (&orig != this) { 109cf200d32Sopenharmony_ci memcpy(code, orig.code, 440); 110cf200d32Sopenharmony_ci diskSignature = orig.diskSignature; 111cf200d32Sopenharmony_ci nulls = orig.nulls; 112cf200d32Sopenharmony_ci MBRSignature = orig.MBRSignature; 113cf200d32Sopenharmony_ci blockSize = orig.blockSize; 114cf200d32Sopenharmony_ci diskSize = orig.diskSize; 115cf200d32Sopenharmony_ci numHeads = orig.numHeads; 116cf200d32Sopenharmony_ci numSecspTrack = orig.numSecspTrack; 117cf200d32Sopenharmony_ci canDeleteMyDisk = orig.canDeleteMyDisk; 118cf200d32Sopenharmony_ci device = orig.device; 119cf200d32Sopenharmony_ci state = orig.state; 120cf200d32Sopenharmony_ci 121cf200d32Sopenharmony_ci myDisk = new DiskIO; 122cf200d32Sopenharmony_ci if (myDisk == NULL) { 123cf200d32Sopenharmony_ci cerr << "Unable to allocate memory in BasicMBRData::operator=()! Terminating!\n"; 124cf200d32Sopenharmony_ci exit(1); 125cf200d32Sopenharmony_ci } // if 126cf200d32Sopenharmony_ci if (orig.myDisk != NULL) 127cf200d32Sopenharmony_ci myDisk->OpenForRead(orig.myDisk->GetName()); 128cf200d32Sopenharmony_ci 129cf200d32Sopenharmony_ci for (i = 0; i < MAX_MBR_PARTS; i++) { 130cf200d32Sopenharmony_ci partitions[i] = orig.partitions[i]; 131cf200d32Sopenharmony_ci } // for 132cf200d32Sopenharmony_ci } // if 133cf200d32Sopenharmony_ci return *this; 134cf200d32Sopenharmony_ci} // BasicMBRData::operator=() 135cf200d32Sopenharmony_ci 136cf200d32Sopenharmony_ci/********************** 137cf200d32Sopenharmony_ci * * 138cf200d32Sopenharmony_ci * Disk I/O functions * 139cf200d32Sopenharmony_ci * * 140cf200d32Sopenharmony_ci **********************/ 141cf200d32Sopenharmony_ci 142cf200d32Sopenharmony_ci// Read data from MBR. Returns 1 if read was successful (even if the 143cf200d32Sopenharmony_ci// data isn't a valid MBR), 0 if the read failed. 144cf200d32Sopenharmony_ciint BasicMBRData::ReadMBRData(const string & deviceFilename) { 145cf200d32Sopenharmony_ci int allOK; 146cf200d32Sopenharmony_ci 147cf200d32Sopenharmony_ci if (myDisk == NULL) { 148cf200d32Sopenharmony_ci myDisk = new DiskIO; 149cf200d32Sopenharmony_ci if (myDisk == NULL) { 150cf200d32Sopenharmony_ci cerr << "Unable to allocate memory in BasicMBRData::ReadMBRData()! Terminating!\n"; 151cf200d32Sopenharmony_ci exit(1); 152cf200d32Sopenharmony_ci } // if 153cf200d32Sopenharmony_ci canDeleteMyDisk = 1; 154cf200d32Sopenharmony_ci } // if 155cf200d32Sopenharmony_ci if (myDisk->OpenForRead(deviceFilename)) { 156cf200d32Sopenharmony_ci allOK = ReadMBRData(myDisk); 157cf200d32Sopenharmony_ci } else { 158cf200d32Sopenharmony_ci allOK = 0; 159cf200d32Sopenharmony_ci } // if 160cf200d32Sopenharmony_ci 161cf200d32Sopenharmony_ci if (allOK) 162cf200d32Sopenharmony_ci device = deviceFilename; 163cf200d32Sopenharmony_ci 164cf200d32Sopenharmony_ci return allOK; 165cf200d32Sopenharmony_ci} // BasicMBRData::ReadMBRData(const string & deviceFilename) 166cf200d32Sopenharmony_ci 167cf200d32Sopenharmony_ci// Read data from MBR. If checkBlockSize == 1 (the default), the block 168cf200d32Sopenharmony_ci// size is checked; otherwise it's set to the default (512 bytes). 169cf200d32Sopenharmony_ci// Note that any extended partition(s) present will be omitted from 170cf200d32Sopenharmony_ci// in the partitions[] array; these partitions must be re-created when 171cf200d32Sopenharmony_ci// the partition table is saved in MBR format. 172cf200d32Sopenharmony_ciint BasicMBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) { 173cf200d32Sopenharmony_ci int allOK = 1, i, logicalNum = 3; 174cf200d32Sopenharmony_ci int err = 1; 175cf200d32Sopenharmony_ci TempMBR tempMBR; 176cf200d32Sopenharmony_ci 177cf200d32Sopenharmony_ci if ((myDisk != NULL) && (myDisk != theDisk) && (canDeleteMyDisk)) { 178cf200d32Sopenharmony_ci delete myDisk; 179cf200d32Sopenharmony_ci canDeleteMyDisk = 0; 180cf200d32Sopenharmony_ci } // if 181cf200d32Sopenharmony_ci 182cf200d32Sopenharmony_ci myDisk = theDisk; 183cf200d32Sopenharmony_ci 184cf200d32Sopenharmony_ci // Empty existing MBR data, including the logical partitions... 185cf200d32Sopenharmony_ci EmptyMBR(0); 186cf200d32Sopenharmony_ci 187cf200d32Sopenharmony_ci if (myDisk->Seek(0)) 188cf200d32Sopenharmony_ci if (myDisk->Read(&tempMBR, 512)) 189cf200d32Sopenharmony_ci err = 0; 190cf200d32Sopenharmony_ci if (err) { 191cf200d32Sopenharmony_ci cerr << "Problem reading disk in BasicMBRData::ReadMBRData()!\n"; 192cf200d32Sopenharmony_ci } else { 193cf200d32Sopenharmony_ci for (i = 0; i < 440; i++) 194cf200d32Sopenharmony_ci code[i] = tempMBR.code[i]; 195cf200d32Sopenharmony_ci diskSignature = tempMBR.diskSignature; 196cf200d32Sopenharmony_ci nulls = tempMBR.nulls; 197cf200d32Sopenharmony_ci for (i = 0; i < 4; i++) { 198cf200d32Sopenharmony_ci partitions[i] = tempMBR.partitions[i]; 199cf200d32Sopenharmony_ci if (partitions[i].GetLengthLBA() > 0) 200cf200d32Sopenharmony_ci partitions[i].SetInclusion(PRIMARY); 201cf200d32Sopenharmony_ci } // for i... (reading all four partitions) 202cf200d32Sopenharmony_ci MBRSignature = tempMBR.MBRSignature; 203cf200d32Sopenharmony_ci ReadCHSGeom(); 204cf200d32Sopenharmony_ci 205cf200d32Sopenharmony_ci // Reverse the byte order, if necessary 206cf200d32Sopenharmony_ci if (IsLittleEndian() == 0) { 207cf200d32Sopenharmony_ci ReverseBytes(&diskSignature, 4); 208cf200d32Sopenharmony_ci ReverseBytes(&nulls, 2); 209cf200d32Sopenharmony_ci ReverseBytes(&MBRSignature, 2); 210cf200d32Sopenharmony_ci for (i = 0; i < 4; i++) { 211cf200d32Sopenharmony_ci partitions[i].ReverseByteOrder(); 212cf200d32Sopenharmony_ci } // for 213cf200d32Sopenharmony_ci } // if 214cf200d32Sopenharmony_ci 215cf200d32Sopenharmony_ci if (MBRSignature != MBR_SIGNATURE) { 216cf200d32Sopenharmony_ci allOK = 0; 217cf200d32Sopenharmony_ci state = invalid; 218cf200d32Sopenharmony_ci } // if 219cf200d32Sopenharmony_ci 220cf200d32Sopenharmony_ci // Find disk size 221cf200d32Sopenharmony_ci diskSize = myDisk->DiskSize(&err); 222cf200d32Sopenharmony_ci 223cf200d32Sopenharmony_ci // Find block size 224cf200d32Sopenharmony_ci if (checkBlockSize) { 225cf200d32Sopenharmony_ci blockSize = myDisk->GetBlockSize(); 226cf200d32Sopenharmony_ci } // if (checkBlockSize) 227cf200d32Sopenharmony_ci 228cf200d32Sopenharmony_ci // Load logical partition data, if any is found.... 229cf200d32Sopenharmony_ci if (allOK) { 230cf200d32Sopenharmony_ci for (i = 0; i < 4; i++) { 231cf200d32Sopenharmony_ci if ((partitions[i].GetType() == 0x05) || (partitions[i].GetType() == 0x0f) 232cf200d32Sopenharmony_ci || (partitions[i].GetType() == 0x85)) { 233cf200d32Sopenharmony_ci // Found it, so call a function to load everything from them.... 234cf200d32Sopenharmony_ci logicalNum = ReadLogicalParts(partitions[i].GetStartLBA(), abs(logicalNum) + 1); 235cf200d32Sopenharmony_ci if (logicalNum < 0) { 236cf200d32Sopenharmony_ci cerr << "Error reading logical partitions! List may be truncated!\n"; 237cf200d32Sopenharmony_ci } // if maxLogicals valid 238cf200d32Sopenharmony_ci DeletePartition(i); 239cf200d32Sopenharmony_ci } // if primary partition is extended 240cf200d32Sopenharmony_ci } // for primary partition loop 241cf200d32Sopenharmony_ci if (allOK) { // Loaded logicals OK 242cf200d32Sopenharmony_ci state = mbr; 243cf200d32Sopenharmony_ci } else { 244cf200d32Sopenharmony_ci state = invalid; 245cf200d32Sopenharmony_ci } // if 246cf200d32Sopenharmony_ci } // if 247cf200d32Sopenharmony_ci 248cf200d32Sopenharmony_ci // Check to see if it's in GPT format.... 249cf200d32Sopenharmony_ci if (allOK) { 250cf200d32Sopenharmony_ci for (i = 0; i < 4; i++) { 251cf200d32Sopenharmony_ci if (partitions[i].GetType() == UINT8_C(0xEE)) { 252cf200d32Sopenharmony_ci state = gpt; 253cf200d32Sopenharmony_ci } // if 254cf200d32Sopenharmony_ci } // for 255cf200d32Sopenharmony_ci } // if 256cf200d32Sopenharmony_ci 257cf200d32Sopenharmony_ci // If there's an EFI GPT partition, look for other partition types, 258cf200d32Sopenharmony_ci // to flag as hybrid 259cf200d32Sopenharmony_ci if (state == gpt) { 260cf200d32Sopenharmony_ci for (i = 0 ; i < 4; i++) { 261cf200d32Sopenharmony_ci if ((partitions[i].GetType() != UINT8_C(0xEE)) && 262cf200d32Sopenharmony_ci (partitions[i].GetType() != UINT8_C(0x00))) 263cf200d32Sopenharmony_ci state = hybrid; 264cf200d32Sopenharmony_ci if (logicalNum != 3) 265cf200d32Sopenharmony_ci cerr << "Warning! MBR Logical partitions found on a hybrid MBR disk! This is an\n" 266cf200d32Sopenharmony_ci << "EXTREMELY dangerous configuration!\n\a"; 267cf200d32Sopenharmony_ci } // for 268cf200d32Sopenharmony_ci } // if (hybrid detection code) 269cf200d32Sopenharmony_ci } // no initial error 270cf200d32Sopenharmony_ci return allOK; 271cf200d32Sopenharmony_ci} // BasicMBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) 272cf200d32Sopenharmony_ci 273cf200d32Sopenharmony_ci// This is a function to read all the logical partitions, following the 274cf200d32Sopenharmony_ci// logical partition linked list from the disk and storing the basic data in the 275cf200d32Sopenharmony_ci// partitions[] array. Returns last index to partitions[] used, or -1 times the 276cf200d32Sopenharmony_ci// that index if there was a problem. (Some problems can leave valid logical 277cf200d32Sopenharmony_ci// partition data.) 278cf200d32Sopenharmony_ci// Parameters: 279cf200d32Sopenharmony_ci// extendedStart = LBA of the start of the extended partition 280cf200d32Sopenharmony_ci// partNum = number of first partition in extended partition (normally 4). 281cf200d32Sopenharmony_ciint BasicMBRData::ReadLogicalParts(uint64_t extendedStart, int partNum) { 282cf200d32Sopenharmony_ci struct TempMBR ebr; 283cf200d32Sopenharmony_ci int i, another = 1, allOK = 1; 284cf200d32Sopenharmony_ci uint8_t ebrType; 285cf200d32Sopenharmony_ci uint64_t offset; 286cf200d32Sopenharmony_ci uint64_t EbrLocations[MAX_MBR_PARTS]; 287cf200d32Sopenharmony_ci 288cf200d32Sopenharmony_ci offset = extendedStart; 289cf200d32Sopenharmony_ci memset(&EbrLocations, 0, MAX_MBR_PARTS * sizeof(uint64_t)); 290cf200d32Sopenharmony_ci while (another && (partNum < MAX_MBR_PARTS) && (partNum >= 0) && (allOK > 0)) { 291cf200d32Sopenharmony_ci for (i = 0; i < MAX_MBR_PARTS; i++) { 292cf200d32Sopenharmony_ci if (EbrLocations[i] == offset) { // already read this one; infinite logical partition loop! 293cf200d32Sopenharmony_ci cerr << "Logical partition infinite loop detected! This is being corrected.\n"; 294cf200d32Sopenharmony_ci allOK = -1; 295cf200d32Sopenharmony_ci if (partNum > 0) //don't go negative 296cf200d32Sopenharmony_ci partNum -= 1; 297cf200d32Sopenharmony_ci } // if 298cf200d32Sopenharmony_ci } // for 299cf200d32Sopenharmony_ci EbrLocations[partNum] = offset; 300cf200d32Sopenharmony_ci if (myDisk->Seek(offset) == 0) { // seek to EBR record 301cf200d32Sopenharmony_ci cerr << "Unable to seek to " << offset << "! Aborting!\n"; 302cf200d32Sopenharmony_ci allOK = -1; 303cf200d32Sopenharmony_ci } 304cf200d32Sopenharmony_ci if (myDisk->Read(&ebr, 512) != 512) { // Load the data.... 305cf200d32Sopenharmony_ci cerr << "Error seeking to or reading logical partition data from " << offset 306cf200d32Sopenharmony_ci << "!\nSome logical partitions may be missing!\n"; 307cf200d32Sopenharmony_ci allOK = -1; 308cf200d32Sopenharmony_ci } else if (IsLittleEndian() != 1) { // Reverse byte ordering of some data.... 309cf200d32Sopenharmony_ci ReverseBytes(&ebr.MBRSignature, 2); 310cf200d32Sopenharmony_ci ReverseBytes(&ebr.partitions[0].firstLBA, 4); 311cf200d32Sopenharmony_ci ReverseBytes(&ebr.partitions[0].lengthLBA, 4); 312cf200d32Sopenharmony_ci ReverseBytes(&ebr.partitions[1].firstLBA, 4); 313cf200d32Sopenharmony_ci ReverseBytes(&ebr.partitions[1].lengthLBA, 4); 314cf200d32Sopenharmony_ci } // if/else/if 315cf200d32Sopenharmony_ci 316cf200d32Sopenharmony_ci if (ebr.MBRSignature != MBR_SIGNATURE) { 317cf200d32Sopenharmony_ci allOK = -1; 318cf200d32Sopenharmony_ci cerr << "EBR signature for logical partition invalid; read 0x"; 319cf200d32Sopenharmony_ci cerr.fill('0'); 320cf200d32Sopenharmony_ci cerr.width(4); 321cf200d32Sopenharmony_ci cerr.setf(ios::uppercase); 322cf200d32Sopenharmony_ci cerr << hex << ebr.MBRSignature << ", but should be 0x"; 323cf200d32Sopenharmony_ci cerr.width(4); 324cf200d32Sopenharmony_ci cerr << MBR_SIGNATURE << dec << "\n"; 325cf200d32Sopenharmony_ci cerr.fill(' '); 326cf200d32Sopenharmony_ci } // if 327cf200d32Sopenharmony_ci 328cf200d32Sopenharmony_ci if ((partNum >= 0) && (partNum < MAX_MBR_PARTS) && (allOK > 0)) { 329cf200d32Sopenharmony_ci // Sometimes an EBR points directly to another EBR, rather than defining 330cf200d32Sopenharmony_ci // a logical partition and then pointing to another EBR. Thus, we skip 331cf200d32Sopenharmony_ci // the logical partition when this is the case.... 332cf200d32Sopenharmony_ci ebrType = ebr.partitions[0].partitionType; 333cf200d32Sopenharmony_ci if ((ebrType == 0x05) || (ebrType == 0x0f) || (ebrType == 0x85)) { 334cf200d32Sopenharmony_ci cout << "EBR points to an EBR!\n"; 335cf200d32Sopenharmony_ci offset = extendedStart + ebr.partitions[0].firstLBA; 336cf200d32Sopenharmony_ci } else { 337cf200d32Sopenharmony_ci // Copy over the basic data.... 338cf200d32Sopenharmony_ci partitions[partNum] = ebr.partitions[0]; 339cf200d32Sopenharmony_ci // Adjust the start LBA, since it's encoded strangely.... 340cf200d32Sopenharmony_ci partitions[partNum].SetStartLBA(ebr.partitions[0].firstLBA + offset); 341cf200d32Sopenharmony_ci partitions[partNum].SetInclusion(LOGICAL); 342cf200d32Sopenharmony_ci 343cf200d32Sopenharmony_ci // Find the next partition (if there is one) 344cf200d32Sopenharmony_ci if ((ebr.partitions[1].firstLBA != UINT32_C(0)) && (partNum < (MAX_MBR_PARTS - 1))) { 345cf200d32Sopenharmony_ci offset = extendedStart + ebr.partitions[1].firstLBA; 346cf200d32Sopenharmony_ci partNum++; 347cf200d32Sopenharmony_ci } else { 348cf200d32Sopenharmony_ci another = 0; 349cf200d32Sopenharmony_ci } // if another partition 350cf200d32Sopenharmony_ci } // if/else 351cf200d32Sopenharmony_ci } // if 352cf200d32Sopenharmony_ci } // while() 353cf200d32Sopenharmony_ci return (partNum * allOK); 354cf200d32Sopenharmony_ci} // BasicMBRData::ReadLogicalPart() 355cf200d32Sopenharmony_ci 356cf200d32Sopenharmony_ci// Write the MBR data to the default defined device. This writes both the 357cf200d32Sopenharmony_ci// MBR itself and any defined logical partitions, provided there's an 358cf200d32Sopenharmony_ci// MBR extended partition. 359cf200d32Sopenharmony_ciint BasicMBRData::WriteMBRData(void) { 360cf200d32Sopenharmony_ci int allOK; 361cf200d32Sopenharmony_ci 362cf200d32Sopenharmony_ci if (myDisk != NULL) { 363cf200d32Sopenharmony_ci if (myDisk->OpenForWrite() != 0) { 364cf200d32Sopenharmony_ci allOK = WriteMBRData(myDisk); 365cf200d32Sopenharmony_ci cout << "Done writing data!\n"; 366cf200d32Sopenharmony_ci } else { 367cf200d32Sopenharmony_ci allOK = 0; 368cf200d32Sopenharmony_ci } // if/else 369cf200d32Sopenharmony_ci myDisk->Close(); 370cf200d32Sopenharmony_ci } else allOK = 0; 371cf200d32Sopenharmony_ci return allOK; 372cf200d32Sopenharmony_ci} // BasicMBRData::WriteMBRData(void) 373cf200d32Sopenharmony_ci 374cf200d32Sopenharmony_ci// Save the MBR data to a file. This writes both the 375cf200d32Sopenharmony_ci// MBR itself and any defined logical partitions. 376cf200d32Sopenharmony_ciint BasicMBRData::WriteMBRData(DiskIO *theDisk) { 377cf200d32Sopenharmony_ci int i, j, partNum, next, allOK, moreLogicals = 0; 378cf200d32Sopenharmony_ci uint64_t extFirstLBA = 0; 379cf200d32Sopenharmony_ci uint64_t writeEbrTo; // 64-bit because we support extended in 2-4TiB range 380cf200d32Sopenharmony_ci TempMBR tempMBR; 381cf200d32Sopenharmony_ci 382cf200d32Sopenharmony_ci allOK = CreateExtended(); 383cf200d32Sopenharmony_ci if (allOK) { 384cf200d32Sopenharmony_ci // First write the main MBR data structure.... 385cf200d32Sopenharmony_ci memcpy(tempMBR.code, code, 440); 386cf200d32Sopenharmony_ci tempMBR.diskSignature = diskSignature; 387cf200d32Sopenharmony_ci tempMBR.nulls = nulls; 388cf200d32Sopenharmony_ci tempMBR.MBRSignature = MBRSignature; 389cf200d32Sopenharmony_ci for (i = 0; i < 4; i++) { 390cf200d32Sopenharmony_ci partitions[i].StoreInStruct(&tempMBR.partitions[i]); 391cf200d32Sopenharmony_ci if (partitions[i].GetType() == 0x0f) { 392cf200d32Sopenharmony_ci extFirstLBA = partitions[i].GetStartLBA(); 393cf200d32Sopenharmony_ci moreLogicals = 1; 394cf200d32Sopenharmony_ci } // if 395cf200d32Sopenharmony_ci } // for i... 396cf200d32Sopenharmony_ci } // if 397cf200d32Sopenharmony_ci allOK = allOK && WriteMBRData(tempMBR, theDisk, 0); 398cf200d32Sopenharmony_ci 399cf200d32Sopenharmony_ci // Set up tempMBR with some constant data for logical partitions... 400cf200d32Sopenharmony_ci tempMBR.diskSignature = 0; 401cf200d32Sopenharmony_ci for (i = 2; i < 4; i++) { 402cf200d32Sopenharmony_ci tempMBR.partitions[i].firstLBA = tempMBR.partitions[i].lengthLBA = 0; 403cf200d32Sopenharmony_ci tempMBR.partitions[i].partitionType = 0x00; 404cf200d32Sopenharmony_ci for (j = 0; j < 3; j++) { 405cf200d32Sopenharmony_ci tempMBR.partitions[i].firstSector[j] = 0; 406cf200d32Sopenharmony_ci tempMBR.partitions[i].lastSector[j] = 0; 407cf200d32Sopenharmony_ci } // for j 408cf200d32Sopenharmony_ci } // for i 409cf200d32Sopenharmony_ci 410cf200d32Sopenharmony_ci partNum = FindNextInUse(4); 411cf200d32Sopenharmony_ci writeEbrTo = (uint64_t) extFirstLBA; 412cf200d32Sopenharmony_ci // Write logicals... 413cf200d32Sopenharmony_ci while (allOK && moreLogicals && (partNum < MAX_MBR_PARTS) && (partNum >= 0)) { 414cf200d32Sopenharmony_ci partitions[partNum].StoreInStruct(&tempMBR.partitions[0]); 415cf200d32Sopenharmony_ci tempMBR.partitions[0].firstLBA = 1; 416cf200d32Sopenharmony_ci // tempMBR.partitions[1] points to next EBR or terminates EBR linked list... 417cf200d32Sopenharmony_ci next = FindNextInUse(partNum + 1); 418cf200d32Sopenharmony_ci if ((next < MAX_MBR_PARTS) && (next > 0) && (partitions[next].GetStartLBA() > 0)) { 419cf200d32Sopenharmony_ci tempMBR.partitions[1].partitionType = 0x0f; 420cf200d32Sopenharmony_ci tempMBR.partitions[1].firstLBA = (uint32_t) (partitions[next].GetStartLBA() - extFirstLBA - 1); 421cf200d32Sopenharmony_ci tempMBR.partitions[1].lengthLBA = (uint32_t) (partitions[next].GetLengthLBA() + 1); 422cf200d32Sopenharmony_ci LBAtoCHS((uint64_t) tempMBR.partitions[1].firstLBA, 423cf200d32Sopenharmony_ci (uint8_t *) &tempMBR.partitions[1].firstSector); 424cf200d32Sopenharmony_ci LBAtoCHS(tempMBR.partitions[1].lengthLBA - extFirstLBA, 425cf200d32Sopenharmony_ci (uint8_t *) &tempMBR.partitions[1].lastSector); 426cf200d32Sopenharmony_ci } else { 427cf200d32Sopenharmony_ci tempMBR.partitions[1].partitionType = 0x00; 428cf200d32Sopenharmony_ci tempMBR.partitions[1].firstLBA = 0; 429cf200d32Sopenharmony_ci tempMBR.partitions[1].lengthLBA = 0; 430cf200d32Sopenharmony_ci moreLogicals = 0; 431cf200d32Sopenharmony_ci } // if/else 432cf200d32Sopenharmony_ci allOK = WriteMBRData(tempMBR, theDisk, writeEbrTo); 433cf200d32Sopenharmony_ci writeEbrTo = (uint64_t) tempMBR.partitions[1].firstLBA + (uint64_t) extFirstLBA; 434cf200d32Sopenharmony_ci partNum = next; 435cf200d32Sopenharmony_ci } // while 436cf200d32Sopenharmony_ci DeleteExtendedParts(); 437cf200d32Sopenharmony_ci return allOK; 438cf200d32Sopenharmony_ci} // BasicMBRData::WriteMBRData(DiskIO *theDisk) 439cf200d32Sopenharmony_ci 440cf200d32Sopenharmony_ciint BasicMBRData::WriteMBRData(const string & deviceFilename) { 441cf200d32Sopenharmony_ci device = deviceFilename; 442cf200d32Sopenharmony_ci return WriteMBRData(); 443cf200d32Sopenharmony_ci} // BasicMBRData::WriteMBRData(const string & deviceFilename) 444cf200d32Sopenharmony_ci 445cf200d32Sopenharmony_ci// Write a single MBR record to the specified sector. Used by the like-named 446cf200d32Sopenharmony_ci// function to write both the MBR and multiple EBR (for logical partition) 447cf200d32Sopenharmony_ci// records. 448cf200d32Sopenharmony_ci// Returns 1 on success, 0 on failure 449cf200d32Sopenharmony_ciint BasicMBRData::WriteMBRData(struct TempMBR & mbr, DiskIO *theDisk, uint64_t sector) { 450cf200d32Sopenharmony_ci int i, allOK; 451cf200d32Sopenharmony_ci 452cf200d32Sopenharmony_ci // Reverse the byte order, if necessary 453cf200d32Sopenharmony_ci if (IsLittleEndian() == 0) { 454cf200d32Sopenharmony_ci ReverseBytes(&mbr.diskSignature, 4); 455cf200d32Sopenharmony_ci ReverseBytes(&mbr.nulls, 2); 456cf200d32Sopenharmony_ci ReverseBytes(&mbr.MBRSignature, 2); 457cf200d32Sopenharmony_ci for (i = 0; i < 4; i++) { 458cf200d32Sopenharmony_ci ReverseBytes(&mbr.partitions[i].firstLBA, 4); 459cf200d32Sopenharmony_ci ReverseBytes(&mbr.partitions[i].lengthLBA, 4); 460cf200d32Sopenharmony_ci } // for 461cf200d32Sopenharmony_ci } // if 462cf200d32Sopenharmony_ci 463cf200d32Sopenharmony_ci // Now write the data structure... 464cf200d32Sopenharmony_ci allOK = theDisk->OpenForWrite(); 465cf200d32Sopenharmony_ci if (allOK && theDisk->Seek(sector)) { 466cf200d32Sopenharmony_ci if (theDisk->Write(&mbr, 512) != 512) { 467cf200d32Sopenharmony_ci allOK = 0; 468cf200d32Sopenharmony_ci cerr << "Error " << errno << " when saving MBR!\n"; 469cf200d32Sopenharmony_ci } // if 470cf200d32Sopenharmony_ci } else { 471cf200d32Sopenharmony_ci allOK = 0; 472cf200d32Sopenharmony_ci cerr << "Error " << errno << " when seeking to MBR to write it!\n"; 473cf200d32Sopenharmony_ci } // if/else 474cf200d32Sopenharmony_ci theDisk->Close(); 475cf200d32Sopenharmony_ci 476cf200d32Sopenharmony_ci // Reverse the byte order back, if necessary 477cf200d32Sopenharmony_ci if (IsLittleEndian() == 0) { 478cf200d32Sopenharmony_ci ReverseBytes(&mbr.diskSignature, 4); 479cf200d32Sopenharmony_ci ReverseBytes(&mbr.nulls, 2); 480cf200d32Sopenharmony_ci ReverseBytes(&mbr.MBRSignature, 2); 481cf200d32Sopenharmony_ci for (i = 0; i < 4; i++) { 482cf200d32Sopenharmony_ci ReverseBytes(&mbr.partitions[i].firstLBA, 4); 483cf200d32Sopenharmony_ci ReverseBytes(&mbr.partitions[i].lengthLBA, 4); 484cf200d32Sopenharmony_ci } // for 485cf200d32Sopenharmony_ci }// if 486cf200d32Sopenharmony_ci return allOK; 487cf200d32Sopenharmony_ci} // BasicMBRData::WriteMBRData(uint64_t sector) 488cf200d32Sopenharmony_ci 489cf200d32Sopenharmony_ci// Set a new disk device; used in copying one disk's partition 490cf200d32Sopenharmony_ci// table to another disk. 491cf200d32Sopenharmony_civoid BasicMBRData::SetDisk(DiskIO *theDisk) { 492cf200d32Sopenharmony_ci int err; 493cf200d32Sopenharmony_ci 494cf200d32Sopenharmony_ci myDisk = theDisk; 495cf200d32Sopenharmony_ci diskSize = theDisk->DiskSize(&err); 496cf200d32Sopenharmony_ci canDeleteMyDisk = 0; 497cf200d32Sopenharmony_ci ReadCHSGeom(); 498cf200d32Sopenharmony_ci} // BasicMBRData::SetDisk() 499cf200d32Sopenharmony_ci 500cf200d32Sopenharmony_ci/******************************************** 501cf200d32Sopenharmony_ci * * 502cf200d32Sopenharmony_ci * Functions that display data for the user * 503cf200d32Sopenharmony_ci * * 504cf200d32Sopenharmony_ci ********************************************/ 505cf200d32Sopenharmony_ci 506cf200d32Sopenharmony_ci// Show the MBR data to the user, up to the specified maximum number 507cf200d32Sopenharmony_ci// of partitions.... 508cf200d32Sopenharmony_civoid BasicMBRData::DisplayMBRData(void) { 509cf200d32Sopenharmony_ci int i; 510cf200d32Sopenharmony_ci 511cf200d32Sopenharmony_ci cout << "\nDisk size is " << diskSize << " sectors (" 512cf200d32Sopenharmony_ci << BytesToIeee(diskSize, blockSize) << ")\n"; 513cf200d32Sopenharmony_ci cout << "MBR disk identifier: 0x"; 514cf200d32Sopenharmony_ci cout.width(8); 515cf200d32Sopenharmony_ci cout.fill('0'); 516cf200d32Sopenharmony_ci cout.setf(ios::uppercase); 517cf200d32Sopenharmony_ci cout << hex << diskSignature << dec << "\n"; 518cf200d32Sopenharmony_ci cout << "MBR partitions:\n\n"; 519cf200d32Sopenharmony_ci if ((state == gpt) || (state == hybrid)) { 520cf200d32Sopenharmony_ci cout << "Number Boot Start Sector End Sector Status Code\n"; 521cf200d32Sopenharmony_ci } else { 522cf200d32Sopenharmony_ci cout << " Can Be Can Be\n"; 523cf200d32Sopenharmony_ci cout << "Number Boot Start Sector End Sector Status Logical Primary Code\n"; 524cf200d32Sopenharmony_ci UpdateCanBeLogical(); 525cf200d32Sopenharmony_ci } // 526cf200d32Sopenharmony_ci for (i = 0; i < MAX_MBR_PARTS; i++) { 527cf200d32Sopenharmony_ci if (partitions[i].GetLengthLBA() != 0) { 528cf200d32Sopenharmony_ci cout.fill(' '); 529cf200d32Sopenharmony_ci cout.width(4); 530cf200d32Sopenharmony_ci cout << i + 1 << " "; 531cf200d32Sopenharmony_ci partitions[i].ShowData((state == gpt) || (state == hybrid)); 532cf200d32Sopenharmony_ci } // if 533cf200d32Sopenharmony_ci cout.fill(' '); 534cf200d32Sopenharmony_ci } // for 535cf200d32Sopenharmony_ci} // BasicMBRData::DisplayMBRData() 536cf200d32Sopenharmony_ci 537cf200d32Sopenharmony_ci// Displays the state, as a word, on stdout. Used for debugging & to 538cf200d32Sopenharmony_ci// tell the user about the MBR state when the program launches.... 539cf200d32Sopenharmony_civoid BasicMBRData::ShowState(void) { 540cf200d32Sopenharmony_ci switch (state) { 541cf200d32Sopenharmony_ci case invalid: 542cf200d32Sopenharmony_ci cout << " MBR: not present\n"; 543cf200d32Sopenharmony_ci break; 544cf200d32Sopenharmony_ci case gpt: 545cf200d32Sopenharmony_ci cout << " MBR: protective\n"; 546cf200d32Sopenharmony_ci break; 547cf200d32Sopenharmony_ci case hybrid: 548cf200d32Sopenharmony_ci cout << " MBR: hybrid\n"; 549cf200d32Sopenharmony_ci break; 550cf200d32Sopenharmony_ci case mbr: 551cf200d32Sopenharmony_ci cout << " MBR: MBR only\n"; 552cf200d32Sopenharmony_ci break; 553cf200d32Sopenharmony_ci default: 554cf200d32Sopenharmony_ci cout << "\a MBR: unknown -- bug!\n"; 555cf200d32Sopenharmony_ci break; 556cf200d32Sopenharmony_ci } // switch 557cf200d32Sopenharmony_ci} // BasicMBRData::ShowState() 558cf200d32Sopenharmony_ci 559cf200d32Sopenharmony_ci/************************ 560cf200d32Sopenharmony_ci * * 561cf200d32Sopenharmony_ci * GPT Checks and fixes * 562cf200d32Sopenharmony_ci * * 563cf200d32Sopenharmony_ci ************************/ 564cf200d32Sopenharmony_ci 565cf200d32Sopenharmony_ci// Perform a very rudimentary check for GPT data on the disk; searches for 566cf200d32Sopenharmony_ci// the GPT signature in the main and backup metadata areas. 567cf200d32Sopenharmony_ci// Returns 0 if GPT data not found, 1 if main data only is found, 2 if 568cf200d32Sopenharmony_ci// backup only is found, 3 if both main and backup data are found, and 569cf200d32Sopenharmony_ci// -1 if a disk error occurred. 570cf200d32Sopenharmony_ciint BasicMBRData::CheckForGPT(void) { 571cf200d32Sopenharmony_ci int retval = 0, err; 572cf200d32Sopenharmony_ci char signature1[9], signature2[9]; 573cf200d32Sopenharmony_ci 574cf200d32Sopenharmony_ci if (myDisk != NULL) { 575cf200d32Sopenharmony_ci if (myDisk->OpenForRead() != 0) { 576cf200d32Sopenharmony_ci if (myDisk->Seek(1)) { 577cf200d32Sopenharmony_ci myDisk->Read(signature1, 8); 578cf200d32Sopenharmony_ci signature1[8] = '\0'; 579cf200d32Sopenharmony_ci } else retval = -1; 580cf200d32Sopenharmony_ci if (myDisk->Seek(myDisk->DiskSize(&err) - 1)) { 581cf200d32Sopenharmony_ci myDisk->Read(signature2, 8); 582cf200d32Sopenharmony_ci signature2[8] = '\0'; 583cf200d32Sopenharmony_ci } else retval = -1; 584cf200d32Sopenharmony_ci if ((retval >= 0) && (strcmp(signature1, "EFI PART") == 0)) 585cf200d32Sopenharmony_ci retval += 1; 586cf200d32Sopenharmony_ci if ((retval >= 0) && (strcmp(signature2, "EFI PART") == 0)) 587cf200d32Sopenharmony_ci retval += 2; 588cf200d32Sopenharmony_ci } else { 589cf200d32Sopenharmony_ci retval = -1; 590cf200d32Sopenharmony_ci } // if/else 591cf200d32Sopenharmony_ci myDisk->Close(); 592cf200d32Sopenharmony_ci } else retval = -1; 593cf200d32Sopenharmony_ci return retval; 594cf200d32Sopenharmony_ci} // BasicMBRData::CheckForGPT() 595cf200d32Sopenharmony_ci 596cf200d32Sopenharmony_ci// Blanks the 2nd (sector #1, numbered from 0) and last sectors of the disk, 597cf200d32Sopenharmony_ci// but only if GPT data are verified on the disk, and only for the sector(s) 598cf200d32Sopenharmony_ci// with GPT signatures. 599cf200d32Sopenharmony_ci// Returns 1 if operation completes successfully, 0 if not (returns 1 if 600cf200d32Sopenharmony_ci// no GPT data are found on the disk). 601cf200d32Sopenharmony_ciint BasicMBRData::BlankGPTData(void) { 602cf200d32Sopenharmony_ci int allOK = 1, err; 603cf200d32Sopenharmony_ci uint8_t blank[512]; 604cf200d32Sopenharmony_ci 605cf200d32Sopenharmony_ci memset(blank, 0, 512); 606cf200d32Sopenharmony_ci switch (CheckForGPT()) { 607cf200d32Sopenharmony_ci case -1: 608cf200d32Sopenharmony_ci allOK = 0; 609cf200d32Sopenharmony_ci break; 610cf200d32Sopenharmony_ci case 0: 611cf200d32Sopenharmony_ci break; 612cf200d32Sopenharmony_ci case 1: 613cf200d32Sopenharmony_ci if ((myDisk != NULL) && (myDisk->OpenForWrite())) { 614cf200d32Sopenharmony_ci if (!((myDisk->Seek(1)) && (myDisk->Write(blank, 512) == 512))) 615cf200d32Sopenharmony_ci allOK = 0; 616cf200d32Sopenharmony_ci myDisk->Close(); 617cf200d32Sopenharmony_ci } else allOK = 0; 618cf200d32Sopenharmony_ci break; 619cf200d32Sopenharmony_ci case 2: 620cf200d32Sopenharmony_ci if ((myDisk != NULL) && (myDisk->OpenForWrite())) { 621cf200d32Sopenharmony_ci if (!((myDisk->Seek(myDisk->DiskSize(&err) - 1)) && 622cf200d32Sopenharmony_ci (myDisk->Write(blank, 512) == 512))) 623cf200d32Sopenharmony_ci allOK = 0; 624cf200d32Sopenharmony_ci myDisk->Close(); 625cf200d32Sopenharmony_ci } else allOK = 0; 626cf200d32Sopenharmony_ci break; 627cf200d32Sopenharmony_ci case 3: 628cf200d32Sopenharmony_ci if ((myDisk != NULL) && (myDisk->OpenForWrite())) { 629cf200d32Sopenharmony_ci if (!((myDisk->Seek(1)) && (myDisk->Write(blank, 512) == 512))) 630cf200d32Sopenharmony_ci allOK = 0; 631cf200d32Sopenharmony_ci if (!((myDisk->Seek(myDisk->DiskSize(&err) - 1)) && 632cf200d32Sopenharmony_ci (myDisk->Write(blank, 512) == 512))) 633cf200d32Sopenharmony_ci allOK = 0; 634cf200d32Sopenharmony_ci myDisk->Close(); 635cf200d32Sopenharmony_ci } else allOK = 0; 636cf200d32Sopenharmony_ci break; 637cf200d32Sopenharmony_ci default: 638cf200d32Sopenharmony_ci break; 639cf200d32Sopenharmony_ci } // switch() 640cf200d32Sopenharmony_ci return allOK; 641cf200d32Sopenharmony_ci} // BasicMBRData::BlankGPTData 642cf200d32Sopenharmony_ci 643cf200d32Sopenharmony_ci/********************************************************************* 644cf200d32Sopenharmony_ci * * 645cf200d32Sopenharmony_ci * Functions that set or get disk metadata (CHS geometry, disk size, * 646cf200d32Sopenharmony_ci * etc.) * 647cf200d32Sopenharmony_ci * * 648cf200d32Sopenharmony_ci *********************************************************************/ 649cf200d32Sopenharmony_ci 650cf200d32Sopenharmony_ci// Read the CHS geometry using OS calls, or if that fails, set to 651cf200d32Sopenharmony_ci// the most common value for big disks (255 heads, 63 sectors per 652cf200d32Sopenharmony_ci// track, & however many cylinders that computes to). 653cf200d32Sopenharmony_civoid BasicMBRData::ReadCHSGeom(void) { 654cf200d32Sopenharmony_ci int err; 655cf200d32Sopenharmony_ci 656cf200d32Sopenharmony_ci numHeads = myDisk->GetNumHeads(); 657cf200d32Sopenharmony_ci numSecspTrack = myDisk->GetNumSecsPerTrack(); 658cf200d32Sopenharmony_ci diskSize = myDisk->DiskSize(&err); 659cf200d32Sopenharmony_ci blockSize = myDisk->GetBlockSize(); 660cf200d32Sopenharmony_ci partitions[0].SetGeometry(numHeads, numSecspTrack, diskSize, blockSize); 661cf200d32Sopenharmony_ci} // BasicMBRData::ReadCHSGeom() 662cf200d32Sopenharmony_ci 663cf200d32Sopenharmony_ci// Find the low and high used partition numbers (numbered from 0). 664cf200d32Sopenharmony_ci// Return value is the number of partitions found. Note that the 665cf200d32Sopenharmony_ci// *low and *high values are both set to 0 when no partitions 666cf200d32Sopenharmony_ci// are found, as well as when a single partition in the first 667cf200d32Sopenharmony_ci// position exists. Thus, the return value is the only way to 668cf200d32Sopenharmony_ci// tell when no partitions exist. 669cf200d32Sopenharmony_ciint BasicMBRData::GetPartRange(uint32_t *low, uint32_t *high) { 670cf200d32Sopenharmony_ci uint32_t i; 671cf200d32Sopenharmony_ci int numFound = 0; 672cf200d32Sopenharmony_ci 673cf200d32Sopenharmony_ci *low = MAX_MBR_PARTS + 1; // code for "not found" 674cf200d32Sopenharmony_ci *high = 0; 675cf200d32Sopenharmony_ci for (i = 0; i < MAX_MBR_PARTS; i++) { 676cf200d32Sopenharmony_ci if (partitions[i].GetStartLBA() != UINT32_C(0)) { // it exists 677cf200d32Sopenharmony_ci *high = i; // since we're counting up, set the high value 678cf200d32Sopenharmony_ci // Set the low value only if it's not yet found... 679cf200d32Sopenharmony_ci if (*low == (MAX_MBR_PARTS + 1)) 680cf200d32Sopenharmony_ci *low = i; 681cf200d32Sopenharmony_ci numFound++; 682cf200d32Sopenharmony_ci } // if 683cf200d32Sopenharmony_ci } // for 684cf200d32Sopenharmony_ci 685cf200d32Sopenharmony_ci // Above will leave *low pointing to its "not found" value if no partitions 686cf200d32Sopenharmony_ci // are defined, so reset to 0 if this is the case.... 687cf200d32Sopenharmony_ci if (*low == (MAX_MBR_PARTS + 1)) 688cf200d32Sopenharmony_ci *low = 0; 689cf200d32Sopenharmony_ci return numFound; 690cf200d32Sopenharmony_ci} // GPTData::GetPartRange() 691cf200d32Sopenharmony_ci 692cf200d32Sopenharmony_ci// Converts 64-bit LBA value to MBR-style CHS value. Returns 1 if conversion 693cf200d32Sopenharmony_ci// was within the range that can be expressed by CHS (including 0, for an 694cf200d32Sopenharmony_ci// empty partition), 0 if the value is outside that range, and -1 if chs is 695cf200d32Sopenharmony_ci// invalid. 696cf200d32Sopenharmony_ciint BasicMBRData::LBAtoCHS(uint64_t lba, uint8_t * chs) { 697cf200d32Sopenharmony_ci uint64_t cylinder, head, sector; // all numbered from 0 698cf200d32Sopenharmony_ci uint64_t remainder; 699cf200d32Sopenharmony_ci int retval = 1; 700cf200d32Sopenharmony_ci int done = 0; 701cf200d32Sopenharmony_ci 702cf200d32Sopenharmony_ci if (chs != NULL) { 703cf200d32Sopenharmony_ci // Special case: In case of 0 LBA value, zero out CHS values.... 704cf200d32Sopenharmony_ci if (lba == 0) { 705cf200d32Sopenharmony_ci chs[0] = chs[1] = chs[2] = UINT8_C(0); 706cf200d32Sopenharmony_ci done = 1; 707cf200d32Sopenharmony_ci } // if 708cf200d32Sopenharmony_ci // If LBA value is too large for CHS, max out CHS values.... 709cf200d32Sopenharmony_ci if ((!done) && (lba >= ((uint64_t) numHeads * numSecspTrack * MAX_CYLINDERS))) { 710cf200d32Sopenharmony_ci chs[0] = 254; 711cf200d32Sopenharmony_ci chs[1] = chs[2] = 255; 712cf200d32Sopenharmony_ci done = 1; 713cf200d32Sopenharmony_ci retval = 0; 714cf200d32Sopenharmony_ci } // if 715cf200d32Sopenharmony_ci // If neither of the above applies, compute CHS values.... 716cf200d32Sopenharmony_ci if (!done) { 717cf200d32Sopenharmony_ci cylinder = lba / (uint64_t) (numHeads * numSecspTrack); 718cf200d32Sopenharmony_ci remainder = lba - (cylinder * numHeads * numSecspTrack); 719cf200d32Sopenharmony_ci head = remainder / numSecspTrack; 720cf200d32Sopenharmony_ci remainder -= head * numSecspTrack; 721cf200d32Sopenharmony_ci sector = remainder; 722cf200d32Sopenharmony_ci if (head < numHeads) 723cf200d32Sopenharmony_ci chs[0] = (uint8_t) head; 724cf200d32Sopenharmony_ci else 725cf200d32Sopenharmony_ci retval = 0; 726cf200d32Sopenharmony_ci if (sector < numSecspTrack) { 727cf200d32Sopenharmony_ci chs[1] = (uint8_t) ((sector + 1) + (cylinder >> 8) * 64); 728cf200d32Sopenharmony_ci chs[2] = (uint8_t) (cylinder & UINT64_C(0xFF)); 729cf200d32Sopenharmony_ci } else { 730cf200d32Sopenharmony_ci retval = 0; 731cf200d32Sopenharmony_ci } // if/else 732cf200d32Sopenharmony_ci } // if value is expressible and non-0 733cf200d32Sopenharmony_ci } else { // Invalid (NULL) chs pointer 734cf200d32Sopenharmony_ci retval = -1; 735cf200d32Sopenharmony_ci } // if CHS pointer valid 736cf200d32Sopenharmony_ci return (retval); 737cf200d32Sopenharmony_ci} // BasicMBRData::LBAtoCHS() 738cf200d32Sopenharmony_ci 739cf200d32Sopenharmony_ci// Look for overlapping partitions. Also looks for a couple of non-error 740cf200d32Sopenharmony_ci// conditions that the user should be told about. 741cf200d32Sopenharmony_ci// Returns the number of problems found 742cf200d32Sopenharmony_ciint BasicMBRData::FindOverlaps(void) { 743cf200d32Sopenharmony_ci int i, j, numProbs = 0, numEE = 0, ProtectiveOnOne = 0; 744cf200d32Sopenharmony_ci 745cf200d32Sopenharmony_ci for (i = 0; i < MAX_MBR_PARTS; i++) { 746cf200d32Sopenharmony_ci for (j = i + 1; j < MAX_MBR_PARTS; j++) { 747cf200d32Sopenharmony_ci if ((partitions[i].GetInclusion() != NONE) && (partitions[j].GetInclusion() != NONE) && 748cf200d32Sopenharmony_ci (partitions[i].DoTheyOverlap(partitions[j]))) { 749cf200d32Sopenharmony_ci numProbs++; 750cf200d32Sopenharmony_ci cout << "\nProblem: MBR partitions " << i + 1 << " and " << j + 1 751cf200d32Sopenharmony_ci << " overlap!\n"; 752cf200d32Sopenharmony_ci } // if 753cf200d32Sopenharmony_ci } // for (j...) 754cf200d32Sopenharmony_ci if (partitions[i].GetType() == 0xEE) { 755cf200d32Sopenharmony_ci numEE++; 756cf200d32Sopenharmony_ci if (partitions[i].GetStartLBA() == 1) 757cf200d32Sopenharmony_ci ProtectiveOnOne = 1; 758cf200d32Sopenharmony_ci } // if 759cf200d32Sopenharmony_ci } // for (i...) 760cf200d32Sopenharmony_ci 761cf200d32Sopenharmony_ci if (numEE > 1) 762cf200d32Sopenharmony_ci cout << "\nCaution: More than one 0xEE MBR partition found. This can cause problems\n" 763cf200d32Sopenharmony_ci << "in some OSes.\n"; 764cf200d32Sopenharmony_ci if (!ProtectiveOnOne && (numEE > 0)) 765cf200d32Sopenharmony_ci cout << "\nWarning: 0xEE partition doesn't start on sector 1. This can cause " 766cf200d32Sopenharmony_ci << "problems\nin some OSes.\n"; 767cf200d32Sopenharmony_ci 768cf200d32Sopenharmony_ci return numProbs; 769cf200d32Sopenharmony_ci} // BasicMBRData::FindOverlaps() 770cf200d32Sopenharmony_ci 771cf200d32Sopenharmony_ci// Returns the number of primary partitions, including the extended partition 772cf200d32Sopenharmony_ci// required to hold any logical partitions found. 773cf200d32Sopenharmony_ciint BasicMBRData::NumPrimaries(void) { 774cf200d32Sopenharmony_ci int i, numPrimaries = 0, logicalsFound = 0; 775cf200d32Sopenharmony_ci 776cf200d32Sopenharmony_ci for (i = 0; i < MAX_MBR_PARTS; i++) { 777cf200d32Sopenharmony_ci if (partitions[i].GetLengthLBA() > 0) { 778cf200d32Sopenharmony_ci if (partitions[i].GetInclusion() == PRIMARY) 779cf200d32Sopenharmony_ci numPrimaries++; 780cf200d32Sopenharmony_ci if (partitions[i].GetInclusion() == LOGICAL) 781cf200d32Sopenharmony_ci logicalsFound = 1; 782cf200d32Sopenharmony_ci } // if 783cf200d32Sopenharmony_ci } // for 784cf200d32Sopenharmony_ci return (numPrimaries + logicalsFound); 785cf200d32Sopenharmony_ci} // BasicMBRData::NumPrimaries() 786cf200d32Sopenharmony_ci 787cf200d32Sopenharmony_ci// Returns the number of logical partitions. 788cf200d32Sopenharmony_ciint BasicMBRData::NumLogicals(void) { 789cf200d32Sopenharmony_ci int i, numLogicals = 0; 790cf200d32Sopenharmony_ci 791cf200d32Sopenharmony_ci for (i = 0; i < MAX_MBR_PARTS; i++) { 792cf200d32Sopenharmony_ci if (partitions[i].GetInclusion() == LOGICAL) 793cf200d32Sopenharmony_ci numLogicals++; 794cf200d32Sopenharmony_ci } // for 795cf200d32Sopenharmony_ci return numLogicals; 796cf200d32Sopenharmony_ci} // BasicMBRData::NumLogicals() 797cf200d32Sopenharmony_ci 798cf200d32Sopenharmony_ci// Returns the number of partitions (primaries plus logicals), NOT including 799cf200d32Sopenharmony_ci// the extended partition required to house the logicals. 800cf200d32Sopenharmony_ciint BasicMBRData::CountParts(void) { 801cf200d32Sopenharmony_ci int i, num = 0; 802cf200d32Sopenharmony_ci 803cf200d32Sopenharmony_ci for (i = 0; i < MAX_MBR_PARTS; i++) { 804cf200d32Sopenharmony_ci if ((partitions[i].GetInclusion() == LOGICAL) || 805cf200d32Sopenharmony_ci (partitions[i].GetInclusion() == PRIMARY)) 806cf200d32Sopenharmony_ci num++; 807cf200d32Sopenharmony_ci } // for 808cf200d32Sopenharmony_ci return num; 809cf200d32Sopenharmony_ci} // BasicMBRData::CountParts() 810cf200d32Sopenharmony_ci 811cf200d32Sopenharmony_ci// Updates the canBeLogical and canBePrimary flags for all the partitions. 812cf200d32Sopenharmony_civoid BasicMBRData::UpdateCanBeLogical(void) { 813cf200d32Sopenharmony_ci int i, j, sectorBefore, numPrimaries, numLogicals, usedAsEBR; 814cf200d32Sopenharmony_ci uint64_t firstLogical, lastLogical, lStart, pStart; 815cf200d32Sopenharmony_ci 816cf200d32Sopenharmony_ci numPrimaries = NumPrimaries(); 817cf200d32Sopenharmony_ci numLogicals = NumLogicals(); 818cf200d32Sopenharmony_ci firstLogical = FirstLogicalLBA() - 1; 819cf200d32Sopenharmony_ci lastLogical = LastLogicalLBA(); 820cf200d32Sopenharmony_ci for (i = 0; i < MAX_MBR_PARTS; i++) { 821cf200d32Sopenharmony_ci usedAsEBR = (SectorUsedAs(partitions[i].GetLastLBA()) == EBR); 822cf200d32Sopenharmony_ci if (usedAsEBR) { 823cf200d32Sopenharmony_ci partitions[i].SetCanBeLogical(0); 824cf200d32Sopenharmony_ci partitions[i].SetCanBePrimary(0); 825cf200d32Sopenharmony_ci } else if (partitions[i].GetLengthLBA() > 0) { 826cf200d32Sopenharmony_ci // First determine if it can be logical.... 827cf200d32Sopenharmony_ci sectorBefore = SectorUsedAs(partitions[i].GetStartLBA() - 1); 828cf200d32Sopenharmony_ci lStart = partitions[i].GetStartLBA(); // start of potential logical part. 829cf200d32Sopenharmony_ci if ((lastLogical > 0) && 830cf200d32Sopenharmony_ci ((sectorBefore == EBR) || (sectorBefore == NONE))) { 831cf200d32Sopenharmony_ci // Assume it can be logical, then search for primaries that make it 832cf200d32Sopenharmony_ci // not work and, if found, flag appropriately. 833cf200d32Sopenharmony_ci partitions[i].SetCanBeLogical(1); 834cf200d32Sopenharmony_ci for (j = 0; j < MAX_MBR_PARTS; j++) { 835cf200d32Sopenharmony_ci if ((i != j) && (partitions[j].GetInclusion() == PRIMARY)) { 836cf200d32Sopenharmony_ci pStart = partitions[j].GetStartLBA(); 837cf200d32Sopenharmony_ci if (((pStart < lStart) && (firstLogical < pStart)) || 838cf200d32Sopenharmony_ci ((pStart > lStart) && (firstLogical > pStart))) { 839cf200d32Sopenharmony_ci partitions[i].SetCanBeLogical(0); 840cf200d32Sopenharmony_ci } // if/else 841cf200d32Sopenharmony_ci } // if 842cf200d32Sopenharmony_ci } // for 843cf200d32Sopenharmony_ci } else { 844cf200d32Sopenharmony_ci if ((sectorBefore != EBR) && (sectorBefore != NONE)) 845cf200d32Sopenharmony_ci partitions[i].SetCanBeLogical(0); 846cf200d32Sopenharmony_ci else 847cf200d32Sopenharmony_ci partitions[i].SetCanBeLogical(lastLogical == 0); // can be logical only if no logicals already 848cf200d32Sopenharmony_ci } // if/else 849cf200d32Sopenharmony_ci // Now determine if it can be primary. Start by assuming it can be... 850cf200d32Sopenharmony_ci partitions[i].SetCanBePrimary(1); 851cf200d32Sopenharmony_ci if ((numPrimaries >= 4) && (partitions[i].GetInclusion() != PRIMARY)) { 852cf200d32Sopenharmony_ci partitions[i].SetCanBePrimary(0); 853cf200d32Sopenharmony_ci if ((partitions[i].GetInclusion() == LOGICAL) && (numLogicals == 1) && 854cf200d32Sopenharmony_ci (numPrimaries == 4)) 855cf200d32Sopenharmony_ci partitions[i].SetCanBePrimary(1); 856cf200d32Sopenharmony_ci } // if 857cf200d32Sopenharmony_ci if ((partitions[i].GetStartLBA() > (firstLogical + 1)) && 858cf200d32Sopenharmony_ci (partitions[i].GetLastLBA() < lastLogical)) 859cf200d32Sopenharmony_ci partitions[i].SetCanBePrimary(0); 860cf200d32Sopenharmony_ci } // else if 861cf200d32Sopenharmony_ci } // for 862cf200d32Sopenharmony_ci} // BasicMBRData::UpdateCanBeLogical() 863cf200d32Sopenharmony_ci 864cf200d32Sopenharmony_ci// Returns the first sector occupied by any logical partition. Note that 865cf200d32Sopenharmony_ci// this does NOT include the logical partition's EBR! Returns UINT32_MAX 866cf200d32Sopenharmony_ci// if there are no logical partitions defined. 867cf200d32Sopenharmony_ciuint64_t BasicMBRData::FirstLogicalLBA(void) { 868cf200d32Sopenharmony_ci int i; 869cf200d32Sopenharmony_ci uint64_t firstFound = UINT32_MAX; 870cf200d32Sopenharmony_ci 871cf200d32Sopenharmony_ci for (i = 0; i < MAX_MBR_PARTS; i++) { 872cf200d32Sopenharmony_ci if ((partitions[i].GetInclusion() == LOGICAL) && 873cf200d32Sopenharmony_ci (partitions[i].GetStartLBA() < firstFound)) { 874cf200d32Sopenharmony_ci firstFound = partitions[i].GetStartLBA(); 875cf200d32Sopenharmony_ci } // if 876cf200d32Sopenharmony_ci } // for 877cf200d32Sopenharmony_ci return firstFound; 878cf200d32Sopenharmony_ci} // BasicMBRData::FirstLogicalLBA() 879cf200d32Sopenharmony_ci 880cf200d32Sopenharmony_ci// Returns the last sector occupied by any logical partition, or 0 if 881cf200d32Sopenharmony_ci// there are no logical partitions defined. 882cf200d32Sopenharmony_ciuint64_t BasicMBRData::LastLogicalLBA(void) { 883cf200d32Sopenharmony_ci int i; 884cf200d32Sopenharmony_ci uint64_t lastFound = 0; 885cf200d32Sopenharmony_ci 886cf200d32Sopenharmony_ci for (i = 0; i < MAX_MBR_PARTS; i++) { 887cf200d32Sopenharmony_ci if ((partitions[i].GetInclusion() == LOGICAL) && 888cf200d32Sopenharmony_ci (partitions[i].GetLastLBA() > lastFound)) 889cf200d32Sopenharmony_ci lastFound = partitions[i].GetLastLBA(); 890cf200d32Sopenharmony_ci } // for 891cf200d32Sopenharmony_ci return lastFound; 892cf200d32Sopenharmony_ci} // BasicMBRData::LastLogicalLBA() 893cf200d32Sopenharmony_ci 894cf200d32Sopenharmony_ci// Returns 1 if logical partitions are contiguous (have no primaries 895cf200d32Sopenharmony_ci// in their midst), or 0 if one or more primaries exist between 896cf200d32Sopenharmony_ci// logicals. 897cf200d32Sopenharmony_ciint BasicMBRData::AreLogicalsContiguous(void) { 898cf200d32Sopenharmony_ci int allOK = 1, i = 0; 899cf200d32Sopenharmony_ci uint64_t firstLogical, lastLogical; 900cf200d32Sopenharmony_ci 901cf200d32Sopenharmony_ci firstLogical = FirstLogicalLBA() - 1; // subtract 1 for EBR 902cf200d32Sopenharmony_ci lastLogical = LastLogicalLBA(); 903cf200d32Sopenharmony_ci if (lastLogical > 0) { 904cf200d32Sopenharmony_ci do { 905cf200d32Sopenharmony_ci if ((partitions[i].GetInclusion() == PRIMARY) && 906cf200d32Sopenharmony_ci (partitions[i].GetStartLBA() >= firstLogical) && 907cf200d32Sopenharmony_ci (partitions[i].GetStartLBA() <= lastLogical)) { 908cf200d32Sopenharmony_ci allOK = 0; 909cf200d32Sopenharmony_ci } // if 910cf200d32Sopenharmony_ci i++; 911cf200d32Sopenharmony_ci } while ((i < MAX_MBR_PARTS) && allOK); 912cf200d32Sopenharmony_ci } // if 913cf200d32Sopenharmony_ci return allOK; 914cf200d32Sopenharmony_ci} // BasicMBRData::AreLogicalsContiguous() 915cf200d32Sopenharmony_ci 916cf200d32Sopenharmony_ci// Returns 1 if all partitions fit on the disk, given its size; 0 if any 917cf200d32Sopenharmony_ci// partition is too big. 918cf200d32Sopenharmony_ciint BasicMBRData::DoTheyFit(void) { 919cf200d32Sopenharmony_ci int i, allOK = 1; 920cf200d32Sopenharmony_ci 921cf200d32Sopenharmony_ci for (i = 0; i < MAX_MBR_PARTS; i++) { 922cf200d32Sopenharmony_ci if ((partitions[i].GetStartLBA() > diskSize) || (partitions[i].GetLastLBA() > diskSize)) { 923cf200d32Sopenharmony_ci allOK = 0; 924cf200d32Sopenharmony_ci } // if 925cf200d32Sopenharmony_ci } // for 926cf200d32Sopenharmony_ci return allOK; 927cf200d32Sopenharmony_ci} // BasicMBRData::DoTheyFit(void) 928cf200d32Sopenharmony_ci 929cf200d32Sopenharmony_ci// Returns 1 if there's at least one free sector immediately preceding 930cf200d32Sopenharmony_ci// all partitions flagged as logical; 0 if any logical partition lacks 931cf200d32Sopenharmony_ci// this space. 932cf200d32Sopenharmony_ciint BasicMBRData::SpaceBeforeAllLogicals(void) { 933cf200d32Sopenharmony_ci int i = 0, allOK = 1; 934cf200d32Sopenharmony_ci 935cf200d32Sopenharmony_ci do { 936cf200d32Sopenharmony_ci if ((partitions[i].GetStartLBA() > 0) && (partitions[i].GetInclusion() == LOGICAL)) { 937cf200d32Sopenharmony_ci allOK = allOK && (SectorUsedAs(partitions[i].GetStartLBA() - 1) == EBR); 938cf200d32Sopenharmony_ci } // if 939cf200d32Sopenharmony_ci i++; 940cf200d32Sopenharmony_ci } while (allOK && (i < MAX_MBR_PARTS)); 941cf200d32Sopenharmony_ci return allOK; 942cf200d32Sopenharmony_ci} // BasicMBRData::SpaceBeforeAllLogicals() 943cf200d32Sopenharmony_ci 944cf200d32Sopenharmony_ci// Returns 1 if the partitions describe a legal layout -- all logicals 945cf200d32Sopenharmony_ci// are contiguous and have at least one preceding empty sector, 946cf200d32Sopenharmony_ci// the number of primaries is under 4 (or under 3 if there are any 947cf200d32Sopenharmony_ci// logicals), there are no overlapping partitions, etc. 948cf200d32Sopenharmony_ci// Does NOT assume that primaries are numbered 1-4; uses the 949cf200d32Sopenharmony_ci// IsItPrimary() function of the MBRPart class to determine 950cf200d32Sopenharmony_ci// primary status. Also does NOT consider partition order; there 951cf200d32Sopenharmony_ci// can be gaps and it will still be considered legal. 952cf200d32Sopenharmony_ciint BasicMBRData::IsLegal(void) { 953cf200d32Sopenharmony_ci int allOK; 954cf200d32Sopenharmony_ci 955cf200d32Sopenharmony_ci allOK = (FindOverlaps() == 0); 956cf200d32Sopenharmony_ci allOK = (allOK && (NumPrimaries() <= 4)); 957cf200d32Sopenharmony_ci allOK = (allOK && AreLogicalsContiguous()); 958cf200d32Sopenharmony_ci allOK = (allOK && DoTheyFit()); 959cf200d32Sopenharmony_ci allOK = (allOK && SpaceBeforeAllLogicals()); 960cf200d32Sopenharmony_ci return allOK; 961cf200d32Sopenharmony_ci} // BasicMBRData::IsLegal() 962cf200d32Sopenharmony_ci 963cf200d32Sopenharmony_ci// Returns 1 if the 0xEE partition in the protective/hybrid MBR is marked as 964cf200d32Sopenharmony_ci// active/bootable. 965cf200d32Sopenharmony_ciint BasicMBRData::IsEEActive(void) { 966cf200d32Sopenharmony_ci int i, IsActive = 0; 967cf200d32Sopenharmony_ci 968cf200d32Sopenharmony_ci for (i = 0; i < MAX_MBR_PARTS; i++) { 969cf200d32Sopenharmony_ci if ((partitions[i].GetStatus() & 0x80) && (partitions[i].GetType() == 0xEE)) 970cf200d32Sopenharmony_ci IsActive = 1; 971cf200d32Sopenharmony_ci } 972cf200d32Sopenharmony_ci return IsActive; 973cf200d32Sopenharmony_ci} // BasicMBRData::IsEEActive() 974cf200d32Sopenharmony_ci 975cf200d32Sopenharmony_ci// Finds the next in-use partition, starting with start (will return start 976cf200d32Sopenharmony_ci// if it's in use). Returns -1 if no subsequent partition is in use. 977cf200d32Sopenharmony_ciint BasicMBRData::FindNextInUse(int start) { 978cf200d32Sopenharmony_ci if (start >= MAX_MBR_PARTS) 979cf200d32Sopenharmony_ci start = -1; 980cf200d32Sopenharmony_ci while ((start < MAX_MBR_PARTS) && (start >= 0) && (partitions[start].GetInclusion() == NONE)) 981cf200d32Sopenharmony_ci start++; 982cf200d32Sopenharmony_ci if ((start < 0) || (start >= MAX_MBR_PARTS)) 983cf200d32Sopenharmony_ci start = -1; 984cf200d32Sopenharmony_ci return start; 985cf200d32Sopenharmony_ci} // BasicMBRData::FindFirstLogical(); 986cf200d32Sopenharmony_ci 987cf200d32Sopenharmony_ci/***************************************************** 988cf200d32Sopenharmony_ci * * 989cf200d32Sopenharmony_ci * Functions to create, delete, or change partitions * 990cf200d32Sopenharmony_ci * * 991cf200d32Sopenharmony_ci *****************************************************/ 992cf200d32Sopenharmony_ci 993cf200d32Sopenharmony_ci// Empty all data. Meant mainly for calling by constructors, but it's also 994cf200d32Sopenharmony_ci// used by the hybrid MBR functions in the GPTData class. 995cf200d32Sopenharmony_civoid BasicMBRData::EmptyMBR(int clearBootloader) { 996cf200d32Sopenharmony_ci int i; 997cf200d32Sopenharmony_ci 998cf200d32Sopenharmony_ci // Zero out the boot loader section, the disk signature, and the 999cf200d32Sopenharmony_ci // 2-byte nulls area only if requested to do so. (This is the 1000cf200d32Sopenharmony_ci // default.) 1001cf200d32Sopenharmony_ci if (clearBootloader == 1) { 1002cf200d32Sopenharmony_ci EmptyBootloader(); 1003cf200d32Sopenharmony_ci } // if 1004cf200d32Sopenharmony_ci 1005cf200d32Sopenharmony_ci // Blank out the partitions 1006cf200d32Sopenharmony_ci for (i = 0; i < MAX_MBR_PARTS; i++) { 1007cf200d32Sopenharmony_ci partitions[i].Empty(); 1008cf200d32Sopenharmony_ci } // for 1009cf200d32Sopenharmony_ci MBRSignature = MBR_SIGNATURE; 1010cf200d32Sopenharmony_ci state = mbr; 1011cf200d32Sopenharmony_ci} // BasicMBRData::EmptyMBR() 1012cf200d32Sopenharmony_ci 1013cf200d32Sopenharmony_ci// Blank out the boot loader area. Done with the initial MBR-to-GPT 1014cf200d32Sopenharmony_ci// conversion, since MBR boot loaders don't understand GPT, and so 1015cf200d32Sopenharmony_ci// need to be replaced.... 1016cf200d32Sopenharmony_civoid BasicMBRData::EmptyBootloader(void) { 1017cf200d32Sopenharmony_ci int i; 1018cf200d32Sopenharmony_ci 1019cf200d32Sopenharmony_ci for (i = 0; i < 440; i++) 1020cf200d32Sopenharmony_ci code[i] = 0; 1021cf200d32Sopenharmony_ci nulls = 0; 1022cf200d32Sopenharmony_ci} // BasicMBRData::EmptyBootloader 1023cf200d32Sopenharmony_ci 1024cf200d32Sopenharmony_ci// Create a partition of the specified number based on the passed 1025cf200d32Sopenharmony_ci// partition. This function does *NO* error checking, so it's possible 1026cf200d32Sopenharmony_ci// to seriously screw up a partition table using this function! 1027cf200d32Sopenharmony_ci// Note: This function should NOT be used to create the 0xEE partition 1028cf200d32Sopenharmony_ci// in a conventional GPT configuration, since that partition has 1029cf200d32Sopenharmony_ci// specific size requirements that this function won't handle. It may 1030cf200d32Sopenharmony_ci// be used for creating the 0xEE partition(s) in a hybrid MBR, though, 1031cf200d32Sopenharmony_ci// since those toss the rulebook away anyhow.... 1032cf200d32Sopenharmony_civoid BasicMBRData::AddPart(int num, const MBRPart& newPart) { 1033cf200d32Sopenharmony_ci partitions[num] = newPart; 1034cf200d32Sopenharmony_ci} // BasicMBRData::AddPart() 1035cf200d32Sopenharmony_ci 1036cf200d32Sopenharmony_ci// Create a partition of the specified number, starting LBA, and 1037cf200d32Sopenharmony_ci// length. This function does almost no error checking, so it's possible 1038cf200d32Sopenharmony_ci// to seriously screw up a partition table using this function! 1039cf200d32Sopenharmony_ci// Note: This function should NOT be used to create the 0xEE partition 1040cf200d32Sopenharmony_ci// in a conventional GPT configuration, since that partition has 1041cf200d32Sopenharmony_ci// specific size requirements that this function won't handle. It may 1042cf200d32Sopenharmony_ci// be used for creating the 0xEE partition(s) in a hybrid MBR, though, 1043cf200d32Sopenharmony_ci// since those toss the rulebook away anyhow.... 1044cf200d32Sopenharmony_civoid BasicMBRData::MakePart(int num, uint64_t start, uint64_t length, int type, int bootable) { 1045cf200d32Sopenharmony_ci if ((num >= 0) && (num < MAX_MBR_PARTS) && (start <= UINT32_MAX) && (length <= UINT32_MAX)) { 1046cf200d32Sopenharmony_ci partitions[num].Empty(); 1047cf200d32Sopenharmony_ci partitions[num].SetType(type); 1048cf200d32Sopenharmony_ci partitions[num].SetLocation(start, length); 1049cf200d32Sopenharmony_ci if (num < 4) 1050cf200d32Sopenharmony_ci partitions[num].SetInclusion(PRIMARY); 1051cf200d32Sopenharmony_ci else 1052cf200d32Sopenharmony_ci partitions[num].SetInclusion(LOGICAL); 1053cf200d32Sopenharmony_ci SetPartBootable(num, bootable); 1054cf200d32Sopenharmony_ci } // if valid partition number & size 1055cf200d32Sopenharmony_ci} // BasicMBRData::MakePart() 1056cf200d32Sopenharmony_ci 1057cf200d32Sopenharmony_ci// Set the partition's type code. 1058cf200d32Sopenharmony_ci// Returns 1 if successful, 0 if not (invalid partition number) 1059cf200d32Sopenharmony_ciint BasicMBRData::SetPartType(int num, int type) { 1060cf200d32Sopenharmony_ci int allOK; 1061cf200d32Sopenharmony_ci 1062cf200d32Sopenharmony_ci if ((num >= 0) && (num < MAX_MBR_PARTS)) { 1063cf200d32Sopenharmony_ci if (partitions[num].GetLengthLBA() != UINT32_C(0)) { 1064cf200d32Sopenharmony_ci allOK = partitions[num].SetType(type); 1065cf200d32Sopenharmony_ci } else allOK = 0; 1066cf200d32Sopenharmony_ci } else allOK = 0; 1067cf200d32Sopenharmony_ci return allOK; 1068cf200d32Sopenharmony_ci} // BasicMBRData::SetPartType() 1069cf200d32Sopenharmony_ci 1070cf200d32Sopenharmony_ci// Set (or remove) the partition's bootable flag. Setting it is the 1071cf200d32Sopenharmony_ci// default; pass 0 as bootable to remove the flag. 1072cf200d32Sopenharmony_ci// Returns 1 if successful, 0 if not (invalid partition number) 1073cf200d32Sopenharmony_ciint BasicMBRData::SetPartBootable(int num, int bootable) { 1074cf200d32Sopenharmony_ci int allOK = 1; 1075cf200d32Sopenharmony_ci 1076cf200d32Sopenharmony_ci if ((num >= 0) && (num < MAX_MBR_PARTS)) { 1077cf200d32Sopenharmony_ci if (partitions[num].GetLengthLBA() != UINT32_C(0)) { 1078cf200d32Sopenharmony_ci if (bootable == 0) 1079cf200d32Sopenharmony_ci partitions[num].SetStatus(UINT8_C(0x00)); 1080cf200d32Sopenharmony_ci else 1081cf200d32Sopenharmony_ci partitions[num].SetStatus(UINT8_C(0x80)); 1082cf200d32Sopenharmony_ci } else allOK = 0; 1083cf200d32Sopenharmony_ci } else allOK = 0; 1084cf200d32Sopenharmony_ci return allOK; 1085cf200d32Sopenharmony_ci} // BasicMBRData::SetPartBootable() 1086cf200d32Sopenharmony_ci 1087cf200d32Sopenharmony_ci// Create a partition that fills the most available space. Returns 1088cf200d32Sopenharmony_ci// 1 if partition was created, 0 otherwise. Intended for use in 1089cf200d32Sopenharmony_ci// creating hybrid MBRs. 1090cf200d32Sopenharmony_ciint BasicMBRData::MakeBiggestPart(int i, int type) { 1091cf200d32Sopenharmony_ci uint64_t start = UINT64_C(1); // starting point for each search 1092cf200d32Sopenharmony_ci uint64_t firstBlock; // first block in a segment 1093cf200d32Sopenharmony_ci uint64_t lastBlock; // last block in a segment 1094cf200d32Sopenharmony_ci uint64_t segmentSize; // size of segment in blocks 1095cf200d32Sopenharmony_ci uint64_t selectedSegment = UINT64_C(0); // location of largest segment 1096cf200d32Sopenharmony_ci uint64_t selectedSize = UINT64_C(0); // size of largest segment in blocks 1097cf200d32Sopenharmony_ci int found = 0; 1098cf200d32Sopenharmony_ci string anything; 1099cf200d32Sopenharmony_ci 1100cf200d32Sopenharmony_ci do { 1101cf200d32Sopenharmony_ci firstBlock = FindFirstAvailable(start); 1102cf200d32Sopenharmony_ci if (firstBlock > UINT64_C(0)) { // something's free... 1103cf200d32Sopenharmony_ci lastBlock = FindLastInFree(firstBlock); 1104cf200d32Sopenharmony_ci segmentSize = lastBlock - firstBlock + UINT64_C(1); 1105cf200d32Sopenharmony_ci if (segmentSize > selectedSize) { 1106cf200d32Sopenharmony_ci selectedSize = segmentSize; 1107cf200d32Sopenharmony_ci selectedSegment = firstBlock; 1108cf200d32Sopenharmony_ci } // if 1109cf200d32Sopenharmony_ci start = lastBlock + 1; 1110cf200d32Sopenharmony_ci } // if 1111cf200d32Sopenharmony_ci } while (firstBlock != 0); 1112cf200d32Sopenharmony_ci if ((selectedSize > UINT64_C(0)) && (selectedSize < diskSize)) { 1113cf200d32Sopenharmony_ci found = 1; 1114cf200d32Sopenharmony_ci MakePart(i, selectedSegment, selectedSize, type, 0); 1115cf200d32Sopenharmony_ci } else { 1116cf200d32Sopenharmony_ci found = 0; 1117cf200d32Sopenharmony_ci } // if/else 1118cf200d32Sopenharmony_ci return found; 1119cf200d32Sopenharmony_ci} // BasicMBRData::MakeBiggestPart(int i) 1120cf200d32Sopenharmony_ci 1121cf200d32Sopenharmony_ci// Delete partition #i 1122cf200d32Sopenharmony_civoid BasicMBRData::DeletePartition(int i) { 1123cf200d32Sopenharmony_ci partitions[i].Empty(); 1124cf200d32Sopenharmony_ci} // BasicMBRData::DeletePartition() 1125cf200d32Sopenharmony_ci 1126cf200d32Sopenharmony_ci// Set the inclusion status (PRIMARY, LOGICAL, or NONE) with some sanity 1127cf200d32Sopenharmony_ci// checks to ensure the table remains legal. 1128cf200d32Sopenharmony_ci// Returns 1 on success, 0 on failure. 1129cf200d32Sopenharmony_ciint BasicMBRData::SetInclusionwChecks(int num, int inclStatus) { 1130cf200d32Sopenharmony_ci int allOK = 1, origValue; 1131cf200d32Sopenharmony_ci 1132cf200d32Sopenharmony_ci if (IsLegal()) { 1133cf200d32Sopenharmony_ci if ((inclStatus == PRIMARY) || (inclStatus == LOGICAL) || (inclStatus == NONE)) { 1134cf200d32Sopenharmony_ci origValue = partitions[num].GetInclusion(); 1135cf200d32Sopenharmony_ci partitions[num].SetInclusion(inclStatus); 1136cf200d32Sopenharmony_ci if (!IsLegal()) { 1137cf200d32Sopenharmony_ci partitions[num].SetInclusion(origValue); 1138cf200d32Sopenharmony_ci cerr << "Specified change is not legal! Aborting change!\n"; 1139cf200d32Sopenharmony_ci } // if 1140cf200d32Sopenharmony_ci } else { 1141cf200d32Sopenharmony_ci cerr << "Invalid partition inclusion code in BasicMBRData::SetInclusionwChecks()!\n"; 1142cf200d32Sopenharmony_ci } // if/else 1143cf200d32Sopenharmony_ci } else { 1144cf200d32Sopenharmony_ci cerr << "Partition table is not currently in a valid state. Aborting change!\n"; 1145cf200d32Sopenharmony_ci allOK = 0; 1146cf200d32Sopenharmony_ci } // if/else 1147cf200d32Sopenharmony_ci return allOK; 1148cf200d32Sopenharmony_ci} // BasicMBRData::SetInclusionwChecks() 1149cf200d32Sopenharmony_ci 1150cf200d32Sopenharmony_ci// Recomputes the CHS values for the specified partition and adjusts the value. 1151cf200d32Sopenharmony_ci// Note that this will create a technically incorrect CHS value for EFI GPT (0xEE) 1152cf200d32Sopenharmony_ci// protective partitions, but this is required by some buggy BIOSes, so I'm 1153cf200d32Sopenharmony_ci// providing a function to do this deliberately at the user's command. 1154cf200d32Sopenharmony_ci// This function does nothing if the partition's length is 0. 1155cf200d32Sopenharmony_civoid BasicMBRData::RecomputeCHS(int partNum) { 1156cf200d32Sopenharmony_ci partitions[partNum].RecomputeCHS(); 1157cf200d32Sopenharmony_ci} // BasicMBRData::RecomputeCHS() 1158cf200d32Sopenharmony_ci 1159cf200d32Sopenharmony_ci// Sorts the partitions starting with partition #start. This function 1160cf200d32Sopenharmony_ci// does NOT pay attention to primary/logical assignment, which is 1161cf200d32Sopenharmony_ci// critical when writing the partitions. 1162cf200d32Sopenharmony_civoid BasicMBRData::SortMBR(int start) { 1163cf200d32Sopenharmony_ci if ((start < MAX_MBR_PARTS) && (start >= 0)) 1164cf200d32Sopenharmony_ci sort(partitions + start, partitions + MAX_MBR_PARTS); 1165cf200d32Sopenharmony_ci} // BasicMBRData::SortMBR() 1166cf200d32Sopenharmony_ci 1167cf200d32Sopenharmony_ci// Delete any partitions that are too big to fit on the disk 1168cf200d32Sopenharmony_ci// or that are too big for MBR (32-bit limits). 1169cf200d32Sopenharmony_ci// This deletes the partitions by setting values to 0, not just 1170cf200d32Sopenharmony_ci// by setting them as being omitted. 1171cf200d32Sopenharmony_ci// Returns the number of partitions deleted in this way. 1172cf200d32Sopenharmony_ciint BasicMBRData::DeleteOversizedParts() { 1173cf200d32Sopenharmony_ci int num = 0, i; 1174cf200d32Sopenharmony_ci 1175cf200d32Sopenharmony_ci for (i = 0; i < MAX_MBR_PARTS; i++) { 1176cf200d32Sopenharmony_ci if ((partitions[i].GetStartLBA() > diskSize) || (partitions[i].GetLastLBA() > diskSize) || 1177cf200d32Sopenharmony_ci (partitions[i].GetStartLBA() > UINT32_MAX) || (partitions[i].GetLengthLBA() > UINT32_MAX)) { 1178cf200d32Sopenharmony_ci cerr << "\aWarning: Deleting oversized partition #" << i + 1 << "! Start = " 1179cf200d32Sopenharmony_ci << partitions[i].GetStartLBA() << ", length = " << partitions[i].GetLengthLBA() << "\n"; 1180cf200d32Sopenharmony_ci partitions[i].Empty(); 1181cf200d32Sopenharmony_ci num++; 1182cf200d32Sopenharmony_ci } // if 1183cf200d32Sopenharmony_ci } // for 1184cf200d32Sopenharmony_ci return num; 1185cf200d32Sopenharmony_ci} // BasicMBRData::DeleteOversizedParts() 1186cf200d32Sopenharmony_ci 1187cf200d32Sopenharmony_ci// Search for and delete extended partitions. 1188cf200d32Sopenharmony_ci// Returns the number of partitions deleted. 1189cf200d32Sopenharmony_ciint BasicMBRData::DeleteExtendedParts() { 1190cf200d32Sopenharmony_ci int i, numDeleted = 0; 1191cf200d32Sopenharmony_ci uint8_t type; 1192cf200d32Sopenharmony_ci 1193cf200d32Sopenharmony_ci for (i = 0; i < MAX_MBR_PARTS; i++) { 1194cf200d32Sopenharmony_ci type = partitions[i].GetType(); 1195cf200d32Sopenharmony_ci if (((type == 0x05) || (type == 0x0f) || (type == (0x85))) && 1196cf200d32Sopenharmony_ci (partitions[i].GetLengthLBA() > 0)) { 1197cf200d32Sopenharmony_ci partitions[i].Empty(); 1198cf200d32Sopenharmony_ci numDeleted++; 1199cf200d32Sopenharmony_ci } // if 1200cf200d32Sopenharmony_ci } // for 1201cf200d32Sopenharmony_ci return numDeleted; 1202cf200d32Sopenharmony_ci} // BasicMBRData::DeleteExtendedParts() 1203cf200d32Sopenharmony_ci 1204cf200d32Sopenharmony_ci// Finds any overlapping partitions and omits the smaller of the two. 1205cf200d32Sopenharmony_civoid BasicMBRData::OmitOverlaps() { 1206cf200d32Sopenharmony_ci int i, j; 1207cf200d32Sopenharmony_ci 1208cf200d32Sopenharmony_ci for (i = 0; i < MAX_MBR_PARTS; i++) { 1209cf200d32Sopenharmony_ci for (j = i + 1; j < MAX_MBR_PARTS; j++) { 1210cf200d32Sopenharmony_ci if ((partitions[i].GetInclusion() != NONE) && 1211cf200d32Sopenharmony_ci partitions[i].DoTheyOverlap(partitions[j])) { 1212cf200d32Sopenharmony_ci if (partitions[i].GetLengthLBA() < partitions[j].GetLengthLBA()) 1213cf200d32Sopenharmony_ci partitions[i].SetInclusion(NONE); 1214cf200d32Sopenharmony_ci else 1215cf200d32Sopenharmony_ci partitions[j].SetInclusion(NONE); 1216cf200d32Sopenharmony_ci } // if 1217cf200d32Sopenharmony_ci } // for (j...) 1218cf200d32Sopenharmony_ci } // for (i...) 1219cf200d32Sopenharmony_ci} // BasicMBRData::OmitOverlaps() 1220cf200d32Sopenharmony_ci 1221cf200d32Sopenharmony_ci// Convert as many partitions into logicals as possible, except for 1222cf200d32Sopenharmony_ci// the first partition, if possible. 1223cf200d32Sopenharmony_civoid BasicMBRData::MaximizeLogicals() { 1224cf200d32Sopenharmony_ci int earliestPart = 0, earliestPartWas = NONE, i; 1225cf200d32Sopenharmony_ci 1226cf200d32Sopenharmony_ci for (i = MAX_MBR_PARTS - 1; i >= 0; i--) { 1227cf200d32Sopenharmony_ci UpdateCanBeLogical(); 1228cf200d32Sopenharmony_ci earliestPart = i; 1229cf200d32Sopenharmony_ci if (partitions[i].CanBeLogical()) { 1230cf200d32Sopenharmony_ci partitions[i].SetInclusion(LOGICAL); 1231cf200d32Sopenharmony_ci } else if (partitions[i].CanBePrimary()) { 1232cf200d32Sopenharmony_ci partitions[i].SetInclusion(PRIMARY); 1233cf200d32Sopenharmony_ci } else { 1234cf200d32Sopenharmony_ci partitions[i].SetInclusion(NONE); 1235cf200d32Sopenharmony_ci } // if/elseif/else 1236cf200d32Sopenharmony_ci } // for 1237cf200d32Sopenharmony_ci // If we have spare primaries, convert back the earliest partition to 1238cf200d32Sopenharmony_ci // its original state.... 1239cf200d32Sopenharmony_ci if ((NumPrimaries() < 4) && (partitions[earliestPart].GetInclusion() == LOGICAL)) 1240cf200d32Sopenharmony_ci partitions[earliestPart].SetInclusion(earliestPartWas); 1241cf200d32Sopenharmony_ci} // BasicMBRData::MaximizeLogicals() 1242cf200d32Sopenharmony_ci 1243cf200d32Sopenharmony_ci// Add primaries up to the maximum allowed, from the omitted category. 1244cf200d32Sopenharmony_civoid BasicMBRData::MaximizePrimaries() { 1245cf200d32Sopenharmony_ci int num, i = 0; 1246cf200d32Sopenharmony_ci 1247cf200d32Sopenharmony_ci num = NumPrimaries(); 1248cf200d32Sopenharmony_ci while ((num < 4) && (i < MAX_MBR_PARTS)) { 1249cf200d32Sopenharmony_ci if ((partitions[i].GetInclusion() == NONE) && (partitions[i].CanBePrimary())) { 1250cf200d32Sopenharmony_ci partitions[i].SetInclusion(PRIMARY); 1251cf200d32Sopenharmony_ci num++; 1252cf200d32Sopenharmony_ci UpdateCanBeLogical(); 1253cf200d32Sopenharmony_ci } // if 1254cf200d32Sopenharmony_ci i++; 1255cf200d32Sopenharmony_ci } // while 1256cf200d32Sopenharmony_ci} // BasicMBRData::MaximizePrimaries() 1257cf200d32Sopenharmony_ci 1258cf200d32Sopenharmony_ci// Remove primary partitions in excess of 4, starting with the later ones, 1259cf200d32Sopenharmony_ci// in terms of the array location.... 1260cf200d32Sopenharmony_civoid BasicMBRData::TrimPrimaries(void) { 1261cf200d32Sopenharmony_ci int numToDelete, i = MAX_MBR_PARTS - 1; 1262cf200d32Sopenharmony_ci 1263cf200d32Sopenharmony_ci numToDelete = NumPrimaries() - 4; 1264cf200d32Sopenharmony_ci while ((numToDelete > 0) && (i >= 0)) { 1265cf200d32Sopenharmony_ci if (partitions[i].GetInclusion() == PRIMARY) { 1266cf200d32Sopenharmony_ci partitions[i].SetInclusion(NONE); 1267cf200d32Sopenharmony_ci numToDelete--; 1268cf200d32Sopenharmony_ci } // if 1269cf200d32Sopenharmony_ci i--; 1270cf200d32Sopenharmony_ci } // while (numToDelete > 0) 1271cf200d32Sopenharmony_ci} // BasicMBRData::TrimPrimaries() 1272cf200d32Sopenharmony_ci 1273cf200d32Sopenharmony_ci// Locates primary partitions located between logical partitions and 1274cf200d32Sopenharmony_ci// either converts the primaries into logicals (if possible) or omits 1275cf200d32Sopenharmony_ci// them. 1276cf200d32Sopenharmony_civoid BasicMBRData::MakeLogicalsContiguous(void) { 1277cf200d32Sopenharmony_ci uint64_t firstLogicalLBA, lastLogicalLBA; 1278cf200d32Sopenharmony_ci int i; 1279cf200d32Sopenharmony_ci 1280cf200d32Sopenharmony_ci firstLogicalLBA = FirstLogicalLBA(); 1281cf200d32Sopenharmony_ci lastLogicalLBA = LastLogicalLBA(); 1282cf200d32Sopenharmony_ci for (i = 0; i < MAX_MBR_PARTS; i++) { 1283cf200d32Sopenharmony_ci if ((partitions[i].GetInclusion() == PRIMARY) && 1284cf200d32Sopenharmony_ci (partitions[i].GetStartLBA() >= firstLogicalLBA) && 1285cf200d32Sopenharmony_ci (partitions[i].GetLastLBA() <= lastLogicalLBA)) { 1286cf200d32Sopenharmony_ci if (SectorUsedAs(partitions[i].GetStartLBA() - 1) == NONE) 1287cf200d32Sopenharmony_ci partitions[i].SetInclusion(LOGICAL); 1288cf200d32Sopenharmony_ci else 1289cf200d32Sopenharmony_ci partitions[i].SetInclusion(NONE); 1290cf200d32Sopenharmony_ci } // if 1291cf200d32Sopenharmony_ci } // for 1292cf200d32Sopenharmony_ci} // BasicMBRData::MakeLogicalsContiguous() 1293cf200d32Sopenharmony_ci 1294cf200d32Sopenharmony_ci// If MBR data aren't legal, adjust primary/logical assignments and, 1295cf200d32Sopenharmony_ci// if necessary, drop partitions, to make the data legal. 1296cf200d32Sopenharmony_civoid BasicMBRData::MakeItLegal(void) { 1297cf200d32Sopenharmony_ci if (!IsLegal()) { 1298cf200d32Sopenharmony_ci DeleteOversizedParts(); 1299cf200d32Sopenharmony_ci MaximizeLogicals(); 1300cf200d32Sopenharmony_ci MaximizePrimaries(); 1301cf200d32Sopenharmony_ci if (!AreLogicalsContiguous()) 1302cf200d32Sopenharmony_ci MakeLogicalsContiguous(); 1303cf200d32Sopenharmony_ci if (NumPrimaries() > 4) 1304cf200d32Sopenharmony_ci TrimPrimaries(); 1305cf200d32Sopenharmony_ci OmitOverlaps(); 1306cf200d32Sopenharmony_ci } // if 1307cf200d32Sopenharmony_ci} // BasicMBRData::MakeItLegal() 1308cf200d32Sopenharmony_ci 1309cf200d32Sopenharmony_ci// Removes logical partitions and deactivated partitions from first four 1310cf200d32Sopenharmony_ci// entries (primary space). 1311cf200d32Sopenharmony_ci// Returns the number of partitions moved. 1312cf200d32Sopenharmony_ciint BasicMBRData::RemoveLogicalsFromFirstFour(void) { 1313cf200d32Sopenharmony_ci int i, j, numMoved = 0, swapped = 0; 1314cf200d32Sopenharmony_ci MBRPart temp; 1315cf200d32Sopenharmony_ci 1316cf200d32Sopenharmony_ci for (i = 0; i < 4; i++) { 1317cf200d32Sopenharmony_ci if ((partitions[i].GetInclusion() != PRIMARY) && (partitions[i].GetLengthLBA() > 0)) { 1318cf200d32Sopenharmony_ci j = 4; 1319cf200d32Sopenharmony_ci swapped = 0; 1320cf200d32Sopenharmony_ci do { 1321cf200d32Sopenharmony_ci if ((partitions[j].GetInclusion() == NONE) && (partitions[j].GetLengthLBA() == 0)) { 1322cf200d32Sopenharmony_ci temp = partitions[j]; 1323cf200d32Sopenharmony_ci partitions[j] = partitions[i]; 1324cf200d32Sopenharmony_ci partitions[i] = temp; 1325cf200d32Sopenharmony_ci swapped = 1; 1326cf200d32Sopenharmony_ci numMoved++; 1327cf200d32Sopenharmony_ci } // if 1328cf200d32Sopenharmony_ci j++; 1329cf200d32Sopenharmony_ci } while ((j < MAX_MBR_PARTS) && !swapped); 1330cf200d32Sopenharmony_ci if (j >= MAX_MBR_PARTS) 1331cf200d32Sopenharmony_ci cerr << "Warning! Too many partitions in BasicMBRData::RemoveLogicalsFromFirstFour()!\n"; 1332cf200d32Sopenharmony_ci } // if 1333cf200d32Sopenharmony_ci } // for i... 1334cf200d32Sopenharmony_ci return numMoved; 1335cf200d32Sopenharmony_ci} // BasicMBRData::RemoveLogicalsFromFirstFour() 1336cf200d32Sopenharmony_ci 1337cf200d32Sopenharmony_ci// Move all primaries into the first four partition spaces 1338cf200d32Sopenharmony_ci// Returns the number of partitions moved. 1339cf200d32Sopenharmony_ciint BasicMBRData::MovePrimariesToFirstFour(void) { 1340cf200d32Sopenharmony_ci int i, j = 0, numMoved = 0, swapped = 0; 1341cf200d32Sopenharmony_ci MBRPart temp; 1342cf200d32Sopenharmony_ci 1343cf200d32Sopenharmony_ci for (i = 4; i < MAX_MBR_PARTS; i++) { 1344cf200d32Sopenharmony_ci if (partitions[i].GetInclusion() == PRIMARY) { 1345cf200d32Sopenharmony_ci j = 0; 1346cf200d32Sopenharmony_ci swapped = 0; 1347cf200d32Sopenharmony_ci do { 1348cf200d32Sopenharmony_ci if (partitions[j].GetInclusion() != PRIMARY) { 1349cf200d32Sopenharmony_ci temp = partitions[j]; 1350cf200d32Sopenharmony_ci partitions[j] = partitions[i]; 1351cf200d32Sopenharmony_ci partitions[i] = temp; 1352cf200d32Sopenharmony_ci swapped = 1; 1353cf200d32Sopenharmony_ci numMoved++; 1354cf200d32Sopenharmony_ci } // if 1355cf200d32Sopenharmony_ci j++; 1356cf200d32Sopenharmony_ci } while ((j < 4) && !swapped); 1357cf200d32Sopenharmony_ci } // if 1358cf200d32Sopenharmony_ci } // for 1359cf200d32Sopenharmony_ci return numMoved; 1360cf200d32Sopenharmony_ci} // BasicMBRData::MovePrimariesToFirstFour() 1361cf200d32Sopenharmony_ci 1362cf200d32Sopenharmony_ci// Create an extended partition, if necessary, to hold the logical partitions. 1363cf200d32Sopenharmony_ci// This function also sorts the primaries into the first four positions of 1364cf200d32Sopenharmony_ci// the table. 1365cf200d32Sopenharmony_ci// Returns 1 on success, 0 on failure. 1366cf200d32Sopenharmony_ciint BasicMBRData::CreateExtended(void) { 1367cf200d32Sopenharmony_ci int allOK = 1, i = 0, swapped = 0; 1368cf200d32Sopenharmony_ci MBRPart temp; 1369cf200d32Sopenharmony_ci 1370cf200d32Sopenharmony_ci if (IsLegal()) { 1371cf200d32Sopenharmony_ci // Move logicals out of primary space... 1372cf200d32Sopenharmony_ci RemoveLogicalsFromFirstFour(); 1373cf200d32Sopenharmony_ci // Move primaries out of logical space... 1374cf200d32Sopenharmony_ci MovePrimariesToFirstFour(); 1375cf200d32Sopenharmony_ci 1376cf200d32Sopenharmony_ci // Create the extended partition 1377cf200d32Sopenharmony_ci if (NumLogicals() > 0) { 1378cf200d32Sopenharmony_ci SortMBR(4); // sort starting from 4 -- that is, logicals only 1379cf200d32Sopenharmony_ci temp.Empty(); 1380cf200d32Sopenharmony_ci temp.SetStartLBA(FirstLogicalLBA() - 1); 1381cf200d32Sopenharmony_ci temp.SetLengthLBA(LastLogicalLBA() - FirstLogicalLBA() + 2); 1382cf200d32Sopenharmony_ci temp.SetType(0x0f, 1); 1383cf200d32Sopenharmony_ci temp.SetInclusion(PRIMARY); 1384cf200d32Sopenharmony_ci do { 1385cf200d32Sopenharmony_ci if ((partitions[i].GetInclusion() == NONE) || (partitions[i].GetLengthLBA() == 0)) { 1386cf200d32Sopenharmony_ci partitions[i] = temp; 1387cf200d32Sopenharmony_ci swapped = 1; 1388cf200d32Sopenharmony_ci } // if 1389cf200d32Sopenharmony_ci i++; 1390cf200d32Sopenharmony_ci } while ((i < 4) && !swapped); 1391cf200d32Sopenharmony_ci if (!swapped) { 1392cf200d32Sopenharmony_ci cerr << "Could not create extended partition; no room in primary table!\n"; 1393cf200d32Sopenharmony_ci allOK = 0; 1394cf200d32Sopenharmony_ci } // if 1395cf200d32Sopenharmony_ci } // if (NumLogicals() > 0) 1396cf200d32Sopenharmony_ci } else allOK = 0; 1397cf200d32Sopenharmony_ci // Do a final check for EFI GPT (0xEE) partitions & flag as a problem if found 1398cf200d32Sopenharmony_ci // along with an extended partition 1399cf200d32Sopenharmony_ci for (i = 0; i < MAX_MBR_PARTS; i++) 1400cf200d32Sopenharmony_ci if (swapped && partitions[i].GetType() == 0xEE) 1401cf200d32Sopenharmony_ci allOK = 0; 1402cf200d32Sopenharmony_ci return allOK; 1403cf200d32Sopenharmony_ci} // BasicMBRData::CreateExtended() 1404cf200d32Sopenharmony_ci 1405cf200d32Sopenharmony_ci/**************************************** 1406cf200d32Sopenharmony_ci * * 1407cf200d32Sopenharmony_ci * Functions to find data on free space * 1408cf200d32Sopenharmony_ci * * 1409cf200d32Sopenharmony_ci ****************************************/ 1410cf200d32Sopenharmony_ci 1411cf200d32Sopenharmony_ci// Finds the first free space on the disk from start onward; returns 0 1412cf200d32Sopenharmony_ci// if none available.... 1413cf200d32Sopenharmony_ciuint64_t BasicMBRData::FindFirstAvailable(uint64_t start) { 1414cf200d32Sopenharmony_ci uint64_t first; 1415cf200d32Sopenharmony_ci uint64_t i; 1416cf200d32Sopenharmony_ci int firstMoved; 1417cf200d32Sopenharmony_ci 1418cf200d32Sopenharmony_ci if ((start >= (UINT32_MAX - 1)) || (start >= (diskSize - 1))) 1419cf200d32Sopenharmony_ci return 0; 1420cf200d32Sopenharmony_ci 1421cf200d32Sopenharmony_ci first = start; 1422cf200d32Sopenharmony_ci 1423cf200d32Sopenharmony_ci // ...now search through all partitions; if first is within an 1424cf200d32Sopenharmony_ci // existing partition, move it to the next sector after that 1425cf200d32Sopenharmony_ci // partition and repeat. If first was moved, set firstMoved 1426cf200d32Sopenharmony_ci // flag; repeat until firstMoved is not set, so as to catch 1427cf200d32Sopenharmony_ci // cases where partitions are out of sequential order.... 1428cf200d32Sopenharmony_ci do { 1429cf200d32Sopenharmony_ci firstMoved = 0; 1430cf200d32Sopenharmony_ci for (i = 0; i < 4; i++) { 1431cf200d32Sopenharmony_ci // Check if it's in the existing partition 1432cf200d32Sopenharmony_ci if ((first >= partitions[i].GetStartLBA()) && 1433cf200d32Sopenharmony_ci (first < (partitions[i].GetStartLBA() + partitions[i].GetLengthLBA()))) { 1434cf200d32Sopenharmony_ci first = partitions[i].GetStartLBA() + partitions[i].GetLengthLBA(); 1435cf200d32Sopenharmony_ci firstMoved = 1; 1436cf200d32Sopenharmony_ci } // if 1437cf200d32Sopenharmony_ci } // for 1438cf200d32Sopenharmony_ci } while (firstMoved == 1); 1439cf200d32Sopenharmony_ci if ((first >= diskSize) || (first > UINT32_MAX)) 1440cf200d32Sopenharmony_ci first = 0; 1441cf200d32Sopenharmony_ci return (first); 1442cf200d32Sopenharmony_ci} // BasicMBRData::FindFirstAvailable() 1443cf200d32Sopenharmony_ci 1444cf200d32Sopenharmony_ci// Finds the last free sector on the disk from start forward. 1445cf200d32Sopenharmony_ciuint64_t BasicMBRData::FindLastInFree(uint64_t start) { 1446cf200d32Sopenharmony_ci uint64_t nearestStart; 1447cf200d32Sopenharmony_ci uint64_t i; 1448cf200d32Sopenharmony_ci 1449cf200d32Sopenharmony_ci if ((diskSize <= UINT32_MAX) && (diskSize > 0)) 1450cf200d32Sopenharmony_ci nearestStart = diskSize - 1; 1451cf200d32Sopenharmony_ci else 1452cf200d32Sopenharmony_ci nearestStart = UINT32_MAX - 1; 1453cf200d32Sopenharmony_ci 1454cf200d32Sopenharmony_ci for (i = 0; i < 4; i++) { 1455cf200d32Sopenharmony_ci if ((nearestStart > partitions[i].GetStartLBA()) && 1456cf200d32Sopenharmony_ci (partitions[i].GetStartLBA() > start)) { 1457cf200d32Sopenharmony_ci nearestStart = partitions[i].GetStartLBA() - 1; 1458cf200d32Sopenharmony_ci } // if 1459cf200d32Sopenharmony_ci } // for 1460cf200d32Sopenharmony_ci return (nearestStart); 1461cf200d32Sopenharmony_ci} // BasicMBRData::FindLastInFree() 1462cf200d32Sopenharmony_ci 1463cf200d32Sopenharmony_ci// Finds the first free sector on the disk from start backward. 1464cf200d32Sopenharmony_ciuint64_t BasicMBRData::FindFirstInFree(uint64_t start) { 1465cf200d32Sopenharmony_ci uint64_t bestLastLBA, thisLastLBA; 1466cf200d32Sopenharmony_ci int i; 1467cf200d32Sopenharmony_ci 1468cf200d32Sopenharmony_ci bestLastLBA = 1; 1469cf200d32Sopenharmony_ci for (i = 0; i < 4; i++) { 1470cf200d32Sopenharmony_ci thisLastLBA = partitions[i].GetLastLBA() + 1; 1471cf200d32Sopenharmony_ci if (thisLastLBA > 0) 1472cf200d32Sopenharmony_ci thisLastLBA--; 1473cf200d32Sopenharmony_ci if ((thisLastLBA > bestLastLBA) && (thisLastLBA < start)) 1474cf200d32Sopenharmony_ci bestLastLBA = thisLastLBA + 1; 1475cf200d32Sopenharmony_ci } // for 1476cf200d32Sopenharmony_ci return (bestLastLBA); 1477cf200d32Sopenharmony_ci} // BasicMBRData::FindFirstInFree() 1478cf200d32Sopenharmony_ci 1479cf200d32Sopenharmony_ci// Returns NONE (unused), PRIMARY, LOGICAL, EBR (for EBR or MBR), or INVALID. 1480cf200d32Sopenharmony_ci// Note: If the sector immediately before a logical partition is in use by 1481cf200d32Sopenharmony_ci// another partition, this function returns PRIMARY or LOGICAL for that 1482cf200d32Sopenharmony_ci// sector, rather than EBR. 1483cf200d32Sopenharmony_ciint BasicMBRData::SectorUsedAs(uint64_t sector, int topPartNum) { 1484cf200d32Sopenharmony_ci int i = 0, usedAs = NONE; 1485cf200d32Sopenharmony_ci 1486cf200d32Sopenharmony_ci do { 1487cf200d32Sopenharmony_ci if ((partitions[i].GetStartLBA() <= sector) && (partitions[i].GetLastLBA() >= sector)) 1488cf200d32Sopenharmony_ci usedAs = partitions[i].GetInclusion(); 1489cf200d32Sopenharmony_ci if ((partitions[i].GetStartLBA() == (sector + 1)) && (partitions[i].GetInclusion() == LOGICAL)) 1490cf200d32Sopenharmony_ci usedAs = EBR; 1491cf200d32Sopenharmony_ci if (sector == 0) 1492cf200d32Sopenharmony_ci usedAs = EBR; 1493cf200d32Sopenharmony_ci if (sector >= diskSize) 1494cf200d32Sopenharmony_ci usedAs = INVALID; 1495cf200d32Sopenharmony_ci i++; 1496cf200d32Sopenharmony_ci } while ((i < topPartNum) && ((usedAs == NONE) || (usedAs == EBR))); 1497cf200d32Sopenharmony_ci return usedAs; 1498cf200d32Sopenharmony_ci} // BasicMBRData::SectorUsedAs() 1499cf200d32Sopenharmony_ci 1500cf200d32Sopenharmony_ci/****************************************************** 1501cf200d32Sopenharmony_ci * * 1502cf200d32Sopenharmony_ci * Functions that extract data on specific partitions * 1503cf200d32Sopenharmony_ci * * 1504cf200d32Sopenharmony_ci ******************************************************/ 1505cf200d32Sopenharmony_ci 1506cf200d32Sopenharmony_ciuint8_t BasicMBRData::GetStatus(int i) { 1507cf200d32Sopenharmony_ci MBRPart* thePart; 1508cf200d32Sopenharmony_ci uint8_t retval; 1509cf200d32Sopenharmony_ci 1510cf200d32Sopenharmony_ci thePart = GetPartition(i); 1511cf200d32Sopenharmony_ci if (thePart != NULL) 1512cf200d32Sopenharmony_ci retval = thePart->GetStatus(); 1513cf200d32Sopenharmony_ci else 1514cf200d32Sopenharmony_ci retval = UINT8_C(0); 1515cf200d32Sopenharmony_ci return retval; 1516cf200d32Sopenharmony_ci} // BasicMBRData::GetStatus() 1517cf200d32Sopenharmony_ci 1518cf200d32Sopenharmony_ciuint8_t BasicMBRData::GetType(int i) { 1519cf200d32Sopenharmony_ci MBRPart* thePart; 1520cf200d32Sopenharmony_ci uint8_t retval; 1521cf200d32Sopenharmony_ci 1522cf200d32Sopenharmony_ci thePart = GetPartition(i); 1523cf200d32Sopenharmony_ci if (thePart != NULL) 1524cf200d32Sopenharmony_ci retval = thePart->GetType(); 1525cf200d32Sopenharmony_ci else 1526cf200d32Sopenharmony_ci retval = UINT8_C(0); 1527cf200d32Sopenharmony_ci return retval; 1528cf200d32Sopenharmony_ci} // BasicMBRData::GetType() 1529cf200d32Sopenharmony_ci 1530cf200d32Sopenharmony_ciuint64_t BasicMBRData::GetFirstSector(int i) { 1531cf200d32Sopenharmony_ci MBRPart* thePart; 1532cf200d32Sopenharmony_ci uint64_t retval; 1533cf200d32Sopenharmony_ci 1534cf200d32Sopenharmony_ci thePart = GetPartition(i); 1535cf200d32Sopenharmony_ci if (thePart != NULL) 1536cf200d32Sopenharmony_ci retval = thePart->GetStartLBA(); 1537cf200d32Sopenharmony_ci else 1538cf200d32Sopenharmony_ci retval = UINT32_C(0); 1539cf200d32Sopenharmony_ci return retval; 1540cf200d32Sopenharmony_ci} // BasicMBRData::GetFirstSector() 1541cf200d32Sopenharmony_ci 1542cf200d32Sopenharmony_ciuint64_t BasicMBRData::GetLength(int i) { 1543cf200d32Sopenharmony_ci MBRPart* thePart; 1544cf200d32Sopenharmony_ci uint64_t retval; 1545cf200d32Sopenharmony_ci 1546cf200d32Sopenharmony_ci thePart = GetPartition(i); 1547cf200d32Sopenharmony_ci if (thePart != NULL) 1548cf200d32Sopenharmony_ci retval = thePart->GetLengthLBA(); 1549cf200d32Sopenharmony_ci else 1550cf200d32Sopenharmony_ci retval = UINT64_C(0); 1551cf200d32Sopenharmony_ci return retval; 1552cf200d32Sopenharmony_ci} // BasicMBRData::GetLength() 1553cf200d32Sopenharmony_ci 1554cf200d32Sopenharmony_ci/*********************** 1555cf200d32Sopenharmony_ci * * 1556cf200d32Sopenharmony_ci * Protected functions * 1557cf200d32Sopenharmony_ci * * 1558cf200d32Sopenharmony_ci ***********************/ 1559cf200d32Sopenharmony_ci 1560cf200d32Sopenharmony_ci// Return a pointer to a primary or logical partition, or NULL if 1561cf200d32Sopenharmony_ci// the partition is out of range.... 1562cf200d32Sopenharmony_ciMBRPart* BasicMBRData::GetPartition(int i) { 1563cf200d32Sopenharmony_ci MBRPart* thePart = NULL; 1564cf200d32Sopenharmony_ci 1565cf200d32Sopenharmony_ci if ((i >= 0) && (i < MAX_MBR_PARTS)) 1566cf200d32Sopenharmony_ci thePart = &partitions[i]; 1567cf200d32Sopenharmony_ci return thePart; 1568cf200d32Sopenharmony_ci} // GetPartition() 1569cf200d32Sopenharmony_ci 1570cf200d32Sopenharmony_ci/******************************************* 1571cf200d32Sopenharmony_ci * * 1572cf200d32Sopenharmony_ci * Functions that involve user interaction * 1573cf200d32Sopenharmony_ci * * 1574cf200d32Sopenharmony_ci *******************************************/ 1575cf200d32Sopenharmony_ci 1576cf200d32Sopenharmony_ci// Present the MBR operations menu. Note that the 'w' option does not 1577cf200d32Sopenharmony_ci// immediately write data; that's handled by the calling function. 1578cf200d32Sopenharmony_ci// Returns the number of partitions defined on exit, or -1 if the 1579cf200d32Sopenharmony_ci// user selected the 'q' option. (Thus, the caller should save data 1580cf200d32Sopenharmony_ci// if the return value is >0, or possibly >=0 depending on intentions.) 1581cf200d32Sopenharmony_ciint BasicMBRData::DoMenu(const string& prompt) { 1582cf200d32Sopenharmony_ci int goOn = 1, quitting = 0, retval, num, haveShownInfo = 0; 1583cf200d32Sopenharmony_ci unsigned int hexCode; 1584cf200d32Sopenharmony_ci string tempStr; 1585cf200d32Sopenharmony_ci 1586cf200d32Sopenharmony_ci do { 1587cf200d32Sopenharmony_ci cout << prompt; 1588cf200d32Sopenharmony_ci switch (ReadString()[0]) { 1589cf200d32Sopenharmony_ci case '\0': 1590cf200d32Sopenharmony_ci goOn = cin.good(); 1591cf200d32Sopenharmony_ci break; 1592cf200d32Sopenharmony_ci case 'a': case 'A': 1593cf200d32Sopenharmony_ci num = GetNumber(1, MAX_MBR_PARTS, 1, "Toggle active flag for partition: ") - 1; 1594cf200d32Sopenharmony_ci if (partitions[num].GetInclusion() != NONE) 1595cf200d32Sopenharmony_ci partitions[num].SetStatus(partitions[num].GetStatus() ^ 0x80); 1596cf200d32Sopenharmony_ci break; 1597cf200d32Sopenharmony_ci case 'c': case 'C': 1598cf200d32Sopenharmony_ci for (num = 0; num < MAX_MBR_PARTS; num++) 1599cf200d32Sopenharmony_ci RecomputeCHS(num); 1600cf200d32Sopenharmony_ci break; 1601cf200d32Sopenharmony_ci case 'l': case 'L': 1602cf200d32Sopenharmony_ci num = GetNumber(1, MAX_MBR_PARTS, 1, "Partition to set as logical: ") - 1; 1603cf200d32Sopenharmony_ci SetInclusionwChecks(num, LOGICAL); 1604cf200d32Sopenharmony_ci break; 1605cf200d32Sopenharmony_ci case 'o': case 'O': 1606cf200d32Sopenharmony_ci num = GetNumber(1, MAX_MBR_PARTS, 1, "Partition to omit: ") - 1; 1607cf200d32Sopenharmony_ci SetInclusionwChecks(num, NONE); 1608cf200d32Sopenharmony_ci break; 1609cf200d32Sopenharmony_ci case 'p': case 'P': 1610cf200d32Sopenharmony_ci if (!haveShownInfo) { 1611cf200d32Sopenharmony_ci cout << "\n** NOTE: Partition numbers do NOT indicate final primary/logical " 1612cf200d32Sopenharmony_ci << "status,\n** unlike in most MBR partitioning tools!\n\a"; 1613cf200d32Sopenharmony_ci cout << "\n** Extended partitions are not displayed, but will be generated " 1614cf200d32Sopenharmony_ci << "as required.\n"; 1615cf200d32Sopenharmony_ci haveShownInfo = 1; 1616cf200d32Sopenharmony_ci } // if 1617cf200d32Sopenharmony_ci DisplayMBRData(); 1618cf200d32Sopenharmony_ci break; 1619cf200d32Sopenharmony_ci case 'q': case 'Q': 1620cf200d32Sopenharmony_ci cout << "This will abandon your changes. Are you sure? "; 1621cf200d32Sopenharmony_ci if (GetYN() == 'Y') { 1622cf200d32Sopenharmony_ci goOn = 0; 1623cf200d32Sopenharmony_ci quitting = 1; 1624cf200d32Sopenharmony_ci } // if 1625cf200d32Sopenharmony_ci break; 1626cf200d32Sopenharmony_ci case 'r': case 'R': 1627cf200d32Sopenharmony_ci num = GetNumber(1, MAX_MBR_PARTS, 1, "Partition to set as primary: ") - 1; 1628cf200d32Sopenharmony_ci SetInclusionwChecks(num, PRIMARY); 1629cf200d32Sopenharmony_ci break; 1630cf200d32Sopenharmony_ci case 's': case 'S': 1631cf200d32Sopenharmony_ci SortMBR(); 1632cf200d32Sopenharmony_ci break; 1633cf200d32Sopenharmony_ci case 't': case 'T': 1634cf200d32Sopenharmony_ci num = GetNumber(1, MAX_MBR_PARTS, 1, "Partition to change type code: ") - 1; 1635cf200d32Sopenharmony_ci hexCode = 0x00; 1636cf200d32Sopenharmony_ci if (partitions[num].GetLengthLBA() > 0) { 1637cf200d32Sopenharmony_ci while ((hexCode <= 0) || (hexCode > 255)) { 1638cf200d32Sopenharmony_ci cout << "Enter an MBR hex code: "; 1639cf200d32Sopenharmony_ci tempStr = ReadString(); 1640cf200d32Sopenharmony_ci if (IsHex(tempStr)) 1641cf200d32Sopenharmony_ci sscanf(tempStr.c_str(), "%x", &hexCode); 1642cf200d32Sopenharmony_ci } // while 1643cf200d32Sopenharmony_ci partitions[num].SetType(hexCode); 1644cf200d32Sopenharmony_ci } // if 1645cf200d32Sopenharmony_ci break; 1646cf200d32Sopenharmony_ci case 'w': case 'W': 1647cf200d32Sopenharmony_ci goOn = 0; 1648cf200d32Sopenharmony_ci break; 1649cf200d32Sopenharmony_ci default: 1650cf200d32Sopenharmony_ci ShowCommands(); 1651cf200d32Sopenharmony_ci break; 1652cf200d32Sopenharmony_ci } // switch 1653cf200d32Sopenharmony_ci } while (goOn); 1654cf200d32Sopenharmony_ci if (quitting) 1655cf200d32Sopenharmony_ci retval = -1; 1656cf200d32Sopenharmony_ci else 1657cf200d32Sopenharmony_ci retval = CountParts(); 1658cf200d32Sopenharmony_ci return (retval); 1659cf200d32Sopenharmony_ci} // BasicMBRData::DoMenu() 1660cf200d32Sopenharmony_ci 1661cf200d32Sopenharmony_civoid BasicMBRData::ShowCommands(void) { 1662cf200d32Sopenharmony_ci cout << "a\ttoggle the active/boot flag\n"; 1663cf200d32Sopenharmony_ci cout << "c\trecompute all CHS values\n"; 1664cf200d32Sopenharmony_ci cout << "l\tset partition as logical\n"; 1665cf200d32Sopenharmony_ci cout << "o\tomit partition\n"; 1666cf200d32Sopenharmony_ci cout << "p\tprint the MBR partition table\n"; 1667cf200d32Sopenharmony_ci cout << "q\tquit without saving changes\n"; 1668cf200d32Sopenharmony_ci cout << "r\tset partition as primary\n"; 1669cf200d32Sopenharmony_ci cout << "s\tsort MBR partitions\n"; 1670cf200d32Sopenharmony_ci cout << "t\tchange partition type code\n"; 1671cf200d32Sopenharmony_ci cout << "w\twrite the MBR partition table to disk and exit\n"; 1672cf200d32Sopenharmony_ci} // BasicMBRData::ShowCommands() 1673