~youscribe/parted/3.1

« back to all changes in this revision

Viewing changes to libparted/labels/pc98.c

  • Committer: Guilhem Lettron
  • Date: 2012-10-22 14:37:59 UTC
  • Revision ID: guilhem+ubuntu@lettron.fr-20121022143759-m403kecgz13sknvp
3.1 from tarball

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    libparted - a library for manipulating disk partitions
 
3
    Copyright (C) 2000-2001, 2007-2012 Free Software Foundation, Inc.
 
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
#include <config.h>
 
20
 
 
21
#include <parted/parted.h>
 
22
#include <parted/debug.h>
 
23
#include <parted/endian.h>
 
24
 
 
25
#include "pt-tools.h"
 
26
 
 
27
#if ENABLE_NLS
 
28
#  include <libintl.h>
 
29
#  define _(String) dgettext (PACKAGE, String)
 
30
#else
 
31
#  define _(String) (String)
 
32
#endif /* ENABLE_NLS */
 
33
 
 
34
/* hacked from Linux/98 source: fs/partitions/nec98.h
 
35
 *
 
36
 * See also:
 
37
 *      http://people.FreeBSD.org/~kato/pc98.html
 
38
 *      http://www.kmc.kyoto-u.ac.jp/proj/linux98/index-english.html
 
39
 *
 
40
 * Partition types:
 
41
 *
 
42
 *   id0(mid):
 
43
 *      bit 7: 1=bootable, 0=not bootable
 
44
 *        # Linux uses this flag to make a distinction between ext2 and swap.
 
45
 *      bit 6--0:
 
46
 *        00H      : N88-BASIC(data)?, PC-UX(data)?
 
47
 *        04H      : PC-UX(data)
 
48
 *        06H      : N88-BASIC
 
49
 *        10H      : N88-BASIC
 
50
 *        14H      : *BSD, PC-UX
 
51
 *        20H      : DOS(data), Windows95/98/NT, Linux
 
52
 *        21H..2FH : DOS(system#1 .. system#15)
 
53
 *        40H      : Minix
 
54
 *
 
55
 *   id1(sid):
 
56
 *      bit 7: 1=active, 0=sleep(hidden)
 
57
 *        # PC-UX uses this flag to make a distinction between its file system
 
58
 *        # and its swap.
 
59
 *      bit 6--0:
 
60
 *        01H: FAT12
 
61
 *        11H: FAT16, <32MB [accessible to DOS 3.3]
 
62
 *        21H: FAT16, >=32MB [Large Partition]
 
63
 *        31H: NTFS
 
64
 *        28H: Windows NT (Volume/Stripe Set?)
 
65
 *        41H: Windows NT (Volume/Stripe Set?)
 
66
 *        48H: Windows NT (Volume/Stripe Set?)
 
67
 *        61H: FAT32
 
68
 *        04H: PC-UX
 
69
 *        06H: N88-BASIC
 
70
 *        44H: *BSD
 
71
 *        62H: ext2, linux-swap
 
72
 */
 
73
 
 
74
#define MAX_PART_COUNT 16
 
75
#define PC9800_EXTFMT_MAGIC 0xAA55
 
76
 
 
77
#define BIT(x) (1 << (x))
 
78
#define GET_BIT(n,bit) (((n) & BIT(bit)) != 0)
 
79
#define SET_BIT(n,bit,val) n = (val)?  (n | BIT(bit))  :  (n & ~BIT(bit))
 
80
 
 
81
typedef struct _PC98RawPartition        PC98RawPartition;
 
82
typedef struct _PC98RawTable            PC98RawTable;
 
83
 
 
84
/* ripped from Linux/98 source */
 
85
struct _PC98RawPartition {
 
86
        uint8_t         mid;            /* 0x80 - boot */
 
87
        uint8_t         sid;            /* 0x80 - active */
 
88
        uint8_t         dum1;           /* dummy for padding */
 
89
        uint8_t         dum2;           /* dummy for padding */
 
90
        uint8_t         ipl_sect;       /* IPL sector */
 
91
        uint8_t         ipl_head;       /* IPL head */
 
92
        uint16_t        ipl_cyl;        /* IPL cylinder */
 
93
        uint8_t         sector;         /* starting sector */
 
94
        uint8_t         head;           /* starting head */
 
95
        uint16_t        cyl;            /* starting cylinder */
 
96
        uint8_t         end_sector;     /* end sector */
 
97
        uint8_t         end_head;       /* end head */
 
98
        uint16_t        end_cyl;        /* end cylinder */
 
99
        char            name[16];
 
100
} __attribute__((packed));
 
