forked from virtio-win/kvm-guest-drivers-windows
-
Notifications
You must be signed in to change notification settings - Fork 0
/
power.c
176 lines (142 loc) · 4.43 KB
/
power.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*
* This file contains PNP power callbacks
*
* Copyright (C) 2018 Virtuozzo International GmbH
*
*/
#include "driver.h"
#include "fwcfg.h"
#include "trace.h"
#include "power.tmh"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FwCfgEvtDevicePrepareHardware)
#pragma alloc_text(PAGE, FwCfgEvtDeviceReleaseHardware)
#pragma alloc_text(PAGE, FwCfgEvtDeviceD0Entry)
#pragma alloc_text(PAGE, FwCfgEvtDeviceD0Exit)
#endif
VOID PutKdbg(PDEVICE_CONTEXT ctx)
{
if (ctx->kdbg)
{
ExFreePool(ctx->kdbg);
ctx->kdbg = NULL;
VMCoreInfoSend(ctx);
}
}
NTSTATUS FwCfgEvtDeviceD0Exit(IN WDFDEVICE Device,
IN WDF_POWER_DEVICE_STATE TargetState)
{
UNREFERENCED_PARAMETER(Device);
UNREFERENCED_PARAMETER(TargetState);
PAGED_CODE();
return STATUS_SUCCESS;
}
NTSTATUS FwCfgEvtDeviceD0Entry(IN WDFDEVICE Device,
IN WDF_POWER_DEVICE_STATE PreviousState)
{
PDEVICE_CONTEXT ctx = GetDeviceContext(Device);
NTSTATUS status;
PVMCI_ELF64_NOTE note = ctx->vmci_data.pNote;
PVMCOREINFO pVmci = ctx->vmci_data.pVmci;
UNREFERENCED_PARAMETER(PreviousState);
PAGED_CODE();
if (!ctx->kdbg)
return STATUS_SUCCESS;
note->n_namesz = sizeof(VMCI_ELF_NOTE_NAME);
note->n_descsz = DUMP_HDR_SIZE;
note->n_type = 0;
memcpy(note->n_name, VMCI_ELF_NOTE_NAME, note->n_namesz);
pVmci->host_fmt = 0;
pVmci->guest_fmt = VMCOREINFO_FORMAT_ELF;
pVmci->paddr = ctx->vmci_data.note_pa;
pVmci->size = sizeof(VMCI_ELF64_NOTE);
status = VMCoreInfoFill(ctx);
if (!NT_SUCCESS(status))
{
return status;
}
status = VMCoreInfoSend(ctx);
return status;
}
NTSTATUS PrepareVMCoreInfo(PDEVICE_CONTEXT ctx)
{
NTSTATUS status;
if (FWCfgCheckSig(ctx->ioBase) ||
FWCfgCheckFeatures(ctx->ioBase, FW_CFG_VERSION_DMA) ||
FWCfgCheckDma(ctx->ioBase))
{
TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
"FwCfg device is not suitable for VMCoreInfo");
return STATUS_UNSUCCESSFUL;
}
status = FWCfgFindEntry(ctx->ioBase, ENTRY_NAME, &ctx->index,
sizeof(VMCOREINFO));
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
"VMCoreInfo entry is not found");
return status;
}
TraceEvents(TRACE_LEVEL_VERBOSE, DBG_PNP,
"VMCoreInfo entry index is 0x%x", ctx->index);
status = GetKdbg(ctx);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
"Failed to get KdDebuggerDataBlock");
return status;
}
return STATUS_SUCCESS;
}
NTSTATUS FwCfgEvtDevicePrepareHardware(IN WDFDEVICE Device,
IN WDFCMRESLIST Resources,
IN WDFCMRESLIST ResourcesTranslated)
{
ULONG i;
PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
PDEVICE_CONTEXT ctx;
NTSTATUS status = STATUS_RESOURCE_IN_USE;
UNREFERENCED_PARAMETER(Resources);
PAGED_CODE();
ctx = GetDeviceContext(Device);
for (i = 0; i < WdfCmResourceListGetCount(ResourcesTranslated); i++)
{
desc = WdfCmResourceListGetDescriptor(ResourcesTranslated, i);
if (desc &&
(desc->Type == CmResourceTypePort) &&
(desc->Flags & CM_RESOURCE_PORT_IO))
{
ctx->ioBase = (PVOID)(ULONG_PTR)desc->u.Port.Start.QuadPart;
ctx->ioSize = desc->u.Port.Length;
TraceEvents(TRACE_LEVEL_VERBOSE, DBG_PNP,
"I/O ports: 0x%llx-0x%llx", (UINT64)ctx->ioBase,
(UINT64)ctx->ioBase + ctx->ioSize);
status = STATUS_SUCCESS;
}
}
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "No I/O ports");
return status;
}
status = PrepareVMCoreInfo(ctx);
if (!NT_SUCCESS(status))
{
/*
* Don't fail here, because the driver is not only for vmcoreinfo,
* but for the whole fw_cfg device. But the driver will be useless.
*/
TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "VMCoreInfo will not work");
}
return STATUS_SUCCESS;
}
NTSTATUS FwCfgEvtDeviceReleaseHardware(IN WDFDEVICE Device,
IN WDFCMRESLIST ResourcesTranslated)
{
PDEVICE_CONTEXT ctx;
UNREFERENCED_PARAMETER(ResourcesTranslated);
PAGED_CODE();
ctx = GetDeviceContext(Device);
PutKdbg(ctx);
return STATUS_SUCCESS;
}