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
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; }
* 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) },
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 }
/* ** 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(); }
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); }