]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/ppc/pk_disklabel.c
Regenerate configure files in ld sub-directory
[thirdparty/binutils-gdb.git] / sim / ppc / pk_disklabel.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>.
17
18 */
19
20
21 #ifndef _PK_DISKLABEL_C_
22 #define _PK_DISKLABEL_C_
23
24 #ifndef STATIC_INLINE_PK_DISKLABEL
25 #define STATIC_INLINE_PK_DISKLABEL STATIC_INLINE
26 #endif
27
28 #include "device_table.h"
29
30 #include "pk.h"
31
32 #include <stdlib.h>
33
34 /* PACKAGE
35
36 disk-label - all knowing disk I/O package
37
38 DESCRIPTION
39
40 The disk-label package provides a generic interface to disk
41 devices. It uses the arguments specified when an instance is being
42 created to determine if the raw disk, a partition, or a file within
43 a partition should be opened.
44
45 An instance create call to disk-label could result, for instance,
46 in the opening of a DOS file system contained within a dos
47 partition contained within a physical disk.
48
49 */
50
51 /* taken from bfd/ppcboot.c by Michael Meissner */
52
53 /* PPCbug location structure */
54 typedef struct ppcboot_location {
55 uint8_t ind;
56 uint8_t head;
57 uint8_t sector;
58 uint8_t cylinder;
59 } ppcboot_location_t;
60
61 /* PPCbug partition table layout */
62 typedef struct ppcboot_partition {
63 ppcboot_location_t partition_begin; /* partition begin */
64 ppcboot_location_t partition_end; /* partition end */
65 uint8_t sector_begin[4]; /* 32-bit start RBA (zero-based), little endian */
66 uint8_t sector_length[4]; /* 32-bit RBA count (one-based), little endian */
67 } ppcboot_partition_t;
68
69 #if 0
70 /* PPCbug boot layout. */
71 typedef struct ppcboot_hdr {
72 uint8_t pc_compatibility[446]; /* x86 instruction field */
73 ppcboot_partition_t partition[4]; /* partition information */
74 uint8_t signature[2]; /* 0x55 and 0xaa */
75 uint8_t entry_offset[4]; /* entry point offset, little endian */
76 uint8_t length[4]; /* load image length, little endian */
77 uint8_t flags; /* flag field */
78 uint8_t os_id; /* OS_ID */
79 char partition_name[32]; /* partition name */
80 uint8_t reserved1[470]; /* reserved */
81 } ppcboot_hdr_t;
82 #endif
83
84
85 typedef struct _disklabel {
86 device_instance *parent;
87 device_instance *raw_disk;
88 unsigned_word pos;
89 unsigned_word sector_begin;
90 unsigned_word sector_length;
91 } disklabel;
92
93
94 static unsigned_word
95 sector2uw(uint8_t s[4])
96 {
97 return ((s[3] << 24)
98 + (s[2] << 16)
99 + (s[1] << 8)
100 + (s[0] << 0));
101 }
102
103
104 static void
105 disklabel_delete(device_instance *instance)
106 {
107 disklabel *label = device_instance_data(instance);
108 device_instance_delete(label->raw_disk);
109 free(label);
110 }
111
112
113 static int
114 disklabel_read(device_instance *instance,
115 void *buf,
116 unsigned_word len)
117 {
118 disklabel *label = device_instance_data(instance);
119 int nr_read;
120 if (label->pos + len > label->sector_length)
121 len = label->sector_length - label->pos;
122 if (device_instance_seek(label->raw_disk, 0,
123 label->sector_begin + label->pos) < 0)
124 return -1;
125 nr_read = device_instance_read(label->raw_disk, buf, len);
126 if (nr_read > 0)
127 label->pos += nr_read;
128 return nr_read;
129 }
130
131 static int
132 disklabel_write(device_instance *instance,
133 const void *buf,
134 unsigned_word len)
135 {
136 disklabel *label = device_instance_data(instance);
137 int nr_written;
138 if (label->pos + len > label->sector_length)
139 len = label->sector_length - label->pos;
140 if (device_instance_seek(label->raw_disk, 0,
141 label->sector_begin + label->pos) < 0)
142 return -1;
143 nr_written = device_instance_write(label->raw_disk, buf, len);
144 if (nr_written > 0)
145 label->pos += nr_written;
146 return nr_written;
147 }
148
149 static int
150 disklabel_seek(device_instance *instance,
151 unsigned_word pos_hi,
152 unsigned_word pos_lo)
153 {
154 disklabel *label = device_instance_data(instance);
155 if (pos_lo >= label->sector_length || pos_hi != 0)
156 return -1;
157 label->pos = pos_lo;
158 return 0;
159 }
160
161
162 static const device_instance_callbacks package_disklabel_callbacks = {
163 disklabel_delete,
164 disklabel_read,
165 disklabel_write,
166 disklabel_seek,
167 };
168
169 /* Reconize different types of boot block */
170
171 static int
172 block0_is_bpb(const uint8_t block[])
173 {
174 const char ebdic_ibma[] = { 0xc9, 0xc2, 0xd4, 0xc1 };
175 /* ref PowerPC Microprocessor CHRP bindings 1.2b - page 47 */
176 /* can't start with IBMA */
177 if (memcmp(block, ebdic_ibma, sizeof(ebdic_ibma)) == 0)
178 return 0;
179 /* must have LE 0xAA55 signature at offset 510 */
180 if (block[511] != 0xAA && block[510] != 0x55)
181 return 0;
182 /* valid 16 bit LE bytes per sector - 256, 512, 1024 */
183 if (block[11] != 0
184 || (block[12] != 1 && block[12] != 2 && block[12] != 4))
185 return 0;
186 /* nr fats is 1 or 2 */
187 if (block[16] != 1 && block[16] != 2)
188 return 0;
189 return 1;
190 }
191
192
193 /* Verify that the device contains an ISO-9660 File system */
194
195 static int
196 is_iso9660(device_instance *raw_disk)
197 {
198 /* ref PowerPC Microprocessor CHRP bindings 1.2b - page 47 */
199 uint8_t block[512];
200 if (device_instance_seek(raw_disk, 0, 512 * 64) < 0)
201 return 0;
202 if (device_instance_read(raw_disk, block, sizeof(block)) != sizeof(block))
203 return 0;
204 if (block[0] == 0x01
205 && block[1] == 'C'
206 && block[2] == 'D'
207 && block[3] == '0'
208 && block[4] == '0'
209 && block[5] == '1')
210 return 1;
211 return 0;
212 }
213
214
215 /* Verify that the disk block contains a valid DOS partition table.
216 While we're at it have a look around for active partitions etc.
217
218 Return 0: invalid
219 Return 1..4: valid, value returned is the first active partition
220 Return -1: no active partition */
221
222 static int
223 block0_is_fdisk(const uint8_t block[])
224 {
225 const int partition_type_fields[] = { 0, 0x1c2, 0x1d2, 0x1e2, 0x1f2 };
226 const int partition_active_fields[] = { 0, 0x1be, 0x1ce, 0x1de, 0xee };
227 int partition;
228 int active = -1;
229 /* ref PowerPC Microprocessor CHRP bindings 1.2b - page 47 */
230 /* must have LE 0xAA55 signature at offset 510 */
231 if (block[511/*0x1ff*/] != 0xAA && block[510/*0x1fe*/] != 0x55)
232 return 0;
233 /* must contain valid partition types */
234 for (partition = 1; partition <= 4 && active != 0; partition++) {
235 int partition_type = block[partition_type_fields[partition]];
236 int is_active = block[partition_active_fields[partition]] == 0x80;
237 const char *type;
238 switch (partition_type) {
239 case 0x00:
240 type = "UNUSED";
241 break;
242 case 0x01:
243 type = "FAT 12 File system";
244 break;
245 case 0x04:
246 type = "FAT 16 File system";
247 break;
248 case 0x05:
249 case 0x06:
250 type = "rejected - extended/chained partition not supported";
251 active = 0;
252 break;
253 case 0x41:
254 type = "Single program image";
255 break;
256 case 0x82:
257 type = "Solaris?";
258 break;
259 case 0x96:
260 type = "ISO 9660 File system";
261 break;
262 default:
263 type = "rejected - unknown type";
264 active = 0;
265 break;
266 }
267 PTRACE(disklabel, ("partition %d of type 0x%02x - %s%s\n",
268 partition,
269 partition_type,
270 type,
271 is_active && active != 0 ? " (active)" : ""));
272 if (partition_type != 0 && is_active && active < 0)
273 active = partition;
274 }
275 return active;
276 }
277
278
279 /* Verify that block0 corresponds to a MAC disk */
280
281 static int
282 block0_is_mac_disk(const uint8_t block[])
283 {
284 /* ref PowerPC Microprocessor CHRP bindings 1.2b - page 47 */
285 /* signature - BEx4552 at offset 0 */
286 if (block[0] != 0x45 || block[1] != 0x52)
287 return 0;
288 return 1;
289 }
290
291
292 /* Open a logical disk/file */
293
294 device_instance *
295 pk_disklabel_create_instance(device_instance *raw_disk,
296 const char *args)
297 {
298 int partition;
299 char *filename;
300
301 /* parse the arguments */
302 if (args == NULL) {
303 partition = 0;
304 filename = NULL;
305 }
306 else {
307 partition = strtoul((char*)args, &filename, 0);
308 if (filename == args)
309 partition = -1; /* not specified */
310 if (*filename == ',')
311 filename++;
312 if (*filename == '\0')
313 filename = NULL; /* easier */
314 }
315
316 if (partition == 0) {
317 /* select the raw disk */
318 return raw_disk;
319 }
320 else {
321 uint8_t boot_block[512];
322 /* get the boot block for examination */
323 if (device_instance_seek(raw_disk, 0, 0) < 0)
324 device_error(device_instance_device(raw_disk),
325 "Problem seeking on raw disk");
326 if (device_instance_read(raw_disk, &boot_block, sizeof(boot_block))
327 != sizeof(boot_block))
328 device_error(device_instance_device(raw_disk), "Problem reading boot block");
329
330 if (partition < 0) {
331 /* select the active partition */
332 if (block0_is_bpb(boot_block)) {
333 device_error(device_instance_device(raw_disk), "Unimplemented active BPB");
334 }
335 else if (block0_is_fdisk(boot_block)) {
336 int active = block0_is_fdisk(boot_block);
337 device_error(device_instance_device(raw_disk), "Unimplemented active FDISK (%d)",
338 active);
339 }
340 else if (is_iso9660(raw_disk)) {
341 device_error(device_instance_device(raw_disk), "Unimplemented active ISO9660");
342 }
343 else if (block0_is_mac_disk(boot_block)) {
344 device_error(device_instance_device(raw_disk), "Unimplemented active MAC DISK");
345 }
346 else {
347 device_error(device_instance_device(raw_disk), "Unreconized bootblock");
348 }
349 }
350 else {
351 /* select the specified disk partition */
352 if (block0_is_bpb(boot_block)) {
353 device_error(device_instance_device(raw_disk), "Unimplemented BPB");
354 }
355 else if (block0_is_fdisk(boot_block)) {
356 /* return an instance */
357 ppcboot_partition_t *partition_table = (ppcboot_partition_t*) &boot_block[446];
358 ppcboot_partition_t *partition_entry;
359 disklabel *label;
360 if (partition > 4)
361 device_error(device_instance_device(raw_disk),
362 "Only FDISK partitions 1..4 supported");
363 partition_entry = &partition_table[partition - 1];
364 label = ZALLOC(disklabel);
365 label->raw_disk = raw_disk;
366 label->pos = 0;
367 label->sector_begin = 512 * sector2uw(partition_entry->sector_begin);
368 label->sector_length = 512 * sector2uw(partition_entry->sector_length);
369 PTRACE(disklabel, ("partition %ld, sector-begin %ld, length %ld\n",
370 (long)partition,
371 (long)label->sector_begin,
372 (long)label->sector_length));
373 if (filename != NULL)
374 device_error(device_instance_device(raw_disk),
375 "FDISK file names not yet supported");
376 return device_create_instance_from(NULL, raw_disk,
377 label,
378 NULL, args,
379 &package_disklabel_callbacks);
380 }
381 else if (block0_is_mac_disk(boot_block)) {
382 device_error(device_instance_device(raw_disk), "Unimplemented MAC DISK");
383 }
384 else {
385 device_error(device_instance_device(raw_disk),
386 "Unreconized bootblock");
387 }
388 }
389 }
390
391 return NULL;
392 }
393
394
395 #endif /* _PK_DISKLABEL_C_ */
396