genode/ports/src/virtualbox/main.cc
2014-04-16 17:31:24 +02:00

227 lines
5.0 KiB
C++

/*
* \brief Port of VirtualBox to Genode
* \author Norman Feske
* \date 2013-08-20
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/env.h>
#include <base/printf.h>
#include <os/config.h>
#include <base/snprintf.h>
/* libc includes */
#include <stdio.h>
/* Virtualbox includes of VBoxBFE */
#include <iprt/initterm.h>
#include <iprt/err.h>
void *operator new (Genode::size_t size) {
return Genode::env()->heap()->alloc(size); }
void operator delete(void * p) {
if (Genode::env()->heap()->need_size_for_free()) {
PERR("leaking memory - delete operator is missing size information");
return;
}
Genode::env()->heap()->free(p, 0);
}
namespace {
template <int MAX_ARGS>
struct Args
{
int argc = 0;
char *argv[MAX_ARGS] = { };
struct Too_many_arguments { };
void add(char const *arg)
{
/* argv[MAX_ARGS - 1] must be unused and set to 0 */
if (argc >= MAX_ARGS - 1)
throw Too_many_arguments();
/* XXX yes const-casting hurts but main() needs char** */
argv[argc++] = const_cast<char *>(arg);
}
};
} /* unnamed namespace */
extern "C" {
/* string conversion function currently does not convert ... */
int RTStrCurrentCPToUtf8Tag(char **ppszString, char *pszString,
const char *pszTag)
{
/* dangerous */
*ppszString = pszString;
return 0;
}
/* don't use 'Runtime/r3/posix/utf8-posix.cpp' because it depends on libiconv */
int RTStrUtf8ToCurrentCPTag(char **ppszString, char *pszString,
const char *pszTag)
{
/* dangerous */
*ppszString = pszString;
return 0;
}
char * RTPathRealDup(const char *pszPath)
{
/* dangerous */
return (char *)pszPath;
}
bool RTPathExists(const char *pszPath)
{
return true;
}
/* make output of Virtualbox visible */
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
{
if (!stream || !ptr ||
!(fileno(stdout) == fileno(stream) || fileno(stderr) == fileno(stream)))
return EOF;
char const * cptr = reinterpret_cast<const char *>(ptr);
for (size_t j = 0; j < nmemb; j++)
for (size_t i = 0; i < size; i++)
Genode::printf("%c", cptr[j * size + i]);
return nmemb;
}
int fprintf(FILE *stream, const char *format, ...) /* called by RTAssertMsg1 */
{
if (!stream ||
!(fileno(stdout) == fileno(stream) || fileno(stderr) == fileno(stream)))
return EOF;
va_list list;
va_start(list, format);
Genode::vprintf(format, list);
va_end(list);
return 0;
}
int fputs(const char *s, FILE *stream) /* called by RTAssertMsg2Weak */
{
if (!stream ||
!(fileno(stdout) == fileno(stream) || fileno(stderr) == fileno(stream)))
return EOF;
fwrite(s, Genode::strlen(s), 1, stream);
}
/* our libc provides a _nanosleep function */
int _nanosleep(const struct timespec *req, struct timespec *rem);
int nanosleep(const struct timespec *req, struct timespec *rem) {
return _nanosleep(req, rem); }
/*
* Genode way of using a configuration. Wrap VBox main until we throught it
* out eventually.
*/
/* main function of VBox is in Frontends/VBoxBFE/VBoxBFE.cpp */
extern "C" DECLEXPORT(int) TrustedMain (int argc, char **argv, char **envp);
int main()
{
static char c_mem[16];
static char c_type[4];
static char c_file[128];
static bool bOverlay = false;
static Args<64> args;
/* request max available memory */
size_t vm_size = Genode::env()->ram_session()->avail();
enum { VMM_MEMORY = 64 * 1024 * 1024 /* let a bit memory for the VMM */ };
if (vm_size < VMM_MEMORY) {
PERR("not enough memory available - need %u, available only %zu "
"- exit", VMM_MEMORY, vm_size);
return 1;
}
vm_size -= VMM_MEMORY;
try {
using namespace Genode;
Xml_node node = config()->xml_node().sub_node("image");
Xml_node::Attribute type = node.attribute("type");
Xml_node::Attribute file = node.attribute("file");
try {
Xml_node::Attribute overlay = node.attribute("overlay");
overlay.value(c_type, sizeof(c_type));
if (!strcmp(c_type, "yes"))
bOverlay = true;
} catch (...) { }
type.value(c_type, sizeof(c_type));
file.value(c_file, sizeof(c_file));
} catch (...) {
PERR("C++ exception during xml parsing");
return 2;
}
args.add("virtualbox");
args.add("-m");
Genode::snprintf(c_mem, sizeof(c_mem), "%u", vm_size / 1024 / 1024);
args.add(c_mem);
args.add("-boot");
if (!Genode::strcmp(c_type, "iso")) {
args.add("d");
args.add("-cdrom");
} else
if (!Genode::strcmp(c_type, "vdi")) {
args.add("c");
args.add("-hda");
} else {
PERR("invalid configuration - abort");
return 3;
}
args.add(c_file);
args.add("-ioapic");
if (bOverlay)
args.add("-overlay");
PINF("start %s image '%s' with %zu MB Guest memory=%zu",
c_type, c_file, vm_size / 1024 / 1024,
Genode::env()->ram_session()->avail());
if (RT_FAILURE(RTR3InitExe(args.argc, (char ***)&args.argv, 0))) {
PERR("Intialization of VBox Runtime failed.");
return 5;
}
return TrustedMain(args.argc, args.argv, NULL);
}
} /* EXTERN "C" */