~ubuntu-branches/ubuntu/raring/mame/raring-proposed

« back to all changes in this revision

Viewing changes to mess/src/mess/tools/imgtool/modules/pc_hard.c

  • Committer: Package Import Robot
  • Author(s): Jordi Mallach, Jordi Mallach, Emmanuel Kasper
  • Date: 2011-12-19 22:56:27 UTC
  • mfrom: (0.1.2)
  • Revision ID: package-import@ubuntu.com-20111219225627-ub5oga1oys4ogqzm
Tags: 0.144-1
[ Jordi Mallach ]
* Fix syntax errors in DEP5 copyright file (lintian).
* Use a versioned copyright Format specification field.
* Update Vcs-* URLs.
* Move transitional packages to the new metapackages section, and make
  them priority extra.
* Remove references to GNU/Linux and MESS sources from copyright.
* Add build variables for s390x.
* Use .xz tarballs as it cuts 4MB for the upstream sources.
* Add nplayers.ini as a patch. Update copyright file to add CC-BY-SA-3.0.

[ Emmanuel Kasper ]
* New upstream release. Closes: #651538.
* Add Free Desktop compliant png icons of various sizes taken from
  the hydroxygen iconset
* Mess is now built from a new source package, to avoid possible source
  incompatibilities between mame and the mess overlay.
* Mame-tools are not built from the mame source package anymore, but
  from the mess source package

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/****************************************************************************
2
 
 
3
 
    pc_hard.c
4
 
 
5
 
    PC hard drives
6
 
 
7
 
*****************************************************************************
8
 
 
9
 
  Master boot record format:
10
 
 
11
 
  Offset  Length  Description
12
 
  ------  ------  -----------
13
 
       0     446  Boot machine code
14
 
     446      16  Partion #1 info
15
 
     462      16  Partion #2 info
16
 
     478      16  Partion #3 info
17
 
     494      16  Partion #4 info
18
 
     510       2  Magic bytes (0x55 0xAA)
19
 
 
20
 
 
21
 
  Partition info format:
22
 
 
23
 
  Offset  Length  Description
24
 
  ------  ------  -----------
25
 
       0       1  Bootable (0x80=bootable 0x00=not bootable)
26
 
       1       1  Starting head
27
 
       2       1  Starting sector (bits 5-0) and high bits of starting track (bits 6-5)
28
 
       3       1  Low bits of starting track
29
 
       4       1  Partition type:
30
 
                       0x00     Unused
31
 
                       0x?1     FAT12   (0-15 MB)
32
 
                       0x?2     XENIX
33
 
                       0x?4     FAT16   (16-32 MB)
34
 
                       0x?6     FAT16`  (32 MB-2 GB)
35
 
                       0x?7     HPFS or NTFS
36
 
                       0x?A     Boot Manager
37
 
                       0x?B     FAT32   (512 MB-2 TB)
38
 
                       0x?C     FAT32   (512 MB-2 TB LBA)
39
 
                       0x1?     OS/2 Boot manager/Win95 hidden
40
 
                       0xC?     DR-DOS secured partition
41
 
                       0xD?     Multiuser DOS secured partition
42
 
                       0xE?     SpeedStor extended partition
43
 
       5       1  Ending head
44
 
       6       1  Ending sector (bits 5-0) and high bits of ending track (bits 6-5)
45
 
       7       1  Low bits of ending track
46
 
       8       4  Sector index of beginning of partition
47
 
      12       4  Total sectors in partition
48
 
 
49
 
****************************************************************************/
50
 
#include "imgtool.h"
51
 
#include "formats/imageutl.h"
52
 
#include "imghd.h"
53
 
 
54
 
#define FAT_SECLEN      512
55
 
 
56
 
static OPTION_GUIDE_START( pc_chd_create_optionguide )
57
 
        OPTION_INT('T', "cylinders",    "Cylinders" )
58
 
        OPTION_INT('H', "heads",                "Heads" )
59
 
        OPTION_INT('S', "sectors",              "Sectors" )
60
 
OPTION_GUIDE_END
61
 
 
62
 
