Skip to content
Snippets Groups Projects
Commit 7cfc0db4 authored by adrian.spycher's avatar adrian.spycher
Browse files

feat!: handle disk hypercall and prepare for emulated call

parent 39d45041
Branches
No related tags found
No related merge requests found
......@@ -13,6 +13,7 @@
#define HYPERCALL_CODE_CONSOLE 1
#define HYPERCALL_CODE_TIMER 2
#define HYPERCALL_CODE_GFX_INIT 3
#define HYPERCALL_CODE_IDE 4
#define REG_TIMER_CMD 0x43
#define REG_TIMER_DATA 0x40
......@@ -21,6 +22,10 @@
#define REG_GFX_INIT_CMD 0x4E700100
#define REG_GFX_INIT_DATA 0x4E700200
#define REG_IDE_ST 0x1F7
#define REG_IDE_CMD 0x1F7
#define REG_IDE_DATA 0x1F0
// --- SHARED STRUCT ---
typedef struct {
......@@ -39,6 +44,12 @@ typedef struct {
uint32_t height; // vertical resolution in pixels
} __attribute__((packed)) hyper_init_gfx_params_t;
typedef struct {
uint32_t sector_idx; // sector index ( or number )
uint64_t data; // address of data to write (512 bytes)
} __attribute__((packed)) hyper_ide_params_t;
// --- FUNCTION ---
// ...
......
......@@ -92,6 +92,7 @@ static state_t *state_check(uint64_t addr, uint8_t size, uint32_t value) {
break;
case OP_WRITE_STORE:
case OP_WRITE_STORE_LOOP:
if (next_state->addr == addr && next_state->size == size && next_state->callback != NULL)
return next_state;
......@@ -111,11 +112,6 @@ static void state_compute(state_t *state, uint32_t value) {
switch (state->op) {
case OP_WRITE_STORE:
state->callback(&value);
break;
case OP_READ_INJECT:
injecte_data((uint8_t *)&state->addr, state->size, state->value);
......@@ -123,12 +119,22 @@ static void state_compute(state_t *state, uint32_t value) {
state->size * 8, state->addr, state->value);
break;
case OP_WRITE_STORE_LOOP:
if (flag_stop_loop == false)
current_state = state - 1; // cancled next +1
break;
case OP_EMUL_END:
case OP_WRITE_STORE:
case OP_WRITE_EQUAL:
// nothing...
break;
}
if (state->callback != NULL)
state->callback(&value);
// - check and compute last operation -
current_state = state + 1;
if (current_state->op == OP_EMUL_END) {
......@@ -162,6 +168,14 @@ static void wrapper_op_gfx_init(uint8_t *shared_buf) {
op_callback_gfx_init_conclude(p_init_gfx);
}
static void wrapper_op_ide(uint8_t *shared_buf, uint8_t *mem) {
hyper_ide_params_t *p_ide = (hyper_ide_params_t *)shared_buf;
p_ide->data = p_ide->data + (uint64_t)mem;
op_callback_ide_condlude(p_ide);
}
// --- FUNCTION ---
// - VMM EXIT REASON HANDLER -
......@@ -170,7 +184,7 @@ void handle_halt(struct kvm_run *run, ...) {
va_list args; va_start(args, run);
va_arg(args, uint8_t *); va_arg(args, uint8_t *); // skip two first args
va_arg(args, uint8_t *); va_arg(args, uint8_t *); // skip two first args
bool *done = va_arg(args, bool *);
printf("guest halted\n");
......@@ -208,7 +222,6 @@ void handle_pmio(struct kvm_run *run, ...) {
va_end(args);
}
// waiting for : uint8_t *shared_buf, uint8_t *mem
void handle_mmio(struct kvm_run *run, ...) {
if (run->mmio.is_write) {
......@@ -241,6 +254,10 @@ void handle_hypercall(uint32_t code, uint8_t *shared_buf, uint8_t *mem) {
wrapper_op_gfx_init(shared_buf);
break;
case HYPERCALL_CODE_IDE:
wrapper_op_ide(shared_buf, mem);
break;
default:
errx(1, "Unsupported hypercall code.\n");
break;
......
#include "operation.h"
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <semaphore.h>
#include "shared/ide_regs.h"
#include "shared/hypercall_params.h"
// --- DEFINE ---
......@@ -18,21 +22,43 @@ state_t STATE_TIMER[] = {
state_t STATE_GFX_INIT[] = {
{ OP_READ_INJECT, REG_GFX_INIT_ST, 0, 4, NULL },
{ OP_READ_INJECT, REG_GFX_INIT_ST, 0, 1, NULL },
{ OP_WRITE_EQUAL, REG_GFX_INIT_CMD, 5, 4, NULL },
{ OP_WRITE_STORE, REG_GFX_INIT_DATA, 0, 4, op_callback_gfx_init_store_w},
{ OP_WRITE_STORE, REG_GFX_INIT_DATA, 0, 4, op_callback_gfx_init_store_h},
{ OP_EMUL_END, 0, 0, 0, op_callback_gfx_init_conclude},
{ OP_WRITE_STORE, REG_GFX_INIT_DATA, 0, 4, op_callback_gfx_init_store_w },
{ OP_WRITE_STORE, REG_GFX_INIT_DATA, 0, 4, op_callback_gfx_init_store_h },
{ OP_EMUL_END, 0, 0, 0, op_callback_gfx_init_conclude },
};
state_t STATE_IDE[] = {
{ OP_READ_INJECT, REG_IDE_ST, 0, 1, op_callback_ide_prepare },
{ OP_WRITE_EQUAL, REG_IDE_DATA + 2, 1, 1, NULL },
{ OP_WRITE_STORE, REG_IDE_DATA + 3, 0, 1, op_callback_ide_store_sector_1 },
{ OP_WRITE_STORE, REG_IDE_DATA + 4, 0, 1, op_callback_ide_store_sector_2 },
{ OP_WRITE_STORE, REG_IDE_DATA + 5, 0, 1, op_callback_ide_store_sector_3 },
{ OP_WRITE_STORE, REG_IDE_DATA + 6, 0, 1, op_callback_ide_store_sector_4 },
{ OP_WRITE_EQUAL, REG_IDE_CMD, 0x30, 1, NULL },
{ OP_READ_INJECT, REG_IDE_ST, 0, 1, NULL },
{ OP_WRITE_STORE_LOOP, REG_IDE_DATA, 0, 2, op_callback_ide_store_data },
{ OP_EMUL_END, 0, 0, 0, op_callback_ide_condlude },
};
state_t *STATE_ALL_STARTERS[] = {
&STATE_TIMER[0],
&STATE_GFX_INIT[0],
&STATE_IDE[0],
};
bool flag_stop_loop = false;
static hyper_timer_sleep_params_t param_timer;
static hyper_init_gfx_params_t param_gfx_init;
static hyper_ide_params_t param_ide;
// store the index of the actual loop
static uint32_t loop_ide_data;
static uint16_t buf_ide_data[MAX_LOOP_IDE_DATA];
// --- STATIC FUNCTION ---
......@@ -80,3 +106,74 @@ void op_callback_gfx_init_conclude(void *addr) {
height_gfx = p_gfx_init->height;
sem_post(&sem_gfx);
}
void op_callback_ide_prepare(void *addr) {
flag_stop_loop = false;
loop_ide_data = MAX_LOOP_IDE_DATA;
param_ide.data = (uint64_t)buf_ide_data;
}
void op_callback_ide_store_sector_1(void *addr) {
param_ide.sector_idx = *(uint8_t *)addr;
}
void op_callback_ide_store_sector_2(void *addr) {
param_ide.sector_idx |= (*(uint8_t *)addr) << 8;
}
void op_callback_ide_store_sector_3(void *addr) {
param_ide.sector_idx |= (*(uint8_t *)addr) << 16;
}
void op_callback_ide_store_sector_4(void *addr) {
param_ide.sector_idx |= ((*(uint8_t *)addr) & 0x0F) << 24;
// TODO: what to do with the mode ?
}
void op_callback_ide_store_data(void *addr) {
buf_ide_data[MAX_LOOP_IDE_DATA - loop_ide_data] = *(uint16_t *)addr;
loop_ide_data--;
if (loop_ide_data == 0) {
flag_stop_loop = true;
loop_ide_data = MAX_LOOP_IDE_DATA;
}
}
void op_callback_ide_condlude(void *addr) {
hyper_ide_params_t *p_ide = (addr == NULL) ? &param_ide : (hyper_ide_params_t *)addr;
printf("action : writing on 0x%lx on sector %d\n", p_ide->data, p_ide->sector_idx);
// check sector range
if (p_ide->sector_idx > MAX_SECTOR_NUM) err(1, "IDE sector is out of range");
FILE *disk = fopen(disk_path, "r+b");
if (!disk) err(1, "Failed opening the disk file");
// calculate the offset for the sector
uint64_t offset = (uint64_t)p_ide->sector_idx * SECTOR_SIZE;
// Seek to the sector position
if (fseek(disk, offset, SEEK_SET) != 0) {
err(1, "IDE seek failed");
fclose(disk);
}
// Write 512 bytes to the specified sector
size_t bytes_written = fwrite((void *)p_ide->data, 1, SECTOR_SIZE, disk);
if (bytes_written != SECTOR_SIZE) {
err(1, "IDE failed to write full sector");
fclose(disk);
}
fclose(disk);
}
......@@ -3,6 +3,7 @@
#include <stdint.h>
#include <unistd.h>
#include <stdbool.h>
#include <pthread.h>
#include <semaphore.h>
......@@ -13,10 +14,11 @@
typedef enum {
OP_WRITE_EQUAL, // Perform a write operation and check if the written value matches the expected value
OP_WRITE_STORE, // Store the written value into a specific location (used in callbacks)
OP_READ_INJECT, // Inject a value into the guest from a specific address
OP_EMUL_END, // End of the state machine, with an callback for completion
OP_WRITE_EQUAL, // Perform a write operation and check if the written value matches the expected value
OP_WRITE_STORE, // Store the written value into a specific location (used in callbacks)
OP_WRITE_STORE_LOOP, // Store the written value into a specific location multiple time
OP_READ_INJECT, // Inject a value into the guest from a specific address
OP_EMUL_END, // End of the state machine, with an callback for completion
} operation_t;
typedef struct {
......@@ -28,10 +30,14 @@ typedef struct {
void (*callback)(void *addr); // custom function that would be executed at the end of the state
} state_t;
extern bool flag_stop_loop;
extern sem_t sem_gfx;
extern uint32_t width_gfx;
extern uint32_t height_gfx;
extern char *disk_path;
extern state_t *STATE_ALL_STARTERS[];
extern state_t STATE_TIMER[];
......@@ -84,4 +90,18 @@ void op_callback_gfx_init_store_h(void *addr);
*/
void op_callback_gfx_init_conclude(void *addr);
void op_callback_ide_prepare(void *addr);
void op_callback_ide_store_sector_1(void *addr);
void op_callback_ide_store_sector_2(void *addr);
void op_callback_ide_store_sector_3(void *addr);
void op_callback_ide_store_sector_4(void *addr);
void op_callback_ide_store_data(void *addr);
void op_callback_ide_condlude(void *addr);
#endif // _OPERATION_H_
......@@ -30,6 +30,8 @@ sem_t sem_gfx;
uint32_t width_gfx;
uint32_t height_gfx;
char *disk_path;
static uint8_t *mem, *shared_buf;
static struct kvm_run *run;
static int vcpufd;
......@@ -67,8 +69,9 @@ int main(int argc, char* argv[])
int32_t mmap_size;
// -- 0. Handle Args --
if (argc != 2) err(1, "Number of args invalide");
if (argc != 3) err(1, "Number of args invalide");
char *file_path = argv[1];
disk_path = argv[2];
// -- 1. Create a KVM device --
kvmfd = open("/dev/kvm", O_RDWR | O_CLOEXEC); // get file descriptor
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment