xref: /freebsd/sys/kern/subr_module.c (revision 6ba9413b55aefe0b03d4af6a2a27a4f222c17a8d)
16ba9413bSMike Smith /*-
26ba9413bSMike Smith  * Copyright (c) 1998 Michael Smith
36ba9413bSMike Smith  * All rights reserved.
46ba9413bSMike Smith  *
56ba9413bSMike Smith  * Redistribution and use in source and binary forms, with or without
66ba9413bSMike Smith  * modification, are permitted provided that the following conditions
76ba9413bSMike Smith  * are met:
86ba9413bSMike Smith  * 1. Redistributions of source code must retain the above copyright
96ba9413bSMike Smith  *    notice, this list of conditions and the following disclaimer.
106ba9413bSMike Smith  * 2. Redistributions in binary form must reproduce the above copyright
116ba9413bSMike Smith  *    notice, this list of conditions and the following disclaimer in the
126ba9413bSMike Smith  *    documentation and/or other materials provided with the distribution.
136ba9413bSMike Smith  *
146ba9413bSMike Smith  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
156ba9413bSMike Smith  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
166ba9413bSMike Smith  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
176ba9413bSMike Smith  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
186ba9413bSMike Smith  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
196ba9413bSMike Smith  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
206ba9413bSMike Smith  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
216ba9413bSMike Smith  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
226ba9413bSMike Smith  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
236ba9413bSMike Smith  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
246ba9413bSMike Smith  * SUCH DAMAGE.
256ba9413bSMike Smith  *
266ba9413bSMike Smith  *	$Id$
276ba9413bSMike Smith  */
286ba9413bSMike Smith 
296ba9413bSMike Smith #include <sys/param.h>
306ba9413bSMike Smith #include <sys/kernel.h>
316ba9413bSMike Smith #include <sys/systm.h>
326ba9413bSMike Smith #include <sys/linker.h>
336ba9413bSMike Smith 
346ba9413bSMike Smith /*
356ba9413bSMike Smith  * Preloaded module support
366ba9413bSMike Smith  */
376ba9413bSMike Smith 
386ba9413bSMike Smith caddr_t	module_metadata;
396ba9413bSMike Smith 
406ba9413bSMike Smith /*
416ba9413bSMike Smith  * Search for the preloaded module (name)
426ba9413bSMike Smith  */
436ba9413bSMike Smith caddr_t
446ba9413bSMike Smith module_search_by_name(const char *name)
456ba9413bSMike Smith {
466ba9413bSMike Smith     caddr_t	curp;
476ba9413bSMike Smith     u_int32_t	*hdr;
486ba9413bSMike Smith 
496ba9413bSMike Smith     if (module_metadata != NULL) {
506ba9413bSMike Smith 
516ba9413bSMike Smith 	curp = module_metadata;
526ba9413bSMike Smith 	for (;;) {
536ba9413bSMike Smith 	    hdr = (u_int32_t *)curp;
546ba9413bSMike Smith 	    if (hdr[0] == 0)
556ba9413bSMike Smith 		break;
566ba9413bSMike Smith 
576ba9413bSMike Smith 	    /* Search for a MODINFO_NAME field */
586ba9413bSMike Smith 	    if ((hdr[0] == MODINFO_NAME) &&
596ba9413bSMike Smith 		!strcmp(name, curp + sizeof(u_int32_t) * 2))
606ba9413bSMike Smith 		return(curp);
616ba9413bSMike Smith 
626ba9413bSMike Smith 	    /* skip to next field */
636ba9413bSMike Smith 	    curp += sizeof(u_int32_t) * 2 + hdr[1];
646ba9413bSMike Smith 	}
656ba9413bSMike Smith     }
666ba9413bSMike Smith     return(NULL);
676ba9413bSMike Smith }
686ba9413bSMike Smith 
696ba9413bSMike Smith /*
706ba9413bSMike Smith  * Search for the first preloaded module of (type)
716ba9413bSMike Smith  */
726ba9413bSMike Smith caddr_t
736ba9413bSMike Smith module_search_by_type(const char *type)
746ba9413bSMike Smith {
756ba9413bSMike Smith     caddr_t	curp, lname;
766ba9413bSMike Smith     u_int32_t	*hdr;
776ba9413bSMike Smith 
786ba9413bSMike Smith     if (module_metadata != NULL) {
796ba9413bSMike Smith 
806ba9413bSMike Smith 	curp = module_metadata;
816ba9413bSMike Smith 	lname = NULL;
826ba9413bSMike Smith 	for (;;) {
836ba9413bSMike Smith 	    hdr = (u_int32_t *)curp;
846ba9413bSMike Smith 	    if (hdr[0] == 0)
856ba9413bSMike Smith 		break;
866ba9413bSMike Smith 
876ba9413bSMike Smith 	    /* remember the start of each record */
886ba9413bSMike Smith 	    if (hdr[0] == MODINFO_NAME)
896ba9413bSMike Smith 		lname = curp;
906ba9413bSMike Smith 
916ba9413bSMike Smith 	    /* Search for a MODINFO_TYPE field */
926ba9413bSMike Smith 	    if ((hdr[0] == MODINFO_TYPE) &&
936ba9413bSMike Smith 		!strcmp(type, curp + sizeof(u_int32_t) * 2))
946ba9413bSMike Smith 		return(lname);
956ba9413bSMike Smith 
966ba9413bSMike Smith 	    /* skip to next field */
976ba9413bSMike Smith 	    curp += sizeof(u_int32_t) * 2 + hdr[1];
986ba9413bSMike Smith 	}
996ba9413bSMike Smith     }
1006ba9413bSMike Smith     return(NULL);
1016ba9413bSMike Smith }
1026ba9413bSMike Smith 
1036ba9413bSMike Smith /*
1046ba9413bSMike Smith  * Given a preloaded module handle (mod), return a pointer
1056ba9413bSMike Smith  * to the data for the attribute (inf).
1066ba9413bSMike Smith  */
1076ba9413bSMike Smith caddr_t
1086ba9413bSMike Smith module_search_info(caddr_t mod, int inf)
1096ba9413bSMike Smith {
1106ba9413bSMike Smith     caddr_t	curp;
1116ba9413bSMike Smith     u_int32_t	*hdr;
1126ba9413bSMike Smith     u_int32_t	type = 0;
1136ba9413bSMike Smith 
1146ba9413bSMike Smith     curp = mod;
1156ba9413bSMike Smith     for (;;) {
1166ba9413bSMike Smith 	hdr = (u_int32_t *)curp;
1176ba9413bSMike Smith 	/* end of module data? */
1186ba9413bSMike Smith 	if (hdr[0] == 0)
1196ba9413bSMike Smith 	    break;
1206ba9413bSMike Smith 	/*
1216ba9413bSMike Smith 	 * We give up once we've looped back to what we were looking at
1226ba9413bSMike Smith 	 * first - this should normally be a MODINFO_NAME field.
1236ba9413bSMike Smith 	 */
1246ba9413bSMike Smith 	if (type == 0) {
1256ba9413bSMike Smith 	    type = hdr[0];
1266ba9413bSMike Smith 	} else {
1276ba9413bSMike Smith 	    if (hdr[0] == type)
1286ba9413bSMike Smith 		break;
1296ba9413bSMike Smith 	}
1306ba9413bSMike Smith 
1316ba9413bSMike Smith 	/*
1326ba9413bSMike Smith 	 * Attribute match? Return pointer to data.
1336ba9413bSMike Smith 	 * Consumer may safely assume that size value preceeds
1346ba9413bSMike Smith 	 * data.
1356ba9413bSMike Smith 	 */
1366ba9413bSMike Smith 	if (hdr[0] == inf)
1376ba9413bSMike Smith 	    return(curp + (sizeof(u_int32_t) * 2));
1386ba9413bSMike Smith 
1396ba9413bSMike Smith 	/* skip to next field */
1406ba9413bSMike Smith 	curp += sizeof(u_int32_t) * 2 + hdr[1];
1416ba9413bSMike Smith     }
1426ba9413bSMike Smith     return(NULL);
1436ba9413bSMike Smith }
1446ba9413bSMike Smith 
145