sanity check: avoid infinitely nested hubs

git-svn-id: svn://kolibrios.org@4302 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
CleverMouse 2013-11-27 14:47:05 +00:00
parent ea362458cb
commit 10242c9784

View File

@ -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