101
 
 
102
struct _PC98RawTable {
 
103
        uint8_t                 boot_code [510];
 
104
        uint16_t                magic;
 
105
        PC98RawPartition        partitions [MAX_PART_COUNT];
 
106
} __attribute__((packed));
 
107
 
 
108
typedef struct {
 
109
        PedSector       ipl_sector;
 
110
        int             system;
 
111
        int             boot;
 
112
        int             hidden;
 
113
        char            name [17];
 
114
} PC98PartitionData;
 
115
 
 
116
/* this MBR boot code is dummy */
 
117
static const char MBR_BOOT_CODE[] = {
 
118
        0xcb,                   /* retf */
 
119
        0x00, 0x00, 0x00,       /* */
 
120
        0x49, 0x50, 0x4c, 0x31  /* "IPL1" */
 
121
};
 
122
 
 
123
static PedDiskType pc98_disk_type;
 
124
 
 
125
static PedSector chs_to_sector (const PedDevice* dev, int c, int h, int s);
 
126
static void sector_to_chs (const PedDevice* dev, PedSector sector,
 
127
                           int* c, int* h, int* s);
 
128
 
 
129
/* magic(?) check */
 
130
static int
 
131
pc98_check_magic (const PC98RawTable *part_table)
 
132
{
 
133
        /* check "extended-format" (have partition table?) */
 
134
        if (PED_LE16_TO_CPU(part_table->magic) != PC9800_EXTFMT_MAGIC)
 
135
                return 0;
 
136
 
 
137
        return 1;
 
138
}
 
139
 
 
140
static int
 
141
pc98_check_ipl_signature (const PC98RawTable *part_table)
 
142
{
 
143
        if (memcmp (part_table->boot_code + 4, "IPL1", 4) == 0)
 
144
                return 1;
 
145
        else if (memcmp (part_table->boot_code + 4, "Linux 98", 8) == 0)
 
146
                return 1;
 
147
        else if (memcmp (part_table->boot_code + 4, "GRUB/98 ", 8) == 0)
 
148
                return 1;
 
149
        else
 
150
                return 0;
 
151
}
 
152
 
 
153
static int
 
154
pc98_probe (const PedDevice *dev)
 
155
{
 
156
        PC98RawTable            part_table;
 
157
 
 
158
        PED_ASSERT (dev != NULL);
 
159
 
 
160
        if (dev->sector_size != 512)
 
161
                return 0;
 
162
 
 
163
        if (!ped_device_read (dev, &part_table, 0, 2))
 
164
                return 0;
 
165
 
 
166
        /* check magic */
 
167
        if (!pc98_check_magic (&part_table))
 
168
                return 0;
 
169
 
 
170
        /* check for boot loader signatures */
 
171
        return pc98_check_ipl_signature (&part_table);
 
172
}
 
173
 
 
174
static PedDisk*
 
175
pc98_alloc (const PedDevice* dev)
 
176
{
 
177
        PED_ASSERT (dev != NULL);
 
178
 
 
179
        return _ped_disk_alloc (dev, &pc98_disk_type);
 
180
}
 
181
 
 
182
static PedDisk*
 
183
pc98_duplicate (const PedDisk* disk)
 
184
{
 
185
        return ped_disk_new_fresh (disk->dev, &pc98_disk_type);
 
186
}
 
187
 
 
188
static void
 
189
pc98_free (PedDisk* disk)
 
190
{
 
191
        PED_ASSERT (disk != NULL);
 
192
 
 
193
        _ped_disk_free (disk);
 
194
}
 
195
 
 
196
static PedSector _GL_ATTRIBUTE_PURE
 
197
chs_to_sector (const PedDevice* dev, int c, int h, int s)
 
