diff --git a/nu/guid.c b/nu/guid.c index f2f706f..3ea1064 100644 --- a/nu/guid.c +++ b/nu/guid.c @@ -2,3 +2,4 @@ #include #include "nu/eeprom.h" +#include "nu/sram.h" diff --git a/nu/meson.build b/nu/meson.build index f827bb9..d4aaeaf 100644 --- a/nu/meson.build +++ b/nu/meson.build @@ -13,5 +13,7 @@ nu_lib = static_library( 'guid.c', 'nvram.c', 'nvram.h', + 'sram.c', + 'sram.h', ], ) diff --git a/nu/sram.c b/nu/sram.c new file mode 100644 index 0000000..08083d6 --- /dev/null +++ b/nu/sram.c @@ -0,0 +1,118 @@ +#include + +#include "hook/iohook.h" + +#include "nu/sram.h" +#include "nu/nvram.h" + +#include "util/dprintf.h" +#include "util/setupapi.h" + +static HRESULT sram_handle_irp(struct irp *irp); +static HRESULT sram_handle_open(struct irp *irp); +static HRESULT sram_handle_close(struct irp *irp); +static HRESULT sram_handle_ioctl(struct irp *irp); + +static HRESULT sram_ioctl_get_geometry(struct irp *irp); + +static HANDLE sram_file; + +HRESULT sram_hook_init(void) +{ + HRESULT hr; + + hr = nvram_open_file(&sram_file, L"DEVICE\\sram.bin", 0x80000); + + if (FAILED(hr)) { + return hr; + } + + hr = iohook_push_handler(sram_handle_irp); + + if (FAILED(hr)) { + return hr; + } + + hr = setupapi_add_phantom_dev(&sram_guid, L"$sram"); + + if (FAILED(hr)) { + return hr; + } + + return S_OK; +} + +static HRESULT sram_handle_irp(struct irp *irp) +{ + assert(irp != NULL); + + if (irp->op != IRP_OP_OPEN && irp->fd != sram_file) { + return iohook_invoke_next(irp); + } + + switch (irp->op) { + case IRP_OP_OPEN: return sram_handle_open(irp); + case IRP_OP_CLOSE: return sram_handle_close(irp); + case IRP_OP_IOCTL: return sram_handle_ioctl(irp); + default: return iohook_invoke_next(irp); + } +} + +static HRESULT sram_handle_open(struct irp *irp) +{ + if (wcscmp(irp->open_filename, L"$sram") != 0) { + return iohook_invoke_next(irp); + } + + dprintf("SRAM: Open device\n"); + irp->fd = sram_file; + + return S_OK; +} + +static HRESULT sram_handle_close(struct irp *irp) +{ + dprintf("SRAM: Close device\n"); + + return S_OK; +} + +static HRESULT sram_handle_ioctl(struct irp *irp) +{ + switch (irp->ioctl) { + case IOCTL_DISK_GET_DRIVE_GEOMETRY: + return sram_ioctl_get_geometry(irp); + + default: + dprintf("SRAM: 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 sram_ioctl_get_geometry(struct irp *irp) +{ + DISK_GEOMETRY *out; + + if (irp->read.nbytes < sizeof(*out)) { + dprintf("SRAM: Invalid ioctl response buffer size\n"); + + return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + } + + dprintf("SRAM: Get geometry\n"); + + out = (DISK_GEOMETRY *) irp->read.bytes; + out->Cylinders.QuadPart = 0x20000; + out->MediaType = 0; + out->TracksPerCylinder = 1; + out->SectorsPerTrack = 1; + out->BytesPerSector = 4; + + irp->read.pos = sizeof(*out); + + return S_OK; +} diff --git a/nu/sram.h b/nu/sram.h new file mode 100644 index 0000000..f2c4c3b --- /dev/null +++ b/nu/sram.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +DEFINE_GUID( + sram_guid, + 0x741B5FCA, + 0x4635, + 0x4443, + 0xA7, 0xA0, 0x57, 0xCA, 0x7B, 0x50, 0x6A, 0x49); + +HRESULT sram_hook_init(void);