xref: /haiku/src/add-ons/kernel/partitioning_systems/sun/sun.cpp (revision 68ea01249e1e2088933cb12f9c28d4e5c5d1c9ef)
1 /*
2  * Copyright (C) 2020 Adrien Destugues <pulkomandy@pulkomandy.tk>
3  *
4  * Distributed under terms of the MIT license.
5  */
6 
7 
8 #ifdef _BOOT_MODE
9 #	include <boot/partitions.h>
10 #else
11 #	include <DiskDeviceTypes.h>
12 #endif
13 
14 #include <ByteOrder.h>
15 #include <ddm_modules.h>
16 #include <util/kernel_cpp.h>
17 #include <KernelExport.h>
18 #include <stdint.h>
19 #include <string.h>
20 
21 
22 //#define TRACE_SUN_PARTITION
23 #ifdef TRACE_SUN_PARTITION
24 #	define TRACE(x) dprintf x
25 #else
26 #	define TRACE(x) ;
27 #endif
28 
29 #define SUN_PARTITION_MODULE_NAME "partitioning_systems/sun/v1"
30 #define SUN_PARTITION_NAME "Sun volume table of contents"
31 
32 
33 static uint16_t kMainSignature = 0xDABE;
34 static uint32_t kVtocSignature = 0x600DDEEE;
35 static uint32_t kVtocVersion = 1;
36 static off_t kSectorSize = 512;
37 
38 
39 struct sun_vtoc {
40 	char diskName[128];
41 	struct {
42 		uint32_t version;
43 		char volumeName[8];
44 		uint16_t partitionCount;
45 		struct {
46 			uint16_t type;
47 			uint16_t flags;
48 		} partitions[8];
49 		uint8_t bootinfo[12];
50 		uint8_t reserved[2];
51 		uint32_t signature;
52 		uint8_t reserved2[38];
53 		uint32_t timestamp[8];
54 	} __attribute__((packed)) vtoc;
55 	uint16_t write_skip;
56 	uint16_t read_skip;
57 	uint8_t reserved[154];
58 	uint16_t diskSpeed;
59 	uint16_t cylinders;
60 	uint16_t alternates;
61 	uint8_t reserved2[4];
62 	uint16_t interleave;
63 	uint16_t dataCylinders;
64 	uint16_t alternateCylinders;
65 	uint16_t heads;
66 	uint16_t sectorsPerTrack;
67 	uint8_t reserved3[4];
68 	struct {
69 		uint32_t startCylinder;
70 		uint32_t sectorCount;
71 	} partitions[8];
72 	uint16_t signature;
73 	uint16_t checksum;
74 } __attribute__((packed));
75 
76 
77 //	#pragma mark -
78 //	Sun VTOC public module interface
79 
80 
81 static status_t
sun_std_ops(int32 op,...)82 sun_std_ops(int32 op, ...)
83 {
84 	switch (op) {
85 		case B_MODULE_INIT:
86 		case B_MODULE_UNINIT:
87 			return B_OK;
88 	}
89 
90 	return B_ERROR;
91 }
92 
93 
94 static float
sun_identify_partition(int fd,partition_data * partition,void ** _cookie)95 sun_identify_partition(int fd, partition_data *partition, void **_cookie)
96 {
97 	uint8 buffer[512];
98 	ssize_t bytesRead = read_pos(fd, 0, buffer, sizeof(buffer));
99 	sun_vtoc *vtoc = (sun_vtoc *)buffer;
100 	if (bytesRead < (ssize_t)sizeof(buffer)) {
101 		TRACE(("%s: read error: %ld\n", __FUNCTION__, bytesRead));
102 		return B_ERROR;
103 	}
104 
105 	if (vtoc->signature == B_HOST_TO_BENDIAN_INT16(kMainSignature)
106 		&& vtoc->vtoc.signature == B_HOST_TO_BENDIAN_INT32(kVtocSignature)
107 		&& vtoc->vtoc.version == B_HOST_TO_BENDIAN_INT32(kVtocVersion)) {
108 		// TODO verify the checksum
109 
110 		uint16_t partitionCount
111 			= B_BENDIAN_TO_HOST_INT16(vtoc->vtoc.partitionCount);
112 		TRACE(("Found %d partitions\n", partitionCount));
113 
114 		if (partitionCount > 8)
115 			return B_ERROR;
116 
117 		vtoc = new sun_vtoc();
118 		memcpy(vtoc, buffer, sizeof(sun_vtoc));
119 		*_cookie = (void *)vtoc;
120 
121 		bool hasParent = (get_parent_partition(partition->id) != NULL);
122 		if (!hasParent)
123 			return 0.61; // Larger than iso9660
124 		else
125 			return 0.3;
126 	}
127 
128 	return B_ERROR;
129 }
130 
131 
132 static status_t
sun_scan_partition(int fd,partition_data * partition,void * cookie)133 sun_scan_partition(int fd, partition_data *partition, void *cookie)
134 {
135 	sun_vtoc *vtoc = (sun_vtoc *)cookie;
136 
137 	partition->status = B_PARTITION_VALID;
138 	partition->flags |= B_PARTITION_PARTITIONING_SYSTEM
139 						| B_PARTITION_READ_ONLY;
140 	partition->content_size = partition->size;
141 
142 	off_t headCount = B_BENDIAN_TO_HOST_INT16(vtoc->heads);
143 	off_t sectorsPerTrack = B_BENDIAN_TO_HOST_INT16(vtoc->sectorsPerTrack);
144 	off_t cylinderSize = kSectorSize * headCount * sectorsPerTrack;
145 
146 	TRACE(("%" B_PRIdOFF " heads, %" B_PRIdOFF " sectors, cylindersize %"
147 		B_PRIdOFF "\n", headCount, sectorsPerTrack, cylinderSize));
148 
149 	for (int i = 0; i < B_BENDIAN_TO_HOST_INT16(vtoc->vtoc.partitionCount);
150 		i++) {
151 		uint16_t type = B_BENDIAN_TO_HOST_INT16(vtoc->vtoc.partitions[i].type);
152 		// Ignore unused and "whole disk" entries
153 		if (type == 0 || type == 5)
154 			continue;
155 
156 		off_t start = B_BENDIAN_TO_HOST_INT32(
157 			vtoc->partitions[i].startCylinder) * cylinderSize;
158 		off_t size = B_BENDIAN_TO_HOST_INT32(vtoc->partitions[i].sectorCount)
159 			* kSectorSize;
160 		TRACE(("Part %d type %d start %" B_PRIdOFF " size %" B_PRIdOFF "\n", i,
161 			type, start, size));
162 		partition_data *child = create_child_partition(partition->id, i,
163 			start, size, -1);
164 		if (child == NULL) {
165 			TRACE(("sun: Creating child at index %d failed\n", i));
166 			return B_ERROR;
167 		}
168 		child->block_size = partition->block_size;
169 	}
170 
171 	return B_OK;
172 }
173 
174 
175 static void
sun_free_identify_partition_cookie(partition_data * partition,void * _cookie)176 sun_free_identify_partition_cookie(partition_data *partition, void *_cookie)
177 {
178 	delete (sun_vtoc *)_cookie;
179 }
180 
181 
182 #ifndef _BOOT_MODE
183 static partition_module_info sSunPartitionModule = {
184 #else
185 partition_module_info gSunPartitionModule = {
186 #endif
187 	{
188 		SUN_PARTITION_MODULE_NAME,
189 		0,
190 		sun_std_ops
191 	},
192 	"sun",							// short_name
193 	SUN_PARTITION_NAME,				// pretty_name
194 	0,									// flags
195 
196 	// scanning
197 	sun_identify_partition,		// identify_partition
198 	sun_scan_partition,			// scan_partition
199 	sun_free_identify_partition_cookie,	// free_identify_partition_cookie
200 	NULL,
201 //	atari_free_partition_content_cookie,	// free_partition_content_cookie
202 };
203 
204 #ifndef _BOOT_MODE
205 partition_module_info *modules[] = {
206 	&sSunPartitionModule,
207 	NULL
208 };
209 #endif
210