1 /* $NetBSD: cgd.c,v 1.139 2020/08/01 02:15:49 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.139 2020/08/01 02:15:49 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 const int pmask = 1 << RAW_PART; 533 struct cgd_softc *sc = device_private(self); 534 struct dk_softc *dksc = &sc->sc_dksc; 535 536 if (DK_BUSY(dksc, pmask)) 537 return EBUSY; 538 539 if (DK_ATTACHED(dksc) && 540 (ret = cgd_ioctl_clr(sc, curlwp)) != 0) 541 return ret; 542 543 disk_destroy(&dksc->sc_dkdev); 544 cv_destroy(&sc->sc_cv); 545 mutex_destroy(&sc->sc_lock); 546 547 return 0; 548 } 549 550 void 551 cgdattach(int num) 552 { 553 #ifndef _MODULE 554 int error; 555 556 mutex_init(&cgd_spawning_mtx, MUTEX_DEFAULT, IPL_NONE); 557 cv_init(&cgd_spawning_cv, "cgspwn"); 558 559 error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca); 560 if (error != 0) 561 aprint_error("%s: unable to register cfattach\n", 562 cgd_cd.cd_name); 563 #endif 564 565 cgd_selftest(); 566 } 567 568 static struct cgd_softc * 569 cgd_spawn(int unit) 570 { 571 cfdata_t cf; 572 struct cgd_worker *cw; 573 struct cgd_softc *sc; 574 575 cf = kmem_alloc(sizeof(*cf), KM_SLEEP); 576 cf->cf_name = cgd_cd.cd_name; 577 cf->cf_atname = cgd_cd.cd_name; 578 cf->cf_unit = unit; 579 cf->cf_fstate = FSTATE_STAR; 580 581 cw = cgd_create_one_worker(); 582 if (cw == NULL) { 583 kmem_free(cf, sizeof(*cf)); 584 return NULL; 585 } 586 587 sc = device_private(config_attach_pseudo(cf)); 588 if (sc == NULL) { 589 cgd_destroy_one_worker(cw); 590 return NULL; 591 } 592 593 sc->sc_worker = cw; 594 595 return sc; 596 } 597 598 static int 599 cgd_destroy(device_t dev) 600 { 601 struct cgd_softc *sc = device_private(dev); 602 struct cgd_worker *cw = sc->sc_worker; 603 cfdata_t cf; 604 int error; 605 606 cf = device_cfdata(dev); 607 error = config_detach(dev, DETACH_QUIET); 608 if (error) 609 return error; 610 611 cgd_destroy_one_worker(cw); 612 613 kmem_free(cf, sizeof(*cf)); 614 return 0; 615 } 616 617 static void 618 cgd_busy(struct cgd_softc *sc) 619 { 620 621 mutex_enter(&sc->sc_lock); 622 while (sc->sc_busy) 623 cv_wait(&sc->sc_cv, &sc->sc_lock); 624 sc->sc_busy = true; 625 mutex_exit(&sc->sc_lock); 626 } 627 628 static void 629 cgd_unbusy(struct cgd_softc *sc) 630 { 631 632 mutex_enter(&sc->sc_lock); 633 sc->sc_busy = false; 634 cv_broadcast(&sc->sc_cv); 635 mutex_exit(&sc->sc_lock); 636 } 637 638 static struct cgd_worker * 639 cgd_create_one_worker(void) 640 { 641 KASSERT(cgd_spawning); 642 643 if (cgd_refcnt++ == 0) { 644 KASSERT(cgd_worker == NULL); 645 cgd_worker = cgd_create_worker(); 646 } 647 648 KASSERT(cgd_worker != NULL); 649 return cgd_worker; 650 } 651 652 static void 653 cgd_destroy_one_worker(struct cgd_worker *cw) 654 { 655 KASSERT(cgd_spawning); 656 KASSERT(cw == cgd_worker); 657 658 if (--cgd_refcnt == 0) { 659 cgd_destroy_worker(cgd_worker); 660 cgd_worker = NULL; 661 } 662 } 663 664 static struct cgd_worker * 665 cgd_create_worker(void) 666 { 667 struct cgd_worker *cw; 668 struct workqueue *wq; 669 struct pool *cp; 670 int error; 671 672 cw = kmem_alloc(sizeof(struct cgd_worker), KM_SLEEP); 673 cp = kmem_alloc(sizeof(struct pool), KM_SLEEP); 674 675 error = workqueue_create(&wq, "cgd", cgd_process, NULL, 676 PRI_BIO, IPL_BIO, WQ_FPU|WQ_MPSAFE|WQ_PERCPU); 677 if (error) { 678 kmem_free(cp, sizeof(struct pool)); 679 kmem_free(cw, sizeof(struct cgd_worker)); 680 return NULL; 681 } 682 683 cw->cw_cpool = cp; 684 cw->cw_wq = wq; 685 pool_init(cw->cw_cpool, sizeof(struct cgd_xfer), 0, 686 0, 0, "cgdcpl", NULL, IPL_BIO); 687 mutex_init(&cw->cw_lock, MUTEX_DEFAULT, IPL_BIO); 688 689 return cw; 690 } 691 692 static void 693 cgd_destroy_worker(struct cgd_worker *cw) 694 { 695 mutex_destroy(&cw->cw_lock); 696 697 if (cw->cw_cpool) { 698 pool_destroy(cw->cw_cpool); 699 kmem_free(cw->cw_cpool, sizeof(struct pool)); 700 } 701 if (cw->cw_wq) 702 workqueue_destroy(cw->cw_wq); 703 704 kmem_free(cw, sizeof(struct cgd_worker)); 705 } 706 707 static int 708 cgdopen(dev_t dev, int flags, int fmt, struct lwp *l) 709 { 710 struct cgd_softc *sc; 711 int error; 712 713 DPRINTF_FOLLOW(("cgdopen(0x%"PRIx64", %d)\n", dev, flags)); 714 715 error = cgd_lock(true); 716 if (error) 717 return error; 718 sc = getcgd_softc(dev); 719 if (sc == NULL) 720 sc = cgd_spawn(CGDUNIT(dev)); 721 cgd_unlock(); 722 if (sc == NULL) 723 return ENXIO; 724 725 return dk_open(&sc->sc_dksc, dev, flags, fmt, l); 726 } 727 728 static int 729 cgdclose(dev_t dev, int flags, int fmt, struct lwp *l) 730 { 731 struct cgd_softc *sc; 732 struct dk_softc *dksc; 733 int error; 734 735 DPRINTF_FOLLOW(("cgdclose(0x%"PRIx64", %d)\n", dev, flags)); 736 737 error = cgd_lock(false); 738 if (error) 739 return error; 740 sc = getcgd_softc(dev); 741 if (sc == NULL) { 742 error = ENXIO; 743 goto done; 744 } 745 746 dksc = &sc->sc_dksc; 747 if ((error = dk_close(dksc, dev, flags, fmt, l)) != 0) 748 goto done; 749 750 if (!DK_ATTACHED(dksc)) { 751 if ((error = cgd_destroy(sc->sc_dksc.sc_dev)) != 0) { 752 device_printf(dksc->sc_dev, 753 "unable to detach instance\n"); 754 goto done; 755 } 756 } 757 758 done: 759 cgd_unlock(); 760 761 return error; 762 } 763 764 static void 765 cgdstrategy(struct buf *bp) 766 { 767 struct cgd_softc *sc = getcgd_softc(bp->b_dev); 768 769 DPRINTF_FOLLOW(("cgdstrategy(%p): b_bcount = %ld\n", bp, 770 (long)bp->b_bcount)); 771 772 /* 773 * Reject unaligned writes. 774 */ 775 if (((uintptr_t)bp->b_data & 3) != 0) { 776 bp->b_error = EINVAL; 777 goto bail; 778 } 779 780 dk_strategy(&sc->sc_dksc, bp); 781 return; 782 783 bail: 784 bp->b_resid = bp->b_bcount; 785 biodone(bp); 786 return; 787 } 788 789 static int 790 cgdsize(dev_t dev) 791 { 792 struct cgd_softc *sc = getcgd_softc(dev); 793 794 DPRINTF_FOLLOW(("cgdsize(0x%"PRIx64")\n", dev)); 795 if (!sc) 796 return -1; 797 return dk_size(&sc->sc_dksc, dev); 798 } 799 800 /* 801 * cgd_{get,put}data are functions that deal with getting a buffer 802 * for the new encrypted data. 803 * We can no longer have a buffer per device, we need a buffer per 804 * work queue... 805 */ 806 807 static void * 808 cgd_getdata(struct cgd_softc *sc, unsigned long size) 809 { 810 void *data = NULL; 811 812 mutex_enter(&sc->sc_lock); 813 if (!sc->sc_data_used) { 814 sc->sc_data_used = true; 815 data = sc->sc_data; 816 } 817 mutex_exit(&sc->sc_lock); 818 819 if (data) 820 return data; 821 822 return kmem_intr_alloc(size, KM_NOSLEEP); 823 } 824 825 static void 826 cgd_putdata(struct cgd_softc *sc, void *data, unsigned long size) 827 { 828 829 if (data == sc->sc_data) { 830 mutex_enter(&sc->sc_lock); 831 sc->sc_data_used = false; 832 mutex_exit(&sc->sc_lock); 833 } else 834 kmem_intr_free(data, size); 835 } 836 837 static int 838 cgd_diskstart(device_t dev, struct buf *bp) 839 { 840 struct cgd_softc *sc = device_private(dev); 841 struct cgd_worker *cw = sc->sc_worker; 842 struct dk_softc *dksc = &sc->sc_dksc; 843 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom; 844 struct cgd_xfer *cx; 845 struct buf *nbp; 846 void * newaddr; 847 daddr_t bn; 848 849 DPRINTF_FOLLOW(("cgd_diskstart(%p, %p)\n", dksc, bp)); 850 851 bn = bp->b_rawblkno; 852 853 /* 854 * We attempt to allocate all of our resources up front, so that 855 * we can fail quickly if they are unavailable. 856 */ 857 nbp = getiobuf(sc->sc_tvn, false); 858 if (nbp == NULL) 859 return EAGAIN; 860 861 cx = pool_get(cw->cw_cpool, PR_NOWAIT); 862 if (cx == NULL) { 863 putiobuf(nbp); 864 return EAGAIN; 865 } 866 867 cx->cx_sc = sc; 868 cx->cx_obp = bp; 869 cx->cx_nbp = nbp; 870 cx->cx_srcv = cx->cx_dstv = bp->b_data; 871 cx->cx_blkno = bn; 872 cx->cx_secsize = dg->dg_secsize; 873 874 /* 875 * If we are writing, then we need to encrypt the outgoing 876 * block into a new block of memory. 877 */ 878 if ((bp->b_flags & B_READ) == 0) { 879 newaddr = cgd_getdata(sc, bp->b_bcount); 880 if (!newaddr) { 881 pool_put(cw->cw_cpool, cx); 882 putiobuf(nbp); 883 return EAGAIN; 884 } 885 886 cx->cx_dstv = newaddr; 887 cx->cx_len = bp->b_bcount; 888 cx->cx_dir = CGD_CIPHER_ENCRYPT; 889 890 cgd_enqueue(sc, cx); 891 return 0; 892 } 893 894 cgd_diskstart2(sc, cx); 895 return 0; 896 } 897 898 static void 899 cgd_diskstart2(struct cgd_softc *sc, struct cgd_xfer *cx) 900 { 901 struct vnode *vp; 902 struct buf *bp; 903 struct buf *nbp; 904 905 bp = cx->cx_obp; 906 nbp = cx->cx_nbp; 907 908 nbp->b_data = cx->cx_dstv; 909 nbp->b_flags = bp->b_flags; 910 nbp->b_oflags = bp->b_oflags; 911 nbp->b_cflags = bp->b_cflags; 912 nbp->b_iodone = cgdiodone; 913 nbp->b_proc = bp->b_proc; 914 nbp->b_blkno = btodb(cx->cx_blkno * cx->cx_secsize); 915 nbp->b_bcount = bp->b_bcount; 916 nbp->b_private = cx; 917 918 BIO_COPYPRIO(nbp, bp); 919 920 if ((nbp->b_flags & B_READ) == 0) { 921 vp = nbp->b_vp; 922 mutex_enter(vp->v_interlock); 923 vp->v_numoutput++; 924 mutex_exit(vp->v_interlock); 925 } 926 VOP_STRATEGY(sc->sc_tvn, nbp); 927 } 928 929 static void 930 cgdiodone(struct buf *nbp) 931 { 932 struct cgd_xfer *cx = nbp->b_private; 933 struct buf *obp = cx->cx_obp; 934 struct cgd_softc *sc = getcgd_softc(obp->b_dev); 935 struct dk_softc *dksc = &sc->sc_dksc; 936 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom; 937 daddr_t bn; 938 939 KDASSERT(sc); 940 941 DPRINTF_FOLLOW(("cgdiodone(%p)\n", nbp)); 942 DPRINTF(CGDB_IO, ("cgdiodone: bp %p bcount %d resid %d\n", 943 obp, obp->b_bcount, obp->b_resid)); 944 DPRINTF(CGDB_IO, (" dev 0x%"PRIx64", nbp %p bn %" PRId64 945 " addr %p bcnt %d\n", nbp->b_dev, nbp, nbp->b_blkno, nbp->b_data, 946 nbp->b_bcount)); 947 if (nbp->b_error != 0) { 948 obp->b_error = nbp->b_error; 949 DPRINTF(CGDB_IO, ("%s: error %d\n", dksc->sc_xname, 950 obp->b_error)); 951 } 952 953 /* Perform the decryption if we are reading. 954 * 955 * Note: use the blocknumber from nbp, since it is what 956 * we used to encrypt the blocks. 957 */ 958 959 if (nbp->b_flags & B_READ) { 960 bn = dbtob(nbp->b_blkno) / dg->dg_secsize; 961 962 cx->cx_obp = obp; 963 cx->cx_nbp = nbp; 964 cx->cx_dstv = obp->b_data; 965 cx->cx_srcv = obp->b_data; 966 cx->cx_len = obp->b_bcount; 967 cx->cx_blkno = bn; 968 cx->cx_secsize = dg->dg_secsize; 969 cx->cx_dir = CGD_CIPHER_DECRYPT; 970 971 cgd_enqueue(sc, cx); 972 return; 973 } 974 975 cgd_iodone2(sc, cx); 976 } 977 978 static void 979 cgd_iodone2(struct cgd_softc *sc, struct cgd_xfer *cx) 980 { 981 struct cgd_worker *cw = sc->sc_worker; 982 struct buf *obp = cx->cx_obp; 983 struct buf *nbp = cx->cx_nbp; 984 struct dk_softc *dksc = &sc->sc_dksc; 985 986 pool_put(cw->cw_cpool, cx); 987 988 /* If we allocated memory, free it now... */ 989 if (nbp->b_data != obp->b_data) 990 cgd_putdata(sc, nbp->b_data, nbp->b_bcount); 991 992 putiobuf(nbp); 993 994 /* Request is complete for whatever reason */ 995 obp->b_resid = 0; 996 if (obp->b_error != 0) 997 obp->b_resid = obp->b_bcount; 998 999 dk_done(dksc, obp); 1000 dk_start(dksc, NULL); 1001 } 1002 1003 static int 1004 cgd_dumpblocks(device_t dev, void *va, daddr_t blkno, int nblk) 1005 { 1006 struct cgd_softc *sc = device_private(dev); 1007 struct dk_softc *dksc = &sc->sc_dksc; 1008 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom; 1009 size_t nbytes, blksize; 1010 void *buf; 1011 int error; 1012 1013 /* 1014 * dk_dump gives us units of disklabel sectors. Everything 1015 * else in cgd uses units of diskgeom sectors. These had 1016 * better agree; otherwise we need to figure out how to convert 1017 * between them. 1018 */ 1019 KASSERTMSG((dg->dg_secsize == dksc->sc_dkdev.dk_label->d_secsize), 1020 "diskgeom secsize %"PRIu32" != disklabel secsize %"PRIu32, 1021 dg->dg_secsize, dksc->sc_dkdev.dk_label->d_secsize); 1022 blksize = dg->dg_secsize; 1023 1024 /* 1025 * Compute the number of bytes in this request, which dk_dump 1026 * has `helpfully' converted to a number of blocks for us. 1027 */ 1028 nbytes = nblk*blksize; 1029 1030 /* Try to acquire a buffer to store the ciphertext. */ 1031 buf = cgd_getdata(sc, nbytes); 1032 if (buf == NULL) 1033 /* Out of memory: give up. */ 1034 return ENOMEM; 1035 1036 /* Encrypt the caller's data into the temporary buffer. */ 1037 cgd_cipher(sc, buf, va, nbytes, blkno, blksize, CGD_CIPHER_ENCRYPT); 1038 1039 /* Pass it on to the underlying disk device. */ 1040 error = bdev_dump(sc->sc_tdev, blkno, buf, nbytes); 1041 1042 /* Release the buffer. */ 1043 cgd_putdata(sc, buf, nbytes); 1044 1045 /* Return any error from the underlying disk device. */ 1046 return error; 1047 } 1048 1049 /* XXX: we should probably put these into dksubr.c, mostly */ 1050 static int 1051 cgdread(dev_t dev, struct uio *uio, int flags) 1052 { 1053 struct cgd_softc *sc; 1054 struct dk_softc *dksc; 1055 1056 DPRINTF_FOLLOW(("cgdread(0x%llx, %p, %d)\n", 1057 (unsigned long long)dev, uio, flags)); 1058 sc = getcgd_softc(dev); 1059 if (sc == NULL) 1060 return ENXIO; 1061 dksc = &sc->sc_dksc; 1062 if (!DK_ATTACHED(dksc)) 1063 return ENXIO; 1064 return physio(cgdstrategy, NULL, dev, B_READ, minphys, uio); 1065 } 1066 1067 /* XXX: we should probably put these into dksubr.c, mostly */ 1068 static int 1069 cgdwrite(dev_t dev, struct uio *uio, int flags) 1070 { 1071 struct cgd_softc *sc; 1072 struct dk_softc *dksc; 1073 1074 DPRINTF_FOLLOW(("cgdwrite(0x%"PRIx64", %p, %d)\n", dev, uio, flags)); 1075 sc = getcgd_softc(dev); 1076 if (sc == NULL) 1077 return ENXIO; 1078 dksc = &sc->sc_dksc; 1079 if (!DK_ATTACHED(dksc)) 1080 return ENXIO; 1081 return physio(cgdstrategy, NULL, dev, B_WRITE, minphys, uio); 1082 } 1083 1084 static int 1085 cgdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 1086 { 1087 struct cgd_softc *sc; 1088 struct dk_softc *dksc; 1089 int part = DISKPART(dev); 1090 int pmask = 1 << part; 1091 int error; 1092 1093 DPRINTF_FOLLOW(("cgdioctl(0x%"PRIx64", %ld, %p, %d, %p)\n", 1094 dev, cmd, data, flag, l)); 1095 1096 switch (cmd) { 1097 case CGDIOCGET: 1098 return cgd_ioctl_get(dev, data, l); 1099 case CGDIOCSET: 1100 case CGDIOCCLR: 1101 if ((flag & FWRITE) == 0) 1102 return EBADF; 1103 /* FALLTHROUGH */ 1104 default: 1105 sc = getcgd_softc(dev); 1106 if (sc == NULL) 1107 return ENXIO; 1108 dksc = &sc->sc_dksc; 1109 break; 1110 } 1111 1112 switch (cmd) { 1113 case CGDIOCSET: 1114 cgd_busy(sc); 1115 if (DK_ATTACHED(dksc)) 1116 error = EBUSY; 1117 else 1118 error = cgd_ioctl_set(sc, data, l); 1119 cgd_unbusy(sc); 1120 break; 1121 case CGDIOCCLR: 1122 cgd_busy(sc); 1123 if (DK_BUSY(&sc->sc_dksc, pmask)) 1124 error = EBUSY; 1125 else 1126 error = cgd_ioctl_clr(sc, l); 1127 cgd_unbusy(sc); 1128 break; 1129 case DIOCGCACHE: 1130 case DIOCCACHESYNC: 1131 cgd_busy(sc); 1132 if (!DK_ATTACHED(dksc)) { 1133 cgd_unbusy(sc); 1134 error = ENOENT; 1135 break; 1136 } 1137 /* 1138 * We pass this call down to the underlying disk. 1139 */ 1140 error = VOP_IOCTL(sc->sc_tvn, cmd, data, flag, l->l_cred); 1141 cgd_unbusy(sc); 1142 break; 1143 case DIOCGSECTORALIGN: { 1144 struct disk_sectoralign *dsa = data; 1145 1146 cgd_busy(sc); 1147 if (!DK_ATTACHED(dksc)) { 1148 cgd_unbusy(sc); 1149 error = ENOENT; 1150 break; 1151 } 1152 1153 /* Get the underlying disk's sector alignment. */ 1154 error = VOP_IOCTL(sc->sc_tvn, cmd, data, flag, l->l_cred); 1155 if (error) { 1156 cgd_unbusy(sc); 1157 break; 1158 } 1159 1160 /* Adjust for the disklabel partition if necessary. */ 1161 if (part != RAW_PART) { 1162 struct disklabel *lp = dksc->sc_dkdev.dk_label; 1163 daddr_t offset = lp->d_partitions[part].p_offset; 1164 uint32_t r = offset % dsa->dsa_alignment; 1165 1166 if (r < dsa->dsa_firstaligned) 1167 dsa->dsa_firstaligned = dsa->dsa_firstaligned 1168 - r; 1169 else 1170 dsa->dsa_firstaligned = (dsa->dsa_firstaligned 1171 + dsa->dsa_alignment) - r; 1172 } 1173 cgd_unbusy(sc); 1174 break; 1175 } 1176 case DIOCGSTRATEGY: 1177 case DIOCSSTRATEGY: 1178 if (!DK_ATTACHED(dksc)) { 1179 error = ENOENT; 1180 break; 1181 } 1182 /*FALLTHROUGH*/ 1183 default: 1184 error = dk_ioctl(dksc, dev, cmd, data, flag, l); 1185 break; 1186 case CGDIOCGET: 1187 KASSERT(0); 1188 error = EINVAL; 1189 } 1190 1191 return error; 1192 } 1193 1194 static int 1195 cgddump(dev_t dev, daddr_t blkno, void *va, size_t size) 1196 { 1197 struct cgd_softc *sc; 1198 1199 DPRINTF_FOLLOW(("cgddump(0x%"PRIx64", %" PRId64 ", %p, %lu)\n", 1200 dev, blkno, va, (unsigned long)size)); 1201 sc = getcgd_softc(dev); 1202 if (sc == NULL) 1203 return ENXIO; 1204 return dk_dump(&sc->sc_dksc, dev, blkno, va, size, DK_DUMP_RECURSIVE); 1205 } 1206 1207 /* 1208 * XXXrcd: 1209 * for now we hardcode the maximum key length. 1210 */ 1211 #define MAX_KEYSIZE 1024 1212 1213 static const struct { 1214 const char *n; 1215 int v; 1216 int d; 1217 } encblkno[] = { 1218 { "encblkno", CGD_CIPHER_CBC_ENCBLKNO8, 1 }, 1219 { "encblkno8", CGD_CIPHER_CBC_ENCBLKNO8, 1 }, 1220 { "encblkno1", CGD_CIPHER_CBC_ENCBLKNO1, 8 }, 1221 }; 1222 1223 /* ARGSUSED */ 1224 static int 1225 cgd_ioctl_set(struct cgd_softc *sc, void *data, struct lwp *l) 1226 { 1227 struct cgd_ioctl *ci = data; 1228 struct vnode *vp; 1229 int ret; 1230 size_t i; 1231 size_t keybytes; /* key length in bytes */ 1232 const char *cp; 1233 struct pathbuf *pb; 1234 char *inbuf; 1235 struct dk_softc *dksc = &sc->sc_dksc; 1236 1237 cp = ci->ci_disk; 1238 1239 ret = pathbuf_copyin(ci->ci_disk, &pb); 1240 if (ret != 0) { 1241 return ret; 1242 } 1243 ret = vn_bdev_openpath(pb, &vp, l); 1244 pathbuf_destroy(pb); 1245 if (ret != 0) { 1246 return ret; 1247 } 1248 1249 inbuf = kmem_alloc(MAX_KEYSIZE, KM_SLEEP); 1250 1251 if ((ret = cgdinit(sc, cp, vp, l)) != 0) 1252 goto bail; 1253 1254 (void)memset(inbuf, 0, MAX_KEYSIZE); 1255 ret = copyinstr(ci->ci_alg, inbuf, 256, NULL); 1256 if (ret) 1257 goto bail; 1258 sc->sc_cfuncs = cryptfuncs_find(inbuf); 1259 if (!sc->sc_cfuncs) { 1260 ret = EINVAL; 1261 goto bail; 1262 } 1263 1264 (void)memset(inbuf, 0, MAX_KEYSIZE); 1265 ret = copyinstr(ci->ci_ivmethod, inbuf, MAX_KEYSIZE, NULL); 1266 if (ret) 1267 goto bail; 1268 1269 for (i = 0; i < __arraycount(encblkno); i++) 1270 if (strcmp(encblkno[i].n, inbuf) == 0) 1271 break; 1272 1273 if (i == __arraycount(encblkno)) { 1274 ret = EINVAL; 1275 goto bail; 1276 } 1277 1278 keybytes = ci->ci_keylen / 8 + 1; 1279 if (keybytes > MAX_KEYSIZE) { 1280 ret = EINVAL; 1281 goto bail; 1282 } 1283 1284 (void)memset(inbuf, 0, MAX_KEYSIZE); 1285 ret = copyin(ci->ci_key, inbuf, keybytes); 1286 if (ret) 1287 goto bail; 1288 1289 sc->sc_cdata.cf_blocksize = ci->ci_blocksize; 1290 sc->sc_cdata.cf_mode = encblkno[i].v; 1291 1292 /* 1293 * Print a warning if the user selected the legacy encblkno8 1294 * mistake, and reject it altogether for ciphers that it 1295 * doesn't apply to. 1296 */ 1297 if (encblkno[i].v != CGD_CIPHER_CBC_ENCBLKNO1) { 1298 if (strcmp(sc->sc_cfuncs->cf_name, "aes-cbc") && 1299 strcmp(sc->sc_cfuncs->cf_name, "3des-cbc") && 1300 strcmp(sc->sc_cfuncs->cf_name, "blowfish-cbc")) { 1301 log(LOG_WARNING, "cgd: %s only makes sense for cbc," 1302 " not for %s; ignoring\n", 1303 encblkno[i].n, sc->sc_cfuncs->cf_name); 1304 sc->sc_cdata.cf_mode = CGD_CIPHER_CBC_ENCBLKNO1; 1305 } else { 1306 log(LOG_WARNING, "cgd: enabling legacy encblkno8\n"); 1307 } 1308 } 1309 1310 sc->sc_cdata.cf_keylen = ci->ci_keylen; 1311 sc->sc_cdata.cf_priv = sc->sc_cfuncs->cf_init(ci->ci_keylen, inbuf, 1312 &sc->sc_cdata.cf_blocksize); 1313 if (sc->sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE) { 1314 log(LOG_WARNING, "cgd: Disallowed cipher with blocksize %zu > %u\n", 1315 sc->sc_cdata.cf_blocksize, CGD_MAXBLOCKSIZE); 1316 sc->sc_cdata.cf_priv = NULL; 1317 } 1318 1319 /* 1320 * The blocksize is supposed to be in bytes. Unfortunately originally 1321 * it was expressed in bits. For compatibility we maintain encblkno 1322 * and encblkno8. 1323 */ 1324 sc->sc_cdata.cf_blocksize /= encblkno[i].d; 1325 (void)explicit_memset(inbuf, 0, MAX_KEYSIZE); 1326 if (!sc->sc_cdata.cf_priv) { 1327 ret = EINVAL; /* XXX is this the right error? */ 1328 goto bail; 1329 } 1330 kmem_free(inbuf, MAX_KEYSIZE); 1331 1332 bufq_alloc(&dksc->sc_bufq, "fcfs", 0); 1333 1334 sc->sc_data = kmem_alloc(MAXPHYS, KM_SLEEP); 1335 sc->sc_data_used = false; 1336 1337 /* Attach the disk. */ 1338 dk_attach(dksc); 1339 disk_attach(&dksc->sc_dkdev); 1340 1341 disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL); 1342 1343 /* Discover wedges on this disk. */ 1344 dkwedge_discover(&dksc->sc_dkdev); 1345 1346 return 0; 1347 1348 bail: 1349 kmem_free(inbuf, MAX_KEYSIZE); 1350 (void)vn_close(vp, FREAD|FWRITE, l->l_cred); 1351 return ret; 1352 } 1353 1354 /* ARGSUSED */ 1355 static int 1356 cgd_ioctl_clr(struct cgd_softc *sc, struct lwp *l) 1357 { 1358 struct dk_softc *dksc = &sc->sc_dksc; 1359 1360 if (!DK_ATTACHED(dksc)) 1361 return ENXIO; 1362 1363 /* Delete all of our wedges. */ 1364 dkwedge_delall(&dksc->sc_dkdev); 1365 1366 /* Kill off any queued buffers. */ 1367 dk_drain(dksc); 1368 bufq_free(dksc->sc_bufq); 1369 1370 (void)vn_close(sc->sc_tvn, FREAD|FWRITE, l->l_cred); 1371 sc->sc_cfuncs->cf_destroy(sc->sc_cdata.cf_priv); 1372 kmem_free(sc->sc_tpath, sc->sc_tpathlen); 1373 kmem_free(sc->sc_data, MAXPHYS); 1374 sc->sc_data_used = false; 1375 dk_detach(dksc); 1376 disk_detach(&dksc->sc_dkdev); 1377 1378 return 0; 1379 } 1380 1381 static int 1382 cgd_ioctl_get(dev_t dev, void *data, struct lwp *l) 1383 { 1384 struct cgd_softc *sc; 1385 struct cgd_user *cgu; 1386 int unit, error; 1387 1388 unit = CGDUNIT(dev); 1389 cgu = (struct cgd_user *)data; 1390 1391 DPRINTF_FOLLOW(("cgd_ioctl_get(0x%"PRIx64", %d, %p, %p)\n", 1392 dev, unit, data, l)); 1393 1394 /* XXX, we always return this units data, so if cgu_unit is 1395 * not -1, that field doesn't match the rest 1396 */ 1397 if (cgu->cgu_unit == -1) 1398 cgu->cgu_unit = unit; 1399 1400 if (cgu->cgu_unit < 0) 1401 return EINVAL; /* XXX: should this be ENXIO? */ 1402 1403 error = cgd_lock(false); 1404 if (error) 1405 return error; 1406 1407 sc = device_lookup_private(&cgd_cd, unit); 1408 if (sc == NULL || !DK_ATTACHED(&sc->sc_dksc)) { 1409 cgu->cgu_dev = 0; 1410 cgu->cgu_alg[0] = '\0'; 1411 cgu->cgu_blocksize = 0; 1412 cgu->cgu_mode = 0; 1413 cgu->cgu_keylen = 0; 1414 } 1415 else { 1416 mutex_enter(&sc->sc_lock); 1417 cgu->cgu_dev = sc->sc_tdev; 1418 strncpy(cgu->cgu_alg, sc->sc_cfuncs->cf_name, 1419 sizeof(cgu->cgu_alg)); 1420 cgu->cgu_blocksize = sc->sc_cdata.cf_blocksize; 1421 cgu->cgu_mode = sc->sc_cdata.cf_mode; 1422 cgu->cgu_keylen = sc->sc_cdata.cf_keylen; 1423 mutex_exit(&sc->sc_lock); 1424 } 1425 1426 cgd_unlock(); 1427 return 0; 1428 } 1429 1430 static int 1431 cgdinit(struct cgd_softc *sc, const char *cpath, struct vnode *vp, 1432 struct lwp *l) 1433 { 1434 struct disk_geom *dg; 1435 int ret; 1436 char *tmppath; 1437 uint64_t psize; 1438 unsigned secsize; 1439 struct dk_softc *dksc = &sc->sc_dksc; 1440 1441 sc->sc_tvn = vp; 1442 sc->sc_tpath = NULL; 1443 1444 tmppath = kmem_alloc(MAXPATHLEN, KM_SLEEP); 1445 ret = copyinstr(cpath, tmppath, MAXPATHLEN, &sc->sc_tpathlen); 1446 if (ret) 1447 goto bail; 1448 sc->sc_tpath = kmem_alloc(sc->sc_tpathlen, KM_SLEEP); 1449 memcpy(sc->sc_tpath, tmppath, sc->sc_tpathlen); 1450 1451 sc->sc_tdev = vp->v_rdev; 1452 1453 if ((ret = getdisksize(vp, &psize, &secsize)) != 0) 1454 goto bail; 1455 1456 if (psize == 0) { 1457 ret = ENODEV; 1458 goto bail; 1459 } 1460 1461 /* 1462 * XXX here we should probe the underlying device. If we 1463 * are accessing a partition of type RAW_PART, then 1464 * we should populate our initial geometry with the 1465 * geometry that we discover from the device. 1466 */ 1467 dg = &dksc->sc_dkdev.dk_geom; 1468 memset(dg, 0, sizeof(*dg)); 1469 dg->dg_secperunit = psize; 1470 dg->dg_secsize = secsize; 1471 dg->dg_ntracks = 1; 1472 dg->dg_nsectors = 1024 * 1024 / dg->dg_secsize; 1473 dg->dg_ncylinders = dg->dg_secperunit / dg->dg_nsectors; 1474 1475 bail: 1476 kmem_free(tmppath, MAXPATHLEN); 1477 if (ret && sc->sc_tpath) 1478 kmem_free(sc->sc_tpath, sc->sc_tpathlen); 1479 return ret; 1480 } 1481 1482 /* 1483 * Our generic cipher entry point. This takes care of the 1484 * IV mode and passes off the work to the specific cipher. 1485 * We implement here the IV method ``encrypted block 1486 * number''. 1487 * 1488 * XXXrcd: for now we rely on our own crypto framework defined 1489 * in dev/cgd_crypto.c. This will change when we 1490 * get a generic kernel crypto framework. 1491 */ 1492 1493 static void 1494 blkno2blkno_buf(char *sbuf, daddr_t blkno) 1495 { 1496 int i; 1497 1498 /* Set up the blkno in blkno_buf, here we do not care much 1499 * about the final layout of the information as long as we 1500 * can guarantee that each sector will have a different IV 1501 * and that the endianness of the machine will not affect 1502 * the representation that we have chosen. 1503 * 1504 * We choose this representation, because it does not rely 1505 * on the size of buf (which is the blocksize of the cipher), 1506 * but allows daddr_t to grow without breaking existing 1507 * disks. 1508 * 1509 * Note that blkno2blkno_buf does not take a size as input, 1510 * and hence must be called on a pre-zeroed buffer of length 1511 * greater than or equal to sizeof(daddr_t). 1512 */ 1513 for (i=0; i < sizeof(daddr_t); i++) { 1514 *sbuf++ = blkno & 0xff; 1515 blkno >>= 8; 1516 } 1517 } 1518 1519 static struct cpu_info * 1520 cgd_cpu(struct cgd_softc *sc) 1521 { 1522 struct cgd_worker *cw = sc->sc_worker; 1523 struct cpu_info *ci = NULL; 1524 u_int cidx, i; 1525 1526 if (cw->cw_busy == 0) { 1527 cw->cw_last = cpu_index(curcpu()); 1528 return NULL; 1529 } 1530 1531 for (i=0, cidx = cw->cw_last+1; i<maxcpus; ++i, ++cidx) { 1532 if (cidx >= maxcpus) 1533 cidx = 0; 1534 ci = cpu_lookup(cidx); 1535 if (ci) { 1536 cw->cw_last = cidx; 1537 break; 1538 } 1539 } 1540 1541 return ci; 1542 } 1543 1544 static void 1545 cgd_enqueue(struct cgd_softc *sc, struct cgd_xfer *cx) 1546 { 1547 struct cgd_worker *cw = sc->sc_worker; 1548 struct cpu_info *ci; 1549 1550 mutex_enter(&cw->cw_lock); 1551 ci = cgd_cpu(sc); 1552 cw->cw_busy++; 1553 mutex_exit(&cw->cw_lock); 1554 1555 workqueue_enqueue(cw->cw_wq, &cx->cx_work, ci); 1556 } 1557 1558 static void 1559 cgd_process(struct work *wk, void *arg) 1560 { 1561 struct cgd_xfer *cx = (struct cgd_xfer *)wk; 1562 struct cgd_softc *sc = cx->cx_sc; 1563 struct cgd_worker *cw = sc->sc_worker; 1564 1565 cgd_cipher(sc, cx->cx_dstv, cx->cx_srcv, cx->cx_len, 1566 cx->cx_blkno, cx->cx_secsize, cx->cx_dir); 1567 1568 if (cx->cx_dir == CGD_CIPHER_ENCRYPT) { 1569 cgd_diskstart2(sc, cx); 1570 } else { 1571 cgd_iodone2(sc, cx); 1572 } 1573 1574 mutex_enter(&cw->cw_lock); 1575 if (cw->cw_busy > 0) 1576 cw->cw_busy--; 1577 mutex_exit(&cw->cw_lock); 1578 } 1579 1580 static void 1581 cgd_cipher(struct cgd_softc *sc, void *dstv, const void *srcv, 1582 size_t len, daddr_t blkno, size_t secsize, int dir) 1583 { 1584 char *dst = dstv; 1585 const char *src = srcv; 1586 cfunc_cipher *cipher = sc->sc_cfuncs->cf_cipher; 1587 size_t blocksize = sc->sc_cdata.cf_blocksize; 1588 size_t todo; 1589 char blkno_buf[CGD_MAXBLOCKSIZE] __aligned(CGD_BLOCKALIGN); 1590 1591 DPRINTF_FOLLOW(("cgd_cipher() dir=%d\n", dir)); 1592 1593 if (sc->sc_cdata.cf_mode == CGD_CIPHER_CBC_ENCBLKNO8) 1594 blocksize /= 8; 1595 1596 KASSERT(len % blocksize == 0); 1597 /* ensure that sizeof(daddr_t) <= blocksize (for encblkno IVing) */ 1598 KASSERT(sizeof(daddr_t) <= blocksize); 1599 KASSERT(blocksize <= CGD_MAXBLOCKSIZE); 1600 1601 for (; len > 0; len -= todo) { 1602 todo = MIN(len, secsize); 1603 1604 memset(blkno_buf, 0x0, blocksize); 1605 blkno2blkno_buf(blkno_buf, blkno); 1606 IFDEBUG(CGDB_CRYPTO, hexprint("step 1: blkno_buf", 1607 blkno_buf, blocksize)); 1608 1609 /* 1610 * Handle bollocksed up encblkno8 mistake. We used to 1611 * compute the encryption of a zero block with blkno as 1612 * the CBC IV -- except in an early mistake arising 1613 * from bit/byte confusion, we actually computed the 1614 * encryption of the last of _eight_ zero blocks under 1615 * CBC as the CBC IV. 1616 * 1617 * Encrypting the block number is handled inside the 1618 * cipher dispatch now (even though in practice, both 1619 * CBC and XTS will do the same thing), so we have to 1620 * simulate the block number that would yield the same 1621 * result. So we encrypt _six_ zero blocks -- the 1622 * first one and the last one are handled inside the 1623 * cipher dispatch. 1624 */ 1625 if (sc->sc_cdata.cf_mode == CGD_CIPHER_CBC_ENCBLKNO8) { 1626 static const uint8_t zero[CGD_MAXBLOCKSIZE]; 1627 uint8_t iv[CGD_MAXBLOCKSIZE]; 1628 1629 memcpy(iv, blkno_buf, blocksize); 1630 cipher(sc->sc_cdata.cf_priv, blkno_buf, zero, 1631 6*blocksize, iv, CGD_CIPHER_ENCRYPT); 1632 memmove(blkno_buf, blkno_buf + 5*blocksize, blocksize); 1633 } 1634 1635 cipher(sc->sc_cdata.cf_priv, dst, src, todo, blkno_buf, dir); 1636 1637 dst += todo; 1638 src += todo; 1639 blkno++; 1640 } 1641 } 1642 1643 #ifdef DEBUG 1644 static void 1645 hexprint(const char *start, void *buf, int len) 1646 { 1647 char *c = buf; 1648 1649 KASSERTMSG(len >= 0, "hexprint: called with len < 0"); 1650 printf("%s: len=%06d 0x", start, len); 1651 while (len--) 1652 printf("%02x", (unsigned char) *c++); 1653 } 1654 #endif 1655 1656 static void 1657 cgd_selftest(void) 1658 { 1659 struct cgd_softc sc; 1660 void *buf; 1661 1662 for (size_t i = 0; i < __arraycount(selftests); i++) { 1663 const char *alg = selftests[i].alg; 1664 int encblkno8 = selftests[i].encblkno8; 1665 const uint8_t *key = selftests[i].key; 1666 int keylen = selftests[i].keylen; 1667 int txtlen = selftests[i].txtlen; 1668 1669 aprint_verbose("cgd: self-test %s-%d%s\n", alg, keylen, 1670 encblkno8 ? " (encblkno8)" : ""); 1671 1672 memset(&sc, 0, sizeof(sc)); 1673 1674 sc.sc_cfuncs = cryptfuncs_find(alg); 1675 if (sc.sc_cfuncs == NULL) 1676 panic("%s not implemented", alg); 1677 1678 sc.sc_cdata.cf_blocksize = 8 * selftests[i].blocksize; 1679 sc.sc_cdata.cf_mode = encblkno8 ? CGD_CIPHER_CBC_ENCBLKNO8 : 1680 CGD_CIPHER_CBC_ENCBLKNO1; 1681 sc.sc_cdata.cf_keylen = keylen; 1682 1683 sc.sc_cdata.cf_priv = sc.sc_cfuncs->cf_init(keylen, 1684 key, &sc.sc_cdata.cf_blocksize); 1685 if (sc.sc_cdata.cf_priv == NULL) 1686 panic("cf_priv is NULL"); 1687 if (sc.sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE) 1688 panic("bad block size %zu", sc.sc_cdata.cf_blocksize); 1689 1690 if (!encblkno8) 1691 sc.sc_cdata.cf_blocksize /= 8; 1692 1693 buf = kmem_alloc(txtlen, KM_SLEEP); 1694 memcpy(buf, selftests[i].ptxt, txtlen); 1695 1696 cgd_cipher(&sc, buf, buf, txtlen, selftests[i].blkno, 1697 selftests[i].secsize, CGD_CIPHER_ENCRYPT); 1698 if (memcmp(buf, selftests[i].ctxt, txtlen) != 0) { 1699 hexdump(printf, "was", buf, txtlen); 1700 hexdump(printf, "exp", selftests[i].ctxt, txtlen); 1701 panic("cgd %s-%d encryption is broken [%zu]", 1702 selftests[i].alg, keylen, i); 1703 } 1704 1705 cgd_cipher(&sc, buf, buf, txtlen, selftests[i].blkno, 1706 selftests[i].secsize, CGD_CIPHER_DECRYPT); 1707 if (memcmp(buf, selftests[i].ptxt, txtlen) != 0) { 1708 hexdump(printf, "was", buf, txtlen); 1709 hexdump(printf, "exp", selftests[i].ptxt, txtlen); 1710 panic("cgd %s-%d decryption is broken [%zu]", 1711 selftests[i].alg, keylen, i); 1712 } 1713 1714 kmem_free(buf, txtlen); 1715 sc.sc_cfuncs->cf_destroy(sc.sc_cdata.cf_priv); 1716 } 1717 1718 aprint_verbose("cgd: self-tests passed\n"); 1719 } 1720 1721 MODULE(MODULE_CLASS_DRIVER, cgd, "blowfish,des,dk_subr,bufq_fcfs"); 1722 1723 #ifdef _MODULE 1724 CFDRIVER_DECL(cgd, DV_DISK, NULL); 1725 1726 devmajor_t cgd_bmajor = -1, cgd_cmajor = -1; 1727 #endif 1728 1729 static int 1730 cgd_modcmd(modcmd_t cmd, void *arg) 1731 { 1732 int error = 0; 1733 1734 switch (cmd) { 1735 case MODULE_CMD_INIT: 1736 #ifdef _MODULE 1737 mutex_init(&cgd_spawning_mtx, MUTEX_DEFAULT, IPL_NONE); 1738 cv_init(&cgd_spawning_cv, "cgspwn"); 1739 1740 error = config_cfdriver_attach(&cgd_cd); 1741 if (error) 1742 break; 1743 1744 error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca); 1745 if (error) { 1746 config_cfdriver_detach(&cgd_cd); 1747 aprint_error("%s: unable to register cfattach for" 1748 "%s, error %d\n", __func__, cgd_cd.cd_name, error); 1749 break; 1750 } 1751 /* 1752 * Attach the {b,c}devsw's 1753 */ 1754 error = devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor, 1755 &cgd_cdevsw, &cgd_cmajor); 1756 1757 /* 1758 * If devsw_attach fails, remove from autoconf database 1759 */ 1760 if (error) { 1761 config_cfattach_detach(cgd_cd.cd_name, &cgd_ca); 1762 config_cfdriver_detach(&cgd_cd); 1763 aprint_error("%s: unable to attach %s devsw, " 1764 "error %d", __func__, cgd_cd.cd_name, error); 1765 break; 1766 } 1767 #endif 1768 break; 1769 1770 case MODULE_CMD_FINI: 1771 #ifdef _MODULE 1772 /* 1773 * Remove {b,c}devsw's 1774 */ 1775 devsw_detach(&cgd_bdevsw, &cgd_cdevsw); 1776 1777 /* 1778 * Now remove device from autoconf database 1779 */ 1780 error = config_cfattach_detach(cgd_cd.cd_name, &cgd_ca); 1781 if (error) { 1782 (void)devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor, 1783 &cgd_cdevsw, &cgd_cmajor); 1784 aprint_error("%s: failed to detach %s cfattach, " 1785 "error %d\n", __func__, cgd_cd.cd_name, error); 1786 break; 1787 } 1788 error = config_cfdriver_detach(&cgd_cd); 1789 if (error) { 1790 (void)config_cfattach_attach(cgd_cd.cd_name, &cgd_ca); 1791 (void)devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor, 1792 &cgd_cdevsw, &cgd_cmajor); 1793 aprint_error("%s: failed to detach %s cfdriver, " 1794 "error %d\n", __func__, cgd_cd.cd_name, error); 1795 break; 1796 } 1797 1798 cv_destroy(&cgd_spawning_cv); 1799 mutex_destroy(&cgd_spawning_mtx); 1800 #endif 1801 break; 1802 1803 case MODULE_CMD_STAT: 1804 error = ENOTTY; 1805 break; 1806 default: 1807 error = ENOTTY; 1808 break; 1809 } 1810 1811 return error; 1812 } 1813