blob: 8efad0a4d0008bbd2ca05758b4f48805789b55e3 [file] [log] [blame]
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) Hewlett-Packard (Paul Bame) paul_bame@hp.com
*/
#include "common.h"
#include <stdio.h>
int
is_extended(int id)
{
switch(id)
{
case DOS_EXTENDED_PARTITION:
case LINUX_EXTENDED_PARTITION:
case WIN98_EXTENDED_PARTITION:
return 1;
}
return 0;
}
int
load_partitions(int bootdev, struct diskpartition *mptab, int maxparts)
{
struct firstblock fb;
struct partition *ptab = &fb.part[0];
int i;
int ex = -1;
int extnum = 4;
unsigned offset;
/* seekread MBR */
if (seekread(bootdev, (char *)&fb, sizeof fb, 0) == -1)
return 0;
if (fb.dosmagic[0] != 0x55 || fb.dosmagic[1] != 0xaa)
return 0;
for (i = 0; i < 4; i++)
{
mptab[i].start = __le32_to_cpu(ptab[i].start_sect);
mptab[i].length = __le32_to_cpu(ptab[i].nr_sects);
mptab[i].id = ptab[i].sys_ind;
if (is_extended(ptab[i].sys_ind))
ex = i;
}
if (ex != -1)
{
offset = mptab[ex].start;
while (extnum < maxparts)
{
/* we're currently using 32-bit file seeks which is ok since
* the IPL is also limited to 2G right now. On disks > 4GB
* this next read may fail. Handle that gracefully.
* Yes, we know newer IODC can read/write > 2GB but
* it would confuse too many people if the docs attempted
* to explain for no tangible benefit. And moving boot disks
* between systems will always work (assuming a useable
* kernel is present).
*/
if (offset >= (2 * (GB / 512))) { /* weird () to quiet compiler */
printf("Skipping extended partition %d - beyond reach of IPL\n\r",
extnum + 1);
break;
}
if (seekread(bootdev, (char *)&fb, sizeof fb, 512 * offset) == -1) {
printf("seekread(bootdev,..., 512 * 0x%x) failed!\n\r", offset);
break;
}
if (fb.dosmagic[0] != 0x55 || fb.dosmagic[1] != 0xaa)
{
printf("Bad DOS magic in extended partition\n\r");
break;
}
mptab[extnum].start = __le32_to_cpu(ptab[0].start_sect) + offset;
mptab[extnum].length = __le32_to_cpu(ptab[0].nr_sects);
mptab[extnum].id = ptab[0].sys_ind;
extnum++;
if (!is_extended(ptab[1].sys_ind))
break;
offset = mptab[ex].start + __le32_to_cpu(ptab[1].start_sect);
}
}
return 1;
}
void
print_ptab(struct diskpartition *mptab, int maxparts)
{
int i;
for (i = 0; i < maxparts; i++)
{
if (mptab[i].id != 0)
printf("/dev/ida%-2d %02x %10u %10u\n\r",
i + 1, mptab[i].id,
mptab[i].start,
mptab[i].length);
}
}
void
print_ptab_pretty(struct diskpartition *mptab, int maxparts)
{
int i;
const int mbshift = 20 - 9;
printf("Partition Start(MB) End(MB) Id Type\n\r");
for (i = 0; i < maxparts; i++)
{
if (mptab[i].id != 0 && ! is_extended(mptab[i].id))
printf("%-9x %7d %5d %2x %s\n\r",
i + 1,
1 + (mptab[i].start >> mbshift),
(mptab[i].start + mptab[i].length) >> mbshift,
mptab[i].id,
mptab[i].id == LINUX_EXT2_PARTITION ? "ext2" :
(mptab[i].id == LINUX_SWAP_PARTITION ? "swap" :
(mptab[i].id == LINUX_RAID_PARTITION ? "RAID" :
(mptab[i].id == PALO_PARTITION ? "Palo" : "Unknown"))));
}
}