FreeBSD/Linux Kernel Cross Reference
sys/dev/cgd.c
1 /* $NetBSD: cgd.c,v 1.146 2022/04/02 09:53:20 riastradh Exp $ */
2
3 /*-
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Roland C. Dowdeswell.
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 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.146 2022/04/02 09:53:20 riastradh Exp $");
34
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/buf.h>
38 #include <sys/bufq.h>
39 #include <sys/conf.h>
40 #include <sys/cpu.h>
41 #include <sys/device.h>
42 #include <sys/disk.h>
43 #include <sys/disklabel.h>
44 #include <sys/errno.h>
45 #include <sys/fcntl.h>
46 #include <sys/ioctl.h>
47 #include <sys/kmem.h>
48 #include <sys/module.h>
49 #include <sys/namei.h> /* for pathbuf */
50 #include <sys/pool.h>
51 #include <sys/proc.h>
52 #include <sys/syslog.h>
53 #include <sys/systm.h>
54 #include <sys/vnode.h>
55 #include <sys/workqueue.h>
56
57 #include <dev/cgd_crypto.h>
58 #include <dev/cgdvar.h>
59 #include <dev/dkvar.h>
60
61 #include <miscfs/specfs/specdev.h> /* for v_rdev */
62
63 #include "ioconf.h"
64
65 struct selftest_params {
66 const char *alg;
67 int encblkno8;
68 int blocksize; /* number of bytes */
69 int secsize;
70 daddr_t blkno;
71 int keylen; /* number of bits */
72 int txtlen; /* number of bytes */
73 const uint8_t *key;
74 const uint8_t *ptxt;
75 const uint8_t *ctxt;
76 };
77
78 /* Entry Point Functions */
79
80 static dev_type_open(cgdopen);
81 static dev_type_close(cgdclose);
82 static dev_type_read(cgdread);
83 static dev_type_write(cgdwrite);
84 static dev_type_ioctl(cgdioctl);
85 static dev_type_strategy(cgdstrategy);
86 static dev_type_dump(cgddump);
87 static dev_type_size(cgdsize);
88
89 const struct bdevsw cgd_bdevsw = {
90 .d_open = cgdopen,
91 .d_close = cgdclose,
92 .d_strategy = cgdstrategy,
93 .d_ioctl = cgdioctl,
94 .d_dump = cgddump,
95 .d_psize = cgdsize,
96 .d_discard = nodiscard,
97 .d_flag = D_DISK | D_MPSAFE
98 };
99
100 const struct cdevsw cgd_cdevsw = {
101 .d_open = cgdopen,
102 .d_close = cgdclose,
103 .d_read = cgdread,
104 .d_write = cgdwrite,
105 .d_ioctl = cgdioctl,
106 .d_stop = nostop,
107 .d_tty = notty,
108 .d_poll = nopoll,
109 .d_mmap = nommap,
110 .d_kqfilter = nokqfilter,
111 .d_discard = nodiscard,
112 .d_flag = D_DISK | D_MPSAFE
113 };
114
115 /*
116 * Vector 5 from IEEE 1619/D16 truncated to 64 bytes, blkno 1.
117 */
118 static const uint8_t selftest_aes_xts_256_ptxt[64] = {
119 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
120 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
121 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
122 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
123 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
124 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
125 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
126 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
127 };
128
129 static const uint8_t selftest_aes_xts_256_ctxt[512] = {
130 0x26, 0x4d, 0x3c, 0xa8, 0x51, 0x21, 0x94, 0xfe,
131 0xc3, 0x12, 0xc8, 0xc9, 0x89, 0x1f, 0x27, 0x9f,
132 0xef, 0xdd, 0x60, 0x8d, 0x0c, 0x02, 0x7b, 0x60,
133 0x48, 0x3a, 0x3f, 0xa8, 0x11, 0xd6, 0x5e, 0xe5,
134 0x9d, 0x52, 0xd9, 0xe4, 0x0e, 0xc5, 0x67, 0x2d,
135 0x81, 0x53, 0x2b, 0x38, 0xb6, 0xb0, 0x89, 0xce,
136 0x95, 0x1f, 0x0f, 0x9c, 0x35, 0x59, 0x0b, 0x8b,
137 0x97, 0x8d, 0x17, 0x52, 0x13, 0xf3, 0x29, 0xbb,
138 };
139
140 static const uint8_t selftest_aes_xts_256_key[33] = {
141 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
142 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
143 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
144 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95,
145 0
146 };
147
148 /*
149 * Vector 11 from IEEE 1619/D16 truncated to 64 bytes, blkno 0xffff.
150 */
151 static const uint8_t selftest_aes_xts_512_ptxt[64] = {
152 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
153 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
154 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
155 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
156 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
157 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
158 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
159 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
160 };
161
162 static const uint8_t selftest_aes_xts_512_ctxt[64] = {
163 0x77, 0xa3, 0x12, 0x51, 0x61, 0x8a, 0x15, 0xe6,
164 0xb9, 0x2d, 0x1d, 0x66, 0xdf, 0xfe, 0x7b, 0x50,
165 0xb5, 0x0b, 0xad, 0x55, 0x23, 0x05, 0xba, 0x02,
166 0x17, 0xa6, 0x10, 0x68, 0x8e, 0xff, 0x7e, 0x11,
167 0xe1, 0xd0, 0x22, 0x54, 0x38, 0xe0, 0x93, 0x24,
168 0x2d, 0x6d, 0xb2, 0x74, 0xfd, 0xe8, 0x01, 0xd4,
169 0xca, 0xe0, 0x6f, 0x20, 0x92, 0xc7, 0x28, 0xb2,
170 0x47, 0x85, 0x59, 0xdf, 0x58, 0xe8, 0x37, 0xc2,
171 };
172
173 static const uint8_t selftest_aes_xts_512_key[65] = {
174 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
175 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
176 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69,
177 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27,
178 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
179 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95,
180 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37,
181 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92,
182 0
183 };
184
185 static const uint8_t selftest_aes_cbc_key[32] = {
186 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
187 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
188 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69,
189 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27,
190 };
191
192 static const uint8_t selftest_aes_cbc_128_ptxt[64] = {
193 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
194 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
195 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
196 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
197 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
198 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
199 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
200 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
201 };
202
203 static const uint8_t selftest_aes_cbc_128_ctxt[64] = { /* blkno=1 */
204 0x93, 0x94, 0x56, 0x36, 0x83, 0xbc, 0xff, 0xa4,
205 0xe0, 0x24, 0x34, 0x12, 0xbe, 0xfa, 0xb0, 0x7d,
206 0x88, 0x1e, 0xc5, 0x57, 0x55, 0x23, 0x05, 0x0c,
207 0x69, 0xa5, 0xc1, 0xda, 0x64, 0xee, 0x74, 0x10,
208 0xc2, 0xc5, 0xe6, 0x66, 0xd6, 0xa7, 0x49, 0x1c,
209 0x9d, 0x40, 0xb5, 0x0c, 0x9b, 0x6e, 0x1c, 0xe6,
210 0xb1, 0x7a, 0x1c, 0xe7, 0x5a, 0xfe, 0xf9, 0x2a,
211 0x78, 0xfa, 0xb7, 0x7b, 0x08, 0xdf, 0x8e, 0x51,
212 };
213
214 static const uint8_t selftest_aes_cbc_256_ptxt[64] = {
215 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
216 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
217 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
218 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
219 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
220 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
221 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
222 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
223 };
224
225 static const uint8_t selftest_aes_cbc_256_ctxt[64] = { /* blkno=0xffff */
226 0x6c, 0xa3, 0x15, 0x17, 0x51, 0x90, 0xe9, 0x69,
227 0x08, 0x36, 0x7b, 0xa6, 0xbb, 0xd1, 0x0b, 0x9e,
228 0xcd, 0x6b, 0x1e, 0xaf, 0xb6, 0x2e, 0x62, 0x7d,
229 0x8e, 0xde, 0xf0, 0xed, 0x0d, 0x44, 0xe7, 0x31,
230 0x26, 0xcf, 0xd5, 0x0b, 0x3e, 0x95, 0x59, 0x89,
231 0xdf, 0x5d, 0xd6, 0x9a, 0x00, 0x66, 0xcc, 0x7f,
232 0x45, 0xd3, 0x06, 0x58, 0xed, 0xef, 0x49, 0x47,
233 0x87, 0x89, 0x17, 0x7d, 0x08, 0x56, 0x50, 0xe1,
234 };
235
236 static const uint8_t selftest_3des_cbc_key[24] = {
237 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
238 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
239 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
240 };
241
242 static const uint8_t selftest_3des_cbc_ptxt[64] = {
243 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
244 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
245 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
246 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
247 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
248 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
249 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
250 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
251 };
252
253 static const uint8_t selftest_3des_cbc_ctxt[64] = {
254 0xa2, 0xfe, 0x81, 0xaa, 0x10, 0x6c, 0xea, 0xb9,
255 0x11, 0x58, 0x1f, 0x29, 0xb5, 0x86, 0x71, 0x56,
256 0xe9, 0x25, 0x1d, 0x07, 0xb1, 0x69, 0x59, 0x6c,
257 0x96, 0x80, 0xf7, 0x54, 0x38, 0xaa, 0xa7, 0xe4,
258 0xe8, 0x81, 0xf5, 0x00, 0xbb, 0x1c, 0x00, 0x3c,
259 0xba, 0x38, 0x45, 0x97, 0x4c, 0xcf, 0x84, 0x14,
260 0x46, 0x86, 0xd9, 0xf4, 0xc5, 0xe2, 0xf0, 0x54,
261 0xde, 0x41, 0xf6, 0xa1, 0xef, 0x1b, 0x0a, 0xea,
262 };
263
264 static const uint8_t selftest_bf_cbc_key[56] = {
265 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
266 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
267 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
268 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
269 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
270 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
271 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
272 };
273
274 static const uint8_t selftest_bf_cbc_ptxt[64] = {
275 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
276 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
277 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
278 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
279 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
280 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
281 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
282 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
283 };
284
285 static const uint8_t selftest_bf_cbc_ctxt[64] = {
286 0xec, 0xa2, 0xc0, 0x0e, 0xa9, 0x7f, 0x04, 0x1e,
287 0x2e, 0x4f, 0x64, 0x07, 0x67, 0x3e, 0xf4, 0x58,
288 0x61, 0x5f, 0xd3, 0x50, 0x5e, 0xd3, 0x4d, 0x34,
289 0xa0, 0x53, 0xbe, 0x47, 0x75, 0x69, 0x3b, 0x1f,
290 0x86, 0xf2, 0xae, 0x8b, 0xb7, 0x91, 0xda, 0xd4,
291 0x2b, 0xa5, 0x47, 0x9b, 0x7d, 0x13, 0x30, 0xdd,
292 0x7b, 0xad, 0x86, 0x57, 0x51, 0x11, 0x74, 0x42,
293 0xb8, 0xbf, 0x69, 0x17, 0x20, 0x0a, 0xf7, 0xda,
294 };
295
296 static const uint8_t selftest_aes_cbc_encblkno8_zero64[64];
297 static const uint8_t selftest_aes_cbc_encblkno8_ctxt[64] = {
298 0xa2, 0x06, 0x26, 0x26, 0xac, 0xdc, 0xe7, 0xcf,
299 0x47, 0x68, 0x24, 0x0e, 0xfa, 0x40, 0x44, 0x83,
300 0x07, 0xe1, 0xf4, 0x5d, 0x53, 0x47, 0xa0, 0xfe,
301 0xc0, 0x6e, 0x4e, 0xf8, 0x9d, 0x98, 0x63, 0xb8,
302 0x2c, 0x27, 0xfa, 0x3a, 0xd5, 0x40, 0xda, 0xdb,
303 0xe6, 0xc3, 0xe4, 0xfb, 0x85, 0x53, 0xfb, 0x78,
304 0x5d, 0xbd, 0x8f, 0x4c, 0x1a, 0x04, 0x9c, 0x88,
305 0x85, 0xec, 0x3c, 0x56, 0x46, 0x1a, 0x6e, 0xf5,
306 };
307
308 const struct selftest_params selftests[] = {
309 {
310 .alg = "aes-xts",
311 .blocksize = 16,
312 .secsize = 512,
313 .blkno = 1,
314 .keylen = 256,
315 .txtlen = sizeof(selftest_aes_xts_256_ptxt),
316 .key = selftest_aes_xts_256_key,
317 .ptxt = selftest_aes_xts_256_ptxt,
318 .ctxt = selftest_aes_xts_256_ctxt
319 },
320 {
321 .alg = "aes-xts",
322 .blocksize = 16,
323 .secsize = 512,
324 .blkno = 0xffff,
325 .keylen = 512,
326 .txtlen = sizeof(selftest_aes_xts_512_ptxt),
327 .key = selftest_aes_xts_512_key,
328 .ptxt = selftest_aes_xts_512_ptxt,
329 .ctxt = selftest_aes_xts_512_ctxt
330 },
331 {
332 .alg = "aes-cbc",
333 .blocksize = 16,
334 .secsize = 512,
335 .blkno = 1,
336 .keylen = 128,
337 .txtlen = sizeof(selftest_aes_cbc_128_ptxt),
338 .key = selftest_aes_cbc_key,
339 .ptxt = selftest_aes_cbc_128_ptxt,
340 .ctxt = selftest_aes_cbc_128_ctxt,
341 },
342 {
343 .alg = "aes-cbc",
344 .blocksize = 16,
345 .secsize = 512,
346 .blkno = 0xffff,
347 .keylen = 256,
348 .txtlen = sizeof(selftest_aes_cbc_256_ptxt),
349 .key = selftest_aes_cbc_key,
350 .ptxt = selftest_aes_cbc_256_ptxt,
351 .ctxt = selftest_aes_cbc_256_ctxt,
352 },
353 {
354 .alg = "3des-cbc",
355 .blocksize = 8,
356 .secsize = 512,
357 .blkno = 1,
358 .keylen = 192, /* 168 + 3*8 parity bits */
359 .txtlen = sizeof(selftest_3des_cbc_ptxt),
360 .key = selftest_3des_cbc_key,
361 .ptxt = selftest_3des_cbc_ptxt,
362 .ctxt = selftest_3des_cbc_ctxt,
363 },
364 {
365 .alg = "blowfish-cbc",
366 .blocksize = 8,
367 .secsize = 512,
368 .blkno = 1,
369 .keylen = 448,
370 .txtlen = sizeof(selftest_bf_cbc_ptxt),
371 .key = selftest_bf_cbc_key,
372 .ptxt = selftest_bf_cbc_ptxt,
373 .ctxt = selftest_bf_cbc_ctxt,
374 },
375 {
376 .alg = "aes-cbc",
377 .encblkno8 = 1,
378 .blocksize = 16,
379 .secsize = 512,
380 .blkno = 0,
381 .keylen = 128,
382 .txtlen = sizeof(selftest_aes_cbc_encblkno8_zero64),
383 .key = selftest_aes_cbc_encblkno8_zero64,
384 .ptxt = selftest_aes_cbc_encblkno8_zero64,
385 .ctxt = selftest_aes_cbc_encblkno8_ctxt,
386 },
387 };
388
389 static int cgd_match(device_t, cfdata_t, void *);
390 static void cgd_attach(device_t, device_t, void *);
391 static int cgd_detach(device_t, int);
392 static struct cgd_softc *cgd_spawn(int);
393 static struct cgd_worker *cgd_create_one_worker(void);
394 static void cgd_destroy_one_worker(struct cgd_worker *);
395 static struct cgd_worker *cgd_create_worker(void);
396 static void cgd_destroy_worker(struct cgd_worker *);
397 static int cgd_destroy(device_t);
398
399 /* Internal Functions */
400
401 static int cgd_diskstart(device_t, struct buf *);
402 static void cgd_diskstart2(struct cgd_softc *, struct cgd_xfer *);
403 static void cgdiodone(struct buf *);
404 static void cgd_iodone2(struct cgd_softc *, struct cgd_xfer *);
405 static void cgd_enqueue(struct cgd_softc *, struct cgd_xfer *);
406 static void cgd_process(struct work *, void *);
407 static int cgd_dumpblocks(device_t, void *, daddr_t, int);
408
409 static int cgd_ioctl_set(struct cgd_softc *, void *, struct lwp *);
410 static int cgd_ioctl_clr(struct cgd_softc *, struct lwp *);
411 static int cgd_ioctl_get(dev_t, void *, struct lwp *);
412 static int cgdinit(struct cgd_softc *, const char *, struct vnode *,
413 struct lwp *);
414 static void cgd_cipher(struct cgd_softc *, void *, const void *,
415 size_t, daddr_t, size_t, int);
416
417 static void cgd_selftest(void);
418
419 static const struct dkdriver cgddkdriver = {
420 .d_minphys = minphys,
421 .d_open = cgdopen,
422 .d_close = cgdclose,
423 .d_strategy = cgdstrategy,
424 .d_iosize = NULL,
425 .d_diskstart = cgd_diskstart,
426 .d_dumpblocks = cgd_dumpblocks,
427 .d_lastclose = NULL
428 };
429
430 CFATTACH_DECL3_NEW(cgd, sizeof(struct cgd_softc),
431 cgd_match, cgd_attach, cgd_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
432
433 /* DIAGNOSTIC and DEBUG definitions */
434
435 #if defined(CGDDEBUG) && !defined(DEBUG)
436 #define DEBUG
437 #endif
438
439 #ifdef DEBUG
440 int cgddebug = 0;
441
442 #define CGDB_FOLLOW 0x1
443 #define CGDB_IO 0x2
444 #define CGDB_CRYPTO 0x4
445
446 #define IFDEBUG(x,y) if (cgddebug & (x)) y
447 #define DPRINTF(x,y) IFDEBUG(x, printf y)
448 #define DPRINTF_FOLLOW(y) DPRINTF(CGDB_FOLLOW, y)
449
450 static void hexprint(const char *, void *, int);
451
452 #else
453 #define IFDEBUG(x,y)
454 #define DPRINTF(x,y)
455 #define DPRINTF_FOLLOW(y)
456 #endif
457
458 /* Global variables */
459
460 static kmutex_t cgd_spawning_mtx;
461 static kcondvar_t cgd_spawning_cv;
462 static bool cgd_spawning;
463 static struct cgd_worker *cgd_worker;
464 static u_int cgd_refcnt; /* number of users of cgd_worker */
465
466 /* Utility Functions */
467
468 #define CGDUNIT(x) DISKUNIT(x)
469
470 /* The code */
471
472 static int
473 cgd_lock(bool intr)
474 {
475 int error = 0;
476
477 mutex_enter(&cgd_spawning_mtx);
478 while (cgd_spawning) {
479 if (intr)
480 error = cv_wait_sig(&cgd_spawning_cv, &cgd_spawning_mtx);
481 else
482 cv_wait(&cgd_spawning_cv, &cgd_spawning_mtx);
483 }
484 if (error == 0)
485 cgd_spawning = true;
486 mutex_exit(&cgd_spawning_mtx);
487 return error;
488 }
489
490 static void
491 cgd_unlock(void)
492 {
493 mutex_enter(&cgd_spawning_mtx);
494 cgd_spawning = false;
495 cv_broadcast(&cgd_spawning_cv);
496 mutex_exit(&cgd_spawning_mtx);
497 }
498
499 static struct cgd_softc *
500 getcgd_softc(dev_t dev)
501 {
502 return device_lookup_private(&cgd_cd, CGDUNIT(dev));
503 }
504
505 static int
506 cgd_match(device_t self, cfdata_t cfdata, void *aux)
507 {
508
509 return 1;
510 }
511
512 static void
513 cgd_attach(device_t parent, device_t self, void *aux)
514 {
515 struct cgd_softc *sc = device_private(self);
516
517 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_BIO);
518 cv_init(&sc->sc_cv, "cgdcv");
519 dk_init(&sc->sc_dksc, self, DKTYPE_CGD);
520 disk_init(&sc->sc_dksc.sc_dkdev, sc->sc_dksc.sc_xname, &cgddkdriver);
521
522 if (!pmf_device_register(self, NULL, NULL))
523 aprint_error_dev(self,
524 "unable to register power management hooks\n");
525 }
526
527
528 static int
529 cgd_detach(device_t self, int flags)
530 {
531 int ret;
532 struct cgd_softc *sc = device_private(self);
533 struct dk_softc *dksc = &sc->sc_dksc;
534
535 if (DK_BUSY(dksc, 0))
536 return EBUSY;
537
538 if (DK_ATTACHED(dksc) &&
539 (ret = cgd_ioctl_clr(sc, curlwp)) != 0)
540 return ret;
541
542 disk_destroy(&dksc->sc_dkdev);
543 cv_destroy(&sc->sc_cv);
544 mutex_destroy(&sc->sc_lock);
545
546 return 0;
547 }
548
549 void
550 cgdattach(int num)
551 {
552 #ifndef _MODULE
553 int error;
554
555 mutex_init(&cgd_spawning_mtx, MUTEX_DEFAULT, IPL_NONE);
556 cv_init(&cgd_spawning_cv, "cgspwn");
557
558 error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
559 if (error != 0)
560 aprint_error("%s: unable to register cfattach\n",
561 cgd_cd.cd_name);
562 #endif
563
564 cgd_selftest();
565 }
566
567 static struct cgd_softc *
568 cgd_spawn(int unit)
569 {
570 cfdata_t cf;
571 struct cgd_worker *cw;
572 struct cgd_softc *sc;
573
574 cf = kmem_alloc(sizeof(*cf), KM_SLEEP);
575 cf->cf_name = cgd_cd.cd_name;
576 cf->cf_atname = cgd_cd.cd_name;
577 cf->cf_unit = unit;
578 cf->cf_fstate = FSTATE_STAR;
579
580 cw = cgd_create_one_worker();
581 if (cw == NULL) {
582 kmem_free(cf, sizeof(*cf));
583 return NULL;
584 }
585
586 sc = device_private(config_attach_pseudo(cf));
587 if (sc == NULL) {
588 cgd_destroy_one_worker(cw);
589 return NULL;
590 }
591
592 sc->sc_worker = cw;
593
594 return sc;
595 }
596
597 static int
598 cgd_destroy(device_t dev)
599 {
600 struct cgd_softc *sc = device_private(dev);
601 struct cgd_worker *cw = sc->sc_worker;
602 cfdata_t cf;
603 int error;
604
605 cf = device_cfdata(dev);
606 error = config_detach(dev, DETACH_QUIET);
607 if (error)
608 return error;
609
610 cgd_destroy_one_worker(cw);
611
612 kmem_free(cf, sizeof(*cf));
613 return 0;
614 }
615
616 static void
617 cgd_busy(struct cgd_softc *sc)
618 {
619
620 mutex_enter(&sc->sc_lock);
621 while (sc->sc_busy)
622 cv_wait(&sc->sc_cv, &sc->sc_lock);
623 sc->sc_busy = true;
624 mutex_exit(&sc->sc_lock);
625 }
626
627 static void
628 cgd_unbusy(struct cgd_softc *sc)
629 {
630
631 mutex_enter(&sc->sc_lock);
632 sc->sc_busy = false;
633 cv_broadcast(&sc->sc_cv);
634 mutex_exit(&sc->sc_lock);
635 }
636
637 static struct cgd_worker *
638 cgd_create_one_worker(void)
639 {
640 KASSERT(cgd_spawning);
641
642 if (cgd_refcnt++ == 0) {
643 KASSERT(cgd_worker == NULL);
644 cgd_worker = cgd_create_worker();
645 }
646
647 KASSERT(cgd_worker != NULL);
648 return cgd_worker;
649 }
650
651 static void
652 cgd_destroy_one_worker(struct cgd_worker *cw)
653 {
654 KASSERT(cgd_spawning);
655 KASSERT(cw == cgd_worker);
656
657 if (--cgd_refcnt == 0) {
658 cgd_destroy_worker(cgd_worker);
659 cgd_worker = NULL;
660 }
661 }
662
663 static struct cgd_worker *
664 cgd_create_worker(void)
665 {
666 struct cgd_worker *cw;
667 struct workqueue *wq;
668 struct pool *cp;
669 int error;
670
671 cw = kmem_alloc(sizeof(struct cgd_worker), KM_SLEEP);
672 cp = kmem_alloc(sizeof(struct pool), KM_SLEEP);
673
674 error = workqueue_create(&wq, "cgd", cgd_process, NULL,
675 PRI_BIO, IPL_BIO, WQ_FPU|WQ_MPSAFE|WQ_PERCPU);
676 if (error) {
677 kmem_free(cp, sizeof(struct pool));
678 kmem_free(cw, sizeof(struct cgd_worker));
679 return NULL;
680 }
681
682 cw->cw_cpool = cp;
683 cw->cw_wq = wq;
684 pool_init(cw->cw_cpool, sizeof(struct cgd_xfer), 0,
685 0, 0, "cgdcpl", NULL, IPL_BIO);
686 mutex_init(&cw->cw_lock, MUTEX_DEFAULT, IPL_BIO);
687
688 return cw;
689 }
690
691 static void
692 cgd_destroy_worker(struct cgd_worker *cw)
693 {
694
695 /*
696 * Wait for all worker threads to complete before destroying
697 * the rest of the cgd_worker.
698 */
699 if (cw->cw_wq)
700 workqueue_destroy(cw->cw_wq);
701
702 mutex_destroy(&cw->cw_lock);
703
704 if (cw->cw_cpool) {
705 pool_destroy(cw->cw_cpool);
706 kmem_free(cw->cw_cpool, sizeof(struct pool));
707 }
708
709 kmem_free(cw, sizeof(struct cgd_worker));
710 }
711
712 static int
713 cgdopen(dev_t dev, int flags, int fmt, struct lwp *l)
714 {
715 struct cgd_softc *sc;
716 int error;
717
718 DPRINTF_FOLLOW(("cgdopen(0x%"PRIx64", %d)\n", dev, flags));
719
720 error = cgd_lock(true);
721 if (error)
722 return error;
723 sc = getcgd_softc(dev);
724 if (sc == NULL)
725 sc = cgd_spawn(CGDUNIT(dev));
726 cgd_unlock();
727 if (sc == NULL)
728 return ENXIO;
729
730 return dk_open(&sc->sc_dksc, dev, flags, fmt, l);
731 }
732
733 static int
734 cgdclose(dev_t dev, int flags, int fmt, struct lwp *l)
735 {
736 struct cgd_softc *sc;
737 struct dk_softc *dksc;
738 int error;
739
740 DPRINTF_FOLLOW(("cgdclose(0x%"PRIx64", %d)\n", dev, flags));
741
742 error = cgd_lock(false);
743 if (error)
744 return error;
745 sc = getcgd_softc(dev);
746 if (sc == NULL) {
747 error = ENXIO;
748 goto done;
749 }
750
751 dksc = &sc->sc_dksc;
752 if ((error = dk_close(dksc, dev, flags, fmt, l)) != 0)
753 goto done;
754
755 if (!DK_ATTACHED(dksc)) {
756 if ((error = cgd_destroy(sc->sc_dksc.sc_dev)) != 0) {
757 device_printf(dksc->sc_dev,
758 "unable to detach instance\n");
759 goto done;
760 }
761 }
762
763 done:
764 cgd_unlock();
765
766 return error;
767 }
768
769 static void
770 cgdstrategy(struct buf *bp)
771 {
772 struct cgd_softc *sc = getcgd_softc(bp->b_dev);
773
774 DPRINTF_FOLLOW(("cgdstrategy(%p): b_bcount = %ld\n", bp,
775 (long)bp->b_bcount));
776
777 /*
778 * Reject unaligned writes.
779 */
780 if (((uintptr_t)bp->b_data & 3) != 0) {
781 bp->b_error = EINVAL;
782 goto bail;
783 }
784
785 dk_strategy(&sc->sc_dksc, bp);
786 return;
787
788 bail:
789 bp->b_resid = bp->b_bcount;
790 biodone(bp);
791 return;
792 }
793
794 static int
795 cgdsize(dev_t dev)
796 {
797 struct cgd_softc *sc = getcgd_softc(dev);
798
799 DPRINTF_FOLLOW(("cgdsize(0x%"PRIx64")\n", dev));
800 if (!sc)
801 return -1;
802 return dk_size(&sc->sc_dksc, dev);
803 }
804
805 /*
806 * cgd_{get,put}data are functions that deal with getting a buffer
807 * for the new encrypted data.
808 * We can no longer have a buffer per device, we need a buffer per
809 * work queue...
810 */
811
812 static void *
813 cgd_getdata(struct cgd_softc *sc, unsigned long size)
814 {
815 void *data = NULL;
816
817 mutex_enter(&sc->sc_lock);
818 if (!sc->sc_data_used) {
819 sc->sc_data_used = true;
820 data = sc->sc_data;
821 }
822 mutex_exit(&sc->sc_lock);
823
824 if (data)
825 return data;
826
827 return kmem_intr_alloc(size, KM_NOSLEEP);
828 }
829
830 static void
831 cgd_putdata(struct cgd_softc *sc, void *data, unsigned long size)
832 {
833
834 if (data == sc->sc_data) {
835 mutex_enter(&sc->sc_lock);
836 sc->sc_data_used = false;
837 mutex_exit(&sc->sc_lock);
838 } else
839 kmem_intr_free(data, size);
840 }
841
842 static int
843 cgd_diskstart(device_t dev, struct buf *bp)
844 {
845 struct cgd_softc *sc = device_private(dev);
846 struct cgd_worker *cw = sc->sc_worker;
847 struct dk_softc *dksc = &sc->sc_dksc;
848 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
849 struct cgd_xfer *cx;
850 struct buf *nbp;
851 void * newaddr;
852 daddr_t bn;
853
854 DPRINTF_FOLLOW(("cgd_diskstart(%p, %p)\n", dksc, bp));
855
856 bn = bp->b_rawblkno;
857
858 /*
859 * We attempt to allocate all of our resources up front, so that
860 * we can fail quickly if they are unavailable.
861 */
862 nbp = getiobuf(sc->sc_tvn, false);
863 if (nbp == NULL)
864 return EAGAIN;
865
866 cx = pool_get(cw->cw_cpool, PR_NOWAIT);
867 if (cx == NULL) {
868 putiobuf(nbp);
869 return EAGAIN;
870 }
871
872 cx->cx_sc = sc;
873 cx->cx_obp = bp;
874 cx->cx_nbp = nbp;
875 cx->cx_srcv = cx->cx_dstv = bp->b_data;
876 cx->cx_blkno = bn;
877 cx->cx_secsize = dg->dg_secsize;
878
879 /*
880 * If we are writing, then we need to encrypt the outgoing
881 * block into a new block of memory.
882 */
883 if ((bp->b_flags & B_READ) == 0) {
884 newaddr = cgd_getdata(sc, bp->b_bcount);
885 if (!newaddr) {
886 pool_put(cw->cw_cpool, cx);
887 putiobuf(nbp);
888 return EAGAIN;
889 }
890
891 cx->cx_dstv = newaddr;
892 cx->cx_len = bp->b_bcount;
893 cx->cx_dir = CGD_CIPHER_ENCRYPT;
894
895 cgd_enqueue(sc, cx);
896 return 0;
897 }
898
899 cgd_diskstart2(sc, cx);
900 return 0;
901 }
902
903 static void
904 cgd_diskstart2(struct cgd_softc *sc, struct cgd_xfer *cx)
905 {
906 struct vnode *vp;
907 struct buf *bp;
908 struct buf *nbp;
909
910 bp = cx->cx_obp;
911 nbp = cx->cx_nbp;
912
913 nbp->b_data = cx->cx_dstv;
914 nbp->b_flags = bp->b_flags;
915 nbp->b_oflags = bp->b_oflags;
916 nbp->b_cflags = bp->b_cflags;
917 nbp->b_iodone = cgdiodone;
918 nbp->b_proc = bp->b_proc;
919 nbp->b_blkno = btodb(cx->cx_blkno * cx->cx_secsize);
920 nbp->b_bcount = bp->b_bcount;
921 nbp->b_private = cx;
922
923 BIO_COPYPRIO(nbp, bp);
924
925 if ((nbp->b_flags & B_READ) == 0) {
926 vp = nbp->b_vp;
927 mutex_enter(vp->v_interlock);
928 vp->v_numoutput++;
929 mutex_exit(vp->v_interlock);
930 }
931 VOP_STRATEGY(sc->sc_tvn, nbp);
932 }
933
934 static void
935 cgdiodone(struct buf *nbp)
936 {
937 struct cgd_xfer *cx = nbp->b_private;
938 struct buf *obp = cx->cx_obp;
939 struct cgd_softc *sc = getcgd_softc(obp->b_dev);
940 struct dk_softc *dksc = &sc->sc_dksc;
941 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
942 daddr_t bn;
943
944 KDASSERT(sc);
945
946 DPRINTF_FOLLOW(("cgdiodone(%p)\n", nbp));
947 DPRINTF(CGDB_IO, ("cgdiodone: bp %p bcount %d resid %d\n",
948 obp, obp->b_bcount, obp->b_resid));
949 DPRINTF(CGDB_IO, (" dev 0x%"PRIx64", nbp %p bn %" PRId64
950 " addr %p bcnt %d\n", nbp->b_dev, nbp, nbp->b_blkno, nbp->b_data,
951 nbp->b_bcount));
952 if (nbp->b_error != 0) {
953 obp->b_error = nbp->b_error;
954 DPRINTF(CGDB_IO, ("%s: error %d\n", dksc->sc_xname,
955 obp->b_error));
956 }
957
958 /* Perform the decryption if we are reading.
959 *
960 * Note: use the blocknumber from nbp, since it is what
961 * we used to encrypt the blocks.
962 */
963
964 if (nbp->b_flags & B_READ) {
965 bn = dbtob(nbp->b_blkno) / dg->dg_secsize;
966
967 cx->cx_obp = obp;
968 cx->cx_nbp = nbp;
969 cx->cx_dstv = obp->b_data;
970 cx->cx_srcv = obp->b_data;
971 cx->cx_len = obp->b_bcount;
972 cx->cx_blkno = bn;
973 cx->cx_secsize = dg->dg_secsize;
974 cx->cx_dir = CGD_CIPHER_DECRYPT;
975
976 cgd_enqueue(sc, cx);
977 return;
978 }
979
980 cgd_iodone2(sc, cx);
981 }
982
983 static void
984 cgd_iodone2(struct cgd_softc *sc, struct cgd_xfer *cx)
985 {
986 struct cgd_worker *cw = sc->sc_worker;
987 struct buf *obp = cx->cx_obp;
988 struct buf *nbp = cx->cx_nbp;
989 struct dk_softc *dksc = &sc->sc_dksc;
990
991 pool_put(cw->cw_cpool, cx);
992
993 /* If we allocated memory, free it now... */
994 if (nbp->b_data != obp->b_data)
995 cgd_putdata(sc, nbp->b_data, nbp->b_bcount);
996
997 putiobuf(nbp);
998
999 /* Request is complete for whatever reason */
1000 obp->b_resid = 0;
1001 if (obp->b_error != 0)
1002 obp->b_resid = obp->b_bcount;
1003
1004 dk_done(dksc, obp);
1005 dk_start(dksc, NULL);
1006 }
1007
1008 static int
1009 cgd_dumpblocks(device_t dev, void *va, daddr_t blkno, int nblk)
1010 {
1011 struct cgd_softc *sc = device_private(dev);
1012 struct dk_softc *dksc = &sc->sc_dksc;
1013 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
1014 size_t nbytes, blksize;
1015 void *buf;
1016 int error;
1017
1018 /*
1019 * dk_dump gives us units of disklabel sectors. Everything
1020 * else in cgd uses units of diskgeom sectors. These had
1021 * better agree; otherwise we need to figure out how to convert
1022 * between them.
1023 */
1024 KASSERTMSG((dg->dg_secsize == dksc->sc_dkdev.dk_label->d_secsize),
1025 "diskgeom secsize %"PRIu32" != disklabel secsize %"PRIu32,
1026 dg->dg_secsize, dksc->sc_dkdev.dk_label->d_secsize);
1027 blksize = dg->dg_secsize;
1028
1029 /*
1030 * Compute the number of bytes in this request, which dk_dump
1031 * has `helpfully' converted to a number of blocks for us.
1032 */
1033 nbytes = nblk*blksize;
1034
1035 /* Try to acquire a buffer to store the ciphertext. */
1036 buf = cgd_getdata(sc, nbytes);
1037 if (buf == NULL)
1038 /* Out of memory: give up. */
1039 return ENOMEM;
1040
1041 /* Encrypt the caller's data into the temporary buffer. */
1042 cgd_cipher(sc, buf, va, nbytes, blkno, blksize, CGD_CIPHER_ENCRYPT);
1043
1044 /* Pass it on to the underlying disk device. */
1045 error = bdev_dump(sc->sc_tdev, blkno, buf, nbytes);
1046
1047 /* Release the buffer. */
1048 cgd_putdata(sc, buf, nbytes);
1049
1050 /* Return any error from the underlying disk device. */
1051 return error;
1052 }
1053
1054 /* XXX: we should probably put these into dksubr.c, mostly */
1055 static int
1056 cgdread(dev_t dev, struct uio *uio, int flags)
1057 {
1058 struct cgd_softc *sc;
1059 struct dk_softc *dksc;
1060
1061 DPRINTF_FOLLOW(("cgdread(0x%llx, %p, %d)\n",
1062 (unsigned long long)dev, uio, flags));
1063 sc = getcgd_softc(dev);
1064 if (sc == NULL)
1065 return ENXIO;
1066 dksc = &sc->sc_dksc;
1067 if (!DK_ATTACHED(dksc))
1068 return ENXIO;
1069 return physio(cgdstrategy, NULL, dev, B_READ, minphys, uio);
1070 }
1071
1072 /* XXX: we should probably put these into dksubr.c, mostly */
1073 static int
1074 cgdwrite(dev_t dev, struct uio *uio, int flags)
1075 {
1076 struct cgd_softc *sc;
1077 struct dk_softc *dksc;
1078
1079 DPRINTF_FOLLOW(("cgdwrite(0x%"PRIx64", %p, %d)\n", dev, uio, flags));
1080 sc = getcgd_softc(dev);
1081 if (sc == NULL)
1082 return ENXIO;
1083 dksc = &sc->sc_dksc;
1084 if (!DK_ATTACHED(dksc))
1085 return ENXIO;
1086 return physio(cgdstrategy, NULL, dev, B_WRITE, minphys, uio);
1087 }
1088
1089 static int
1090 cgdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
1091 {
1092 struct cgd_softc *sc;
1093 struct dk_softc *dksc;
1094 int part = DISKPART(dev);
1095 int pmask = 1 << part;
1096 int error;
1097
1098 DPRINTF_FOLLOW(("cgdioctl(0x%"PRIx64", %ld, %p, %d, %p)\n",
1099 dev, cmd, data, flag, l));
1100
1101 switch (cmd) {
1102 case CGDIOCGET:
1103 return cgd_ioctl_get(dev, data, l);
1104 case CGDIOCSET:
1105 case CGDIOCCLR:
1106 if ((flag & FWRITE) == 0)
1107 return EBADF;
1108 /* FALLTHROUGH */
1109 default:
1110 sc = getcgd_softc(dev);
1111 if (sc == NULL)
1112 return ENXIO;
1113 dksc = &sc->sc_dksc;
1114 break;
1115 }
1116
1117 switch (cmd) {
1118 case CGDIOCSET:
1119 cgd_busy(sc);
1120 if (DK_ATTACHED(dksc))
1121 error = EBUSY;
1122 else
1123 error = cgd_ioctl_set(sc, data, l);
1124 cgd_unbusy(sc);
1125 break;
1126 case CGDIOCCLR:
1127 cgd_busy(sc);
1128 if (DK_BUSY(&sc->sc_dksc, pmask))
1129 error = EBUSY;
1130 else
1131 error = cgd_ioctl_clr(sc, l);
1132 cgd_unbusy(sc);
1133 break;
1134 case DIOCGCACHE:
1135 case DIOCCACHESYNC:
1136 cgd_busy(sc);
1137 if (!DK_ATTACHED(dksc)) {
1138 cgd_unbusy(sc);
1139 error = ENOENT;
1140 break;
1141 }
1142 /*
1143 * We pass this call down to the underlying disk.
1144 */
1145 error = VOP_IOCTL(sc->sc_tvn, cmd, data, flag, l->l_cred);
1146 cgd_unbusy(sc);
1147 break;
1148 case DIOCGSECTORALIGN: {
1149 struct disk_sectoralign *dsa = data;
1150
1151 cgd_busy(sc);
1152 if (!DK_ATTACHED(dksc)) {
1153 cgd_unbusy(sc);
1154 error = ENOENT;
1155 break;
1156 }
1157
1158 /* Get the underlying disk's sector alignment. */
1159 error = VOP_IOCTL(sc->sc_tvn, cmd, data, flag, l->l_cred);
1160 if (error) {
1161 cgd_unbusy(sc);
1162 break;
1163 }
1164
1165 /* Adjust for the disklabel partition if necessary. */
1166 if (part != RAW_PART) {
1167 struct disklabel *lp = dksc->sc_dkdev.dk_label;
1168 daddr_t offset = lp->d_partitions[part].p_offset;
1169 uint32_t r = offset % dsa->dsa_alignment;
1170
1171 if (r < dsa->dsa_firstaligned)
1172 dsa->dsa_firstaligned = dsa->dsa_firstaligned
1173 - r;
1174 else
1175 dsa->dsa_firstaligned = (dsa->dsa_firstaligned
1176 + dsa->dsa_alignment) - r;
1177 }
1178 cgd_unbusy(sc);
1179 break;
1180 }
1181 case DIOCGSTRATEGY:
1182 case DIOCSSTRATEGY:
1183 if (!DK_ATTACHED(dksc)) {
1184 error = ENOENT;
1185 break;
1186 }
1187 /*FALLTHROUGH*/
1188 default:
1189 error = dk_ioctl(dksc, dev, cmd, data, flag, l);
1190 break;
1191 case CGDIOCGET:
1192 KASSERT(0);
1193 error = EINVAL;
1194 }
1195
1196 return error;
1197 }
1198
1199 static int
1200 cgddump(dev_t dev, daddr_t blkno, void *va, size_t size)
1201 {
1202 struct cgd_softc *sc;
1203
1204 DPRINTF_FOLLOW(("cgddump(0x%"PRIx64", %" PRId64 ", %p, %lu)\n",
1205 dev, blkno, va, (unsigned long)size));
1206 sc = getcgd_softc(dev);
1207 if (sc == NULL)
1208 return ENXIO;
1209 return dk_dump(&sc->sc_dksc, dev, blkno, va, size, DK_DUMP_RECURSIVE);
1210 }
1211
1212 /*
1213 * XXXrcd:
1214 * for now we hardcode the maximum key length.
1215 */
1216 #define MAX_KEYSIZE 1024
1217
1218 static const struct {
1219 const char *n;
1220 int v;
1221 int d;
1222 } encblkno[] = {
1223 { "encblkno", CGD_CIPHER_CBC_ENCBLKNO8, 1 },
1224 { "encblkno8", CGD_CIPHER_CBC_ENCBLKNO8, 1 },
1225 { "encblkno1", CGD_CIPHER_CBC_ENCBLKNO1, 8 },
1226 };
1227
1228 /* ARGSUSED */
1229 static int
1230 cgd_ioctl_set(struct cgd_softc *sc, void *data, struct lwp *l)
1231 {
1232 struct cgd_ioctl *ci = data;
1233 struct vnode *vp;
1234 int ret;
1235 size_t i;
1236 size_t keybytes; /* key length in bytes */
1237 const char *cp;
1238 struct pathbuf *pb;
1239 char *inbuf;
1240 struct dk_softc *dksc = &sc->sc_dksc;
1241
1242 cp = ci->ci_disk;
1243
1244 ret = pathbuf_copyin(ci->ci_disk, &pb);
1245 if (ret != 0) {
1246 return ret;
1247 }
1248 ret = vn_bdev_openpath(pb, &vp, l);
1249 pathbuf_destroy(pb);
1250 if (ret != 0) {
1251 return ret;
1252 }
1253
1254 inbuf = kmem_alloc(MAX_KEYSIZE, KM_SLEEP);
1255
1256 if ((ret = cgdinit(sc, cp, vp, l)) != 0)
1257 goto bail;
1258
1259 (void)memset(inbuf, 0, MAX_KEYSIZE);
1260 ret = copyinstr(ci->ci_alg, inbuf, 256, NULL);
1261 if (ret)
1262 goto bail;
1263 sc->sc_cfuncs = cryptfuncs_find(inbuf);
1264 if (!sc->sc_cfuncs) {
1265 ret = EINVAL;
1266 goto bail;
1267 }
1268
1269 (void)memset(inbuf, 0, MAX_KEYSIZE);
1270 ret = copyinstr(ci->ci_ivmethod, inbuf, MAX_KEYSIZE, NULL);
1271 if (ret)
1272 goto bail;
1273
1274 for (i = 0; i < __arraycount(encblkno); i++)
1275 if (strcmp(encblkno[i].n, inbuf) == 0)
1276 break;
1277
1278 if (i == __arraycount(encblkno)) {
1279 ret = EINVAL;
1280 goto bail;
1281 }
1282
1283 keybytes = ci->ci_keylen / 8 + 1;
1284 if (keybytes > MAX_KEYSIZE) {
1285 ret = EINVAL;
1286 goto bail;
1287 }
1288
1289 (void)memset(inbuf, 0, MAX_KEYSIZE);
1290 ret = copyin(ci->ci_key, inbuf, keybytes);
1291 if (ret)
1292 goto bail;
1293
1294 sc->sc_cdata.cf_blocksize = ci->ci_blocksize;
1295 sc->sc_cdata.cf_mode = encblkno[i].v;
1296
1297 /*
1298 * Print a warning if the user selected the legacy encblkno8
1299 * mistake, and reject it altogether for ciphers that it
1300 * doesn't apply to.
1301 */
1302 if (encblkno[i].v != CGD_CIPHER_CBC_ENCBLKNO1) {
1303 if (strcmp(sc->sc_cfuncs->cf_name, "aes-cbc") &&
1304 strcmp(sc->sc_cfuncs->cf_name, "3des-cbc") &&
1305 strcmp(sc->sc_cfuncs->cf_name, "blowfish-cbc")) {
1306 log(LOG_WARNING, "cgd: %s only makes sense for cbc,"
1307 " not for %s; ignoring\n",
1308 encblkno[i].n, sc->sc_cfuncs->cf_name);
1309 sc->sc_cdata.cf_mode = CGD_CIPHER_CBC_ENCBLKNO1;
1310 } else {
1311 log(LOG_WARNING, "cgd: enabling legacy encblkno8\n");
1312 }
1313 }
1314
1315 sc->sc_cdata.cf_keylen = ci->ci_keylen;
1316 sc->sc_cdata.cf_priv = sc->sc_cfuncs->cf_init(ci->ci_keylen, inbuf,
1317 &sc->sc_cdata.cf_blocksize);
1318 if (sc->sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE) {
1319 log(LOG_WARNING, "cgd: Disallowed cipher with blocksize %zu > %u\n",
1320 sc->sc_cdata.cf_blocksize, CGD_MAXBLOCKSIZE);
1321 sc->sc_cdata.cf_priv = NULL;
1322 }
1323
1324 /*
1325 * The blocksize is supposed to be in bytes. Unfortunately originally
1326 * it was expressed in bits. For compatibility we maintain encblkno
1327 * and encblkno8.
1328 */
1329 sc->sc_cdata.cf_blocksize /= encblkno[i].d;
1330 (void)explicit_memset(inbuf, 0, MAX_KEYSIZE);
1331 if (!sc->sc_cdata.cf_priv) {
1332 ret = EINVAL; /* XXX is this the right error? */
1333 goto bail;
1334 }
1335 kmem_free(inbuf, MAX_KEYSIZE);
1336
1337 bufq_alloc(&dksc->sc_bufq, "fcfs", 0);
1338
1339 sc->sc_data = kmem_alloc(MAXPHYS, KM_SLEEP);
1340 sc->sc_data_used = false;
1341
1342 /* Attach the disk. */
1343 dk_attach(dksc);
1344 disk_attach(&dksc->sc_dkdev);
1345
1346 disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL);
1347
1348 /* Discover wedges on this disk. */
1349 dkwedge_discover(&dksc->sc_dkdev);
1350
1351 return 0;
1352
1353 bail:
1354 kmem_free(inbuf, MAX_KEYSIZE);
1355 (void)vn_close(vp, FREAD|FWRITE, l->l_cred);
1356 return ret;
1357 }
1358
1359 /* ARGSUSED */
1360 static int
1361 cgd_ioctl_clr(struct cgd_softc *sc, struct lwp *l)
1362 {
1363 struct dk_softc *dksc = &sc->sc_dksc;
1364
1365 if (!DK_ATTACHED(dksc))
1366 return ENXIO;
1367
1368 /* Delete all of our wedges. */
1369 dkwedge_delall(&dksc->sc_dkdev);
1370
1371 /* Kill off any queued buffers. */
1372 dk_drain(dksc);
1373 bufq_free(dksc->sc_bufq);
1374
1375 (void)vn_close(sc->sc_tvn, FREAD|FWRITE, l->l_cred);
1376 sc->sc_cfuncs->cf_destroy(sc->sc_cdata.cf_priv);
1377 kmem_free(sc->sc_tpath, sc->sc_tpathlen);
1378 kmem_free(sc->sc_data, MAXPHYS);
1379 sc->sc_data_used = false;
1380 dk_detach(dksc);
1381 disk_detach(&dksc->sc_dkdev);
1382
1383 return 0;
1384 }
1385
1386 static int
1387 cgd_ioctl_get(dev_t dev, void *data, struct lwp *l)
1388 {
1389 struct cgd_softc *sc;
1390 struct cgd_user *cgu;
1391 int unit, error;
1392
1393 unit = CGDUNIT(dev);
1394 cgu = (struct cgd_user *)data;
1395
1396 DPRINTF_FOLLOW(("cgd_ioctl_get(0x%"PRIx64", %d, %p, %p)\n",
1397 dev, unit, data, l));
1398
1399 /* XXX, we always return this units data, so if cgu_unit is
1400 * not -1, that field doesn't match the rest
1401 */
1402 if (cgu->cgu_unit == -1)
1403 cgu->cgu_unit = unit;
1404
1405 if (cgu->cgu_unit < 0)
1406 return EINVAL; /* XXX: should this be ENXIO? */
1407
1408 error = cgd_lock(false);
1409 if (error)
1410 return error;
1411
1412 sc = device_lookup_private(&cgd_cd, unit);
1413 if (sc == NULL || !DK_ATTACHED(&sc->sc_dksc)) {
1414 cgu->cgu_dev = 0;
1415 cgu->cgu_alg[0] = '\0';
1416 cgu->cgu_blocksize = 0;
1417 cgu->cgu_mode = 0;
1418 cgu->cgu_keylen = 0;
1419 }
1420 else {
1421 mutex_enter(&sc->sc_lock);
1422 cgu->cgu_dev = sc->sc_tdev;
1423 strncpy(cgu->cgu_alg, sc->sc_cfuncs->cf_name,
1424 sizeof(cgu->cgu_alg));
1425 cgu->cgu_blocksize = sc->sc_cdata.cf_blocksize;
1426 cgu->cgu_mode = sc->sc_cdata.cf_mode;
1427 cgu->cgu_keylen = sc->sc_cdata.cf_keylen;
1428 mutex_exit(&sc->sc_lock);
1429 }
1430
1431 cgd_unlock();
1432 return 0;
1433 }
1434
1435 static int
1436 cgdinit(struct cgd_softc *sc, const char *cpath, struct vnode *vp,
1437 struct lwp *l)
1438 {
1439 struct disk_geom *dg;
1440 int ret;
1441 char *tmppath;
1442 uint64_t psize;
1443 unsigned secsize;
1444 struct dk_softc *dksc = &sc->sc_dksc;
1445
1446 sc->sc_tvn = vp;
1447 sc->sc_tpath = NULL;
1448
1449 tmppath = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1450 ret = copyinstr(cpath, tmppath, MAXPATHLEN, &sc->sc_tpathlen);
1451 if (ret)
1452 goto bail;
1453 sc->sc_tpath = kmem_alloc(sc->sc_tpathlen, KM_SLEEP);
1454 memcpy(sc->sc_tpath, tmppath, sc->sc_tpathlen);
1455
1456 sc->sc_tdev = vp->v_rdev;
1457
1458 if ((ret = getdisksize(vp, &psize, &secsize)) != 0)
1459 goto bail;
1460
1461 if (psize == 0) {
1462 ret = ENODEV;
1463 goto bail;
1464 }
1465
1466 /*
1467 * XXX here we should probe the underlying device. If we
1468 * are accessing a partition of type RAW_PART, then
1469 * we should populate our initial geometry with the
1470 * geometry that we discover from the device.
1471 */
1472 dg = &dksc->sc_dkdev.dk_geom;
1473 memset(dg, 0, sizeof(*dg));
1474 dg->dg_secperunit = psize;
1475 dg->dg_secsize = secsize;
1476 dg->dg_ntracks = 1;
1477 dg->dg_nsectors = 1024 * 1024 / dg->dg_secsize;
1478 dg->dg_ncylinders = dg->dg_secperunit / dg->dg_nsectors;
1479
1480 bail:
1481 kmem_free(tmppath, MAXPATHLEN);
1482 if (ret && sc->sc_tpath)
1483 kmem_free(sc->sc_tpath, sc->sc_tpathlen);
1484 return ret;
1485 }
1486
1487 /*
1488 * Our generic cipher entry point. This takes care of the
1489 * IV mode and passes off the work to the specific cipher.
1490 * We implement here the IV method ``encrypted block
1491 * number''.
1492 *
1493 * XXXrcd: for now we rely on our own crypto framework defined
1494 * in dev/cgd_crypto.c. This will change when we
1495 * get a generic kernel crypto framework.
1496 */
1497
1498 static void
1499 blkno2blkno_buf(char *sbuf, daddr_t blkno)
1500 {
1501 int i;
1502
1503 /* Set up the blkno in blkno_buf, here we do not care much
1504 * about the final layout of the information as long as we
1505 * can guarantee that each sector will have a different IV
1506 * and that the endianness of the machine will not affect
1507 * the representation that we have chosen.
1508 *
1509 * We choose this representation, because it does not rely
1510 * on the size of buf (which is the blocksize of the cipher),
1511 * but allows daddr_t to grow without breaking existing
1512 * disks.
1513 *
1514 * Note that blkno2blkno_buf does not take a size as input,
1515 * and hence must be called on a pre-zeroed buffer of length
1516 * greater than or equal to sizeof(daddr_t).
1517 */
1518 for (i=0; i < sizeof(daddr_t); i++) {
1519 *sbuf++ = blkno & 0xff;
1520 blkno >>= 8;
1521 }
1522 }
1523
1524 static struct cpu_info *
1525 cgd_cpu(struct cgd_softc *sc)
1526 {
1527 struct cgd_worker *cw = sc->sc_worker;
1528 struct cpu_info *ci = NULL;
1529 u_int cidx, i;
1530
1531 if (cw->cw_busy == 0) {
1532 cw->cw_last = cpu_index(curcpu());
1533 return NULL;
1534 }
1535
1536 for (i=0, cidx = cw->cw_last+1; i<maxcpus; ++i, ++cidx) {
1537 if (cidx >= maxcpus)
1538 cidx = 0;
1539 ci = cpu_lookup(cidx);
1540 if (ci) {
1541 cw->cw_last = cidx;
1542 break;
1543 }
1544 }
1545
1546 return ci;
1547 }
1548
1549 static void
1550 cgd_enqueue(struct cgd_softc *sc, struct cgd_xfer *cx)
1551 {
1552 struct cgd_worker *cw = sc->sc_worker;
1553 struct cpu_info *ci;
1554
1555 mutex_enter(&cw->cw_lock);
1556 ci = cgd_cpu(sc);
1557 cw->cw_busy++;
1558 mutex_exit(&cw->cw_lock);
1559
1560 workqueue_enqueue(cw->cw_wq, &cx->cx_work, ci);
1561 }
1562
1563 static void
1564 cgd_process(struct work *wk, void *arg)
1565 {
1566 struct cgd_xfer *cx = (struct cgd_xfer *)wk;
1567 struct cgd_softc *sc = cx->cx_sc;
1568 struct cgd_worker *cw = sc->sc_worker;
1569
1570 cgd_cipher(sc, cx->cx_dstv, cx->cx_srcv, cx->cx_len,
1571 cx->cx_blkno, cx->cx_secsize, cx->cx_dir);
1572
1573 if (cx->cx_dir == CGD_CIPHER_ENCRYPT) {
1574 cgd_diskstart2(sc, cx);
1575 } else {
1576 cgd_iodone2(sc, cx);
1577 }
1578
1579 mutex_enter(&cw->cw_lock);
1580 if (cw->cw_busy > 0)
1581 cw->cw_busy--;
1582 mutex_exit(&cw->cw_lock);
1583 }
1584
1585 static void
1586 cgd_cipher(struct cgd_softc *sc, void *dstv, const void *srcv,
1587 size_t len, daddr_t blkno, size_t secsize, int dir)
1588 {
1589 char *dst = dstv;
1590 const char *src = srcv;
1591 cfunc_cipher *cipher = sc->sc_cfuncs->cf_cipher;
1592 size_t blocksize = sc->sc_cdata.cf_blocksize;
1593 size_t todo;
1594 char blkno_buf[CGD_MAXBLOCKSIZE] __aligned(CGD_BLOCKALIGN);
1595
1596 DPRINTF_FOLLOW(("cgd_cipher() dir=%d\n", dir));
1597
1598 if (sc->sc_cdata.cf_mode == CGD_CIPHER_CBC_ENCBLKNO8)
1599 blocksize /= 8;
1600
1601 KASSERT(len % blocksize == 0);
1602 /* ensure that sizeof(daddr_t) <= blocksize (for encblkno IVing) */
1603 KASSERT(sizeof(daddr_t) <= blocksize);
1604 KASSERT(blocksize <= CGD_MAXBLOCKSIZE);
1605
1606 for (; len > 0; len -= todo) {
1607 todo = MIN(len, secsize);
1608
1609 memset(blkno_buf, 0x0, blocksize);
1610 blkno2blkno_buf(blkno_buf, blkno);
1611 IFDEBUG(CGDB_CRYPTO, hexprint("step 1: blkno_buf",
1612 blkno_buf, blocksize));
1613
1614 /*
1615 * Handle bollocksed up encblkno8 mistake. We used to
1616 * compute the encryption of a zero block with blkno as
1617 * the CBC IV -- except in an early mistake arising
1618 * from bit/byte confusion, we actually computed the
1619 * encryption of the last of _eight_ zero blocks under
1620 * CBC as the CBC IV.
1621 *
1622 * Encrypting the block number is handled inside the
1623 * cipher dispatch now (even though in practice, both
1624 * CBC and XTS will do the same thing), so we have to
1625 * simulate the block number that would yield the same
1626 * result. So we encrypt _six_ zero blocks -- the
1627 * first one and the last one are handled inside the
1628 * cipher dispatch.
1629 */
1630 if (sc->sc_cdata.cf_mode == CGD_CIPHER_CBC_ENCBLKNO8) {
1631 static const uint8_t zero[CGD_MAXBLOCKSIZE];
1632 uint8_t iv[CGD_MAXBLOCKSIZE];
1633
1634 memcpy(iv, blkno_buf, blocksize);
1635 cipher(sc->sc_cdata.cf_priv, blkno_buf, zero,
1636 6*blocksize, iv, CGD_CIPHER_ENCRYPT);
1637 memmove(blkno_buf, blkno_buf + 5*blocksize, blocksize);
1638 }
1639
1640 cipher(sc->sc_cdata.cf_priv, dst, src, todo, blkno_buf, dir);
1641
1642 dst += todo;
1643 src += todo;
1644 blkno++;
1645 }
1646 }
1647
1648 #ifdef DEBUG
1649 static void
1650 hexprint(const char *start, void *buf, int len)
1651 {
1652 char *c = buf;
1653
1654 KASSERTMSG(len >= 0, "hexprint: called with len < 0");
1655 printf("%s: len=%06d 0x", start, len);
1656 while (len--)
1657 printf("%02x", (unsigned char) *c++);
1658 }
1659 #endif
1660
1661 static void
1662 cgd_selftest(void)
1663 {
1664 struct cgd_softc sc;
1665 void *buf;
1666
1667 for (size_t i = 0; i < __arraycount(selftests); i++) {
1668 const char *alg = selftests[i].alg;
1669 int encblkno8 = selftests[i].encblkno8;
1670 const uint8_t *key = selftests[i].key;
1671 int keylen = selftests[i].keylen;
1672 int txtlen = selftests[i].txtlen;
1673
1674 aprint_debug("cgd: self-test %s-%d%s\n", alg, keylen,
1675 encblkno8 ? " (encblkno8)" : "");
1676
1677 memset(&sc, 0, sizeof(sc));
1678
1679 sc.sc_cfuncs = cryptfuncs_find(alg);
1680 if (sc.sc_cfuncs == NULL)
1681 panic("%s not implemented", alg);
1682
1683 sc.sc_cdata.cf_blocksize = 8 * selftests[i].blocksize;
1684 sc.sc_cdata.cf_mode = encblkno8 ? CGD_CIPHER_CBC_ENCBLKNO8 :
1685 CGD_CIPHER_CBC_ENCBLKNO1;
1686 sc.sc_cdata.cf_keylen = keylen;
1687
1688 sc.sc_cdata.cf_priv = sc.sc_cfuncs->cf_init(keylen,
1689 key, &sc.sc_cdata.cf_blocksize);
1690 if (sc.sc_cdata.cf_priv == NULL)
1691 panic("cf_priv is NULL");
1692 if (sc.sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE)
1693 panic("bad block size %zu", sc.sc_cdata.cf_blocksize);
1694
1695 if (!encblkno8)
1696 sc.sc_cdata.cf_blocksize /= 8;
1697
1698 buf = kmem_alloc(txtlen, KM_SLEEP);
1699 memcpy(buf, selftests[i].ptxt, txtlen);
1700
1701 cgd_cipher(&sc, buf, buf, txtlen, selftests[i].blkno,
1702 selftests[i].secsize, CGD_CIPHER_ENCRYPT);
1703 if (memcmp(buf, selftests[i].ctxt, txtlen) != 0) {
1704 hexdump(printf, "was", buf, txtlen);
1705 hexdump(printf, "exp", selftests[i].ctxt, txtlen);
1706 panic("cgd %s-%d encryption is broken [%zu]",
1707 selftests[i].alg, keylen, i);
1708 }
1709
1710 cgd_cipher(&sc, buf, buf, txtlen, selftests[i].blkno,
1711 selftests[i].secsize, CGD_CIPHER_DECRYPT);
1712 if (memcmp(buf, selftests[i].ptxt, txtlen) != 0) {
1713 hexdump(printf, "was", buf, txtlen);
1714 hexdump(printf, "exp", selftests[i].ptxt, txtlen);
1715 panic("cgd %s-%d decryption is broken [%zu]",
1716 selftests[i].alg, keylen, i);
1717 }
1718
1719 kmem_free(buf, txtlen);
1720 sc.sc_cfuncs->cf_destroy(sc.sc_cdata.cf_priv);
1721 }
1722
1723 aprint_debug("cgd: self-tests passed\n");
1724 }
1725
1726 MODULE(MODULE_CLASS_DRIVER, cgd, "blowfish,des,dk_subr,bufq_fcfs");
1727
1728 #ifdef _MODULE
1729 CFDRIVER_DECL(cgd, DV_DISK, NULL);
1730
1731 devmajor_t cgd_bmajor = -1, cgd_cmajor = -1;
1732 #endif
1733
1734 static int
1735 cgd_modcmd(modcmd_t cmd, void *arg)
1736 {
1737 int error = 0;
1738
1739 switch (cmd) {
1740 case MODULE_CMD_INIT:
1741 #ifdef _MODULE
1742 mutex_init(&cgd_spawning_mtx, MUTEX_DEFAULT, IPL_NONE);
1743 cv_init(&cgd_spawning_cv, "cgspwn");
1744
1745 /*
1746 * Attach the {b,c}devsw's
1747 */
1748 error = devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1749 &cgd_cdevsw, &cgd_cmajor);
1750 if (error) {
1751 aprint_error("%s: unable to attach %s devsw, "
1752 "error %d", __func__, cgd_cd.cd_name, error);
1753 break;
1754 }
1755
1756 /*
1757 * Attach to autoconf database
1758 */
1759 error = config_cfdriver_attach(&cgd_cd);
1760 if (error) {
1761 devsw_detach(&cgd_bdevsw, &cgd_cdevsw);
1762 aprint_error("%s: unable to register cfdriver for"
1763 "%s, error %d\n", __func__, cgd_cd.cd_name, error);
1764 break;
1765 }
1766
1767 error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
1768 if (error) {
1769 config_cfdriver_detach(&cgd_cd);
1770 devsw_detach(&cgd_bdevsw, &cgd_cdevsw);
1771 aprint_error("%s: unable to register cfattach for"
1772 "%s, error %d\n", __func__, cgd_cd.cd_name, error);
1773 break;
1774 }
1775 #endif
1776 break;
1777
1778 case MODULE_CMD_FINI:
1779 #ifdef _MODULE
1780 /*
1781 * Remove device from autoconf database
1782 */
1783 error = config_cfattach_detach(cgd_cd.cd_name, &cgd_ca);
1784 if (error) {
1785 aprint_error("%s: failed to detach %s cfattach, "
1786 "error %d\n", __func__, cgd_cd.cd_name, error);
1787 break;
1788 }
1789 error = config_cfdriver_detach(&cgd_cd);
1790 if (error) {
1791 (void)config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
1792 aprint_error("%s: failed to detach %s cfdriver, "
1793 "error %d\n", __func__, cgd_cd.cd_name, error);
1794 break;
1795 }
1796
1797 /*
1798 * Remove {b,c}devsw's
1799 */
1800 devsw_detach(&cgd_bdevsw, &cgd_cdevsw);
1801
1802 cv_destroy(&cgd_spawning_cv);
1803 mutex_destroy(&cgd_spawning_mtx);
1804 #endif
1805 break;
1806
1807 case MODULE_CMD_STAT:
1808 error = ENOTTY;
1809 break;
1810 default:
1811 error = ENOTTY;
1812 break;
1813 }
1814
1815 return error;
1816 }
Cache object: 8b17067319a2549c156ca27cdd168901
|