From 5aaab2879d0fbbb0b3665d5c5566c88e74e02a36 Mon Sep 17 00:00:00 2001 From: Tau Date: Wed, 7 Nov 2018 16:45:48 -0500 Subject: [PATCH] nu/eeprom.c: Add emulated EEPROM device --- nu/eeprom.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++++ nu/eeprom.h | 12 ++++ nu/guid.c | 2 + nu/meson.build | 2 + 4 files changed, 170 insertions(+) create mode 100644 nu/eeprom.c create mode 100644 nu/eeprom.h diff --git a/nu/eeprom.c b/nu/eeprom.c new file mode 100644 index 0000000..88400ce --- /dev/null +++ b/nu/eeprom.c @@ -0,0 +1,154 @@ +#include + +#include "hook/iohook.h" + +#include "nu/eeprom.h" +#include "nu/nvram.h" + +#include "util/dprintf.h" +#include "util/setupapi.h" + +static HRESULT eeprom_handle_irp(struct irp *irp); +static HRESULT eeprom_handle_open(struct irp *irp); +static HRESULT eeprom_handle_close(struct irp *irp); +static HRESULT eeprom_handle_ioctl(struct irp *irp); +static HRESULT eeprom_handle_read(struct irp *irp); +static HRESULT eeprom_handle_write(struct irp *irp); + +static HRESULT eeprom_ioctl_get_geometry(struct irp *irp); + +static HANDLE eeprom_file; + +HRESULT eeprom_hook_init(void) +{ + HRESULT hr; + + hr = nvram_open_file(&eeprom_file, L"DEVICE\\eeprom.bin", 0x2000); + + if (FAILED(hr)) { + return hr; + } + + hr = iohook_push_handler(eeprom_handle_irp); + + if (FAILED(hr)) { + return hr; + } + + hr = setupapi_add_phantom_dev(&eeprom_guid, L"$eeprom"); + + if (FAILED(hr)) { + return hr; + } + + return S_OK; +} + +static HRESULT eeprom_handle_irp(struct irp *irp) +{ + assert(irp != NULL); + + if (irp->op != IRP_OP_OPEN && irp->fd != eeprom_file) { + return iohook_invoke_next(irp); + } + + switch (irp->op) { + case IRP_OP_OPEN: return eeprom_handle_open(irp); + case IRP_OP_CLOSE: return eeprom_handle_close(irp); + case IRP_OP_IOCTL: return eeprom_handle_ioctl(irp); + case IRP_OP_READ: return eeprom_handle_read(irp); + case IRP_OP_WRITE: return eeprom_handle_write(irp); + default: return iohook_invoke_next(irp); + } +} + +static HRESULT eeprom_handle_open(struct irp *irp) +{ + if (wcscmp(irp->open_filename, L"$eeprom") != 0) { + return iohook_invoke_next(irp); + } + + dprintf("EEPROM: Open device\n"); + irp->fd = eeprom_file; + + return S_OK; +} + +static HRESULT eeprom_handle_close(struct irp *irp) +{ + dprintf("EEPROM: Close device\n"); + + return S_OK; +} + +static HRESULT eeprom_handle_ioctl(struct irp *irp) +{ + switch (irp->ioctl) { + case IOCTL_DISK_GET_DRIVE_GEOMETRY: + return eeprom_ioctl_get_geometry(irp); + + default: + dprintf("EEPROM: Unknown ioctl %x, write %i read %i\n", + irp->ioctl, + irp->write.nbytes, + irp->read.nbytes); + + return HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION); + } +} + +static HRESULT eeprom_ioctl_get_geometry(struct irp *irp) +{ + DISK_GEOMETRY *out; + + if (irp->read.nbytes < sizeof(*out)) { + dprintf("EEPROM: Invalid ioctl response buffer size\n"); + + return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + } + + dprintf("EEPROM: Get geometry\n"); + + /* Not the real values, just bullshitting something for now */ + + out = (DISK_GEOMETRY *) irp->read.bytes; + out->Cylinders.QuadPart = 0x800; + out->MediaType = 0; + out->TracksPerCylinder = 1; + out->SectorsPerTrack = 2; + out->BytesPerSector = 4; + + irp->read.pos = sizeof(*out); + + return S_OK; +} + +static HRESULT eeprom_handle_read(struct irp *irp) +{ + if (irp->ovl == NULL) { + dprintf("EEPROM: Synchronous read..?\n"); + + return E_UNEXPECTED; + } + + dprintf("EEPROM: Read off %x len %x\n", + (int) irp->ovl->Offset, + irp->read.nbytes); + + return iohook_invoke_next(irp); +} + +static HRESULT eeprom_handle_write(struct irp *irp) +{ + if (irp->ovl == NULL) { + dprintf("EEPROM: Synchronous write..?\n"); + + return E_UNEXPECTED; + } + + dprintf("EEPROM: Write off %x len %x\n", + (int) irp->ovl->Offset, + irp->write.nbytes); + + return iohook_invoke_next(irp); +} diff --git a/nu/eeprom.h b/nu/eeprom.h new file mode 100644 index 0000000..0d1802d --- /dev/null +++ b/nu/eeprom.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +DEFINE_GUID( + eeprom_guid, + 0xB7970F0C, + 0x31C4, + 0x45FF, + 0x96, 0x18, 0x0A, 0x24, 0x00, 0x94, 0xB2, 0x71); + +HRESULT eeprom_hook_init(void); diff --git a/nu/guid.c b/nu/guid.c index 3bb6ac4..f2f706f 100644 --- a/nu/guid.c +++ b/nu/guid.c @@ -1,2 +1,4 @@ #include #include + +#include "nu/eeprom.h" diff --git a/nu/meson.build b/nu/meson.build index 771292e..f827bb9 100644 --- a/nu/meson.build +++ b/nu/meson.build @@ -8,6 +8,8 @@ nu_lib = static_library( capnhook.get_variable('hooklib_dep'), ], sources : [ + 'eeprom.c', + 'eeprom.h', 'guid.c', 'nvram.c', 'nvram.h',