blob: bf76d2c243bab0ef7eaf89a81b1889583bfa80f1 [file] [log] [blame]
srs5694e7b4ff92009-08-18 13:16:10 -04001/* mbr.cc -- Functions for loading, saving, and manipulating legacy MBR partition
2 data. */
3
4/* By Rod Smith, January to February, 2009 */
5
6#define __STDC_LIMIT_MACROS
7#define __STDC_CONSTANT_MACROS
8
9#include <stdio.h>
10#include <unistd.h>
11#include <stdlib.h>
12#include <stdint.h>
13#include <fcntl.h>
14#include <string.h>
15#include <time.h>
16#include <sys/stat.h>
17#include <errno.h>
18#include "mbr.h"
19#include "support.h"
20
21using namespace std;
22
23/****************************************
24 * *
25 * MBRData class and related structures *
26 * *
27 ****************************************/
28
29MBRData::MBRData(void) {
30 blockSize = SECTOR_SIZE;
31 diskSize = 0;
32 strcpy(device, "");
33 state = invalid;
34 srand((unsigned int) time(NULL));
35 EmptyMBR();
36} // MBRData default constructor
37
38MBRData::MBRData(char *filename) {
39 blockSize = SECTOR_SIZE;
40 diskSize = 0;
41 strcpy(device, filename);
42 state = invalid;
43
44 srand((unsigned int) time(NULL));
45 // Try to read the specified partition table, but if it fails....
46 if (!ReadMBRData(filename)) {
47 EmptyMBR();
48 strcpy(device, "");
49 } // if
50} // MBRData(char *filename) constructor
51
52MBRData::~MBRData(void) {
53} // MBRData destructor
54
srs5694c0ca8f82009-08-20 21:35:25 -040055// Empty all data. Meant mainly for calling by constructors, but it's also
56// used by the hybrid MBR functions in the GPTData class.
57void MBRData::EmptyMBR(int clearBootloader) {
srs5694e7b4ff92009-08-18 13:16:10 -040058 int i;
59
srs5694c0ca8f82009-08-20 21:35:25 -040060 // Zero out the boot loader section, the disk signature, and the
61 // 2-byte nulls area only if requested to do so. (This is the
62 // default.)
63 if (clearBootloader == 1) {
64 for (i = 0; i < 440; i++)
65 code[i] = 0;
66 diskSignature = (uint32_t) rand();
67 nulls = 0;
68 } // if
69
70 // Blank out the partitions
srs5694e7b4ff92009-08-18 13:16:10 -040071 for (i = 0; i < 4; i++) {
72 partitions[i].status = UINT8_C(0);
73 partitions[i].firstSector[0] = UINT8_C(0);
74 partitions[i].firstSector[1] = UINT8_C(0);
75 partitions[i].firstSector[2] = UINT8_C(0);
76 partitions[i].partitionType = UINT8_C(0);
77 partitions[i].lastSector[0] = UINT8_C(0);
78 partitions[i].lastSector[1] = UINT8_C(0);
79 partitions[i].lastSector[2] = UINT8_C(0);
80 partitions[i].firstLBA = UINT32_C(0);
81 partitions[i].lengthLBA = UINT32_C(0);
82 } // for
83 MBRSignature = MBR_SIGNATURE;
84
85 blockSize = SECTOR_SIZE;
86 diskSize = 0;
87 for (i = 0; i < NUM_LOGICALS; i++) {
88 logicals[i].status = UINT8_C(0);
89 logicals[i].firstSector[0] = UINT8_C(0);
90 logicals[i].firstSector[1] = UINT8_C(0);
91 logicals[i].firstSector[2] = UINT8_C(0);
92 logicals[i].partitionType = UINT8_C(0);
93 logicals[i].lastSector[0] = UINT8_C(0);
94 logicals[i].lastSector[1] = UINT8_C(0);
95 logicals[i].lastSector[2] = UINT8_C(0);
96 logicals[i].firstLBA = UINT32_C(0);
97 logicals[i].lengthLBA = UINT32_C(0);
98 } // for
99} // MBRData::EmptyMBR()
100
101// Read data from MBR. Returns 1 if read was successful (even if the
102// data isn't a valid MBR), 0 if the read failed.
103int MBRData::ReadMBRData(char* deviceFilename) {
104 int fd, allOK = 1;
105
106 if ((fd = open(deviceFilename, O_RDONLY)) != -1) {
107 ReadMBRData(fd);
108 } else {
109 allOK = 0;
110 } // if
111
112 close(fd);
113
114 if (allOK)
115 strcpy(device, deviceFilename);
116
117 return allOK;
118} // MBRData::ReadMBRData(char* deviceFilename)
119
120// Read data from MBR.
121void MBRData::ReadMBRData(int fd) {
srs569486dd7842009-08-26 14:39:40 -0400122 int allOK = 1, i, maxLogicals = 0;
srs5694e7b4ff92009-08-18 13:16:10 -0400123 int err;
124
125 // Clear logical partition array
126 for (i = 0; i < NUM_LOGICALS; i++) {
127 logicals[i].status = UINT8_C(0);
128 logicals[i].firstSector[0] = UINT8_C(0);
129 logicals[i].firstSector[1] = UINT8_C(0);
130 logicals[i].firstSector[2] = UINT8_C(0);
131 logicals[i].partitionType = UINT8_C(0);
132 logicals[i].lastSector[0] = UINT8_C(0);
133 logicals[i].lastSector[1] = UINT8_C(0);
134 logicals[i].lastSector[2] = UINT8_C(0);
135 logicals[i].firstLBA = UINT32_C(0);
136 logicals[i].lengthLBA = UINT32_C(0);
137 } // for
138
139 read(fd, code, 440);
140 read(fd, &diskSignature, 4);
141 read(fd, &nulls, 2);
142 read(fd, partitions, 64);
143 read(fd, &MBRSignature, 2);
srs56942a9f5da2009-08-26 00:48:01 -0400144
145 // Reverse the byte order, if necessary
146 if (IsLittleEndian() == 0) {
147 ReverseBytes((char*) &diskSignature, 4);
148 ReverseBytes((char*) &nulls, 2);
149 ReverseBytes((char*) &MBRSignature, 2);
150 for (i = 0; i < 4; i++) {
151 ReverseBytes((char*) &partitions[i].firstLBA, 4);
152 ReverseBytes((char*) &partitions[i].lengthLBA, 4);
153 } // for
154 } // if
155
srs5694e7b4ff92009-08-18 13:16:10 -0400156 if (MBRSignature != MBR_SIGNATURE) {
157 allOK = 0;
158 state = invalid;
159 fprintf(stderr, "MBR signature invalid; read 0x%04X, but should be 0x%04X\n",
160 (unsigned int) MBRSignature, (unsigned int) MBR_SIGNATURE);
161 } /* if */
162
163 // Find disk size
164 diskSize = disksize(fd, &err);
165
166 // Find block size
167 if ((blockSize = GetBlockSize(fd)) == -1) {
168 blockSize = SECTOR_SIZE;
169 printf("Unable to determine sector size; assuming %lu bytes!\n",
170 (unsigned long) SECTOR_SIZE);
171 } // if
172
173 // Load logical partition data, if any is found....
174 if (allOK) {
175 for (i = 0; i < 4; i++) {
176 if ((partitions[i].partitionType == 0x05) || (partitions[i].partitionType == 0x0f)
177 || (partitions[i].partitionType == 0x85)) {
178 // Found it, so call a recursive algorithm to load everything from them....
srs569486dd7842009-08-26 14:39:40 -0400179 maxLogicals = ReadLogicalPart(fd, partitions[i].firstLBA, UINT32_C(0), maxLogicals);
180 if ((maxLogicals < 0) || (maxLogicals > NUM_LOGICALS)) {
181 allOK = 0;
182 fprintf(stderr, "Error reading logical partitions! List may be truncated!\n");
183 } // if maxLogicals valid
184 } // if primary partition is extended
185 } // for primary partition loop
srs5694e7b4ff92009-08-18 13:16:10 -0400186 if (allOK) { // Loaded logicals OK
187 state = mbr;
188 } else {
189 state = invalid;
190 } // if
191 } // if
192
193 /* Check to see if it's in GPT format.... */
194 if (allOK) {
195 for (i = 0; i < 4; i++) {
196 if (partitions[i].partitionType == UINT8_C(0xEE)) {
197 state = gpt;
srs56942a9f5da2009-08-26 00:48:01 -0400198 } // if
199 } // for
200 } // if
201
202 // If there's an EFI GPT partition, look for other partition types,
203 // to flag as hybrid
204 if (state == gpt) {
205 for (i = 0 ; i < 4; i++) {
206 if ((partitions[i].partitionType != UINT8_C(0xEE)) &&
207 (partitions[i].partitionType != UINT8_C(0x00)))
208 state = hybrid;
209 } // for
210 } // if hybrid
srs5694e7b4ff92009-08-18 13:16:10 -0400211
212/* // Tell the user what the MBR state is...
213 switch (state) {
214 case invalid:
215 printf("Information: MBR appears to be empty or invalid.\n");
216 break;
217 case gpt:
218 printf("Information: MBR holds GPT placeholder partitions.\n");
219 break;
220 case hybrid:
221 printf("Information: MBR holds hybrid GPT/MBR data.\n");
222 break;
223 case mbr:
224 printf("Information: MBR data appears to be valid.\n");
225 break;
226 } // switch */
227} // MBRData::ReadMBRData(int fd)
228
229// Write the MBR data to the default defined device.
230int MBRData::WriteMBRData(void) {
231 int allOK = 1, fd;
232
233 if ((fd = open(device, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH)) != -1) {
234 WriteMBRData(fd);
235 } else {
236 allOK = 0;
237 } // if/else
238 close(fd);
239 return allOK;
240} // MBRData::WriteMBRData(void)
241
242// Save the MBR data to a file. Note that this function writes ONLY the
243// MBR data, not the logical partitions (if any are defined).
244void MBRData::WriteMBRData(int fd) {
srs56942a9f5da2009-08-26 00:48:01 -0400245 int i;
246
247 // Reverse the byte order, if necessary
248 if (IsLittleEndian() == 0) {
249 ReverseBytes((char*) &diskSignature, 4);
250 ReverseBytes((char*) &nulls, 2);
251 ReverseBytes((char*) &MBRSignature, 2);
252 for (i = 0; i < 4; i++) {
253 ReverseBytes((char*) &partitions[i].firstLBA, 4);
254 ReverseBytes((char*) &partitions[i].lengthLBA, 4);
255 } // for
256 } // if
257
srs5694e7b4ff92009-08-18 13:16:10 -0400258 write(fd, code, 440);
259 write(fd, &diskSignature, 4);
260 write(fd, &nulls, 2);
261 write(fd, partitions, 64);
262 write(fd, &MBRSignature, 2);
srs56942a9f5da2009-08-26 00:48:01 -0400263
264 // Reverse the byte order, if necessary
265 if (IsLittleEndian() == 0) {
266 ReverseBytes((char*) &diskSignature, 4);
267 ReverseBytes((char*) &nulls, 2);
268 ReverseBytes((char*) &MBRSignature, 2);
269 for (i = 0; i < 4; i++) {
270 ReverseBytes((char*) &partitions[i].firstLBA, 4);
271 ReverseBytes((char*) &partitions[i].lengthLBA, 4);
272 } // for
273 }// if
srs5694e7b4ff92009-08-18 13:16:10 -0400274} // MBRData::WriteMBRData(int fd)
275
276// This is a recursive function to read all the logical partitions, following the
srs569486dd7842009-08-26 14:39:40 -0400277// logical partition linked list from the disk and storing the basic data in the
278// logicals[] array. Returns last index to logicals[] uses, or -1 if there was a
279// problem
srs5694e7b4ff92009-08-18 13:16:10 -0400280int MBRData::ReadLogicalPart(int fd, uint32_t extendedStart,
281 uint32_t diskOffset, int partNum) {
srs5694e7b4ff92009-08-18 13:16:10 -0400282 struct EBRRecord ebr;
283 off_t offset;
284
srs569486dd7842009-08-26 14:39:40 -0400285 if ((partNum < NUM_LOGICALS) && (partNum >= 0)) {
286 offset = (off_t) (extendedStart + diskOffset) * blockSize;
287 if (lseek64(fd, offset, SEEK_SET) == (off_t) -1) { // seek to EBR record
288 fprintf(stderr, "Unable to seek to %lu! Aborting!\n", (unsigned long) offset);
289 partNum = -1;
290 }
291 if (read(fd, &ebr, 512) != 512) { // Load the data....
292 fprintf(stderr, "Error seeking to or reading logical partition data from %lu!\nAborting!\n",
293 (unsigned long) offset);
294 partNum = -1;
295 } else if (IsLittleEndian() != 1) { // Reverse byte ordering of some data....
296 ReverseBytes((char*) &ebr.MBRSignature, 2);
297 ReverseBytes((char*) &ebr.partitions[0].firstLBA, 4);
298 ReverseBytes((char*) &ebr.partitions[0].lengthLBA, 4);
299 ReverseBytes((char*) &ebr.partitions[1].firstLBA, 4);
300 ReverseBytes((char*) &ebr.partitions[1].lengthLBA, 4);
301 } // if/else/if
srs56942a9f5da2009-08-26 00:48:01 -0400302
srs569486dd7842009-08-26 14:39:40 -0400303 if (ebr.MBRSignature != MBR_SIGNATURE) {
304 partNum = -1;
305 fprintf(stderr, "MBR signature in logical partition invalid; read 0x%04X, but should be 0x%04X\n",
306 (unsigned int) ebr.MBRSignature, (unsigned int) MBR_SIGNATURE);
307 } // if
srs5694e7b4ff92009-08-18 13:16:10 -0400308
srs569486dd7842009-08-26 14:39:40 -0400309 // Copy over the basic data....
310 logicals[partNum].status = ebr.partitions[0].status;
311 logicals[partNum].firstLBA = ebr.partitions[0].firstLBA + diskOffset + extendedStart;
312 logicals[partNum].lengthLBA = ebr.partitions[0].lengthLBA;
313 logicals[partNum].partitionType = ebr.partitions[0].partitionType;
srs5694e7b4ff92009-08-18 13:16:10 -0400314
srs569486dd7842009-08-26 14:39:40 -0400315 // Find the next partition (if there is one) and recurse....
316 if ((ebr.partitions[1].firstLBA != UINT32_C(0)) && (partNum >= 0) &&
317 (partNum < (NUM_LOGICALS - 1))) {
318 partNum = ReadLogicalPart(fd, extendedStart, ebr.partitions[1].firstLBA,
319 partNum + 1);
320 } else {
321 partNum++;
322 } // if another partition
323 } // Not enough space for all the logicals (or previous error encountered)
324 return (partNum);
srs5694e7b4ff92009-08-18 13:16:10 -0400325} // MBRData::ReadLogicalPart()
326
327// Show the MBR data to the user....
328void MBRData::DisplayMBRData(void) {
329 int i;
330 char tempStr[255];
srs5694e19ba092009-08-24 14:10:35 -0400331 char bootCode;
srs5694e7b4ff92009-08-18 13:16:10 -0400332
333 printf("MBR disk identifier: 0x%08X\n", (unsigned int) diskSignature);
334 printf("MBR partitions:\n");
srs5694e19ba092009-08-24 14:10:35 -0400335 printf("Number\t Boot\t Start (sector)\t Length (sectors)\tType\n");
srs5694e7b4ff92009-08-18 13:16:10 -0400336 for (i = 0; i < 4; i++) {
337 if (partitions[i].lengthLBA != 0) {
srs5694e19ba092009-08-24 14:10:35 -0400338 if (partitions[i].status && 0x80) // it's bootable
339 bootCode = '*';
340 else
341 bootCode = ' ';
342 printf("%4d\t %c\t%13lu\t%15lu \t0x%02X\n", i + 1, bootCode,
343 (unsigned long) partitions[i].firstLBA,
srs5694e7b4ff92009-08-18 13:16:10 -0400344 (unsigned long) partitions[i].lengthLBA, partitions[i].partitionType);
345 } // if
346 } // for
347
348 // Now display logical partition data....
349 for (i = 0; i < NUM_LOGICALS; i++) {
350 if (logicals[i].lengthLBA != 0) {
351 printf("%4d\t%13lu\t%15lu \t0x%02X\n", i + 5, (unsigned long) logicals[i].firstLBA,
352 (unsigned long) logicals[i].lengthLBA, logicals[i].partitionType);
353 } // if
354 } // for
355 printf("\nDisk size is %lu sectors (%s)\n", (unsigned long) diskSize,
356 BytesToSI(diskSize * (uint64_t) blockSize, tempStr));
357} // MBRData::DisplayMBRData()
358
359// Create a protective MBR
360void MBRData::MakeProtectiveMBR(void) {
361 int i;
362
363 // Initialize variables
364 nulls = 0;
365 MBRSignature = MBR_SIGNATURE;
366
367 partitions[0].status = UINT8_C(0); // Flag the protective part. as unbootable
368
369 // Write CHS data. This maxes out the use of the disk, as much as
370 // possible -- even to the point of exceeding the capacity of sub-8GB
371 // disks. The EFI spec says to use 0xffffff as the ending value,
372 // although normal MBR disks max out at 0xfeffff. FWIW, both GNU Parted
373 // and Apple's Disk Utility use 0xfeffff, and the latter puts that
374 // value in for the FIRST sector, too!
375 partitions[0].firstSector[0] = UINT8_C(0);
376 partitions[0].firstSector[1] = UINT8_C(1);
377 partitions[0].firstSector[2] = UINT8_C(0);
378 partitions[0].lastSector[0] = UINT8_C(255);
379 partitions[0].lastSector[1] = UINT8_C(255);
380 partitions[0].lastSector[2] = UINT8_C(255);
381
382 partitions[0].partitionType = UINT8_C(0xEE);
383 partitions[0].firstLBA = UINT32_C(1);
384 if (diskSize < UINT32_MAX) { // If the disk is under 2TiB
385 partitions[0].lengthLBA = diskSize - 1;
386 } else { // disk is too big to represent, so fake it...
387 partitions[0].lengthLBA = UINT32_MAX;
388 } // if/else
389
390 // Zero out three unused primary partitions...
391 for (i = 1; i < 4; i++) {
392 partitions[i].status = UINT8_C(0);
393 partitions[i].firstSector[0] = UINT8_C(0);
394 partitions[i].firstSector[1] = UINT8_C(0);
395 partitions[i].firstSector[2] = UINT8_C(0);
396 partitions[i].partitionType = UINT8_C(0);
397 partitions[i].lastSector[0] = UINT8_C(0);
398 partitions[i].lastSector[1] = UINT8_C(0);
399 partitions[i].lastSector[2] = UINT8_C(0);
400 partitions[i].firstLBA = UINT32_C(0);
401 partitions[i].lengthLBA = UINT32_C(0);
402 } // for
403
404 // Zero out all the logical partitions. Not necessary for data
405 // integrity on write, but eliminates stray entries if user wants
406 // to view the MBR after converting the disk
407 for (i = 0; i < NUM_LOGICALS; i++) {
408 logicals[i].status = UINT8_C(0);
409 logicals[i].firstSector[0] = UINT8_C(0);
410 logicals[i].firstSector[1] = UINT8_C(0);
411 logicals[i].firstSector[2] = UINT8_C(0);
412 logicals[i].partitionType = UINT8_C(0);
413 logicals[i].lastSector[0] = UINT8_C(0);
414 logicals[i].lastSector[1] = UINT8_C(0);
415 logicals[i].lastSector[2] = UINT8_C(0);
416 logicals[i].firstLBA = UINT32_C(0);
417 logicals[i].lengthLBA = UINT32_C(0);
418 } // for
419
420 state = gpt;
421} // MBRData::MakeProtectiveMBR()
422
srs5694c0ca8f82009-08-20 21:35:25 -0400423// Create a partition that fills the most available space. Returns
424// 1 if partition was created, 0 otherwise. Intended for use in
425// creating hybrid MBRs.
426int MBRData::MakeBiggestPart(int i, int type) {
427 uint32_t start = UINT32_C(1); // starting point for each search
428 uint32_t firstBlock; // first block in a segment
429 uint32_t lastBlock; // last block in a segment
430 uint32_t segmentSize; // size of segment in blocks
431 uint32_t selectedSegment = UINT32_C(0); // location of largest segment
432 uint32_t selectedSize = UINT32_C(0); // size of largest segment in blocks
433 int found = 0;
434
435 do {
436 firstBlock = FindFirstAvailable(start);
437 if (firstBlock != UINT32_C(0)) { // something's free...
438 lastBlock = FindLastInFree(firstBlock);
439 segmentSize = lastBlock - firstBlock + UINT32_C(1);
440 if (segmentSize > selectedSize) {
441 selectedSize = segmentSize;
442 selectedSegment = firstBlock;
443 } // if
444 start = lastBlock + 1;
445 } // if
446 } while (firstBlock != 0);
447 if ((selectedSize > UINT32_C(0)) && ((uint64_t) selectedSize < diskSize)) {
448 found = 1;
449 MakePart(i, selectedSegment, selectedSize, type, 0);
450 } else {
451 found = 0;
452 } // if/else
453 return found;
454} // MBRData::MakeBiggestPart(int i)
455
srs5694e7b4ff92009-08-18 13:16:10 -0400456// Return a pointer to a primary or logical partition, or NULL if
457// the partition is out of range....
458struct MBRRecord* MBRData::GetPartition(int i) {
459 MBRRecord* thePart = NULL;
460
461 if ((i >= 0) && (i < 4)) { // primary partition
462 thePart = &partitions[i];
463 } // if
464 if ((i >= 4) && (i < (NUM_LOGICALS + 4))) {
465 thePart = &logicals[i - 4];
466 } // if
467 return thePart;
468} // GetPartition()
469
470// Displays the state, as a word, on stdout. Used for debugging
471void MBRData::ShowState(void) {
472 switch (state) {
473 case invalid:
474 printf("invalid");
475 break;
476 case gpt:
477 printf("gpt");
478 break;
479 case hybrid:
480 printf("hybrid");
481 break;
482 case mbr:
483 printf("mbr");
484 break;
485 default:
486 printf("unknown -- bug!");
487 break;
488 } // switch
489} // MBRData::ShowState()
490
491// Create a primary partition of the specified number, starting LBA,
492// and length. This function does *NO* error checking, so it's possible
493// to seriously screw up a partition table using this function! It's
494// intended as a way to create a hybrid MBR, which is a pretty funky
495// setup to begin with....
496void MBRData::MakePart(int num, uint32_t start, uint32_t length, int type,
497 int bootable) {
498
499 partitions[num].status = (uint8_t) bootable * (uint8_t) 0x80;
500 partitions[num].firstSector[0] = UINT8_C(0);
501 partitions[num].firstSector[1] = UINT8_C(0);
502 partitions[num].firstSector[2] = UINT8_C(0);
503 partitions[num].partitionType = (uint8_t) type;
504 partitions[num].lastSector[0] = UINT8_C(0);
505 partitions[num].lastSector[1] = UINT8_C(0);
506 partitions[num].lastSector[2] = UINT8_C(0);
507 partitions[num].firstLBA = start;
508 partitions[num].lengthLBA = length;
509} // MakePart()
510
srs5694c0ca8f82009-08-20 21:35:25 -0400511// Finds the first free space on the disk from start onward; returns 0
512// if none available....
513uint32_t MBRData::FindFirstAvailable(uint32_t start) {
514 uint32_t first;
515 uint32_t i;
516 int firstMoved = 0;
517
518 first = start;
519
520 // ...now search through all partitions; if first is within an
521 // existing partition, move it to the next sector after that
522 // partition and repeat. If first was moved, set firstMoved
523 // flag; repeat until firstMoved is not set, so as to catch
524 // cases where partitions are out of sequential order....
525 do {
526 firstMoved = 0;
527 for (i = 0; i < 4; i++) {
528 // Check if it's in the existing partition
529 if ((first >= partitions[i].firstLBA) &&
530 (first < (partitions[i].firstLBA + partitions[i].lengthLBA))) {
531 first = partitions[i].firstLBA + partitions[i].lengthLBA;
532 firstMoved = 1;
533 } // if
534 } // for
535 } while (firstMoved == 1);
536 if (first >= diskSize)
537 first = 0;
538 return (first);
539} // MBRData::FindFirstAvailable()
540
541uint32_t MBRData::FindLastInFree(uint32_t start) {
542 uint32_t nearestStart;
543 uint32_t i;
544
545 if (diskSize <= UINT32_MAX)
546 nearestStart = diskSize - 1;
547 else
548 nearestStart = UINT32_MAX - 1;
549 for (i = 0; i < 4; i++) {
550 if ((nearestStart > partitions[i].firstLBA) &&
551 (partitions[i].firstLBA > start)) {
552 nearestStart = partitions[i].firstLBA - 1;
553 } // if
554 } // for
555 return (nearestStart);
556} // MBRData::FindLastInFree
557
srs5694e7b4ff92009-08-18 13:16:10 -0400558uint8_t MBRData::GetStatus(int i) {
559 MBRRecord* thePart;
560 uint8_t retval;
561
562 thePart = GetPartition(i);
563 if (thePart != NULL)
564 retval = thePart->status;
565 else
566 retval = UINT8_C(0);
567 return retval;
568} // MBRData::GetStatus()
569
570uint8_t MBRData::GetType(int i) {
571 MBRRecord* thePart;
572 uint8_t retval;
573
574 thePart = GetPartition(i);
575 if (thePart != NULL)
576 retval = thePart->partitionType;
577 else
578 retval = UINT8_C(0);
579 return retval;
580} // MBRData::GetType()
581
582uint32_t MBRData::GetFirstSector(int i) {
583 MBRRecord* thePart;
584 uint32_t retval;
585
586 thePart = GetPartition(i);
587 if (thePart != NULL) {
588 retval = thePart->firstLBA;
589 } else
590 retval = UINT32_C(0);
591 return retval;
592} // MBRData::GetFirstSector()
593
594uint32_t MBRData::GetLength(int i) {
595 MBRRecord* thePart;
596 uint32_t retval;
597
598 thePart = GetPartition(i);
599 if (thePart != NULL) {
600 retval = thePart->lengthLBA;
601 } else
602 retval = UINT32_C(0);
603 return retval;
604} // MBRData::GetLength()