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