1 // SPDX-License-Identifier: GPL-2.0+
3 * f_sdp.c -- USB HID Serial Download Protocol
5 * Copyright (C) 2017 Toradex
6 * Author: Stefan Agner <stefan.agner@toradex.com>
8 * This file implements the Serial Download Protocol (SDP) as specified in
9 * the i.MX 6 Reference Manual. The SDP is a USB HID based protocol and
10 * allows to download images directly to memory. The implementation
11 * works with the imx_loader (imx_usb) USB client software on host side.
13 * Not all commands are implemented, e.g. WRITE_REGISTER, DCD_WRITE and
14 * SKIP_DCD_HEADER are only stubs.
16 * Parts of the implementation are based on f_dfu and f_thor.
26 #include <linux/usb/ch9.h>
27 #include <linux/usb/gadget.h>
28 #include <linux/usb/composite.h>
38 #define HID_REPORT_ID_MASK 0x000000ff
43 #define HID_REQ_GET_REPORT 0x01
44 #define HID_REQ_GET_IDLE 0x02
45 #define HID_REQ_GET_PROTOCOL 0x03
46 #define HID_REQ_SET_REPORT 0x09
47 #define HID_REQ_SET_IDLE 0x0A
48 #define HID_REQ_SET_PROTOCOL 0x0B
50 #define HID_USAGE_PAGE_LEN 76
53 u8 usage_page
[HID_USAGE_PAGE_LEN
];
56 #define SDP_READ_REGISTER 0x0101
57 #define SDP_WRITE_REGISTER 0x0202
58 #define SDP_WRITE_FILE 0x0404
59 #define SDP_ERROR_STATUS 0x0505
60 #define SDP_DCD_WRITE 0x0a0a
61 #define SDP_JUMP_ADDRESS 0x0b0b
62 #define SDP_SKIP_DCD_HEADER 0x0c0c
64 #define SDP_SECURITY_CLOSED 0x12343412
65 #define SDP_SECURITY_OPEN 0x56787856
67 #define SDP_WRITE_FILE_COMPLETE 0x88888888
68 #define SDP_WRITE_REGISTER_COMPLETE 0x128A8A12
69 #define SDP_SKIP_DCD_HEADER_COMPLETE 0x900DD009
70 #define SDP_ERROR_IMXHEADER 0x000a0533
72 #define SDP_COMMAND_LEN 16
74 #define SDP_HID_PACKET_SIZE_EP1 1024
90 SDP_STATE_RX_DCD_DATA
,
91 SDP_STATE_RX_FILE_DATA
,
92 SDP_STATE_RX_FILE_DATA_BUSY
,
93 SDP_STATE_TX_SEC_CONF
,
94 SDP_STATE_TX_SEC_CONF_BUSY
,
95 SDP_STATE_TX_REGISTER
,
96 SDP_STATE_TX_REGISTER_BUSY
,
98 SDP_STATE_TX_STATUS_BUSY
,
103 struct usb_function usb_function
;
105 struct usb_descriptor_header
**function
;
108 enum sdp_state state
;
109 enum sdp_state next_state
;
112 u32 dnl_bytes_remaining
;
114 bool always_send_status
;
118 struct usb_request
*req
;
121 struct usb_ep
*in_ep
;
122 struct usb_request
*in_req
;
124 struct usb_ep
*out_ep
;
125 struct usb_request
*out_req
;
127 bool configuration_done
;
131 static struct f_sdp
*sdp_func
;
133 static inline struct f_sdp
*func_to_sdp(struct usb_function
*f
)
135 return container_of(f
, struct f_sdp
, usb_function
);
138 static struct usb_interface_descriptor sdp_intf_runtime
= {
139 .bLength
= sizeof(sdp_intf_runtime
),
140 .bDescriptorType
= USB_DT_INTERFACE
,
141 .bAlternateSetting
= 0,
143 .bInterfaceClass
= USB_CLASS_HID
,
144 .bInterfaceSubClass
= 0,
145 .bInterfaceProtocol
= 0,
146 /* .iInterface = DYNAMIC */
149 /* HID configuration */
150 static struct usb_class_hid_descriptor sdp_hid_desc
= {
151 .bLength
= sizeof(sdp_hid_desc
),
152 .bDescriptorType
= USB_DT_CS_DEVICE
,
154 .bcdCDC
= __constant_cpu_to_le16(0x0110),
156 .bNumDescriptors
= 1,
158 .bDescriptorType0
= USB_DT_HID_REPORT
,
159 .wDescriptorLength0
= HID_USAGE_PAGE_LEN
,
162 static struct usb_endpoint_descriptor in_desc
= {
163 .bLength
= USB_DT_ENDPOINT_SIZE
,
164 .bDescriptorType
= USB_DT_ENDPOINT
, /*USB_DT_CS_ENDPOINT*/
166 .bEndpointAddress
= 1 | USB_DIR_IN
,
167 .bmAttributes
= USB_ENDPOINT_XFER_INT
,
168 .wMaxPacketSize
= 64,
172 static struct usb_endpoint_descriptor out_desc
= {
173 .bLength
= USB_DT_ENDPOINT_SIZE
,
174 .bDescriptorType
= USB_DT_ENDPOINT
, /*USB_DT_CS_ENDPOINT*/
176 .bEndpointAddress
= 1 | USB_DIR_OUT
,
177 .bmAttributes
= USB_ENDPOINT_XFER_INT
,
178 .wMaxPacketSize
= 64,
182 static struct usb_endpoint_descriptor in_hs_desc
= {
183 .bLength
= USB_DT_ENDPOINT_SIZE
,
184 .bDescriptorType
= USB_DT_ENDPOINT
, /*USB_DT_CS_ENDPOINT*/
186 .bEndpointAddress
= 1 | USB_DIR_IN
,
187 .bmAttributes
= USB_ENDPOINT_XFER_INT
,
188 .wMaxPacketSize
= 512,
192 static struct usb_endpoint_descriptor out_hs_desc
= {
193 .bLength
= USB_DT_ENDPOINT_SIZE
,
194 .bDescriptorType
= USB_DT_ENDPOINT
, /*USB_DT_CS_ENDPOINT*/
196 .bEndpointAddress
= 1 | USB_DIR_OUT
,
197 .bmAttributes
= USB_ENDPOINT_XFER_INT
,
198 .wMaxPacketSize
= SDP_HID_PACKET_SIZE_EP1
,
202 static struct usb_descriptor_header
*sdp_runtime_descs
[] = {
203 (struct usb_descriptor_header
*)&sdp_intf_runtime
,
204 (struct usb_descriptor_header
*)&sdp_hid_desc
,
205 (struct usb_descriptor_header
*)&in_desc
,
206 (struct usb_descriptor_header
*)&out_desc
,
210 static struct usb_descriptor_header
*sdp_runtime_hs_descs
[] = {
211 (struct usb_descriptor_header
*)&sdp_intf_runtime
,
212 (struct usb_descriptor_header
*)&sdp_hid_desc
,
213 (struct usb_descriptor_header
*)&in_hs_desc
,
214 (struct usb_descriptor_header
*)&out_hs_desc
,
218 /* This is synchronized with what the SoC implementation reports */
219 static struct hid_report sdp_hid_report
= {
221 0x06, 0x00, 0xff, /* Usage Page */
222 0x09, 0x01, /* Usage (Pointer?) */
223 0xa1, 0x01, /* Collection */
225 0x85, 0x01, /* Report ID */
226 0x19, 0x01, /* Usage Minimum */
227 0x29, 0x01, /* Usage Maximum */
228 0x15, 0x00, /* Local Minimum */
229 0x26, 0xFF, 0x00, /* Local Maximum? */
230 0x75, 0x08, /* Report Size */
231 0x95, 0x10, /* Report Count */
232 0x91, 0x02, /* Output Data */
234 0x85, 0x02, /* Report ID */
235 0x19, 0x01, /* Usage Minimum */
236 0x29, 0x01, /* Usage Maximum */
237 0x15, 0x00, /* Local Minimum */
238 0x26, 0xFF, 0x00, /* Local Maximum? */
239 0x75, 0x80, /* Report Size 128 */
240 0x95, 0x40, /* Report Count */
241 0x91, 0x02, /* Output Data */
243 0x85, 0x03, /* Report ID */
244 0x19, 0x01, /* Usage Minimum */
245 0x29, 0x01, /* Usage Maximum */
246 0x15, 0x00, /* Local Minimum */
247 0x26, 0xFF, 0x00, /* Local Maximum? */
248 0x75, 0x08, /* Report Size 8 */
249 0x95, 0x04, /* Report Count */
250 0x81, 0x02, /* Input Data */
252 0x85, 0x04, /* Report ID */
253 0x19, 0x01, /* Usage Minimum */
254 0x29, 0x01, /* Usage Maximum */
255 0x15, 0x00, /* Local Minimum */
256 0x26, 0xFF, 0x00, /* Local Maximum? */
257 0x75, 0x08, /* Report Size 8 */
258 0x95, 0x40, /* Report Count */
259 0x81, 0x02, /* Input Data */
264 static const char sdp_name
[] = "Serial Downloader Protocol";
267 * static strings, in UTF-8
269 static struct usb_string strings_sdp_generic
[] = {
271 { } /* end of list */
274 static struct usb_gadget_strings stringtab_sdp_generic
= {
275 .language
= 0x0409, /* en-us */
276 .strings
= strings_sdp_generic
,
279 static struct usb_gadget_strings
*sdp_generic_strings
[] = {
280 &stringtab_sdp_generic
,
284 static inline void *sdp_ptr(u32 val
)
286 return (void *)(uintptr_t)val
;
289 static void sdp_rx_command_complete(struct usb_ep
*ep
, struct usb_request
*req
)
291 struct f_sdp
*sdp
= req
->context
;
292 int status
= req
->status
;
297 pr_err("Status: %d\n", status
);
302 pr_err("Unexpected report %d\n", report
);
306 struct sdp_command
*cmd
= req
->buf
+ 1;
308 debug("%s: command: %04x, addr: %08x, cnt: %u\n",
309 __func__
, be16_to_cpu(cmd
->cmd
),
310 be32_to_cpu(cmd
->addr
), be32_to_cpu(cmd
->cnt
));
312 switch (be16_to_cpu(cmd
->cmd
)) {
313 case SDP_READ_REGISTER
:
314 sdp
->always_send_status
= false;
315 sdp
->error_status
= 0x0;
317 sdp
->state
= SDP_STATE_TX_SEC_CONF
;
318 sdp
->dnl_address
= be32_to_cpu(cmd
->addr
);
319 sdp
->dnl_bytes_remaining
= be32_to_cpu(cmd
->cnt
);
320 sdp
->next_state
= SDP_STATE_TX_REGISTER
;
321 printf("Reading %d registers at 0x%08x... ",
322 sdp
->dnl_bytes_remaining
, sdp
->dnl_address
);
325 sdp
->always_send_status
= true;
326 sdp
->error_status
= SDP_WRITE_FILE_COMPLETE
;
328 sdp
->state
= SDP_STATE_RX_FILE_DATA
;
329 sdp
->dnl_address
= cmd
->addr
? be32_to_cpu(cmd
->addr
) : CONFIG_SDP_LOADADDR
;
330 sdp
->dnl_bytes_remaining
= be32_to_cpu(cmd
->cnt
);
331 sdp
->dnl_bytes
= sdp
->dnl_bytes_remaining
;
332 sdp
->next_state
= SDP_STATE_IDLE
;
334 printf("Downloading file of size %d to 0x%08x... ",
335 sdp
->dnl_bytes_remaining
, sdp
->dnl_address
);
338 case SDP_ERROR_STATUS
:
339 sdp
->always_send_status
= true;
340 sdp
->error_status
= 0;
342 sdp
->state
= SDP_STATE_TX_SEC_CONF
;
343 sdp
->next_state
= SDP_STATE_IDLE
;
346 sdp
->always_send_status
= true;
347 sdp
->error_status
= SDP_WRITE_REGISTER_COMPLETE
;
349 sdp
->state
= SDP_STATE_RX_DCD_DATA
;
350 sdp
->dnl_bytes_remaining
= be32_to_cpu(cmd
->cnt
);
351 sdp
->next_state
= SDP_STATE_IDLE
;
353 case SDP_JUMP_ADDRESS
:
354 sdp
->always_send_status
= false;
355 sdp
->error_status
= 0;
357 sdp
->jmp_address
= cmd
->addr
? be32_to_cpu(cmd
->addr
) : CONFIG_SDP_LOADADDR
;
358 sdp
->state
= SDP_STATE_TX_SEC_CONF
;
359 sdp
->next_state
= SDP_STATE_JUMP
;
361 case SDP_SKIP_DCD_HEADER
:
362 sdp
->always_send_status
= true;
363 sdp
->error_status
= SDP_SKIP_DCD_HEADER_COMPLETE
;
365 /* Ignore command, DCD not supported anyway */
366 sdp
->state
= SDP_STATE_TX_SEC_CONF
;
367 sdp
->next_state
= SDP_STATE_IDLE
;
370 pr_err("Unknown command: %04x\n", be16_to_cpu(cmd
->cmd
));
374 static void sdp_rx_data_complete(struct usb_ep
*ep
, struct usb_request
*req
)
376 struct f_sdp
*sdp
= req
->context
;
377 int status
= req
->status
;
380 int datalen
= req
->actual
- 1;
383 pr_err("Status: %d\n", status
);
388 pr_err("Unexpected report %d\n", report
);
392 if (sdp
->dnl_bytes_remaining
< datalen
) {
394 * Some USB stacks require to send a complete buffer as
395 * specified in the HID descriptor. This leads to longer
396 * transfers than the file length, no problem for us.
398 sdp
->dnl_bytes_remaining
= 0;
400 sdp
->dnl_bytes_remaining
-= datalen
;
403 if (sdp
->state
== SDP_STATE_RX_FILE_DATA_BUSY
) {
404 memcpy(sdp_ptr(sdp
->dnl_address
), req
->buf
+ 1, datalen
);
405 sdp
->dnl_address
+= datalen
;
408 if (sdp
->dnl_bytes_remaining
) {
409 sdp
->state
= SDP_STATE_RX_FILE_DATA
;
413 #ifndef CONFIG_SPL_BUILD
414 env_set_hex("filesize", sdp
->dnl_bytes
);
418 switch (sdp
->state
) {
419 case SDP_STATE_RX_FILE_DATA_BUSY
:
420 sdp
->state
= SDP_STATE_TX_SEC_CONF
;
422 case SDP_STATE_RX_DCD_DATA
:
423 sdp
->state
= SDP_STATE_TX_SEC_CONF
;
426 pr_err("Invalid state: %d\n", sdp
->state
);
430 static void sdp_tx_complete(struct usb_ep
*ep
, struct usb_request
*req
)
432 struct f_sdp
*sdp
= req
->context
;
433 int status
= req
->status
;
436 pr_err("Status: %d\n", status
);
440 switch (sdp
->state
) {
441 case SDP_STATE_TX_SEC_CONF_BUSY
:
442 /* Not all commands require status report */
443 if (sdp
->always_send_status
|| sdp
->error_status
)
444 sdp
->state
= SDP_STATE_TX_STATUS
;
446 sdp
->state
= sdp
->next_state
;
449 case SDP_STATE_TX_STATUS_BUSY
:
450 sdp
->state
= sdp
->next_state
;
452 case SDP_STATE_TX_REGISTER_BUSY
:
453 if (sdp
->dnl_bytes_remaining
)
454 sdp
->state
= SDP_STATE_TX_REGISTER
;
456 sdp
->state
= SDP_STATE_IDLE
;
459 pr_err("Wrong State: %d\n", sdp
->state
);
460 sdp
->state
= SDP_STATE_IDLE
;
463 debug("%s complete --> %d, %d/%d\n", ep
->name
,
464 status
, req
->actual
, req
->length
);
467 static int sdp_setup(struct usb_function
*f
, const struct usb_ctrlrequest
*ctrl
)
469 struct usb_gadget
*gadget
= f
->config
->cdev
->gadget
;
470 struct usb_request
*req
= f
->config
->cdev
->req
;
471 struct f_sdp
*sdp
= f
->config
->cdev
->req
->context
;
472 u16 len
= le16_to_cpu(ctrl
->wLength
);
473 u16 w_value
= le16_to_cpu(ctrl
->wValue
);
475 u8 req_type
= ctrl
->bRequestType
& USB_TYPE_MASK
;
477 debug("w_value: 0x%04x len: 0x%04x\n", w_value
, len
);
478 debug("req_type: 0x%02x ctrl->bRequest: 0x%02x sdp->state: %d\n",
479 req_type
, ctrl
->bRequest
, sdp
->state
);
481 if (req_type
== USB_TYPE_STANDARD
) {
482 if (ctrl
->bRequest
== USB_REQ_GET_DESCRIPTOR
) {
483 /* Send HID report descriptor */
484 value
= min(len
, (u16
) sizeof(sdp_hid_report
));
485 memcpy(req
->buf
, &sdp_hid_report
, value
);
486 sdp
->configuration_done
= true;
490 if (req_type
== USB_TYPE_CLASS
) {
491 int report
= w_value
& HID_REPORT_ID_MASK
;
493 /* HID (SDP) request */
494 switch (ctrl
->bRequest
) {
495 case HID_REQ_SET_REPORT
:
498 value
= SDP_COMMAND_LEN
+ 1;
499 req
->complete
= sdp_rx_command_complete
;
500 sdp_func
->ep_int_enable
= false;
504 req
->complete
= sdp_rx_data_complete
;
505 sdp_func
->state
= SDP_STATE_RX_FILE_DATA_BUSY
;
513 req
->zero
= value
< len
;
514 value
= usb_ep_queue(gadget
->ep0
, req
, 0);
516 debug("ep_queue --> %d\n", value
);
524 static int sdp_bind(struct usb_configuration
*c
, struct usb_function
*f
)
526 struct usb_gadget
*gadget
= c
->cdev
->gadget
;
527 struct usb_composite_dev
*cdev
= c
->cdev
;
528 struct f_sdp
*sdp
= func_to_sdp(f
);
531 id
= usb_interface_id(c
, f
);
534 sdp_intf_runtime
.bInterfaceNumber
= id
;
536 struct usb_ep
*ep_in
, *ep_out
;
538 /* allocate instance-specific endpoints */
539 ep_in
= usb_ep_autoconfig(gadget
, &in_desc
);
545 ep_out
= usb_ep_autoconfig(gadget
, &out_desc
);
551 if (gadget_is_dualspeed(gadget
)) {
552 /* Assume endpoint addresses are the same for both speeds */
553 in_hs_desc
.bEndpointAddress
= in_desc
.bEndpointAddress
;
554 out_hs_desc
.bEndpointAddress
= out_desc
.bEndpointAddress
;
557 sdp
->in_ep
= ep_in
; /* Store IN EP for enabling @ setup */
558 sdp
->out_ep
= ep_out
;
560 cdev
->req
->context
= sdp
;
566 static void sdp_unbind(struct usb_configuration
*c
, struct usb_function
*f
)
572 static struct usb_request
*alloc_ep_req(struct usb_ep
*ep
, unsigned length
)
574 struct usb_request
*req
;
576 req
= usb_ep_alloc_request(ep
, 0);
580 req
->length
= length
;
581 req
->buf
= memalign(CONFIG_SYS_CACHELINE_SIZE
, length
);
583 usb_ep_free_request(ep
, req
);
591 static struct usb_request
*sdp_start_ep(struct usb_ep
*ep
, bool in
)
593 struct usb_request
*req
;
596 req
= alloc_ep_req(ep
, 65);
598 req
= alloc_ep_req(ep
, 2048);
600 * OUT endpoint request length should be an integral multiple of
601 * maxpacket size 1024, else we break on certain controllers like
602 * DWC3 that expect bulk OUT requests to be divisible by maxpacket size.
604 debug("%s: ep:%p req:%p\n", __func__
, ep
, req
);
609 memset(req
->buf
, 0, req
->length
);
611 req
->complete
= sdp_tx_complete
;
613 req
->complete
= sdp_rx_command_complete
;
617 static int sdp_set_alt(struct usb_function
*f
, unsigned intf
, unsigned alt
)
619 struct f_sdp
*sdp
= func_to_sdp(f
);
620 struct usb_composite_dev
*cdev
= f
->config
->cdev
;
621 struct usb_gadget
*gadget
= cdev
->gadget
;
624 debug("%s: intf: %d alt: %d\n", __func__
, intf
, alt
);
626 if (gadget_is_dualspeed(gadget
) && gadget
->speed
== USB_SPEED_HIGH
) {
627 result
= usb_ep_enable(sdp
->in_ep
, &in_hs_desc
);
628 result
|= usb_ep_enable(sdp
->out_ep
, &out_hs_desc
);
630 result
= usb_ep_enable(sdp
->in_ep
, &in_desc
);
631 result
|= usb_ep_enable(sdp
->out_ep
, &out_desc
);
636 sdp
->in_req
= sdp_start_ep(sdp
->in_ep
, true);
637 sdp
->in_req
->context
= sdp
;
638 sdp
->out_req
= sdp_start_ep(sdp
->out_ep
, false);
639 sdp
->out_req
->context
= sdp
;
641 sdp
->in_ep
->driver_data
= cdev
; /* claim */
642 sdp
->out_ep
->driver_data
= cdev
; /* claim */
644 sdp
->altsetting
= alt
;
645 sdp
->state
= SDP_STATE_IDLE
;
646 sdp
->ep_int_enable
= true;
651 static int sdp_get_alt(struct usb_function
*f
, unsigned intf
)
653 struct f_sdp
*sdp
= func_to_sdp(f
);
655 return sdp
->altsetting
;
658 static void sdp_disable(struct usb_function
*f
)
660 struct f_sdp
*sdp
= func_to_sdp(f
);
662 usb_ep_disable(sdp
->in_ep
);
663 usb_ep_disable(sdp
->out_ep
);
666 free(sdp
->in_req
->buf
);
667 usb_ep_free_request(sdp
->in_ep
, sdp
->in_req
);
671 free(sdp
->out_req
->buf
);
672 usb_ep_free_request(sdp
->out_ep
, sdp
->out_req
);
677 static int sdp_bind_config(struct usb_configuration
*c
)
682 sdp_func
= memalign(CONFIG_SYS_CACHELINE_SIZE
, sizeof(*sdp_func
));
687 memset(sdp_func
, 0, sizeof(*sdp_func
));
689 sdp_func
->usb_function
.name
= "sdp";
690 sdp_func
->usb_function
.hs_descriptors
= sdp_runtime_hs_descs
;
691 sdp_func
->usb_function
.descriptors
= sdp_runtime_descs
;
692 sdp_func
->usb_function
.bind
= sdp_bind
;
693 sdp_func
->usb_function
.unbind
= sdp_unbind
;
694 sdp_func
->usb_function
.set_alt
= sdp_set_alt
;
695 sdp_func
->usb_function
.get_alt
= sdp_get_alt
;
696 sdp_func
->usb_function
.disable
= sdp_disable
;
697 sdp_func
->usb_function
.strings
= sdp_generic_strings
;
698 sdp_func
->usb_function
.setup
= sdp_setup
;
700 status
= usb_add_function(c
, &sdp_func
->usb_function
);
705 int sdp_init(struct udevice
*udc
)
707 printf("SDP: initialize...\n");
708 while (!sdp_func
->configuration_done
) {
710 puts("\rCTRL+C - Operation aborted.\n");
715 dm_usb_gadget_handle_interrupts(udc
);
721 static u32
sdp_jump_imxheader(void *address
)
723 flash_header_v2_t
*headerv2
= address
;
724 ulong (*entry
)(void);
726 if (headerv2
->header
.tag
!= IVT_HEADER_TAG
) {
727 printf("Header Tag is not an IMX image\n");
728 return SDP_ERROR_IMXHEADER
;
731 printf("Jumping to 0x%08x\n", headerv2
->entry
);
732 entry
= sdp_ptr(headerv2
->entry
);
735 /* The image probably never returns hence we won't reach that point */
739 #ifdef CONFIG_SPL_BUILD
740 static ulong
sdp_load_read(struct spl_load_info
*load
, ulong sector
,
741 ulong count
, void *buf
)
743 debug("%s: sector %lx, count %lx, buf %lx\n",
744 __func__
, sector
, count
, (ulong
)buf
);
745 memcpy(buf
, (void *)(load
->dev
+ sector
), count
);
749 static ulong
search_fit_header(ulong p
, int size
)
753 for (i
= 0; i
< size
; i
+= 4) {
754 if (genimg_get_format((const void *)(p
+ i
)) == IMAGE_FORMAT_FIT
)
761 static ulong
search_container_header(ulong p
, int size
)
766 for (i
= 0; i
< size
; i
+= 4) {
768 if (*(hdr
+ 3) == 0x87 && *hdr
== 0)
769 if (*(hdr
+ 1) != 0 || *(hdr
+ 2) != 0)
776 static int sdp_handle_in_ep(struct spl_image_info
*spl_image
,
777 struct spl_boot_device
*bootdev
)
779 u8
*data
= sdp_func
->in_req
->buf
;
783 switch (sdp_func
->state
) {
784 case SDP_STATE_TX_SEC_CONF
:
785 debug("Report 3: HAB security\n");
788 status
= SDP_SECURITY_OPEN
;
789 memcpy(&data
[1], &status
, 4);
790 sdp_func
->in_req
->length
= 5;
791 usb_ep_queue(sdp_func
->in_ep
, sdp_func
->in_req
, 0);
792 sdp_func
->state
= SDP_STATE_TX_SEC_CONF_BUSY
;
795 case SDP_STATE_TX_STATUS
:
796 debug("Report 4: Status\n");
799 memcpy(&data
[1], &sdp_func
->error_status
, 4);
800 sdp_func
->in_req
->length
= 65;
801 usb_ep_queue(sdp_func
->in_ep
, sdp_func
->in_req
, 0);
802 sdp_func
->state
= SDP_STATE_TX_STATUS_BUSY
;
804 case SDP_STATE_TX_REGISTER
:
805 debug("Report 4: Register Values\n");
808 datalen
= sdp_func
->dnl_bytes_remaining
;
813 memcpy(&data
[1], sdp_ptr(sdp_func
->dnl_address
), datalen
);
814 sdp_func
->in_req
->length
= 65;
816 sdp_func
->dnl_bytes_remaining
-= datalen
;
817 sdp_func
->dnl_address
+= datalen
;
819 usb_ep_queue(sdp_func
->in_ep
, sdp_func
->in_req
, 0);
820 sdp_func
->state
= SDP_STATE_TX_REGISTER_BUSY
;
823 printf("Jumping to header at 0x%08x\n", sdp_func
->jmp_address
);
824 status
= sdp_jump_imxheader(sdp_ptr(sdp_func
->jmp_address
));
826 /* If imx header fails, try some U-Boot specific headers */
828 #ifdef CONFIG_SPL_BUILD
829 if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER
))
830 sdp_func
->jmp_address
= (u32
)search_container_header((ulong
)sdp_func
->jmp_address
, sdp_func
->dnl_bytes
);
831 else if (IS_ENABLED(CONFIG_SPL_LOAD_FIT
))
832 sdp_func
->jmp_address
= (u32
)search_fit_header((ulong
)sdp_func
->jmp_address
, sdp_func
->dnl_bytes
);
833 if (sdp_func
->jmp_address
== 0)
834 panic("Error in search header, failed to jump\n");
836 printf("Found header at 0x%08x\n", sdp_func
->jmp_address
);
838 struct legacy_img_hdr
*header
=
839 sdp_ptr(sdp_func
->jmp_address
);
840 #ifdef CONFIG_SPL_LOAD_FIT
841 if (image_get_magic(header
) == FDT_MAGIC
) {
842 struct spl_load_info load
;
844 debug("Found FIT\n");
847 load
.read
= sdp_load_read
;
848 spl_load_simple_fit(spl_image
, &load
, 0,
854 if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER
)) {
855 struct spl_load_info load
;
859 load
.read
= sdp_load_read
;
860 spl_load_imx_container(spl_image
, &load
, 0);
864 /* In SPL, allow jumps to U-Boot images */
865 struct spl_image_info spl_image
= {};
866 struct spl_boot_device bootdev
= {};
867 spl_parse_image_header(&spl_image
, &bootdev
, header
);
868 spl_board_prepare_for_boot();
869 jump_to_image_no_args(&spl_image
);
871 /* In U-Boot, allow jumps to scripts */
872 cmd_source_script(sdp_func
->jmp_address
, NULL
, NULL
);
876 sdp_func
->next_state
= SDP_STATE_IDLE
;
877 sdp_func
->error_status
= status
;
879 /* Only send Report 4 if there was an error */
881 sdp_func
->state
= SDP_STATE_TX_STATUS
;
883 sdp_func
->state
= SDP_STATE_IDLE
;
892 static void sdp_handle_out_ep(void)
896 if (sdp_func
->state
== SDP_STATE_IDLE
) {
897 sdp_func
->out_req
->complete
= sdp_rx_command_complete
;
898 rc
= usb_ep_queue(sdp_func
->out_ep
, sdp_func
->out_req
, 0);
900 printf("error in submission: %s\n",
901 sdp_func
->out_ep
->name
);
902 sdp_func
->state
= SDP_STATE_RX_CMD
;
903 } else if (sdp_func
->state
== SDP_STATE_RX_FILE_DATA
) {
904 sdp_func
->out_req
->complete
= sdp_rx_data_complete
;
905 rc
= usb_ep_queue(sdp_func
->out_ep
, sdp_func
->out_req
, 0);
907 printf("error in submission: %s\n",
908 sdp_func
->out_ep
->name
);
909 sdp_func
->state
= SDP_STATE_RX_FILE_DATA_BUSY
;
913 #ifndef CONFIG_SPL_BUILD
914 int sdp_handle(struct udevice
*udc
)
916 int spl_sdp_handle(struct udevice
*udc
, struct spl_image_info
*spl_image
,
917 struct spl_boot_device
*bootdev
)
921 printf("SDP: handle requests...\n");
924 puts("\rCTRL+C - Operation aborted.\n");
928 if (flag
== SDP_EXIT
)
932 dm_usb_gadget_handle_interrupts(udc
);
934 #ifdef CONFIG_SPL_BUILD
935 flag
= sdp_handle_in_ep(spl_image
, bootdev
);
937 flag
= sdp_handle_in_ep(NULL
, NULL
);
939 if (sdp_func
->ep_int_enable
)
944 int sdp_add(struct usb_configuration
*c
)
948 id
= usb_string_id(c
->cdev
);
951 strings_sdp_generic
[0].id
= id
;
952 sdp_intf_runtime
.iInterface
= id
;
954 debug("%s: cdev: %p gadget: %p gadget->ep0: %p\n", __func__
,
955 c
->cdev
, c
->cdev
->gadget
, c
->cdev
->gadget
->ep0
);
957 return sdp_bind_config(c
);
960 DECLARE_GADGET_BIND_CALLBACK(usb_dnl_sdp
, sdp_add
);