xref: /netbsd-src/sys/dev/dkwedge/dkwedge_tos.c (revision 2ea37e1c0060c38e234124a7dd787d73af3b6b7b)
1 /* $NetBSD: dkwedge_tos.c,v 1.2 2024/04/06 09:51:34 hannken Exp $ */
2 
3 /*
4  * Copyright (c) 2024 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Charlotte Koch.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * dk(4) support for Atari "TOS" partition schemes.
34  *
35  * Technical details taken from:
36  *
37  * - "Atari Hard Disk File Systems Reference Guide" v1.2b by Jean
38  * Louis-Guerin (DrCoolZic) (September 2014)
39  *
40  * https://info-coach.fr/atari/documents/_mydoc/Atari_HD_File_Sytem_Reference_Guide.pdf
41  */
42 
43 #include <sys/buf.h>
44 #include <sys/disk.h>
45 #include <sys/endian.h>
46 #include <sys/vnode.h>
47 
48 #define TOS_PART_TYPE_LEN	3
49 #define TOS_GEM_PARTITION	"GEM"
50 #define TOS_BGM_PARTITION	"BGM"
51 #define TOS_XGM_PARTITION	"XGM"
52 
53 #define TOS_CXNMETHOD_SASI	0x00
54 #define TOS_CXNMETHOD_SCSI	0xFF
55 
56 #define TOS_MAX_PART_COUNT	4
57 #define TOS_SECTOR_SIZE		512
58 
59 struct tos_partition {
60 	uint8_t status;
61 	char type[TOS_PART_TYPE_LEN];
62 	uint32_t offset;
63 	uint32_t size;
64 } __packed;
65 __CTASSERT(sizeof(struct tos_partition) == 12);
66 
67 struct tos_root_sector {
68 	uint8_t unused1[441];
69 	uint8_t connection_method;
70 	uint8_t unused2[8];
71 	uint32_t size;
72 	struct tos_partition parts[TOS_MAX_PART_COUNT];
73 	uint8_t unused3[10];
74 } __packed;
75 __CTASSERT(sizeof(struct tos_root_sector) == TOS_SECTOR_SIZE);
76 
77 static int dkwedge_discover_tos(struct disk *pdk, struct vnode *vp);
78 
79 static int
dkwedge_discover_tos(struct disk * pdk,struct vnode * vp)80 dkwedge_discover_tos(struct disk *pdk, struct vnode *vp)
81 {
82 	struct dkwedge_info dkw;
83 	int error = 0;
84 	size_t i;
85 	char safe_type[4];
86 
87 	/* Get ourselves a fistful of memory. */
88 	buf_t *bp = geteblk(TOS_SECTOR_SIZE);
89 
90 	error = dkwedge_read(pdk, vp, 0L, bp->b_data, TOS_SECTOR_SIZE);
91 	if (error) {
92 		aprint_error("unable to read TOS Root Sector: error = %d",
93 		    error);
94 		goto out;
95 	}
96 
97 	struct tos_root_sector *trs = bp->b_data;
98 
99 	/*
100 	 * If the "connection method" isn't recognized, then this is
101 	 * probably NOT an Atari-style partition, so get outta here. Note
102 	 * that there really isn't a magic number we can rely on; this check
103 	 * is somewhat made up. But at least it's better than nothing.
104 	 */
105 	switch (trs->connection_method) {
106 	case TOS_CXNMETHOD_SASI: /* FALLTHROUGH */
107 	case TOS_CXNMETHOD_SCSI:
108 		; /* OK */
109 		break;
110 	default:
111 		error = ESRCH;
112 		goto out;
113 	}
114 
115 	/*
116 	 * Make a wedge for each partition that exists (i.e., has the "exist"
117 	 * bit set).
118 	 */
119 	for (i = 0; i < TOS_MAX_PART_COUNT; i++) {
120 		struct tos_partition part = trs->parts[i];
121 
122 		if (!(part.status & 0x01))
123 			continue;
124 
125 		/* Ignore if we see it's an extended "XGM" partition. */
126 		if (!strncmp(part.type, TOS_XGM_PARTITION, TOS_PART_TYPE_LEN)) {
127 			aprint_normal(
128 			    "WARNING: XGM partitions are not yet supported\n");
129 			continue;
130 		}
131 
132 		/*
133 		 * Otherwise, get outta here if it's not the partition-types
134 		 * we *do* support.
135 		 */
136 		if (strncmp(part.type, TOS_GEM_PARTITION, TOS_PART_TYPE_LEN) &&
137 		    strncmp(part.type, TOS_BGM_PARTITION, TOS_PART_TYPE_LEN)) {
138 			error = ESRCH;
139 			goto out;
140 		}
141 
142 		memset(&dkw, 0, sizeof(dkw));
143 		memset(safe_type, 0, sizeof(safe_type));
144 
145 		/*
146 		 * The partition type string is NOT NUL-terminated, so let's
147 		 * play it safe.
148 		 */
149 		memcpy(safe_type, part.type, TOS_PART_TYPE_LEN);
150 		safe_type[TOS_PART_TYPE_LEN] = '\0';
151 
152 		/* Finally, make the wedge. */
153 		snprintf(dkw.dkw_wname, sizeof(dkw.dkw_wname), "ATARI_%s_%02zu",
154 		    safe_type, i);
155 		dkw.dkw_offset = be32toh(trs->parts[i].offset);
156 		dkw.dkw_size = be32toh(trs->parts[i].size);
157 		strlcpy(dkw.dkw_ptype, DKW_PTYPE_FAT, sizeof(dkw.dkw_ptype));
158 		strlcpy(dkw.dkw_parent, pdk->dk_name, sizeof(dkw.dkw_parent));
159 		error = dkwedge_add(&dkw);
160 
161 		if (error == EEXIST) {
162 			aprint_error("partition named \"%s\" already exists",
163 			    dkw.dkw_wname);
164 			goto out;
165 		}
166 	}
167 
168 	error = 0;
169 
170 out:
171 	brelse(bp, 0);
172 	return error;
173 }
174 
175 DKWEDGE_DISCOVERY_METHOD_DECL(TOS, 10, dkwedge_discover_tos);
176