summaryrefslogtreecommitdiffstats
path: root/libblkid
diff options
context:
space:
mode:
authorVaclav Dolezal2018-01-10 17:58:39 +0100
committerVaclav Dolezal2018-01-23 17:02:41 +0100
commit50c71f25ffe3b8e3ce07a1283b6345b5741ce7b7 (patch)
treed45961f8ef598a82ee227ab9a16ebc8a35316516 /libblkid
parenttests: use subtests for weeknum cal(1) tests (diff)
downloadkernel-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.am1
-rw-r--r--libblkid/src/partitions/atari.c259
-rw-r--r--libblkid/src/partitions/partitions.c3
-rw-r--r--libblkid/src/partitions/partitions.h1
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 */