File: msdos.c

package info (click to toggle)
delo 0.8-2.5
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 476 kB
  • ctags: 1,272
  • sloc: ansic: 4,027; makefile: 200; sh: 141; asm: 55
file content (150 lines) | stat: -rw-r--r-- 4,058 bytes parent folder | download | duplicates (4)
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;
}