mirror of https://github.com/BOINC/boinc.git
- VBOX: Use sscanf instead of strtol to convert a hex string.
- VBOX: Use new FloppyIO implementation that reports image creation errors. samples/vboxwrapper/ floppyio.cpp, .h vbox.cpp svn path=/trunk/boinc/; revision=25003
This commit is contained in:
parent
f208d2dba4
commit
9faee707fa
|
@ -234,3 +234,13 @@ Rom 6 Jan 2012
|
|||
ViewStatistics.cpp
|
||||
lib/
|
||||
gui_rpc_client_ops.cpp
|
||||
|
||||
Rom 6 Jan 2012
|
||||
- VBOX: Use sscanf instead of strtol to convert a hex string.
|
||||
- VBOX: Use new FloppyIO implementation that reports image
|
||||
creation errors.
|
||||
|
||||
|
||||
samples/vboxwrapper/
|
||||
floppyio.cpp, .h
|
||||
vbox.cpp
|
||||
|
|
|
@ -1,201 +1,372 @@
|
|||
// File: FloppyIO.cpp
|
||||
// Author: Ioannis Charalampidis <ioannis.charalampidis AT cern DOT ch>
|
||||
//
|
||||
// Hypervisor-Virtual machine bi-directional communication
|
||||
// through floppy disk.
|
||||
//
|
||||
// This class provides the hypervisor-side of the script.
|
||||
// For the guest-side, check the perl scripts that
|
||||
// were available with this code.
|
||||
//
|
||||
// Here is the layout of the floppy disk image (Example of 28k):
|
||||
//
|
||||
// +-----------------+------------------------------------------------+
|
||||
// | 0x0000 - 0x37FF | Hypervisor -> Guest Buffer |
|
||||
// | 0x3800 - 0x6FFE | Guest -> Hypervisor Buffer |
|
||||
// | 0x6FFF | "Data available for guest" flag byte |
|
||||
// | 0x7000 | "Data available for hypervisor" flag byte |
|
||||
// +-----------------+------------------------------------------------+
|
||||
//
|
||||
// Created on November 24, 2011, 12:30 PM
|
||||
|
||||
// This file is part Floppy I/O, a Virtual Machine - Hypervisor intercommunication system.
|
||||
// Copyright (C) 2011 Ioannis Charalampidis
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// File: FloppyIO.cpp
|
||||
// Author: Ioannis Charalampidis <ioannis.charalampidis AT cern DOT ch>
|
||||
// License: GNU Lesser General Public License - Version 3.0
|
||||
//
|
||||
// Hypervisor-Virtual machine bi-directional communication
|
||||
// through floppy disk.
|
||||
//
|
||||
// This class provides the hypervisor-side of the script.
|
||||
// For the guest-side, check the perl scripts that
|
||||
// were available with this code.
|
||||
//
|
||||
// Here is the layout of the floppy disk image (Example of 28k):
|
||||
//
|
||||
// +-----------------+------------------------------------------------+
|
||||
// | 0x0000 - 0x37FF | Hypervisor -> Guest Buffer |
|
||||
// | 0x3800 - 0x6FFE | Guest -> Hypervisor Buffer |
|
||||
// | 0x6FFF | "Data available for guest" flag byte |
|
||||
// | 0x7000 | "Data available for hypervisor" flag byte |
|
||||
// +-----------------+------------------------------------------------+
|
||||
//
|
||||
// Updated at January 5, 2012, 13:06 PM
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "boinc_win.h"
|
||||
#else
|
||||
#include <typeinfo>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "util.h"
|
||||
#include "floppyio.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Floppy file constructor
|
||||
//
|
||||
// This constructor opens the specified floppy disk image, fills everything
|
||||
// with zeroes and initializes the topology variables.
|
||||
//
|
||||
// @param filename The filename of the floppy disk image
|
||||
|
||||
FloppyIO::FloppyIO(const char * filename) {
|
||||
|
||||
// Open file
|
||||
fstream *fIO = new fstream(filename, fstream::in | fstream::out | fstream::trunc);
|
||||
|
||||
// Prepare floppy info
|
||||
this->fIO = fIO;
|
||||
this->szFloppy = DEFAULT_FLOPPY_SIZE;
|
||||
|
||||
// Setup offsets and sizes of the I/O parts
|
||||
this->szOutput = this->szFloppy/2-1;
|
||||
this->ofsOutput = 0;
|
||||
this->szInput = this->szOutput;
|
||||
this->ofsInput = this->szOutput;
|
||||
this->ofsCtrlByteOut = this->szInput+this->szOutput;
|
||||
this->ofsCtrlByteIn = this->szInput+this->szOutput+1;
|
||||
|
||||
// Reset floppy file
|
||||
this->reset();
|
||||
|
||||
}
|
||||
|
||||
// Advanced Floppy file constructor
|
||||
//
|
||||
// This constructor allows you to open a floppy disk image with extra flags.
|
||||
//
|
||||
// F_NOINIT Disables the reseting of the image file at open
|
||||
// F_NOCREATE Does not truncate the file at open (If not exists, the file will be created)
|
||||
// F_SYNCHRONIZED The communication is synchronized, meaning that the code will block until the
|
||||
// data are read/written from the guest. [NOT YET IMPLEMENTED]
|
||||
//
|
||||
// @param filename The filename of the floppy disk image
|
||||
|
||||
FloppyIO::FloppyIO(const char * filename, int flags) {
|
||||
|
||||
// Open file
|
||||
ios_base::openmode fOpenFlags = fstream::in | fstream::out;
|
||||
if ((flags & F_NOCREATE) == 0) fOpenFlags = fstream::trunc;
|
||||
fstream *fIO = new fstream(filename, fOpenFlags);
|
||||
|
||||
// Check for errors while F_NOCREATE is there
|
||||
if ((flags & F_NOCREATE) != 0) {
|
||||
if ( (fIO->rdstate() & ifstream::failbit ) != 0 ) {
|
||||
|
||||
// Clear error flag
|
||||
fIO->clear();
|
||||
|
||||
// Try to create file
|
||||
fOpenFlags |= fstream::trunc;
|
||||
fIO->open(filename, fOpenFlags);
|
||||
|
||||
// Still errors?
|
||||
if ( (fIO->rdstate() & ifstream::failbit ) != 0 ) {
|
||||
cerr << "Error opening '" << filename << "'!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// Managed to open it? Reset it...
|
||||
flags &= ~F_NOINIT;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Prepare floppy info
|
||||
this->fIO = fIO;
|
||||
this->szFloppy = DEFAULT_FLOPPY_SIZE;
|
||||
|
||||
// Setup offsets and sizes of the I/O parts
|
||||
this->szOutput = this->szFloppy/2-1;
|
||||
this->ofsOutput = 0;
|
||||
this->szInput = this->szOutput;
|
||||
this->ofsInput = this->szOutput;
|
||||
this->ofsCtrlByteOut = this->szInput+this->szOutput;
|
||||
this->ofsCtrlByteIn = this->szInput+this->szOutput+1;
|
||||
|
||||
// Reset floppy file
|
||||
if ((flags & F_NOINIT) == 0) this->reset();
|
||||
|
||||
}
|
||||
|
||||
|
||||
// FloppyIO Destructor
|
||||
// Closes the file descriptor and releases used memory
|
||||
|
||||
FloppyIO::~FloppyIO() {
|
||||
// Close file
|
||||
this->fIO->close();
|
||||
|
||||
// Release memory
|
||||
delete this->fIO;
|
||||
}
|
||||
|
||||
// Reset the floppy disk image
|
||||
// This function zeroes-out the contents of the FD image
|
||||
|
||||
void FloppyIO::reset() {
|
||||
this->fIO->seekp(0);
|
||||
char * buffer = new char[this->szFloppy];
|
||||
this->fIO->write(buffer, this->szFloppy);
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
// Send data to the floppy image I/O
|
||||
// @param data
|
||||
// @return
|
||||
void FloppyIO::send(string strData) {
|
||||
// Prepare send buffer
|
||||
char * dataToSend = new char[this->szOutput];
|
||||
memset(dataToSend, 0, this->szOutput);
|
||||
|
||||
// Initialize variables
|
||||
int szData = strData.length();
|
||||
|
||||
// Copy the first szInput bytes
|
||||
if (szData > this->szOutput-1) {
|
||||
// Data more than the pad size? Trim...
|
||||
strData.copy(dataToSend, this->szOutput-1, 0);
|
||||
} else {
|
||||
// Else, copy the string to send buffer
|
||||
strData.copy(dataToSend, szData, 0);
|
||||
}
|
||||
|
||||
// Write the data to file
|
||||
this->fIO->seekp(this->ofsOutput);
|
||||
this->fIO->write(dataToSend, this->szOutput);
|
||||
|
||||
// Notify the client that we placed data (Client should clear this on read)
|
||||
this->fIO->seekp(this->ofsCtrlByteOut);
|
||||
this->fIO->write("\x01", 1);
|
||||
}
|
||||
|
||||
|
||||
// Receive the input buffer contents
|
||||
// @return Returns a string object with the file contents
|
||||
|
||||
string FloppyIO::receive() {
|
||||
static string ansBuffer;
|
||||
char * dataToReceive = new char[this->szInput];
|
||||
int dataLength = this->szInput;
|
||||
|
||||
// Find the size of the input string
|
||||
for (int i=0; i<this->szInput; i++) {
|
||||
if (dataToReceive[0] == '\0') {
|
||||
dataLength=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the input bytes from FD
|
||||
this->fIO->seekg(this->ofsInput, ios_base::beg);
|
||||
this->fIO->read(dataToReceive, this->szInput);
|
||||
|
||||
// Notify the client that we have read the data
|
||||
this->fIO->seekp(this->ofsCtrlByteIn);
|
||||
this->fIO->write("\x00", 1);
|
||||
|
||||
// Copy input data to string object
|
||||
ansBuffer = dataToReceive;
|
||||
return ansBuffer;
|
||||
|
||||
}
|
||||
|
||||
// FloppyIO Exception singleton
|
||||
static FloppyIOException __FloppyIOExceptionSingleton;
|
||||
|
||||
// Advanced Floppy file constructor
|
||||
//
|
||||
// This constructor allows you to open a floppy disk image with extra flags.
|
||||
//
|
||||
// F_NOINIT Disables the reseting of the image file at open
|
||||
// F_NOCREATE Does not truncate the file at open (If not exists, the file will be created)
|
||||
// F_SYNCHRONIZED The communication is synchronized, meaning that the code will block until the
|
||||
// data are read/written from the guest.
|
||||
// F_EXCEPTIONS Throw exceptions if something goes wrong.
|
||||
// F_CLIENT Swap in/out buffers for use from within the guest.
|
||||
//
|
||||
// @param filename The filename of the floppy disk image
|
||||
// @param flags The flags that define how the FloppyIO class should function
|
||||
//
|
||||
|
||||
FloppyIO::FloppyIO(const char * filename, int flags) {
|
||||
// Clear error flag
|
||||
this->error = 0;
|
||||
|
||||
// Prepare open flags and create file stream
|
||||
ios_base::openmode fOpenFlags = fstream::in | fstream::out;
|
||||
if ((flags & F_NOCREATE) == 0) fOpenFlags |= fstream::trunc;
|
||||
fstream *fIO = new fstream( );
|
||||
this->fIO = fIO;
|
||||
|
||||
// Enable exceptions on fIO if told so
|
||||
if ((flags & F_EXCEPTIONS) != 0) {
|
||||
fIO->exceptions( ifstream::failbit | ifstream::badbit );
|
||||
this->useExceptions=true;
|
||||
} else {
|
||||
this->useExceptions=false;
|
||||
}
|
||||
|
||||
// Try to open the file
|
||||
fIO->open(filename, fOpenFlags);
|
||||
|
||||
// Check for errors while F_NOCREATE is there
|
||||
if ((flags & F_NOCREATE) != 0) {
|
||||
if ( fIO->fail() ) {
|
||||
|
||||
// Clear error flags
|
||||
fIO->clear();
|
||||
|
||||
// Try to create file
|
||||
fOpenFlags |= fstream::trunc;
|
||||
fIO->open(filename, fOpenFlags);
|
||||
|
||||
// Still errors?
|
||||
if ( fIO->fail() ) {
|
||||
this->setError(-3, "Error while creating floppy I/O file, because it wasn't found even though F_NOCREATE was specified!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Managed to open it? Reset it...
|
||||
flags &= ~F_NOINIT;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Check for failures on open
|
||||
if ( fIO->fail() ) {
|
||||
this->setError(-3, "Error while creating floppy I/O file!");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Prepare floppy info
|
||||
this->szFloppy = DEFAULT_FIO_FLOPPY_SIZE;
|
||||
|
||||
// Setup offsets and sizes of the I/O parts
|
||||
if ((flags & F_CLIENT) != 0) {
|
||||
// Guest mode
|
||||
this->szOutput = this->szFloppy/2-1;
|
||||
this->szInput = this->szOutput;
|
||||
this->ofsOutput = this->szInput;
|
||||
this->ofsInput = 0;
|
||||
this->ofsCtrlByteIn = this->szInput+this->szOutput;
|
||||
this->ofsCtrlByteOut = this->szInput+this->szOutput+1;
|
||||
|
||||
} else {
|
||||
// Hypervisor mode
|
||||
this->szOutput = this->szFloppy/2-1;
|
||||
this->szInput = this->szOutput;
|
||||
this->ofsOutput = 0;
|
||||
this->ofsInput = this->szOutput;
|
||||
this->ofsCtrlByteOut = this->szInput+this->szOutput;
|
||||
this->ofsCtrlByteIn = this->szInput+this->szOutput+1;
|
||||
}
|
||||
|
||||
// Update synchronization flags
|
||||
this->synchronized = false;
|
||||
this->syncTimeout = DEFAULT_FIO_SYNC_TIMEOUT;
|
||||
if ((flags & F_SYNCHRONIZED) != 0) this->synchronized=true;
|
||||
|
||||
// Reset floppy file
|
||||
if ((flags & F_NOINIT) == 0) this->reset();
|
||||
|
||||
}
|
||||
|
||||
|
||||
// FloppyIO Destructor
|
||||
// Closes the file descriptor and releases used memory
|
||||
|
||||
FloppyIO::~FloppyIO() {
|
||||
// Close file
|
||||
this->fIO->close();
|
||||
|
||||
// Release memory
|
||||
delete this->fIO;
|
||||
}
|
||||
|
||||
// Reset the floppy disk image
|
||||
// This function zeroes-out the contents of the FD image
|
||||
|
||||
void FloppyIO::reset() {
|
||||
// Check for ready state
|
||||
if (!this->ready()) {
|
||||
this->setError(-4, "Stream is not ready!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset to the beginnig of file and fill with zeroes
|
||||
this->fIO->seekp(0);
|
||||
char * buffer = new char[this->szFloppy];
|
||||
memset(buffer, 0, this->szFloppy);
|
||||
this->fIO->write(buffer, this->szFloppy);
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
|
||||
// Send data to the floppy image I/O
|
||||
//
|
||||
// @param strData The string to send
|
||||
// @return The number of bytes sent if successful or -1 if an error occured.
|
||||
//
|
||||
int FloppyIO::send(string strData) {
|
||||
// Prepare send buffer
|
||||
char * dataToSend = new char[this->szOutput];
|
||||
memset(dataToSend, 0, this->szOutput);
|
||||
|
||||
// Check for ready state
|
||||
if (!this->ready()) return this->setError(-4, "Stream is not ready!");
|
||||
|
||||
// Initialize variables
|
||||
int szData = (int)strData.length();
|
||||
int szPad = 0;
|
||||
int bytesSent = szData;
|
||||
|
||||
// Copy the first szInput bytes
|
||||
if (szData > this->szOutput-1) { // -1 for the null-termination
|
||||
// Data more than the pad size? Trim...
|
||||
strData.copy(dataToSend, this->szOutput-1, 0);
|
||||
bytesSent = this->szOutput-1;
|
||||
} else {
|
||||
// Else, copy the string to send buffer
|
||||
strData.copy(dataToSend, szData, 0);
|
||||
}
|
||||
|
||||
// Check for stream status
|
||||
if (!this->fIO->good()) return this->setError(-1, "I/O Stream reported no-good state while sending!");
|
||||
|
||||
// Write the data to file
|
||||
this->fIO->seekp(this->ofsOutput);
|
||||
this->fIO->write(dataToSend, this->szOutput);
|
||||
|
||||
// Check if something went wrong after writing
|
||||
if (!this->fIO->good()) return this->setError(-1, "I/O Stream reported no-good state while sending!");
|
||||
|
||||
// Notify the client that we placed data (Client should clear this on read)
|
||||
this->fIO->seekp(this->ofsCtrlByteOut);
|
||||
this->fIO->write("\x01", 1);
|
||||
this->fIO->flush();
|
||||
|
||||
// If synchronized, wait for data to be written
|
||||
if (this->synchronized) {
|
||||
// Wait for input control byte to become 1
|
||||
int iState = this->waitForSync(this->ofsCtrlByteOut, 0, this->syncTimeout);
|
||||
if (iState<0) return iState;
|
||||
}
|
||||
|
||||
// Return number of bytes sent
|
||||
return bytesSent;
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Receive the input buffer contents
|
||||
//
|
||||
// @return Returns a string object with the buffer contents
|
||||
//
|
||||
string FloppyIO::receive() {
|
||||
static string ansBuffer;
|
||||
this->receive(&ansBuffer);
|
||||
return ansBuffer;
|
||||
}
|
||||
|
||||
//
|
||||
// Receive the input buffer contents
|
||||
//
|
||||
// @param string A pointer to a string object that will receive the data
|
||||
// @return Returns the length of the data received or -1 if an error occured.
|
||||
//
|
||||
int FloppyIO::receive(string * ansBuffer) {
|
||||
char * dataToReceive = new char[this->szInput];
|
||||
int dataLength = this->szInput;
|
||||
|
||||
// Check for ready state
|
||||
if (!this->ready()) return this->setError(-4, "Stream is not ready!");
|
||||
|
||||
// If synchronized, wait for input data
|
||||
if (this->synchronized) {
|
||||
// Wait for input control byte to become 1
|
||||
int iState = this->waitForSync(this->ofsCtrlByteIn, 1, this->syncTimeout);
|
||||
if (iState<0) return iState;
|
||||
}
|
||||
|
||||
// Check for stream status
|
||||
if (!this->fIO->good()) return this->setError(-1, "I/O Stream reported no-good state while receiving!");
|
||||
|
||||
// Read the input bytes from FD
|
||||
this->fIO->seekg(this->ofsInput, ios_base::beg);
|
||||
this->fIO->read(dataToReceive, this->szInput);
|
||||
|
||||
// Notify the client that we have read the data
|
||||
this->fIO->seekp(this->ofsCtrlByteIn);
|
||||
this->fIO->write("\x00", 1);
|
||||
this->fIO->flush();
|
||||
|
||||
// Copy input data to string object
|
||||
*ansBuffer = dataToReceive;
|
||||
return (int)ansBuffer->length();
|
||||
|
||||
}
|
||||
|
||||
// Wait for synchronization byte to be cleared.
|
||||
// This function blocks until the byte at controlByteOffset has
|
||||
// the synchronization bit cleared.
|
||||
//
|
||||
// @param controlByteOffset The offset (from the beginning of file) where to look for the control byte
|
||||
// @param state The state the controlByte must be for this function to exit.
|
||||
// @param timeout The time (in seconds) to wait for a change. 0 Will wait forever
|
||||
// @return Returns 0 if everything succeeded, -1 if an error occured, -2 if timed out.
|
||||
|
||||
int FloppyIO::waitForSync(int controlByteOffset, char state, int timeout) {
|
||||
time_t tExpired = time (NULL) + timeout;
|
||||
char cStatusByte;
|
||||
|
||||
// Wait until expired or forever.
|
||||
while ((timeout == 0) || ( time(NULL) <= tExpired)) {
|
||||
|
||||
// Check for stream status
|
||||
if (!this->fIO->good()) return this->setError(-1, "I/O Stream reported no-good state while waiting for sync!");
|
||||
|
||||
// Check the synchronization byte
|
||||
this->fIO->seekg(controlByteOffset, ios_base::beg);
|
||||
this->fIO->read(&cStatusByte, 1);
|
||||
|
||||
// Is the control byte 0? Our job is finished...
|
||||
if (cStatusByte == state) return 0;
|
||||
|
||||
// Sleep for a few milliseconds to decrease CPU-load
|
||||
boinc_sleep(0.250);
|
||||
}
|
||||
|
||||
// If we reached this point, we timed out
|
||||
return this->setError(-2, "Timed-out while waiting for sync!");
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Set last error.
|
||||
// This is a short-hand function to update the error variables.
|
||||
//
|
||||
// @param code The error code
|
||||
// @param message The error message
|
||||
// @return The error code
|
||||
//
|
||||
int FloppyIO::setError(int code, const string message) {
|
||||
this->error = code;
|
||||
|
||||
// Chain errors
|
||||
if (this->errorStr.empty()) {
|
||||
this->errorStr = message;
|
||||
} else {
|
||||
this->errorStr = message + " (" + this->errorStr + ")";
|
||||
}
|
||||
|
||||
// Should we raise an exception?
|
||||
if (this->useExceptions)
|
||||
throw *__FloppyIOExceptionSingleton.set(code, message);
|
||||
|
||||
// Otherwise return code
|
||||
// (Useful for using single-lined: return this->setError(-1, "message..');
|
||||
return code;
|
||||
}
|
||||
|
||||
//
|
||||
// Clear error state flags
|
||||
//
|
||||
void FloppyIO::clear() {
|
||||
this->error = 0;
|
||||
this->errorStr = "";
|
||||
this->fIO->clear();
|
||||
}
|
||||
|
||||
//
|
||||
// Check if everything is in ready state
|
||||
// @return Returns true if there are no errors and stream hasn't failed
|
||||
//
|
||||
bool FloppyIO::ready() {
|
||||
if (this->error!=0) return false;
|
||||
return this->fIO->good();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,84 +1,185 @@
|
|||
// File: FloppyIO.h
|
||||
// Author: Ioannis Charalampidis <ioannis.charalampidis AT cern DOT ch>
|
||||
//
|
||||
// Hypervisor-Virtual machine bi-directional communication
|
||||
// through floppy disk.
|
||||
//
|
||||
// This class provides the hypervisor-side of the script.
|
||||
// For the guest-side, check the perl scripts that
|
||||
// were available with this code.
|
||||
//
|
||||
// Here is the layout of the floppy disk image (Example of 28k):
|
||||
//
|
||||
// +-----------------+------------------------------------------------+
|
||||
// | 0x0000 - 0x37FF | Hypervisor -> Guest Buffer |
|
||||
// | 0x3800 - 0x6FFE | Guest -> Hypervisor Buffer |
|
||||
// | 0x6FFF | "Data available for guest" flag byte |
|
||||
// | 0x7000 | "Data available for hypervisor" flag byte |
|
||||
// +-----------------+------------------------------------------------+
|
||||
//
|
||||
// Created on November 24, 2011, 12:30 PM
|
||||
|
||||
#ifndef FLOPPYIO_H
|
||||
#define FLOPPYIO_H
|
||||
|
||||
// Do not initialize (reset) floppy disk image at open.
|
||||
// (Flag used at FloppyIO constructor)
|
||||
|
||||
#define F_NOINIT 1
|
||||
|
||||
|
||||
// Do not create the filename (assume it exists)
|
||||
// (Flag used at FloppyIO constructor)
|
||||
|
||||
#define F_NOCREATE 2
|
||||
|
||||
|
||||
// Synchronize I/O [NOT YET IMPLEMENTED]
|
||||
// This flag will block the script until the guest has read/written the data.
|
||||
// (Flag used at FloppyIO constructor)
|
||||
|
||||
#define F_SYNCHRONIZED 4
|
||||
|
||||
// Default floppy disk size (In bytes)
|
||||
//
|
||||
// VirtualBox complains if bigger than 28K
|
||||
// It's supposed to go till 1474560 however (!.44 Mb)
|
||||
|
||||
#define DEFAULT_FLOPPY_SIZE 28672
|
||||
|
||||
|
||||
// Floppy I/O Communication class
|
||||
|
||||
class FloppyIO {
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
FloppyIO(const char * filename);
|
||||
FloppyIO(const char * filename, int flags);
|
||||
virtual ~FloppyIO();
|
||||
|
||||
// Functions
|
||||
void reset();
|
||||
void send(std::string strData);
|
||||
std::string receive();
|
||||
|
||||
// Topology info
|
||||
int ofsInput; // Input buffer offset & size
|
||||
int szInput;
|
||||
int ofsOutput; // Output buffer offset & size
|
||||
int szOutput;
|
||||
|
||||
int ofsCtrlByteIn; // Control byte offset for input
|
||||
int ofsCtrlByteOut; // Control byte offset for output
|
||||
|
||||
private:
|
||||
|
||||
// Floppy Info
|
||||
std::fstream* fIO;
|
||||
int szFloppy;
|
||||
|
||||
};
|
||||
|
||||
#endif // FLOPPYIO_H
|
||||
|
||||
// This file is part Floppy I/O, a Virtual Machine - Hypervisor intercommunication system.
|
||||
// Copyright (C) 2011 Ioannis Charalampidis
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// File: FloppyIO.h
|
||||
// Author: Ioannis Charalampidis <ioannis.charalampidis AT cern DOT ch>
|
||||
// License: GNU Lesser General Public License - Version 3.0
|
||||
//
|
||||
// Hypervisor-Virtual machine bi-directional communication
|
||||
// through floppy disk.
|
||||
//
|
||||
// This class provides the hypervisor-side of the script.
|
||||
// For the guest-side, check the perl scripts that
|
||||
// were available with this code.
|
||||
//
|
||||
// Here is the layout of the floppy disk image (Example of 28k):
|
||||
//
|
||||
// +-----------------+------------------------------------------------+
|
||||
// | 0x0000 - 0x37FF | Hypervisor -> Guest Buffer |
|
||||
// | 0x3800 - 0x6FFE | Guest -> Hypervisor Buffer |
|
||||
// | 0x6FFF | "Data available for guest" flag byte |
|
||||
// | 0x7000 | "Data available for hypervisor" flag byte |
|
||||
// +-----------------+------------------------------------------------+
|
||||
//
|
||||
// Updated at January 5, 2012, 13:06 PM
|
||||
//
|
||||
|
||||
#ifndef FLOPPYIO_H
|
||||
#define FLOPPYIO_H
|
||||
|
||||
// Do not initialize (reset) floppy disk image at open.
|
||||
// (Flag used by the FloppyIO constructor)
|
||||
#define F_NOINIT 1
|
||||
|
||||
// Do not create the filename (assume it exists)
|
||||
// (Flag used by the FloppyIO constructor)
|
||||
#define F_NOCREATE 2
|
||||
|
||||
// Synchronize I/O.
|
||||
// This flag will block the script until the guest has read/written the data.
|
||||
// (Flag used by the FloppyIO constructor)
|
||||
#define F_SYNCHRONIZED 4
|
||||
|
||||
// Use exceptions instead of error codes
|
||||
// (Flag used by the FloppyIO constructor)
|
||||
#define F_EXCEPTIONS 8
|
||||
|
||||
// Initialize FloppyIO in client mode.
|
||||
// This flag will swap the input/output buffers, making the script usable from
|
||||
// within the virtual machine.
|
||||
// (Flag used by the FloppyIO constructor)
|
||||
#define F_CLIENT 16
|
||||
|
||||
//
|
||||
// Error code constants
|
||||
//
|
||||
#define FPIO_NOERR 0 // No error occured
|
||||
#define FPIO_ERR_IO -1 // There was an I/O error on the strea,
|
||||
#define FPIO_ERR_TIMEOUT -2 // The operation timed out
|
||||
#define FPIO_ERR_CREATE -3 // Unable to freate the floppy file
|
||||
#define FPIO_ERR_NOTREADY -4 // The I/O object is not ready
|
||||
|
||||
//
|
||||
// Structure of the synchronization control byte.
|
||||
//
|
||||
// This byte usually resides at the beginning of the
|
||||
// floppy file for the receive buffer and at the end
|
||||
// of the file for the sending buffer.
|
||||
//
|
||||
// It's purpose is to force the entire floppy image
|
||||
// to be re-written/re-read by the hypervisor/guest OS and
|
||||
// to synchronize the I/O in case of large ammount of
|
||||
// data being exchanged.
|
||||
//
|
||||
typedef struct fpio_ctlbyte {
|
||||
unsigned short bDataPresent : 1;
|
||||
unsigned short bReserved : 7;
|
||||
} fpio_ctlbytex;
|
||||
|
||||
// Default floppy disk size (In bytes)
|
||||
//
|
||||
// VirtualBox complains if bigger than 28K
|
||||
// It's supposed to go till 1474560 however (1.44 Mb)
|
||||
|
||||
#define DEFAULT_FIO_FLOPPY_SIZE 28672
|
||||
|
||||
// Default synchronization timeout (seconds).
|
||||
// This constant defines how long we should wait for synchronization
|
||||
// feedback from the guest before aborting.
|
||||
|
||||
#define DEFAULT_FIO_SYNC_TIMEOUT 5
|
||||
|
||||
//
|
||||
// Floppy I/O Communication class
|
||||
//
|
||||
class FloppyIO {
|
||||
public:
|
||||
|
||||
// Construcors
|
||||
FloppyIO(const char * filename, int flags = 0);
|
||||
virtual ~FloppyIO();
|
||||
|
||||
// Functions
|
||||
void reset();
|
||||
int send(std::string strData);
|
||||
std::string receive();
|
||||
int receive(std::string* strBuffer);
|
||||
|
||||
// Topology info
|
||||
int ofsInput; // Input buffer offset & size
|
||||
int szInput;
|
||||
int ofsOutput; // Output buffer offset & size
|
||||
int szOutput;
|
||||
|
||||
int ofsCtrlByteIn; // Control byte offset for input
|
||||
int ofsCtrlByteOut; // Control byte offset for output
|
||||
|
||||
// Synchronization stuff
|
||||
bool synchronized; // The read/writes are synchronized
|
||||
int syncTimeout; // For how long should we wait
|
||||
|
||||
// Error reporting and checking
|
||||
int error;
|
||||
std::string errorStr;
|
||||
bool useExceptions; // If TRUE errors will raise exceptions
|
||||
|
||||
void clear(); // Clear errors
|
||||
bool ready(); // Returns TRUE if there are no errors
|
||||
|
||||
private:
|
||||
|
||||
// Floppy Info
|
||||
std::fstream* fIO;
|
||||
int szFloppy;
|
||||
|
||||
// Functions
|
||||
int waitForSync(int controlByteOffset, char state, int timeout);
|
||||
int setError(int code, std::string message);
|
||||
|
||||
};
|
||||
|
||||
//
|
||||
// Floppy I/O Exceptions
|
||||
//
|
||||
class FloppyIOException: public std::exception {
|
||||
public:
|
||||
|
||||
int code;
|
||||
std::string message;
|
||||
|
||||
// Default constructor/destructor
|
||||
FloppyIOException() { this->code=0; this->message=""; };
|
||||
virtual ~FloppyIOException() throw() { };
|
||||
|
||||
// Get description
|
||||
virtual const char* what() const throw() {
|
||||
static std::ostringstream oss (std::ostringstream::out);
|
||||
oss << this->message << ". Error code = " << this->code;
|
||||
return oss.str().c_str();
|
||||
}
|
||||
|
||||
// Change the message and return my instance
|
||||
// (Used for singleton format)
|
||||
FloppyIOException * set(int code, std::string message) {
|
||||
this->code = code;
|
||||
this->message = message;
|
||||
return this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // FLOPPYIO_H
|
||||
|
||||
|
|
|
@ -320,11 +320,13 @@ CLEANUP:
|
|||
|
||||
// Determine the real error code by parsing the output
|
||||
errcode_start = output.find("(0x");
|
||||
errcode_start += 1;
|
||||
errcode_end = output.find(")", errcode_start);
|
||||
errcode = output.substr(errcode_start, errcode_end - errcode_start);
|
||||
if (errcode_start) {
|
||||
errcode_start += 1;
|
||||
errcode_end = output.find(")", errcode_start);
|
||||
errcode = output.substr(errcode_start, errcode_end - errcode_start);
|
||||
|
||||
retval = strtol(errcode.c_str(), NULL, NULL);
|
||||
sscanf(errcode.c_str(), "%x", &retval);
|
||||
}
|
||||
|
||||
// If something couldn't be found, just return ERR_FOPEN
|
||||
if (!retval) retval = ERR_FOPEN;
|
||||
|
@ -801,6 +803,18 @@ int VBOX_VM::register_vm() {
|
|||
// NOTE: This creates the floppy.img file at runtime for use by the VM.
|
||||
//
|
||||
pFloppy = new FloppyIO(floppy_image_filename.c_str());
|
||||
if (!pFloppy->ready()) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"%s Creating virtual floppy image failed.\n"
|
||||
"%s Error Code '%d' Error Message '%s'\n",
|
||||
boinc_msg_prefix(buf, sizeof(buf)),
|
||||
boinc_msg_prefix(buf, sizeof(buf)),
|
||||
pFloppy->error,
|
||||
pFloppy->errorStr.c_str()
|
||||
);
|
||||
return ERR_FWRITE;
|
||||
}
|
||||
|
||||
fprintf(
|
||||
stderr,
|
||||
|
|
Loading…
Reference in New Issue