forked from KolibriOS/kolibrios
sanity check: avoid infinitely nested hubs
git-svn-id: svn://kolibrios.org@4302 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
ea362458cb
commit
10242c9784
@ -219,30 +219,46 @@ virtual at esp
|
|||||||
.config dd ? ; pointer to usb_config_descr
|
.config dd ? ; pointer to usb_config_descr
|
||||||
.interface dd ? ; pointer to usb_interface_descr
|
.interface dd ? ; pointer to usb_interface_descr
|
||||||
end virtual
|
end virtual
|
||||||
|
; 1. Check that the maximal nesting is not exceeded:
|
||||||
|
; 5 non-root hubs is the maximum according to the spec.
|
||||||
|
mov ebx, [.pipe]
|
||||||
|
movi ecx, 5
|
||||||
|
mov eax, ebx
|
||||||
|
.count_parents:
|
||||||
|
mov eax, [eax+usb_pipe.DeviceData]
|
||||||
|
mov eax, [eax+usb_device_data.Hub]
|
||||||
|
test eax, eax
|
||||||
|
jz .depth_ok
|
||||||
|
mov eax, [eax+usb_hub.ConfigPipe]
|
||||||
|
dec ecx
|
||||||
|
jnz .count_parents
|
||||||
|
dbgstr 'Hub chain is too long'
|
||||||
|
jmp .return0
|
||||||
|
.depth_ok:
|
||||||
; Hubs use one IN interrupt endpoint for polling the device
|
; Hubs use one IN interrupt endpoint for polling the device
|
||||||
; 1. Locate the descriptor of the interrupt endpoint.
|
; 2. Locate the descriptor of the interrupt endpoint.
|
||||||
; Loop over all descriptors owned by this interface.
|
; Loop over all descriptors owned by this interface.
|
||||||
.lookep:
|
.lookep:
|
||||||
; 1a. Skip the current descriptor.
|
; 2a. Skip the current descriptor.
|
||||||
movzx eax, [edx+usb_descr.bLength]
|
movzx eax, [edx+usb_descr.bLength]
|
||||||
add edx, eax
|
add edx, eax
|
||||||
sub ecx, eax
|
sub ecx, eax
|
||||||
jb .errorep
|
jb .errorep
|
||||||
; 1b. Length of data left must be at least sizeof.usb_endpoint_descr.
|
; 2b. Length of data left must be at least sizeof.usb_endpoint_descr.
|
||||||
cmp ecx, sizeof.usb_endpoint_descr
|
cmp ecx, sizeof.usb_endpoint_descr
|
||||||
jb .errorep
|
jb .errorep
|
||||||
; 1c. If we have found another interface descriptor but not found our endpoint,
|
; 2c. If we have found another interface descriptor but not found our endpoint,
|
||||||
; this is an error: all subsequent descriptors belong to that interface
|
; this is an error: all subsequent descriptors belong to that interface
|
||||||
; (or further interfaces).
|
; (or further interfaces).
|
||||||
cmp [edx+usb_endpoint_descr.bDescriptorType], USB_INTERFACE_DESCR
|
cmp [edx+usb_endpoint_descr.bDescriptorType], USB_INTERFACE_DESCR
|
||||||
jz .errorep
|
jz .errorep
|
||||||
; 1d. Ignore all interface-related descriptors except endpoint descriptor.
|
; 2d. Ignore all interface-related descriptors except endpoint descriptor.
|
||||||
cmp [edx+usb_endpoint_descr.bDescriptorType], USB_ENDPOINT_DESCR
|
cmp [edx+usb_endpoint_descr.bDescriptorType], USB_ENDPOINT_DESCR
|
||||||
jnz .lookep
|
jnz .lookep
|
||||||
; 1e. Length of endpoint descriptor must be at least sizeof.usb_endpoint_descr.
|
; 2e. Length of endpoint descriptor must be at least sizeof.usb_endpoint_descr.
|
||||||
cmp [edx+usb_endpoint_descr.bLength], sizeof.usb_endpoint_descr
|
cmp [edx+usb_endpoint_descr.bLength], sizeof.usb_endpoint_descr
|
||||||
jb .errorep
|
jb .errorep
|
||||||
; 1f. Ignore all endpoints except for INTERRUPT IN.
|
; 2f. Ignore all endpoints except for INTERRUPT IN.
|
||||||
cmp [edx+usb_endpoint_descr.bEndpointAddress], 0
|
cmp [edx+usb_endpoint_descr.bEndpointAddress], 0
|
||||||
jge .lookep
|
jge .lookep
|
||||||
mov al, [edx+usb_endpoint_descr.bmAttributes]
|
mov al, [edx+usb_endpoint_descr.bmAttributes]
|
||||||
@ -251,23 +267,22 @@ end virtual
|
|||||||
jnz .lookep
|
jnz .lookep
|
||||||
; We have located the descriptor for INTERRUPT IN endpoint,
|
; We have located the descriptor for INTERRUPT IN endpoint,
|
||||||
; the pointer is in edx.
|
; the pointer is in edx.
|
||||||
; 2. Allocate memory for the hub descriptor.
|
; 3. Allocate memory for the hub descriptor.
|
||||||
; Maximum length (assuming 255 downstream ports) is 40 bytes.
|
; Maximum length (assuming 255 downstream ports) is 40 bytes.
|
||||||
; Allocate 4 extra bytes to keep wMaxPacketSize.
|
; Allocate 4 extra bytes to keep wMaxPacketSize.
|
||||||
; 2a. Save registers.
|
; 3a. Save registers.
|
||||||
push edx
|
push edx
|
||||||
; 2b. Call the allocator.
|
; 3b. Call the allocator.
|
||||||
movi eax, 44
|
movi eax, 44
|
||||||
call malloc
|
call malloc
|
||||||
; 2c. Restore registers.
|
; 3c. Restore registers.
|
||||||
pop ecx
|
pop ecx
|
||||||
; 2d. If failed, say something to the debug board and return error.
|
; 3d. If failed, say something to the debug board and return error.
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .nomemory
|
jz .nomemory
|
||||||
; 2e. Store the pointer in esi. xchg eax,r32 is one byte shorter than mov.
|
; 3e. Store the pointer in esi. xchg eax,r32 is one byte shorter than mov.
|
||||||
xchg esi, eax
|
xchg esi, eax
|
||||||
; 3. Open a pipe for the status endpoint with descriptor found in step 1.
|
; 4. Open a pipe for the status endpoint with descriptor found in step 1.
|
||||||
mov ebx, [.pipe]
|
|
||||||
movzx eax, [ecx+usb_endpoint_descr.bEndpointAddress]
|
movzx eax, [ecx+usb_endpoint_descr.bEndpointAddress]
|
||||||
movzx edx, [ecx+usb_endpoint_descr.bInterval]
|
movzx edx, [ecx+usb_endpoint_descr.bInterval]
|
||||||
movzx ecx, [ecx+usb_endpoint_descr.wMaxPacketSize]
|
movzx ecx, [ecx+usb_endpoint_descr.wMaxPacketSize]
|
||||||
@ -276,11 +291,11 @@ end virtual
|
|||||||
push ecx
|
push ecx
|
||||||
stdcall usb_open_pipe, ebx, eax, ecx, INTERRUPT_PIPE, edx
|
stdcall usb_open_pipe, ebx, eax, ecx, INTERRUPT_PIPE, edx
|
||||||
pop ecx
|
pop ecx
|
||||||
; If failed, free the memory allocated in step 2,
|
; If failed, free the memory allocated in step 3,
|
||||||
; say something to the debug board and return error.
|
; say something to the debug board and return error.
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .free
|
jz .free
|
||||||
; 4. Send control query for the hub descriptor,
|
; 5. Send control query for the hub descriptor,
|
||||||
; pass status pipe as a callback parameter,
|
; pass status pipe as a callback parameter,
|
||||||
; allow short packets.
|
; allow short packets.
|
||||||
and ecx, (1 shl 11) - 1
|
and ecx, (1 shl 11) - 1
|
||||||
@ -291,7 +306,7 @@ end virtual
|
|||||||
(USB_HUB_DESCRIPTOR shl 24)
|
(USB_HUB_DESCRIPTOR shl 24)
|
||||||
mov dword [esi+4], 40 shl 16
|
mov dword [esi+4], 40 shl 16
|
||||||
stdcall usb_control_async, ebx, esi, esi, 40, usb_hub_got_config, eax, 1
|
stdcall usb_control_async, ebx, esi, esi, 40, usb_hub_got_config, eax, 1
|
||||||
; 5. If failed, free the memory allocated in step 2,
|
; 6. If failed, free the memory allocated in step 3,
|
||||||
; say something to the debug board and return error.
|
; say something to the debug board and return error.
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .free
|
jz .free
|
||||||
|
Loading…
Reference in New Issue
Block a user