ssize_t serial_server_printf(serial_client_context_t *conn, const char *fmt, ...) { ssize_t expanded_fmt_length; va_list args; /* We simplify everything by just vsnprintf()ing, instead of marshaling * a variable length format string and a variable length argument list. */ if (fmt == NULL || conn == NULL || conn->shmem == NULL) { ZF_LOGE(SERSERVC"printf: NULL passed for required arguments.\n" "\tIs connection handle valid?"); return -seL4_InvalidArgument; } va_start(args, fmt); expanded_fmt_length = vsnprintf((char *)conn->shmem, conn->shmem_size, fmt, args); va_end(args); if (expanded_fmt_length < 0) { return -1; } if ((size_t)expanded_fmt_length >= conn->shmem_size) { ZF_LOGE(SERSERVC"printf: This printf call's total expanded length (%zd) " "exceeds your %zd bytes shmem buffer.\n\tMessage not sent to " "server.", expanded_fmt_length, conn->shmem_size); return -seL4_RangeError; } /* Else, send it off to the server. */ return serial_server_write_ipc_invoke(conn, expanded_fmt_length); }
void start_tcpecho() { uint16_t listen_port = short_be(8777); int ret = 0, yes = 1; struct pico_socket *s = NULL; struct pico_ip4 ip4 = {0}; s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, &cb_tcpecho); if (!s) { ZF_LOGE("%s: error opening socket: %s\n", __FUNCTION__, strerror(pico_err)); } pico_socket_setoption(s, PICO_TCP_NODELAY, &yes); ret = pico_socket_bind(s, &ip4, &listen_port); if (ret < 0) { ZF_LOGE("%s: error binding socket to port %u: %s\n", __FUNCTION__, short_be(listen_port), strerror(pico_err)); } if (pico_socket_listen(s, 40) != 0) { ZF_LOGE("%s: error listening on port %u\n", __FUNCTION__, short_be(listen_port)); } ZF_LOGD("Launching PicoTCP echo server\n"); }
seL4_CPtr vmm_create_async_event_notification_cap(vmm_t *vmm, seL4_Word badge) { if (!(badge & BIT(27))) { ZF_LOGE("Invalid badge"); return seL4_CapNull; } // notification cap seL4_CPtr ntfn = vmm->plat_callbacks.get_async_event_notification(); // path to notification cap slot cspacepath_t ntfn_path = {}; vka_cspace_make_path(&vmm->vka, ntfn, &ntfn_path); // allocate slot to store copy cspacepath_t minted_ntfn_path = {}; vka_cspace_alloc_path(&vmm->vka, &minted_ntfn_path); // mint the notification cap seL4_CapData_t badge_data = seL4_CapData_Badge_new(badge); int error = vka_cnode_mint(&minted_ntfn_path, &ntfn_path, seL4_AllRights, badge_data); if (error != seL4_NoError) { ZF_LOGE("Failed to mint notification cap"); return seL4_CapNull; } return minted_ntfn_path.capPtr; }
int vm_install_tk1_usb_passthrough_device(vm_t* vm) { /* Add the device */ void *addr = map_vm_device(vm, dev_usb.pstart, dev_usb.pstart, seL4_AllRights); if (addr == NULL) { ZF_LOGE("map_vm_device returned NULL"); return -1; } void *vmm_addr = vspace_share_mem(vm_get_vspace(vm), vm_get_vmm_vspace(vm), addr, 1, seL4_PageBits, seL4_AllRights, 0); if (vmm_addr == NULL) { ZF_LOGE("vspace_share_mem returned NULL"); return -1; } int err = vm_add_device(vm, &dev_usb); if (err) { ZF_LOGE("vm_add_device returned error: %d", err); return -1; } err = vm_register_reboot_callback(vm, usb_vm_reboot_hook, vmm_addr); if (err) { ZF_LOGE("vm_register_reboot_callback returned error: %d", err); return -1; } return 0; }
seL4_timer_t * sel4platsupport_get_pit(vka_t *vka, simple_t *simple, ps_io_port_ops_t *ops, seL4_CPtr notification) { seL4_pit_data_t *data = malloc(sizeof(seL4_pit_data_t)); if (data == NULL) { ZF_LOGE("Failed to allocate object of size %zu\n", sizeof(*data)); goto error; } seL4_timer_t *pit = calloc(1, sizeof(*pit)); if (pit == NULL) { ZF_LOGE("Failed to malloc object of size %zu\n", sizeof(*pit)); goto error; } pit->destroy = pit_destroyer; pit->handle_irq = pit_handle_irq; pit->data = data; /* set up irq */ cspacepath_t dest; if (sel4platsupport_copy_irq_cap(vka, simple, PIT_INTERRUPT, &dest) != seL4_NoError) { goto error; } data->irq = dest.capPtr; /* bind to endpoint */ if (seL4_IRQHandler_SetNotification(data->irq, notification) != seL4_NoError) { ZF_LOGE("seL4_IRQHandler_SetEndpoint failed\n"); goto error; } /* ack (api hack) */ seL4_IRQHandler_Ack(data->irq); /* finally set up the actual timer */ pit->timer = pit_get_timer(ops); if (pit->timer == NULL) { goto error; } /* sucess */ return pit; error: if (data != NULL) { free(data); } if (data->irq != 0) { timer_common_cleanup_irq(vka, data->irq); } return NULL; }
seL4_timer_t * sel4platsupport_get_timer(enum timer_id id, vka_t *vka, vspace_t *vspace, simple_t *simple, seL4_CPtr notification) { switch (id) { case DMTIMER2: case DMTIMER3: case DMTIMER4: case DMTIMER5: case DMTIMER6: case DMTIMER7: break; default: ZF_LOGE("Bad timer ID %d\n", id); return NULL; } seL4_timer_t *timer = calloc(1, sizeof(seL4_timer_t)); if (timer == NULL) { ZF_LOGE("Failed to allocate object of size %u\n", sizeof(seL4_timer_t)); return NULL; } timer->handle_irq = timer_common_handle_irq; timer_common_data_t *data = timer_common_init(vspace, simple, vka, notification, dm_timer_irqs[id], (void*)dm_timer_paddrs[id]); timer->data = data; if (timer->data == NULL) { free(timer); return NULL; } timer_config_t config = { .vaddr = data->vaddr, .irq = dm_timer_irqs[id], }; timer->timer = ps_get_timer(id, &config); if (timer->timer == NULL) { timer_common_destroy(timer->data, vka, vspace); free(timer); return NULL; } /* success */ return timer; } seL4_timer_t * sel4platsupport_get_default_timer(vka_t *vka, vspace_t *vspace, simple_t *simple, seL4_CPtr notification) { return sel4platsupport_get_timer(TMR_DEFAULT, vka, vspace, simple, notification); }
/* Binds and IRQ to an endpoint */ static seL4_CPtr irq_bind(irq_t irq, seL4_CPtr notification_cap, int idx, vka_t* vka, simple_t *simple) { seL4_CPtr irq_cap, bnotification_cap; cspacepath_t irq_path, notification_path, bnotification_path; seL4_CapData_t badge; int err; /* Create an IRQ cap */ err = vka_cspace_alloc(vka, &irq_cap); if (err != 0) { ZF_LOGE("Failed to allocate cslot for irq\n"); return seL4_CapNull; } vka_cspace_make_path(vka, irq_cap, &irq_path); err = simple_get_IRQ_control(simple, irq, irq_path); if (err != seL4_NoError) { ZF_LOGE("Failed to get cap to irq_number %d\n", irq); vka_cspace_free(vka, irq_cap); return seL4_CapNull; } /* Badge the provided endpoint. The bit position of the badge tells us the array * index of the associated IRQ data. */ err = vka_cspace_alloc(vka, &bnotification_cap); if (err != 0) { ZF_LOGE("Failed to allocate cslot for irq\n"); vka_cspace_free(vka, irq_cap); return seL4_CapNull; } vka_cspace_make_path(vka, notification_cap, ¬ification_path); vka_cspace_make_path(vka, bnotification_cap, &bnotification_path); badge = seL4_CapData_Badge_new(BIT(idx)); err = vka_cnode_mint(&bnotification_path, ¬ification_path, seL4_AllRights, badge); if (err != seL4_NoError) { ZF_LOGE("Failed to badge IRQ notification endpoint\n"); vka_cspace_free(vka, irq_cap); vka_cspace_free(vka, bnotification_cap); return seL4_CapNull; } /* bind the IRQ cap to our badged endpoint */ err = seL4_IRQHandler_SetNotification(irq_cap, bnotification_cap); if (err != seL4_NoError) { ZF_LOGE("Failed to bind IRQ handler to notification\n"); vka_cspace_free(vka, irq_cap); vka_cspace_free(vka, bnotification_cap); return seL4_CapNull; } /* Finally ACK any pending IRQ and enable the IRQ */ seL4_IRQHandler_Ack(irq_cap); DIRQSERVER("Registered IRQ %d with badge 0x%lx\n", irq, BIT(idx)); return irq_cap; }
void sel4utils_unmap_pages(vspace_t *vspace, void *vaddr, size_t num_pages, size_t size_bits, vka_t *vka) { uintptr_t v = (uintptr_t) vaddr; sel4utils_alloc_data_t *data = get_alloc_data(vspace); sel4utils_res_t *reserve = find_reserve(data, v); if (!sel4_valid_size_bits(size_bits)) { ZF_LOGE("Invalid size_bits %zu", size_bits); return; } if (vka == VSPACE_FREE) { vka = data->vka; } for (int i = 0; i < num_pages; i++) { seL4_CPtr cap = get_cap(data->top_level, v); /* unmap */ if (cap != 0) { int error = seL4_ARCH_Page_Unmap(cap); if (error != seL4_NoError) { ZF_LOGE("Failed to unmap page at vaddr %p", vaddr); } } if (vka) { cspacepath_t path; vka_cspace_make_path(vka, cap, &path); vka_cnode_delete(&path); vka_cspace_free(vka, cap); if (sel4utils_get_cookie(vspace, vaddr)) { vka_utspace_free(vka, kobject_get_type(KOBJECT_FRAME, size_bits), size_bits, sel4utils_get_cookie(vspace, vaddr)); } } if (reserve == NULL) { clear_entries(vspace, v, size_bits); } else { reserve_entries(vspace, v, size_bits); } assert(get_cap(data->top_level, v) != cap); assert(get_cookie(data->top_level, v) == 0); v += (1 << size_bits); vaddr = (void *) v; } }
void spi_handle_irq(spi_bus_t* spi_bus) { #ifdef DEBUG_IRQ int int_type = get_spi_interrupt_type(spi_bus); if (int_type == RDY_BIT_SET) { ZF_LOGE("Interrupt RDY_BIT\n"); } else { ZF_LOGE("Interrupt FIFO ERROR\n"); print_fifo_error(spi_bus->regs->fifo_status); } #endif transfer_data(spi_bus); setbits(spi_bus->regs->xfer_status, SPI_XFER_STS_RDY); }
seL4_timer_t * sel4platsupport_get_tsc_timer(seL4_timer_t *timeout_timer) { if (timeout_timer == NULL) { ZF_LOGE("Cannot initialise tsc frequency, timeout timer is NULL"); return NULL; } seL4_timer_t *timer = calloc(1, sizeof(seL4_timer_t)); if (timer == NULL) { ZF_LOGE("Failed to allocate timer"); return NULL; } return finish_get_tsc(timer, tsc_get_timer(timeout_timer->timer)); }
void simple_default_print(void *data) { if (data == NULL) { ZF_LOGE("Data is null!"); } debug_print_bootinfo(data); }
int sel4utils_map_page_ept(vspace_t *vspace, seL4_CPtr cap, void *vaddr, seL4_CapRights rights, int cacheable, size_t size_bits) { struct sel4utils_alloc_data *data = get_alloc_data(vspace); vka_object_t pagetable = {0}; vka_object_t pagedir = {0}; int error = sel4utils_map_ept_page(data->vka, data->vspace_root, cap, (seL4_Word) vaddr, rights, cacheable, size_bits, &pagetable, &pagedir); if (error) { ZF_LOGE("Error mapping pages, bailing\n"); return -1; } if (pagetable.cptr != 0) { vspace_maybe_call_allocated_object(vspace, pagetable); pagetable.cptr = 0; } if (pagedir.cptr != 0) { vspace_maybe_call_allocated_object(vspace, pagedir); pagedir.cptr = 0; } return seL4_NoError; }
seL4_timer_t * sel4platsupport_get_tsc_timer_freq(uint64_t freq) { if (freq == 0) { ZF_LOGE("Can't init tsc with 0 freq"); return NULL; } seL4_timer_t *timer = calloc(1, sizeof(seL4_timer_t)); if (timer == NULL) { ZF_LOGE("Failed to allocate timer"); return NULL; } return finish_get_tsc(timer, tsc_get_timer_with_freq(freq)); }
void irq_data_ack_irq(struct irq_data* irq) { if (irq == NULL || irq->cap == seL4_CapNull) { ZF_LOGE("IRQ data invalid when acknowledging IRQ\n"); } else { seL4_IRQHandler_Ack(irq->cap); } }
static void* malloc_dma_alloc(void *cookie, size_t size, int align, int cached, ps_mem_flags_t flags) { assert(cached); int error; void *ret = malloc(size); if (ret == NULL){ ZF_LOGE("ERR: Failed to allocate %d\n", size); return NULL; } return ret; }
/* Creates a new thread for an IRQ server */ struct irq_server_thread* irq_server_thread_new(vspace_t* vspace, vka_t* vka, seL4_CPtr cspace, seL4_Word priority, simple_t *simple, seL4_Word label, seL4_CPtr sep) { struct irq_server_thread* st; int err; /* Allocate memory for the structure */ st = (struct irq_server_thread*)malloc(sizeof(*st)); if (st == NULL) { return NULL; } st->node = irq_server_node_new(0, MASK(NIRQS_PER_NODE)); if (st->node == NULL) { free(st); return NULL; } /* Initialise structure */ st->delivery_sep = sep; st->label = label; st->next = NULL; /* Create an endpoint to listen on */ err = vka_alloc_notification(vka, &st->notification); if (err) { ZF_LOGE("Failed to allocate IRQ notification endpoint for IRQ server thread\n"); return NULL; } st->node->notification = st->notification.cptr; /* Create the IRQ thread */ err = sel4utils_configure_thread(vka, vspace, vspace, seL4_CapNull, priority, cspace, seL4_NilData, &st->thread); if (err) { ZF_LOGE("Failed to configure IRQ server thread\n"); return NULL; } /* Start the thread */ err = sel4utils_start_thread(&st->thread, (void*)_irq_thread_entry, st, NULL, 1); if (err) { ZF_LOGE("Failed to start IRQ server thread\n"); return NULL; } return st; }
int sel4utils_map_pages_at_vaddr(vspace_t *vspace, seL4_CPtr caps[], uintptr_t cookies[], void *vaddr, size_t num_pages, size_t size_bits, reservation_t reservation) { sel4utils_alloc_data_t *data = get_alloc_data(vspace); sel4utils_res_t *res = reservation_to_res(reservation); if (!sel4_valid_size_bits(size_bits)) { ZF_LOGE("Invalid size_bits %zu", size_bits); return -1; } if (!check_reservation(data->top_level, res, (uintptr_t) vaddr, (uintptr_t)vaddr + num_pages * BIT(size_bits))) { ZF_LOGE("Invalid reservation"); return -1; } return map_pages_at_vaddr(vspace, caps, cookies, vaddr, num_pages, size_bits, res->rights, res->cacheable); }
static stop_reason_t find_stop_reason(seL4_Word fault_type, seL4_Word *args) { if (fault_type == seL4_Fault_DebugException) { seL4_Word exception_reason = args[1]; ZF_LOGD("MR 0: %zX", args[0]); ZF_LOGD("MR 1: %zX", args[1]); ZF_LOGD("MR 2: %zX", args[2]); ZF_LOGD("MR 3: %zX", args[3]); ZF_LOGD("Breakpoint number %zu", args[1]); if (exception_reason == seL4_DataBreakpoint) { ZF_LOGD("Data breakpoint"); gdb_state.stop_watch_addr = args[2]; return stop_watch; } else if (exception_reason == seL4_InstructionBreakpoint) { ZF_LOGD("Hardware breakpoint"); return stop_hw_break; } else if (exception_reason == seL4_SingleStep && gdb_state.current_thread_step_mode) { return stop_step; } else if (exception_reason == seL4_SoftwareBreakRequest) { ZF_LOGD("Decrementing fault ep because of seL4 kernel behavior"); /* TODO This is a special case where the seL4 kernel gives us a fault instruction pointer that is no the faulting instruction. We decrement the pc to correct for this. In the future the kernel may end up changing the fault ip behavior and this decrement will then need to be removed to account for it. */ gdb_state.current_pc--; delegate_write_register(gdb_state.current_thread_tcb, gdb_state.current_pc, 0); return stop_sw_break; } else { return stop_none; } } else { ZF_LOGE("Unknown fault type: %zd", fault_type); ZF_LOGE("MR 0: %zX", args[0]); ZF_LOGE("MR 1: %zX", args[1]); ZF_LOGE("MR 2: %zX", args[2]); ZF_LOGE("MR 3: %zX", args[3]); return stop_none; } }
static seL4_timer_t * finish_get_tsc(seL4_timer_t *seL4_timer, pstimer_t *ps_timer) { if (ps_timer == NULL) { ZF_LOGE("Failed to init tsc"); free(seL4_timer); return NULL; } seL4_timer->timer = ps_timer; return seL4_timer; }
int sel4utils_new_pages_at_vaddr(vspace_t *vspace, void *vaddr, size_t num_pages, size_t size_bits, reservation_t reservation) { struct sel4utils_alloc_data *data = get_alloc_data(vspace); sel4utils_res_t *res = reservation_to_res(reservation); if (!check_reservation(data->top_level, res, (uintptr_t) vaddr, (uintptr_t)vaddr + num_pages * BIT(size_bits))) { ZF_LOGE("Range for vaddr %p with %"PRIuPTR" 4k pages not reserved!", vaddr, num_pages); return -1; } return new_pages_at_vaddr(vspace, vaddr, num_pages, size_bits, res->rights, res->cacheable); }
/* Handle an incoming IPC from a server node */ void irq_server_handle_irq_ipc(irq_server_t irq_server UNUSED) { seL4_Word badge; uintptr_t node_ptr; badge = seL4_GetMR(0); node_ptr = seL4_GetMR(1); if (node_ptr == 0) { ZF_LOGE("Invalid data in irq server IPC\n"); } else { irq_server_node_handle_irq((struct irq_server_node*)node_ptr, badge); } }
int tegra_mux_init(volatile void* pinmux_misc,volatile void* pinmux_aux, mux_sys_t* mux) { tegra_mux_state_t *state = malloc(sizeof(*state)); if (!state) { ZF_LOGE("Failed to malloc"); return 1; } state->pinmux_misc = pinmux_misc; state->pinmux_aux = pinmux_aux; mux->priv = state; return tegra_mux_init_common(mux); }
void app_tcpclient() { char *daddr = NULL, *dport = NULL; uint16_t send_port = 0, listen_port = short_be(5555); int i = 0, ret = 0, yes = 1; struct pico_socket *s = NULL; struct pico_ip4 dst = {0}; struct pico_ip4 inaddr = {0}; ZF_LOGD("Connecting to: %s:%d\n", daddr, short_be(send_port)); s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, &cb_tcpclient); if (!s) { ZF_LOGE("%s: error opening socket: %s\n", __FUNCTION__, strerror(pico_err)); } pico_socket_setoption(s, PICO_TCP_NODELAY, &yes); ret = pico_socket_bind(s, &inaddr, &listen_port); if (ret < 0) { ZF_LOGE("%s: error binding socket to port %u: %s\n", __FUNCTION__, short_be(listen_port), strerror(pico_err)); } // Set the destination address (string) above in the usual xxx.xxx.xxx.xxx ip4 way. pico_string_to_ipv4(daddr, &dst.addr); ret = pico_socket_connect(s, &dst, send_port); if (ret < 0) { ZF_LOGE("%s: error connecting to %s:%u: %s\n", __FUNCTION__, daddr, short_be(send_port), strerror(pico_err)); } ZF_LOGD("TCP client connected\n"); }
int mux_sys_init(ps_io_ops_t *io_ops, mux_sys_t *mux) { tegra_mux_state_t *state = malloc(sizeof(*state)); if (!state) { ZF_LOGE("Failed to malloc"); return 1; } state->pinmux_misc = (volatile void*)ps_io_map(&io_ops->io_mapper, MUX_PADDR_BASE, PAGE_SIZE_4K, 0, PS_MEM_NORMAL); if (!state->pinmux_misc) { ZF_LOGE("Failed to map pinmux page"); free(state); return 1; } state->pinmux_aux = (volatile void*)ps_io_map(&io_ops->io_mapper, MUX_AUX_PADDR_BASE, PAGE_SIZE_4K, 0, PS_MEM_NORMAL); if (!state->pinmux_aux) { ZF_LOGE("Failed to map auxialiary pinmux page"); ps_io_unmap(&io_ops->io_mapper, (void*)state->pinmux_misc, PAGE_SIZE_4K); free(state); return 1; } mux->priv = state; return tegra_mux_init_common(mux); }
seL4_timer_t * sel4platsupport_get_timer(enum timer_id id, vka_t *vka, vspace_t *vspace, simple_t *simple, seL4_CPtr notification) { timer_common_data_t *data; seL4_timer_t *timer; /* Allocate the timer structure */ timer = calloc(1, sizeof(*timer)); if (timer == NULL) { ZF_LOGE("Failed to allocate object of size %u\n", sizeof(seL4_timer_t)); return NULL; } /* init seL4 resources */ timer->handle_irq = timer_common_handle_irq; data = timer_common_init(vspace, simple, vka, notification, zynq_timer_irqs[id], (void*)zynq_timer_paddrs[id]); timer->data = data; if (timer->data == NULL) { free(timer); return NULL; } /* do hardware init */ timer_config_t config = { .vaddr = data->vaddr, }; timer->timer = ps_get_timer(id, &config); if (timer->timer == NULL) { timer_common_destroy(timer->data, vka, vspace); free(timer); return NULL; } /* success */ return timer; } seL4_timer_t * sel4platsupport_get_default_timer(vka_t *vka, vspace_t *vspace, simple_t *simple, seL4_CPtr notification) { return sel4platsupport_get_timer(TMR_DEFAULT, vka, vspace, simple, notification); }
int serial_server_kill(serial_client_context_t *conn) { seL4_MessageInfo_t tag; if (conn == NULL) { return seL4_InvalidArgument; } seL4_SetMR(SSMSGREG_FUNC, FUNC_KILL_REQ); tag = seL4_MessageInfo_new(0, 0, 0, SSMSGREG_KILL_REQ_END); tag = seL4_Call(conn->badged_server_ep_cspath.capPtr, tag); if (seL4_GetMR(SSMSGREG_FUNC) != FUNC_KILL_ACK) { ZF_LOGE(SERSERVC"kill: Reply message was not a KILL_ACK as expected."); return seL4_IllegalOperation; } return seL4_MessageInfo_get_label(tag); }
void serial_server_disconnect(serial_client_context_t *conn) { seL4_MessageInfo_t tag; if (conn == NULL) { return; } seL4_SetMR(SSMSGREG_FUNC, FUNC_DISCONNECT_REQ); tag = seL4_MessageInfo_new(0, 0, 0, SSMSGREG_DISCONNECT_REQ_END); tag = seL4_Call(conn->badged_server_ep_cspath.capPtr, tag); if (seL4_GetMR(SSMSGREG_FUNC) != FUNC_DISCONNECT_ACK) { ZF_LOGE(SERSERVC"disconnect: reply message was not a DISCONNECT_ACK " "as expected."); } }
void pre_init(void) { struct pico_ip4 netmask, ipaddr, gw, multicast, zero = {0}; pico_device_eth *pico_driver; memset(&io_ops, 0, sizeof(io_ops)); io_ops.dma_manager = (ps_dma_man_t) { .cookie = NULL, .dma_alloc_fn = malloc_dma_alloc, .dma_free_fn = malloc_dma_free, .dma_pin_fn = malloc_dma_pin, .dma_unpin_fn = malloc_dma_unpin, .dma_cache_op_fn = malloc_dma_cache_op }; /* Initialise the PicoTCP stack */ pico_stack_init(); /* Create a driver. This utilises preallocated buffers, backed up by malloc above */ pico_driver = pico_eth_create_no_malloc("eth0", ethdriver_init, NULL, io_ops, &_picotcp_driver); assert(pico_driver); pico_string_to_ipv4("0.0.0.0", &gw.addr); pico_string_to_ipv4(server_ip_addr, &ipaddr.addr); pico_string_to_ipv4(multicast_addr, &multicast.addr); pico_string_to_ipv4("255.255.255.0", &netmask.addr); pico_ipv4_link_add(pico_driver, ipaddr, netmask); pico_ipv4_route_add(zero, zero, gw, 1, NULL); if (pico_ipv4_is_multicast(multicast.addr)) { ZF_LOGE("Multicast not yet implemented\n"); // PicoTCP usually deals with multicast at the socket layer, using pico_socket_setoption. // It can be done at the igmp level too by using igmp_state_change. See the picoTCP documentation // Eg: pico_igmp_state_change(&ipaddr, &multicast, .... ); } /* Start the timer for tcp */ // TCP runs off a tick for handling events and timeouts. timer_periodic(0, NS_IN_MS * PICO_TICK_MS); start_tcpecho(); }
ethif_virtio_emul_t *ethif_virtio_emul_init(ps_io_ops_t io_ops, int queue_size, virtio_emul_vm_t *emul_vm, ethif_driver_init driver, void *config) { ethif_virtio_emul_t *emul = NULL; ethif_virtio_emul_internal_t *internal = NULL; int err; emul = malloc(sizeof(*emul)); internal = malloc(sizeof(*internal)); if (!emul || !internal) { goto error; } memset(emul, 0, sizeof(*emul)); memset(internal, 0, sizeof(*internal)); emul->internal = internal; emul->io_in = emul_io_in; emul->io_out = emul_io_out; emul->notify = emul_notify; internal->queue_size[RX_QUEUE] = queue_size; internal->queue_size[TX_QUEUE] = queue_size; /* create dummy rings. we never actually dereference the rings so they can be null */ vring_init(&internal->vring[RX_QUEUE], emul->internal->queue_size[RX_QUEUE], 0, VIRTIO_PCI_VRING_ALIGN); vring_init(&internal->vring[TX_QUEUE], emul->internal->queue_size[RX_QUEUE], 0, VIRTIO_PCI_VRING_ALIGN); internal->driver.cb_cookie = emul; internal->driver.i_cb = emul_callbacks; internal->dma_man = io_ops.dma_manager; internal->emul_vm = emul_vm; err = driver(&internal->driver, io_ops, config); if (err) { ZF_LOGE("Fafiled to initialize driver"); goto error; } int mtu; internal->driver.i_fn.low_level_init(&internal->driver, internal->mac, &mtu); return emul; error: if (emul) { free(emul); } if (internal) { free(internal); } return NULL; }
ssize_t serial_server_write(serial_client_context_t *conn, const char *in_buff, ssize_t len) { if (in_buff == NULL || conn == NULL || conn->shmem == NULL) { ZF_LOGE(SERSERVC"printf: NULL passed for required arguments.\n" "\tIs connection handle valid?"); return -seL4_InvalidArgument; } if (len > conn->shmem_size) { return -seL4_RangeError; } if (len == 0) { return 0; } memcpy((void *)conn->shmem, in_buff, len); /* Else, send it off to the server. */ return serial_server_write_ipc_invoke(conn, len); }