Linux Kernel Emulation

On Linux, calling the kernel is done with the CPU instruction, INT 0x80. Which system call is determined by the value in EAX. See the file c/source/kernel/syscall.c for a complete list of which system calls are emulated.

The file system is a big part of the Linux emulation.   Boxedwine starts by looking at the file that was passed in to run, in our case this is usually /bin/wine.  It inspects the file to see if it is an i386 ELF file and if so then figures out which loader to use, usually this is /lib/ld-linux.so.2.  Boxedwine will then call loadProgram in c/source/kernel/loader/loader.c with the loader.  loadProgram maps the loader into memory then figures out which address we should start running the CPU from.  This will be the first instruction the emulated CPU will run.  ld-linux will then figure out the dependencies of /bin/wine and load them into memory, it will expect these dependencies to be in particular locations.  So our filesystem will end up looking like a typical Linux file system, where we have home, bin, lib, etc, var, tmp, etc in the root.  I created the file systems on Sourceforge from the Debian repo by unpacking/installing manually the libraries necessary for Wine to run.

Linux apps also communicate with the kernel via the file system by opening virtual files, like /dev/null.  In c/source/sdl/main.c these virtual files are added to the file system:

 addVirtualFile("/dev/tty0", &ttyAccess, K__S_IREAD|K__S_IWRITE|K__S_IFCHR, mdev(4, 0));
 addVirtualFile("/dev/tty", &ttyAccess, K__S_IREAD|K__S_IWRITE|K__S_IFCHR, mdev(4, 0));
 addVirtualFile("/dev/tty2", &ttyAccess, K__S_IREAD|K__S_IWRITE|K__S_IFCHR, mdev(4, 2)); // used by XOrg
 addVirtualFile("/dev/urandom", &urandomAccess, K__S_IREAD|K__S_IFCHR, mdev(1, 9));
 addVirtualFile("/dev/random", &urandomAccess, K__S_IREAD|K__S_IFCHR, mdev(1, 8));
 addVirtualFile("/dev/null", &nullAccess, K__S_IREAD|K__S_IWRITE|K__S_IFCHR, mdev(1, 3));
 addVirtualFile("/dev/zero", &zeroAccess, K__S_IREAD|K__S_IWRITE|K__S_IFCHR, mdev(1, 5));
 addVirtualFile("/proc/meminfo", &meminfoAccess, K__S_IREAD, mdev(0, 0));
 bufferAccess.data = ""; // no kernel arguments
 addVirtualFile("/proc/cmdline", &bufferAccess, K__S_IREAD, mdev(0, 0)); // kernel command line
 addVirtualFile("/dev/fb0", &fbAccess, K__S_IREAD|K__S_IWRITE|K__S_IFCHR, mdev(0x1d, 0));
 addVirtualFile("/dev/input/event3", &touchInputAccess, K__S_IWRITE|K__S_IREAD|K__S_IFCHR, mdev(0xd, 0x43));
 addVirtualFile("/dev/input/event4", &keyboardInputAccess, K__S_IWRITE|K__S_IREAD|K__S_IFCHR, mdev(0xd, 0x44));
 if (sound) {
     addVirtualFile("/dev/dsp", &dspAccess, K__S_IWRITE | K__S_IREAD | K__S_IFCHR, mdev(14, 3));
     addVirtualFile("/dev/mixer", &mixerAccess, K__S_IWRITE | K__S_IREAD | K__S_IFCHR, mdev(14, 0));
 }