xref: /haiku/src/add-ons/kernel/partitioning_systems/apple/apple.cpp (revision 1d9d47fc72028bb71b5f232a877231e59cfe2438)
1 /*
2 ** Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3 ** Distributed under the terms of the Haiku License.
4 */
5 
6 
7 #include "apple.h"
8 
9 #include <ddm_modules.h>
10 #include <KernelExport.h>
11 #ifdef _BOOT_MODE
12 #	include <boot/partitions.h>
13 #else
14 #	include <DiskDeviceTypes.h>
15 #endif
16 #include <util/kernel_cpp.h>
17 
18 #include <unistd.h>
19 #include <string.h>
20 
21 
22 #define TRACE_APPLE 0
23 #if TRACE_APPLE
24 #	define TRACE(x) dprintf x
25 #else
26 #	define TRACE(x) ;
27 #endif
28 
29 #define APPLE_PARTITION_MODULE_NAME "partitioning_systems/apple/v1"
30 #define APPLE_PARTITION_NAME "Apple Partition Map"
31 
32 static const char *kApplePartitionTypes[] = {
33 	"partition_map",	// the partition map itself
34 	"Driver",			// contains a device driver
35 	"Driver43",			// the SCSI 4.3 manager
36 	"MFS",				// Macintosh File System
37 	"HFS",				// Hierarchical File System (HFS/HFS+)
38 	"Unix_SVR2",		// UFS
39 	"PRODOS",
40 	"Free",				// unused partition
41 	"Scratch",			// empty partition
42 	"Driver_ATA",		// the device driver for an ATA device
43 	"Driver_ATAPI",		// the device driver for an ATAPI device
44 	"Driver43_CD",		// an SCSI CD-ROM driver suitable for booting
45 	"FWDriver",			// a FireWire driver for the device
46 	"Void",				// dummy partition map entry (used to align entries for CD-ROM)
47 	"Patches",
48 	NULL
49 };
50 #if 0
51 static const char *kOtherPartitionTypes[] = {
52 	"Be_BFS",			// Be's BFS (not specified endian)
53 };
54 #endif
55 
56 static status_t
57 get_next_partition(int fd, apple_driver_descriptor &descriptor, uint32 &cookie,
58 	apple_partition_map &partition)
59 {
60 	uint32 block = cookie;
61 
62 	// find first partition map if this is the first call,
63 	// or else, just load the next block
64 	do {
65 		ssize_t bytesRead = read_pos(fd, (off_t)block * descriptor.BlockSize(),
66 					(void *)&partition, sizeof(apple_partition_map));
67 		if (bytesRead < (ssize_t)sizeof(apple_partition_map))
68 			return B_ERROR;
69 
70 		block++;
71 	} while (cookie == 0 && block < 64 && !partition.HasValidSignature());
72 
73 	if (!partition.HasValidSignature()) {
74 		if (cookie)
75 			return B_ENTRY_NOT_FOUND;
76 
77 		// we searched for the first partition map entry and failed
78 		return B_ERROR;
79 	}
80 
81 	// the first partition map entry must be of type Apple_partition_map
82 	if (!cookie && (strncmp(partition.type, "Apple_", 6)
83 		|| strcmp(partition.type + 6, kApplePartitionTypes[0])))
84 		return B_ERROR;
85 
86 	// ToDo: warn about unknown types?
87 
88 	cookie = block;
89 	return B_OK;
90 }
91 
92 
93 //	#pragma mark -
94 //	Apple public module interface
95 
96 
97 static status_t
98 apple_std_ops(int32 op, ...)
99 {
100 	switch (op) {
101 		case B_MODULE_INIT:
102 		case B_MODULE_UNINIT:
103 			return B_OK;
104 	}
105 
106 	return B_ERROR;
107 }
108 
109 
110 static float
111 apple_identify_partition(int fd, partition_data *partition, void **_cookie)
112 {
113 	struct apple_driver_descriptor *descriptor;
114 	uint8 buffer[512];
115 
116 	if (read_pos(fd, 0, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer))
117 		return B_ERROR;
118 
119 	descriptor = (apple_driver_descriptor *)buffer;
120 
121 	TRACE(("apple: read first chunk (signature = %x)\n", descriptor->signature));
122 
123 	if (!descriptor->HasValidSignature())
124 		return B_ERROR;
125 
126 	TRACE(("apple: valid partition descriptor!\n"));
127 
128 	// ToDo: Should probably call get_next_partition() once to know if there
129 	//		are any partitions on this disk
130 
131 	// copy the relevant part of the first block
132 	descriptor = new apple_driver_descriptor();
133 	memcpy(descriptor, buffer, sizeof(apple_driver_descriptor));
134 
135 	*_cookie = (void *)descriptor;
136 
137 	// ToDo: reevaluate the priority with ISO-9660 and others in mind
138 	//		(for CD-ROM only, as far as I can tell)
139 	return 0.5f;
140 }
141 
142 
143 static status_t
144 apple_scan_partition(int fd, partition_data *partition, void *_cookie)
145 {
146 	TRACE(("apple_scan_partition(cookie = %p)\n", _cookie));
147 
148 	apple_driver_descriptor &descriptor = *(apple_driver_descriptor *)_cookie;
149 
150 	partition->status = B_PARTITION_VALID;
151 	partition->flags |= B_PARTITION_PARTITIONING_SYSTEM
152 						| B_PARTITION_READ_ONLY;
153 	partition->content_size = descriptor.BlockSize() * descriptor.BlockCount();
154 
155 	// scan all children
156 
157 	apple_partition_map partitionMap;
158 	uint32 index = 0, cookie = 0;
159 	status_t status;
160 
161 	while ((status = get_next_partition(fd, descriptor, cookie, partitionMap)) == B_OK) {
162 		TRACE(("apple: found partition: name = \"%s\", type = \"%s\"\n",
163 			partitionMap.name, partitionMap.type));
164 
165 		if (partitionMap.Start(descriptor) + partitionMap.Size(descriptor) > (uint64)partition->size) {
166 			TRACE(("apple: child partition exceeds existing space (%Ld bytes)\n",
167 				partitionMap.Size(descriptor)));
168 			continue;
169 		}
170 
171 		partition_data *child = create_child_partition(partition->id, index++, -1);
172 		if (child == NULL) {
173 			TRACE(("apple: Creating child at index %ld failed\n", index - 1));
174 			return B_ERROR;
175 		}
176 
177 		child->offset = partition->offset + partitionMap.Start(descriptor);
178 		child->size = partitionMap.Size(descriptor);
179 		child->block_size = partition->block_size;
180 	}
181 
182 	if (status == B_ENTRY_NOT_FOUND)
183 		return B_OK;
184 
185 	return status;
186 }
187 
188 
189 static void
190 apple_free_identify_partition_cookie(partition_data *partition, void *_cookie)
191 {
192 	delete (apple_driver_descriptor *)_cookie;
193 }
194 
195 
196 #ifndef _BOOT_MODE
197 static partition_module_info sApplePartitionModule = {
198 #else
199 partition_module_info gApplePartitionModule = {
200 #endif
201 	{
202 		APPLE_PARTITION_MODULE_NAME,
203 		0,
204 		apple_std_ops
205 	},
206 	APPLE_PARTITION_NAME,				// pretty_name
207 	0,									// flags
208 
209 	// scanning
210 	apple_identify_partition,			// identify_partition
211 	apple_scan_partition,				// scan_partition
212 	apple_free_identify_partition_cookie,	// free_identify_partition_cookie
213 	NULL,
214 };
215 
216 #ifndef _BOOT_MODE
217 partition_module_info *modules[] = {
218 	&sApplePartitionModule,
219 	NULL
220 };
221 #endif
222