1/*
2 * Copyright 2003-2007, Ingo Weinhold, bonefish@cs.tu-berlin.de.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef _INTEL_PARTITION_MAP_H
6#define _INTEL_PARTITION_MAP_H
7
8/*!	\file PartitionMap.h
9	\ingroup intel_module
10	\brief Definitions for "intel" style partitions and interface definitions
11		   for related classes.
12*/
13
14// NOTE: <http://www.win.tue.nl/~aeb/partitions/partition_tables-2.html>
15
16#include <SupportDefs.h>
17#include <driver_settings.h>
18
19#include <disk_device_types.h>
20
21#ifndef _USER_MODE
22#	include <util/kernel_cpp.h>
23#else
24#	include <new>
25#endif
26
27
28// partition_type
29struct partition_type {
30	uint8		type;
31	const char*	name;
32	bool		used;
33};
34
35
36// is_empty_type
37static inline bool
38is_empty_type(uint8 type)
39{
40	return type == 0x00;
41}
42
43
44// is_extended_type
45static inline bool
46is_extended_type(uint8 type)
47{
48	return type == 0x05 || type == 0x0f || type == 0x85;
49}
50
51
52void get_partition_type_string(uint8 type, char* buffer);
53
54// chs
55// NOTE: The CHS cannot express locations within larger disks (more than 8GB),
56// and is therefore obsolete.
57// However, some BIOSes still rely on it being 0 for unused partition, and some
58// other value for valid records. Usually they are filled with 0xFF, which is
59// an invalid CHS value, to notify the BIOS that LBA should be used instead.
60struct chs {
61	uint8	cylinder;
62	uint16	head_sector;	// head[15:10], sector[9:0]
63	void SetUnused() { cylinder = 0xFF; head_sector = 0xFFFF; }
64	void Unset() { cylinder = 0; head_sector = 0; }
65} _PACKED;
66
67// partition_descriptor
68struct partition_descriptor {
69	uint8	active;
70	chs		begin;				// mostly ignored
71	uint8	type;				// empty, filesystem or extended
72	chs		end;				// mostly ignored
73	uint32	start;				// in sectors
74	uint32	size;				// in sectors
75
76	bool is_empty() const		{ return is_empty_type(type); }
77	bool is_extended() const	{ return is_extended_type(type); }
78} _PACKED;
79
80// partition_table
81struct partition_table {
82	char					code_area[440];
83	uint32					disk_id;
84	uint16					reserved;
85	partition_descriptor	table[4];
86	uint16					signature;
87
88	void clear_code_area()
89	{
90		memset(code_area, 0, sizeof(code_area));
91	}
92
93	void fill_code_area(const uint8* code, size_t size)
94	{
95		memcpy(code_area, code, min_c(sizeof(code_area), size));
96	}
97} _PACKED;
98
99static const uint16 kPartitionTableSectorSignature = 0xaa55;
100
101class Partition;
102class PrimaryPartition;
103class LogicalPartition;
104
105
106// PartitionType
107/*!
108  \brief Class for validating partition types.
109
110  To this class we can set a partition type and then we can check whether
111  this type is valid, empty or if it represents an extended partition.
112  We can also retrieve the name of that partition type or find the next
113  supported type.
114*/
115class PartitionType {
116public:
117	PartitionType();
118
119	bool SetType(uint8 type);
120	bool SetType(const char* typeName);
121	bool SetContentType(const char* contentType);
122
123	bool IsValid() const	{ return fValid; }
124	bool IsEmpty() const	{ return is_empty_type(fType); }
125	bool IsExtended() const	{ return is_extended_type(fType); }
126
127	uint8 Type() const		{ return fType; }
128	bool FindNext();
129	void GetTypeString(char* buffer) const
130		{ get_partition_type_string(fType, buffer); }
131private:
132	uint8	fType;
133	bool	fValid;
134};
135
136
137// Partition
138class Partition {
139public:
140								Partition();
141								Partition(const partition_descriptor* descriptor,
142									off_t tableOffset, off_t baseOffset,
143									uint32 blockSize);
144
145			void				SetTo(const partition_descriptor* descriptor,
146									off_t tableOffset, off_t baseOffset,
147									uint32 blockSize);
148			void				SetTo(off_t offset, off_t size, uint8 type,
149									bool active, off_t tableOffset,
150									uint32 blockSize);
151			void				Unset();
152
153			bool				IsEmpty() const
154									{ return is_empty_type(fType); }
155			bool				IsExtended() const
156									{ return is_extended_type(fType); }
157
158	// NOTE: Both PartitionTableOffset() and Offset() are absolute with regards
159	// to the session (usually the disk). Ie, for all primary partitions,
160	// including the primary extended partition, the PartitionTableOffset()
161	// points to the MBR (0).
162	// For logical partitions, the PartitionTableOffset() is located within the
163	// primary extended partition, but again, the returned values are absolute
164	// with regards to the session. All values are expressed in bytes.
165			off_t				PartitionTableOffset() const
166									{ return fPartitionTableOffset; }
167									// offset of the partition table
168			off_t				Offset() const		{ return fOffset; }
169									// start offset of the partition contents
170			off_t				Size() const		{ return fSize; }
171			uint8				Type() const		{ return fType; }
172			bool				Active() const		{ return fActive; }
173			uint32				BlockSize() const	{ return fBlockSize; }
174			void				GetTypeString(char* buffer) const
175									{ get_partition_type_string(fType, buffer); }
176
177			void				SetPartitionTableOffset(off_t offset)
178									{ fPartitionTableOffset = offset; }
179			void				SetOffset(off_t offset)
180									{ fOffset = offset; }
181			void				SetSize(off_t size)
182									{ fSize = size; }
183			void				SetType(uint8 type)
184									{ fType = type; }
185			void				SetActive(bool active)
186									{ fActive = active; }
187			void				SetBlockSize(uint32 blockSize)
188									{ fBlockSize = blockSize; }
189
190			bool				CheckLocation(off_t sessionSize) const;
191			bool				FitSizeToSession(off_t sessionSize);
192
193private:
194			off_t				fPartitionTableOffset;
195			off_t				fOffset;
196				// relative to the start of the session
197			off_t				fSize;
198			uint32				fBlockSize;
199			uint8				fType;
200			bool				fActive;
201};
202
203
204// PrimaryPartition
205class PrimaryPartition : public Partition {
206public:
207								PrimaryPartition();
208
209			void				SetTo(const partition_descriptor* descriptor,
210									off_t tableOffset, uint32 blockSize);
211			void				SetTo(off_t offset, off_t size, uint8 type,
212									bool active, uint32 blockSize);
213			void				Unset();
214
215			status_t			Assign(const PrimaryPartition& other);
216
217			int32				Index() const			{ return fIndex; }
218			void				SetIndex(int32 index)	{ fIndex = index; }
219			void				GetPartitionDescriptor(
220									partition_descriptor* descriptor) const;
221
222				// private
223
224			// only if extended
225			int32				CountLogicalPartitions() const
226									{ return fLogicalPartitionCount; }
227			LogicalPartition*	LogicalPartitionAt(int32 index) const;
228			void				AddLogicalPartition(LogicalPartition* partition);
229			void				RemoveLogicalPartition(
230									LogicalPartition* partition);
231
232private:
233			LogicalPartition*	fHead;
234			LogicalPartition*	fTail;
235			int32				fLogicalPartitionCount;
236			int32				fIndex;
237};
238
239
240// LogicalPartition
241class LogicalPartition : public Partition {
242public:
243								LogicalPartition();
244								LogicalPartition(
245									const partition_descriptor* descriptor,
246									off_t tableOffset,
247									PrimaryPartition* primary);
248
249			void				SetTo(const partition_descriptor* descriptor,
250									off_t tableOffset,
251									PrimaryPartition* primary);
252			void				SetTo(off_t offset, off_t size, uint8 type,
253									bool active, off_t tableOffset,
254									PrimaryPartition* primary);
255			void				Unset();
256			void				GetPartitionDescriptor(
257									partition_descriptor* descriptor,
258									bool inner = false) const;
259
260
261			void				SetPrimaryPartition(PrimaryPartition* primary)
262									{ fPrimary = primary; }
263			PrimaryPartition*	GetPrimaryPartition() const
264									{ return fPrimary; }
265
266			void				SetNext(LogicalPartition* next)
267									{ fNext = next; }
268			LogicalPartition*	Next() const
269									{ return fNext; }
270
271			void				SetPrevious(LogicalPartition* previous)
272									{ fPrevious = previous; }
273			LogicalPartition*	Previous() const
274									{ return fPrevious; }
275
276private:
277			PrimaryPartition*	fPrimary;
278			LogicalPartition*	fNext;
279			LogicalPartition*	fPrevious;
280};
281
282
283// PartitionMap
284class PartitionMap {
285public:
286								PartitionMap();
287								~PartitionMap();
288
289			void				Unset();
290
291			status_t			Assign(const PartitionMap& other);
292
293			PrimaryPartition*	PrimaryPartitionAt(int32 index);
294			const PrimaryPartition* PrimaryPartitionAt(int32 index) const;
295			int32				IndexOfPrimaryPartition(
296									const PrimaryPartition* partition) const;
297			int32				CountNonEmptyPrimaryPartitions() const;
298
299			int32				ExtendedPartitionIndex() const;
300
301			int32				CountPartitions() const;
302			int32				CountNonEmptyPartitions() const;
303			Partition*			PartitionAt(int32 index);
304			const Partition*	PartitionAt(int32 index) const;
305
306			bool				Check(off_t sessionSize) const;
307			const partition_type* GetNextSupportedPartitionType(uint32 cookie);
308
309private:
310			PrimaryPartition	fPrimaries[4];
311};
312
313#endif	// _INTEL_PARTITION_MAP_H
314