static const char pc_chd_create_optionspec[] = "H1-[16]S1-[32]-63T10/20/30/40/50/60/70/80/90/[100]/110/120/130/140/150/160/170/180/190/200";
63
 
 
64
 
static const char fat8_string[8]  = { 'F', 'A', 'T', ' ', ' ', ' ', ' ', ' ' };
65
 
static const char fat12_string[8] = { 'F', 'A', 'T', '1', '2', ' ', ' ', ' ' };
66
 
static const char fat16_string[8] = { 'F', 'A', 'T', '1', '6', ' ', ' ', ' ' };
67
 
static const char fat32_string[8] = { 'F', 'A', 'T', '3', '2', ' ', ' ', ' ' };
68
 
 
69
 
/* imports from fat.c */
70
 
extern void fat_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info);
71
 
 
72
 
 
73
 
typedef struct _pc_chd_image_info pc_chd_image_info;
74
 
struct _pc_chd_image_info
75
 
{
76
 
        struct mess_hard_disk_file hard_disk;
77
 
 
78
 
        struct
79
 
        {
80
 
                unsigned int corrupt : 1;
81
 
                UINT8 partition_type;
82
 
                UINT32 fat_bits;
83
 
                UINT32 starting_track;
84
 
                UINT32 starting_head;
85
 
                UINT32 starting_sector;
86
 
                UINT32 ending_track;
87
 
                UINT32 ending_head;
88
 
                UINT32 ending_sector;
89
 
                UINT32 sector_index;
90
 
                UINT32 total_sectors;
91
 
        } partitions[4];
92
 
};
93
 
 
94
 
 
95
 
 
96
 
static pc_chd_image_info *pc_chd_get_image_info(imgtool_image *image)
97
 
{
98
 
        return (pc_chd_image_info *) imgtool_image_extra_bytes(image);
99
 
}
100
 
 
101
 
 
102
 
 
103
 
static void pc_chd_locate_block(imgtool_image *image, UINT64 block, UINT32 *cylinder, UINT32 *head, UINT32 *sector)
104
 
{
105
 
        pc_chd_image_info *info;
106
 
        const hard_disk_info *hd_info;
107
 
 
108
 
        info = pc_chd_get_image_info(image);
109
 
        hd_info = imghd_get_header(&info->hard_disk);
110
 
 
111
 
        *sector = block % hd_info->sectors;
112
 
        *head = (block / hd_info->sectors) % hd_info->heads;
113
 
        *cylinder = block / hd_info->sectors / hd_info->heads;
114
 
}
115
 
 
116
 
 
117
 
 
118
 
static imgtoolerr_t pc_chd_partition_create(imgtool_image *image, int partition_index, UINT64 first_block, UINT64 block_count)
119
 
{
120
 
        imgtoolerr_t err;
121
 
        UINT8 header_block[FAT_SECLEN];
122
 
        UINT8 partition_block[FAT_SECLEN];
123
 
        UINT8 partition_type;
124
 
        UINT8 *fat_type;
125
 
        UINT8 *partition_entry;
126
 
        UINT32 first_cylinder, first_head, first_sector;
127
 
        UINT32 last_cylinder, last_head, last_sector;
128
 
        imgtool_class imgclass = { fat_get_info };
129
 
        imgtoolerr_t (*fat_partition_create)(imgtool_image *image, UINT64 first_block, UINT64 block_count);
130
 
 
131
 
        /* sanity checks */
132
 
        assert((partition_index >= 0) && (partition_index <= 3));
133
 
 
134
 
        /* compute geometry */
135
 
        pc_chd_locate_block(image, first_block, &first_cylinder, &first_head, &first_sector);
136
 
        pc_chd_locate_block(image, first_block + block_count - 1, &last_cylinder, &last_head, &last_sector);
137
 
 
138
 
        /* load fat_partition_create */
139
 
        fat_partition_create = (imgtoolerr_t (*)(imgtool_image *, UINT64, UINT64))
140
 
                imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_CREATE_PARTITION);
141
 
 
142
 
        /* first create the actual partition */
143
 
        err = fat_partition_create(image, first_block, block_count);