198
{
 
199
        PED_ASSERT (dev != NULL);
 
200
        return (c * dev->hw_geom.heads + h) * dev->hw_geom.sectors + s;
 
201
}
 
202
 
 
203
static void
 
204
sector_to_chs (const PedDevice* dev, PedSector sector, int* c, int* h, int* s)
 
205
{
 
206
        PedSector cyl_size;
 
207
 
 
208
        PED_ASSERT (dev != NULL);
 
209
        PED_ASSERT (c != NULL);
 
210
        PED_ASSERT (h != NULL);
 
211
        PED_ASSERT (s != NULL);
 
212
 
 
213
        cyl_size = dev->hw_geom.heads * dev->hw_geom.sectors;
 
214
 
 
215
        *c = sector / cyl_size;
 
216
        *h = (sector) % cyl_size / dev->hw_geom.sectors;
 
217
        *s = (sector) % cyl_size % dev->hw_geom.sectors;
 
218
}
 
219
 
 
220
static PedSector _GL_ATTRIBUTE_PURE
 
221
legacy_start (const PedDisk* disk, const PC98RawPartition* raw_part)
 
222
{
 
223
        PED_ASSERT (disk != NULL);
 
224
        PED_ASSERT (raw_part != NULL);
 
225
 
 
226
        return chs_to_sector (disk->dev, PED_LE16_TO_CPU(raw_part->cyl),
 
227
                              raw_part->head, raw_part->sector);
 
228
}
 
229
 
 
230
static PedSector _GL_ATTRIBUTE_PURE
 
231
legacy_end (const PedDisk* disk, const PC98RawPartition* raw_part)
 
232
{
 
233
        PED_ASSERT (disk != NULL);
 
234
        PED_ASSERT (raw_part != NULL);
 
235
 
 
236
        if (raw_part->end_head == 0 && raw_part->end_sector == 0) {
 
237
                return chs_to_sector (disk->dev,
 
238
                                      PED_LE16_TO_CPU(raw_part->end_cyl),
 
239
                                      disk->dev->hw_geom.heads - 1,
 
240
                                      disk->dev->hw_geom.sectors - 1);
 
241
        } else {
 
242
                return chs_to_sector (disk->dev,
 
243
                                      PED_LE16_TO_CPU(raw_part->end_cyl),
 
244
                                      raw_part->end_head,
 
245
                                      raw_part->end_sector);
 
246
        }
 
247
}
 
248
 
 
249
static int
 
250
is_unused_partition(const PC98RawPartition* raw_part)
 
251
{
 
252
        if (raw_part->mid || raw_part->sid
 
253
            || raw_part->ipl_sect
 
254
            || raw_part->ipl_head
 
255
            || PED_LE16_TO_CPU(raw_part->ipl_cyl)
 
256
            || raw_part->sector
 
257
            || raw_part->head
 
258
            || PED_LE16_TO_CPU(raw_part->cyl)
 
259
            || raw_part->end_sector
 
260
            || raw_part->end_head
 
261
            || PED_LE16_TO_CPU(raw_part->end_cyl))
 
262
                return 0;
 
263
        return 1;
 
264
}
 
265
 
 
266
static int
 
267
read_table (PedDisk* disk)
 
