/**Copyright(c)1997,1998DougRabson*Allrightsreserved.**Redistributionanduseinsourceandbinaryforms,withorwithout*modification,arepermittedprovidedthatthefollowingconditions*aremet:*1.Redistributionsofsourcecodemustretaintheabovecopyright*notice,thislistofcondi
tionsandthefollowingdisclaimer.*2.Redistributionsinbinaryformmustreproducetheabovecopyright*notice,thislistofconditionsandthefollowingdisclaimerinthe*documentationand/orothermaterialsprovidedwiththedistribution.**THISSOFTWAREISPROVIDEDBYTHEAUTHORANDCONTRIBUTO
RS``ASIS''AND*ANYEXPRESSORIMPLIEDWARRANTIES,INCLUDING,BUTNOTLIMITEDTO,THE*IMPLIEDWARRANTIESOFMERCHANTABILITYANDFITNESSFORAPARTICULARPURPOSE*AREDISCLAIMED.INNOEVENTSHALLTHEAUTHORORCONTRIBUTORSBELIABLE*FORANYDIRECT,INDIRECT,INCIDENTAL,SPECIAL,EXEMPLARY,ORCONSEQ
UENTIAL*DAMAGES(INCLUDING,BUTNOTLIMITEDTO,PROCUREMENTOFSUBSTITUTEGOODS*ORSERVICES;LOSSOFUSE,DATA,ORPROFITS;ORBUSINESSINTERRUPTION)*HOWEVERCAUSEDANDONANYTHEORYOFLIABILITY,WHETHERINCONTRACT,STRICT*LIABILITY,ORTORT(INCLUDINGNEGLIGENCEOROTHERWISE)ARISINGINANYWAY*
OUTOFTHEUSEOFTHISSOFTWARE,EVENIFADVISEDOFTHEPOSSIBILITYOF*SUCHDAMAGE.**$FreeBSD:src/sys/kern/subr_bus.c,v1.54.2.82001/01/1800:19:50n_hibmaExp$*/#include"opt_bus.h"#include<sys/param.h>#include<sys/queue.h>#include<sys/malloc.h>#include<sys/kernel.h>#include<s
ys/module.h>#ifdefDEVICE_SYSCTLS#include<sys/sysctl.h>#endif#include<sys/bus_private.h>#include<sys/systm.h>#include<machine/bus.h>#include<sys/rman.h>#include<machine/stdarg.h>/*fordevice_printf()*/MALLOC_DEFINE(M_BUS,"bus","Busdatastructures");#ifdefBUS_DEB
UG#definePDEBUG(a)(printf(__FUNCTION__":%d:",__LINE__),printfa,printf("\n"))#defineDEVICENAME(d)((d)?device_get_name(d):"nodevice")#defineDRIVERNAME(d)((d)?d->name:"nodriver")#defineDEVCLANAME(d)((d)?d->name:"nodevclass")/*Producetheindenting,indent*2spacespl
usa'.'aheadofthatto*preventsyslogfromdeletinginitialspaces*/#defineindentprintf(p)do{intiJ;printf(".");for(iJ=0;iJ<indent;iJ++)printf("");printfp;}while(0)staticvoidprint_method_list(device_method_t*m,intindent);staticvoidprint_device_ops(device_ops_tops,inti
ndent);staticvoidprint_device_short(device_tdev,intindent);staticvoidprint_device(device_tdev,intindent);voidprint_device_tree_short(device_tdev,intindent);voidprint_device_tree(device_tdev,intindent);staticvoidprint_driver_short(driver_t*driver,intindent);st
aticvoidprint_driver(driver_t*driver,intindent);staticvoidprint_driver_list(driver_list_tdrivers,intindent);staticvoidprint_devclass_short(devclass_tdc,intindent);staticvoidprint_devclass(devclass_tdc,intindent);voidprint_devclass_list_short(void);voidprint_d
evclass_list(void);#else/*Makethecompilerignorethefunctioncalls*/#definePDEBUG(a)/*nop*/#defineDEVICENAME(d)/*nop*/#defineDRIVERNAME(d)/*nop*/#defineDEVCLANAME(d)/*nop*/#defineprint_method_list(m,i)/*nop*/#defineprint_device_ops(o,i)/*nop*/#defineprint_device
_short(d,i)/*nop*/#defineprint_device(d,i)/*nop*/#defineprint_device_tree_short(d,i)/*nop*/#defineprint_device_tree(d,i)/*nop*/#defineprint_driver_short(d,i)/*nop*/#defineprint_driver(d,i)/*nop*/#defineprint_driver_list(d,i)/*nop*/#defineprint_devclass_short(
d,i)/*nop*/#defineprint_devclass(d,i)/*nop*/#defineprint_devclass_list_short()/*nop*/#defineprint_devclass_list()/*nop*/#endif#ifdefDEVICE_SYSCTLSstaticvoiddevice_register_oids(device_tdev);staticvoiddevice_unregister_oids(device_tdev);#endif/**Methodtablehan
dling*/staticinterror_method(void);staticintnext_method_offset=1;LIST_HEAD(methodlist,method)methods;structmethod{LIST_ENTRY(method)link;/*linkedlistofmethods*/intoffset;/*offsetinmethodtable*/intrefs;/*countofdevice_op_descusers*/devop_tdeflt;/*defaultimplem
entation*/char*name;/*uniquenameofmethod*/};staticvoidregister_method(structdevice_op_desc*desc){structmethod*m;if(desc->method){desc->method->refs++;return;}/**Makesurethatdesc->defltisalwaysvalidtosimplifydispatch.*/if(!desc->deflt)desc->deflt=error_method;
for(m=LIST_FIRST(&methods);m;m=LIST_NEXT(m,link)){if(!strcmp(m->name,desc->name)){desc->offset=m->offset;desc->method=m;m->refs++;PDEBUG(("method%phasthesamename,%s,withoffset%d",(void*)m,desc->name,desc->offset));return;}}m=(structmethod*)malloc(sizeof(struc
tmethod)+strlen(desc->name)+1,M_BUS,M_NOWAIT);if(!m)panic("register_method:outofmemory");bzero(m,sizeof(structmethod)+strlen(desc->name)+1);m->offset=next_method_offset++;m->refs=1;m->deflt=desc->deflt;m->name=(char*)(m+1);strcpy(m->name,desc->name);LIST_INSE
RT_HEAD(&methods,m,link);desc->offset=m->offset;desc->method=m;}staticvoidunregister_method(structdevice_op_desc*desc){structmethod*m=desc->method;m->refs--;if(m->refs==0){PDEBUG(("method%s,reachedrefcount0",desc->name));LIST_REMOVE(m,link);free(m,M_BUS);desc
->method=0;}}staticinterror_method(void){returnENXIO;}staticstructdevice_opsnull_ops={1,{error_method}};staticvoidcompile_methods(driver_t*driver){device_ops_tops;structdevice_method*m;structmethod*cm;inti;/**Firstregisteranymethodswhichneedit.*/for(i=0,m=dri
ver->methods;m->desc;i++,m++)register_method(m->desc);/**Thenallocatethecompiledoptable.*/ops=malloc(sizeof(structdevice_ops)+(next_method_offset-1)*sizeof(devop_t),M_BUS,M_NOWAIT);if(!ops)panic("compile_methods:outofmemory");bzero(ops,sizeof(structdevice_ops
)+(next_method_offset-1)*sizeof(devop_t));ops->maxoffset=next_method_offset;/*Fillindefaultmethodsandthenoverwritewithdrivermethods*/for(i=0;i<next_method_offset;i++)ops->methods[i]=error_method;for(cm=LIST_FIRST(&methods);cm;cm=LIST_NEXT(cm,link)){if(cm->def
lt)ops->methods[cm->offset]=cm->deflt;}for(i=0,m=driver->methods;m->desc;i++,m++)ops->methods[m->desc->offset]=m->func;PDEBUG(("%shas%dmethod%s,wasting%dbytes",DRIVERNAME(driver),i,(i==1?"":"s"),(next_method_offset-i)*sizeof(devop_t)));driver->ops=ops;}static
voidfree_methods(driver_t*driver){inti;structdevice_method*m;/**Unregisteranymethodswhicharenolongerused.*/for(i=0,m=driver->methods;m->desc;i++,m++)unregister_method(m->desc);/**Freememoryandcleanup.*/free(driver->ops,M_BUS);driver->ops=0;}/**Devclassimpleme
ntation*/staticdevclass_list_tdevclasses=TAILQ_HEAD_INITIALIZER(devclasses);staticdevclass_tdevclass_find_internal(constchar*classname,intcreate){devclass_tdc;PDEBUG(("lookingfor%s",classname));if(!classname)returnNULL;for(dc=TAILQ_FIRST(&devclasses);dc;dc=TA
ILQ_NEXT(dc,link))if(!strcmp(dc->name,classname))returndc;PDEBUG(("%snotfound%s",classname,(create?",creating":"")));if(create){dc=malloc(sizeof(structdevclass)+strlen(classname)+1,M_BUS,M_NOWAIT);if(!dc)returnNULL;bzero(dc,sizeof(structdevclass)+strlen(class
name)+1);dc->name=(char*)(dc+1);strcpy(dc->name,classname);dc->devices=NULL;dc->maxunit=0;TAILQ_INIT(&dc->drivers);TAILQ_INSERT_TAIL(&devclasses,dc,link);}returndc;}devclass_tdevclass_create(constchar*classname){returndevclass_find_internal(classname,TRUE);}d
evclass_tdevclass_find(constchar*classname){returndevclass_find_internal(classname,FALSE);}intdevclass_add_driver(devclass_tdc,driver_t*driver){driverlink_tdl;inti;PDEBUG(("%s",DRIVERNAME(driver)));dl=malloc(sizeof*dl,M_BUS,M_NOWAIT);if(!dl)returnENOMEM;bzero
(dl,sizeof*dl);/**Compilethedriver'smethods.*/if(!driver->ops)compile_methods(driver);/**Makesurethedevclasswhichthedriverisimplementingexists.*/devclass_find_internal(driver->name,TRUE);dl->driver=driver;TAILQ_INSERT_TAIL(&dc->drivers,dl,link);driver->refs++
;/**CallBUS_DRIVER_ADDEDforanyexistingbussesinthisclass.*/for(i=0;i<dc->maxunit;i++)if(dc->devices[i])BUS_DRIVER_ADDED(dc->devices[i],driver);return0;}intdevclass_delete_driver(devclass_tbusclass,driver_t*driver){devclass_tdc=devclass_find(driver->name);drive
rlink_tdl;device_tdev;inti;interror;PDEBUG(("%sfromdevclass%s",driver->name,DEVCLANAME(busclass)));if(!dc)return0;/**Findthelinkstructureinthebus'listofdrivers.*/for(dl=TAILQ_FIRST(&busclass->drivers);dl;dl=TAILQ_NEXT(dl,link)){if(dl->driver==driver)break;}if
(!dl){PDEBUG(("%snotfoundin%slist",driver->name,busclass->name));returnENOENT;}/**Disassociatefromanydevices.Weiteratethroughallthe*devicesinthedevclassofthedriveranddetachanywhichare*usingthedriverandwhichhaveaparentinthedevclasswhich*wearedeletingfrom.**Not
ethatsinceadrivercanbeinmultipledevclasses,we*shouldnotdetachdeviceswhicharenotchildrenofdevicesin*theaffecteddevclass.*/for(i=0;i<dc->maxunit;i++){if(dc->devices[i]){dev=dc->devices[i];if(dev->driver==driver&&dev->parent&&dev->parent->devclass==busclass){if(
(error=device_detach(dev))!=0)returnerror;device_set_driver(dev,NULL);}}}TAILQ_REMOVE(&busclass->drivers,dl,link);free(dl,M_BUS);driver->refs--;if(driver->refs==0)free_methods(driver);return0;}staticdriverlink_tdevclass_find_driver_internal(devclass_tdc,const
char*classname){driverlink_tdl;PDEBUG(("%sindevclass%s",classname,DEVCLANAME(dc)));for(dl=TAILQ_FIRST(&dc->drivers);dl;dl=TAILQ_NEXT(dl,link)){if(!strcmp(dl->driver->name,classname))returndl;}PDEBUG(("notfound"));returnNULL;}driver_t*devclass_find_driver(devc
lass_tdc,constchar*classname){driverlink_tdl;dl=devclass_find_driver_internal(dc,classname);if(dl)returndl->driver;elsereturnNULL;}constchar*devclass_get_name(devclass_tdc){returndc->name;}device_tdevclass_get_device(devclass_tdc,intunit){if(dc==NULL||unit<0|
|unit>=dc->maxunit)returnNULL;returndc->devices[unit];}void*devclass_get_softc(devclass_tdc,intunit){device_tdev;dev=devclass_get_device(dc,unit);if(!dev)return(NULL);return(device_get_softc(dev));}intdevclass_get_devices(devclass_tdc,device_t**devlistp,int*d
evcountp){inti;intcount;device_t*list;count=0;for(i=0;i<dc->maxunit;i++)if(dc->devices[i])count++;list=malloc(count*sizeof(device_t),M_TEMP,M_NOWAIT);if(!list)returnENOMEM;bzero(list,count*sizeof(device_t));count=0;for(i=0;i<dc->maxunit;i++)if(dc->devices[i])
{list[count]=dc->devices[i];count++;}*devlistp=list;*devcountp=count;return0;}intdevclass_get_maxunit(devclass_tdc){returndc->maxunit;}staticintdevclass_alloc_unit(devclass_tdc,int*unitp){intunit=*unitp;PDEBUG(("unit%dindevclass%s",unit,DEVCLANAME(dc)));/*Ifw
ehavebeengivenawiredunitnumber,checkforexistingdevice*/if(unit!=-1){if(unit>=0&&unit<dc->maxunit&&dc->devices[unit]!=NULL){if(bootverbose)printf("%s-:%s%dexists,usingnextavailableunitnumber\n",dc->name,dc->name,unit);/*findthenextavailableslot*/while(++unit<d
c->maxunit&&dc->devices[unit]!=NULL);}}else{/*Unwireddevice,findthenextavailableslotforit*/unit=0;while(unit<dc->maxunit&&dc->devices[unit]!=NULL)unit++;}/**We'veselectedaunitbeyondthelengthofthetable,solet'sextend*thetabletomakeroomforallunitsuptoandincludin
gthisone.*/if(unit>=dc->maxunit){device_t*newlist;intnewsize;newsize=roundup((unit+1),MINALLOCSIZE/sizeof(device_t));newlist=malloc(sizeof(device_t)*newsize,M_BUS,M_NOWAIT);if(!newlist)returnENOMEM;bcopy(dc->devices,newlist,sizeof(device_t)*dc->maxunit);bzero
(newlist+dc->maxunit,sizeof(device_t)*(newsize-dc->maxunit));if(dc->devices)free(dc->devices,M_BUS);dc->devices=newlist;dc->maxunit=newsize;}PDEBUG(("now:unit%dindevclass%s",unit,DEVCLANAME(dc)));*unitp=unit;return0;}staticintdevclass_add_device(devclass_tdc,
device_tdev){intbuflen,error;PDEBUG(("%sindevclass%s",DEVICENAME(dev),DEVCLANAME(dc)));buflen=strlen(dc->name)+5;dev->nameunit=malloc(buflen,M_BUS,M_NOWAIT);if(!dev->nameunit)returnENOMEM;bzero(dev->nameunit,buflen);if((error=devclass_alloc_unit(dc,&dev->unit
))!=0){free(dev->nameunit,M_BUS);dev->nameunit=NULL;returnerror;}dc->devices[dev->unit]=dev;dev->devclass=dc;snprintf(dev->nameunit,buflen,"%s%d",dc->name,dev->unit);#ifdefDEVICE_SYSCTLSdevice_register_oids(dev);#endifreturn0;}staticintdevclass_delete_device(
devclass_tdc,device_tdev){if(!dc||!dev)return0;PDEBUG(("%sindevclass%s",DEVICENAME(dev),DEVCLANAME(dc)));if(dev->devclass!=dc||dc->devices[dev->unit]!=dev)panic("devclass_delete_device:inconsistentdeviceclass");dc->devices[dev->unit]=NULL;if(dev->flags&DF_WIL
DCARD)dev->unit=-1;dev->devclass=NULL;free(dev->nameunit,M_BUS);dev->nameunit=NULL;#ifdefDEVICE_SYSCTLSdevice_unregister_oids(dev);#endifreturn0;}staticdevice_tmake_device(device_tparent,constchar*name,intunit){device_tdev;devclass_tdc;PDEBUG(("%sat%sasunit%d
",name,DEVICENAME(parent),unit));if(name){dc=devclass_find_internal(name,TRUE);if(!dc){printf("make_device:can'tfinddeviceclass%s\n",name);returnNULL;}}elsedc=NULL;dev=malloc(sizeof(structdevice),M_BUS,M_NOWAIT);if(!dev)return0;bzero(dev,sizeof(structdevice))
;dev->parent=parent;TAILQ_INIT(&dev->children);dev->ops=&null_ops;dev->driver=NULL;dev->devclass=NULL;dev->unit=unit;dev->nameunit=NULL;dev->desc=NULL;dev->busy=0;dev->devflags=0;dev->flags=DF_ENABLED;dev->order=0;if(unit==-1)dev->flags|=DF_WILDCARD;if(name){
dev->flags|=DF_FIXEDCLASS;devclass_add_device(dc,dev);}dev->ivars=NULL;dev->softc=NULL;dev->state=DS_NOTPRESENT;returndev;}staticintdevice_print_child(device_tdev,device_tchild){intretval=0;if(device_is_alive(child)){retval+=BUS_PRINT_CHILD(dev,child);}elsere
tval+=device_printf(child,"notfound\n");return(retval);}device_tdevice_add_child(device_tdev,constchar*name,intunit){returndevice_add_child_ordered(dev,0,name,unit);}device_tdevice_add_child_ordered(device_tdev,intorder,constchar*name,intunit){device_tchild;d
evice_tplace;PDEBUG(("%sat%swithorder%dasunit%d",name,DEVICENAME(dev),order,unit));child=make_device(dev,name,unit);if(child==NULL)returnchild;child->order=order;TAILQ_FOREACH(place,&dev->children,link)if(place->order>order)break;if(place){/**Thedevice'place'
isthefirstdevicewhoseorderis*greaterthanthenewchild.*/TAILQ_INSERT_BEFORE(place,child,link);}else{/**Thenewchild'sorderisgreaterorequaltotheorderof*anyexistingdevice.Addthechildtothetailofthelist.*/TAILQ_INSERT_TAIL(&dev->children,child,link);}returnchild;}in
tdevice_delete_child(device_tdev,device_tchild){interror;device_tgrandchild;PDEBUG(("%sfrom%s",DEVICENAME(child),DEVICENAME(dev)));/*removechildrenfirst*/while((grandchild=TAILQ_FIRST(&child->children))){error=device_delete_child(child,grandchild);if(error)re
turnerror;}if((error=device_detach(child))!=0)returnerror;if(child->devclass)devclass_delete_device(child->devclass,child);TAILQ_REMOVE(&dev->children,child,link);device_set_desc(child,NULL);free(child,M_BUS);return0;}/**Findonlydevicesattachedtothisbus.*/dev
ice_tdevice_find_child(device_tdev,constchar*classname,intunit){devclass_tdc;device_tchild;dc=devclass_find(classname);if(!dc)returnNULL;child=devclass_get_device(dc,unit);if(child&&child->parent==dev)returnchild;returnNULL;}staticdriverlink_tfirst_matching_d
river(devclass_tdc,device_tdev){if(dev->devclass)returndevclass_find_driver_internal(dc,dev->devclass->name);elsereturnTAILQ_FIRST(&dc->drivers);}staticdriverlink_tnext_matching_driver(devclass_tdc,device_tdev,driverlink_tlast){if(dev->devclass){driverlink_td
l;for(dl=TAILQ_NEXT(last,link);dl;dl=TAILQ_NEXT(dl,link))if(!strcmp(dev->devclass->name,dl->driver->name))returndl;returnNULL;}elsereturnTAILQ_NEXT(last,link);}staticintdevice_probe_child(device_tdev,device_tchild){devclass_tdc;driverlink_tbest=0;driverlink_t
dl;intresult,pri=0;inthasclass=(child->devclass!=0);dc=dev->devclass;if(!dc)panic("device_probe_child:parentdevicehasnodevclass");if(child->state==DS_ALIVE)return0;for(dl=first_matching_driver(dc,child);dl;dl=next_matching_driver(dc,child,dl)){PDEBUG(("Trying
%s",DRIVERNAME(dl->driver)));device_set_driver(child,dl->driver);if(!hasclass)device_set_devclass(child,dl->driver->name);result=DEVICE_PROBE(child);if(!hasclass)device_set_devclass(child,0);/**IfthedriverreturnsSUCCESS,therecanbenohighermatch*forthisdevice.*
/if(result==0){best=dl;pri=0;break;}/**Thedriverreturnedanerrorsoitcertainlydoesn'tmatch.*/if(result>0){device_set_driver(child,0);continue;}/**AprioritylowerthanSUCCESS,rememberthebestmatching*driver.Initialisethevalueofpriforthefirstmatch.*/if(best==0||resu
lt>pri){best=dl;pri=result;continue;}}/**Ifwefoundadriver,changestateandinitialisethedevclass.*/if(best){if(!child->devclass)device_set_devclass(child,best->driver->name);device_set_driver(child,best->driver);if(pri<0){/**Abitbogus.Calltheprobemethodagaintoma
kesure*thatwehavetherightdescription.*/DEVICE_PROBE(child);}child->state=DS_ALIVE;return0;}returnENXIO;}device_tdevice_get_parent(device_tdev){returndev->parent;}intdevice_get_children(device_tdev,device_t**devlistp,int*devcountp){intcount;device_tchild;devic
e_t*list;count=0;for(child=TAILQ_FIRST(&dev->children);child;child=TAILQ_NEXT(child,link))count++;list=malloc(count*sizeof(device_t),M_TEMP,M_NOWAIT);if(!list)returnENOMEM;bzero(list,count*sizeof(device_t));count=0;for(child=TAILQ_FIRST(&dev->children);child;
child=TAILQ_NEXT(child,link)){list[count]=child;count++;}*devlistp=list;*devcountp=count;return0;}driver_t*device_get_driver(device_tdev){returndev->driver;}devclass_tdevice_get_devclass(device_tdev){returndev->devclass;}constchar*device_get_name(device_tdev)
{if(dev->devclass)returndevclass_get_name(dev->devclass);returnNULL;}constchar*device_get_nameunit(device_tdev){returndev->nameunit;}intdevice_get_unit(device_tdev){returndev->unit;}constchar*device_get_desc(device_tdev){returndev->desc;}u_int32_tdevice_get_f
lags(device_tdev){returndev->devflags;}intdevice_print_prettyname(device_tdev){constchar*name=device_get_name(dev);if(name==0)returnprintf("unknown:");elsereturnprintf("%s%d:",name,device_get_unit(dev));}intdevice_printf(device_tdev,constchar*fmt,...){va_list
ap;intretval;retval=device_print_prettyname(dev);va_start(ap,fmt);retval+=vprintf(fmt,ap);va_end(ap);returnretval;}staticvoiddevice_set_desc_internal(device_tdev,constchar*desc,intcopy){if(dev->desc&&(dev->flags&DF_DESCMALLOCED)){free(dev->desc,M_BUS);dev->fl
ags&=~DF_DESCMALLOCED;dev->desc=NULL;}if(copy&&desc){dev->desc=malloc(strlen(desc)+1,M_BUS,M_NOWAIT);if(dev->desc){strcpy(dev->desc,desc);dev->flags|=DF_DESCMALLOCED;}}else/*Avoida-Wcast-qualwarning*/dev->desc=(char*)(uintptr_t)desc;#ifdefDEVICE_SYSCTLS{struc
tsysctl_oid*oid=&dev->oid[1];oid->oid_arg1=dev->desc?dev->desc:"";oid->oid_arg2=dev->desc?strlen(dev->desc):0;}#endif}voiddevice_set_desc(device_tdev,constchar*desc){device_set_desc_internal(dev,desc,FALSE);}voiddevice_set_desc_copy(device_tdev,constchar*desc
){device_set_desc_internal(dev,desc,TRUE);}voiddevice_set_flags(device_tdev,u_int32_tflags){dev->devflags=flags;}void*device_get_softc(device_tdev){returndev->softc;}voiddevice_set_softc(device_tdev,void*softc){if(dev->softc&&!(dev->flags&DF_EXTERNALSOFTC))fr
ee(dev->softc,M_BUS);dev->softc=softc;if(dev->softc)dev->flags|=DF_EXTERNALSOFTC;elsedev->flags&=~DF_EXTERNALSOFTC;}void*device_get_ivars(device_tdev){returndev->ivars;}voiddevice_set_ivars(device_tdev,void*ivars){if(!dev)return;dev->ivars=ivars;return;}devic
e_state_tdevice_get_state(device_tdev){returndev->state;}voiddevice_enable(device_tdev){dev->flags|=DF_ENABLED;}voiddevice_disable(device_tdev){dev->flags&=~DF_ENABLED;}voiddevice_busy(device_tdev){if(dev->state<DS_ATTACHED)panic("device_busy:calledforunattac
heddevice");if(dev->busy==0&&dev->parent)device_busy(dev->parent);dev->busy++;dev->state=DS_BUSY;}voiddevice_unbusy(device_tdev){if(dev->state!=DS_BUSY)panic("device_unbusy:calledfornon-busydevice");dev->busy--;if(dev->busy==0){if(dev->parent)device_unbusy(de
v->parent);dev->state=DS_ATTACHED;}}voiddevice_quiet(device_tdev){dev->flags|=DF_QUIET;}voiddevice_verbose(device_tdev){dev->flags&=~DF_QUIET;}intdevice_is_quiet(device_tdev){return(dev->flags&DF_QUIET)!=0;}intdevice_is_enabled(device_tdev){return(dev->flags&
DF_ENABLED)!=0;}intdevice_is_alive(device_tdev){returndev->state>=DS_ALIVE;}intdevice_set_devclass(device_tdev,constchar*classname){devclass_tdc;if(!classname){if(dev->devclass)devclass_delete_device(dev->devclass,dev);return0;}if(dev->devclass){printf("devic
e_set_devclass:deviceclassalreadyset\n");returnEINVAL;}dc=devclass_find_internal(classname,TRUE);if(!dc)returnENOMEM;returndevclass_add_device(dc,dev);}intdevice_set_driver(device_tdev,driver_t*driver){if(dev->state>=DS_ATTACHED)returnEBUSY;if(dev->driver==dr
iver)return0;if(dev->softc&&!(dev->flags&DF_EXTERNALSOFTC)){free(dev->softc,M_BUS);dev->softc=NULL;}dev->ops=&null_ops;dev->driver=driver;if(driver){dev->ops=driver->ops;if(!(dev->flags&DF_EXTERNALSOFTC)){dev->softc=malloc(driver->softc,M_BUS,M_NOWAIT);if(!de
v->softc){dev->ops=&null_ops;dev->driver=NULL;returnENOMEM;}bzero(dev->softc,driver->softc);}}return0;}intdevice_probe_and_attach(device_tdev){device_tbus=dev->parent;interror=0;inthasclass=(dev->devclass!=0);if(dev->state>=DS_ALIVE)return0;if(dev->flags&DF_E
NABLED){error=device_probe_child(bus,dev);if(!error){if(!device_is_quiet(dev))device_print_child(bus,dev);error=DEVICE_ATTACH(dev);if(!error)dev->state=DS_ATTACHED;else{printf("device_probe_and_attach:%s%dattachreturned%d\n",dev->driver->name,dev->unit,error)
;/*Unsettheclassthatwassetindevice_probe_child*/if(!hasclass)device_set_devclass(dev,0);device_set_driver(dev,NULL);dev->state=DS_NOTPRESENT;}}else{if(!(dev->flags&DF_DONENOMATCH)){BUS_PROBE_NOMATCH(bus,dev);dev->flags|=DF_DONENOMATCH;}}}else{if(bootverbose){
device_print_prettyname(dev);printf("notprobed(disabled)\n");}}returnerror;}intdevice_detach(device_tdev){interror;PDEBUG(("%s",DEVICENAME(dev)));if(dev->state==DS_BUSY)returnEBUSY;if(dev->state!=DS_ATTACHED)return0;if((error=DEVICE_DETACH(dev))!=0)returnerro
r;device_printf(dev,"detached\n");if(dev->parent)BUS_CHILD_DETACHED(dev->parent,dev);if(!(dev->flags&DF_FIXEDCLASS))devclass_delete_device(dev->devclass,dev);dev->state=DS_NOTPRESENT;device_set_driver(dev,NULL);return0;}intdevice_shutdown(device_tdev){if(dev-
>state<DS_ATTACHED)return0;returnDEVICE_SHUTDOWN(dev);}intdevice_set_unit(device_tdev,intunit){devclass_tdc;interr;dc=device_get_devclass(dev);if(unit<dc->maxunit&&dc->devices[unit])returnEBUSY;err=devclass_delete_device(dc,dev);if(err)returnerr;dev->unit=uni
t;err=devclass_add_device(dc,dev);if(err)returnerr;return0;}#ifdefDEVICE_SYSCTLS/**Sysctlnodesfordevices.*/SYSCTL_NODE(_hw,OID_AUTO,devices,CTLFLAG_RW,0,"Alistofalldevices");staticintsysctl_handle_children(SYSCTL_HANDLER_ARGS){device_tdev=arg1;device_tchild;i
ntfirst=1,error=0;for(child=TAILQ_FIRST(&dev->children);child;child=TAILQ_NEXT(child,link)){if(child->nameunit){if(!first){error=SYSCTL_OUT(req,",",1);if(error)returnerror;}else{first=0;}error=SYSCTL_OUT(req,child->nameunit,strlen(child->nameunit));if(error)r
eturnerror;}}error=SYSCTL_OUT(req,"",1);returnerror;}staticintsysctl_handle_state(SYSCTL_HANDLER_ARGS){device_tdev=arg1;switch(dev->state){caseDS_NOTPRESENT:returnSYSCTL_OUT(req,"notpresent",sizeof("notpresent"));caseDS_ALIVE:returnSYSCTL_OUT(req,"alive",size
of("alive"));caseDS_ATTACHED:returnSYSCTL_OUT(req,"attached",sizeof("attached"));caseDS_BUSY:returnSYSCTL_OUT(req,"busy",sizeof("busy"));}return0;}staticvoiddevice_register_oids(device_tdev){structsysctl_oid*oid;oid=&dev->oid[0];bzero(oid,sizeof(*oid));oid->o
id_parent=&sysctl__hw_devices_children;oid->oid_number=OID_AUTO;oid->oid_kind=CTLTYPE_NODE|CTLFLAG_RW;oid->oid_arg1=&dev->oidlist[0];oid->oid_arg2=0;oid->oid_name=dev->nameunit;oid->oid_handler=0;oid->oid_fmt="N";SLIST_INIT(&dev->oidlist[0]);sysctl_register_o
id(oid);oid=&dev->oid[1];bzero(oid,sizeof(*oid));oid->oid_parent=&dev->oidlist[0];oid->oid_number=OID_AUTO;oid->oid_kind=CTLTYPE_STRING|CTLFLAG_RD;oid->oid_arg1=dev->desc?dev->desc:"";oid->oid_arg2=dev->desc?strlen(dev->desc):0;oid->oid_name="desc";oid->oid_h
andler=sysctl_handle_string;oid->oid_fmt="A";sysctl_register_oid(oid);oid=&dev->oid[2];bzero(oid,sizeof(*oid));oid->oid_parent=&dev->oidlist[0];oid->oid_number=OID_AUTO;oid->oid_kind=CTLTYPE_INT|CTLFLAG_RD;oid->oid_arg1=dev;oid->oid_arg2=0;oid->oid_name="chil
dren";oid->oid_handler=sysctl_handle_children;oid->oid_fmt="A";sysctl_register_oid(oid);oid=&dev->oid[3];bzero(oid,sizeof(*oid));oid->oid_parent=&dev->oidlist[0];oid->oid_number=OID_AUTO;oid->oid_kind=CTLTYPE_INT|CTLFLAG_RD;oid->oid_arg1=dev;oid->oid_arg2=0;o
id->oid_name="state";oid->oid_handler=sysctl_handle_state;oid->oid_fmt="A";sysctl_register_oid(oid);}staticvoiddevice_unregister_oids(device_tdev){sysctl_unregister_oid(&dev->oid[0]);sysctl_unregister_oid(&dev->oid[1]);sysctl_unregister_oid(&dev->oid[2]);}#en
dif/*======================================*//**Accessfunctionsfordeviceresources.*//*Suppliedbyconfig(8)inioconf.c*/externstructconfig_deviceconfig_devtab[];externintdevtab_count;/*Runtimeversion*/structconfig_device*devtab=config_devtab;staticintresource_ne
w_name(constchar*name,intunit){structconfig_device*new;new=malloc((devtab_count+1)*sizeof(*new),M_TEMP,M_NOWAIT);if(new==NULL)return-1;if(devtab&&devtab_count>0)bcopy(devtab,new,devtab_count*sizeof(*new));bzero(&new[devtab_count],sizeof(*new));new[devtab_coun
t].name=malloc(strlen(name)+1,M_TEMP,M_NOWAIT);if(new[devtab_count].name==NULL){free(new,M_TEMP);return-1;}strcpy(new[devtab_count].name,name);new[devtab_count].unit=unit;new[devtab_count].resource_count=0;new[devtab_count].resources=NULL;devtab=new;returndev
tab_count++;}staticintresource_new_resname(intj,constchar*resname,resource_typetype){structconfig_resource*new;inti;i=devtab[j].resource_count;new=malloc((i+1)*sizeof(*new),M_TEMP,M_NOWAIT);if(new==NULL)return-1;if(devtab[j].resources&&i>0)bcopy(devtab[j].res
ources,new,i*sizeof(*new));bzero(&new[i],sizeof(*new));new[i].name=malloc(strlen(resname)+1,M_TEMP,M_NOWAIT);if(new[i].name==NULL){free(new,M_TEMP);return-1;}strcpy(new[i].name,resname);new[i].type=type;if(devtab[j].resources)free(devtab[j].resources,M_TEMP);
devtab[j].resources=new;devtab[j].resource_count=i+1;returni;}staticintresource_match_string(inti,constchar*resname,constchar*value){intj;structconfig_resource*res;for(j=0,res=devtab[i].resources;j<devtab[i].resource_count;j++,res++)if(!strcmp(res->name,resna
me)&&res->type==RES_STRING&&!strcmp(res->u.stringval,value))returnj;return-1;}staticintresource_find(constchar*name,intunit,constchar*resname,structconfig_resource**result){inti,j;structconfig_resource*res;/**Firstcheckspecificinstances,thengeneric.*/for(i=0;
i<devtab_count;i++){if(devtab[i].unit<0)continue;if(!strcmp(devtab[i].name,name)&&devtab[i].unit==unit){res=devtab[i].resources;for(j=0;j<devtab[i].resource_count;j++,res++)if(!strcmp(res->name,resname)){*result=res;return0;}}}for(i=0;i<devtab_count;i++){if(d
evtab[i].unit>=0)continue;/*XXXshouldthis`&&devtab[i].unit==unit'behere?*//*XXXifso,thenthegenericmatchdoesnothing*/if(!strcmp(devtab[i].name,name)&&devtab[i].unit==unit){res=devtab[i].resources;for(j=0;j<devtab[i].resource_count;j++,res++)if(!strcmp(res->nam
e,resname)){*result=res;return0;}}}returnENOENT;}intresource_int_value(constchar*name,intunit,constchar*resname,int*result){interror;structconfig_resource*res;if((error=resource_find(name,unit,resname,&res))!=0)returnerror;if(res->type!=RES_INT)returnEFTYPE;*
result=res->u.intval;return0;}intresource_long_value(constchar*name,intunit,constchar*resname,long*result){interror;structconfig_resource*res;if((error=resource_find(name,unit,resname,&res))!=0)returnerror;if(res->type!=RES_LONG)returnEFTYPE;*result=res->u.lo
ngval;return0;}intresource_string_value(constchar*name,intunit,constchar*resname,char**result){interror;structconfig_resource*res;if((error=resource_find(name,unit,resname,&res))!=0)returnerror;if(res->type!=RES_STRING)returnEFTYPE;*result=res->u.stringval;re
turn0;}intresource_query_string(inti,constchar*resname,constchar*value){if(i<0)i=0;elsei=i+1;for(;i<devtab_count;i++)if(resource_match_string(i,resname,value)>=0)returni;return-1;}intresource_locate(inti,constchar*resname){if(i<0)i=0;elsei=i+1;for(;i<devtab_c
ount;i++)if(!strcmp(devtab[i].name,resname))returni;return-1;}intresource_count(void){returndevtab_count;}char*resource_query_name(inti){returndevtab[i].name;}intresource_query_unit(inti){returndevtab[i].unit;}staticintresource_create(constchar*name,intunit,c
onstchar*resname,resource_typetype,structconfig_resource**result){inti,j;structconfig_resource*res=NULL;for(i=0;i<devtab_count;i++){if(!strcmp(devtab[i].name,name)&&devtab[i].unit==unit){res=devtab[i].resources;break;}}if(res==NULL){i=resource_new_name(name,u
nit);if(i<0)returnENOMEM;res=devtab[i].resources;}for(j=0;j<devtab[i].resource_count;j++,res++){if(!strcmp(res->name,resname)){*result=res;return0;}}j=resource_new_resname(i,resname,type);if(j<0)returnENOMEM;res=&devtab[i].resources[j];*result=res;return0;}in
tresource_set_int(constchar*name,intunit,constchar*resname,intvalue){interror;structconfig_resource*res;error=resource_create(name,unit,resname,RES_INT,&res);if(error)returnerror;if(res->type!=RES_INT)returnEFTYPE;res->u.intval=value;return0;}intresource_set_
long(constchar*name,intunit,constchar*resname,longvalue){interror;structconfig_resource*res;error=resource_create(name,unit,resname,RES_LONG,&res);if(error)returnerror;if(res->type!=RES_LONG)returnEFTYPE;res->u.longval=value;return0;}intresource_set_string(co
nstchar*name,intunit,constchar*resname,constchar*value){interror;structconfig_resource*res;error=resource_create(name,unit,resname,RES_STRING,&res);if(error)returnerror;if(res->type!=RES_STRING)returnEFTYPE;if(res->u.stringval)free(res->u.stringval,M_TEMP);re
s->u.stringval=malloc(strlen(value)+1,M_TEMP,M_NOWAIT);if(res->u.stringval==NULL)returnENOMEM;strcpy(res->u.stringval,value);return0;}staticvoidresource_cfgload(void*dummy__unused){structconfig_resource*res,*cfgres;inti,j;interror;char*name,*resname;intunit;r
esource_typetype;char*stringval;intconfig_devtab_count;config_devtab_count=devtab_count;devtab=NULL;devtab_count=0;for(i=0;i<config_devtab_count;i++){name=config_devtab[i].name;unit=config_devtab[i].unit;for(j=0;j<config_devtab[i].resource_count;j++){cfgres=c
onfig_devtab[i].resources;resname=cfgres[j].name;type=cfgres[j].type;error=resource_create(name,unit,resname,type,&res);if(error){printf("createresource%s%d:error%d\n",name,unit,error);continue;}if(res->type!=type){printf("typemismatch%s%d:%d!=%d\n",name,unit
,res->type,type);continue;}switch(type){caseRES_INT:res->u.intval=cfgres[j].u.intval;break;caseRES_LONG:res->u.longval=cfgres[j].u.longval;break;caseRES_STRING:if(res->u.stringval)free(res->u.stringval,M_TEMP);stringval=cfgres[j].u.stringval;res->u.stringval=
malloc(strlen(stringval)+1,M_TEMP,M_NOWAIT);if(res->u.stringval==NULL)break;strcpy(res->u.stringval,stringval);break;default:panic("unknownresourcetype%d\n",type);}}}}SYSINIT(cfgload,SI_SUB_KMEM,SI_ORDER_ANY+50,resource_cfgload,0)/*===========================
===========*//**Someusefulmethodimplementationstomakelifeeasierforbusdrivers.*/voidresource_list_init(structresource_list*rl){SLIST_INIT(rl);}voidresource_list_free(structresource_list*rl){structresource_list_entry*rle;while((rle=SLIST_FIRST(rl))!=NULL){if(rl
e->res)panic("resource_list_free:resourceentryisbusy");SLIST_REMOVE_HEAD(rl,link);free(rle,M_BUS);}}voidresource_list_add(structresource_list*rl,inttype,intrid,u_longstart,u_longend,u_longcount){structresource_list_entry*rle;rle=resource_list_find(rl,type,rid
);if(!rle){rle=malloc(sizeof(structresource_list_entry),M_BUS,M_NOWAIT);if(!rle)panic("resource_list_add:can'trecordentry");SLIST_INSERT_HEAD(rl,rle,link);rle->type=type;rle->rid=rid;rle->res=NULL;}if(rle->res)panic("resource_list_add:resourceentryisbusy");rl
e->start=start;rle->end=end;rle->count=count;}structresource_list_entry*resource_list_find(structresource_list*rl,inttype,intrid){structresource_list_entry*rle;SLIST_FOREACH(rle,rl,link)if(rle->type==type&&rle->rid==rid)returnrle;returnNULL;}voidresource_list
_delete(structresource_list*rl,inttype,intrid){structresource_list_entry*rle=resource_list_find(rl,type,rid);if(rle){SLIST_REMOVE(rl,rle,resource_list_entry,link);free(rle,M_BUS);}}structresource*resource_list_alloc(structresource_list*rl,device_tbus,device_t
child,inttype,int*rid,u_longstart,u_longend,u_longcount,u_intflags){structresource_list_entry*rle=0;intpassthrough=(device_get_parent(child)!=bus);intisdefault=(start==0UL&&end==~0UL);if(passthrough){returnBUS_ALLOC_RESOURCE(device_get_parent(bus),child,type,
rid,start,end,count,flags);}rle=resource_list_find(rl,type,*rid);if(!rle)return0;/*noresourceofthattype/rid*/if(rle->res)panic("resource_list_alloc:resourceentryisbusy");if(isdefault){start=rle->start;count=max(count,rle->count);end=max(rle->end,start+count-1
);}rle->res=BUS_ALLOC_RESOURCE(device_get_parent(bus),child,type,rid,start,end,count,flags);/**Recordthenewrange.*/if(rle->res){rle->start=rman_get_start(rle->res);rle->end=rman_get_end(rle->res);rle->count=count;}returnrle->res;}intresource_list_release(stru
ctresource_list*rl,device_tbus,device_tchild,inttype,intrid,structresource*res){structresource_list_entry*rle=0;intpassthrough=(device_get_parent(child)!=bus);interror;if(passthrough){returnBUS_RELEASE_RESOURCE(device_get_parent(bus),child,type,rid,res);}rle=
resource_list_find(rl,type,rid);if(!rle)panic("resource_list_release:can'tfindresource");if(!rle->res)panic("resource_list_release:resourceentryisnotbusy");error=BUS_RELEASE_RESOURCE(device_get_parent(bus),child,type,rid,res);if(error)returnerror;rle->res=NUL
L;return0;}/**CallDEVICE_IDENTIFYforeachdriver.*/intbus_generic_probe(device_tdev){devclass_tdc=dev->devclass;driverlink_tdl;for(dl=TAILQ_FIRST(&dc->drivers);dl;dl=TAILQ_NEXT(dl,link))DEVICE_IDENTIFY(dl->driver,dev);return0;}intbus_generic_attach(device_tdev)
{device_tchild;for(child=TAILQ_FIRST(&dev->children);child;child=TAILQ_NEXT(child,link))device_probe_and_attach(child);return0;}intbus_generic_detach(device_tdev){device_tchild;interror;if(dev->state!=DS_ATTACHED)returnEBUSY;for(child=TAILQ_FIRST(&dev->childr
en);child;child=TAILQ_NEXT(child,link))if((error=device_detach(child))!=0)returnerror;return0;}intbus_generic_shutdown(device_tdev){device_tchild;for(child=TAILQ_FIRST(&dev->children);child;child=TAILQ_NEXT(child,link))device_shutdown(child);return0;}intbus_g
eneric_suspend(device_tdev){interror;device_tchild,child2;for(child=TAILQ_FIRST(&dev->children);child;child=TAILQ_NEXT(child,link)){error=DEVICE_SUSPEND(child);if(error){for(child2=TAILQ_FIRST(&dev->children);child2&&child2!=child;child2=TAILQ_NEXT(child2,lin
k))DEVICE_RESUME(child2);return(error);}}return0;}intbus_generic_resume(device_tdev){device_tchild;for(child=TAILQ_FIRST(&dev->children);child;child=TAILQ_NEXT(child,link)){DEVICE_RESUME(child);/*ifresumefails,there'snothingwecanusefullydo...*/}return0;}intbu
s_print_child_header(device_tdev,device_tchild){intretval=0;if(device_get_desc(child)){retval+=device_printf(child,"<%s>",device_get_desc(child));}else{retval+=printf("%s",device_get_nameunit(child));}return(retval);}intbus_print_child_footer(device_tdev,devi
ce_tchild){return(printf("on%s\n",device_get_nameunit(dev)));}intbus_generic_print_child(device_tdev,device_tchild){intretval=0;retval+=bus_print_child_header(dev,child);retval+=bus_print_child_footer(dev,child);return(retval);}intbus_generic_read_ivar(device
_tdev,device_tchild,intindex,uintptr_t*result){returnENOENT;}intbus_generic_write_ivar(device_tdev,device_tchild,intindex,uintptr_tvalue){returnENOENT;}voidbus_generic_driver_added(device_tdev,driver_t*driver){device_tchild;DEVICE_IDENTIFY(driver,dev);for(chi
ld=TAILQ_FIRST(&dev->children);child;child=TAILQ_NEXT(child,link))if(child->state==DS_NOTPRESENT)device_probe_and_attach(child);}intbus_generic_setup_intr(device_tdev,device_tchild,structresource*irq,intflags,driver_intr_t*intr,void*arg,void**cookiep){/*Propa
gateupthebushierarchyuntilsomeonehandlesit.*/if(dev->parent)return(BUS_SETUP_INTR(dev->parent,child,irq,flags,intr,arg,cookiep));elsereturn(EINVAL);}intbus_generic_teardown_intr(device_tdev,device_tchild,structresource*irq,void*cookie){/*Propagateupthebushier
archyuntilsomeonehandlesit.*/if(dev->parent)return(BUS_TEARDOWN_INTR(dev->parent,child,irq,cookie));elsereturn(EINVAL);}structresource*bus_generic_alloc_resource(device_tdev,device_tchild,inttype,int*rid,u_longstart,u_longend,u_longcount,u_intflags){/*Propaga
teupthebushierarchyuntilsomeonehandlesit.*/if(dev->parent)return(BUS_ALLOC_RESOURCE(dev->parent,child,type,rid,start,end,count,flags));elsereturn(NULL);}intbus_generic_release_resource(device_tdev,device_tchild,inttype,intrid,structresource*r){/*Propagateupth
ebushierarchyuntilsomeonehandlesit.*/if(dev->parent)return(BUS_RELEASE_RESOURCE(dev->parent,child,type,rid,r));elsereturn(EINVAL);}intbus_generic_activate_resource(device_tdev,device_tchild,inttype,intrid,structresource*r){/*Propagateupthebushierarchyuntilsom
eonehandlesit.*/if(dev->parent)return(BUS_ACTIVATE_RESOURCE(dev->parent,child,type,rid,r));elsereturn(EINVAL);}intbus_generic_deactivate_resource(device_tdev,device_tchild,inttype,intrid,structresource*r){/*Propagateupthebushierarchyuntilsomeonehandlesit.*/if
(dev->parent)return(BUS_DEACTIVATE_RESOURCE(dev->parent,child,type,rid,r));elsereturn(EINVAL);}/**Someconveniencefunctionstomakeiteasierfordriverstousethe*resource-managementfunctions.Allthesereallydoishidethe*indirectionthroughtheparent'smethodtable,makingfo
rslightly*less-wordycode.Inthefuture,itmightmakesenseforthiscode*tomaintainsomesortofalistofresourcesallocatedbyeachdevice.*/structresource*bus_alloc_resource(device_tdev,inttype,int*rid,u_longstart,u_longend,u_longcount,u_intflags){if(dev->parent==0)return(0
);return(BUS_ALLOC_RESOURCE(dev->parent,dev,type,rid,start,end,count,flags));}intbus_activate_resource(device_tdev,inttype,intrid,structresource*r){if(dev->parent==0)return(EINVAL);return(BUS_ACTIVATE_RESOURCE(dev->parent,dev,type,rid,r));}intbus_deactivate_r
esource(device_tdev,inttype,intrid,structresource*r){if(dev->parent==0)return(EINVAL);return(BUS_DEACTIVATE_RESOURCE(dev->parent,dev,type,rid,r));}intbus_release_resource(device_tdev,inttype,intrid,structresource*r){if(dev->parent==0)return(EINVAL);return(BUS
_RELEASE_RESOURCE(dev->parent,dev,type,rid,r));}intbus_setup_intr(device_tdev,structresource*r,intflags,driver_intr_thandler,void*arg,void**cookiep){if(dev->parent==0)return(EINVAL);return(BUS_SETUP_INTR(dev->parent,dev,r,flags,handler,arg,cookiep));}intbus_t
eardown_intr(device_tdev,structresource*r,void*cookie){if(dev->parent==0)return(EINVAL);return(BUS_TEARDOWN_INTR(dev->parent,dev,r,cookie));}intbus_set_resource(device_tdev,inttype,intrid,u_longstart,u_longcount){returnBUS_SET_RESOURCE(device_get_parent(dev),
dev,type,rid,start,count);}intbus_get_resource(device_tdev,inttype,intrid,u_long*startp,u_long*countp){returnBUS_GET_RESOURCE(device_get_parent(dev),dev,type,rid,startp,countp);}u_longbus_get_resource_start(device_tdev,inttype,intrid){u_longstart,count;interr
or;error=BUS_GET_RESOURCE(device_get_parent(dev),dev,type,rid,&start,&count);if(error)return0;returnstart;}u_longbus_get_resource_count(device_tdev,inttype,intrid){u_longstart,count;interror;error=BUS_GET_RESOURCE(device_get_parent(dev),dev,type,rid,&start,&c
ount);if(error)return0;returncount;}voidbus_delete_resource(device_tdev,inttype,intrid){BUS_DELETE_RESOURCE(device_get_parent(dev),dev,type,rid);}staticintroot_print_child(device_tdev,device_tchild){return(0);}staticintroot_setup_intr(device_tdev,device_tchil
d,driver_intr_t*intr,void*arg,void**cookiep){/**Ifaninterruptmappinggetstoheresomethingbadhashappened.*/panic("root_setup_intr");}staticdevice_method_troot_methods[]={/*Deviceinterface*/DEVMETHOD(device_shutdown,bus_generic_shutdown),DEVMETHOD(device_suspend,
bus_generic_suspend),DEVMETHOD(device_resume,bus_generic_resume),/*Businterface*/DEVMETHOD(bus_print_child,root_print_child),DEVMETHOD(bus_read_ivar,bus_generic_read_ivar),DEVMETHOD(bus_write_ivar,bus_generic_write_ivar),DEVMETHOD(bus_setup_intr,root_setup_in
tr),{0,0}};staticdriver_troot_driver={"root",root_methods,1,/*nosoftc*/};device_troot_bus;devclass_troot_devclass;staticintroot_bus_module_handler(module_tmod,intwhat,void*arg){switch(what){caseMOD_LOAD:compile_methods(&root_driver);root_bus=make_device(NULL,
"root",0);root_bus->desc="Systemrootbus";root_bus->ops=root_driver.ops;root_bus->driver=&root_driver;root_bus->state=DS_ATTACHED;root_devclass=devclass_find_internal("root",FALSE);return0;caseMOD_SHUTDOWN:device_shutdown(root_bus);return0;}return0;}staticmodu
ledata_troot_bus_mod={"rootbus",root_bus_module_handler,0};DECLARE_MODULE(rootbus,root_bus_mod,SI_SUB_DRIVERS,SI_ORDER_FIRST);voidroot_bus_configure(void){device_tdev;PDEBUG(("."));for(dev=TAILQ_FIRST(&root_bus->children);dev;dev=TAILQ_NEXT(dev,link)){device_
probe_and_attach(dev);}}intdriver_module_handler(module_tmod,intwhat,void*arg){interror,i;structdriver_module_data*dmd;devclass_tbus_devclass;dmd=(structdriver_module_data*)arg;bus_devclass=devclass_find_internal(dmd->dmd_busname,TRUE);error=0;switch(what){ca
seMOD_LOAD:if(dmd->dmd_chainevh)error=dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);for(i=0;!error&&i<dmd->dmd_ndrivers;i++){PDEBUG(("Loadingmodule:driver%sonbus%s",DRIVERNAME(dmd->dmd_drivers[i]),dmd->dmd_busname));error=devclass_add_driver(bus_devclass,dmd-
>dmd_drivers[i]);}if(error)break;/**Thedriversloadedinthiswayareassumedtoall*implementthesamedevclass.*/*dmd->dmd_devclass=devclass_find_internal(dmd->dmd_drivers[0]->name,TRUE);break;caseMOD_UNLOAD:for(i=0;!error&&i<dmd->dmd_ndrivers;i++){PDEBUG(("Unloadingm
odule:driver%sfrombus%s",DRIVERNAME(dmd->dmd_drivers[i]),dmd->dmd_busname));error=devclass_delete_driver(bus_devclass,dmd->dmd_drivers[i]);}if(!error&&dmd->dmd_chainevh)error=dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);break;}return(error);}#ifdefBUS_DEBUG/
*the_shortversionsavoiditerationbynotcallinganythingthatprints*morethanoneliners.Iloveoneliners.*/staticvoidprint_method_list(device_method_t*m,intindent){inti;if(!m)return;for(i=0;m->desc;i++,m++)indentprintf(("method%d:%s,offset=%d\n",i,m->desc->name,m->des
c->offset));}staticvoidprint_device_ops(device_ops_tops,intindent){inti;intcount=0;if(!ops)return;/*wepresentalistofthemethodsthatarepointingtothe*error_method,butignorethe0'thelements;itisalways*error_method.*/for(i=1;i<ops->maxoffset;i++){if(ops->methods[i]
==error_method){if(count==0)indentprintf(("error_method:"));printf("%d",i);count++;}}if(count)printf("\n");indentprintf(("(%dmethod%s,%dvalid,%derror_method%s)\n",ops->maxoffset-1,(ops->maxoffset-1==1?"":"s"),ops->maxoffset-1-count,count,(count==1?"":"'s")));
}staticvoidprint_device_short(device_tdev,intindent){if(!dev)return;indentprintf(("device%d:<%s>%sparent,%schildren,%s%s%s%s,%sivars,%ssoftc,busy=%d\n",dev->unit,dev->desc,(dev->parent?"":"no"),(TAILQ_EMPTY(&dev->children)?"no":""),(dev->flags&DF_ENABLED?"ena
bled,":"disabled,"),(dev->flags&DF_FIXEDCLASS?"fixed,":""),(dev->flags&DF_WILDCARD?"wildcard,":""),(dev->flags&DF_DESCMALLOCED?"descmalloced,":""),(dev->ivars?"":"no"),(dev->softc?"":"no"),dev->busy));}staticvoidprint_device(device_tdev,intindent){if(!dev)ret
urn;print_device_short(dev,indent);indentprintf(("Parent:\n"));print_device_short(dev->parent,indent+1);indentprintf(("Methods:\n"));print_device_ops(dev->ops,indent+1);indentprintf(("Driver:\n"));print_driver_short(dev->driver,indent+1);indentprintf(("Devcla
ss:\n"));print_devclass_short(dev->devclass,indent+1);}voidprint_device_tree_short(device_tdev,intindent)/*printthedeviceandallitschildren(indented)*/{device_tchild;if(!dev)return;print_device_short(dev,indent);for(child=TAILQ_FIRST(&dev->children);child;chil
d=TAILQ_NEXT(child,link))print_device_tree_short(child,indent+1);}voidprint_device_tree(device_tdev,intindent)/*printthedeviceandallitschildren(indented)*/{device_tchild;if(!dev)return;print_device(dev,indent);for(child=TAILQ_FIRST(&dev->children);child;child
=TAILQ_NEXT(child,link))print_device_tree(child,indent+1);}staticvoidprint_driver_short(driver_t*driver,intindent){if(!driver)return;indentprintf(("driver%s:softcsize=%d\n",driver->name,driver->softc));}staticvoidprint_driver(driver_t*driver,intindent){if(!dr
iver)return;print_driver_short(driver,indent);indentprintf(("Methods:\n"));print_method_list(driver->methods,indent+1);indentprintf(("Operations:\n"));print_device_ops(driver->ops,indent+1);}staticvoidprint_driver_list(driver_list_tdrivers,intindent){driverli
nk_tdriver;for(driver=TAILQ_FIRST(&drivers);driver;driver=TAILQ_NEXT(driver,link))print_driver(driver->driver,indent);}staticvoidprint_devclass_short(devclass_tdc,intindent){if(!dc)return;indentprintf(("devclass%s:maxunits=%d\n",dc->name,dc->maxunit));}static
voidprint_devclass(devclass_tdc,intindent){inti;if(!dc)return;print_devclass_short(dc,indent);indentprintf(("Drivers:\n"));print_driver_list(dc->drivers,indent+1);indentprintf(("Devices:\n"));for(i=0;i<dc->maxunit;i++)if(dc->devices[i])print_device(dc->device
s[i],indent+1);}voidprint_devclass_list_short(void){devclass_tdc;printf("Shortlistingofdevclasses,drivers&devices:\n");for(dc=TAILQ_FIRST(&devclasses);dc;dc=TAILQ_NEXT(dc,link))print_devclass_short(dc,0);}voidprint_devclass_list(void){devclass_tdc;printf("Ful
llistingofdevclasses,drivers&devices:\n");for(dc=TAILQ_FIRST(&devclasses);dc;dc=TAILQ_NEXT(dc,link))print_devclass(dc,0);}#endif/**Copyright(c)1993,DavidGreenman*Allrightsreserved.**Redistributionanduseinsourceandbinaryforms,withorwithout*modification,areperm
ittedprovidedthatthefollowingconditions*aremet:*1.Redistributionsofsourcecodemustretaintheabovecopyright*notice,thislistofconditionsandthefollowingdisclaimer.*2.Redistributionsinbinaryformmustreproducetheabovecopyright*notice,thislistofconditionsandthefollowi
ngdisclaimerinthe*documentationand/orothermaterialsprovidedwiththedistribution.**THISSOFTWAREISPROVIDEDBYTHEAUTHORANDCONTRIBUTORS``ASIS''AND*ANYEXPRESSORIMPLIEDWARRANTIES,INCLUDING,BUTNOTLIMITEDTO,THE*IMPLIEDWARRANTIESOFMERCHANTABILITYANDFITNESSFORAPARTICULAR
PURPOSE*AREDISCLAIMED.INNOEVENTSHALLTHEAUTHORORCONTRIBUTORSBELIABLE*FORANYDIRECT,INDIRECT,INCIDENTAL,SPECIAL,EXEMPLARY,ORCONSEQUENTIAL*DAMAGES(INCLUDING,BUTNOTLIMITEDTO,PROCUREMENTOFSUBSTITUTEGOODS*ORSERVICES;LOSSOFUSE,DATA,ORPROFITS;ORBUSINESSINTERRUPTION)*H
OWEVERCAUSEDANDONANYTHEORYOFLIABILITY,WHETHERINCONTRACT,STRICT*LIABILITY,ORTORT(INCLUDINGNEGLIGENCEOROTHERWISE)ARISINGINANYWAY*OUTOFTHEUSEOFTHISSOFTWARE,EVENIFADVISEDOFTHEPOSSIBILITYOF*SUCHDAMAGE.**$FreeBSD:src/sys/kern/kern_exec.c,v1.107.2.142002/04/2113:06:
23nectarExp$*/#include<sys/param.h>#include<sys/systm.h>#include<sys/sysproto.h>#include<sys/kernel.h>#include<sys/mount.h>#include<sys/filedesc.h>#include<sys/fcntl.h>#include<sys/acct.h>#include<sys/exec.h>#include<sys/imgact.h>#include<sys/imgact_elf.h>#in
clude<sys/wait.h>#include<sys/malloc.h>#include<sys/proc.h>#include<sys/signalvar.h>#include<sys/pioctl.h>#include<sys/namei.h>#include<sys/sysent.h>#include<sys/shm.h>#include<sys/sysctl.h>#include<sys/vnode.h>#include<sys/aio.h>#include<vm/vm.h>#include<vm/
vm_param.h>#include<sys/lock.h>#include<vm/pmap.h>#include<vm/vm_page.h>#include<vm/vm_map.h>#include<vm/vm_kern.h>#include<vm/vm_extern.h>#include<vm/vm_object.h>#include<vm/vm_pager.h>#include<sys/user.h>#include<machine/reg.h>MALLOC_DEFINE(M_PARGS,"proc-ar
gs","Processarguments");staticregister_t*exec_copyout_strings__P((structimage_params*));/*XXXThisshouldbevm_size_t.*/staticu_longps_strings=PS_STRINGS;SYSCTL_ULONG(_kern,KERN_PS_STRINGS,ps_strings,CTLFLAG_RD,&ps_strings,0,"");/*XXXThisshouldbevm_size_t.*/stat
icu_longusrstack=USRSTACK;SYSCTL_ULONG(_kern,KERN_USRSTACK,usrstack,CTLFLAG_RD,&usrstack,0,"");u_longps_arg_cache_limit=PAGE_SIZE/16;SYSCTL_LONG(_kern,OID_AUTO,ps_arg_cache_limit,CTLFLAG_RW,&ps_arg_cache_limit,0,"");intps_argsopen=1;SYSCTL_INT(_kern,OID_AUTO,
ps_argsopen,CTLFLAG_RW,&ps_argsopen,0,"");/**Eachoftheitemsisapointertoa`conststructexecsw',hencethe*doublepointerhere.*/staticconststructexecsw**execsw;#ifndef_SYS_SYSPROTO_H_structexecve_args{char*fname;char**argv;char**envv;};#endif/**execve()systemcall.*/
intexecve(p,uap)structproc*p;registerstructexecve_args*uap;{structnameidatand,*ndp;register_t*stack_base;interror,len,i;structimage_paramsimage_params,*imgp;structvattrattr;int(*img_first)__P((structimage_params*));imgp=&image_params;/**Locktheprocessandsetth
eP_INEXECflagtoindicatethat*itshouldbeleftaloneuntilwe'redonehere.Thisis*necessarytoavoidraceconditions-e.g.inptrace()-*thatmightallowalocalusertoillicitlyobtainelevated*privileges.*/p->p_flag|=P_INEXEC;/**Initializepartofthecommondata*/imgp->proc=p;imgp->uap
=uap;imgp->attr=&attr;imgp->argc=imgp->envc=0;imgp->argv0=NULL;imgp->entry_addr=0;imgp->vmspace_destroyed=0;imgp->interpreted=0;imgp->interpreter_name[0]='\0';imgp->auxargs=NULL;imgp->vp=NULL;imgp->firstpage=NULL;imgp->ps_strings=0;/**Allocatetemporarydemandz
eroedspaceforargumentand*environmentstrings*/imgp->stringbase=(char*)kmem_alloc_wait(exec_map,ARG_MAX+PAGE_SIZE);if(imgp->stringbase==NULL){error=ENOMEM;gotoexec_fail;}imgp->stringp=imgp->stringbase;imgp->stringspace=ARG_MAX;imgp->image_header=imgp->stringbas
e+ARG_MAX;/**Translatethefilename.namei()returnsavnodepointer*inni_vpamoungotherthings.*/ndp=&nd;NDINIT(ndp,LOOKUP,LOCKLEAF|FOLLOW|SAVENAME,UIO_USERSPACE,uap->fname,p);interpret:error=namei(ndp);if(error){kmem_free_wakeup(exec_map,(vm_offset_t)imgp->stringbas
e,ARG_MAX+PAGE_SIZE);gotoexec_fail;}imgp->vp=ndp->ni_vp;imgp->fname=uap->fname;/**Checkfilepermissions(also'opens'file)*/error=exec_check_permissions(imgp);if(error){VOP_UNLOCK(imgp->vp,0,p);gotoexec_fail_dealloc;}error=exec_map_first_page(imgp);VOP_UNLOCK(im
gp->vp,0,p);if(error)gotoexec_fail_dealloc;/**Ifthecurrentprocesshasaspecialimageactivatorit*wantstotryfirst,callit.Forexample,emulatingshell*scriptsdifferently.*/error=-1;if((img_first=imgp->proc->p_sysent->sv_imgact_try)!=NULL)error=img_first(imgp);/**Loopt
hroughthelistofimageactivators,callingeachone.*Anactivatorreturns-1ifthereisnomatch,0onsuccess,*andanerrorotherwise.*/for(i=0;error==-1&&execsw[i];++i){if(execsw[i]->ex_imgact==NULL||execsw[i]->ex_imgact==img_first){continue;}error=(*execsw[i]->ex_imgact)(img
p);}if(error){if(error==-1)error=ENOEXEC;gotoexec_fail_dealloc;}/**Specialinterpreteroperation,cleanupandloopuptotryto*activatetheinterpreter.*/if(imgp->interpreted){exec_unmap_first_page(imgp);/*freenamebufferandoldvnode*/NDFREE(ndp,NDF_ONLY_PNBUF);vrele(ndp
->ni_vp);/*setnewnametothatoftheinterpreter*/NDINIT(ndp,LOOKUP,LOCKLEAF|FOLLOW|SAVENAME,UIO_SYSSPACE,imgp->interpreter_name,p);gotointerpret;}/**Copyoutstrings(argsandenv)andinitializestackbase*/stack_base=exec_copyout_strings(imgp);p->p_vmspace->vm_minsaddr=
(char*)stack_base;/**Ifcustomstackfixuproutinepresentforthisprocess*letitdothestacksetup.*Elsestuffargumentcountasfirstitemonstack*/if(p->p_sysent->sv_fixup)(*p->p_sysent->sv_fixup)(&stack_base,imgp);elsesuword(--stack_base,imgp->argc);/**Forsecurityandotherr
easons,thefiledescriptortablecannot*besharedafteranexec.*/if(p->p_fd->fd_refcnt>1){structfiledesc*tmp;tmp=fdcopy(p);fdfree(p);p->p_fd=tmp;}/**Forsecurityandotherreasons,signalhandlerscannot*besharedafteranexec.Thenewprocesgetsacopyoftheold*handlers.Inexecsigs
(),thenewprocesswillhaveitssignals*reset.*/if(p->p_procsig->ps_refcnt>1){structprocsig*newprocsig;MALLOC(newprocsig,structprocsig*,sizeof(structprocsig),M_SUBPROC,M_WAITOK);bcopy(p->p_procsig,newprocsig,sizeof(*newprocsig));p->p_procsig->ps_refcnt--;p->p_proc
sig=newprocsig;p->p_procsig->ps_refcnt=1;if(p->p_sigacts==&p->p_addr->u_sigacts)panic("sharedprocsigbutprivatesigacts?");p->p_addr->u_sigacts=*p->p_sigacts;p->p_sigacts=&p->p_addr->u_sigacts;}/*Stopprofiling*/stopprofclock(p);/*closefilesonexec*/fdcloseexec(p
);/*resetcaughtsignals*/execsigs(p);/*namethisprocess-nameiexec(p,ndp)*/len=min(ndp->ni_cnd.cn_namelen,MAXCOMLEN);bcopy(ndp->ni_cnd.cn_nameptr,p->p_comm,len);p->p_comm[len]=0;/**markasexeced,wakeuptheprocessthatvforked(ifany)andtell*itthatitnowhasitsownresour
cesback*/p->p_flag|=P_EXEC;if(p->p_pptr&&(p->p_flag&P_PPWAIT)){p->p_flag&=~P_PPWAIT;wakeup((caddr_t)p->p_pptr);}/**Implementimagesetuid/setgid.**Don'thonorsetuid/setgidifthefilesystemprohibitsitorif*theprocessisbeingtraced.*/if((((attr.va_mode&VSUID)&&p->p_uc
red->cr_uid!=attr.va_uid)||((attr.va_mode&VSGID)&&p->p_ucred->cr_gid!=attr.va_gid))&&(imgp->vp->v_mount->mnt_flag&MNT_NOSUID)==0&&(p->p_flag&P_TRACED)==0){/**Turnoffsyscalltracingforset-idprograms,exceptfor*root.Recordanyset-idflagsfirsttomakesurethat*wedonot
regainanytracingduringapossibleblock.*/setsugid(p);if(p->p_tracep&&suser(p)){structvnode*vtmp;if((vtmp=p->p_tracep)!=NULL){p->p_tracep=NULL;p->p_traceflag=0;vrele(vtmp);}}/*Makesurefiledescriptors0..2areinuse.*/error=fdcheckstd(p);if(error!=0)gotoexec_fail_de
alloc;/**Setthenewcredentials.*/p->p_ucred=crcopy(p->p_ucred);if(attr.va_mode&VSUID)change_euid(p,attr.va_uid);if(attr.va_mode&VSGID)p->p_ucred->cr_gid=attr.va_gid;setugidsafety(p);}else{if(p->p_ucred->cr_uid==p->p_cred->p_ruid&&p->p_ucred->cr_gid==p->p_cred-
>p_rgid)p->p_flag&=~P_SUGID;}/**ImplementcorrectPOSIXsaved-idbehavior.*/p->p_cred->p_svuid=p->p_ucred->cr_uid;p->p_cred->p_svgid=p->p_ucred->cr_gid;/**Storethevpforuseinprocfs*/if(p->p_textvp)/*releaseoldreference*/vrele(p->p_textvp);VREF(ndp->ni_vp);p->p_tex
tvp=ndp->ni_vp;/**Notifyothersthatweexec'd,andcleartheP_INEXECflag*aswe'renowabonafidefreshly-execedprocess.*/KNOTE(&p->p_klist,NOTE_EXEC);p->p_flag&=~P_INEXEC;/**Iftracingtheprocess,traptodebuggersobreakpoints*canbesetbeforetheprogramexecutes.*/STOPEVENT(p,S
_EXEC,0);if(p->p_flag&P_TRACED)psignal(p,SIGTRAP);/*clear"forkbutnoexec"flag,aswe_are_execing*/p->p_acflag&=~AFORK;/*Setvaluespassedintotheprograminregisters.*/setregs(p,imgp->entry_addr,(u_long)(uintptr_t)stack_base,imgp->ps_strings);/*Freeanypreviousargumen
tcache*/if(p->p_args&&--p->p_args->ar_ref==0)FREE(p->p_args,M_PARGS);p->p_args=NULL;/*Cacheargumentsiftheyfitinsideourallowance*/i=imgp->endargs-imgp->stringbase;if(ps_arg_cache_limit>=i+sizeof(structpargs)){MALLOC(p->p_args,structpargs*,sizeof(structpargs)+i
,M_PARGS,M_WAITOK);p->p_args->ar_ref=1;p->p_args->ar_length=i;bcopy(imgp->stringbase,p->p_args->ar_args,i);}exec_fail_dealloc:/**freevariousallocatedresources*/if(imgp->firstpage)exec_unmap_first_page(imgp);if(imgp->stringbase!=NULL)kmem_free_wakeup(exec_map,
(vm_offset_t)imgp->stringbase,ARG_MAX+PAGE_SIZE);if(imgp->vp){NDFREE(ndp,NDF_ONLY_PNBUF);vrele(imgp->vp);}if(error==0)return(0);exec_fail:/*we'redonehere,clearP_INEXEC*/p->p_flag&=~P_INEXEC;if(imgp->vmspace_destroyed){/*sorry,nomoreprocessanymore.exitgraceful
ly*/exit1(p,W_EXITCODE(0,SIGABRT));/*NOTREACHED*/return(0);}else{return(error);}}intexec_map_first_page(imgp)structimage_params*imgp;{ints,rv,i;intinitial_pagein;vm_page_tma[VM_INITIAL_PAGEIN];vm_object_tobject;if(imgp->firstpage){exec_unmap_first_page(imgp);
}VOP_GETVOBJECT(imgp->vp,&object);s=splvm();ma[0]=vm_page_grab(object,0,VM_ALLOC_NORMAL|VM_ALLOC_RETRY);if((ma[0]->valid&VM_PAGE_BITS_ALL)!=VM_PAGE_BITS_ALL){initial_pagein=VM_INITIAL_PAGEIN;if(initial_pagein>object->size)initial_pagein=object->size;for(i=1;i
<initial_pagein;i++){if((ma[i]=vm_page_lookup(object,i))!=NULL){if((ma[i]->flags&PG_BUSY)||ma[i]->busy)break;if(ma[i]->valid)break;vm_page_busy(ma[i]);}else{ma[i]=vm_page_alloc(object,i,VM_ALLOC_NORMAL);if(ma[i]==NULL)break;}}initial_pagein=i;rv=vm_pager_get_
pages(object,ma,initial_pagein,0);ma[0]=vm_page_lookup(object,0);if((rv!=VM_PAGER_OK)||(ma[0]==NULL)||(ma[0]->valid==0)){if(ma[0]){vm_page_protect(ma[0],VM_PROT_NONE);vm_page_free(ma[0]);}splx(s);returnEIO;}}vm_page_wire(ma[0]);vm_page_wakeup(ma[0]);splx(s);p
map_kenter((vm_offset_t)imgp->image_header,VM_PAGE_TO_PHYS(ma[0]));imgp->firstpage=ma[0];return0;}voidexec_unmap_first_page(imgp)structimage_params*imgp;{if(imgp->firstpage){pmap_kremove((vm_offset_t)imgp->image_header);vm_page_unwire(imgp->firstpage,1);imgp-
>firstpage=NULL;}}/**Destroyoldaddressspace,andallocateanewstack*ThenewstackisonlySGROWSIZlargebecauseitisgrown*automaticallyintrap.c.*/intexec_new_vmspace(imgp)structimage_params*imgp;{interror;structvmspace*vmspace=imgp->proc->p_vmspace;vm_offset_tstack_add
r=USRSTACK-maxssiz;vm_map_tmap=&vmspace->vm_map;imgp->vmspace_destroyed=1;/**PreventapendingAIOfrommodifyingthenewaddressspace.*/aio_proc_rundown(imgp->proc);/**BlowawayentireprocessVM,ifaddressspacenotshared,*otherwise,createanewVMspacesothatotherthreadsare*
notdisrupted*/if(vmspace->vm_refcnt==1){if(vmspace->vm_shm)shmexit(imgp->proc);pmap_remove_pages(vmspace_pmap(vmspace),0,VM_MAXUSER_ADDRESS);vm_map_remove(map,0,VM_MAXUSER_ADDRESS);}else{vmspace_exec(imgp->proc);vmspace=imgp->proc->p_vmspace;map=&vmspace->vm_
map;}/*Allocateanewstack*/error=vm_map_stack(&vmspace->vm_map,stack_addr,(vm_size_t)maxssiz,VM_PROT_ALL,VM_PROT_ALL,0);if(error)return(error);/*vm_ssizeandvm_maxsaddraresomewhatantiquatedconceptsinthe*VM_STACKcase,buttheyarestillusedtomonitorthesizeofthe*proc
essstacksowecancheckthestackrlimit.*/vmspace->vm_ssize=sgrowsiz>>PAGE_SHIFT;vmspace->vm_maxsaddr=(char*)USRSTACK-maxssiz;return(0);}/**Copyoutargumentandenvironmentstringsfromtheoldprocess*addressspaceintothetemporarystringbuffer.*/intexec_extract_strings(img
p)structimage_params*imgp;{char**argv,**envv;char*argp,*envp;interror;size_tlength;/**extractargumentsfirst*/argv=imgp->uap->argv;if(argv){argp=(caddr_t)(intptr_t)fuword(argv);if(argp==(caddr_t)-1)return(EFAULT);if(argp)argv++;if(imgp->argv0)argp=imgp->argv0;
if(argp){do{if(argp==(caddr_t)-1)return(EFAULT);if((error=copyinstr(argp,imgp->stringp,imgp->stringspace,&length))){if(error==ENAMETOOLONG)return(E2BIG);return(error);}imgp->stringspace-=length;imgp->stringp+=length;imgp->argc++;}while((argp=(caddr_t)(intptr_
t)fuword(argv++)));}}imgp->endargs=imgp->stringp;/**extractenvironmentstrings*/envv=imgp->uap->envv;if(envv){while((envp=(caddr_t)(intptr_t)fuword(envv++))){if(envp==(caddr_t)-1)return(EFAULT);if((error=copyinstr(envp,imgp->stringp,imgp->stringspace,&length))
){if(error==ENAMETOOLONG)return(E2BIG);return(error);}imgp->stringspace-=length;imgp->stringp+=length;imgp->envc++;}}return(0);}/**Copystringsouttothenewprocessaddressspace,constructing*newargandenvvectortables.Returnapointertothebase*sothatitcanbeusedasthein
itialstackpointer.*/register_t*exec_copyout_strings(imgp)structimage_params*imgp;{intargc,envc;char**vectp;char*stringp,*destp;register_t*stack_base;structps_strings*arginfo;intszsigcode;/**Calculatestringbaseandvectortablepointers.*Alsodealwithsignaltrampoli
necodeforthisexectype.*/arginfo=(structps_strings*)PS_STRINGS;szsigcode=*(imgp->proc->p_sysent->sv_szsigcode);destp=(caddr_t)arginfo-szsigcode-SPARE_USRSPACE-roundup((ARG_MAX-imgp->stringspace),sizeof(char*));/**installsigcode*/if(szsigcode)copyout(imgp->proc
->p_sysent->sv_sigcode,((caddr_t)arginfo-szsigcode),szsigcode);/**Ifwehaveavalidauxargsptr,preparesomeroom*onthestack.*/if(imgp->auxargs)/**The'+2'isforthenullpointersattheendofeachofthe*argandenvvectorsets,and'AT_COUNT*2'isroomforthe*ELFAuxargsdata.*/vectp=(
char**)(destp-(imgp->argc+imgp->envc+2+AT_COUNT*2)*sizeof(char*));else/**The'+2'isforthenullpointersattheendofeachofthe*argandenvvectorsets*/vectp=(char**)(destp-(imgp->argc+imgp->envc+2)*sizeof(char*));/**vectpalsobecomesourinitialstackbase*/stack_base=(regi
ster_t*)vectp;stringp=imgp->stringbase;argc=imgp->argc;envc=imgp->envc;/**Copyoutstrings-argumentsandenvironment.*/copyout(stringp,destp,ARG_MAX-imgp->stringspace);/**Fillin"ps_strings"structforps,w,etc.*/suword(&arginfo->ps_argvstr,(long)(intptr_t)vectp);suw
ord(&arginfo->ps_nargvstr,argc);/**Fillinargumentportionofvectortable.*/for(;argc>0;--argc){suword(vectp++,(long)(intptr_t)destp);while(*stringp++!=0)destp++;destp++;}/*anullvectortablepointerseperatestheargp'sfromtheenvp's*/suword(vectp++,0);suword(&arginfo-
>ps_envstr,(long)(intptr_t)vectp);suword(&arginfo->ps_nenvstr,envc);/**Fillinenvironmentportionofvectortable.*/for(;envc>0;--envc){suword(vectp++,(long)(intptr_t)destp);while(*stringp++!=0)destp++;destp++;}/*endofvectortableisanullpointer*/suword(vectp,0);ret
urn(stack_base);}/**Checkpermissionsoffiletoexecute.*Return0forsuccessorerrorcodeonfailure.*/intexec_check_permissions(imgp)structimage_params*imgp;{structproc*p=imgp->proc;structvnode*vp=imgp->vp;structvattr*attr=imgp->attr;interror;/*Getfileattributes*/erro
r=VOP_GETATTR(vp,attr,p->p_ucred,p);if(error)return(error);/**1)Checkiffileexecutionisdisabledforthefilesystemthatthis*fileresideson.*2)Insurethatatleastoneexecutebitison-otherwiseroot*willalwayssucceed,andwedon'twanttohappenunlessthe*filereallyisexecutable.*

Hosted by uCoz