/* 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
#ifndef __STDC_CONSTANT_MACROS
#define __STDC_CONSTANT_MACROS
#endif

#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()

