Skip to content

Commit 2cd9088

Browse files
[viostor] Introduce Registry read capability
Introduces a Registry read capability: 1. Implemented in VioStorReadRegistryParameter() 2. Requires neo helper CopyBufferToAnsiString() 3. Adds capacity to both detect and read DWORD values in: (a) HKLM\SYSTEM\CurrentControlSet\Services\viostor\Paramaters\Device (b) HKLM\SYSTEM\CurrentControlSet\Services\viostor\Paramaters\Device(d) NOT WORKING 4. Also supports per-HBA values for \Parameters\Device\Valuename_123 when the \Parameters\Device(d) key is unavailable (presently broken) 5. Adds TRACE_REGISTRY WPP tracing flag Signed-off-by: benyamin-codez <[email protected]>
1 parent 2bcf04f commit 2cd9088

File tree

2 files changed

+224
-0
lines changed

2 files changed

+224
-0
lines changed

viostor/virtio_stor.c

+223
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,229 @@ VOID WppCleanupRoutine(PVOID arg1)
130130
}
131131
#endif
132132

133+
USHORT CopyBufferToAnsiString(void *_pDest, const void *_pSrc, const char delimiter, size_t _maxlength)
134+
{
135+
PCHAR dst = (PCHAR)_pDest;
136+
PCHAR src = (PCHAR)_pSrc;
137+
USHORT _length = _maxlength;
138+
139+
while (_length && (*src != delimiter))
140+
{
141+
*dst++ = *src++;
142+
--_length;
143+
};
144+
*dst = '\0';
145+
return _length;
146+
}
147+
148+
BOOLEAN VioStorReadRegistryParameter(IN PVOID DeviceExtension, IN PUCHAR ValueName, IN LONG offset)
149+
{
150+
BOOLEAN bReadResult = FALSE;
151+
BOOLEAN bUseAltPerHbaRegRead = FALSE;
152+
ULONG pBufferLength = sizeof(ULONG);
153+
UCHAR *pBuffer = NULL;
154+
PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension;
155+
ULONG spgspn_rc, i, j;
156+
STOR_ADDRESS HwAddress = {0};
157+
PSTOR_ADDRESS pHwAddress = &HwAddress;
158+
CHAR valname_as_str[64] = {0};
159+
CHAR hba_id_as_str[4] = {0};
160+
USHORT shAdapterId = (USHORT)adaptExt->slot_number - 1;
161+
ULONG value_as_ulong;
162+
163+
/* Get a clean buffer to store the registry value... */
164+
pBuffer = StorPortAllocateRegistryBuffer(DeviceExtension, &pBufferLength);
165+
if (pBuffer == NULL)
166+
{
167+
RhelDbgPrint(TRACE_LEVEL_WARNING, " StorPortAllocateRegistryBuffer failed to allocate buffer\n");
168+
return FALSE;
169+
}
170+
memset(pBuffer, 0, sizeof(ULONG));
171+
172+
/* Check if we can get a System PortNumber to access the \Parameters\Device(d) subkey to get a per HBA value.
173+
* FIXME NOTE
174+
*
175+
* Regarding StorPortGetSystemPortNumber():
176+
*
177+
* StorPort always reports STOR_STATUS_INVALID_DEVICE_STATE and does not update pHwAddress->Port.
178+
* Calls to StorPortRegistryRead() and StorPortRegistryWrite() only read or write to \Parameters\Device-1,
179+
* which appears to be an uninitialized value. Therefore, the alternate per HBA read technique will always be used.
180+
*
181+
* Please refer to PR #1216 for more details.
182+
*
183+
* FIXME NOTE END
184+
*/
185+
pHwAddress->Type = STOR_ADDRESS_TYPE_BTL8;
186+
pHwAddress->AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH;
187+
RhelDbgPrint(TRACE_REGISTRY,
188+
" Checking whether the HBA system port number and HBA specific registry are available for reading... "
189+
"\n");
190+
spgspn_rc = StorPortGetSystemPortNumber(DeviceExtension, pHwAddress);
191+
if (spgspn_rc = STOR_STATUS_INVALID_DEVICE_STATE)
192+
{
193+
RhelDbgPrint(TRACE_REGISTRY,
194+
" WARNING : !!!...HBA Port not ready yet...!!! Returns : 0x%x (STOR_STATUS_INVALID_DEVICE_STATE) "
195+
"\n",
196+
spgspn_rc);
197+
/*
198+
* When we are unable to get a valid system PortNumber, we need to
199+
* use an alternate per HBA registry read technique. The technique
200+
* implemented here uses per HBA registry value names based on the
201+
* Storport provided slot_number minus one, padded to hundreds,
202+
* e.g. \Parameters\Device\Valuename_123.
203+
*
204+
* This permits up to 999 HBAs. That ought to be enough... c( O.O )ɔ
205+
*/
206+
bUseAltPerHbaRegRead = TRUE;
207+
RhelDbgPrint(TRACE_REGISTRY,
208+
" Using alternate per HBA registry read technique [\\Parameters\\Device\\Value_(ddd)]. \n");
209+
210+
/* Grab the first 60 characters of the target Registry Value.
211+
* Value name limit is 16,383 characters, so this is important.
212+
* We leave the last 4 characters for the hba_id_as_str values.
213+
* NULL terminator wraps things up. Also used in TRACING.
214+
*/
215+
CopyBufferToAnsiString(&valname_as_str, ValueName, '\0', 60);
216+
CopyBufferToAnsiString(&hba_id_as_str, &shAdapterId, '\0', 4);
217+
218+
/* Convert from integer to padded ASCII numbers. */
219+
if (shAdapterId / 100)
220+
{
221+
j = 0;
222+
hba_id_as_str[j] = (UCHAR)(shAdapterId / 100) + 48;
223+
}
224+
else
225+
{
226+
hba_id_as_str[0] = 48;
227+
if (shAdapterId / 10)
228+
{
229+
j = 1;
230+
hba_id_as_str[j] = (UCHAR)(shAdapterId / 10) + 48;
231+
}
232+
else
233+
{
234+
hba_id_as_str[1] = 48;
235+
j = 2;
236+
hba_id_as_str[j] = (UCHAR)shAdapterId + 48;
237+
}
238+
}
239+
if ((j < 1) && (shAdapterId / 10))
240+
{
241+
j = 1;
242+
hba_id_as_str[j] = (UCHAR)(((shAdapterId - ((shAdapterId / 100) * 100)) / 10) + 48);
243+
}
244+
else if ((j < 2) && (shAdapterId > 9))
245+
{
246+
j = 2;
247+
hba_id_as_str[j] = (UCHAR)((shAdapterId - ((shAdapterId / 10) * 10)) + 48);
248+
}
249+
else
250+
{
251+
j = 1;
252+
hba_id_as_str[j] = 48;
253+
}
254+
if ((j < 2) && (shAdapterId > 0))
255+
{
256+
j = 2;
257+
hba_id_as_str[j] = (UCHAR)((shAdapterId - ((shAdapterId / 10) * 10)) + 48);
258+
}
259+
else if (j < 2)
260+
{
261+
j = 2;
262+
hba_id_as_str[j] = 48;
263+
}
264+
/* NULL-terminate the string. */
265+
hba_id_as_str[3] = '\0';
266+
/* Skip the exisitng ValueName. */
267+
for (i = 0; valname_as_str[i] != '\0'; ++i)
268+
{
269+
}
270+
/* Append an underscore. */
271+
valname_as_str[i] = '\x5F';
272+
/* Append the padded HBA ID and NULL terminator. */
273+
for (j = 0; j < 4; ++j)
274+
{
275+
valname_as_str[i + j + 1] = hba_id_as_str[j];
276+
}
277+
278+
PUCHAR ValueNamePerHba = (UCHAR *)&valname_as_str;
279+
bReadResult = StorPortRegistryRead(DeviceExtension,
280+
ValueNamePerHba,
281+
1,
282+
MINIPORT_REG_DWORD,
283+
pBuffer,
284+
&pBufferLength);
285+
}
286+
else
287+
{
288+
RhelDbgPrint(TRACE_REGISTRY, " HBA Port : %u | Returns : 0x%x \n", pHwAddress->Port, spgspn_rc);
289+
RhelDbgPrint(TRACE_REGISTRY, " Using StorPort-based per HBA registry read [\\Parameters\\Device(d)]. \n");
290+
/* FIXME : THIS DOES NOT WORK. IT WILL NOT READ \Parameters\Device(d) subkeys...
291+
* NOTE : Only MINIPORT_REG_DWORD values are supported.
292+
*/
293+
bReadResult = StorPortRegistryRead(DeviceExtension, ValueName, 0, MINIPORT_REG_DWORD, pBuffer, &pBufferLength);
294+
/* Grab the first 64 characters of the target Registry Value.
295+
* Value name limit is 16,383 characters, so this is important.
296+
* NULL terminator wraps things up. Used in TRACING.
297+
*/
298+
CopyBufferToAnsiString(&valname_as_str, ValueName, '\0', 64);
299+
}
300+
301+
if ((bReadResult == FALSE) || (pBufferLength == 0))
302+
{
303+
RhelDbgPrint(TRACE_REGISTRY,
304+
" StorPortRegistryRead was unable to find a per HBA value %s. Attempting to find a global "
305+
"value... \n",
306+
(bUseAltPerHbaRegRead) ? "using \\Parameters\\Device\\Value_(ddd) value names"
307+
: "at the \\Parameters\\Device(d) subkey");
308+
bReadResult = FALSE;
309+
pBufferLength = sizeof(ULONG);
310+
memset(pBuffer, 0, sizeof(ULONG));
311+
312+
/* Do a "Global" read of the Parameters\Device subkey...
313+
* NOTE : Only MINIPORT_REG_DWORD values are supported.
314+
*/
315+
bReadResult = StorPortRegistryRead(DeviceExtension, ValueName, 1, MINIPORT_REG_DWORD, pBuffer, &pBufferLength);
316+
/* Grab the first 64 characters of the target Registry Value.
317+
* Value name limit is 16,383 characters, so this is important.
318+
* NULL terminator wraps things up. Used in TRACING.
319+
*/
320+
CopyBufferToAnsiString(&valname_as_str, ValueName, '\0', 64);
321+
}
322+
/* Give me the DWORD Registry Value as a ULONG from the pointer.
323+
* Used in TRACING.
324+
*/
325+
memcpy(&value_as_ulong, pBuffer, sizeof(ULONG));
326+
327+
if ((bReadResult == FALSE) || (pBufferLength == 0))
328+
{
329+
RhelDbgPrint(TRACE_REGISTRY,
330+
" StorPortRegistryRead of %s returned NOT FOUND or EMPTY, pBufferLength = %d, Possible "
331+
"pBufferLength Hint = 0x%x (%lu) \n",
332+
valname_as_str,
333+
pBufferLength,
334+
value_as_ulong,
335+
value_as_ulong);
336+
StorPortFreeRegistryBuffer(DeviceExtension, pBuffer);
337+
return FALSE;
338+
}
339+
else
340+
{
341+
RhelDbgPrint(TRACE_REGISTRY,
342+
" StorPortRegistryRead of %s returned SUCCESS, pBufferLength = %d, Value = 0x%x (%lu) \n",
343+
valname_as_str,
344+
pBufferLength,
345+
value_as_ulong,
346+
value_as_ulong);
347+
348+
StorPortCopyMemory((PVOID)((UINT_PTR)adaptExt + offset), (PVOID)pBuffer, sizeof(ULONG));
349+
350+
StorPortFreeRegistryBuffer(DeviceExtension, pBuffer);
351+
352+
return TRUE;
353+
}
354+
}
355+
133356
ULONG
134357
DriverEntry(IN PVOID DriverObject, IN PVOID RegistryPath)
135358
{

viostor/virtio_stor_trace.h

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ extern int nViostorDebugLevel;
9090
WPP_DEFINE_BIT(TRACE_LEVEL_WARNING) /* bit 3 = 0x00000008 */ \
9191
WPP_DEFINE_BIT(TRACE_LEVEL_INFORMATION) /* bit 4 = 0x00000010 */ \
9292
WPP_DEFINE_BIT(TRACE_LEVEL_VERBOSE) /* bit 5 = 0x00000020 */ \
93+
WPP_DEFINE_BIT(TRACE_REGISTRY) /* bit 6 = 0x00000040 */ \
9394
)
9495

9596
#define WPP_Flags_LEVEL_LOGGER(Flags, level) \

0 commit comments

Comments
 (0)