144
 
        if (err)
145
 
                goto done;
146
 
 
147
 
        /* read the first block of the partition, to determine the type of FAT */
148
 
        err = imgtool_image_read_block(image, first_block, partition_block);
149
 
        if (err)
150
 
                goto done;
151
 
        fat_type = &partition_block[54];
152
 
        if (!memcmp(fat_type, fat8_string, sizeof(fat8_string)))
153
 
                partition_type = 0x01;
154
 
        else if (!memcmp(fat_type, fat12_string, sizeof(fat12_string)))
155
 
                partition_type = 0x01;
156
 
        else if ((!memcmp(fat_type, fat16_string, sizeof(fat16_string))) && (block_count < 32*1024*1024/FAT_SECLEN))
157
 
                partition_type = 0x04;
158
 
        else if ((!memcmp(fat_type, fat16_string, sizeof(fat16_string))) && (block_count >= 32*1024*1024/FAT_SECLEN))
159
 
                partition_type = 0x06;
160
 
        else
161
 
                partition_type = 0x0B;
162
 
 
163
 
        /* read the partition header */
164
 
        err = imgtool_image_read_block(image, 0, header_block);
165
 
        if (err)
166
 
                goto done;
167
 
 
168
 
        /* fill out the partition entry */
169
 
        partition_entry = &header_block[446 + (partition_index * 16)];
170
 
        place_integer_le(partition_entry,  0, 1, 0x80);
171
 
        place_integer_le(partition_entry,  1, 1, first_head);
172
 
        place_integer_le(partition_entry,  2, 1, ((first_sector & 0x3F) | (first_cylinder >> 8 << 2)));
173
 
        place_integer_le(partition_entry,  3, 1, first_cylinder);
174
 
        place_integer_le(partition_entry,  4, 1, partition_type);
175
 
        place_integer_le(partition_entry,  5, 1, last_head);
176
 
        place_integer_le(partition_entry,  6, 1, ((last_sector & 0x3F) | (last_cylinder >> 8 << 2)));
177
 
        place_integer_le(partition_entry,  7, 1, last_cylinder);
178
 
        place_integer_le(partition_entry,  8, 4, first_block);
179
 
        place_integer_le(partition_entry, 12, 4, block_count);
180
 
 
181
 
        /* write the partition header */
182
 
        err = imgtool_image_write_block(image, 0, header_block);
183
 
        if (err)
184
 
                goto done;
185
 
 
186
 
done:
187
 
        return err;
188
 
}
189
 
 
190
 
 
191
 
 
192
 
static imgtoolerr_t pc_chd_read_partition_header(imgtool_image *image)
193
 
{
194
 
        imgtoolerr_t err;
195
 
        int i;
196
 
        const UINT8 *partition_info;
197
 
        pc_chd_image_info *info;
198
 
        UINT8 buffer[FAT_SECLEN];
199
 
 
200
 
        info = pc_chd_get_image_info(image);
201
 
 
202
 
        /* read the initial block */
203
 
        err = imgtool_image_read_block(image, 0, buffer);
204
 
        if (err)
205
 
                return err;
206
 
 
207
 
        /* magic bytes present? */
208
 
        if ((buffer[510] != 0x55) || (buffer[511] != 0xAA))
209
 
                return IMGTOOLERR_CORRUPTIMAGE;
210
 
 
211
 
        for (i = 0; i < ARRAY_LENGTH(info->partitions); i++)
212
 
        {
213
 
                partition_info = &buffer[446 + i * 16];
214
 
 
215
 
                info->partitions[i].partition_type      = partition_info[4];
216
 
                info->partitions[i].starting_head       = partition_info[1];
217
 
                info->partitions[i].starting_track      = ((partition_info[2] << 2) & 0xFF00) | partition_info[3];
218
 
                info->partitions[i].starting_sector     = partition_info[2] & 0x3F;
219
 
                info->partitions[i].ending_head         = partition_info[5];
220
 
                info->partitions[i].ending_track        = ((partition_info[6] << 2) & 0xFF00) | partition_info[7];
221
 
                info->partitions[i].ending_sector       = partition_info[6] & 0x3F;
222
 
 
223
 
                info->partitions[i].sector_index        = pick_integer_le(partition_info,  8, 4);
224
 
                info->partitions[i].total_sectors       = pick_integer_le(partition_info, 12, 4);
225
 
 
226
 
                if (info->partitions[i].starting_track > info->partitions[i].ending_track)
227
 
                        return IMGTOOLERR_CORRUPTIMAGE;
228
 
        }
229
 
        return IMGTOOLERR_SUCCESS;
230
 
}
231
 
 
232
 
 
233
 
 
234
 
