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