ReactOS 0.4.17-dev-1281-g065abb3
hubdrom.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS SuperSpeed USB Hub Driver
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: USB4 router DROM read hooks of the hub machine
5 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org>
6 */
7
8#include "usbhub3.h"
9
10#define NDEBUG
11#include <debug.h>
12
13/* Vendor requests that reach the router mailbox registers over the hub's default pipe */
14#define HUB_MAILBOX_READ_TYPE 0xC0
15#define HUB_MAILBOX_WRITE_TYPE 0x40
16#define HUB_MAILBOX_READ_REQUEST 0x40
17#define HUB_MAILBOX_WRITE_REQUEST 0x41
18#define HUB_MAILBOX_SPACE 0x0400
19
20/* Hub hardware verifier bit that stops in the debugger on a failed control transfer */
21#define HUB_VERIFIER_CONTROL_FAILURE 0x00000002
22
23/* USB4 DROM layout the identity lookup uses */
24#define DROM_VERSION_OFFSET 13
25#define DROM_LENGTH_OFFSET 14
26#define DROM_LENGTH_MASK 0x0FFF
27#define DROM_FIRST_ENTRY 22
28#define DROM_ENTRY_HEADER 2
29#define DROM_ENTRY_ADAPTER 0x80
30#define DROM_ENTRY_TYPE_MASK 0x3F
31#define DROM_ENTRY_TYPE_IDENTITY 9
32
33/* Field offsets inside the identity entry, and the length that holds all of them */
34#define DROM_IDENTITY_VENDOR 4
35#define DROM_IDENTITY_PRODUCT 6
36#define DROM_IDENTITY_BCD 8
37#define DROM_IDENTITY_REVISION 14
38#define DROM_IDENTITY_LENGTH 15
39
40static EVT_WDF_REQUEST_COMPLETION_ROUTINE HubMailboxComplete;
41
42static
43VOID
46 _In_ WDFREQUEST Request,
47 _In_ WDFIOTARGET Target,
50{
52 NTSTATUS Status = Params->IoStatus.Status;
53
56
58
59 if (!NT_SUCCESS(Status))
60 {
61 DPRINT1("Hub %p mailbox register %u access failed 0x%lx, URB status 0x%lx\n",
62 Hub, Hub->m_Control.Urb.SetupPacket[4], Status, Hub->m_Control.Urb.Hdr.Status);
63
65 return;
66 }
67
69}
70
71/* Four byte transfer of m_DromMailbox; a refused send is reported to the machine at once */
72static
73VOID
79{
81
86 sizeof(Hub->m_DromMailbox));
87
89 Hub->UsbDevice(),
91 Hub,
93 sizeof(Hub->m_DromMailbox),
94 FALSE,
96 if (!NT_SUCCESS(Status))
97 {
98 DPRINT1("Hub %p mailbox register %u %s not sent 0x%lx\n", Hub, Register, Write ? "write" : "read", Status);
100 }
101}
102
103static
104USHORT
105NTAPI
107 _In_reads_bytes_(2) const UCHAR* Bytes)
108{
109 return (USHORT)(Bytes[0] | (Bytes[1] << 8));
110}
111
112/* QUIRK: the firmware update protocol gates the read, not tunneling; the identity only names the update device */
115{
116 return m_Hub->m_Parent.HubDepth != 0 && m_Hub->m_FwUpdateProtocol == 1;
117}
118
119ULONG
121{
122 return m_Hub->m_DromMailbox;
123}
124
125ULONG
127{
128 const UCHAR* Header = (const UCHAR*)m_Hub->m_DromHeader;
129
131}
132
133VOID
136{
138}
139
140VOID
144{
147}
148
149VOID
151{
154}
155
156/* Whole DWORDs are stored, so the buffer is rounded up to them */
160{
161 ULONG Bytes = ALIGN_UP_BY(Length, sizeof(ULONG));
163
165 if (Buffer == NULL)
166 {
167 DPRINT1("Hub %p no memory for a %lu byte router DROM\n", m_Hub, Length);
168 return FALSE;
169 }
170
174 return TRUE;
175}
176
177VOID
179{
180 if (m_Hub->m_DromPool != NULL)
182
185 m_Hub->m_DromLength = 0;
186}
187
188VOID
191{
194}
195
200VOID
202{
204 const UCHAR* Drom = (const UCHAR*)m_Hub->m_DromPool;
205 const UCHAR* Entry;
208
209 if (Drom == NULL || Drom[DROM_VERSION_OFFSET] != 1)
210 return;
211
213 {
214 Entry = &Drom[Offset];
215
216 if (Entry[0] == 0)
217 {
218 DPRINT1("Hub %p router DROM has a zero length entry at %lu\n", m_Hub, Offset);
219 return;
220 }
221
222 if (Entry[0] > Length - Offset)
223 {
224 DPRINT1("Hub %p router DROM entry at %lu overruns the DROM\n", m_Hub, Offset);
225 return;
226 }
227
229 continue;
230
232 {
233 DPRINT1("Hub %p router DROM identity entry is only %u bytes\n", m_Hub, Entry[0]);
234 return;
235 }
236
237 /* QUIRK: a later read that fails keeps this identity */
242 Identity->Known = TRUE;
243
244 DPRINT("Hub %p router VID %04X PID %04X BCD %04X REV %04X\n",
245 m_Hub, Identity->VendorId, Identity->ProductId, Identity->BcdDevice, Identity->Revision);
246 return;
247 }
248
249 DPRINT1("Hub %p router DROM has no identity entry\n", m_Hub);
250}
251
257VOID
258NTAPI
259HubDromReportFirmwareUpdateDevice(
260 _In_ HubFdo* Hub)
261{
263
264 if (!Identity->Known || Hub->IsRootHub() || Hub->m_FwUpdateProtocol == 0)
265 return;
266
267 DPRINT1("Hub %p firmware update device USB\\VID_%04X&PID_%04X&BCD_%04X&REV_%04X&GFU is not supported\n",
268 Hub, Identity->VendorId, Identity->ProductId, Identity->BcdDevice, Identity->Revision);
269}
#define ALIGN_UP_BY(size, align)
unsigned char BOOLEAN
Definition: actypes.h:127
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
HubFdo * Hub
Definition: bootdev.cpp:261
Definition: bufpool.h:45
Definition: Header.h:9
Definition: fdo.h:132
ULONG m_DromLength
Definition: fdo.h:459
WDFIOTARGET m_RootHubTarget
Definition: fdo.h:368
ULONG m_DromHeader[4]
Definition: fdo.h:456
VOID Post(_In_ HubEvent Event)
Definition: fdo.h:194
PULONG m_DromPool
Definition: fdo.h:458
HubControlRequest m_Control
Definition: fdo.h:413
UCXUSBDEVICE UsbDevice() const
Definition: fdo.h:180
ULONG m_FwUpdateProtocol
Definition: fdo.h:453
BOOLEAN NeedsForwardProgress() const
Definition: fdo.h:208
UCXHUB_PARENT_INTERFACE m_Parent
Definition: fdo.h:355
BOOLEAN IsRootHub() const
Definition: fdo.h:174
PULONG m_DromBuffer
Definition: fdo.h:457
HubRouterIdentity m_RouterIdentity
Definition: fdo.h:461
ULONG m_DromMailbox
Definition: fdo.h:460
VOID ReadDromRegister(_In_ USHORT Register)
Definition: hubdrom.cpp:134
ULONG MailboxValue()
Definition: hubdrom.cpp:120
VOID ReleaseDromBuffer()
Definition: hubdrom.cpp:178
BOOLEAN IsDromReadWanted()
Definition: hubdrom.cpp:114
VOID ParseDromIdentity()
Finds the router identity entry of a version 1 DROM, bounds checking each entry.
Definition: hubdrom.cpp:201
ULONG DromDataLength()
Definition: hubdrom.cpp:126
VOID UseDromHeaderBuffer()
Definition: hubdrom.cpp:150
HubFdo * m_Hub
Definition: hubsm.h:574
VOID StoreDromWord(_In_ ULONG Index)
Definition: hubdrom.cpp:189
VOID WriteDromRegister(_In_ USHORT Register, _In_ ULONG Value)
Definition: hubdrom.cpp:141
BOOLEAN AllocateDromBuffer(_In_ ULONG Length)
Definition: hubdrom.cpp:158
PLIST_ENTRY Entry
Definition: devhcd.cpp:1262
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
static GLfloat Identity[16]
Definition: matrix.c:127
#define _IRQL_requires_(irql)
Definition: driverspecs.h:229
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define NonPagedPool
Definition: env_spec_w32.h:307
Status
Definition: gdiplustypes.h:24
static EVT_WDF_REQUEST_COMPLETION_ROUTINE HubMailboxComplete
Definition: hubdrom.cpp:40
#define DROM_FIRST_ENTRY
Definition: hubdrom.cpp:27
#define DROM_LENGTH_OFFSET
Definition: hubdrom.cpp:25
#define DROM_ENTRY_TYPE_MASK
Definition: hubdrom.cpp:30
#define DROM_IDENTITY_LENGTH
Definition: hubdrom.cpp:38
#define HUB_MAILBOX_READ_REQUEST
Definition: hubdrom.cpp:16
static USHORT NTAPI HubDromReadUshort(_In_reads_bytes_(2) const UCHAR *Bytes)
Definition: hubdrom.cpp:106
#define DROM_LENGTH_MASK
Definition: hubdrom.cpp:26
#define DROM_ENTRY_ADAPTER
Definition: hubdrom.cpp:29
#define DROM_IDENTITY_VENDOR
Definition: hubdrom.cpp:34
#define DROM_ENTRY_TYPE_IDENTITY
Definition: hubdrom.cpp:31
#define HUB_MAILBOX_READ_TYPE
Definition: hubdrom.cpp:14
#define DROM_VERSION_OFFSET
Definition: hubdrom.cpp:24
#define HUB_MAILBOX_WRITE_TYPE
Definition: hubdrom.cpp:15
#define HUB_MAILBOX_WRITE_REQUEST
Definition: hubdrom.cpp:17
#define HUB_MAILBOX_SPACE
Definition: hubdrom.cpp:18
#define DROM_IDENTITY_REVISION
Definition: hubdrom.cpp:37
#define DROM_IDENTITY_PRODUCT
Definition: hubdrom.cpp:35
static VOID NTAPI HubMailboxTransfer(_In_ HubFdo *Hub, _In_ BOOLEAN Write, _In_ USHORT Register)
Definition: hubdrom.cpp:75
#define DROM_ENTRY_HEADER
Definition: hubdrom.cpp:28
#define DROM_IDENTITY_BCD
Definition: hubdrom.cpp:36
@ TransferFailed
#define HUB_TAG_HUB
Definition: hubutil.h:12
Config Register
Definition: hubwmi.cpp:126
_In_ PIRP _In_ PIO_COMPLETION_ROUTINE _In_ PVOID Context
Definition: kse.h:81
if(dx< 0)
Definition: linetemp.h:194
_In_ UINT Bytes
Definition: mmcopy.h:9
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
static PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
#define _In_reads_bytes_(s)
Definition: no_sal2.h:170
#define _In_
Definition: no_sal2.h:158
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
unsigned short USHORT
Definition: pedump.c:61
#define DPRINT
Definition: sndvol32.h:73
NTSTATUS Send(_In_ WDFIOTARGET Target, _In_opt_ UCXUSBDEVICE Device, _In_ PFN_WDF_REQUEST_COMPLETION_ROUTINE Completion, _In_ WDFCONTEXT Context, _In_reads_bytes_opt_(Length) PVOID Buffer, _In_ ULONG Length, _In_ BOOLEAN ShortTransferOk, _In_ BOOLEAN ForwardProgress)
Definition: hubreq.cpp:62
VOID SetSetup(_In_ UCHAR RequestType, _In_ UCHAR RequestCode, _In_ USHORT Value, _In_ USHORT Index, _In_ USHORT Length)
Definition: hubreq.h:34
struct _URB_CONTROL_TRANSFER_EX Urb
Definition: hubreq.h:21
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char UCHAR
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFREQUEST Request
static BOOL Write(PBYTE Address, PBYTE Data, SIZE_T Size)
Definition: vmhorizon.c:15
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_In_ WDFIOTARGET Target
Definition: wdfrequest.h:306
_In_ WDFIOTARGET _In_ PWDF_REQUEST_COMPLETION_PARAMS Params
Definition: wdfrequest.h:308
#define NT_ASSERT
Definition: rtlfuncs.h:3334