static imgtoolerr_t pc_chd_image_create(imgtool_image *image, imgtool_stream *f, option_resolution *opts)
235
 
{
236
 
        imgtoolerr_t err;
237
 
        UINT32 cylinders, heads, sectors;
238
 
        pc_chd_image_info *info;
239
 
        UINT8 header_block[FAT_SECLEN];
240
 
 
241
 
        cylinders = option_resolution_lookup_int(opts, 'T');
242
 
        heads = option_resolution_lookup_int(opts, 'H');
243
 
        sectors = option_resolution_lookup_int(opts, 'S');
244
 
 
245
 
        info = pc_chd_get_image_info(image);
246
 
 
247
 
        /* create the hard disk image */
248
 
        err = imghd_create(f, 0, cylinders, heads, sectors, FAT_SECLEN);
249
 
        if (err)
250
 
                goto done;
251
 
 
252
 
        err = imghd_open(f, &info->hard_disk);
253
 
        if (err)
254
 
                goto done;
255
 
 
256
 
        /* set up partition header block */
257
 
        memset(header_block, 0, sizeof(header_block));
258
 
        header_block[510] = 0x55;
259
 
        header_block[511] = 0xAA;
260
 
        err = imgtool_image_write_block(image, 0, header_block);
261
 
        if (err)
262
 
                goto done;
263
 
 
264
 
        err = pc_chd_partition_create(image, 0, 1, cylinders * heads * sectors - 1);
265
 
        if (err)
266
 
                goto done;
267
 
 
268
 
        err = pc_chd_read_partition_header(image);
269
 
        if (err)
270
 
                goto done;
271
 
 
272
 
done:
273
 
        if (err)
274
 
                imghd_close(&info->hard_disk);
275
 
        return err;
276
 
}
277
 
 
278
 
 
279
 
 
280
 
static imgtoolerr_t pc_chd_image_open(imgtool_image *image, imgtool_stream *stream)
281
 
{
282
 
        imgtoolerr_t err;
283
 
        pc_chd_image_info *info;
284
 
 
285
 
        info = pc_chd_get_image_info(image);
286
 
 
287
 
        /* open the hard drive */
288
 
        err = imghd_open(stream, &info->hard_disk);
289
 
        if (err)
290
 
                return err;
291
 
 
292
 
        err = pc_chd_read_partition_header(image);
293
 
        if (err)
294
 
                return err;
295
 
 
296
 
        return IMGTOOLERR_SUCCESS;
297
 
}
298
 
 
299
 
 
300
 
 
301
 
static void pc_chd_image_close(imgtool_image *image)
302
 
{
303
 
        pc_chd_image_info *info;
304
 
        info = pc_chd_get_image_info(image);
305
 
        imghd_close(&info->hard_disk);
306
 
}
307
 
 
308
 
 
309
 
 
310
 
static imgtoolerr_t pc_chd_image_get_geometry(imgtool_image *image, UINT32 *tracks, UINT32 *heads, UINT32 *sectors)
311
 
{
312
 
        pc_chd_image_info *info;
313
 
        const hard_disk_info *hd_info;
314
 
 
315
 
        info = pc_chd_get_image_info(image);
316
 
        hd_info = imghd_get_header(&info->hard_disk);
317
 
 
318
 
        *tracks = hd_info->cylinders;
319
 
        *heads = hd_info->heads;
320
 
        *sectors = hd_info->sectors;
321
 
        return IMGTOOLERR_SUCCESS;
322
 
}
323
 
 
324
 
 
325
 
 
326
 
