blob: 27f84a5b074fe2eef67ea6d437938d1193f83969 [file] [log] [blame]
/*
libparted - a library for manipulating disk partitions
Copyright (C) 2000, 2001, 2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <config.h>
#include <parted/parted.h>
#include <parted/debug.h>
#include <parted/endian.h>
#if ENABLE_NLS
# include <libintl.h>
# define _(String) dgettext (PACKAGE, String)
#else
# define _(String) (String)
#endif /* ENABLE_NLS */
/* hacked from Linux/98 source: fs/partitions/nec98.h
*
* See also:
* http://people.FreeBSD.org/~kato/pc98.html
* http://www.kmc.kyoto-u.ac.jp/proj/linux98/index-english.html
*
* Partition types:
*
* id0(mid):
* bit 7: 1=bootable, 0=not bootable
* # Linux uses this flag to make a distinction between ext2 and swap.
* bit 6--0:
* 00H : N88-BASIC(data)?, PC-UX(data)?
* 04H : PC-UX(data)
* 06H : N88-BASIC
* 10H : N88-BASIC
* 14H : *BSD, PC-UX
* 20H : DOS(data), Windows95/98/NT, Linux
* 21H..2FH : DOS(system#1 .. system#15)
* 40H : Minix
*
* id1(sid):
* bit 7: 1=active, 0=sleep(hidden)
* # PC-UX uses this flag to make a distinction between its file system
* # and its swap.
* bit 6--0:
* 01H: FAT12
* 11H: FAT16, <32MB [accessible to DOS 3.3]
* 21H: FAT16, >=32MB [Large Partition]
* 31H: NTFS
* 28H: Windows NT (Volume/Stripe Set?)
* 41H: Windows NT (Volume/Stripe Set?)
* 48H: Windows NT (Volume/Stripe Set?)
* 61H: FAT32
* 04H: PC-UX
* 06H: N88-BASIC
* 44H: *BSD
* 62H: ext2, linux-swap
*/
#define MAX_PART_COUNT 16
#define PC9800_EXTFMT_MAGIC 0xAA55
#define BIT(x) (1 << (x))
#define GET_BIT(n,bit) (((n) & BIT(bit)) != 0)
#define SET_BIT(n,bit,val) n = (val)? (n | BIT(bit)) : (n & ~BIT(bit))
typedef struct _PC98RawPartition PC98RawPartition;
typedef struct _PC98RawTable PC98RawTable;
/* ripped from Linux/98 source */
struct _PC98RawPartition {
uint8_t mid; /* 0x80 - boot */
uint8_t sid; /* 0x80 - active */
uint8_t dum1; /* dummy for padding */
uint8_t dum2; /* dummy for padding */
uint8_t ipl_sect; /* IPL sector */
uint8_t ipl_head; /* IPL head */
uint16_t ipl_cyl; /* IPL cylinder */
uint8_t sector; /* starting sector */
uint8_t head; /* starting head */
uint16_t cyl; /* starting cylinder */
uint8_t end_sector; /* end sector */
uint8_t end_head; /* end head */
uint16_t end_cyl; /* end cylinder */
char name[16];
} __attribute__((packed));
struct _PC98RawTable {
uint8_t boot_code [510];
uint16_t magic;
PC98RawPartition partitions [MAX_PART_COUNT];
} __attribute__((packed));
typedef struct {
PedSector ipl_sector;
int system;
int boot;
int hidden;
char name [17];
} PC98PartitionData;
/* this MBR boot code is dummy */
static const char MBR_BOOT_CODE[] = {
0xcb, /* retf */
0x00, 0x00, 0x00, /* */
0x49, 0x50, 0x4c, 0x31 /* "IPL1" */
};
static PedDiskType pc98_disk_type;
static PedSector chs_to_sector (const PedDevice* dev, int c, int h, int s);
static void sector_to_chs (const PedDevice* dev, PedSector sector,
int* c, int* h, int* s);
/* magic(?) check */
static int
pc98_check_magic (const PC98RawTable *part_table)
{
/* check "extended-format" (have partition table?) */
if (PED_LE16_TO_CPU(part_table->magic) != PC9800_EXTFMT_MAGIC)
return 0;
return 1;
}
static int
pc98_check_ipl_signature (const PC98RawTable *part_table)
{
return !memcmp (part_table->boot_code + 4, "IPL1", 4);
}
static int
check_partition_consistency (const PedDevice* dev,
const PC98RawPartition* raw_part)
{
if (raw_part->ipl_sect >= dev->hw_geom.sectors
|| raw_part->sector >= dev->hw_geom.sectors
|| raw_part->end_sector >= dev->hw_geom.sectors
|| raw_part->ipl_head >= dev->hw_geom.heads
|| raw_part->head >= dev->hw_geom.heads
|| raw_part->end_head >= dev->hw_geom.heads
|| PED_LE16_TO_CPU(raw_part->ipl_cyl) >= dev->hw_geom.cylinders
|| PED_LE16_TO_CPU(raw_part->cyl) >= dev->hw_geom.cylinders
|| PED_LE16_TO_CPU(raw_part->end_cyl) >= dev->hw_geom.cylinders
|| PED_LE16_TO_CPU(raw_part->cyl)
> PED_LE16_TO_CPU(raw_part->end_cyl)
#if 0
|| !chs_to_sector(dev, PED_LE16_TO_CPU(raw_part->ipl_cyl),
raw_part->ipl_head, raw_part->ipl_sect)
|| !chs_to_sector(dev, PED_LE16_TO_CPU(raw_part->cyl),
raw_part->head, raw_part->sector)
|| !chs_to_sector(dev, PED_LE16_TO_CPU(raw_part->end_cyl),
raw_part->end_head, raw_part->end_sector)
#endif
|| PED_LE16_TO_CPU(raw_part->end_cyl)
< PED_LE16_TO_CPU(raw_part->cyl))
return 0;
return 1;
}
static int
pc98_probe (const PedDevice *dev)
{
PC98RawTable part_table;
int empty;
const PC98RawPartition* p;
PED_ASSERT (dev != NULL, return 0);
if (dev->sector_size != 512)
return 0;
if (!ped_device_read (dev, &part_table, 0, 2))
return 0;
/* check magic */
if (!pc98_check_magic (&part_table))
return 0;
/* check consistency */
empty = 1;
for (p = part_table.partitions;
p < part_table.partitions + MAX_PART_COUNT;
p++)
{
if (p->mid == 0 && p->sid == 0)
continue;
empty = 0;
if (!check_partition_consistency (dev, p))
return 0;
}
/* check boot loader */
if (pc98_check_ipl_signature (&part_table))
return 1;
else if (part_table.boot_code[0]) /* invalid boot loader */
return 0;
/* Not to mistake msdos disk map for PC-9800's empty disk map */
if (empty)
return 0;
return 1;
}
#ifndef DISCOVER_ONLY
static int
pc98_clobber (PedDevice* dev)
{
PC98RawTable table;
PED_ASSERT (dev != NULL, return 0);
PED_ASSERT (pc98_probe (dev), return 0);
if (!ped_device_read (dev, &table, 0, 1))
return 0;
memset (table.partitions, 0, sizeof (table.partitions));
table.magic = PED_CPU_TO_LE16(0);
if (pc98_check_ipl_signature (&table))
memset (table.boot_code, 0, sizeof (table.boot_code));
if (!ped_device_write (dev, (void*) &table, 0, 1))
return 0;
return ped_device_sync (dev);
}
#endif /* !DISCOVER_ONLY */
static PedDisk*
pc98_alloc (const PedDevice* dev)
{
PED_ASSERT (dev != NULL, return 0);
return _ped_disk_alloc (dev, &pc98_disk_type);
}
static PedDisk*
pc98_duplicate (const PedDisk* disk)
{
return ped_disk_new_fresh (disk->dev, &pc98_disk_type);
}
static void
pc98_free (PedDisk* disk)
{
PED_ASSERT (disk != NULL, return);
_ped_disk_free (disk);
}
static PedSector
chs_to_sector (const PedDevice* dev, int c, int h, int s)
{
PED_ASSERT (dev != NULL, return 0);
return (c * dev->hw_geom.heads + h) * dev->hw_geom.sectors + s;
}
static void
sector_to_chs (const PedDevice* dev, PedSector sector, int* c, int* h, int* s)
{
PedSector cyl_size;
PED_ASSERT (dev != NULL, return);
PED_ASSERT (c != NULL, return);
PED_ASSERT (h != NULL, return);
PED_ASSERT (s != NULL, return);
cyl_size = dev->hw_geom.heads * dev->hw_geom.sectors;
*c = sector / cyl_size;
*h = (sector) % cyl_size / dev->hw_geom.sectors;
*s = (sector) % cyl_size % dev->hw_geom.sectors;
}
static PedSector
legacy_start (const PedDisk* disk, const PC98RawPartition* raw_part)
{
PED_ASSERT (disk != NULL, return 0);
PED_ASSERT (raw_part != NULL, return 0);
return chs_to_sector (disk->dev, PED_LE16_TO_CPU(raw_part->cyl),
raw_part->head, raw_part->sector);
}
static PedSector
legacy_end (const PedDisk* disk, const PC98RawPartition* raw_part)
{
PED_ASSERT (disk != NULL, return 0);
PED_ASSERT (raw_part != NULL, return 0);
if (raw_part->end_head == 0 && raw_part->end_sector == 0) {
return chs_to_sector (disk->dev,
PED_LE16_TO_CPU(raw_part->end_cyl),
disk->dev->hw_geom.heads - 1,
disk->dev->hw_geom.sectors - 1);
} else {
return chs_to_sector (disk->dev,
PED_LE16_TO_CPU(raw_part->end_cyl),
raw_part->end_head,
raw_part->end_sector);
}
}
static int
is_unused_partition(const PC98RawPartition* raw_part)
{
if (raw_part->mid || raw_part->sid
|| raw_part->ipl_sect
|| raw_part->ipl_head
|| PED_LE16_TO_CPU(raw_part->ipl_cyl)
|| raw_part->sector
|| raw_part->head
|| PED_LE16_TO_CPU(raw_part->cyl)
|| raw_part->end_sector
|| raw_part->end_head
|| PED_LE16_TO_CPU(raw_part->end_cyl))
return 0;
return 1;
}
static int
read_table (PedDisk* disk)
{
int i;
PC98RawTable table;
PedConstraint* constraint_any;
PED_ASSERT (disk != NULL, return 0);
PED_ASSERT (disk->dev != NULL, return 0);
constraint_any = ped_constraint_any (disk->dev);
if (!ped_device_read (disk->dev, (void*) &table, 0, 2))
goto error;
if (!pc98_check_magic(&table)) {
if (ped_exception_throw (
PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL,
_("Invalid partition table on %s."),
disk->dev->path))
goto error;
}
for (i = 0; i < MAX_PART_COUNT; i++) {
PC98RawPartition* raw_part;
PedPartition* part;
PC98PartitionData* pc98_data;
PedSector part_start;
PedSector part_end;
raw_part = &table.partitions [i];
if (is_unused_partition(raw_part))
continue;
part_start = legacy_start (disk, raw_part);
part_end = legacy_end (disk, raw_part);
part = ped_partition_new (disk, 0, NULL, part_start, part_end);
if (!part)
goto error;
pc98_data = part->disk_specific;
PED_ASSERT (pc98_data != NULL, goto error);
pc98_data->system = (raw_part->mid << 8) | raw_part->sid;
pc98_data->boot = GET_BIT(raw_part->mid, 7);
pc98_data->hidden = !GET_BIT(raw_part->sid, 7);
ped_partition_set_name (part, raw_part->name);
pc98_data->ipl_sector = chs_to_sector (
disk->dev,
PED_LE16_TO_CPU(raw_part->ipl_cyl),
raw_part->ipl_head,
raw_part->ipl_sect);
/* hack */
if (pc98_data->ipl_sector == part->geom.start)
pc98_data->ipl_sector = 0;
part->num = i + 1;
if (!ped_disk_add_partition (disk, part, constraint_any))
goto error;
if (part->geom.start != part_start
|| part->geom.end != part_end) {
ped_exception_throw (
PED_EXCEPTION_NO_FEATURE,
PED_EXCEPTION_CANCEL,
_("Partition %d isn't aligned to cylinder "
"boundaries. This is still unsupported."),
part->num);
goto error;
}
part->fs_type = ped_file_system_probe (&part->geom);
}
ped_constraint_destroy (constraint_any);
return 1;
error:
ped_disk_delete_all (disk);
ped_constraint_destroy (constraint_any);
return 0;
}
static int
pc98_read (PedDisk* disk)
{
PED_ASSERT (disk != NULL, return 0);
PED_ASSERT (disk->dev != NULL, return 0);
ped_disk_delete_all (disk);
return read_table (disk);
}
#ifndef DISCOVER_ONLY
static int
fill_raw_part (PC98RawPartition* raw_part, const PedPartition* part)
{
PC98PartitionData* pc98_data;
int c, h, s;
const char* name;
PED_ASSERT (raw_part != NULL, return 0);
PED_ASSERT (part != NULL, return 0);
PED_ASSERT (part->disk_specific != NULL, return 0);
pc98_data = part->disk_specific;
raw_part->mid = (pc98_data->system >> 8) & 0xFF;
raw_part->sid = pc98_data->system & 0xFF;
SET_BIT(raw_part->mid, 7, pc98_data->boot);
SET_BIT(raw_part->sid, 7, !pc98_data->hidden);
memset (raw_part->name, ' ', sizeof(raw_part->name));
name = ped_partition_get_name (part);
PED_ASSERT (name != NULL, return 0);
PED_ASSERT (strlen (name) <= 16, return 0);
if (!strlen (name) && part->fs_type)
name = part->fs_type->name;
memcpy (raw_part->name, name, strlen (name));
sector_to_chs (part->disk->dev, part->geom.start, &c, &h, &s);
raw_part->cyl = PED_CPU_TO_LE16(c);
raw_part->head = h;
raw_part->sector = s;
if (pc98_data->ipl_sector) {
sector_to_chs (part->disk->dev, pc98_data->ipl_sector,
&c, &h, &s);
raw_part->ipl_cyl = PED_CPU_TO_LE16(c);
raw_part->ipl_head = h;
raw_part->ipl_sect = s;
} else {
raw_part->ipl_cyl = raw_part->cyl;
raw_part->ipl_head = raw_part->head;
raw_part->ipl_sect = raw_part->sector;
}
sector_to_chs (part->disk->dev, part->geom.end, &c, &h, &s);
if (h != part->disk->dev->hw_geom.heads - 1
|| s != part->disk->dev->hw_geom.sectors - 1) {
ped_exception_throw (
PED_EXCEPTION_NO_FEATURE,
PED_EXCEPTION_CANCEL,
_("Partition %d isn't aligned to cylinder "
"boundaries. This is still unsupported."),
part->num);
return 0;
}
raw_part->end_cyl = PED_CPU_TO_LE16(c);
#if 0
raw_part->end_head = h;
raw_part->end_sector = s;
#else
raw_part->end_head = 0;
raw_part->end_sector = 0;
#endif
return 1;
}
static int
pc98_write (const PedDisk* disk)
{
PC98RawTable table;
PedPartition* part;
int i;
PED_ASSERT (disk != NULL, return 0);
PED_ASSERT (disk->dev != NULL, return 0);
if (!ped_device_read (disk->dev, &table, 0, 2))
return 0;
if (!pc98_check_ipl_signature (&table)) {
memset (table.boot_code, 0, sizeof(table.boot_code));
memcpy (table.boot_code, MBR_BOOT_CODE, sizeof(MBR_BOOT_CODE));
}
memset (table.partitions, 0, sizeof (table.partitions));
table.magic = PED_CPU_TO_LE16(PC9800_EXTFMT_MAGIC);
for (i = 1; i <= MAX_PART_COUNT; i++) {
part = ped_disk_get_partition (disk, i);
if (!part)
continue;
if (!fill_raw_part (&table.partitions [i - 1], part))
return 0;
}
if (!ped_device_write (disk->dev, (void*) &table, 0, 2))
return 0;
return ped_device_sync (disk->dev);
}
#endif /* !DISCOVER_ONLY */
static PedPartition*
pc98_partition_new (
const PedDisk* disk, PedPartitionType part_type,
const PedFileSystemType* fs_type, PedSector start, PedSector end)
{
PedPartition* part;
PC98PartitionData* pc98_data;
part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
if (!part)
goto error;
if (ped_partition_is_active (part)) {
part->disk_specific
= pc98_data = ped_malloc (sizeof (PC98PartitionData));
if (!pc98_data)
goto error_free_part;
pc98_data->ipl_sector = 0;
pc98_data->hidden = 0;
pc98_data->boot = 0;
strcpy (pc98_data->name, "");
} else {
part->disk_specific = NULL;
}
return part;
ped_free (pc98_data);
error_free_part:
ped_free (part);
error:
return 0;
}
static PedPartition*
pc98_partition_duplicate (const PedPartition* part)
{
PedPartition* new_part;
PC98PartitionData* new_pc98_data;
PC98PartitionData* old_pc98_data;
new_part = ped_partition_new (part->disk, part->type,
part->fs_type, part->geom.start,
part->geom.end);
if (!new_part)
return NULL;
new_part->num = part->num;
old_pc98_data = (PC98PartitionData*) part->disk_specific;
new_pc98_data = (PC98PartitionData*) new_part->disk_specific;
/* ugly, but C is ugly :p */
memcpy (new_pc98_data, old_pc98_data, sizeof (PC98PartitionData));
return new_part;
}
static void
pc98_partition_destroy (PedPartition* part)
{
PED_ASSERT (part != NULL, return);
if (ped_partition_is_active (part))
ped_free (part->disk_specific);
ped_free (part);
}
static int
pc98_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
{
PC98PartitionData* pc98_data = part->disk_specific;
part->fs_type = fs_type;
pc98_data->system = 0x2062;
if (fs_type) {
if (!strcmp (fs_type->name, "fat16")) {
if (part->geom.length * 512 >= 32 * 1024 * 1024)
pc98_data->system = 0x2021;
else
pc98_data->system = 0x2011;
} else if (!strcmp (fs_type->name, "fat32")) {
pc98_data->system = 0x2061;
} else if (!strcmp (fs_type->name, "ntfs")) {
pc98_data->system = 0x2031;
} else if (!strncmp (fs_type->name, "ufs", 3)) {
pc98_data->system = 0x2044;
} else { /* ext2, reiser, xfs, etc. */
/* ext2 partitions must be marked boot */
pc98_data->boot = 1;
pc98_data->system = 0xa062;
}
}
if (pc98_data->boot)
pc98_data->system |= 0x8000;
if (!pc98_data->hidden)
pc98_data->system |= 0x0080;
return 1;
}
static int
pc98_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
{
PC98PartitionData* pc98_data;
PED_ASSERT (part != NULL, return 0);
PED_ASSERT (part->disk_specific != NULL, return 0);
pc98_data = part->disk_specific;
switch (flag) {
case PED_PARTITION_HIDDEN:
pc98_data->hidden = state;
return ped_partition_set_system (part, part->fs_type);
case PED_PARTITION_BOOT:
pc98_data->boot = state;
return ped_partition_set_system (part, part->fs_type);
default:
return 0;
}
}
static int
pc98_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
{
PC98PartitionData* pc98_data;
PED_ASSERT (part != NULL, return 0);
PED_ASSERT (part->disk_specific != NULL, return 0);
pc98_data = part->disk_specific;
switch (flag) {
case PED_PARTITION_HIDDEN:
return pc98_data->hidden;
case PED_PARTITION_BOOT:
return pc98_data->boot;
default:
return 0;
}
}
static int
pc98_partition_is_flag_available (
const PedPartition* part, PedPartitionFlag flag)
{
switch (flag) {
case PED_PARTITION_HIDDEN:
case PED_PARTITION_BOOT:
return 1;
default:
return 0;
}
}
static void
pc98_partition_set_name (PedPartition* part, const char* name)
{
PC98PartitionData* pc98_data;
int i;
PED_ASSERT (part != NULL, return);
PED_ASSERT (part->disk_specific != NULL, return);
pc98_data = part->disk_specific;
strncpy (pc98_data->name, name, 16);
pc98_data->name [16] = 0;
for (i = strlen (pc98_data->name) - 1; pc98_data->name[i] == ' '; i--)
pc98_data->name [i] = 0;
}
static const char*
pc98_partition_get_name (const PedPartition* part)
{
PC98PartitionData* pc98_data;
PED_ASSERT (part != NULL, return NULL);
PED_ASSERT (part->disk_specific != NULL, return NULL);
pc98_data = part->disk_specific;
return pc98_data->name;
}
static PedConstraint*
_primary_constraint (PedDisk* disk)
{
PedDevice* dev = disk->dev;
PedAlignment start_align;
PedAlignment end_align;
PedGeometry max_geom;
PedSector cylinder_size;
cylinder_size = dev->hw_geom.sectors * dev->hw_geom.heads;
if (!ped_alignment_init (&start_align, 0, cylinder_size))
return NULL;
if (!ped_alignment_init (&end_align, -1, cylinder_size))
return NULL;
if (!ped_geometry_init (&max_geom, dev, cylinder_size,
dev->length - cylinder_size))
return NULL;
return ped_constraint_new (&start_align, &end_align, &max_geom,
&max_geom, 1, dev->length);
}
static int
pc98_partition_align (PedPartition* part, const PedConstraint* constraint)
{
PED_ASSERT (part != NULL, return 0);
if (_ped_partition_attempt_align (part, constraint,
_primary_constraint (part->disk)))
return 1;
#ifndef DISCOVER_ONLY
ped_exception_throw (
PED_EXCEPTION_ERROR,
PED_EXCEPTION_CANCEL,
_("Unable to satisfy all constraints on the partition."));
#endif
return 0;
}
static int
next_primary (PedDisk* disk)
{
int i;
for (i=1; i<=MAX_PART_COUNT; i++) {
if (!ped_disk_get_partition (disk, i))
return i;
}
return 0;
}
static int
pc98_partition_enumerate (PedPartition* part)
{
PED_ASSERT (part != NULL, return 0);
PED_ASSERT (part->disk != NULL, return 0);
/* don't re-number a partition */
if (part->num != -1)
return 1;
PED_ASSERT (ped_partition_is_active (part), return 0);
part->num = next_primary (part->disk);
if (!part->num) {
ped_exception_throw (PED_EXCEPTION_ERROR,
PED_EXCEPTION_CANCEL,
_("Can't add another partition."));
return 0;
}
return 1;
}
static int
pc98_alloc_metadata (PedDisk* disk)
{
PedPartition* new_part;
PedConstraint* constraint_any = NULL;
PedSector cyl_size;
PED_ASSERT (disk != NULL, goto error);
PED_ASSERT (disk->dev != NULL, goto error);
constraint_any = ped_constraint_any (disk->dev);
cyl_size = disk->dev->hw_geom.sectors * disk->dev->hw_geom.heads;
new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL,
0, cyl_size - 1);
if (!new_part)
goto error;
if (!ped_disk_add_partition (disk, new_part, constraint_any)) {
ped_partition_destroy (new_part);
goto error;
}
ped_constraint_destroy (constraint_any);
return 1;
error:
ped_constraint_destroy (constraint_any);
return 0;
}
static int
pc98_get_max_primary_partition_count (const PedDisk* disk)
{
return MAX_PART_COUNT;
}
static PedDiskOps pc98_disk_ops = {
probe: pc98_probe,
#ifndef DISCOVER_ONLY
clobber: pc98_clobber,
#else
clobber: NULL,
#endif
alloc: pc98_alloc,
duplicate: pc98_duplicate,
free: pc98_free,
read: pc98_read,
#ifndef DISCOVER_ONLY
write: pc98_write,
#else
write: NULL,
#endif
partition_new: pc98_partition_new,
partition_duplicate: pc98_partition_duplicate,
partition_destroy: pc98_partition_destroy,
partition_set_system: pc98_partition_set_system,
partition_set_flag: pc98_partition_set_flag,
partition_get_flag: pc98_partition_get_flag,
partition_is_flag_available: pc98_partition_is_flag_available,
partition_set_name: pc98_partition_set_name,
partition_get_name: pc98_partition_get_name,
partition_align: pc98_partition_align,
partition_enumerate: pc98_partition_enumerate,
alloc_metadata: pc98_alloc_metadata,
get_max_primary_partition_count:
pc98_get_max_primary_partition_count
};
static PedDiskType pc98_disk_type = {
next: NULL,
name: "pc98",
ops: &pc98_disk_ops,
features: PED_DISK_TYPE_PARTITION_NAME
};
void
ped_disk_pc98_init ()
{
PED_ASSERT (sizeof (PC98RawTable) == 512 * 2, return);
ped_disk_type_register (&pc98_disk_type);
}
void
ped_disk_pc98_done ()
{
ped_disk_type_unregister (&pc98_disk_type);
}