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