kvm-guest-drivers-windows
147 строк · 3.9 Кб
1/*
2* This file contains fw_cfg routines
3*
4* Copyright (C) 2018 Virtuozzo International GmbH
5*
6*/
7#include "fwcfg.h"8#include "trace.h"9#include "fwcfg.tmh"10
11VOID FWCfgReadBlob(PVOID ioBase, UINT16 key, PVOID buf, ULONG count)12{
13WRITE_PORT_USHORT((PUSHORT)FW_CFG_CTL(ioBase), key);14READ_PORT_BUFFER_UCHAR(FW_CFG_DAT(ioBase), (PUCHAR)buf, count);15}
16
17NTSTATUS FWCfgCheckSig(PVOID ioBase)18{
19UCHAR signature[FW_CFG_SIG_SIZE];20
21FWCfgReadBlob(ioBase, FW_CFG_SIGNATURE, signature, FW_CFG_SIG_SIZE);22TraceEvents(TRACE_LEVEL_VERBOSE, DBG_ALL,23"Signature is [%.4s]", (PCHAR)signature);24if (memcmp(signature, FW_CFG_QEMU, FW_CFG_SIG_SIZE))25{26TraceEvents(TRACE_LEVEL_ERROR, DBG_ALL, "Signature check failed, "27"["FW_CFG_QEMU"] expected");28return STATUS_BAD_DATA;29}30
31return STATUS_SUCCESS;32}
33
34NTSTATUS FWCfgCheckFeatures(PVOID ioBase, UINT32 features)35{
36UINT32 f_bitmap;37
38FWCfgReadBlob(ioBase, FW_CFG_ID, &f_bitmap, sizeof(f_bitmap));39TraceEvents(TRACE_LEVEL_VERBOSE, DBG_ALL, "Features are 0x%lx", f_bitmap);40if ((f_bitmap & features) != features)41{42TraceEvents(TRACE_LEVEL_ERROR, DBG_ALL, "Features check failed, "43" 0x%lx expected", features);44return STATUS_BAD_DATA;45}46
47return STATUS_SUCCESS;48}
49
50UINT64 FWCfgReadDmaReg(PVOID ioBase)51{
52UINT64 dma_reg;53
54((UINT32 *)&dma_reg)[0] = READ_PORT_ULONG((PULONG)FW_CFG_DMA(ioBase));55((UINT32 *)&dma_reg)[1] = READ_PORT_ULONG((PULONG)FW_CFG_DMA(ioBase) + 1);56
57return RtlUlonglongByteSwap(dma_reg);58}
59
60VOID FWCfgWriteDmaReg(PVOID ioBase, UINT64 val)61{
62val = RtlUlonglongByteSwap(val);63WRITE_PORT_ULONG((PULONG)FW_CFG_DMA(ioBase), ((PULONG)&val)[0]);64WRITE_PORT_ULONG((PULONG)FW_CFG_DMA(ioBase) + 1, ((PULONG)&val)[1]);65}
66
67NTSTATUS FWCfgCheckDma(PVOID ioBase)68{
69UINT64 test = FWCfgReadDmaReg(ioBase);70if (test != FW_CFG_QEMU_DMA)71{72return STATUS_BAD_DATA;73}74
75return STATUS_SUCCESS;76}
77
78/*
79At the end of this routine selector points at first file entry
80*/
81UINT32 FWCfgGetEntriesNum(PVOID ioBase)82{
83UINT32 num;84
85FWCfgReadBlob(ioBase, FW_CFG_FILE_DIR, &num, sizeof(num));86num = RtlUlongByteSwap(num);87TraceEvents(TRACE_LEVEL_VERBOSE, DBG_ALL, "Total %lu entries", num);88
89return num;90}
91
92NTSTATUS FWCfgFindEntry(PVOID ioBase, const char *name,93PUSHORT index, ULONG size)94{
95UINT32 i;96UINT32 total = FWCfgGetEntriesNum(ioBase);97FWCfgFile f;98
99if (total > MAXUINT16)100{101return STATUS_BAD_DATA;102}103
104for (i = 0; i < total; i++)105{106READ_PORT_BUFFER_UCHAR(FW_CFG_DAT(ioBase), (PUCHAR)&f, sizeof(f));107TraceEvents(TRACE_LEVEL_VERBOSE, DBG_ALL, "[%.56s]", f.name);108if (!strncmp(f.name, name, FW_CFG_MAX_FILE_PATH))109{110if (RtlUlongByteSwap(f.size) == size)111{112*index = RtlUshortByteSwap(f.select);113return STATUS_SUCCESS;114}115return STATUS_BAD_DATA;116}117}118
119return STATUS_BAD_DATA;120}
121
122NTSTATUS FWCfgDmaSend(PVOID ioBase, LONGLONG data_pa, USHORT index,123UINT32 size, FWCfgDmaAccess *pDmaAccess, LONGLONG dmaAccess_pa)124{
125UINT16 ctrl = FW_CFG_DMA_CTL_SELECT | FW_CFG_DMA_CTL_WRITE;126NTSTATUS status;127
128pDmaAccess->control = RtlUlongByteSwap(((UINT32)index << 16UL) | ctrl);129pDmaAccess->length = RtlUlongByteSwap(size);130pDmaAccess->address = RtlUlonglongByteSwap(data_pa);131
132FWCfgWriteDmaReg(ioBase, (UINT64)dmaAccess_pa);133
134ctrl = RtlUlongByteSwap(pDmaAccess->control) & MAXUINT16;135if (!ctrl)136{137TraceEvents(TRACE_LEVEL_VERBOSE, DBG_ALL, "Transfer succeed");138status = STATUS_SUCCESS;139}140else141{142TraceEvents(TRACE_LEVEL_ERROR, DBG_ALL, "Transfer failed, 0x%x", ctrl);143status = STATUS_IO_DEVICE_ERROR;144}145
146return status;147}
148