--- /dev/null
+# Makefile for GeekOS kernel, userspace, and tools
+#
+# Northwestern University
+# (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
+# (c) 2008, Peter Dinda <pdinda@northwestern.edu>
+# (c) 2008, Lei Xia <xiaxlei@gmail.com>
+# (c) 2008, The V3VEE Project <http://www.v3vee.org>
+#
+# Based on GeekOS Makefile:
+# Copyright (c) 2004,2005 David H. Hovemeyer <daveho@cs.umd.edu>
+# $Revision: 1.71 $
+
+
+# This is free software. You are permitted to use,
+# redistribute, and modify it as specified in the file "COPYING".
+
+# Required software to build GeekOS:
+# - GNU Make (http://www.gnu.org/software/make)
+# - gcc 2.95.2 generating code for target (i386/ELF) and host platforms
+# - nasm (http://nasm.sourceforge.net)
+# - Perl5, AWK (any version), egrep
+#
+# Cygwin (http://cygwin.com) may be used to build GeekOS.
+# Make sure that gcc, binutils, nasm, and perl are installed.
+
+# NOTES:
+# - This makefile has been written carefully to work correctly
+# with the -j (parallel make) option. I regularly use "make -j 2"
+# to speed the build process on 2 processor systems.
+
+
+# Base address of kernel
+#
+# Note: at top of memory minus three pages (GDT/TSS/IDT)
+# minus maximum size
+#
+#
+# Note that the code will initially load at 0x10000
+#
+# The setup code needs to copy it up to this address and jump there
+#
+KERNEL_BASE_ADDR := 0x00100000
+
+# Kernel entry point function
+KERNEL_ENTRY = $(SYM_PFX)Main
+
+
+PROJECT_ROOT := ..
+V3_ROOT := $(PROJECT_ROOT)/../palacios
+VPATH := $(PROJECT_ROOT)/src
+
+
+
+#
+#TCPSTACK, uIP is used currently
+#
+TCPSTACK=UIP
+
++#
++#TCPSTACK, uIP is used currently
++#
++UIP=OFF
+
++#
++#LWIP, ON -- used, OFF -- not used
++#
++LWIP=ON
+
+
+#
+# This is wrong for current cygwin - no changes needed
+#
+# Figure out if we're compiling with cygwin, http://cygwin.com
+#
+#
+#SYSTEM_NAME := $(shell uname -s)
+#ifeq ($(findstring CYGWIN,$(SYSTEM_NAME)),CYGWIN)
+#SYM_PFX := _
+#EXTRA_C_OPTS := -DNEED_UNDERSCORE -DGNU_WIN32
+#EXTRA_NASM_OPTS := -DNEED_UNDERSCORE
+#NON_ELF_SYSTEM := yes
+#EXTRA_CC_USER_OPTS := -Dmain=geekos_main
+#endif
+
+
+
+
+# ----------------------------------------------------------------------
+# Configuration -
+# Various options specifying how GeekOS should be built,
+# what source files to build, which user programs to build,
+# etc. This is generally the only section of the makefile
+# that will need to be modified.
+# ----------------------------------------------------------------------
+
+# List of targets to build by default.
+# These targets encompass everything needed to boot
+# and run GeekOS.
+ALL_TARGETS := vmm.img
+
+
+# Kernel source files
+KERNEL_C_SRCS := idt.c int.c trap.c irq.c io.c \
+ blockdev.c ide.c ne2k.c \
+ keyboard.c screen.c timer.c \
+ mem.c crc32.c \
+ gdt.c tss.c segment.c \
+ bget.c malloc.c \
+ synch.c kthread.c \
+ serial.c reboot.c \
+ paging.c \
+ debug.c vmm_stubs.c vm.c pci.c\
+ queue.c socket.c net.c ring_buffer.c \
+ main.c
+
+
+# Kernel object files built from C source files
+KERNEL_C_OBJS := $(KERNEL_C_SRCS:%.c=geekos/%.o)
+
+# Kernel assembly files
+KERNEL_ASM_SRCS := lowlevel.asm
+
+KERNEL_GAS_SRCS :=
+
+# Kernel object files build from assembler source files
+KERNEL_ASM_OBJS := $(KERNEL_ASM_SRCS:%.asm=geekos/%.o)
+
+KERNEL_GAS_OBJS := $(KERNEL_GAS_SRCS:%.s=geekos/%.o)
+
+
+# All kernel object files
+KERNEL_OBJS := $(KERNEL_C_OBJS) \
+ $(KERNEL_ASM_OBJS) $(KERNEL_GAS_OBJS)
+
+# Common library source files.
+# This library is linked into both the kernel and user programs.
+# It provides string functions and generic printf()-style
+# formatted output.
+COMMON_C_SRCS := fmtout.c string.c memmove.c
+
+# Common library object files.
+COMMON_C_OBJS := $(COMMON_C_SRCS:%.c=common/%.o)
+
+
+
+
+V3_LD_FLAGS := -L./palacios/
+#V3_LIBS := -lxed -lv3vee
+V3_LIBS := ./palacios/libxed.a ./palacios/libv3vee.a ./palacios/libxed.a ./palacios/libv3vee.a
+
+
+
- TCPSTACK_C_SRCS := psock.c timer.c uip_arp.c uip.c uip-fw.c uiplib.c uip-neighbor.c uip-split.c resolv.c
+
- TCPSTACK_C_OBJS := $(TCPSTACK_C_SRCS:%.c=net/%.o)
+
- TCPSTACK_OBJS := $(TCPSTACK_C_OBJS)
+
++ifeq ($(UIP),ON)
++ UIP_C_SRCS := psock.c timer.c uip_arp.c uip.c uip-fw.c uiplib.c uip-neighbor.c uip-split.c resolv.c
++ UIP_C_OBJS := $(UIP_C_SRCS:%.c=net/%.o)
++else
++ UIP_C_SRCS :=
++ UIP_C_OBJS :=
++endif
++
++ifeq ($(LWIP),ON)
++ LWIP_OBJS := lwip/*.o
++ CC_LWIP_OPTS := -I$(PROJECT_ROOT)/include/lwip -I$(PROJECT_ROOT)/include/lwip/ipv4 -I$(PROJECT_ROOT)/include/libc -DLWIP_DEBUG
++else
++ LWIP_OBJS :=
++ CC_LWIP_OPTS :=
++endif
+
++TCPSTACK_OBJS := $(UIP_C_OBJS) $(LWIP_OBJS)
+
+
+# ----------------------------------------------------------------------
+# Tools -
+# This section defines programs that are used to build GeekOS.
+# ----------------------------------------------------------------------
+
+# Uncomment if cross compiling
+TARGET_CC_PREFIX := $(PROJECT_ROOT)/../devtools/i386/bin/i386-elf-
+#TARGET_CC_PREFIX := i386-elf-
+
+# Target C compiler. gcc 2.95.2 or later should work.
+TARGET_CC := $(TARGET_CC_PREFIX)gcc
+#TARGET_CC := $(TARGET_CC_PREFIX)gcc34 -m32
+
+# Host C compiler. This is used to compile programs to execute on
+# the host platform, not the target (x86) platform. On x86/ELF
+# systems, such as Linux and FreeBSD, it can generally be the same
+# as the target C compiler.
+HOST_CC := gcc
+
+# Target linker. GNU ld is probably to only one that will work.
+TARGET_LD := $(TARGET_CC_PREFIX)ld -melf_i386
+
+# Target archiver
+TARGET_AR := $(TARGET_CC_PREFIX)ar
+
+# Target ranlib
+TARGET_RANLIB := $(TARGET_CC_PREFIX)ranlib
+
+# Target nm
+TARGET_NM := $(TARGET_CC_PREFIX)nm
+
+# Target objcopy
+TARGET_OBJCOPY := $(TARGET_CC_PREFIX)objcopy
+
+# Nasm (http://nasm.sourceforge.net)
+NASM := $(PROJECT_ROOT)/../devtools/bin/nasm
+#NASM := /opt/vmm-tools/bin/nasm
+
+AS = as --32
+
+# Tool to build PFAT filesystem images.
+BUILDFAT := tools/builtFat.exe
+
+# Perl5 or later
+PERL := perl
+
+# Pad a file so its size is a multiple of some unit (i.e., sector size)
+PAD := $(PERL) $(PROJECT_ROOT)/scripts/pad
+
+# Create a file filled with zeroes.
+ZEROFILE := $(PERL) $(PROJECT_ROOT)/scripts/zerofile
+
+# Calculate size of file in sectors
+NUMSECS := $(PERL) $(PROJECT_ROOT)/scripts/numsecs
+
+
+FD_SECTORS_PER_TRACK := $(PERL) $(PROJECT_ROOT)/scripts/numsecs_per_track
+
+
+# ----------------------------------------------------------------------
+# Definitions -
+# Options passed to the tools.
+# ----------------------------------------------------------------------
+
+# Flags used for all C source files
+GENERAL_OPTS := -O -Wall $(EXTRA_C_OPTS) $(BOOT_FLAGS) -fPIC
+CC_GENERAL_OPTS := $(GENERAL_OPTS) -Werror
+
+# Flags used for kernel C source files
+CC_KERNEL_OPTS := -g -DGEEKOS -I$(PROJECT_ROOT)/include -I$(V3_ROOT)/include
+
+
+# Flags user for kernel assembly files
+NASM_KERNEL_OPTS := -I$(PROJECT_ROOT)/src/geekos/ -f elf $(EXTRA_NASM_OPTS)
+
+# Flags used for common library and libc source files
+CC_USER_OPTS := -I$(PROJECT_ROOT)/include -I$(PROJECT_ROOT)/include/libc \
+ $(EXTRA_CC_USER_OPTS) -I$(V3_ROOT)/include
+
+# Flags passed to objcopy program (strip unnecessary sections from kernel.exe)
+OBJCOPY_FLAGS := -R .dynamic -R .note -R .comment
+
+# ----------------------------------------------------------------------
+# Rules -
+# Describes how to compile the source files.
+# ----------------------------------------------------------------------
+
+# Compilation of kernel C source files
+
+geekos/%.o : geekos/%.c
- $(TARGET_CC) -c $(CC_GENERAL_OPTS) $(CC_KERNEL_OPTS) $< -o geekos/$*.o
++ $(TARGET_CC) -c $(CC_GENERAL_OPTS) $(CC_KERNEL_OPTS) $(CC_LWIP_OPTS) $< -o geekos/$*.o
+
+
+# Compilation of kernel assembly source files
+geekos/%.o : geekos/%.asm
+ $(NASM) $(NASM_KERNEL_OPTS) $< -o geekos/$*.o
+
+
+# Compilation of common library C source files
+common/%.o : common/%.c
+ $(TARGET_CC) -c $(CC_GENERAL_OPTS) $(CC_USER_OPTS) $< -o common/$*.o
+
+
+net/%.o : net/%.c
+ $(TARGET_CC) -c $(CC_GENERAL_OPTS) $(CC_USER_OPTS) $< -o net/$*.o
+
+# ----------------------------------------------------------------------
+# Targets -
+# Specifies files to be built
+# ----------------------------------------------------------------------
+
+# Default target - see definition of ALL_TARGETS in Configuration section
+all : $(ALL_TARGETS)
+
+
+#geekos/vmx_lowlevel.o: $(PROJECT_ROOT)/src/geekos/vmx_lowlevel.asm
+# $(NASM) -O99 \
+# -f elf \
+# -I$(PROJECT_ROOT)/src/geekos/ \
+# $(PROJECT_ROOT)/src/geekos/vmx_lowlevel.asm \
+# -o $@
+
+
+#geekos/test: geekos/test.o geekos/vmcs.o geekos/vmx_lowlevel.o
+# $(CC) geekos/test.o geekos/vmcs.o geekos/vmx_lowlevel.o -o geekos/test
+
+# Standard floppy image - just boots the kernel
+fd.img : geekos/fd_boot.bin geekos/setup.bin geekos/kernel.bin
+ cat geekos/fd_boot.bin geekos/setup.bin geekos/kernel.bin > _temp
+ $(PAD) _temp 512
+ cp _temp fd.img
+
+
+vmm.img: fd.img
+ cp fd.img vmm.img
+ $(PAD) vmm.img 1474560
+
+
+
+
+
+
+# Floppy boot sector (first stage boot loader).
+geekos/fd_boot.bin : geekos/setup.bin geekos/kernel.bin $(PROJECT_ROOT)/src/geekos/fd_boot.asm
+ $(NASM) -f bin \
+ -I$(PROJECT_ROOT)/src/geekos/ \
+ -DNUM_SETUP_SECTORS=`$(NUMSECS) geekos/setup.bin` \
+ -DNUM_KERN_SECTORS=`$(NUMSECS) geekos/kernel.bin` \
+ -DSECTORS_PER_TRACK=`$(FD_SECTORS_PER_TRACK) geekos/kernel.bin geekos/setup.bin` \
+ $(PROJECT_ROOT)/src/geekos/fd_boot.asm \
+ -o $@
+
+# Setup program (second stage boot loader).
+geekos/setup.bin : geekos/kernel.bin $(PROJECT_ROOT)/src/geekos/setup.asm
+ $(NASM) -f bin \
+ -I$(PROJECT_ROOT)/src/geekos/ \
+ -DENTRY_POINT=0x`egrep 'Main$$' geekos/kernel.syms |awk '{print $$1}'` \
+ -DVMM_SIZE=`$(NUMSECS) geekos/kernel.bin` \
+ $(PROJECT_ROOT)/src/geekos/setup.asm \
+ -o $@
+ $(PAD) $@ 2048
+
+# Loadable (flat) kernel image.
+geekos/kernel.bin : geekos/kernel.exe
+ $(TARGET_OBJCOPY) $(OBJCOPY_FLAGS) -S -O binary geekos/kernel.exe geekos/kernel.bin
+ $(PAD) $@ 512
+
+# The kernel executable and symbol map.
+geekos/kernel.exe : $(KERNEL_OBJS) $(COMMON_C_OBJS) $(TCPSTACK_OBJS)
+ $(TARGET_LD) -o geekos/kernel.exe -Ttext $(KERNEL_BASE_ADDR) -e $(KERNEL_ENTRY) \
+ $(V3_LD_FLAGS) \
+ $(KERNEL_OBJS) $(COMMON_C_OBJS) $(TCPSTACK_OBJS) $(V3_LIBS) -b binary ./palacios/vm_kernel
+ $(TARGET_NM) geekos/kernel.exe > geekos/kernel.syms
+
+
+force:
+
+
+#vm_kernel: force
+# $(PAD) vm_kernel 512
+# @echo "VM kernel lives at 0x100000 and is" `$(NUMSECS) vm_kernel` "sectors long"
+
+
+
+
+# Clean build directories of generated files
+clean :
+ for d in geekos common libc user tools net; do \
+ (cd $$d && rm -f *); \
+ done
+
+
+# Build header file dependencies, so source files are recompiled when
+# header files they depend on are modified.
+depend : $(GENERATED_LIBC_SRCS)
+ $(TARGET_CC) -M $(CC_GENERAL_OPTS) $(CC_KERNEL_OPTS) \
+ $(KERNEL_C_SRCS:%.c=$(PROJECT_ROOT)/src/geekos/%.c) \
+ | $(PERL) -n -e 's,^(\S),geekos/$$1,;print' \
+ > depend.mak
+ $(TARGET_CC) -M $(CC_GENERAL_OPTS) $(CC_USER_OPTS) \
+ $(COMMON_C_SRCS:%.c=$(PROJECT_ROOT)/src/common/%.c) \
+ | $(PERL) -n -e 's,^(\S),common/$$1,;print' \
+ >> depend.mak
+
+
+# By default, there are no header file dependencies.
+depend.mak :
+ touch $@
+
+include depend.mak
--- /dev/null
--- /dev/null
++#ifndef __PING_H__
++#define __PING_H__
++
++void ping_init(void);
++
++#endif /* __PING_H__ */
--- /dev/null
--- /dev/null
++/* ne2k network interface for lwip\r
++ *\r
++ * Lei Xia (lxia@northwestern.edu)\r
++ */
++
++#ifndef __NETIF_NE2KIF_H__
++#define __NETIF_NE2KIF_H__
++
++#include <lwip/lwip/netif.h>
++#include <lwip/lwip/err.h>
++#include <geekos/ktypes.h>
++#include <geekos/ne2k.h>
++
++extern struct netif ne2kif;
++
++err_t ne2kif_init(struct netif *netif);
++
++void ne2kif_input(struct NE2K_Packet_Info * info, uchar_t * pkt);
++
++err_t ne2kif_output(struct netif * netif, struct pbuf * p);
++
++#endif /*__NETIF_NE2KIF_H__*/
--- /dev/null
--- /dev/null
++/**
++ * @file
++ * Ping sender module
++ *
++ */
++
++/*
++ * Redistribution and use in source and binary forms, with or without modification,
++ * are permitted provided that the following conditions are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote products
++ * derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
++ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
++ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
++ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
++ * OF SUCH DAMAGE.
++ *
++ * This file is part of the lwIP TCP/IP stack.
++ *
++ */
++
++/**
++ * This is an example of a "ping" sender (with raw API and socket API).
++ * It can be used as a start point to maintain opened a network connection, or
++ * like a network "watchdog" for your device.
++ *
++ */
++
++#include "lwip/opt.h"
++
++#if LWIP_RAW && LWIP_ICMP /* don't build if not configured for use in lwipopts.h */
++
++#include "lwip/mem.h"
++#include "lwip/raw.h"
++#include "lwip/icmp.h"
++#include "lwip/netif.h"
++#include "lwip/sys.h"
++#include "lwip/sockets.h"
++#include "lwip/inet.h"
++#include "lwip/inet_chksum.h"
++
++#include "apps/ping.h"
++
++#include <geekos/timer.h>
++#include <geekos/ktypes.h>
++
++/**
++ * PING_DEBUG: Enable debugging for PING.
++ */
++#ifndef PING_DEBUG
++#define PING_DEBUG LWIP_DBG_ON
++#endif
++
++/** ping target - should be a "struct ip_addr" */
++#ifndef PING_TARGET
++#define PING_TARGET (netif_default?netif_default->gw:ip_addr_any)
++#endif
++
++/** ping receive timeout - in milliseconds */
++#ifndef PING_RCV_TIMEO
++#define PING_RCV_TIMEO 1000
++#endif
++
++/** ping delay - in milliseconds */
++#ifndef PING_DELAY
++#define PING_DELAY 1000
++#endif
++
++/** ping identifier - must fit on a u16_t */
++#ifndef PING_ID
++#define PING_ID 0xAFAF
++#endif
++
++/** ping additional data size to include in the packet */
++#ifndef PING_DATA_SIZE
++#define PING_DATA_SIZE 32
++#endif
++
++/** ping result action - no default action */
++#ifndef PING_RESULT
++#define PING_RESULT(ping_ok)
++#endif
++
++/* ping variables */
++static u16_t ping_seq_num;
++static u32_t ping_time;
++
++#if NO_SYS
++/* port-defined functions used for timer execution */
++void sys_msleep(u32_t ms);
++u32_t sys_now();
++#endif /* NO_SYS */
++
++/** Prepare a echo ICMP request */
++static void
++ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len)
++{
++ int i;
++
++ ICMPH_TYPE_SET(iecho,ICMP_ECHO);
++ ICMPH_CODE_SET(iecho, 0);
++ iecho->chksum = 0;
++ iecho->id = PING_ID;
++ iecho->seqno = htons(++ping_seq_num);
++ iecho->chksum = inet_chksum(iecho, len);
++
++ /* fill the additional data buffer with some data */
++ for(i = 0; i < PING_DATA_SIZE; i++) {
++ ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = i;
++ }
++}
++
++#if LWIP_SOCKET
++
++/* Ping using the socket ip */
++static err_t
++ping_send(int s, struct ip_addr *addr)
++{
++ int err;
++ struct icmp_echo_hdr *iecho;
++ struct sockaddr_in to;
++ size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE;
++
++ if (!(iecho = mem_malloc(ping_size))) {
++ return ERR_MEM;
++ }
++
++ ping_prepare_echo(iecho, ping_size);
++
++ to.sin_len = sizeof(to);
++ to.sin_family = AF_INET;
++ to.sin_addr.s_addr = addr->addr;
++
++ err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to));
++
++ mem_free(iecho);
++
++ return (err ? ERR_OK : ERR_VAL);
++}
++
++static void
++ping_recv(int s)
++{
++ char buf[64];
++ int fromlen, len;
++ struct sockaddr_in from;
++ struct ip_hdr *iphdr;
++ struct icmp_echo_hdr *iecho;
++
++ while((len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, (socklen_t*)&fromlen)) > 0) {
++ if (len >= (sizeof(struct ip_hdr)+sizeof(struct icmp_echo_hdr))) {
++ LWIP_DEBUGF( PING_DEBUG, ("ping: recv "));
++ ip_addr_debug_print(PING_DEBUG, (struct ip_addr *)&(from.sin_addr));
++ LWIP_DEBUGF( PING_DEBUG, (" %lu ms\n", (sys_now()-ping_time)));
++
++ iphdr = (struct ip_hdr *)buf;
++ iecho = (struct icmp_echo_hdr *)(buf+(IPH_HL(iphdr) * 4));
++ if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num))) {
++ /* do some ping result processing */
++ PING_RESULT((ICMPH_TYPE(iecho) == ICMP_ER));
++ return;
++ } else {
++ LWIP_DEBUGF( PING_DEBUG, ("ping: drop\n"));
++ }
++ }
++ }
++
++ if (len == 0) {
++ LWIP_DEBUGF( PING_DEBUG, ("ping: recv - %lu ms - timeout\n", (sys_now()-ping_time)));
++ }
++
++ /* do some ping result processing */
++ PING_RESULT(0);
++}
++
++static void
++ping_thread(void *arg)
++{
++ int s;
++ int timeout = PING_RCV_TIMEO;
++ struct ip_addr ping_target;
++
++ LWIP_UNUSED_ARG(arg);
++
++ if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) {
++ return;
++ }
++
++ lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
++
++ while (1) {
++ ping_target = PING_TARGET;
++
++ if (ping_send(s, &ping_target) == ERR_OK) {
++ LWIP_DEBUGF( PING_DEBUG, ("ping: send "));
++ ip_addr_debug_print(PING_DEBUG, &ping_target);
++ LWIP_DEBUGF( PING_DEBUG, ("\n"));
++
++ ping_time = sys_now();
++ ping_recv(s);
++ } else {
++ LWIP_DEBUGF( PING_DEBUG, ("ping: send "));
++ ip_addr_debug_print(PING_DEBUG, &ping_target);
++ LWIP_DEBUGF( PING_DEBUG, (" - error\n"));
++ }
++ sys_msleep(PING_DELAY);
++ }
++}
++
++#else /* LWIP_SOCKET */
++
++/* Ping using the raw ip */
++static u8_t
++ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *addr)
++{
++ struct icmp_echo_hdr *iecho;
++
++ if (pbuf_header( p, -PBUF_IP_HLEN)==0) {
++ iecho = p->payload;
++
++ if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num))) {
++ LWIP_DEBUGF( PING_DEBUG, ("ping: recv "));
++ ip_addr_debug_print(PING_DEBUG, addr);
++ LWIP_DEBUGF( PING_DEBUG, (" %lu ms\n", (sys_now()-ping_time)));
++
++ /* do some ping result processing */
++ PING_RESULT(1);
++ }
++ }
++
++ return 1; /* eat the event */
++}
++
++static void
++ping_send(struct raw_pcb *raw, struct ip_addr *addr)
++{
++ struct pbuf *p;
++ struct icmp_echo_hdr *iecho;
++ size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE;
++
++ if (!(p = pbuf_alloc(PBUF_IP, ping_size, PBUF_RAM))) {
++ return;
++ }
++ if ((p->len == p->tot_len) && (p->next == NULL)) {
++ iecho = p->payload;
++
++ ping_prepare_echo(iecho, ping_size);
++
++ raw_sendto(raw, p, addr);
++ ping_time = sys_now();
++ }
++ pbuf_free(p);
++}
++
++static void
++ping_timeout(void *arg)
++{
++ struct raw_pcb *pcb = (struct raw_pcb*)arg;
++ struct ip_addr ping_target = PING_TARGET;
++
++ LWIP_ASSERT("ping_timeout: no pcb given!", pcb != NULL);
++
++ LWIP_DEBUGF( PING_DEBUG, ("ping: send "));
++ ip_addr_debug_print(PING_DEBUG, &ping_target);
++ LWIP_DEBUGF( PING_DEBUG, ("\n"));
++
++ ping_send(pcb, &ping_target);
++
++ sys_timeout(PING_DELAY, ping_timeout, pcb);
++}
++
++static void
++ping_raw_init(void)
++{
++ struct raw_pcb *pcb;
++
++ if (!(pcb = raw_new(IP_PROTO_ICMP))) {
++ return;
++ }
++
++ raw_recv(pcb, ping_recv, NULL);
++ raw_bind(pcb, IP_ADDR_ANY);
++ sys_timeout(PING_DELAY, ping_timeout, pcb);
++}
++
++#endif /* LWIP_SOCKET */
++
++void
++ping_init(void)
++{
++#if LWIP_SOCKET
++ sys_thread_new("ping_thread", ping_thread, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
++#else /* LWIP_SOCKET */
++ ping_raw_init();
++#endif /* LWIP_SOCKET */
++}
++
++
++u32_t
++sys_now()
++{
++ ulong_t msec;
++
++ msec = clock_time();
++
++ return msec;
++}
++
++#endif /* LWIP_RAW && LWIP_ICMP */
--- /dev/null
--- /dev/null
++/**\r
++ * @file\r
++ * Ethernet Interface for ne2k device\r
++ *\r
++ * Lei Xia (lxia@northwestern.edu\r
++ */\r
++\r
++#include "lwip/opt.h"\r
++ \r
++\r
++#include "lwip/def.h"\r
++#include "lwip/mem.h"\r
++#include "lwip/pbuf.h"\r
++#include "lwip/sys.h"\r
++#include <lwip/stats.h>\r
++#include <lwip/snmp.h>\r
++#include "netif/etharp.h"\r
++#include "netif/ppp_oe.h"\r
++#include "lwip/netifapi.h"\r
++#include "netif/ne2kif.h"\r
++\r
++\r
++#include <geekos/ne2k.h>\r
++#include <geekos/ktypes.h>\r
++#include <geekos/debug.h>\r
++\r
++\r
++struct netif ne2kif; \r
++\r
++/**\r
++ * This function should do the actual transmission of the packet. The packet is\r
++ * contained in the pbuf that is passed to the function. This pbuf\r
++ * might be chained.\r
++ *\r
++ * @param netif the lwip network interface structure for this ethernetif\r
++ * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)\r
++ * @return ERR_OK if the packet could be sent\r
++ * an err_t value if the packet couldn't be sent\r
++ *\r
++ * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to\r
++ * strange results. You might consider waiting for space in the DMA queue\r
++ * to become availale since the stack doesn't retry to send a packet\r
++ * dropped because of memory failure (except for the TCP timers).\r
++ */\r
++\r
++err_t\r
++ne2kif_output(struct netif *netif, struct pbuf *p)\r
++{\r
++ struct pbuf *q;\r
++ int size, offset, remlen;\r
++ uchar_t *packet;\r
++ \r
++#if ETH_PAD_SIZE\r
++ pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */\r
++#endif\r
++\r
++ size = p->tot_len;\r
++ offset = 0;\r
++ remlen = size;\r
++\r
++ packet = (uchar_t *)Malloc (remlen);\r
++\r
++ for(q = p; q != NULL && remlen >0; q = q->next) {\r
++ /* Send the data from the pbuf to the interface, one pbuf at a\r
++ time. The size of the data in each pbuf is kept in the ->len\r
++ variable. */\r
++\r
++ memcpy(packet+offset, q->payload, q->len < remlen? q->len:remlen);\r
++ remlen -= q->len;\r
++ offset += q->len;\r
++ \r
++ }\r
++ NE2K_Send_Packet(packet, size);\r
++\r
++ //signal that packet should be sent();\r
++\r
++#if ETH_PAD_SIZE\r
++ pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */\r
++#endif\r
++ \r
++ LINK_STATS_INC(link.xmit);\r
++\r
++ return ERR_OK;\r
++}\r
++\r
++\r
++/**\r
++ * This function should be called when a packet is ready to be read\r
++ * from the interface. It uses the function low_level_input() that\r
++ * should handle the actual reception of bytes from the network\r
++ * interface. Then the type of the received packet is determined and\r
++ * the appropriate input function is called.\r
++ *\r
++ * @param netif the lwip network interface structure for this ethernetif\r
++ */\r
++void\r
++ne2kif_input(struct NE2K_Packet_Info * info, uchar_t * pkt)\r
++{\r
++ struct pbuf *p, *q;\r
++ uint_t offset;\r
++ uint_t len, rlen;\r
++ \r
++ len = info->size; \r
++\r
++ PrintBoth("Ne2k: Packet REceived\n");\r
++\r
++#if ETH_PAD_SIZE\r
++ len += ETH_PAD_SIZE; // allow room for Ethernet padding \r
++#endif\r
++\r
++ p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);\r
++ \r
++ if (p != NULL) {\r
++\r
++#if ETH_PAD_SIZE\r
++ pbuf_header(p, -ETH_PAD_SIZE); // drop the padding word \r
++#endif\r
++\r
++ // iterate over the pbuf chain until it has read the entire packet into the pbuf.\r
++ for(offset = 0, q = p; q != NULL && rlen > 0; q = q->next) {\r
++ memcpy(q->payload, pkt+offset, rlen > q->len? q->len: rlen);\r
++ rlen -= q->len;\r
++ offset += q->len;\r
++ }\r
++\r
++#if ETH_PAD_SIZE\r
++ pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */\r
++#endif\r
++\r
++ LINK_STATS_INC(link.recv);\r
++ } else {\r
++ LINK_STATS_INC(link.memerr);\r
++ LINK_STATS_INC(link.drop);\r
++ }\r
++\r
++ Free(pkt);\r
++ \r
++ if (p == NULL) return;\r
++ /* points to packet payload, which starts with an Ethernet header */\r
++ //ethhdr = p->payload;\r
++\r
++ /* full packet send to tcpip_thread to process */\r
++ if (ne2kif.input(p, &ne2kif)!=ERR_OK)\r
++ { LWIP_DEBUGF(NETIF_DEBUG, ("ne2kif_input: IP input error\n"));\r
++ pbuf_free(p);\r
++ p = NULL;\r
++ }\r
++\r
++#if 0\r
++ switch (htons(ethhdr->type)) {\r
++ /* IP or ARP packet? */\r
++ case ETHTYPE_IP:\r
++ case ETHTYPE_ARP:\r
++#if PPPOE_SUPPORT\r
++ /* PPPoE packet? */\r
++ case ETHTYPE_PPPOEDISC:\r
++ case ETHTYPE_PPPOE:\r
++#endif /* PPPOE_SUPPORT */\r
++ \r
++ break;\r
++\r
++ default:\r
++ pbuf_free(p);\r
++ p = NULL;\r
++ break;\r
++ }\r
++#endif\r
++\r
++}\r
++\r
++/**\r
++ * Should be called at the beginning of the program to set up the\r
++ * network interface. It calls the function low_level_init() to do the\r
++ * actual setup of the hardware.\r
++ *\r
++ * This function should be passed as a parameter to netif_add().\r
++ *\r
++ * @param netif the lwip network interface structure for this ethernetif\r
++ * @return ERR_OK if the loopif is initialized\r
++ * ERR_MEM if private data couldn't be allocated\r
++ * any other err_t on error\r
++ */\r
++err_t\r
++ne2kif_init(struct netif *netif)\r
++{\r
++\r
++#if LWIP_NETIF_HOSTNAME\r
++ /* Initialize interface hostname */\r
++ netif->hostname = "lwip";\r
++#endif /* LWIP_NETIF_HOSTNAME */\r
++\r
++ /*\r
++ * Initialize the snmp variables and counters inside the struct netif.\r
++ * The last argument should be replaced with your link speed, in units\r
++ * of bits per second.\r
++ */\r
++ NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);\r
++\r
++ netif->state = NULL;\r
++ netif->name[0] = 'n';\r
++ netif->name[1] = 'e';\r
++ /* We directly use etharp_output() here to save a function call.\r
++ * You can instead declare your own function an call etharp_output()\r
++ * from it if you have to do some checks before sending (e.g. if link\r
++ * is available...) */\r
++ netif->output = etharp_output;\r
++ netif->linkoutput = ne2kif_output;\r
++ \r
++\r
++ /* set MAC hardware address length */\r
++ netif->hwaddr_len = ETHARP_HWADDR_LEN;\r
++\r
++ /* set MAC hardware address */\r
++ netif->hwaddr[0] = PHY_ADDR1;\r
++ netif->hwaddr[1] = PHY_ADDR2;\r
++ netif->hwaddr[2] = PHY_ADDR3;\r
++ netif->hwaddr[3] = PHY_ADDR4;\r
++ netif->hwaddr[4] = PHY_ADDR5;\r
++ netif->hwaddr[5] = PHY_ADDR6;\r
++\r
++ /* maximum transfer unit */\r
++ netif->mtu = 1500;\r
++ \r
++ /* device capabilities */\r
++ /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */\r
++ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;\r
++\r
++ //initate ne2k hardware\r
++ Init_Ne2k(&ne2kif_input);\r
++\r
++ return ERR_OK;\r
++}\r
+XED_C_SRCS := v3-xed-compat.c
-DEVICE_C_SRCS := generic.c keyboard.c nvram.c timer.c simple_pic.c 8259a.c 8254.c serial.c $(RAMDISK_SRCS)
+XED_C_OBJS := $(XED_C_SRCS:%.c=xed/%.o)
-DEVICE_C_OBJS := $(DEVICE_C_SRCS:%.c=devices/%.o)
+XED_GAS_SRCS := v3-udiv-compat.s
-DEVICE_OBJS := $(DEVICE_C_OBJS)
+XED_GAS_OBJS := $(XED_GAS_SRCS:%.s=xed/%.o)
-V3LIBS := $(DECODER_LIBS)
+XED_OBJS := $(XED_C_OBJS) $(XED_GAS_OBJS)
+
+DEVICE_C_SRCS := generic.c keyboard.c nvram.c timer.c simple_pic.c 8259a.c 8254.c serial.c ramdisk.c cdrom.c
-ifeq ($(UIP),ON)
- UIP_C_SRCS := psock.c timer.c uip_arp.c uip.c uip-fw.c uiplib.c uip-neighbor.c uip-split.c resolv.c
- UIP_C_OBJS := $(UIP_C_SRCS:%.c=net/%.o)
-else
- UIP_C_SRCS :=
- UIP_C_OBJS :=
-endif
+DEVICE_C_OBJS := $(DEVICE_C_SRCS:%.c=devices/%.o)
-ifeq ($(LWIP),ON)
- LWIP_OBJS := lwip/*.o
- CC_LWIP_OPTS := -I$(PROJECT_ROOT)/include/lwip -I$(PROJECT_ROOT)/include/lwip/ipv4 -I$(PROJECT_ROOT)/include/libc -DLWIP_DEBUG
-else
- LWIP_OBJS :=
- CC_LWIP_OPTS :=
-endif
+DEVICE_OBJS := $(DEVICE_C_OBJS)
+
+V3LIBS := $(DECODER_LIBS)
-TCPSTACK_OBJS := $(UIP_C_OBJS) $(LWIP_OBJS)
# Describes how to compile the source files.
# ----------------------------------------------------------------------
-# Compilation of kernel C source files
-geekos/%.o : geekos/%.c
- $(TARGET_CC) -c $(CC_GENERAL_OPTS) $(CC_KERNEL_OPTS) $(CC_LWIP_OPTS) $< -o geekos/$*.o
-
-
-# Compilation of kernel assembly source files
-geekos/%.o : geekos/%.asm
- $(NASM) $(NASM_KERNEL_OPTS) $< -o geekos/$*.o
-
-# Compilation of test VM
-geekos/%.o : geekos/%.s
- $(AS) $< -o geekos/$*.o
-
-geekos/%.o : geekos/%.S
- $(TARGET_CC) -c $(CC_GENERAL_OPTS) $(CC_KERNEL_OPTS) $< -o geekos/$*.o
-
-# Compilation of common library C source files
-common/%.o : common/%.c
- $(TARGET_CC) -c $(CC_GENERAL_OPTS) $(CC_USER_OPTS) $< -o common/$*.o
-
palacios/%.o : palacios/%.c
$(TARGET_CC) -c $(CC_GENERAL_OPTS) $(CC_VMM_OPTS) $< -o palacios/$*.o
force_payload: force_rombios force_vgabios
../scripts/make_payload.pl payload_layout.txt vm_kernel
- inter1: force_payload
+ inter1: force_payload force_lwip
-make clean
-world: inter1 vmm.img
-
-# make ready to boot over PXE
-pxe: vmm.img
- cp vmm.img /tftpboot/vmm.img
+world: inter1 vmm
-run: vmm.img
- /usr/local/qemu/bin/qemu-system-x86_64 -m 1024 -serial file:serial.out -cdrom puppy.iso -fda vmm.img
+vmm: palacios/vmm.lib