268
{
 
269
        int                     i;
 
270
        PC98RawTable            table;
 
271
        PedConstraint*          constraint_any;
 
272
 
 
273
        PED_ASSERT (disk != NULL);
 
274
        PED_ASSERT (disk->dev != NULL);
 
275
 
 
276
        constraint_any = ped_constraint_any (disk->dev);
 
277
 
 
278
        if (!ped_device_read (disk->dev, (void*) &table, 0, 2))
 
279
                goto error;
 
280
 
 
281
        if (!pc98_check_magic(&table)) {
 
282
                if (ped_exception_throw (
 
283
                        PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL,
 
284
                        _("Invalid partition table on %s."),
 
285
                        disk->dev->path))
 
286
                        goto error;
 
287
        }
 
288
 
 
289
        for (i = 0; i < MAX_PART_COUNT; i++) {
 
290
                PC98RawPartition*       raw_part;
 
291
                PedPartition*           part;
 
292
                PC98PartitionData*      pc98_data;
 
293
                PedSector               part_start;
 
294
                PedSector               part_end;
 
295
 
 
296
                raw_part = &table.partitions [i];
 
297
 
 
298
                if (is_unused_partition(raw_part))
 
299
                        continue;
 
300
 
 
301
                part_start = legacy_start (disk, raw_part);
 
302
                part_end   = legacy_end (disk, raw_part);
 
303
 
 
304
                part = ped_partition_new (disk, PED_PARTITION_NORMAL,
 
305
                                          NULL, part_start, part_end);
 
306
                if (!part)
 
307
                        goto error;
 
308
                pc98_data = part->disk_specific;
 
309
                PED_ASSERT (pc98_data != NULL);
 
310
 
 
311
                pc98_data->system = (raw_part->mid << 8) | raw_part->sid;
 
312
                pc98_data->boot = GET_BIT(raw_part->mid, 7);
 
313
                pc98_data->hidden = !GET_BIT(raw_part->sid, 7);
 
314
 
 
315
                ped_partition_set_name (part, raw_part->name);
 
316
 
 
317
                pc98_data->ipl_sector = chs_to_sector (
 
318
                        disk->dev,
 
319
                        PED_LE16_TO_CPU(raw_part->ipl_cyl),
 
320
                        raw_part->ipl_head,
 
321
                        raw_part->ipl_sect);
 
322
 
 
323
                /* hack */
 
324
                if (pc98_data->ipl_sector == part->geom.start)
 
325
                        pc98_data->ipl_sector = 0;
 
326
 
 
327
                part->num = i + 1;
 
328
 
 
329
                if (!ped_disk_add_partition (disk, part, constraint_any))
 
330
                        goto error;
 
331
 
 
332
                if (part->geom.start != part_start
 
333
                    || part->geom.end != part_end) {
 
334
                        ped_exception_throw (
 
335
                                PED_EXCEPTION_NO_FEATURE,
 
336
                                PED_EXCEPTION_CANCEL,
 
337
                                _("Partition %d isn't aligned to cylinder "
 
338
                                  "boundaries.  This is still unsupported."),
 
339
                                part->num);
 
340
                        goto error;
 
341
                }
 
342
 
 
343
                part->fs_type = ped_file_system_probe (&part->geom);
 
344
        }
 
345
 
 
346
        ped_constraint_destroy (constraint_any);
 
347
        return 1;
 
348
 
 
349
error:
 
350
        ped_disk_delete_all (disk);
 
351
        ped_constraint_destroy (constraint_any);
 
352
        return 0;
 
353
}
 
354
 
 
355
static int
 
356
pc98_read (PedDisk* disk)
 
357
{
 
358
        PED_ASSERT (disk != NULL);
 
359
        PED_ASSERT (disk->dev != NULL);
 
360
 
 
361
        ped_disk_delete_all (disk);
 
362
        return read_table (disk);
 
363
}
 
364
 
 
365
#ifndef DISCOVER_ONLY
 
366
static int
 
367
fill_raw_part (PC98RawPartition* raw_part, const PedPartition* part)
 
