diff options
author | Vaclav Dolezal | 2018-01-10 17:58:39 +0100 |
---|---|---|
committer | Vaclav Dolezal | 2018-01-23 17:02:41 +0100 |
commit | 50c71f25ffe3b8e3ce07a1283b6345b5741ce7b7 (patch) | |
tree | d45961f8ef598a82ee227ab9a16ebc8a35316516 /libblkid | |
parent | tests: use subtests for weeknum cal(1) tests (diff) | |
download | kernel-qcow2-util-linux-50c71f25ffe3b8e3ce07a1283b6345b5741ce7b7.tar.gz kernel-qcow2-util-linux-50c71f25ffe3b8e3ce07a1283b6345b5741ce7b7.tar.xz kernel-qcow2-util-linux-50c71f25ffe3b8e3ce07a1283b6345b5741ce7b7.zip |
libblkid: Support for Atari partitioning scheme
Addresses: https://github.com/karelzak/util-linux/issues/517
Signed-off-by: Vaclav Dolezal <vdolezal@redhat.com>
Diffstat (limited to 'libblkid')
-rw-r--r-- | libblkid/src/Makemodule.am | 1 | ||||
-rw-r--r-- | libblkid/src/partitions/atari.c | 259 | ||||
-rw-r--r-- | libblkid/src/partitions/partitions.c | 3 | ||||
-rw-r--r-- | libblkid/src/partitions/partitions.h | 1 |
4 files changed, 263 insertions, 1 deletions
diff --git a/libblkid/src/Makemodule.am b/libblkid/src/Makemodule.am index 1046be100..0e1c765fb 100644 --- a/libblkid/src/Makemodule.am +++ b/libblkid/src/Makemodule.am @@ -29,6 +29,7 @@ libblkid_la_SOURCES = \ \ libblkid/src/partitions/aix.c \ libblkid/src/partitions/aix.h \ + libblkid/src/partitions/atari.c \ libblkid/src/partitions/bsd.c \ libblkid/src/partitions/dos.c \ libblkid/src/partitions/gpt.c \ diff --git a/libblkid/src/partitions/atari.c b/libblkid/src/partitions/atari.c new file mode 100644 index 000000000..eb3604088 --- /dev/null +++ b/libblkid/src/partitions/atari.c @@ -0,0 +1,259 @@ +/* + * atari partitions parsing code + * + * Copyright (C) 2018 Vaclav Dolezal <vdolezal@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * + * Based on Linux kernel implementation and atari-fdisk + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <stdint.h> + +#include "partitions.h" + +struct atari_part_def { + /* + * flags: + * 0 (LSB): active + * 1-6: (reserved) + * 7 (MSB): bootable + */ + unsigned char flags; + char id[3]; + uint32_t start; + uint32_t size; +} __attribute__((packed)); + +struct atari_rootsector { + char unused0[0x156]; /* boot code */ + struct atari_part_def icd_part[8]; /* ICD partition entries */ + char unused1[0xc]; + uint32_t hd_size; + struct atari_part_def part[4]; /* primary partition entries */ + uint32_t bsl_start; /* bad sector list start */ + uint32_t bsl_len; /* bad sector list length */ + uint16_t checksum; +} __attribute__((packed)); + + +/* + * Generated using linux kernel ctype.{c,h} + * + * Since kernel uses isalnum() to detect whether it is Atari PT, we need same + * definition of alnum character to be consistent with kernel. + */ +static const unsigned char _linux_isalnum[] = { +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, +0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, +0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1 +}; + +static int linux_isalnum(unsigned char c) { + return _linux_isalnum[c]; +} + +#define isalnum linux_isalnum + +#define IS_ACTIVE(partdef) ((partdef).flags & 1) + +#define IS_PARTDEF_VALID(partdef) \ + ( \ + (partdef).flags & 1 && \ + isalnum((partdef).id[0]) && \ + isalnum((partdef).id[1]) && \ + isalnum((partdef).id[2]) \ + ) + +static int is_id_common(char *id) +{ + const char *ids[] = {"GEM", "BGM", "LNX", "SWP", "RAW", }; + unsigned i; + + for (i = 0; i < ARRAY_SIZE(ids); i++) { + if (!memcmp(ids[i], id, 3)) + return 1; + } + return 0; +} + +static int parse_partition(blkid_partlist ls, blkid_parttable tab, + struct atari_part_def *part, uint32_t offset) +{ + blkid_partition par; + uint32_t start; + uint32_t size; + + start = be32_to_cpu(part->start) + offset; + size = be32_to_cpu(part->size); + + par = blkid_partlist_add_partition(ls, tab, start, size); + if (!par) + return -ENOMEM; + + blkid_partition_set_type_string(par, (unsigned char *) part->id, + sizeof(part->id)); + return 1; +} + +/* + * \return 1: OK, 0: bad format or -errno + */ +static int parse_extended(blkid_probe pr, blkid_partlist ls, + blkid_parttable tab, struct atari_part_def *part) +{ + uint32_t x0start, xstart; + unsigned i = 0; + int rc; + + x0start = xstart = be32_to_cpu(part->start); + while (1) { + struct atari_rootsector *xrs; + xrs = (struct atari_rootsector *) blkid_probe_get_sector(pr, xstart); + if (!rs) { + if (errno) + return -errno; + return 0; + } + + /* + * There must be data partition followed by reference to next + * XGM or inactive entry. + */ + for (i=0; ; i++) { + if (i >= ARRAY_SIZE(xrs->part) - 1) + return 0; + if (IS_ACTIVE(xrs->part[i])) + break; + } + + if (!memcmp(xrs->part[i].id, "XGM", 3)) + return 0; + + rc = parse_partition(ls, tab, &xrs->part[i], xstart); + if (rc < 0) + return rc; + + if (!IS_ACTIVE(xrs->part[i+1])) + break; + + if (memcmp(xrs->part[i+1].id, "XGM", 3)) + return 0; + + xstart = x0start + be32_to_cpu(xrs->part[i+1].start); + } + + return 1; +} + +static int probe_atari_pt(blkid_probe pr, + const struct blkid_idmag *mag __attribute__((__unused__))) +{ + struct atari_rootsector *rs; + + blkid_parttable tab = NULL; + blkid_partlist ls; + + unsigned i; + int has_xgm = 0; + int rc = 0; + + rs = (struct atari_rootsector *) blkid_probe_get_sector(pr, 0); + if (!rs) { + if (errno) + return -errno; + goto nothing; + } + + /* Look for validly looking primary partition */ + for (i = 0; ; i++) { + if (i >= ARRAY_SIZE(rs->part)) + goto nothing; + + if (IS_PARTDEF_VALID(rs->part[i])) { + blkid_probe_set_magic(pr, + offsetof(struct atari_rootsector, part[i]), + sizeof(rs->part[i].flags) + sizeof(rs->part[i].id), + (unsigned char *) &rs->part[i]); + break; + } + } + + if (blkid_partitions_need_typeonly(pr)) + /* caller does not ask for details about partitions */ + return BLKID_PROBE_OK; + + ls = blkid_probe_get_partlist(pr); + if (!ls) + goto nothing; + + tab = blkid_partlist_new_parttable(ls, "atari", 0); + if (!tab) + goto err; + + for (i = 0; i < ARRAY_SIZE(rs->part); i++) { + struct atari_part_def *p = &rs->part[i]; + + if (!IS_ACTIVE(*p)) { + blkid_partlist_increment_partno(ls); + continue; + } + + if (!memcmp(p->id, "XGM", 3)) { + has_xgm = 1; + rc = parse_extended(pr, ls, tab, p); + } else { + rc = parse_partition(ls, tab, p, 0); + } + if (rc < 0) + return rc; + } + + /* if there are no XGM partitions, we can try ICD format */ + /* if first ICD partition ID is not valid, assume no ICD format */ + if (!has_xgm && is_id_common(rs->icd_part[0].id)) { + for (i = 0; i < ARRAY_SIZE(rs->icd_part); i++) { + struct atari_part_def *p = &rs->icd_part[i]; + + if (!IS_ACTIVE(*p) || !is_id_common(p->id)) { + blkid_partlist_increment_partno(ls); + continue; + } + + rc = parse_partition(ls, tab, p, 0); + if (rc < 0) + return rc; + } + } + + return BLKID_PROBE_OK; + +nothing: + return BLKID_PROBE_NONE; +err: + return -ENOMEM; +} + +const struct blkid_idinfo atari_pt_idinfo = +{ + .name = "atari", + .probefunc = probe_atari_pt, + .magics = BLKID_NONE_MAGIC +}; diff --git a/libblkid/src/partitions/partitions.c b/libblkid/src/partitions/partitions.c index d8fc8e3c8..1f1fc4515 100644 --- a/libblkid/src/partitions/partitions.c +++ b/libblkid/src/partitions/partitions.c @@ -133,7 +133,8 @@ static const struct blkid_idinfo *idinfos[] = &bsd_pt_idinfo, &unixware_pt_idinfo, &solaris_x86_pt_idinfo, - &minix_pt_idinfo + &minix_pt_idinfo, + &atari_pt_idinfo }; /* diff --git a/libblkid/src/partitions/partitions.h b/libblkid/src/partitions/partitions.h index 1d99fb6a3..4a718f4ea 100644 --- a/libblkid/src/partitions/partitions.h +++ b/libblkid/src/partitions/partitions.h @@ -69,5 +69,6 @@ extern const struct blkid_idinfo minix_pt_idinfo; extern const struct blkid_idinfo gpt_pt_idinfo; extern const struct blkid_idinfo pmbr_pt_idinfo; extern const struct blkid_idinfo ultrix_pt_idinfo; +extern const struct blkid_idinfo atari_pt_idinfo; #endif /* BLKID_PARTITIONS_H */ |