static imgtoolerr_t     pc_chd_image_getsectorsize(imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, UINT32 *sector_size)
327
 
{
328
 
        pc_chd_image_info *info;
329
 
        info = pc_chd_get_image_info(image);
330
 
        *sector_size = imghd_get_header(&info->hard_disk)->sectorbytes;
331
 
        return IMGTOOLERR_SUCCESS;
332
 
}
333
 
 
334
 
 
335
 
 
336
 
static UINT32 pc_chd_calc_lbasector(pc_chd_image_info *info, UINT32 track, UINT32 head, UINT32 sector)
337
 
{
338
 
        UINT32 lbasector;
339
 
        const hard_disk_info *hd_info;
340
 
 
341
 
        hd_info = imghd_get_header(&info->hard_disk);
342
 
        lbasector = track;
343
 
        lbasector *= hd_info->heads;
344
 
        lbasector += head;
345
 
        lbasector *= hd_info->sectors;
346
 
        lbasector += sector;
347
 
        return lbasector;
348
 
}
349
 
 
350
 
 
351
 
 
352
 
static imgtoolerr_t     pc_chd_image_readsector(imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, void *buffer, size_t len)
353
 
{
354
 
        pc_chd_image_info *info;
355
 
        info = pc_chd_get_image_info(image);
356
 
        return imghd_read(&info->hard_disk,
357
 
                pc_chd_calc_lbasector(info, track, head, sector),
358
 
                buffer);
359
 
}
360
 
 
361
 
 
362
 
 
363
 
static imgtoolerr_t     pc_chd_image_writesector(imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, const void *buffer, size_t len, int ddam)
364
 
{
365
 
        pc_chd_image_info *info;
366
 
        info = pc_chd_get_image_info(image);
367
 
        return imghd_write(&info->hard_disk,
368
 
                pc_chd_calc_lbasector(info, track, head, sector),
369
 
                buffer);
370
 
}
371
 
 
372
 
 
373
 
 
374
 
static imgtoolerr_t pc_chd_image_readblock(imgtool_image *image, void *buffer, UINT64 block)
375
 
{
376
 
        pc_chd_image_info *info;
377
 
        info = pc_chd_get_image_info(image);
378
 
        return imghd_read(&info->hard_disk, block, buffer);
379
 
}
380
 
 
381
 
 
382
 
 
383
 
static imgtoolerr_t pc_chd_image_writeblock(imgtool_image *image, const void *buffer, UINT64 block)
384
 
{
385
 
        pc_chd_image_info *info;
386
 
        info = pc_chd_get_image_info(image);
387
 
        return imghd_write(&info->hard_disk, block, buffer);
388
 
}
389
 
 
390
 
 
391
 
 
392
 
static imgtoolerr_t pc_chd_list_partitions(imgtool_image *image, imgtool_partition_info *partitions, size_t len)
393
 
