xref: /titanic_53/usr/src/uts/common/io/bl.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * Blacklist special file
31*7c478bd9Sstevel@tonic-gate  */
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/conf.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/open.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/policy.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/fm/protocol.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/bl.h>
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate static dev_info_t *bl_dip;	/* private copy of devinfo pointer */
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate static int
48*7c478bd9Sstevel@tonic-gate bl_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
49*7c478bd9Sstevel@tonic-gate {
50*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
51*7c478bd9Sstevel@tonic-gate 	case DDI_ATTACH:
52*7c478bd9Sstevel@tonic-gate 		break;
53*7c478bd9Sstevel@tonic-gate 	case DDI_RESUME:
54*7c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
55*7c478bd9Sstevel@tonic-gate 	default:
56*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
57*7c478bd9Sstevel@tonic-gate 	}
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate 	if (ddi_create_minor_node(dip, ddi_get_name(dip), S_IFCHR,
60*7c478bd9Sstevel@tonic-gate 	    ddi_get_instance(dip), DDI_PSEUDO, 0) != DDI_SUCCESS)
61*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate 	bl_dip = dip;
64*7c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
65*7c478bd9Sstevel@tonic-gate }
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
68*7c478bd9Sstevel@tonic-gate static int
69*7c478bd9Sstevel@tonic-gate bl_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
70*7c478bd9Sstevel@tonic-gate {
71*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
72*7c478bd9Sstevel@tonic-gate 	case DDI_DETACH:
73*7c478bd9Sstevel@tonic-gate 		break;
74*7c478bd9Sstevel@tonic-gate 	case DDI_SUSPEND:
75*7c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
76*7c478bd9Sstevel@tonic-gate 	default:
77*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
78*7c478bd9Sstevel@tonic-gate 	}
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate 	ddi_remove_minor_node(bl_dip, NULL);
81*7c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
82*7c478bd9Sstevel@tonic-gate }
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
85*7c478bd9Sstevel@tonic-gate static int
86*7c478bd9Sstevel@tonic-gate bl_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
87*7c478bd9Sstevel@tonic-gate {
88*7c478bd9Sstevel@tonic-gate 	int rc = DDI_SUCCESS;
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate 	switch (infocmd) {
91*7c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2DEVINFO:
92*7c478bd9Sstevel@tonic-gate 		*result = bl_dip;
93*7c478bd9Sstevel@tonic-gate 		break;
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2INSTANCE:
96*7c478bd9Sstevel@tonic-gate 		*result = (void *)(uintptr_t)getminor((dev_t)arg);
97*7c478bd9Sstevel@tonic-gate 		break;
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate 	default:
100*7c478bd9Sstevel@tonic-gate 		*result = NULL;
101*7c478bd9Sstevel@tonic-gate 		rc = DDI_FAILURE;
102*7c478bd9Sstevel@tonic-gate 	}
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate 	return (rc);
105*7c478bd9Sstevel@tonic-gate }
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
108*7c478bd9Sstevel@tonic-gate static int
109*7c478bd9Sstevel@tonic-gate bl_open(dev_t *devp, int flag, int otyp, struct cred *credp)
110*7c478bd9Sstevel@tonic-gate {
111*7c478bd9Sstevel@tonic-gate 	if (otyp != OTYP_CHR)
112*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate 	if (secpolicy_blacklist(credp) != 0)
115*7c478bd9Sstevel@tonic-gate 		return (EPERM);
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate 	return (0);
118*7c478bd9Sstevel@tonic-gate }
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
121*7c478bd9Sstevel@tonic-gate static int
122*7c478bd9Sstevel@tonic-gate bl_ioctl(dev_t dev, int cmd, intptr_t data, int flag, cred_t *cred, int *rvalp)
123*7c478bd9Sstevel@tonic-gate {
124*7c478bd9Sstevel@tonic-gate 	bl_req_t blr;
125*7c478bd9Sstevel@tonic-gate 	nvlist_t *fmri;
126*7c478bd9Sstevel@tonic-gate 	const char *scheme;
127*7c478bd9Sstevel@tonic-gate 	char class[128];
128*7c478bd9Sstevel@tonic-gate 	char *buf;
129*7c478bd9Sstevel@tonic-gate 	int err;
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32
132*7c478bd9Sstevel@tonic-gate 	if (get_udatamodel() != DATAMODEL_NATIVE) {
133*7c478bd9Sstevel@tonic-gate 		bl_req32_t blr32;
134*7c478bd9Sstevel@tonic-gate 
135*7c478bd9Sstevel@tonic-gate 		if (copyin((void *)data, &blr32, sizeof (bl_req32_t)) != 0)
136*7c478bd9Sstevel@tonic-gate 			return (EFAULT);
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate 		blr.bl_fmri = (caddr_t)(uintptr_t)blr32.bl_fmri;
139*7c478bd9Sstevel@tonic-gate 		blr.bl_fmrisz = blr32.bl_fmrisz;
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate 		blr.bl_class = (caddr_t)(uintptr_t)blr32.bl_class;
142*7c478bd9Sstevel@tonic-gate 	} else
143*7c478bd9Sstevel@tonic-gate #endif
144*7c478bd9Sstevel@tonic-gate 	{
145*7c478bd9Sstevel@tonic-gate 		if (copyin((void *)data, &blr, sizeof (bl_req_t)) != 0)
146*7c478bd9Sstevel@tonic-gate 			return (EFAULT);
147*7c478bd9Sstevel@tonic-gate 	}
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate 	if (blr.bl_fmri == NULL || blr.bl_fmrisz > BL_FMRI_MAX_BUFSIZE ||
150*7c478bd9Sstevel@tonic-gate 	    blr.bl_class == NULL)
151*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	if (copyinstr(blr.bl_class, class, sizeof (class), NULL) != 0)
154*7c478bd9Sstevel@tonic-gate 		return (EFAULT);
155*7c478bd9Sstevel@tonic-gate 
156*7c478bd9Sstevel@tonic-gate 	buf = kmem_zalloc(blr.bl_fmrisz, KM_SLEEP);
157*7c478bd9Sstevel@tonic-gate 	if (copyin(blr.bl_fmri, buf, blr.bl_fmrisz) != 0) {
158*7c478bd9Sstevel@tonic-gate 		kmem_free(buf, blr.bl_fmrisz);
159*7c478bd9Sstevel@tonic-gate 		return (EFAULT);
160*7c478bd9Sstevel@tonic-gate 	}
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate 	err = nvlist_unpack(buf, blr.bl_fmrisz, &fmri, KM_SLEEP);
163*7c478bd9Sstevel@tonic-gate 	kmem_free(buf, blr.bl_fmrisz);
164*7c478bd9Sstevel@tonic-gate 	if (err != 0)
165*7c478bd9Sstevel@tonic-gate 		return (err);
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate 	if (nvlist_lookup_string(fmri, FM_FMRI_SCHEME, (char **)&scheme) != 0) {
168*7c478bd9Sstevel@tonic-gate 		nvlist_free(fmri);
169*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
170*7c478bd9Sstevel@tonic-gate 	}
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
173*7c478bd9Sstevel@tonic-gate 	case BLIOC_INSERT:
174*7c478bd9Sstevel@tonic-gate 	case BLIOC_DELETE:
175*7c478bd9Sstevel@tonic-gate 		err = blacklist(cmd, scheme, fmri, class);
176*7c478bd9Sstevel@tonic-gate 		break;
177*7c478bd9Sstevel@tonic-gate 	default:
178*7c478bd9Sstevel@tonic-gate 		err = ENOTSUP;
179*7c478bd9Sstevel@tonic-gate 	}
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate 	nvlist_free(fmri);
182*7c478bd9Sstevel@tonic-gate 	return (err);
183*7c478bd9Sstevel@tonic-gate 
184*7c478bd9Sstevel@tonic-gate }
185*7c478bd9Sstevel@tonic-gate 
186*7c478bd9Sstevel@tonic-gate static struct cb_ops bl_cb_ops = {
187*7c478bd9Sstevel@tonic-gate 	bl_open,		/* open */
188*7c478bd9Sstevel@tonic-gate 	nulldev,		/* close */
189*7c478bd9Sstevel@tonic-gate 	nodev,			/* strategy */
190*7c478bd9Sstevel@tonic-gate 	nodev,			/* print */
191*7c478bd9Sstevel@tonic-gate 	nodev,			/* dump */
192*7c478bd9Sstevel@tonic-gate 	nodev,			/* read */
193*7c478bd9Sstevel@tonic-gate 	nodev,			/* write */
194*7c478bd9Sstevel@tonic-gate 	bl_ioctl,		/* ioctl */
195*7c478bd9Sstevel@tonic-gate 	nodev,			/* devmap */
196*7c478bd9Sstevel@tonic-gate 	nodev,			/* mmap */
197*7c478bd9Sstevel@tonic-gate 	nodev,			/* segmap */
198*7c478bd9Sstevel@tonic-gate 	nochpoll,		/* poll */
199*7c478bd9Sstevel@tonic-gate 	ddi_prop_op,		/* cb_prop_op */
200*7c478bd9Sstevel@tonic-gate 	0,			/* streamtab  */
201*7c478bd9Sstevel@tonic-gate 	D_NEW | D_MP | D_64BIT	/* Driver compatibility flag */
202*7c478bd9Sstevel@tonic-gate };
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate static struct dev_ops bl_ops = {
205*7c478bd9Sstevel@tonic-gate 	DEVO_REV,		/* devo_rev */
206*7c478bd9Sstevel@tonic-gate 	0,			/* devo_refcnt  */
207*7c478bd9Sstevel@tonic-gate 	bl_getinfo,		/* devo_getinfo */
208*7c478bd9Sstevel@tonic-gate 	nulldev,		/* devo_identify */
209*7c478bd9Sstevel@tonic-gate 	nulldev,		/* devo_probe */
210*7c478bd9Sstevel@tonic-gate 	bl_attach,		/* devo_attach */
211*7c478bd9Sstevel@tonic-gate 	bl_detach,		/* devo_detach */
212*7c478bd9Sstevel@tonic-gate 	nodev,			/* devo_reset */
213*7c478bd9Sstevel@tonic-gate 	&bl_cb_ops,		/* devo_cb_ops */
214*7c478bd9Sstevel@tonic-gate 	(struct bus_ops *)0,	/* devo_bus_ops */
215*7c478bd9Sstevel@tonic-gate 	NULL			/* devo_power */
216*7c478bd9Sstevel@tonic-gate };
217*7c478bd9Sstevel@tonic-gate 
218*7c478bd9Sstevel@tonic-gate static struct modldrv modldrv = {
219*7c478bd9Sstevel@tonic-gate 	&mod_driverops, "blacklist driver %I%", &bl_ops,
220*7c478bd9Sstevel@tonic-gate };
221*7c478bd9Sstevel@tonic-gate 
222*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
223*7c478bd9Sstevel@tonic-gate 	MODREV_1, &modldrv, NULL
224*7c478bd9Sstevel@tonic-gate };
225*7c478bd9Sstevel@tonic-gate 
226*7c478bd9Sstevel@tonic-gate int
227*7c478bd9Sstevel@tonic-gate _init(void)
228*7c478bd9Sstevel@tonic-gate {
229*7c478bd9Sstevel@tonic-gate 	return (mod_install(&modlinkage));
230*7c478bd9Sstevel@tonic-gate }
231*7c478bd9Sstevel@tonic-gate 
232*7c478bd9Sstevel@tonic-gate int
233*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
234*7c478bd9Sstevel@tonic-gate {
235*7c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
236*7c478bd9Sstevel@tonic-gate }
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate int
239*7c478bd9Sstevel@tonic-gate _fini(void)
240*7c478bd9Sstevel@tonic-gate {
241*7c478bd9Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
242*7c478bd9Sstevel@tonic-gate }
243