void start_networking(void) { struct netfront_dev *dev; struct netif *_netif; struct netif *niret; struct netfrontif *nfi; struct ip_addr ip; struct ip_addr mask; struct ip_addr gw; char *ifip = NULL; ASSERT(netif == NULL); IP4_ADDR(&ip, 192, 168, 1, 128); IP4_ADDR(&mask, 255, 255, 255, 0); IP4_ADDR(&gw, 0, 0, 0, 0); tprintk("Starting networking\n"); /* init netfront */ dev = init_netfront(NULL, NULL, NULL, &ifip); if (!dev) { tprintk("Could not init netfront\n"); goto err_out; } if (ifip) { tprintk("Got IP address %s\n", ifip); ip.addr = inet_addr(ifip); if (IN_CLASSA(ntohl(ip.addr))) { tprintk("Use class A netmask (255.0.0.0)\n"); mask.addr = htonl(IN_CLASSA_NET); } else if (IN_CLASSB(ntohl(ip.addr))) { mask.addr = htonl(IN_CLASSB_NET); tprintk("Use class B netmask (255.255.0.0)\n"); } else if (IN_CLASSC(ntohl(ip.addr))) { mask.addr = htonl(IN_CLASSC_NET); tprintk("Use class C netmask (255.255.255.0)\n"); } else { tprintk("Could not auto-detect IP class for %s," "use class C netmask (255.255.255.0)\n", ifip); } } else { tprintk("Set IP to 192.168.1.128, use class A netmask (255.0.0.0)\n"); } /* allocate netif */ _netif = mem_calloc(1, sizeof(*_netif)); if (!_netif) { tprintk("Could not allocate netif\n"); goto err_shutdown_netfront; } /* allocate netif state data */ nfi = mem_calloc(1, sizeof(*nfi)); if (!nfi) { tprintk("Could not allocate netfrontif\n"); goto err_free_netif; } nfi->dev = dev; /* init lwIP */ #ifdef CONFIG_LWIP_NOTHREADS lwip_init(); niret = netif_add(_netif, &ip, &mask, &gw, nfi, netfrontif_init, ethernet_input); #else tcpip_init(NULL, NULL); niret = netif_add(_netif, &ip, &mask, &gw, nfi, netfrontif_init, tcpip_input); #endif if (!niret) { tprintk("Could not initialize lwIP\n"); goto err_free_nfi; } netif_set_default(_netif); netif_set_up(_netif); netif = _netif; tprintk("Networking started\n"); return; err_free_nfi: mem_free(nfi); err_free_netif: mem_free(_netif); err_shutdown_netfront: shutdown_netfront(dev); err_out: return; }
/** * Initializes and sets up a netfront interface for lwIP. * This function should be passed as a parameter to netfrontif_add(). * * @param netif * the lwip network interface structure for this netfrontif * @return * ERR_OK if the interface was successfully initialized; * An err_t value otherwise */ err_t netfrontif_init(struct netif *netif) { struct netfrontif *nfi; static uint8_t netfrontif_id = 0; LWIP_ASSERT("netif != NULL", (netif != NULL)); if (!(netif->state)) { nfi = mem_calloc(1, sizeof(*nfi)); if (!nfi) { LWIP_DEBUGF(NETIF_DEBUG, ("netfrontif_init: " "Could not allocate \n")); goto err_out; } netif->state = nfi; nfi->_state_is_private = 1; nfi->_dev_is_private = 1; nfi->_hwaddr_is_private = 1; } else { nfi = netif->state; nfi->_state_is_private = 0; nfi->_dev_is_private = !(nfi->dev); nfi->_hwaddr_is_private = eth_addr_cmp(&nfi->hwaddr, ðzero); } /* Netfront */ if (nfi->_dev_is_private) { /* user did not provide an opened netfront, we need to do it here */ if (!nfi->_state_is_private) { /* use vif_id to open an specific NIC interface */ /* Note: netfront will duplicate the passed nodename */ char nodename[128]; snprintf(nodename, sizeof(nodename), "device/vif/%u", nfi->vif_id); nfi->dev = init_netfront(nodename, NULL, NULL, NULL); } else { /* open the next available net interface */ nfi->dev = init_netfront(NULL, NULL, NULL, NULL); } if (!nfi->dev) { LWIP_DEBUGF(NETIF_DEBUG, ("netfrontif_init: " "Could not init netfront\n")); goto err_free_nfi; } } netfront_set_rx_pbuf_handler(nfi->dev, netfrontif_rx_handler, netif); /* Interface identifier */ netif->name[0] = NETFRONTIF_NPREFIX; netif->name[1] = '0' + netfrontif_id; netfrontif_id++; /* We directly use etharp_output() here to save a function call. * Instead, there could be function declared that calls etharp_output() * only if there is a link is available... */ netif->output = etharp_output; netif->linkoutput = netfrontif_transmit; #if LWIP_NETIF_REMOVE_CALLBACK netif->remove_callback = netfrontif_exit; #endif /* CONFIG_NETIF_REMOVE_CALLBACK */ /* Hardware address */ if (nfi->_hwaddr_is_private) { if (!netfront_get_hwaddr(nfi->dev, &nfi->hwaddr)) { LWIP_DEBUGF(NETIF_DEBUG, ("netfrontif_init: %c%c: " "Could not retrieve hardware address\n", netif->name[0], netif->name[1])); goto err_shutdown_netfront; } } else { LWIP_DEBUGF(NETIF_DEBUG, ("netfrontif_init: %c%c: " "Overwriting hardware address\n", netif->name[0], netif->name[1])); } SMEMCPY(&netif->hwaddr, &nfi->hwaddr, ETHARP_HWADDR_LEN); netif->hwaddr_len = ETHARP_HWADDR_LEN; LWIP_DEBUGF(NETIF_DEBUG, ("netfrontif_init: %c%c: hardware address: " "%02x:%02x:%02x:%02x:%02x:%02x\n", netif->name[0], netif->name[1], netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5])); /* Initialize the snmp variables and counters inside the struct netif. * The last argument is the link speed, in units of bits per second. */ NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, NETFRONTIF_SPEED); LWIP_DEBUGF(NETIF_DEBUG, ("netfrontif_init: %c%c: Link speed: %llu bps\n", netif->name[0], netif->name[1], NETFRONTIF_SPEED)); /* Device capabilities */ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; /* Maximum transfer unit */ netif->mtu = NETFRONTIF_MTU; LWIP_DEBUGF(NETIF_DEBUG, ("netfrontif_init: %c%c: MTU: %u\n", netif->name[0], netif->name[1], netif->mtu)); #if LWIP_NETIF_HOSTNAME /* Initialize interface hostname */ if (!netif->hostname) netif->hostname = NULL; #endif /* LWIP_NETIF_HOSTNAME */ #ifndef CONFIG_LWIP_NOTHREADS nfi->_thread_exit = 0; nfi->_thread_name[0] = netif->name[0]; nfi->_thread_name[1] = netif->name[1]; nfi->_thread_name[2] = '-'; nfi->_thread_name[3] = 'r'; nfi->_thread_name[4] = 'x'; nfi->_thread_name[5] = '\0'; create_thread(nfi->_thread_name, netfrontif_thread, netif); #endif /* CONFIG_LWIP_NOTHREADS */ return ERR_OK; err_shutdown_netfront: if (nfi->_dev_is_private) { shutdown_netfront(nfi->dev); nfi->dev = NULL; } err_free_nfi: if (nfi->_state_is_private) { mem_free(nfi); netif->state = NULL; } err_out: return ERR_IF; }
int close(int fd) { printk("close(%d)\n", fd); switch (files[fd].type) { default: files[fd].type = FTYPE_NONE; return 0; #ifdef CONFIG_XENBUS case FTYPE_XENBUS: xs_daemon_close((void*)(intptr_t) fd); return 0; #endif #ifdef HAVE_LWIP case FTYPE_SOCKET: { int res = lwip_close(files[fd].socket.fd); files[fd].type = FTYPE_NONE; return res; } #endif #ifdef CONFIG_XC case FTYPE_XC: minios_interface_close_fd(fd); return 0; case FTYPE_EVTCHN: minios_evtchn_close_fd(fd); return 0; case FTYPE_GNTMAP: minios_gnttab_close_fd(fd); return 0; #endif #ifdef CONFIG_NETFRONT case FTYPE_TAP: shutdown_netfront(files[fd].tap.dev); files[fd].type = FTYPE_NONE; return 0; #endif #ifdef CONFIG_BLKFRONT case FTYPE_BLK: shutdown_blkfront(files[fd].blk.dev); files[fd].type = FTYPE_NONE; return 0; #endif #ifdef CONFIG_TPMFRONT case FTYPE_TPMFRONT: shutdown_tpmfront(files[fd].tpmfront.dev); files[fd].type = FTYPE_NONE; return 0; #endif #ifdef CONFIG_TPM_TIS case FTYPE_TPM_TIS: shutdown_tpm_tis(files[fd].tpm_tis.dev); files[fd].type = FTYPE_NONE; return 0; #endif #ifdef CONFIG_KBDFRONT case FTYPE_KBD: shutdown_kbdfront(files[fd].kbd.dev); files[fd].type = FTYPE_NONE; return 0; #endif #ifdef CONFIG_FBFRONT case FTYPE_FB: shutdown_fbfront(files[fd].fb.dev); files[fd].type = FTYPE_NONE; return 0; #endif #ifdef CONFIG_CONSFRONT case FTYPE_SAVEFILE: case FTYPE_CONSOLE: fini_console(files[fd].cons.dev); files[fd].type = FTYPE_NONE; return 0; #endif case FTYPE_NONE: break; } printk("close(%d): Bad descriptor\n", fd); errno = EBADF; return -1; }
void kexec(void *kernel, long kernel_size, void *module, long module_size, char *cmdline, unsigned long flags) { struct xc_dom_image *dom; int rc; domid_t domid = DOMID_SELF; xen_pfn_t pfn; xc_interface *xc_handle; unsigned long i; void *seg; xen_pfn_t boot_page_mfn = virt_to_mfn(&_boot_page); char features[] = ""; struct mmu_update *m2p_updates; unsigned long nr_m2p_updates; DEBUG("booting with cmdline %s\n", cmdline); xc_handle = xc_interface_open(0,0,0); dom = xc_dom_allocate(xc_handle, cmdline, features); dom->allocate = kexec_allocate; /* We are using guest owned memory, therefore no limits. */ xc_dom_kernel_max_size(dom, 0); xc_dom_ramdisk_max_size(dom, 0); dom->kernel_blob = kernel; dom->kernel_size = kernel_size; dom->ramdisk_blob = module; dom->ramdisk_size = module_size; dom->flags = flags; dom->console_evtchn = start_info.console.domU.evtchn; dom->xenstore_evtchn = start_info.store_evtchn; tpm_hash2pcr(dom, cmdline); if ( (rc = xc_dom_boot_xen_init(dom, xc_handle, domid)) != 0 ) { grub_printf("xc_dom_boot_xen_init returned %d\n", rc); errnum = ERR_BOOT_FAILURE; goto out; } if ( (rc = xc_dom_parse_image(dom)) != 0 ) { grub_printf("xc_dom_parse_image returned %d\n", rc); errnum = ERR_BOOT_FAILURE; goto out; } #ifdef __i386__ if (strcmp(dom->guest_type, "xen-3.0-x86_32p")) { grub_printf("can only boot x86 32 PAE kernels, not %s\n", dom->guest_type); errnum = ERR_EXEC_FORMAT; goto out; } #endif #ifdef __x86_64__ if (strcmp(dom->guest_type, "xen-3.0-x86_64")) { grub_printf("can only boot x86 64 kernels, not %s\n", dom->guest_type); errnum = ERR_EXEC_FORMAT; goto out; } #endif /* equivalent of xc_dom_mem_init */ dom->arch_hooks = xc_dom_find_arch_hooks(xc_handle, dom->guest_type); dom->total_pages = start_info.nr_pages; /* equivalent of arch_setup_meminit */ /* setup initial p2m */ dom->p2m_host = malloc(sizeof(*dom->p2m_host) * dom->total_pages); /* Start with our current P2M */ for (i = 0; i < dom->total_pages; i++) dom->p2m_host[i] = pfn_to_mfn(i); if ( (rc = xc_dom_build_image(dom)) != 0 ) { grub_printf("xc_dom_build_image returned %d\n", rc); errnum = ERR_BOOT_FAILURE; goto out; } /* copy hypercall page */ /* TODO: domctl instead, but requires privileges */ if (dom->parms.virt_hypercall != -1) { pfn = PHYS_PFN(dom->parms.virt_hypercall - dom->parms.virt_base); memcpy((void *) pages[pfn], hypercall_page, PAGE_SIZE); } /* Equivalent of xc_dom_boot_image */ dom->shared_info_mfn = PHYS_PFN(start_info.shared_info); if (!xc_dom_compat_check(dom)) { grub_printf("xc_dom_compat_check failed\n"); errnum = ERR_EXEC_FORMAT; goto out; } /* Move current console, xenstore and boot MFNs to the allocated place */ do_exchange(dom, dom->console_pfn, start_info.console.domU.mfn); do_exchange(dom, dom->xenstore_pfn, start_info.store_mfn); DEBUG("virt base at %llx\n", dom->parms.virt_base); DEBUG("bootstack_pfn %lx\n", dom->bootstack_pfn); _boot_target = dom->parms.virt_base + PFN_PHYS(dom->bootstack_pfn); DEBUG("_boot_target %lx\n", _boot_target); do_exchange(dom, PHYS_PFN(_boot_target - dom->parms.virt_base), virt_to_mfn(&_boot_page)); /* Make sure the bootstrap page table does not RW-map any of our current * page table frames */ kexec_allocate(dom, dom->virt_pgtab_end); if ( (rc = xc_dom_update_guest_p2m(dom))) { grub_printf("xc_dom_update_guest_p2m returned %d\n", rc); errnum = ERR_BOOT_FAILURE; goto out; } if ( dom->arch_hooks->setup_pgtables ) if ( (rc = dom->arch_hooks->setup_pgtables(dom))) { grub_printf("setup_pgtables returned %d\n", rc); errnum = ERR_BOOT_FAILURE; goto out; } /* start info page */ #undef start_info if ( dom->arch_hooks->start_info ) dom->arch_hooks->start_info(dom); #define start_info (start_info_union.start_info) xc_dom_log_memory_footprint(dom); /* Unmap libxc's projection of the boot page table */ seg = xc_dom_seg_to_ptr(dom, &dom->pgtables_seg); munmap(seg, dom->pgtables_seg.vend - dom->pgtables_seg.vstart); /* Unmap day0 pages to avoid having a r/w mapping of the future page table */ for (pfn = 0; pfn < allocated; pfn++) munmap((void*) pages[pfn], PAGE_SIZE); /* Pin the boot page table base */ if ( (rc = pin_table(dom->xch, #ifdef __i386__ MMUEXT_PIN_L3_TABLE, #endif #ifdef __x86_64__ MMUEXT_PIN_L4_TABLE, #endif xc_dom_p2m_host(dom, dom->pgtables_seg.pfn), dom->guest_domid)) != 0 ) { grub_printf("pin_table(%lx) returned %d\n", xc_dom_p2m_host(dom, dom->pgtables_seg.pfn), rc); errnum = ERR_BOOT_FAILURE; goto out_remap; } /* We populate the Mini-OS page table here so that boot.S can just call * update_va_mapping to project itself there. */ need_pgt(_boot_target); DEBUG("day0 pages %lx\n", allocated); DEBUG("boot target page %lx\n", _boot_target); DEBUG("boot page %p\n", &_boot_page); DEBUG("boot page mfn %lx\n", boot_page_mfn); _boot_page_entry = PFN_PHYS(boot_page_mfn) | L1_PROT; DEBUG("boot page entry %llx\n", _boot_page_entry); _boot_oldpdmfn = virt_to_mfn(start_info.pt_base); DEBUG("boot old pd mfn %lx\n", _boot_oldpdmfn); DEBUG("boot pd virt %lx\n", dom->pgtables_seg.vstart); _boot_pdmfn = dom->p2m_host[PHYS_PFN(dom->pgtables_seg.vstart - dom->parms.virt_base)]; DEBUG("boot pd mfn %lx\n", _boot_pdmfn); _boot_stack = _boot_target + PAGE_SIZE; DEBUG("boot stack %lx\n", _boot_stack); _boot_start_info = dom->parms.virt_base + PFN_PHYS(dom->start_info_pfn); DEBUG("boot start info %lx\n", _boot_start_info); _boot_start = dom->parms.virt_entry; DEBUG("boot start %lx\n", _boot_start); /* Keep only useful entries */ for (nr_m2p_updates = pfn = 0; pfn < start_info.nr_pages; pfn++) if (dom->p2m_host[pfn] != pfn_to_mfn(pfn)) nr_m2p_updates++; m2p_updates = malloc(sizeof(*m2p_updates) * nr_m2p_updates); for (i = pfn = 0; pfn < start_info.nr_pages; pfn++) if (dom->p2m_host[pfn] != pfn_to_mfn(pfn)) { m2p_updates[i].ptr = PFN_PHYS(dom->p2m_host[pfn]) | MMU_MACHPHYS_UPDATE; m2p_updates[i].val = pfn; i++; } for (i = 0; i < blk_nb; i++) shutdown_blkfront(blk_dev[i]); if (net_dev) shutdown_netfront(net_dev); if (kbd_dev) shutdown_kbdfront(kbd_dev); stop_kernel(); /* Update M2P */ if ((rc = HYPERVISOR_mmu_update(m2p_updates, nr_m2p_updates, NULL, DOMID_SELF)) < 0) { xprintk("Could not update M2P\n"); ASSERT(0); } xprintk("go!\n"); /* Jump to trampoline boot page */ _boot(); ASSERT(0); out_remap: for (pfn = 0; pfn < allocated; pfn++) do_map_frames(pages[pfn], &pages_mfns[pfn], 1, 0, 0, DOMID_SELF, 0, L1_PROT); out: xc_dom_release(dom); for (pfn = 0; pfn < allocated; pfn++) free_page((void*)pages[pfn]); free(pages); free(pages_mfns); pages = NULL; pages_mfns = NULL; allocated = 0; xc_interface_close(xc_handle ); }
int close(int fd) { printk("close(%d)\n", fd); if (fd < 0 || fd > NOFILE) { errno = EBADF; return -1; } switch (files[fd].type) { default: files[fd].type = FTYPE_NONE; return 0; case FTYPE_XENBUS: xs_daemon_close((void*)(intptr_t) fd); return 0; #ifdef HAVE_LWIP case FTYPE_SOCKET: { int res = lwip_close(files[fd].socket.fd); files[fd].type = FTYPE_NONE; return res; } #endif case FTYPE_XC: minios_interface_close_fd(fd); return 0; case FTYPE_EVTCHN: minios_evtchn_close_fd(fd); return 0; case FTYPE_GNTMAP: printk("close gntmap fd %d; gntmap %p, %d entries\n", fd, files[fd].gntmap.entries, files[fd].gntmap.nentries); minios_gnttab_close_fd(fd); return 0; case FTYPE_TAP: shutdown_netfront(files[fd].tap.dev); files[fd].type = FTYPE_NONE; return 0; case FTYPE_BLK: shutdown_blkfront(files[fd].blk.dev); files[fd].type = FTYPE_NONE; return 0; case FTYPE_KBD: shutdown_kbdfront(files[fd].kbd.dev); files[fd].type = FTYPE_NONE; return 0; case FTYPE_FB: shutdown_fbfront(files[fd].fb.dev); files[fd].type = FTYPE_NONE; return 0; case FTYPE_SAVEFILE: case FTYPE_CONSOLE: fini_console(files[fd].cons.dev); files[fd].type = FTYPE_NONE; return 0; case FTYPE_NONE: break; } printk("close(%d): Bad descriptor\n", fd); errno = EBADF; return -1; }
/* Shut down the network */ void stop_networking(void) { if (dev) shutdown_netfront(dev); }