Ejemplo n.º 1
0
PerDomain_st *Binder_InitDomain(DomainMgr_st *dm_st, 
				dcb_ro_t *rop, dcb_rw_t *rwp,
				StretchAllocator_clp salloc)
{
    Client_t	*bcl;
    Server_t    *bsv;
    PerDomain_st  *bst;
    IDCStubs_Info stubinfo;
  
    /* Allocate bsv, bcl and bst */
    bst = ROP_TO_PDS(rop);
    memset(bst, 0, sizeof(*bst));
    bsv = &bst->s;
    bcl = (Client_t *)&(rwp->binder_rw);
    
    TRC (eprintf("Binder_NewDomain: state at %x\n", bst));

#if 0
    /* Block until the boot domains are ready */
/* XXX XXX see comment in DomainMgr.c about Intel and ARM */

    TRC(eprintf("Dom ID = %qx, boot_regs = %qx\n", rop->id, 
		EC_READ(dm_st->boot_regs)));

#ifdef SRCIT
#undef DOM_USER
#define DOM_USER DOM_SERIAL
#endif
#ifndef __ALPHA__
    EC_AWAIT (dm_st->boot_regs,
	      ((rop->id < DOM_USER) ? rop->id : DOM_USER)&0xffffffff);
#else
    EC_AWAIT (dm_st->boot_regs,
	      (rop->id < DOM_USER) ? rop->id : DOM_USER);
#endif
#endif /* 0 */
    
    /* Create IDC buffers for the new domain's channel to the binder */
    bst->args    = STR_NEW_SALLOC(dm_st->sysalloc, FRAME_SIZE);
    bst->results = STR_NEW_SALLOC(dm_st->sysalloc, FRAME_SIZE);
    
    /* Map the stretches. */
    SALLOC_SETPROT(dm_st->sysalloc, bst->results, rop->pdid, 
		   SET_ELEM(Stretch_Right_Read) );
    SALLOC_SETPROT(dm_st->sysalloc, bst->args, rop->pdid, 
		   SET_ELEM(Stretch_Right_Read)|
		   SET_ELEM(Stretch_Right_Write));

    /*
     * Next, initialise as much of the Client structure as we can at
     * this stage, given that we're in the Binder's domain and the
     * client won't have a threads package anyway. The rest of this
     * state will be initialised when the client domain calls Bind on 
     * the Binder offer.  Compare with lib/nemesis/IDC/ShmTransport.c:
     * notice that we have to init the state to what the methods in
     * Shm[Client|Server]Binding_op are expecting.
     */


    stubinfo = NAME_FIND (IDC_CONTEXT">Binder", IDCStubs_Info);
    
    TRC(eprintf("Binder_NewDomain: creating Binder client IDC state.\n"));
    {
	Binder_clp client_cl = 
	    NARROW ((Type_Any *)(&stubinfo->surr), Binder_clp);

	CL_INIT(bcl->client_cl,  (addr_t) client_cl->op,  bcl);
	CL_INIT(bcl->binding_cl, &BinderClientBinding_op, bcl);
    }
    ANY_INIT (&bcl->cs.srgt, Binder_clp, &bcl->client_cl);
    bcl->cs.binding = &bcl->binding_cl;
    bcl->cs.marshal = dm_st->shmidc;

    /* The client ShmConnection_t immediately follows the Client_t 
       (aka bcl) in the binder_rw. */
    bcl->conn      = (ShmConnection_t *)(bcl+1);

    if(stubinfo->clnt) {
	/* Let the stubs set up any required run-time state */
	IDCClientStubs$InitState(stubinfo->clnt, &bcl->cs);
    }

    /* Now setup the client side ShmConnection */

    /* XXX Leave mu_init to user */

    /* Transmit buffer rec */
    bcl->conn->txbuf.base  = STR_RANGE(bst->args, &bcl->conn->txsize);
    bcl->conn->txbuf.ptr   = bcl->conn->txbuf.base;
    bcl->conn->txbuf.space = bcl->conn->txsize;
    bcl->conn->txbuf.heap  = NULL;
    
    /* Receive buffer rec */
    bcl->conn->rxbuf.base  = STR_RANGE(bst->results, &bcl->conn->rxsize);
    bcl->conn->rxbuf.ptr   = bcl->conn->rxbuf.base;
    bcl->conn->rxbuf.space = bcl->conn->rxsize;
    bcl->conn->rxbuf.heap  = NULL;
    
    /* Event counts will be filled in by the domain */
    bcl->conn->evs.tx	  = NULL_EVENT;
    bcl->conn->evs.rx     = NULL_EVENT;
    
    /* We can call the new domain's VP interface to get end-points */
    bcl->conn->eps.tx	  = VP$AllocChannel (&rop->vp_cl);
    bcl->conn->eps.rx	  = VP$AllocChannel (&rop->vp_cl);
  
    bcl->conn->call       = 0;

    bcl->conn->dom        = dm_st->dm_dom->id;
    /* XXX SMH: for some reason we don't know our own pdom. Hoho. */
    bcl->conn->pdid       = NULL_PDID;

    /* bcl->offer is not used normally; in BINDER_MUX it is inited below */

    /*
     * Initialise the server idc state.
     */

    /* First we setup the server connection state */
    MU_INIT (&bst->sconn.mu); /* XXX - unused; entry SYNC on server */
  
    bst->sconn.txbuf      = bcl->conn->rxbuf;
    bst->sconn.txsize     = bst->sconn.txbuf.space;
    
    bst->sconn.rxbuf      = bcl->conn->txbuf;
    bst->sconn.rxbuf.heap = Pvs(heap); /* XXX */
    bst->sconn.rxsize     = bst->sconn.rxbuf.space;
  
    bst->sconn.call	  = 0;
    
    bst->sconn.eps.tx	  = Events$AllocChannel(Pvs(evs));
    bst->sconn.eps.rx	  = Events$AllocChannel(Pvs(evs));
    
    bst->sconn.evs.tx     = EC_NEW();
    bst->sconn.evs.rx     = NULL_EVENT; /* we use "Entry" synch. on server */

    bst->sconn.dom        = rop->id;
    bst->sconn.pdid       = rop->pdid; 


#ifdef CONFIG_BINDER_MUX
    /* Initialise the (de)muxing server. */
    TRC(eprintf("Binder_NewDomain: creating Binder MuxIDC server state.\n"));

    CL_INIT (bst->mux.cntrl_cl, &MuxStubs_ms, &bst->mux);
    CL_INIT (bst->mux.cntrl_cl, &MuxStubs_ms, &bst->mux);

    /* We use the connection state we setup above */
    bst->mux.conn = &bst->sconn;
    bst->mux.ss.service = NULL; /* There's no specific service */
    bst->mux.ss.binding = &bsv->binding_cl;
    
#endif
    TRC(eprintf("Binder_NewDomain: creating Binder IDC server state.\n"));
    bsv->ss.service = &bst->binder;
    bsv->ss.binding = &bsv->binding_cl;
    bsv->ss.marshal = dm_st->shmidc;


    CL_INIT (bsv->cntrl_cl,    stubinfo->stub->op,  bsv);
    CL_INIT (bsv->binding_cl, &ShmServerBinding_op, bsv);
    
    /* We use (or share!) the connection state we setup above */
    bsv->conn = &bst->sconn;

    /* Hijack offer field for PerDomain_st */
    bsv->offer            = (Offer_t *) bst;
    

    /* XXX PRB Moved this before the Plumber_Connect since otherwise
       Events$Attach does an ntsc_send causing the new domain to be woken
       up! */
    Events$Attach (Pvs(evs), bsv->conn->evs.tx, 
		   bsv->conn->eps.tx,  Channel_EPType_TX);
    
    /* Connect the event channels */
    Plumber$Connect (Plumber, dm_st->dm_dom, rop, 
		     bsv->conn->eps.tx, 
		     bcl->conn->eps.rx);
    Plumber$Connect (Plumber, rop, dm_st->dm_dom, 
		     bcl->conn->eps.tx, 
		     bsv->conn->eps.rx);

#ifdef CONFIG_BINDER_MUX
    /* Register the binder server with the demuxing server */
    bcl->offer = (Offer_t *)RegisterServer(&bst->mux, &bsv->cntrl_cl);
    
    if(bcl->offer == (Offer_t *)-1) {
	eprintf("Binder_NewDomain: addition of binder to mux svr failed!\n");
	ntsc_halt();
    }

#endif

    /* Initialise the rest of the per-domain state */
    TRC(eprintf("Binder_NewDomain: creating Binder per-domain state.\n"));
    bst->rop      = rop;
    bst->rwp      = rwp;
    bst->dm_st    = dm_st;

    /* refCount starts at 1, to allow for the following references to
       the rop/rwp to be held (update as necessary):
       
       1: the server binding (possibly muxed)
       
       */
       
    bst->refCount = 1;
    bst->callback = NULL;
    CL_INIT (bst->binder, &binder_ops, bst);

    /* The offer closure is a special hand crafted one */
    CL_INIT (bst->offer_cl, &offer_ops, bcl);

    rop->binder_offer = &bst->offer_cl;
    
#define panic(format, args...) \
do { eprintf(format, ## args); ntsc_halt(); } while(0)

    TRC(eprintf("Binder_NewDomain: registering entry.\n"));
    TRY {
#ifdef CONFIG_BINDER_MUX
	Entry$Bind (Pvs(entry), bst->mux.conn->eps.rx, &(bst->mux.cntrl_cl));
#else
	Entry$Bind (Pvs(entry), bsv->conn->eps.rx, &bsv->cntrl_cl );
#endif
    } CATCH_Entry$TooManyChannels() {
	eprintf("Too many channels registering Binder\n");
    } ENDTRY;

    TRC(eprintf("Binder_NewDomain: done.\n"));
    return bst;
}
#ifdef EAP_TLS_OPENSSL
	{ STR(opensc_engine_path) },
	{ STR(pkcs11_engine_path) },
	{ STR(pkcs11_module_path) },
#endif /* EAP_TLS_OPENSSL */
	{ STR(driver_param) },
	{ INT(dot11RSNAConfigPMKLifetime) },
	{ INT(dot11RSNAConfigPMKReauthThreshold) },
	{ INT(dot11RSNAConfigSATimeout) },
#ifndef CONFIG_NO_CONFIG_WRITE
	{ INT(update_config) },
#endif /* CONFIG_NO_CONFIG_WRITE */
	{ FUNC_NO_VAR(load_dynamic_eap) },
#ifdef CONFIG_WPS
	{ FUNC(uuid) },
	{ STR_RANGE(device_name, 0, 32) },
	{ STR_RANGE(manufacturer, 0, 64) },
	{ STR_RANGE(model_name, 0, 32) },
	{ STR_RANGE(model_number, 0, 32) },
	{ STR_RANGE(serial_number, 0, 32) },
	{ STR(device_type) },
	{ FUNC(os_version) },
	{ INT_RANGE(wps_cred_processing, 0, 2) },
#endif /* CONFIG_WPS */
	{ FUNC(country) }
};

#undef FUNC
#undef _INT
#undef INT
#undef INT_RANGE
Ejemplo n.º 3
0
static IDCOffer_clp Mount_m(MountLocal_cl     *self, 
			    IDCOffer_clp       drive,
			    uint32_t           partition,
			    MountLocal_Options options, 
			    Context_clp        settings)
{
    IDCOffer_clp  res;
    ext2fs_st	 *st;
    Type_Any      any;
    Heap_clp      heap;
    struct inode *root            = NULL;
    uint32_t      blockcache_size = 1024*128; /* Size of blockcache in bytes */
    CSClientStubMod_cl *stubmod_clp; 


    TRC(printf("ext2fs: mount %d from %p\n", partition, drive));
    /* It's probably a good idea to have a separate heap for the filesystem.
       For now let's just use Pvs(heap), but eventually create a stretch
       of our own. */

    heap = Pvs(heap);

    if(!(st = Heap$Malloc(heap, sizeof(*st)))) {
	fprintf(stderr, "ext2fs: cannot allocate state.\n");
	RAISE_MountLocal$Failure();
    }

    /* Where is this declared? */
    bzero(st, sizeof(*st));

    /* Fill in the fields that we can initialise without accessing the
       filesystem */
    st->heap = heap;

    st->entrymod     = NAME_FIND("modules>EntryMod", EntryMod_clp);
    st->shmtransport = NAME_FIND("modules>ShmTransport", IDCTransport_clp);
    st->csidc        = NAME_FIND("modules>CSIDCTransport", CSIDCTransport_clp);


    st->client.entry = Pvs(entry);
    /* It's not clearn how many entries we are going to require yet
       We probably want separate ones for the USDCallback and the
       FSClient offers. We need to arrange that the entry threads die
       properly when the FS is unmounted. */


    /* Interpret mount flags */
    st->fs.readonly = SET_IN(options,MountLocal_Option_ReadOnly);
    st->fs.debug    = SET_IN(options,MountLocal_Option_Debug);


    /* Place the drive in the state. */
    st->disk.partition     = partition;
    st->disk.drive_offer   = drive;
    st->disk.drive_binding = IDCOffer$Bind(drive, Pvs(gkpr), &any);
    st->disk.usddrive      = NARROW(&any, USDDrive_clp);

 
    TRC(printf("ext2fs: state at [%p, %p]\n",st, (void *)st + sizeof(*st)));
    DBO(printf("ext2fs: debugging output is switched on\n"));

    /* Connect to the disk */
    init_usd(st);

    /* We need a stretch shared between us and the USD to allow us to read
       and write metadata. We'll use this stretch as a cache of blocks read
       from the disk. Because we won't know the blocksize until we have
       managed to read the superblock, we'd better make this buffer a
       multiple of 8k long (8k is currently the maximum blocksize). */

    st->cache.str = Gatekeeper$GetStretch(Pvs(gkpr), IDCOffer$PDID(drive), 
					  blockcache_size, 
					  SET_ELEM(Stretch_Right_Read) |
					  SET_ELEM(Stretch_Right_Write), 
					  PAGE_WIDTH, PAGE_WIDTH);
    st->cache.buf = STR_RANGE(st->cache.str, &st->cache.size);

    TRC(printf("ext2fs: buf is %d bytes at %p\n", st->cache.size,
	       st->cache.buf));
    if (st->cache.size < blockcache_size) {
	printf("ext2fs: warning: couldn't allocate a large blockcache\n");
    }

    /* Now we can get at the disk. Read the superblock, and calculate
       constants from it. */
    if (!read_superblock(st)) {
	printf("ext2fs: couldn't read superblock\n");
	shutdown_usd(st);
	RAISE_MountLocal$BadFS(MountLocal_Problem_BadSuperblock);
    }

    /* XXX should sanity check filesystem size with partition size */
    TRC(printf("ext2fs: filesystem size %d blocks (%d phys)\n"
	   "	    partition size %d blocks (%d phys)\n",
	   st->superblock->s_blocks_count,
	   PHYS_BLKS(st, st->superblock->s_blocks_count),
	   LOGICAL_BLKS(st, st->disk.partition_size),
	   st->disk.partition_size));
    if (st->disk.partition_size < 
	PHYS_BLKS(st, st->superblock->s_blocks_count)) {
	printf("WARNING - filesystem is larger than partition **********\n");
	/* XXX should probably give up now */
    }

    /* Now that we know the logical block size we can initialise the block
       cache */
    init_block_cache(st);

    /* From this point on, all access to the filesystem should be done
       through the block cache. DON'T call logical_read, call bread
       instead. Remember to free blocks once you're finished with them. */

    init_groups(st);

    if(!init_inodes(st)) {
	fprintf(stderr, "ext2fs: failed to initialise inode cache.\n");
	shutdown_usd(st);
	RAISE_MountLocal$Failure();
    }

    /* Checking this probably isn't a bad idea, but let's wait until later */

    /* Ok, now we are capable of reading the root inode (I hope!) */
    TRC(printf("ext2fs: checking root inode.\n"));
    root = get_inode(st, EXT2_ROOT_INO);
    if(!root) {
	fprintf(stderr, "ext2fs: failed to read root inode.\n");
	shutdown_usd(st);
	RAISE_MountLocal$BadFS(MountLocal_Problem_BadRoot);
    }
    
    if(!S_ISDIR(root->i_mode)) {
	fprintf(stderr, "ext2fs: urk!\n"
		"	 inode %d does not refer to a directory\n", 
		EXT2_ROOT_INO);
	shutdown_usd(st);
	RAISE_MountLocal$BadFS(MountLocal_Problem_BadRoot);
    }

    release_inode(st, root);

    /* *thinks* should probably do something about deallocating state
       if we fail, too. */

    /* Initialise the list of clients */
    LINK_INIT(&st->client.clients);
    /* We create a server for the local domain; it lives in the head
       of the list of clients. The call to CSIDCTransport$Offer() will
       set up client-side stubs for this domain and put them in the
       object table. */
    create_client(st, &st->client.clients, NULL);

    /* Now we do all the export stuff */
    CL_INIT(st->client.callback, &client_callback_ms, st);
    ANY_INIT(&any, Ext2_clp, &st->client.clients.cl);
    stubmod_clp = Heap$Malloc(st->heap, sizeof(*stubmod_clp)); 
    CLP_INIT(stubmod_clp, &stubmod_ms, NULL);
    res = CSIDCTransport$Offer (
	st->csidc, &any, FSClient_clp__code, stubmod_clp,
	&st->client.callback, /* XXX produces a warning */
	st->heap, Pvs(gkpr), st->client.entry, &st->client.service);

    TRC(printf("ext2fs: offer at %p\n",res));

    return res;
}
Ejemplo n.º 4
0
 * offset to the field containing the length of the configuration variable.
 * .param3 and .param4 can be used to mark the allowed range (length for STR
 * and value for INT).
 *
 * For each configuration line in wpa_supplicant.conf, the parser goes through
 * this table and select the entry that matches with the field name. The parser
 * function (.parser) is then called to parse the actual value of the field.
 *
 * This kind of mechanism makes it easy to add new configuration parameters,
 * since only one line needs to be added into this table and into the
 * struct wpa_ssid definition if the new variable is either a string or
 * integer. More complex types will need to use their own parser and writer
 * functions.
 */
static const struct parse_data ssid_fields[] = {
	{ STR_RANGE(ssid, 0, MAX_SSID_LEN) },
	{ INT_RANGE(scan_ssid, 0, 1) },
	{ FUNC(bssid) },
	{ FUNC_KEY(psk) },
	{ FUNC(proto) },
	{ FUNC(key_mgmt) },
	{ FUNC(pairwise) },
	{ FUNC(group) },
	{ FUNC(auth_alg) },
#ifdef IEEE8021X_EAPOL
	{ FUNC(eap) },
	{ STR_LENe(identity) },
	{ STR_LENe(anonymous_identity) },
	{ FUNC_KEY(password) },
	{ STRe(ca_cert) },
	{ STRe(ca_path) },
Ejemplo n.º 5
0
void boot(Rd_clp rd, bool_t verbose, string_t cmdline)
{
#ifdef INTEL
    uint32_t NOCLOBBER length;
    uint32_t start, slen;
    uint8_t * NOCLOBBER buff;
    Stretch_clp stretch;
    
    length=Rd$Length(rd);

    /* Read the header of the file to try to work out what it is */

    buff=Heap$Malloc(Pvs(heap), 512);
    Rd$GetChars(rd, buff, 512);

    if (buff[510]==0x55 && buff[511]==0xaa) {
	if (verbose) printf(
	    "Traditional bootable Nemesis image with %d setup blocks.\n",
	    buff[497]);
	start=512*(buff[497]+1);
    } else if (buff[0]==0xfa && buff[1]==0xfc ) {
	if (verbose) printf("Hmm... looks like a bare Nemesis image.\n");
	start=0;
    } else {
	printf("This does not look like a Nemesis image.\n");
	return;
    }

    Heap$Free(Pvs(heap), buff);

    length-=start;

    /* Get a stretch of the appropriate size */
    stretch = STR_NEW(length);
    buff    = STR_RANGE(stretch, &slen);

    /* Read the image */
    Rd$Seek(rd, start);
#define PKTSIZE 8192
    {
	char *bufptr = buff;
	int n;
	int togo = length;

	while (togo) {
	    n = Rd$GetChars(rd, bufptr, PKTSIZE);
	    togo -= n;
	    bufptr += n;
	    printf("."); fflush(stdout);
	} 
    }
    printf("\n");

    /* now shut down any Ethernet cards, so we don't get anything DMAed
     * over the image while it boots */
    /* XXX AND This is a privileged operation.  And we shouldn't really
     * dive at the Netif interface directly. */
    /* XXX SDE we might be in a UDPnash at the moment, so there should be
     * NO OUTPUT after this point */
    verbose=False;
    {
	Type_Any any;
	Netif_clp netif;
	const char * const downlist[] = {"de4x5-0",
					 "de4x5-1",
					 /* don't need 3c509, since no DMA */
					 "eth0",
					 NULL};
	/* HACK: need to lose the "const", since Context$Get() doesn't
         * have it. */
	char ** NOCLOBBER eth = (char**)downlist;
	char buf[32];

	while(*eth)
	{
	    sprintf(buf, "dev>%s>control", *eth);

	    if (Context$Get(Pvs(root), buf, &any))
	    {
		if (verbose)
		{
		    printf("Shutting down %s... ", *eth);
		    fflush(stdout);
		}

		TRY {
		    netif = IDC_OPEN(buf, Netif_clp);
		} CATCH_ALL {
		    if (verbose)
			printf("failed: caught exception\n");
		    netif = NULL;
		} ENDTRY;

		if (netif && !Netif$Down(netif) && verbose)
		{
		    printf("failed: Netif$Down() error\n");
		    netif = NULL;
		}

		if (netif && verbose)
		    printf("ok\n");
	    }

	    eth++;
	}
    }

    if (verbose)
    {
	printf("Starting image...\n");
	PAUSE(MILLISECS(1000));
    }

    /* Chain to the new image */
    ENTER_KERNEL_CRITICAL_SECTION();
    ntsc_chain(buff, length, cmdline);
    LEAVE_KERNEL_CRITICAL_SECTION();

    printf("Bogosity: the new image was not started\n");
    printf("bogosity: (n) (slang); the degree of unusallness and brokenness of some item or event\n");
#else
    printf("Boot chaining not supported\n");
#endif
}
Ejemplo n.º 6
0
/*
** The Nemesis domain is special - it gets passed 
** only half a comment
** and its Pvs are special.
*/
void Go(Activation_cl *self, 
	VP_clp vp /* IN */,
	Activation_Reason ar /* IN */ ) 
{
    kernel_st      *kst = (kernel_st *)self->st;
    dcb_rw_t       *rwp = vp->st;
    dcb_ro_t       *rop = DCB_RW2RO(rwp);
    ActivationF_cl *actf;

    TRY {

#ifdef __IX86__
	ntsc_entkern(); /* There is an NTSC hack that prevents this
			   from being undone. */
#endif /* __IX86__ */

	/* Direct all output from Nemesis domain through NTSC (or,
	   on Alpha, direct to the hardware) */
	Pvs(err)=Pvs(out)=Pvs(console)=&triv_wr_cl;

	TRC(printf("Nemesis domain entered.\n")); 
	TRC(printf(" + DCBRO at %p\n", rop));
	TRC(printf("      psmask=%qx\n", rop->psmask));
#ifdef __ALPHA__
	TRC(printf("      ps=%qx\n", ntsc_rdps()));
#endif
	TRC(printf(" + DCBRW at %p\n", rwp));
	TRC(printf(" + Activation clp at %p\n", self));
	TRC(printf(" + VP clp at %p\n", vp));
	TRC(printf(" + activationsOn=%d\n", VP$ActivationMode(vp)));
	TRC(printf(" + Activation Reason %d\n", ar));
	TRC(printf(" + PVS        = %p\n", PVS()));
	
	TRC(DUMP_PVS());
	
	{
	    StretchAllocator_clp salloc;
	    StretchAllocator_SizeSeq *sizes;
	    StretchAllocator_StretchSeq *stretches;
	    ThreadsPackage_Stack protoStack;
	    Stretch_clp userStretch;
	    BootDomain_Info *nem_info;
	    ThreadsPackage_clp tp;
	    ThreadF_clp thdf;
#ifdef CONFIG_MEMSYS_EXPT
	    SDriverMod_cl *sdmod;
	    StretchTbl_cl *strtab;
#define MAX_DESCS 5
	    Mem_PMemDesc pmem[MAX_DESCS + 1];
	    Type_Any fany; 
	    flink_t *lk;
	    flist_t *cur; 
	    int i = 0; 

	    /* Create a new stretch driver (physical one for now) */
	    TRC(printf("Creating initial stretch driver and stretch tab.\n"));
	    sdmod  = NAME_FIND("modules>SDriverMod", SDriverMod_clp);
	    strtab = NAME_FIND("sys>StretchTable", StretchTbl_clp);

	    /* Grab the pmem which has been allocated for us by dmgr */
	    for(lk = rop->finfo.next; lk != &rop->finfo; lk = lk->next) {
		cur = (flist_t *)lk; 
		pmem[i].start_addr  = cur->base; 
		pmem[i].frame_width = cur->fwidth; 
		pmem[i].nframes     = 
		    cur->npf >> (cur->fwidth - FRAME_WIDTH); 
		pmem[i].attr        = 0;
		if(++i == MAX_DESCS) 
		    break;
	    }
	    pmem[i].nframes = 0; /* terminate array */

	    ANY_INIT(&fany, Frames_clp, rop->frames);
	    Pvs(sdriver) = SDriverMod$NewPhysical(sdmod, vp, Pvs(heap), 
						  strtab, pmem, &fany);
#endif

	    /* Add our personal frames closure into the sys context */
	    /* XXX SDE: I'm not convinced that this is a good idea; the
	       Nemesis domain (and all other domains) should have a bit of
	       private namespace for this. I was bitten once by a domain
	       using the Nemesis domain's Frames closure directly because
	       its own hadn't overridden it in the namespace. */
	    CX_ADD("sys>Frames", rop->frames, Frames_clp);
	    
	    TRC(eprintf (" + Finding Nemesis StretchAllocator\n"));
	    salloc = NAME_FIND("sys>StretchAllocator", StretchAllocator_clp);
	    TRC(eprintf (" + StretchAlloc = %p\n", salloc));
	    
	    TRC(eprintf (" + Finding parameters\n"));
	    nem_info= NAME_FIND("progs>Nemesis", BootDomain_InfoP);

	    sizes = SEQ_NEW(StretchAllocator_SizeSeq, 3, Pvs(heap));
	    SEQ_ELEM(sizes, 0) = FRAME_SIZE; /* for guard page */
	    SEQ_ELEM(sizes, 1) = nem_info->stackWords*sizeof(word_t);
	    SEQ_ELEM(sizes, 2) = nem_info->pHeapWords*sizeof(word_t);
	    
	    TRC(eprintf (" + Allocating Stretches\n"));
	    stretches = STR_NEWLIST_SALLOC(salloc, sizes);
	    
	    protoStack.guard   = SEQ_ELEM(stretches, 0);
	    protoStack.stretch = SEQ_ELEM(stretches, 1);
	    userStretch        = SEQ_ELEM(stretches, 2);
	    
	    TRC(eprintf (" + Freeing SEQs\n"));
	    SEQ_FREE(sizes);
	    SEQ_FREE(stretches);


#ifdef CONFIG_MEMSYS_EXPT
	    /* Bind and map the stack */
	    {
		Stretch_Size sz; 
		addr_t stackva; 
		int npages; 

		TRC(printf("+ Binding and mapping stack.\n"));
		stackva = STR_RANGE(protoStack.stretch, &sz);
		npages  = sz >> PAGE_WIDTH;
		while(npages--) {
		    StretchDriver$Map(Pvs(sdriver), 
				      protoStack.stretch, stackva);
		    stackva += PAGE_SIZE;
		}

	    }
#endif

	    TRC(printf(" + Setting protection\n"));
	    SALLOC_SETGLOBAL(salloc, protoStack.guard, 0);
	    
	    /* XXX PRB Global write is a bit dodgy to say the least! */
	    SALLOC_SETGLOBAL(salloc, protoStack.stretch, 
			     SET_ELEM(Stretch_Right_Read)    |
			     SET_ELEM(Stretch_Right_Write)   );
	    SALLOC_SETGLOBAL(salloc, userStretch,
			     SET_ELEM(Stretch_Right_Read)    |
			     SET_ELEM(Stretch_Right_Write)   );

	    TRC(printf(" + Finding ThreadsPackage\n"));
	    tp = NAME_FIND("modules>NonPreemptiveThreads",ThreadsPackage_clp); 
	    TRC(printf(" + ThreadsPackage = %p\n", tp));
	    if(!(thdf = ThreadsPackage$New(tp, (addr_t)&NemesisMainThread,
					   (addr_t)kst, &protoStack,
					   userStretch,
					   nem_info->stackWords*sizeof(word_t), 
					   (Pervasives_Init *)PVS(), &actf))) {
		TRC(printf("Nemesis: can't get threads.\n"));
		ntsc_halt();
	    } 
	    /* Set ourselves up to handle memory faults */
	    
	    /* first get/set an event channel for fault notification */
	    rwp->mm_ep = VP$AllocChannel(Pvs(vp));
#if defined(CONFIG_MEMSYS_STD) || defined(CONFIG_MEMSYS_EXPT)
	    {
		MMNotifyMod_cl *mmnmod;
		MMNotify_cl *mmnfy;
		StretchTbl_clp strtable; 

#ifdef CONFIG_MEMSYS_EXPT
		/* get the stretch table */
		TRC(eprintf (" + Finding StretchTable\n"));
		strtable = NAME_FIND("sys>StretchTable", StretchTbl_clp);
#else
		strtable = (StretchTbl_cl *)NULL;
#endif
		mmnmod = NAME_FIND("modules>MMNotifyMod", MMNotifyMod_clp);
		mmnfy = MMNotifyMod$New(mmnmod, vp, Pvs(heap), strtable); 
		CX_ADD("sys>MMNotify", mmnfy, MMNotify_clp);
		ActivationF$Attach(actf, (ChannelNotify_cl *)mmnfy, 
				   rwp->mm_ep);
		
	    }
#endif      /* for non expt, we do all this with a mmentry in main thd */
	}
	TRC(printf(" + yielding to main thread.\n"));

	VP$ActivationsOn(Pvs(vp));
	VP$Yield(Pvs(vp));
	
    } CATCH_Context$NotFound(name) {
	printf("Caught execption Context$NotFound(%s)\n", name);
    } CATCH_ALL {
	printf("Caught exception %s\n", exn_ctx.cur_exception);
    } ENDTRY;
    
    /* XXX we are not happy here; for now, just halt. */
    printf("\nNemesis: Much bogosity!!! halting.\n");
    ntsc_dbgstop();
}
Ejemplo n.º 7
0
void Main (Closure_clp self)
{
    FB_st *st;
    IOEntryMod_clp emod;

    int i;
    
    TRC(printf("FB/MGA: entered\n"));
 
    st = (FB_st *)Heap$Malloc(Pvs(heap), 
			      sizeof(FB_st));
    if (st == NULL) 
	RAISE_Heap$NoMemory();

    memset(st, 0, sizeof(FB_st));

    CL_INIT(st->cl, &fb_ms, st);


    /* Before we do anything, see if we can find a framebuffer device
       that we understand. */

    st->cardbase = (Pixel_t *) MGAInit(FB_WIDTH, FB_HEIGHT, FB_DEPTH, FB_MODE);

    TRC(printf("st->cardbase = %p\n", st->cardbase));

    if(!st->cardbase) {
	fprintf(stderr, "Failed to initialise MGA device\n");

	Heap$Free(Pvs(heap), st);

	return;
    }

#ifdef TEST_CARD
    test_card16a( (uint16_t *) st->cardbase );
#else
    memset((uchar_t *) st->cardbase, 0, 
	   FB_WIDTH * FB_HEIGHT * (FB_DEPTH/8) );
#endif	

    /* Init state */
    st->qosleft = 100;
    st->cursched = 0;
    st->schedndx = 0;
    for (i = 0; i < FB_SCHEDLEN; i++) {
	st->sched[0][i] = st->sched[1][i] = 0;
    }
    
    /* Initialise window DS */
    for (i = 0 ; i < FB_MAX_WINDOWS; i++) {
	FB_Window *w = &st->window[i];
	w->wid  = i;
	w->free = True;
	w->tagword = w->tag  = w->wid;

	/* extend the tag to be a full word (32 or 64 bits) wide */
	w->tagword |= (w->tagword<<8);
	w->tagword |= (w->tagword<<16);
	/* Generates harmless overflow warning on 32bit architectures */
	w->tagword |= (w->tagword<<32);

    }
    
    /* Initialise stream DS */
    for (i = 0 ; i < FB_MAX_STREAMS; i++) {
	FB_Stream *s = &st->stream[i];
	s->sid  = i;
	s->free = True;
	s->qos  = 0;
    }

    TRC(printf("About to create an entry...\n"));

    /* Create an entry*/
    emod = NAME_FIND ("modules>IOEntryMod", IOEntryMod_clp);
    st->fbentry = IOEntryMod$New (emod, Pvs(actf), Pvs(vp),
				  VP$NumChannels (Pvs(vp)));    
    

    TRC(printf("About to grab stretches for FB and CLIP\n"));

    /* Grab stretches for FB and CLIP */
    {

	Stretch_clp           str;
	Stretch_Size          size;

	/* Get a stretch for clip RAM. Allocate a spare line of tiles
           at the start and end in case we need to blit over the edges */

	str    = STR_NEW(sizeof(tag_t)*FB_WIDTH*(FB_HEIGHT+16));
	if (!str) {
	    fprintf(stderr,"Couldn't get stretch");
	}
	st->clipstr = str;
	st->clipbase = (tag_t *) STR_RANGE(str, &size);
	st->clip = st->clipbase + (FB_WIDTH * 8);

	if (!st->clip || size < (FB_WIDTH*(FB_HEIGHT+16))) {
	    fprintf(stderr,"Stretch bogus\n");
	}
	TRC(fprintf(stderr,"FB: Clip RAM at %p size %lx\n", st->clip, size));	
    }
    TRC(printf("About to init clip RAM\n"));

    /* Initialise the clip RAM */
    InitClipRAM(&st->cl);

    TRC(printf("About to add dev>fblite to namespace\n"));
    CX_ADD("dev>fblite", st->cardbase, addr_t);

    TRC(printf("About to init blitting code\n"));
    /* Init the blitting code */
    blit_init(st);

    /* Turn on cursor */
    TRC(printf("About to turn on cursor\n"));
    MGALoadCursor(st->cardbase, CURSOR_IDX, CURSOR_BITS);
    MGAMoveCursor(st->cardbase, CURSOR_IDX, CURSOR_INITX, CURSOR_INITY);

    /* Export management interface */
    TRC(printf("About to export management interface\n"));
    IDC_EXPORT ("dev>FB", FB_clp, &st->cl);
    /* Go into a loop to service all the clients */


    /* Launch WSSvr */

    TRC(printf("Trying to launch wssvr\n"));
    TRY {
	Closure_clp wssvr;

	wssvr = NAME_FIND("modules>WSSvr", Closure_clp);
	
	Threads$Fork(Pvs(thds), wssvr->op->Apply, wssvr->st, 0);

	st->wssvr_shares_domain = True;
    } CATCH_ALL {
	printf("Couldn't launch WSSvr - exception %s\n",
	       exn_ctx.cur_exception);
    } ENDTRY;

    TRC(printf("FB/MGA: Init Done. (%ix%i %ibpp mode %i)\n",
	       FB_WIDTH,FB_HEIGHT,FB_DEPTH,FB_MODE));
    blit_loop(st);
}