Skip to content
Permalink
mariux
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
/* mbr.cc -- Functions for loading, saving, and manipulating legacy MBR partition
data. */
/* Initial coding by Rod Smith, January to February, 2009 */
/* This program is copyright (c) 2009-2013 by Roderick W. Smith. It is distributed
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
#define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include <errno.h>
#include <iostream>
#include "mbr.h"
using namespace std;
/****************************************
* *
* MBRData class and related structures *
* *
****************************************/
MBRData::~MBRData(void) {
} // MBRData destructor
/* // Assignment operator -- copy entire set of MBR data.
MBRData & MBRData::operator=(const MBRData & orig) {
BasicMBRData::operator=(orig);
return *this;
} // MBRData::operator=() */
// Assignment operator -- copy entire set of MBR data.
MBRData & MBRData::operator=(const BasicMBRData & orig) {
BasicMBRData::operator=(orig);
return *this;
} // MBRData::operator=()
/*****************************************************
* *
* Functions to create, delete, or change partitions *
* *
*****************************************************/
// Create a protective MBR. Clears the boot loader area if clearBoot > 0.
void MBRData::MakeProtectiveMBR(int clearBoot) {
EmptyMBR(clearBoot);
// Initialize variables
nulls = 0;
MBRSignature = MBR_SIGNATURE;
diskSignature = UINT32_C(0);
partitions[0].SetStatus(0); // Flag the protective part. as unbootable
partitions[0].SetType(UINT8_C(0xEE));
if (diskSize < UINT32_MAX) { // If the disk is under 2TiB
partitions[0].SetLocation(UINT32_C(1), (uint32_t) diskSize - UINT32_C(1));
} else { // disk is too big to represent, so fake it...
partitions[0].SetLocation(UINT32_C(1), UINT32_MAX);
} // if/else
partitions[0].SetInclusion(PRIMARY);
state = gpt;
} // MBRData::MakeProtectiveMBR()
// Optimizes the size of the 0xEE (EFI GPT) partition
void MBRData::OptimizeEESize(void) {
int i, typeFlag = 0;
uint64_t after;
for (i = 0; i < 4; i++) {
// Check for non-empty and non-0xEE partitions
if ((partitions[i].GetType() != 0xEE) && (partitions[i].GetType() != 0x00))
typeFlag++;
if (partitions[i].GetType() == 0xEE) {
// Blank space before this partition; fill it....
if (SectorUsedAs(partitions[i].GetStartLBA() - 1, 4) == NONE) {
partitions[i].SetStartLBA(FindFirstInFree(partitions[i].GetStartLBA() - 1));
} // if
// Blank space after this partition; fill it....
after = partitions[i].GetStartLBA() + partitions[i].GetLengthLBA();
if (SectorUsedAs(after, 4) == NONE) {
partitions[i].SetLengthLBA(FindLastInFree(after) - partitions[i].GetStartLBA() + 1);
} // if free space after
if (after > diskSize) {
if (diskSize < UINT32_MAX) { // If the disk is under 2TiB
partitions[i].SetLengthLBA((uint32_t) diskSize - partitions[i].GetStartLBA());
} else { // disk is too big to represent, so fake it...
partitions[i].SetLengthLBA(UINT32_MAX - partitions[i].GetStartLBA());
} // if/else
} // if protective partition is too big
RecomputeCHS(i);
} // if partition is 0xEE
} // for partition loop
if (typeFlag == 0) { // No non-hybrid partitions found
MakeProtectiveMBR(); // ensure it's a fully compliant protective MBR.
} // if
} // MBRData::OptimizeEESize()
// Delete a partition if one exists at the specified location.
// Returns 1 if a partition was deleted, 0 otherwise....
// Used to help keep GPT & hybrid MBR partitions in sync....
int MBRData::DeleteByLocation(uint64_t start64, uint64_t length64) {
uint32_t start32, length32;
int i, deleted = 0;
if ((start64 < UINT32_MAX) && (length64 < UINT32_MAX)) {
start32 = (uint32_t) start64;
length32 = (uint32_t) length64;
for (i = 0; i < MAX_MBR_PARTS; i++) {
if ((partitions[i].GetType() != 0xEE) && (partitions[i].GetStartLBA() == start32)
&& (partitions[i].GetLengthLBA() == length32)) {
DeletePartition(i);
if (state == hybrid)
OptimizeEESize();
deleted = 1;
} // if (match found)
} // for i (partition scan)
} // if (hybrid & GPT partition < 2TiB)
return deleted;
} // MBRData::DeleteByLocation()
/******************************************************
* *
* Functions that extract data on specific partitions *
* *
******************************************************/
// Return the MBR data as a GPT partition....
GPTPart MBRData::AsGPT(int i) {
MBRPart* origPart;
GPTPart newPart;
uint8_t origType;
uint64_t firstSector, lastSector;
newPart.BlankPartition();
origPart = GetPartition(i);
if (origPart != NULL) {
origType = origPart->GetType();
// don't convert extended, hybrid protective, or null (non-existent)
// partitions (Note similar protection is in GPTData::XFormPartitions(),
// but I want it here too in case I call this function in another
// context in the future....)
if ((origType != 0x05) && (origType != 0x0f) && (origType != 0x85) &&
(origType != 0x00) && (origType != 0xEE)) {
firstSector = (uint64_t) origPart->GetStartLBA();
newPart.SetFirstLBA(firstSector);
lastSector = (uint64_t) origPart->GetLastLBA();
newPart.SetLastLBA(lastSector);
newPart.SetType(((uint16_t) origType) * 0x0100);
newPart.RandomizeUniqueGUID();
newPart.SetAttributes(0);
newPart.SetName(newPart.GetTypeName());
} // if not extended, protective, or non-existent
} // if (origPart != NULL)
return newPart;
} // MBRData::AsGPT()