xref: /haiku/src/add-ons/kernel/partitioning_systems/common/PartitionMap.h (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
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
29 struct partition_type {
30 	uint8		type;
31 	const char*	name;
32 	bool		used;
33 };
34 
35 
36 // is_empty_type
37 static inline bool
38 is_empty_type(uint8 type)
39 {
40 	return type == 0x00;
41 }
42 
43 
44 // is_extended_type
45 static inline bool
46 is_extended_type(uint8 type)
47 {
48 	return type == 0x05 || type == 0x0f || type == 0x85;
49 }
50 
51 
52 void 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.
60 struct 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
68 struct 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
81 struct 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 
99 static const uint16 kPartitionTableSectorSignature = 0xaa55;
100 
101 class Partition;
102 class PrimaryPartition;
103 class 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 */
115 class PartitionType {
116 public:
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); }
131 private:
132 	uint8	fType;
133 	bool	fValid;
134 };
135 
136 
137 // Partition
138 class Partition {
139 public:
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 
193 private:
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
205 class PrimaryPartition : public Partition {
206 public:
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 
232 private:
233 			LogicalPartition*	fHead;
234 			LogicalPartition*	fTail;
235 			int32				fLogicalPartitionCount;
236 			int32				fIndex;
237 };
238 
239 
240 // LogicalPartition
241 class LogicalPartition : public Partition {
242 public:
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 
276 private:
277 			PrimaryPartition*	fPrimary;
278 			LogicalPartition*	fNext;
279 			LogicalPartition*	fPrevious;
280 };
281 
282 
283 // PartitionMap
284 class PartitionMap {
285 public:
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 
309 private:
310 			PrimaryPartition	fPrimaries[4];
311 };
312 
313 #endif	// _INTEL_PARTITION_MAP_H
314