From c6eb899c4d0f8311f8a9d6c991344a27b8f9d4db Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Wed, 20 Apr 2016 10:36:32 +0200 Subject: [PATCH 01/10] tests: py: dfu: Add variables to store dfu alt numbers for test and dummy files This patch replaces hardcoded (i.e. 0 and 1) values passed to dfu_{read|write} with variables. Signed-off-by: Lukasz Majewski Acked-by: Stephen Warren --- Changes for v3: - Replace per module global variables with ones defined inside a function Changes for v2: - None --- test/py/tests/test_dfu.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/py/tests/test_dfu.py b/test/py/tests/test_dfu.py index 093e8d0678..2e6cd7b5b3 100644 --- a/test/py/tests/test_dfu.py +++ b/test/py/tests/test_dfu.py @@ -99,6 +99,10 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config): Nothing. """ + # Default alt settings for test and dummy files + alt_setting_test_file = 0 + alt_setting_dummy_file = 1 + def start_dfu(): """Start U-Boot's dfu shell command. @@ -229,15 +233,15 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config): u_boot_console.log.action('Writing test data to DFU primary ' + 'altsetting') - dfu_write(0, test_f.abs_fn) + dfu_write(alt_setting_test_file, test_f.abs_fn) u_boot_console.log.action('Writing dummy data to DFU secondary ' + 'altsetting to clear DFU buffers') - dfu_write(1, dummy_f.abs_fn) + dfu_write(alt_setting_dummy_file, dummy_f.abs_fn) u_boot_console.log.action('Reading DFU primary altsetting for ' + 'comparison') - dfu_read(0, readback_fn) + dfu_read(alt_setting_test_file, readback_fn) u_boot_console.log.action('Comparing written and read data') written_hash = test_f.content_hash @@ -266,7 +270,7 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config): u_boot_console.log.action( 'Overwriting DFU primary altsetting with dummy data') - dfu_write(0, dummy_f.abs_fn) + dfu_write(alt_setting_test_file, dummy_f.abs_fn) for size in sizes: with u_boot_console.log.section('Data size %d' % size): From 8eb37524468efa6f90dd00862aeaabe934557a5a Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Mon, 18 Apr 2016 17:01:15 +0200 Subject: [PATCH 02/10] tests: py: dfu: Add functionality to set different u-boot's dfu env variable By default (on almost all systems) the dfu env variable, which defines available alt settings, is named as "dfu_alt_info". However on some platforms (i.e. Odroid XU3), the 'dfu_alt_info' is concatenated from other variables - namely 'dfu_alt_boot' and 'dfu_alt_system' at run time (when one types 'dfu 0 mmc 0' for first time). 'dfu_alt_boot' describes alt settings which depend on boot medium - for example boot loader's LBA sectors which are different on eMMC and SD card because of e.g. MBR/GPT. 'dfu_alt_system' describes board agnostic alt settings - like rootfs, kernel. On such system we can only append/modify this env variable. Because of the above, we must have way to modify other than "dfu_ale_info" variable to perform tests. Signed-off-by: Lukasz Majewski Acked-by: Stephen Warren --- Changes for v3: - None Changes for v2: - Rewrite of "alt_info_env_name" variable description - Use of get() method on python's dictionary to easily obtain default value --- test/py/tests/test_dfu.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/test/py/tests/test_dfu.py b/test/py/tests/test_dfu.py index 2e6cd7b5b3..0442af8c84 100644 --- a/test/py/tests/test_dfu.py +++ b/test/py/tests/test_dfu.py @@ -44,6 +44,14 @@ env__dfu_configs = ( # configurations, but don't want to test every single transfer size # on each, to avoid bloating the overall time taken by testing. "test_sizes": (63, 64, 65), + # This value is optional. + # The name of the environment variable that the the dfu command reads + # alt info from. If unspecified, this defaults to dfu_alt_info, which is + # valid for most systems. Some systems use a different variable name. + # One example is the Odroid XU3, which automatically generates + # $dfu_alt_info, each time the dfu command is run, by concatenating + # $dfu_alt_boot and $dfu_alt_system. + "alt_info_env_name": "dfu_alt_system", }, ) @@ -124,7 +132,11 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config): u_boot_console.log.action( 'Starting long-running U-Boot dfu shell command') - cmd = 'setenv dfu_alt_info "%s"' % env__dfu_config['alt_info'] + dfu_alt_info_env = env__dfu_config.get('alt_info_env_name', \ + 'dfu_alt_info') + + cmd = 'setenv "%s" "%s"' % (dfu_alt_info_env, + env__dfu_config['alt_info']) u_boot_console.run_command(cmd) cmd = 'dfu 0 ' + env__dfu_config['cmd_params'] From f3a87f5b79a8f1957753131b09b539027913c731 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Wed, 20 Apr 2016 10:57:08 +0200 Subject: [PATCH 03/10] tests: py: dfu: Provide functionality to set test and dummy files alt settings After concatenation of "dfu_alt_info" variable from "dfu_alt_boot" and "dfu_alt_system" it may happen that test and dummy files alt settings are different than default 0 and 1. This patch provides the ability to set different values for them. Signed-off-by: Lukasz Majewski Acked-by: Stephen Warren --- Changes for v3: - replace variables declarations with ones read from configuration file - remove not necessary str() conversion at DFU host command generation Changes for v2: - generate "alt_info" automatically - use file names as alt settings instead of numerical values - extend in-code documentation --- test/py/tests/test_dfu.py | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/test/py/tests/test_dfu.py b/test/py/tests/test_dfu.py index 0442af8c84..8649d8731b 100644 --- a/test/py/tests/test_dfu.py +++ b/test/py/tests/test_dfu.py @@ -30,6 +30,13 @@ env__usb_dev_ports = ( }, ) +# Optional entries (required only when "alt_id_test_file" and +# "alt_id_dummy_file" are specified). +test_file_name = "/dfu_test.bin" +dummy_file_name = "/dfu_dummy.bin" +# Above files are used to generate proper "alt_info" entry +"alt_info": "/%s ext4 0 2;/%s ext4 0 2" % (test_file_name, dummy_file_name), + env__dfu_configs = ( # eMMC, partition 1 { @@ -52,6 +59,16 @@ env__dfu_configs = ( # $dfu_alt_info, each time the dfu command is run, by concatenating # $dfu_alt_boot and $dfu_alt_system. "alt_info_env_name": "dfu_alt_system", + # This value is optional. + # For boards which require the "test file" alt setting number other than + # default (0) it is possible to specify exact file name to be used as + # this parameter. + "alt_id_test_file": test_file_name, + # This value is optional. + # For boards which require the "dummy file" alt setting number other + # than default (1) it is possible to specify exact file name to be used + # as this parameter. + "alt_id_dummy_file": dummy_file_name, }, ) @@ -107,10 +124,6 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config): Nothing. """ - # Default alt settings for test and dummy files - alt_setting_test_file = 0 - alt_setting_dummy_file = 1 - def start_dfu(): """Start U-Boot's dfu shell command. @@ -188,7 +201,7 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config): Nothing. """ - cmd = ['dfu-util', '-a', str(alt_setting), up_dn_load_arg, fn] + cmd = ['dfu-util', '-a', alt_setting, up_dn_load_arg, fn] if 'host_usb_port_path' in env__usb_dev_port: cmd += ['-p', env__usb_dev_port['host_usb_port_path']] u_boot_utils.run_and_log(u_boot_console, cmd) @@ -276,6 +289,9 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config): dummy_f = u_boot_utils.PersistentRandomFile(u_boot_console, 'dfu_dummy.bin', 1024) + alt_setting_test_file = env__dfu_config.get('alt_id_test_file', '0') + alt_setting_dummy_file = env__dfu_config.get('alt_id_dummy_file', '1') + ignore_cleanup_errors = True try: start_dfu() From 718156ad0ab076f94fbfc5f2628e6b43d1f5a127 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 12 Apr 2016 15:51:48 +0300 Subject: [PATCH 04/10] fastboot: Fix wMaxPacketSize for High-Speed IN endpoint wMaxPacketSize for IN endpoing in High-Speed must be 512 and not 64. While fixing that we do some clean ups like - use cpu_to_le16(decimal_length) instead of hexadecimal length. - No need to initialize bInterval to 0. Static variables are 0 initialized. - Move descriptor setting from fastboot_add to to fastboot_bind. - check for dual speed configuration before setting the high speed descriptors. Signed-off-by: Roger Quadros Tested-by: Steve Rae Tested-by: Steve Rae [Test HW: bcm235xx board] --- drivers/usb/gadget/f_fastboot.c | 36 ++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index 2e87feeece..e1038ead41 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -64,8 +64,7 @@ static struct usb_endpoint_descriptor fs_ep_in = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = TX_ENDPOINT_MAXIMUM_PACKET_SIZE, - .bInterval = 0x00, + .wMaxPacketSize = cpu_to_le16(64), }; static struct usb_endpoint_descriptor fs_ep_out = { @@ -73,8 +72,15 @@ static struct usb_endpoint_descriptor fs_ep_out = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1, - .bInterval = 0x00, + .wMaxPacketSize = cpu_to_le16(64), +}; + +static struct usb_endpoint_descriptor hs_ep_in = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor hs_ep_out = { @@ -82,8 +88,7 @@ static struct usb_endpoint_descriptor hs_ep_out = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0, - .bInterval = 0x00, + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_interface_descriptor interface_desc = { @@ -97,9 +102,15 @@ static struct usb_interface_descriptor interface_desc = { .bInterfaceProtocol = FASTBOOT_INTERFACE_PROTOCOL, }; -static struct usb_descriptor_header *fb_runtime_descs[] = { +static struct usb_descriptor_header *fb_fs_function[] = { (struct usb_descriptor_header *)&interface_desc, (struct usb_descriptor_header *)&fs_ep_in, + (struct usb_descriptor_header *)&fs_ep_out, +}; + +static struct usb_descriptor_header *fb_hs_function[] = { + (struct usb_descriptor_header *)&interface_desc, + (struct usb_descriptor_header *)&hs_ep_in, (struct usb_descriptor_header *)&hs_ep_out, NULL, }; @@ -177,7 +188,15 @@ static int fastboot_bind(struct usb_configuration *c, struct usb_function *f) return -ENODEV; f_fb->out_ep->driver_data = c->cdev; - hs_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress; + f->descriptors = fb_fs_function; + + if (gadget_is_dualspeed(gadget)) { + /* Assume endpoint addresses are the same for both speeds */ + hs_ep_in.bEndpointAddress = fs_ep_in.bEndpointAddress; + hs_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress; + /* copy HS descriptors */ + f->hs_descriptors = fb_hs_function; + } s = getenv("serial#"); if (s) @@ -302,7 +321,6 @@ static int fastboot_add(struct usb_configuration *c) } f_fb->usb_function.name = "f_fastboot"; - f_fb->usb_function.hs_descriptors = fb_runtime_descs; f_fb->usb_function.bind = fastboot_bind; f_fb->usb_function.unbind = fastboot_unbind; f_fb->usb_function.set_alt = fastboot_set_alt; From 8b704a0e3d71ca8d1610ae0a877aa42dfdd8de82 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Wed, 13 Apr 2016 11:30:00 +0300 Subject: [PATCH 05/10] fastboot: Enable the respective speed endpoints at runtime In a dual speed configuration we need to check at runtime if we want to enable the Full-Speed or High-Speed endpoint. Signed-off-by: Roger Quadros Acked-by: Lukasz Majewski Tested-by: Steve Rae [Test HW: bcm235xx board] --- drivers/usb/gadget/f_fastboot.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index e1038ead41..7961231887 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -115,6 +115,15 @@ static struct usb_descriptor_header *fb_hs_function[] = { NULL, }; +static struct usb_endpoint_descriptor * +fb_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs, + struct usb_endpoint_descriptor *hs) +{ + if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) + return hs; + return fs; +} + /* * static strings, in UTF-8 */ @@ -255,18 +264,18 @@ static int fastboot_set_alt(struct usb_function *f, struct usb_composite_dev *cdev = f->config->cdev; struct usb_gadget *gadget = cdev->gadget; struct f_fastboot *f_fb = func_to_fastboot(f); + const struct usb_endpoint_descriptor *d; debug("%s: func: %s intf: %d alt: %d\n", __func__, f->name, interface, alt); - /* make sure we don't enable the ep twice */ - if (gadget->speed == USB_SPEED_HIGH) { - ret = usb_ep_enable(f_fb->out_ep, &hs_ep_out); + if (gadget->speed == USB_SPEED_HIGH) is_high_speed = true; - } else { - ret = usb_ep_enable(f_fb->out_ep, &fs_ep_out); + else is_high_speed = false; - } + + d = fb_ep_desc(gadget, &fs_ep_out, &hs_ep_out); + ret = usb_ep_enable(f_fb->out_ep, d); if (ret) { puts("failed to enable out ep\n"); return ret; @@ -280,7 +289,8 @@ static int fastboot_set_alt(struct usb_function *f, } f_fb->out_req->complete = rx_handler_command; - ret = usb_ep_enable(f_fb->in_ep, &fs_ep_in); + d = fb_ep_desc(gadget, &fs_ep_in, &hs_ep_in); + ret = usb_ep_enable(f_fb->in_ep, d); if (ret) { puts("failed to enable in ep\n"); goto err; From ac484c5a6a5745503a5c1b83a3d4c1808b677ebf Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 19 Apr 2016 10:16:59 +0300 Subject: [PATCH 06/10] fastboot: Clean up bulk-out logic Just use ep->maxpacket to get the maxpacket size and simplify the bulk-out maxpacket alignment. Signed-off-by: Roger Quadros Tested-by: Steve Rae --- drivers/usb/gadget/f_fastboot.c | 50 +++++++++++++++------------------ 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index 7961231887..28b244a8d0 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -39,6 +39,11 @@ #define TX_ENDPOINT_MAXIMUM_PACKET_SIZE (0x0040) #define EP_BUFFER_SIZE 4096 +/* + * EP_BUFFER_SIZE must always be an integral multiple of maxpacket size + * (64 or 512 or 1024), else we break on certain controllers like DWC3 + * that expect bulk OUT requests to be divisible by maxpacket size. + */ struct f_fastboot { struct usb_function usb_function; @@ -57,7 +62,6 @@ static struct f_fastboot *fastboot_func; static unsigned int fastboot_flash_session_id; static unsigned int download_size; static unsigned int download_bytes; -static bool is_high_speed; static struct usb_endpoint_descriptor fs_ep_in = { .bLength = USB_DT_ENDPOINT_SIZE, @@ -269,11 +273,6 @@ static int fastboot_set_alt(struct usb_function *f, debug("%s: func: %s intf: %d alt: %d\n", __func__, f->name, interface, alt); - if (gadget->speed == USB_SPEED_HIGH) - is_high_speed = true; - else - is_high_speed = false; - d = fb_ep_desc(gadget, &fs_ep_out, &hs_ep_out); ret = usb_ep_enable(f_fb->out_ep, d); if (ret) { @@ -455,20 +454,27 @@ static void cb_getvar(struct usb_ep *ep, struct usb_request *req) fastboot_tx_write_str(response); } -static unsigned int rx_bytes_expected(unsigned int maxpacket) +static unsigned int rx_bytes_expected(struct usb_ep *ep) { int rx_remain = download_size - download_bytes; - int rem = 0; - if (rx_remain < 0) + unsigned int rem; + unsigned int maxpacket = ep->maxpacket; + + if (rx_remain <= 0) return 0; - if (rx_remain > EP_BUFFER_SIZE) + else if (rx_remain > EP_BUFFER_SIZE) return EP_BUFFER_SIZE; - if (rx_remain < maxpacket) { - rx_remain = maxpacket; - } else if (rx_remain % maxpacket != 0) { - rem = rx_remain % maxpacket; + + /* + * Some controllers e.g. DWC3 don't like OUT transfers to be + * not ending in maxpacket boundary. So just make them happy by + * always requesting for integral multiple of maxpackets. + * This shouldn't bother controllers that don't care about it. + */ + rem = rx_remain % maxpacket; + if (rem > 0) rx_remain = rx_remain + (maxpacket - rem); - } + return rx_remain; } @@ -480,7 +486,6 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req) const unsigned char *buffer = req->buf; unsigned int buffer_size = req->actual; unsigned int pre_dot_num, now_dot_num; - unsigned int max; if (req->status != 0) { printf("Bad status: %d\n", req->status); @@ -518,11 +523,7 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req) printf("\ndownloading of %d bytes finished\n", download_bytes); } else { - max = is_high_speed ? hs_ep_out.wMaxPacketSize : - fs_ep_out.wMaxPacketSize; - req->length = rx_bytes_expected(max); - if (req->length < ep->maxpacket) - req->length = ep->maxpacket; + req->length = rx_bytes_expected(ep); } req->actual = 0; @@ -533,7 +534,6 @@ static void cb_download(struct usb_ep *ep, struct usb_request *req) { char *cmd = req->buf; char response[FASTBOOT_RESPONSE_LEN]; - unsigned int max; strsep(&cmd, ":"); download_size = simple_strtoul(cmd, NULL, 16); @@ -549,11 +549,7 @@ static void cb_download(struct usb_ep *ep, struct usb_request *req) } else { sprintf(response, "DATA%08x", download_size); req->complete = rx_handler_dl_image; - max = is_high_speed ? hs_ep_out.wMaxPacketSize : - fs_ep_out.wMaxPacketSize; - req->length = rx_bytes_expected(max); - if (req->length < ep->maxpacket) - req->length = ep->maxpacket; + req->length = rx_bytes_expected(ep); } fastboot_tx_write_str(response); } From 842769ea51d849fee3f6c03939cabd3971e75cfd Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 19 Apr 2016 15:20:39 +0300 Subject: [PATCH 07/10] usb: s3c-otg: Fix short packet for request size > ep.maxpacket Request size can be greater than ep.packet and still end in a short packet. We need to tackle this case as end of transfer (if short_not_ok is not set) as indicated in USB 2.0 Specification [1], else we get stuck up on certain protocols like fastboot. [1] - USB2.0 Specification, Section 5.3.2 Pipes Reported-by: Steve Rae Signed-off-by: Roger Quadros Tested-by: Steve Rae Tested-by: Lukasz Majewski --- drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c index bce9c30ef6..9aa0f33810 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c +++ b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c @@ -229,7 +229,7 @@ static void complete_rx(struct dwc2_udc *dev, u8 ep_num) ROUND(xfer_size, CONFIG_SYS_CACHELINE_SIZE)); req->req.actual += min(xfer_size, req->req.length - req->req.actual); - is_short = (xfer_size < ep->ep.maxpacket); + is_short = !!(xfer_size % ep->ep.maxpacket); debug_cond(DEBUG_OUT_EP != 0, "%s: RX DMA done : ep = %d, rx bytes = %d/%d, " From 4d5b63784317821650f614c9bf9a9b9c6949baee Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Fri, 22 Apr 2016 11:02:06 +0200 Subject: [PATCH 08/10] usb: s3c-otg: Fix remaining bytes in debug messages Remaining bytes means bytes that are not yet transferred and not the bytes that were transferred in the last transfer. Reported-by: Lukasz Majewski Signed-off-by: Roger Quadros Tested-by: Steve Rae [Test HW: bcm28155_ap board] --- drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c index 9aa0f33810..12f5c85c31 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c +++ b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c @@ -235,7 +235,7 @@ static void complete_rx(struct dwc2_udc *dev, u8 ep_num) "%s: RX DMA done : ep = %d, rx bytes = %d/%d, " "is_short = %d, DOEPTSIZ = 0x%x, remained bytes = %d\n", __func__, ep_num, req->req.actual, req->req.length, - is_short, ep_tsr, xfer_size); + is_short, ep_tsr, req->req.length - req->req.actual); if (is_short || req->req.actual == req->req.length) { if (ep_num == EP0_CON && dev->ep0state == DATA_STATE_RECV) { @@ -292,7 +292,7 @@ static void complete_tx(struct dwc2_udc *dev, u8 ep_num) "%s: TX DMA done : ep = %d, tx bytes = %d/%d, " "is_short = %d, DIEPTSIZ = 0x%x, remained bytes = %d\n", __func__, ep_num, req->req.actual, req->req.length, - is_short, ep_tsr, xfer_size); + is_short, ep_tsr, req->req.length - req->req.actual); if (ep_num == 0) { if (dev->ep0state == DATA_STATE_XMIT) { From e1b0f6fe3d0a0317486fb879e83dc1440cac3029 Mon Sep 17 00:00:00 2001 From: Mugunthan V N Date: Fri, 22 Apr 2016 14:19:25 +0530 Subject: [PATCH 09/10] drivers: dfu: ram: fix a crash with dfu ram with invalid dfu_alt_info env U-Boot crashes when an invalid dfu_alt_info is set and tried using dfu command. Fixing this as it is handled in dfu-mmc. => dfu 0 ram 0 data abort pc : [<9ff893d6>] lr : [<9ff6edb9>] reloc pc : [<808323d6>] lr : [<80817db9>] sp : 9ef36cf0 ip : 00000158 fp : 9ffbc0b8 r10: 9ffbc0b8 r9 : 9ef36ed8 r8 : 00000000 r7 : 00000000 r6 : 9ffbc0c8 r5 : 9ef36cfc r4 : 9ef392c8 r3 : 00000004 r2 : 00000000 r1 : 9ff9a985 r0 : ffffffff Flags: Nzcv IRQs off FIQs on Mode SVC_32 Resetting CPU ... resetting ... Signed-off-by: Mugunthan V N Reviewed-by: Tom Rini --- drivers/dfu/dfu_ram.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/dfu/dfu_ram.c b/drivers/dfu/dfu_ram.c index e094a946f6..1391a0d52b 100644 --- a/drivers/dfu/dfu_ram.c +++ b/drivers/dfu/dfu_ram.c @@ -54,19 +54,26 @@ static int dfu_read_medium_ram(struct dfu_entity *dfu, u64 offset, int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr, char *s) { - char *st; + const char *argv[3]; + const char **parg = argv; + + for (; parg < argv + sizeof(argv) / sizeof(*argv); ++parg) { + *parg = strsep(&s, " "); + if (*parg == NULL) { + error("Invalid number of arguments.\n"); + return -ENODEV; + } + } dfu->dev_type = DFU_DEV_RAM; - st = strsep(&s, " "); - if (strcmp(st, "ram")) { - error("unsupported device: %s\n", st); + if (strcmp(argv[0], "ram")) { + error("unsupported device: %s\n", argv[0]); return -ENODEV; } dfu->layout = DFU_RAM_ADDR; - dfu->data.ram.start = (void *)simple_strtoul(s, &s, 16); - s++; - dfu->data.ram.size = simple_strtoul(s, &s, 16); + dfu->data.ram.start = (void *)simple_strtoul(argv[1], NULL, 0); + dfu->data.ram.size = simple_strtoul(argv[2], NULL, 0); dfu->write_medium = dfu_write_medium_ram; dfu->get_medium_size = dfu_get_medium_size_ram; From 3517de6d26de7baeddb2c9e9bf145456c35885e1 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 22 Apr 2016 13:34:16 -0600 Subject: [PATCH 10/10] dfu: ram: fix number base of RAM entity parameters U-Boot typically interprets unprefixed numbers as base 16, and DFU RAM entity parsing has historically done so. Reverse the change to default to base 10, so that values in previously working command-lines aren't mis-parsed, causing RAM corruption, crashes, hangs, etc. Fixes: 6aeb877afef0 ("drivers: dfu: ram: fix a crash with dfu ram with invalid dfu_alt_info env") Cc: Mugunthan V N Cc: Tom Rini Signed-off-by: Stephen Warren Reviewed-by: Mugunthan V N Tested-by: Mugunthan V N [Test HW: AM335x BBB] --- drivers/dfu/dfu_ram.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dfu/dfu_ram.c b/drivers/dfu/dfu_ram.c index 1391a0d52b..c1b00217c9 100644 --- a/drivers/dfu/dfu_ram.c +++ b/drivers/dfu/dfu_ram.c @@ -72,8 +72,8 @@ int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr, char *s) } dfu->layout = DFU_RAM_ADDR; - dfu->data.ram.start = (void *)simple_strtoul(argv[1], NULL, 0); - dfu->data.ram.size = simple_strtoul(argv[2], NULL, 0); + dfu->data.ram.start = (void *)simple_strtoul(argv[1], NULL, 16); + dfu->data.ram.size = simple_strtoul(argv[2], NULL, 16); dfu->write_medium = dfu_write_medium_ram; dfu->get_medium_size = dfu_get_medium_size_ram;