I've been doing some research on how to find gaps between the entries in a MBR partition table. There isn't much information on gap finding algorithms as it applies to disks using google, so it looks like that I will have to come up with my own. My research has come up with the following:
- Sort partition table by starting LBA (SLBA)
- Add SLBA to LBA count creating the ending LBA (ELBA)
- Run through the table doing gap = ELBA of previous record - SLBA of current record.
- Special Case: First Record: gap = SLBA - 1
- Special Case: Last Record: gap = Last LBA of disk - ELBA.
I realize that there are other special cases such as no records, one record, etc... but I'm not going to get into that at this time. Does my proposed algorithm look good? Or am I barking up the wrong tree?
I do have some preliminary code that I have written as shown below starting with the definitions:
typedef struct fs_mbr_diskpartrec_tag__ fs_mbrdpart_t;
struct fs_mbr_diskpartrec_tag__
{
uint8 status; /* Record Status Byte */
uint8 schs[3]; /* Partition Start CHS Address */
uint8 ptype; /* Partition/Filesystem Type */
uint8 echs[3]; /* Partition End CHS Address */
uint32 lbastart; /* LBA Partition Start Sector */
uint32 lbacount; /* LBA Partition Sector Count */
} DTYPEPACKED;
/* 512-byte MBR Boot Sector Layout */
typedef struct fs_mbr_bootsect_tag__ fs_mbr_t;
struct fs_mbr_bootsect_tag__
{
uint8 bootcode[394]; /* Bootstrap Code */
fs_mbribm_t ibm[4]; /* IBM Extensions */
uint8 fill[1]; /* Unused */
uint64 sectcnt; /* Sector count of media */
uint32 signature; /* Media Signature */
uint16 sectsize; /* Media Sector Size */
uint8 flag; /* Flag required by MBR Boot Code */
fs_mbrdpart_t pt[4]; /* Partition Table */
uint16 magic; /* BIOS Signature *MUST* be 0xAA55 */
} DTYPEPACKED;
The uint8, uint16, uint32, and uint64 data types are basically typedefs to unsigned char, unsigned short, unsigned int, unsigned long long, respectively.
int fs_mbr_analysis(fs_mbr_t *mbr, uint8 ptype, uint32 seccnt)
{
uint64 scnt;
uint32 lba[4][2];
uint32 gap[5][2];
int i, j;
uint8 fpe;
/* Initialize */
bzero(gap, sizeof(gap));
bzero(lba, sizeof(lba));
j = 0;
fpe = 0;
scnt = fs_dev_getsectcnt();
/* Get the data */
for (i = 0; i < 4; i++)
{
if (mbr->pt[i].ptype != 0)
{
fpe |= 0x80;
fpe >>= 1;
continue;
}
lba[j][0] = mbr->pt[i].lbastart;
lba[j][1] = lba[j][0] + mbr->pt[i].lbacount;
j++;
}
fpe >>= 4;
/* If we already have 4 entries, then there is no space. */
if (j == 4) return(ENOSPC);
/* We have at least one entry. */
if (j > 1)
{
/* Sort the list. */
{
int sc;
int temp;
while(1)
{
sc = 0;
for (i = 1; i < j; i++)
{
if (lba[i][0] < lba[i - 1][0])
{
temp = lba[i - 1][0];
lba[i - 1][0] = lba[i][0];
lba[i][0] = lba[i - 1][0];
temp = lba[i - 1][1];
lba[i - 1][1] = lba[i][1];
lba[i][1] = lba[i - 1][1];
sc++;
}
}
if (sc == 0) break;
}
}
/* List is sorted, generate gap list. */
{
int m;
m = 0;
for (i = 0; i < j; i++)
{
if (i == 0)
{
/* Begining Edge Case */
gap[m][1] = lba[i][0] - 1;
gap[m][0] = 1;
m++;
continue;
}
if (i == (j - 1))
{
/* Ending Edge Case */
gap[m][1] = scnt - lba[i][1];
gap[m][0] = lba[i][1];
m++;
continue;
}
gap[m][1] = lba[i][0] - lba[i - 1][1];
gap[m][0] = lba[i - 1][1] + 1;
m++;
}
}
}
else if (j == 1)
{
}
return(0);
}
This code is not complete, but this is the direction that I'm going with it.