xref: /haiku/src/add-ons/kernel/partitioning_systems/atari/atari.cpp (revision 4cf03112fa7d2fbd98d3248e2c8afd898c596665)
1 /*
2  * Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "atari.h"
8 
9 #include <ByteOrder.h>
10 #include <KernelExport.h>
11 #include <ddm_modules.h>
12 #ifdef _BOOT_MODE
13 #	include <boot/partitions.h>
14 #else
15 #	include <DiskDeviceTypes.h>
16 #endif
17 #include <util/kernel_cpp.h>
18 
19 #include <unistd.h>
20 #include <string.h>
21 #include <ctype.h>
22 
23 #define SECTSZ 512
24 
25 //#define TRACE_ATARI_PARTITION
26 #ifdef TRACE_ATARI_PARTITION
27 #	define TRACE(x) dprintf x
28 #else
29 #	define TRACE(x) ;
30 #endif
31 
32 
33 #define ATARI_PARTITION_MODULE_NAME "partitioning_systems/atari/v1"
34 #define ATARI_PARTITION_NAME "Atari Partition Map"
35 
36 
37 #if 0
38 template<typename Type> bool
39 validate_check_sum(Type *type)
40 {
41 	if (type->SummedLongs() != sizeof(*type) / sizeof(uint32))
42 		return false;
43 
44 	// check checksum
45 	uint32 *longs = (uint32 *)type;
46 	uint32 sum = 0;
47 	for (uint32 i = 0; i < type->SummedLongs(); i++)
48 		sum += B_BENDIAN_TO_HOST_INT32(longs[i]);
49 
50 #ifdef TRACE_ATARI_PARTITION
51 	if (sum != 0)
52 		TRACE(("search_rdb: check sum is incorrect!\n"));
53 #endif
54 
55 	return sum == 0;
56 }
57 #endif
58 
59 
60 //	#pragma mark -
61 //	Atari Root Block public module interface
62 
63 
64 static status_t
65 atari_std_ops(int32 op, ...)
66 {
67 	switch (op) {
68 		case B_MODULE_INIT:
69 		case B_MODULE_UNINIT:
70 			return B_OK;
71 	}
72 
73 	return B_ERROR;
74 }
75 
76 
77 static float
78 atari_identify_partition(int fd, partition_data *partition, void **_cookie)
79 {
80 	uint8 buffer[512];
81 	atari_root_block *arb = (atari_root_block *)buffer;
82 	float weight = 0.5;
83 	int i;
84 	ssize_t bytesRead = read_pos(fd, 0, buffer, sizeof(buffer));
85 	if (bytesRead < (ssize_t)sizeof(buffer)) {
86 		TRACE(("%s: read error: %ld\n", __FUNCTION__, bytesRead));
87 		return B_ERROR;
88 	}
89 	if (partition->offset)
90 		return B_ERROR;
91 
92 	if (arb->Checksum() == 0x55aa)
93 		weight -= 0.1; /* possible but likely a PC sector */
94 	if (arb->_reserved_1[1] != 0x00)
95 		weight -= 10;
96 	/* hope so */
97 	if (arb->MaxPartitionSize() < 10)
98 		weight -= 20;
99 
100 	if ((arb->BadSectorsStart()+arb->BadSectorsCount())*(off_t)SECTSZ > partition->size)
101 		return B_ERROR;
102 
103 	/* check each partition */
104 	for (i = 0; i < 4; i++) {
105 		struct atari_partition_entry *p = &arb->partitions[i];
106 		if (p->Flags() & ATARI_PART_EXISTS) {
107 			/* check for unknown flags */
108 			if (p->Flags() & ~ (ATARI_PART_EXISTS|ATARI_PART_BOOTABLE))
109 				weight -= 10.0;
110 			/* id should be readable */
111 			if (!isalnum(p->id[0]))
112 				weight -= 1.0;
113 			if (!isalnum(p->id[1]))
114 				weight -= 1.0;
115 			if (!isalnum(p->id[2]))
116 				weight -= 1.0;
117 			/* make sure partition doesn't overlap bad sector list */
118 			if ((arb->BadSectorsStart() < p->Start()) &&
119 				((arb->BadSectorsStart() + arb->BadSectorsCount()) > p->Start()))
120 				weight -= 10;
121 			if ((p->Start()+p->Size())*(off_t)SECTSZ > partition->size)
122 				return B_ERROR;
123 			/* should check partitions don't overlap each other... */
124 		} else {
125 			/* empty partition entry, then it must be all null */
126 			if (p->Flags() || p->id[0] || p->id[1] || p->id[2] ||
127 				p->Start() || p->Size())
128 				weight -= 10.0;
129 			else
130 				weight += 0.1;
131 		}
132 	}
133 	/* not exactly sure */
134 	if (arb->Checksum() != ATARI_BOOTABLE_MAGIC)
135 		weight -= 0.1;
136 
137 	if (weight > 1.0)
138 		weight = 1.0;
139 
140 	if (weight > 0.0) {
141 		// copy the root block to a new piece of memory
142 		arb = new atari_root_block();
143 		memcpy(arb, buffer, sizeof(atari_root_block));
144 
145 		*_cookie = (void *)arb;
146 		return weight;
147 	}
148 
149 	return B_ERROR;
150 }
151 
152 
153 static status_t
154 atari_scan_partition(int fd, partition_data *partition, void *_cookie)
155 {
156 	TRACE(("atari_scan_partition(cookie = %p)\n", _cookie));
157 
158 	atari_root_block &arb = *(atari_root_block *)_cookie;
159 
160 	partition->status = B_PARTITION_VALID;
161 	partition->flags |= B_PARTITION_PARTITIONING_SYSTEM
162 						| B_PARTITION_READ_ONLY;
163 	partition->content_size = partition->size;
164 
165 	// scan all children
166 
167 	uint32 index = 0;
168 	status_t status = B_ENTRY_NOT_FOUND;
169 
170 	for (index = 0; index < 4; index++) {
171 		struct atari_partition_entry *p = &arb.partitions[index];
172 		if (!(p->Flags() & ATARI_PART_EXISTS))
173 			continue;
174 		TRACE(("atari: file system: %.3s\n", p->id));
175 		if ((p->Start() + p->Size())*(uint64)SECTSZ > (uint64)partition->size) {
176 			TRACE(("atari: child partition exceeds existing space (%Ld bytes)\n", p->Size()*SECTSZ));
177 			continue;
178 		}
179 		if (!isalnum(p->id[0]))
180 			continue;
181 		if (!isalnum(p->id[1]))
182 			continue;
183 		if (!isalnum(p->id[2]))
184 			continue;
185 
186 		partition_data *child = create_child_partition(partition->id, index,
187 			partition->offset + p->Start() * (uint64)SECTSZ,
188 			p->Size() * (uint64)SECTSZ, -1);
189 		if (child == NULL) {
190 			TRACE(("atari: Creating child at index %ld failed\n", index - 1));
191 			return B_ERROR;
192 		}
193 #warning M68K: use a lookup table ?
194 		char type[] = "??? Partition";
195 		memcpy(type, p->id, 3);
196 		child->type = strdup(type);
197 		child->block_size = SECTSZ;
198 		status = B_OK;
199 	}
200 
201 	if (status == B_ENTRY_NOT_FOUND)
202 		return B_OK;
203 
204 	return status;
205 }
206 
207 
208 static void
209 atari_free_identify_partition_cookie(partition_data *partition, void *_cookie)
210 {
211 	delete (atari_root_block *)_cookie;
212 }
213 
214 
215 #ifndef _BOOT_MODE
216 static partition_module_info sAtariPartitionModule = {
217 #else
218 partition_module_info gAtariPartitionModule = {
219 #endif
220 	{
221 		ATARI_PARTITION_MODULE_NAME,
222 		0,
223 		atari_std_ops
224 	},
225 	"atari",							// short_name
226 	ATARI_PARTITION_NAME,				// pretty_name
227 	0,									// flags
228 
229 	// scanning
230 	atari_identify_partition,		// identify_partition
231 	atari_scan_partition,			// scan_partition
232 	atari_free_identify_partition_cookie,	// free_identify_partition_cookie
233 	NULL,
234 //	atari_free_partition_cookie,			// free_partition_cookie
235 //	atari_free_partition_content_cookie,	// free_partition_content_cookie
236 };
237 
238 #ifndef _BOOT_MODE
239 partition_module_info *modules[] = {
240 	&sAtariPartitionModule,
241 	NULL
242 };
243 #endif
244