368
{
 
369
        PC98PartitionData*      pc98_data;
 
370
        int                     c, h, s;
 
371
        const char*             name;
 
372
 
 
373
        PED_ASSERT (raw_part != NULL);
 
374
        PED_ASSERT (part != NULL);
 
375
        PED_ASSERT (part->disk_specific != NULL);
 
376
 
 
377
        pc98_data = part->disk_specific;
 
378
        raw_part->mid = (pc98_data->system >> 8) & 0xFF;
 
379
        raw_part->sid = pc98_data->system & 0xFF;
 
380
 
 
381
        SET_BIT(raw_part->mid, 7, pc98_data->boot);
 
382
        SET_BIT(raw_part->sid, 7, !pc98_data->hidden);
 
383
 
 
384
        memset (raw_part->name, ' ', sizeof(raw_part->name));
 
385
        name = ped_partition_get_name (part);
 
386
        PED_ASSERT (name != NULL);
 
387
        PED_ASSERT (strlen (name) <= 16);
 
388
        if (!strlen (name) && part->fs_type)
 
389
                name = part->fs_type->name;
 
390
        memcpy (raw_part->name, name, strlen (name));
 
391
 
 
392
        sector_to_chs (part->disk->dev, part->geom.start, &c, &h, &s);
 
393
        raw_part->cyl    = PED_CPU_TO_LE16(c);
 
394
        raw_part->head   = h;
 
395
        raw_part->sector = s;
 
396
 
 
397
        if (pc98_data->ipl_sector) {
 
398
                sector_to_chs (part->disk->dev, pc98_data->ipl_sector,
 
399
                               &c, &h, &s);
 
400
                raw_part->ipl_cyl  = PED_CPU_TO_LE16(c);
 
401
                raw_part->ipl_head = h;
 
402
                raw_part->ipl_sect = s;
 
403
        } else {
 
404
                raw_part->ipl_cyl  = raw_part->cyl;
 
405
                raw_part->ipl_head = raw_part->head;
 
406
                raw_part->ipl_sect = raw_part->sector;
 
407
        }
 
408
 
 
409
        sector_to_chs (part->disk->dev, part->geom.end, &c, &h, &s);
 
410
        if (h != part->disk->dev->hw_geom.heads - 1
 
411
            || s != part->disk->dev->hw_geom.sectors - 1) {
 
412
                ped_exception_throw (
 
413
                    PED_EXCEPTION_NO_FEATURE,
 
414
                    PED_EXCEPTION_CANCEL,
 
415
                    _("Partition %d isn't aligned to cylinder "
 
416
                      "boundaries.  This is still unsupported."),
 
417
                    part->num);
 
418
                return 0;
 
419
        }
 
420
        raw_part->end_cyl    = PED_CPU_TO_LE16(c);
 
421
#if 0
 
422
        raw_part->end_head   = h;
 
423
        raw_part->end_sector = s;
 
424
#else
 
425
        raw_part->end_head   = 0;
 
426
        raw_part->end_sector = 0;
 
427
#endif
 
428
 
 
429
        return 1;
 
430
}
 
431
 
 
432
static int
 
433
pc98_write (const PedDisk* disk)
 
434
{
 
435
        PedPartition*           part;
 
436
        int                     i;
 
437
 
 
438
        PED_ASSERT (disk != NULL);
 
439
        PED_ASSERT (disk->dev != NULL);
 
440
 
 
441
        void *s0;
 
442
        if (!ptt_read_sectors (disk->dev, 0, 2, &s0))
 
443
                return 0;
 
444
        PC98RawTable *table = s0;
 
445
 
 
446
        if (!pc98_check_ipl_signature (table)) {
 
447
                memset (table->boot_code, 0, sizeof(table->boot_code));
 
448
                memcpy (table->boot_code, MBR_BOOT_CODE, sizeof(MBR_BOOT_CODE));
 
449
        }
 
450
 
 
451
        memset (table->partitions, 0, sizeof (table->partitions));
 
452
        table->magic = PED_CPU_TO_LE16(PC9800_EXTFMT_MAGIC);
 
453
 
 
454
        for (i = 1; i <= MAX_PART_COUNT; i++) {
 
455
                part = ped_disk_get_partition (disk, i);
 
456
                if (!part)
 
457
                        continue;
 
458
 
 
459
                if (!fill_raw_part (&table->partitions [i - 1], part))
 
460
                        return 0;
 
461
        }
 
462
 
 
463
        int write_ok = ped_device_write (disk->dev, table, 0, 2);
 
464
        free (s0);
 
465
        if (!write_ok)
 
466
                return 0;
 
467
        return ped_device_sync (disk->dev);
 
468
}
 
469
#endif /* !DISCOVER_ONLY */
 
470
 
 
471
static PedPartition*
 
472
pc98_partition_new (
 
473
        const PedDisk* disk, PedPartitionType part_type,
 
474
        const PedFileSystemType* fs_type, PedSector start, PedSector end)
 