{
394
 
        pc_chd_image_info *info;
395
 
        size_t i;
396
 
 
397
 
        info = pc_chd_get_image_info(image);
398
 
 
399
 
        for (i = 0; i < MIN(4, len); i++)
400
 
        {
401
 
                partitions[i].base_block        = info->partitions[i].sector_index;
402
 
                partitions[i].block_count       = info->partitions[i].total_sectors;
403
 
 
404
 
                switch(info->partitions[i].partition_type)
405
 
                {
406
 
                        case 0x00:      /* Empty Partition */
407
 
                                partitions[i].get_info = NULL;
408
 
                                break;
409
 
 
410
 
                        case 0x01:      /* FAT12 */
411
 
                        case 0x04:      /* FAT16 (-32 MB) */
412
 
                        case 0x06:      /* FAT16 (32+ MB) */
413
 
                        case 0x0B:      /* FAT32 */
414
 
                        case 0x0C:      /* FAT32 (LBA Mapped) */
415
 
                        case 0x0E:      /* FAT16 (LBA Mapped) */
416
 
                        case 0x11:      /* OS/2 FAT12 */
417
 
                        case 0x14:      /* OS/2 FAT16 (-32 MB) */
418
 
                        case 0x16:      /* OS/2 FAT16 (32+ MB) */
419
 
                        case 0x1B:      /* Hidden Win95 FAT32 */
420
 
                        case 0x1C:      /* Hidden Win95 FAT32 (LBA Mapped) */
421
 
                        case 0x1D:      /* Hidden Win95 FAT16 (LBA Mapped) */
422
 
                        case 0xC1:      /* DR-DOS FAT12 */
423
 
                        case 0xC4:      /* DR-DOS FAT16 (-32 MB) */
424
 
                        case 0xC6:      /* DR-DOS FAT16 (32+ MB) */
425
 
                        case 0xD1:      /* Old Multiuser DOS FAT12 */
426
 
                        case 0xD4:      /* Old Multiuser DOS FAT16 (-32 MB) */
427
 
                        case 0xD6:      /* Old Multiuser DOS FAT16 (32+ MB) */
428
 
                                partitions[i].get_info = fat_get_info;
429
 
                                break;
430
 
 
431
 
                        default:
432
 
                                partitions[i].get_info = unknown_partition_get_info;
433
 
                                break;
434
 
                }
435
 
        }
436
 
        return IMGTOOLERR_SUCCESS;
437
 
}
438
 
 
439
 
 
440
 
 
441
 
void pc_chd_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
442
 
{
443
 
        switch(state)
444
 
        {
445
 
                /* --- the following bits of info are returned as 64-bit signed integers --- */
446
 
                case IMGTOOLINFO_INT_BLOCK_SIZE:                                        info->i = FAT_SECLEN; break;
447
 
                case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES:                         info->i = sizeof(pc_chd_image_info); break;
448
 
                case IMGTOOLINFO_INT_TRACKS_ARE_CALLED_CYLINDERS:       info->i = 1; break;
449
 
 
450
 
                /* --- the following bits of info are returned as NULL-terminated strings --- */
451
 
                case IMGTOOLINFO_STR_NAME:                                                      strcpy(info->s = imgtool_temp_str(), "pc_chd"); break;
452
 
                case IMGTOOLINFO_STR_DESCRIPTION:                                       strcpy(info->s = imgtool_temp_str(), "PC CHD disk image"); break;
453
 
                case IMGTOOLINFO_STR_FILE_EXTENSIONS:                           strcpy(info->s = imgtool_temp_str(), "chd"); break;
454
 
                case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC:                       strcpy(info->s = imgtool_temp_str(), pc_chd_create_optionspec); break;
455
 
 
456
 
                /* --- the following bits of info are returned as pointers to data or functions --- */
457
 
                case IMGTOOLINFO_PTR_CREATE:                                            info->create = pc_chd_image_create; break;
458
 
                case IMGTOOLINFO_PTR_OPEN:                                                      info->open = pc_chd_image_open; break;
459
 
                case IMGTOOLINFO_PTR_CLOSE:                                                     info->close = pc_chd_image_close; break;
460
 
                case IMGTOOLINFO_PTR_READ_SECTOR:                                       info->read_sector = pc_chd_image_readsector; break;
461
 
                case IMGTOOLINFO_PTR_WRITE_SECTOR:                                      info->write_sector = pc_chd_image_writesector; break;
462
 
                case IMGTOOLINFO_PTR_READ_BLOCK:                                        info->read_block = pc_chd_image_readblock; break;
463
 
                case IMGTOOLINFO_PTR_WRITE_BLOCK:                                       info->write_block = pc_chd_image_writeblock; break;
464
 
                case IMGTOOLINFO_PTR_GET_SECTOR_SIZE:                           info->get_sector_size = pc_chd_image_getsectorsize; break;
465
 
                case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE:                      info->createimage_optguide = pc_chd_create_optionguide; break;
466
 
                case IMGTOOLINFO_PTR_GET_GEOMETRY:                                      info->get_geometry = pc_chd_image_get_geometry; break;
467
 
                case IMGTOOLINFO_PTR_LIST_PARTITIONS:                           info->list_partitions = pc_chd_list_partitions; break;
468
 
        }
469
 
}