1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
/*
* This file is licensed under the terms of the GNU General Public License,
* version 2. See the file COPYING in the main directory for details.
*
* Copyright (C) 2000-2002 Florian Lohoff <flo@rfc822.org>
* Copyright (C) 2002,2003 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
*/
#include "delo.h"
struct partition {
unsigned char boot_ind; /* 0x80 - active */
unsigned char head; /* starting head */
unsigned char sec_cyl_lo; /* starting sector and cylinder, low byte */
unsigned char sec_cyl_hi; /* starting sector and cylinder, high byte */
#define CYLINDER(p) ((p).sec_cyl_hi << 2 | ((p).sec_cyl_lo >> 6 & 0x03))
#define SECTOR(p) ((p).sec_cyl_lo & 0x3f)
unsigned char sys_ind; /* What partition type */
#define UNUSED_PARTITION 0x00
#define DOS_EXTENDED_PARTITION 0x05
#define WIN95_EXTENDED_PARTITION 0x0f
#define LINUX_NATIVE_PARTITION 0x83
#define LINUX_EXTENDED_PARTITION 0x85
unsigned char end_head; /* end head */
unsigned char end_sec_cyl_lo; /* end sector and cylinder, low byte */
unsigned char end_sec_cyl_hi; /* end sector and cylinder, high byte */
#define END_CYLINDER(p) ((p).end_sec_cyl_hi << 2 | ((p).end_sec_cyl_lo >> 6 & 0x03))
#define END_SECTOR(p) ((p).end_sec_cyl_lo & 0x3f)
unsigned int start_sect; /* starting sector counting from 0 */
unsigned int nr_sects; /* nr of sectors in partition */
} __attribute((packed));
/* Layout of a DOS Master Boot Record */
struct msdos_label {
unsigned char bootcode[0x1be]; /* Space for bootloader code */
struct partition partitions[4]; /* Primary partitions */
unsigned short magic; /* magic number */
#define MSDOS_LABEL_MAGIC 0xAA55
} __attribute((packed));
#define EXTENDED_P(p) \
((p)->sys_ind == DOS_EXTENDED_PARTITION \
|| (p)->sys_ind == WIN95_EXTENDED_PARTITION \
|| (p)->sys_ind == LINUX_EXTENDED_PARTITION)
#define NATIVE_P(p) \
((p)->sys_ind == LINUX_NATIVE_PARTITION)
unsigned int getpartoffset(char *partition)
{
struct msdos_label label;
int estart = 0;
int pno = 0;
int no;
int i;
/*
* Convert partition number (ascii) to int -- dumb strtoi()
*
* This might be empty - pno will be 0 and we will take the first
* ext2/linux partition
*/
for(i = 0; partition[i] != 0; i++)
pno = pno * 10 + partition[i] - '0';
/* Read first sector */
if ((bootread(0, (char*)&label, sizeof(struct msdos_label))
!= sizeof(struct msdos_label)))
return 0; /* Unreported, the boot will fail anyway */
if (label.magic != MSDOS_LABEL_MAGIC) {
puts("No DOS disklabel found");
return 0;
}
for (no = 1; no <= 4; no++) {
struct partition *p = &label.partitions[no - 1];
/* Ignore empty partitions */
if (!p->nr_sects)
continue;
/* Store extended partition offset for later */
if (EXTENDED_P(p)) {
estart = p->start_sect;
continue;
}
#ifdef DEBUG
printf("Partiton %2d: Type %2x, Off %8d, Size %8d\n",
no, p->sys_ind, p->start_sect, p->nr_sects);
#endif
/*
* If we found the partition pno or we want the first
* native partition.
*/
if (pno == no || (!pno && NATIVE_P(p)))
return p->start_sect;
}
while(estart) {
int pstart = estart;
estart = 0;
/* Read extended partition start */
if ((bootread(pstart, (char*)&label, sizeof(struct msdos_label)) <= 0))
return pstart; /* Unreported, the boot will fail anyway */
/*
* If this doesnt contain a LABEL_MAGIC we haven't got
* any further partition tables
*/
if (label.magic != MSDOS_LABEL_MAGIC) {
printf("Magic failed\n");
return pstart;
}
for(i = 1; i <= 4; i++) {
struct partition *p = &label.partitions[i - 1];
if (!p->nr_sects)
continue;
if (EXTENDED_P(p)) {
estart = p->start_sect;
continue;
}
#ifdef DEBUG
printf("Partiton %2d: Type %2x, Off %8d, Size %8d\n",
no, p->sys_ind, p->start_sect, p->nr_sects);
#endif
/*
* If we found the partition pno or we want the first
* native partition.
*/
if (pno == no || (!pno && NATIVE_P(p)))
return pstart + p->start_sect;
no++;
}
}
return 0;
}
|