475
{
 
476
        PedPartition*           part;
 
477
        PC98PartitionData*      pc98_data;
 
478
 
 
479
        part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
 
480
        if (!part)
 
481
                goto error;
 
482
 
 
483
        if (ped_partition_is_active (part)) {
 
484
                part->disk_specific
 
485
                        = pc98_data = ped_malloc (sizeof (PC98PartitionData));
 
486
                if (!pc98_data)
 
487
                        goto error_free_part;
 
488
                pc98_data->ipl_sector = 0;
 
489
                pc98_data->hidden = 0;
 
490
                pc98_data->boot = 0;
 
491
                strcpy (pc98_data->name, "");
 
492
        } else {
 
493
                part->disk_specific = NULL;
 
494
        }
 
495
        return part;
 
496
 
 
497
error_free_part:
 
498
        free (part);
 
499
error:
 
500
        return 0;
 
501
}
 
502
 
 
503
static PedPartition*
 
504
pc98_partition_duplicate (const PedPartition* part)
 
505
{
 
506
        PedPartition*           new_part;
 
507
        PC98PartitionData*      new_pc98_data;
 
508
        PC98PartitionData*      old_pc98_data;
 
509
 
 
510
        new_part = ped_partition_new (part->disk, part->type,
 
511
                                      part->fs_type, part->geom.start,
 
512
                                      part->geom.end);
 
513
        if (!new_part)
 
514
                return NULL;
 
515
        new_part->num = part->num;
 
516
 
 
517
        old_pc98_data = (PC98PartitionData*) part->disk_specific;
 
518
        new_pc98_data = (PC98PartitionData*) new_part->disk_specific;
 
519
 
 
520
        /* ugly, but C is ugly :p */
 
521
        memcpy (new_pc98_data, old_pc98_data, sizeof (PC98PartitionData));
 
522
        return new_part;
 
523
}
 
524
 
 
525
static void
 
526
pc98_partition_destroy (PedPartition* part)
 
527
{
 
528
        PED_ASSERT (part != NULL);
 
529
 
 
530
        if (ped_partition_is_active (part))
 
531
                free (part->disk_specific);
 
532
        free (part);
 
533
}
 
534
 
 
535
static int
 
536
pc98_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
 
537
{
 
538
        PC98PartitionData* pc98_data = part->disk_specific;
 
539
 
 
540
        part->fs_type = fs_type;
 
541
 
 
542
        pc98_data->system = 0x2062;
 
543
        if (fs_type) {
 
544
                if (!strcmp (fs_type->name, "fat16")) {
 
545
                        if (part->geom.length * 512 >= 32 * 1024 * 1024)
 
546
                                pc98_data->system = 0x2021;
 
547
                        else
 
548
                                pc98_data->system = 0x2011;
 
549
                } else if (!strcmp (fs_type->name, "fat32")) {
 
550
                        pc98_data->system = 0x2061;
 
551
                } else if (!strcmp (fs_type->name, "ntfs")) {
 
552
                        pc98_data->system = 0x2031;
 
553
                } else if (!strncmp (fs_type->name, "ufs", 3)) {
 
554
                        pc98_data->system = 0x2044;
 
555
                } else { /* ext2, reiser, xfs, etc. */
 
556
                        /* ext2 partitions must be marked boot */
 
557
                        pc98_data->boot = 1;
 
558
                        pc98_data->system = 0xa062;
 
559
                }
 
560
        }
 
561
 
 
562
        if (pc98_data->boot)
 
563
                pc98_data->system |= 0x8000;
 
564
        if (!pc98_data->hidden)
 
565
                pc98_data->system |= 0x0080;
 
566
        return 1;
 
567
}
 
568
 
 
569
static int
 
570
pc98_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
 
571
{
 
572
        PC98PartitionData*              pc98_data;
 
573
 
 
574
        PED_ASSERT (part != NULL);
 
575
        PED_ASSERT (part->disk_specific != NULL);
 
576
 
 
577
        pc98_data = part->disk_specific;
 
578
 
 
579
        switch (flag) {
 
580
        case PED_PARTITION_HIDDEN:
 
581
                pc98_data->hidden = state;
 
582
                return ped_partition_set_system (part, part->fs_type);
 
583
 
 
584
        case PED_PARTITION_BOOT:
 
585
                pc98_data->boot = state;
 
586
                return ped_partition_set_system (part, part->fs_type);
 
587
 
 
588
        default:
 
589
                return 0;
 
590
        }
 
591
}
 
592
 
 
593
static int _GL_ATTRIBUTE_PURE
 
