diff --git a/shared/hypercall_params.h b/shared/hypercall_params.h index c1338ad75713eb727bd9cd84166b8768e7454f84..0fdc4399118c6f1150cf747cb070857c822ad86c 100644 --- a/shared/hypercall_params.h +++ b/shared/hypercall_params.h @@ -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 --- // ... diff --git a/vmm/handler.c b/vmm/handler.c index 31ef2c42c3efe3a81f9cc6caf12f6658f331a345..5c0b4852cd2c55fe8bb9217b820acdbcda28bbdc 100644 --- a/vmm/handler.c +++ b/vmm/handler.c @@ -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; diff --git a/vmm/operation.c b/vmm/operation.c index e0f3406ac654b9c2ed841f2b3b40813d4eebd417..9a7f6b123c0fb1fa999267e550abc09d72e3703d 100644 --- a/vmm/operation.c +++ b/vmm/operation.c @@ -1,10 +1,14 @@ #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) ? ¶m_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); +} diff --git a/vmm/operation.h b/vmm/operation.h index 05f95d806affcfd172a0a81ef3f42adb544aecf8..ff9af8186e2adc29e4d01d7edbcd150819afc155 100644 --- a/vmm/operation.h +++ b/vmm/operation.h @@ -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_ diff --git a/vmm/vmm_main.c b/vmm/vmm_main.c index 91771d21bf2628e458287ea9f16f8527b120d4f8..1f5b037214df242b83f3c62fd1ff008454259530 100644 --- a/vmm/vmm_main.c +++ b/vmm/vmm_main.c @@ -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