594
pc98_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
 
595
{
 
596
        PC98PartitionData*      pc98_data;
 
597
 
 
598
        PED_ASSERT (part != NULL);
 
599
        PED_ASSERT (part->disk_specific != NULL);
 
600
 
 
601
        pc98_data = part->disk_specific;
 
602
        switch (flag) {
 
603
        case PED_PARTITION_HIDDEN:
 
604
                return pc98_data->hidden;
 
605
 
 
606
        case PED_PARTITION_BOOT:
 
607
                return pc98_data->boot;
 
608
 
 
609
        default:
 
610
                return 0;
 
611
        }
 
612
}
 
613
 
 
614
static int
 
615
pc98_partition_is_flag_available (
 
616
        const PedPartition* part, PedPartitionFlag flag)
 
617
{
 
618
        switch (flag) {
 
619
        case PED_PARTITION_HIDDEN:
 
620
        case PED_PARTITION_BOOT:
 
621
                return 1;
 
622
 
 
623
        default:
 
624
                return 0;
 
625
        }
 
626
}
 
627
 
 
628
static void
 
629
pc98_partition_set_name (PedPartition* part, const char* name)
 
630
{
 
631
        PC98PartitionData*      pc98_data;
 
632
        int                     i;
 
633
 
 
634
        PED_ASSERT (part != NULL);
 
635
        PED_ASSERT (part->disk_specific != NULL);
 
636
        pc98_data = part->disk_specific;
 
637
 
 
638
        strncpy (pc98_data->name, name, 16);
 
639
        pc98_data->name [16] = 0;
 
640
        for (i = strlen (pc98_data->name) - 1; pc98_data->name[i] == ' '; i--)
 
641
                pc98_data->name [i] = 0;
 
642
}
 
643
 
 
644
static const char* _GL_ATTRIBUTE_PURE
 
645
pc98_partition_get_name (const PedPartition* part)
 
646
{
 
647
        PC98PartitionData*      pc98_data;
 
648
 
 
649
        PED_ASSERT (part != NULL);
 
650
        PED_ASSERT (part->disk_specific != NULL);
 
651
        pc98_data = part->disk_specific;
 
652
 
 
653
        return pc98_data->name;
 
654
}
 
655
 
 
656
static PedAlignment*
 
657
pc98_get_partition_alignment(const PedDisk *disk)
 
658
{
 
659
        PedSector cylinder_size =
 
660
                disk->dev->hw_geom.sectors * disk->dev->hw_geom.heads;
 
661
 
 
662
        return ped_alignment_new(0, cylinder_size);
 
663
}
 
664
 
 
665
static PedConstraint*
 
666
_primary_constraint (PedDisk* disk)
 
667
{
 
668
        PedDevice*      dev = disk->dev;
 
669
        PedAlignment    start_align;
 
670
        PedAlignment    end_align;
 
671
        PedGeometry     max_geom;
 
672
        PedSector       cylinder_size;
 
673
 
 
674
        cylinder_size = dev->hw_geom.sectors * dev->hw_geom.heads;
 
675
 
 
676
        if (!ped_alignment_init (&start_align, 0, cylinder_size))
 
677
                return NULL;
 
678
        if (!ped_alignment_init (&end_align, -1, cylinder_size))
 
679
                return NULL;
 
680
        if (!ped_geometry_init (&max_geom, dev, cylinder_size,
 
681
                                dev->length - cylinder_size))
 
682
                return NULL;
 
683
 
 
684
        return ped_constraint_new (&start_align, &end_align, &max_geom,
 
685
                                   &max_geom, 1, dev->length);
 
686
}
 
687
 
 
688
static int
 
689
pc98_partition_align (PedPartition* part, const PedConstraint* constraint)
 
690
{
 
691
        PED_ASSERT (part != NULL);
 
692
 
 
693
        if (_ped_partition_attempt_align (part, constraint,
 
694
                                          _primary_constraint (part->disk)))
 
695
                return 1;
 
696
 
 
697
#ifndef DISCOVER_ONLY
 
698
        ped_exception_throw (
 
699
                PED_EXCEPTION_ERROR,
 
700
                PED_EXCEPTION_CANCEL,
 
701
                _("Unable to satisfy all constraints on the partition."));
 
702
#endif
 
703
        return 0;
 
704
}
 
705
 
 
706
static int
 
707
next_primary (PedDisk* disk)
 
708
{
 
709
        int     i;
 
710
        for (i=1; i<=MAX_PART_COUNT; i++) {
 
711
                if (!ped_disk_get_partition (disk, i))
 
712
                        return i;
 
713
        }
 
714
        return 0;
 
715
}
 
716
 
 
717
static int
 
718
pc98_partition_enumerate (PedPartition* part)
 
719
{
 
720
        PED_ASSERT (part != NULL);
 
721
        PED_ASSERT (part->disk != NULL);
 
722
 
 
723
        /* don't re-number a partition */
 
724
        if (part->num != -1)
 
725
                return 1;
 
726
 
 
727
        PED_ASSERT (ped_partition_is_active (part));
 
728
 
 
729
        part->num = next_primary (part->disk);
 
730
        if (!part->num) {
 
731
                ped_exception_throw (PED_EXCEPTION_ERROR,
 
732
                        PED_EXCEPTION_CANCEL,
 
733
                        _("Can't add another partition."));
 
734
                return 0;
 
735
        }
 
736
 
 
737
        return 1;
 
738
}
 
739
 
 
740
static int
 
741
pc98_alloc_metadata (PedDisk* disk)
 
742
{
 
743
        PedPartition*           new_part;
 
744
        PedConstraint*          constraint_any = NULL;
 
745
        PedSector               cyl_size;
 
746
 
 
747
        PED_ASSERT (disk != NULL);
 
748
        PED_ASSERT (disk->dev != NULL);
 
749
 
 
750
        constraint_any = ped_constraint_any (disk->dev);
 
751
 
 
752
        cyl_size = disk->dev->hw_geom.sectors * disk->dev->hw_geom.heads;
 
753
        new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL,
 
754
                                      0, cyl_size - 1);
 
755
        if (!new_part)
 
756
                goto error;
 
757
 
 
758
        if (!ped_disk_add_partition (disk, new_part, constraint_any)) {
 
759
                ped_partition_destroy (new_part);
 
760
                goto error;
 
761
        }
 
762
 
 
763
        ped_constraint_destroy (constraint_any);
 
764
        return 1;
 
765
 
 
766
error:
 
767
        ped_constraint_destroy (constraint_any);
 
768
        return 0;
 
769
}
 
770
 
 
771
static int
 
772
pc98_get_max_primary_partition_count (const PedDisk* disk)
 
773
{
 
774
        return MAX_PART_COUNT;
 
775
}
 
776
 
 
777
static bool
 
778
pc98_get_max_supported_partition_count (const PedDisk* disk, int *max_n)
 
779
{
 
780
        *max_n = MAX_PART_COUNT;
 
781
        return true;
 
782
}
 
783
 
 
784
#include "pt-common.h"
 
785
PT_define_limit_functions (pc98)
 
786
 
 
787
static PedDiskOps pc98_disk_ops = {
 
788
        clobber:                NULL,
 
789
        write:                  NULL_IF_DISCOVER_ONLY (pc98_write),
 
790
 
 
791
        partition_set_name:     pc98_partition_set_name,
 
792
        partition_get_name:     pc98_partition_get_name,
 
793
 
 
794
        get_partition_alignment: pc98_get_partition_alignment,
 
795
 
 
796
        PT_op_function_initializers (pc98)
 
797
};
 
798
 
 
799
static PedDiskType pc98_disk_type = {
 
800
        next:           NULL,
 
801
        name:           "pc98",
 
802
        ops:            &pc98_disk_ops,
 
803
        features:       PED_DISK_TYPE_PARTITION_NAME
 
804
};
 
805
 
 
806
void
 
807
ped_disk_pc98_init ()
 
808
{
 
809
        PED_ASSERT (sizeof (PC98RawTable) == 512 * 2);
 
810
        ped_disk_type_register (&pc98_disk_type);
 
811
}
 
812
 
 
813
void
 
814
ped_disk_pc98_done ()
 
815
{
 
816
        ped_disk_type_unregister (&pc98_disk_type);
 
817
}