Merge git://git.denx.de/u-boot-usb
This commit is contained in:
commit
cdc7732f37
@ -59,3 +59,15 @@ int dram_init(void)
|
|||||||
gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
|
gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_USB_GADGET_PXA2XX
|
||||||
|
int board_usb_init(int index, enum usb_init_type init)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int board_usb_cleanup(int index, enum usb_init_type init)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -210,6 +210,7 @@ obj-$(CONFIG_LYNXKDI) += lynxkdi.o
|
|||||||
obj-$(CONFIG_MENU) += menu.o
|
obj-$(CONFIG_MENU) += menu.o
|
||||||
obj-$(CONFIG_MODEM_SUPPORT) += modem.o
|
obj-$(CONFIG_MODEM_SUPPORT) += modem.o
|
||||||
obj-$(CONFIG_UPDATE_TFTP) += update.o
|
obj-$(CONFIG_UPDATE_TFTP) += update.o
|
||||||
|
obj-$(CONFIG_DFU_TFTP) += update.o
|
||||||
obj-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
|
obj-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
|
||||||
obj-$(CONFIG_CMD_DFU) += cmd_dfu.o
|
obj-$(CONFIG_CMD_DFU) += cmd_dfu.o
|
||||||
obj-$(CONFIG_CMD_GPT) += cmd_gpt.o
|
obj-$(CONFIG_CMD_GPT) += cmd_gpt.o
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* cmd_dfu.c -- dfu command
|
* cmd_dfu.c -- dfu command
|
||||||
*
|
*
|
||||||
|
* Copyright (C) 2015
|
||||||
|
* Lukasz Majewski <l.majewski@majess.pl>
|
||||||
|
*
|
||||||
* Copyright (C) 2012 Samsung Electronics
|
* Copyright (C) 2012 Samsung Electronics
|
||||||
* authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
* authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||||
* Lukasz Majewski <l.majewski@samsung.com>
|
* Lukasz Majewski <l.majewski@samsung.com>
|
||||||
@ -13,6 +16,7 @@
|
|||||||
#include <dfu.h>
|
#include <dfu.h>
|
||||||
#include <g_dnl.h>
|
#include <g_dnl.h>
|
||||||
#include <usb.h>
|
#include <usb.h>
|
||||||
|
#include <net.h>
|
||||||
|
|
||||||
static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||||
{
|
{
|
||||||
@ -26,6 +30,15 @@ static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|||||||
char *devstring = argv[3];
|
char *devstring = argv[3];
|
||||||
|
|
||||||
int ret, i = 0;
|
int ret, i = 0;
|
||||||
|
#ifdef CONFIG_DFU_TFTP
|
||||||
|
unsigned long addr = 0;
|
||||||
|
if (!strcmp(argv[1], "tftp")) {
|
||||||
|
if (argc == 5)
|
||||||
|
addr = simple_strtoul(argv[4], NULL, 0);
|
||||||
|
|
||||||
|
return update_tftp(addr, interface, devstring);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ret = dfu_init_env_entities(interface, devstring);
|
ret = dfu_init_env_entities(interface, devstring);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -89,4 +102,11 @@ U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu,
|
|||||||
" on device <dev>, attached to interface\n"
|
" on device <dev>, attached to interface\n"
|
||||||
" <interface>\n"
|
" <interface>\n"
|
||||||
" [list] - list available alt settings\n"
|
" [list] - list available alt settings\n"
|
||||||
|
#ifdef CONFIG_DFU_TFTP
|
||||||
|
"dfu tftp <interface> <dev> [<addr>]\n"
|
||||||
|
" - device firmware upgrade via TFTP\n"
|
||||||
|
" on device <dev>, attached to interface\n"
|
||||||
|
" <interface>\n"
|
||||||
|
" [<addr>] - address where FIT image has been stored\n"
|
||||||
|
#endif
|
||||||
);
|
);
|
||||||
|
@ -23,7 +23,7 @@ static int do_fitupd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|||||||
if (argc == 2)
|
if (argc == 2)
|
||||||
addr = simple_strtoul(argv[1], NULL, 16);
|
addr = simple_strtoul(argv[1], NULL, 16);
|
||||||
|
|
||||||
return update_tftp(addr);
|
return update_tftp(addr, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
U_BOOT_CMD(fitupd, 2, 0, do_fitupd,
|
U_BOOT_CMD(fitupd, 2, 0, do_fitupd,
|
||||||
|
@ -75,7 +75,7 @@ void main_loop(void)
|
|||||||
run_preboot_environment_command();
|
run_preboot_environment_command();
|
||||||
|
|
||||||
#if defined(CONFIG_UPDATE_TFTP)
|
#if defined(CONFIG_UPDATE_TFTP)
|
||||||
update_tftp(0UL);
|
update_tftp(0UL, NULL, NULL);
|
||||||
#endif /* CONFIG_UPDATE_TFTP */
|
#endif /* CONFIG_UPDATE_TFTP */
|
||||||
|
|
||||||
s = bootdelay_process();
|
s = bootdelay_process();
|
||||||
|
@ -13,8 +13,8 @@
|
|||||||
#error "CONFIG_FIT and CONFIG_OF_LIBFDT are required for auto-update feature"
|
#error "CONFIG_FIT and CONFIG_OF_LIBFDT are required for auto-update feature"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_SYS_NO_FLASH)
|
#if defined(CONFIG_UPDATE_TFTP) && defined(CONFIG_SYS_NO_FLASH)
|
||||||
#error "CONFIG_SYS_NO_FLASH defined, but FLASH is required for auto-update feature"
|
#error "CONFIG_UPDATE_TFTP and CONFIG_SYS_NO_FLASH needed for legacy behaviour"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <command.h>
|
#include <command.h>
|
||||||
@ -22,6 +22,8 @@
|
|||||||
#include <net.h>
|
#include <net.h>
|
||||||
#include <net/tftp.h>
|
#include <net/tftp.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
#include <dfu.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
/* env variable holding the location of the update file */
|
/* env variable holding the location of the update file */
|
||||||
#define UPDATE_FILE_ENV "updatefile"
|
#define UPDATE_FILE_ENV "updatefile"
|
||||||
@ -41,11 +43,11 @@
|
|||||||
|
|
||||||
extern ulong tftp_timeout_ms;
|
extern ulong tftp_timeout_ms;
|
||||||
extern int tftp_timeout_count_max;
|
extern int tftp_timeout_count_max;
|
||||||
extern flash_info_t flash_info[];
|
|
||||||
extern ulong load_addr;
|
extern ulong load_addr;
|
||||||
|
#ifndef CONFIG_SYS_NO_FLASH
|
||||||
|
extern flash_info_t flash_info[];
|
||||||
static uchar *saved_prot_info;
|
static uchar *saved_prot_info;
|
||||||
|
#endif
|
||||||
static int update_load(char *filename, ulong msec_max, int cnt_max, ulong addr)
|
static int update_load(char *filename, ulong msec_max, int cnt_max, ulong addr)
|
||||||
{
|
{
|
||||||
int size, rv;
|
int size, rv;
|
||||||
@ -94,6 +96,7 @@ static int update_load(char *filename, ulong msec_max, int cnt_max, ulong addr)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_SYS_NO_FLASH
|
||||||
static int update_flash_protect(int prot, ulong addr_first, ulong addr_last)
|
static int update_flash_protect(int prot, ulong addr_first, ulong addr_last)
|
||||||
{
|
{
|
||||||
uchar *sp_info_ptr;
|
uchar *sp_info_ptr;
|
||||||
@ -165,9 +168,11 @@ static int update_flash_protect(int prot, ulong addr_first, ulong addr_last)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int update_flash(ulong addr_source, ulong addr_first, ulong size)
|
static int update_flash(ulong addr_source, ulong addr_first, ulong size)
|
||||||
{
|
{
|
||||||
|
#ifndef CONFIG_SYS_NO_FLASH
|
||||||
ulong addr_last = addr_first + size - 1;
|
ulong addr_last = addr_first + size - 1;
|
||||||
|
|
||||||
/* round last address to the sector boundary */
|
/* round last address to the sector boundary */
|
||||||
@ -203,7 +208,7 @@ static int update_flash(ulong addr_source, ulong addr_first, ulong size)
|
|||||||
printf("Error: could not protect flash sectors\n");
|
printf("Error: could not protect flash sectors\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,13 +228,24 @@ static int update_fit_getparams(const void *fit, int noffset, ulong *addr,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int update_tftp(ulong addr)
|
int update_tftp(ulong addr, char *interface, char *devstring)
|
||||||
{
|
{
|
||||||
char *filename, *env_addr;
|
char *filename, *env_addr, *fit_image_name;
|
||||||
int images_noffset, ndepth, noffset;
|
|
||||||
ulong update_addr, update_fladdr, update_size;
|
ulong update_addr, update_fladdr, update_size;
|
||||||
void *fit;
|
int images_noffset, ndepth, noffset;
|
||||||
|
bool update_tftp_dfu;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
void *fit;
|
||||||
|
|
||||||
|
if (interface == NULL && devstring == NULL) {
|
||||||
|
update_tftp_dfu = false;
|
||||||
|
} else if (interface && devstring) {
|
||||||
|
update_tftp_dfu = true;
|
||||||
|
} else {
|
||||||
|
error("Interface: %s and devstring: %s not supported!\n",
|
||||||
|
interface, devstring);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
/* use already present image */
|
/* use already present image */
|
||||||
if (addr)
|
if (addr)
|
||||||
@ -278,8 +294,8 @@ got_update_file:
|
|||||||
if (ndepth != 1)
|
if (ndepth != 1)
|
||||||
goto next_node;
|
goto next_node;
|
||||||
|
|
||||||
printf("Processing update '%s' :",
|
fit_image_name = (char *)fit_get_name(fit, noffset, NULL);
|
||||||
fit_get_name(fit, noffset, NULL));
|
printf("Processing update '%s' :", fit_image_name);
|
||||||
|
|
||||||
if (!fit_image_verify(fit, noffset)) {
|
if (!fit_image_verify(fit, noffset)) {
|
||||||
printf("Error: invalid update hash, aborting\n");
|
printf("Error: invalid update hash, aborting\n");
|
||||||
@ -295,10 +311,20 @@ got_update_file:
|
|||||||
ret = 1;
|
ret = 1;
|
||||||
goto next_node;
|
goto next_node;
|
||||||
}
|
}
|
||||||
if (update_flash(update_addr, update_fladdr, update_size)) {
|
|
||||||
printf("Error: can't flash update, aborting\n");
|
if (!update_tftp_dfu) {
|
||||||
ret = 1;
|
if (update_flash(update_addr, update_fladdr,
|
||||||
goto next_node;
|
update_size)) {
|
||||||
|
printf("Error: can't flash update, aborting\n");
|
||||||
|
ret = 1;
|
||||||
|
goto next_node;
|
||||||
|
}
|
||||||
|
} else if (fit_image_check_type(fit, noffset,
|
||||||
|
IH_TYPE_FIRMWARE)) {
|
||||||
|
ret = dfu_tftp_write(fit_image_name, update_addr,
|
||||||
|
update_size, interface, devstring);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
next_node:
|
next_node:
|
||||||
noffset = fdt_next_node(fit, noffset, &ndepth);
|
noffset = fdt_next_node(fit, noffset, &ndepth);
|
||||||
|
@ -8,3 +8,4 @@ CONFIG_SYS_EXTRA_OPTIONS="EMMC_BOOT"
|
|||||||
# CONFIG_CMD_FLASH is not set
|
# CONFIG_CMD_FLASH is not set
|
||||||
# CONFIG_CMD_SETEXPR is not set
|
# CONFIG_CMD_SETEXPR is not set
|
||||||
CONFIG_SPI_FLASH=y
|
CONFIG_SPI_FLASH=y
|
||||||
|
CONFIG_DFU_TFTP=y
|
||||||
|
114
doc/README.dfutftp
Normal file
114
doc/README.dfutftp
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
Device Firmware Upgrade (DFU) - extension to use TFTP
|
||||||
|
=====================================================
|
||||||
|
|
||||||
|
Why?
|
||||||
|
----
|
||||||
|
|
||||||
|
* Update TFTP (CONFIG_UPDATE_TFTP) only supports writing
|
||||||
|
code to NAND memory via TFTP.
|
||||||
|
* DFU supports writing data to the variety of mediums (NAND,
|
||||||
|
eMMC, SD, partitions, RAM, etc) via USB.
|
||||||
|
|
||||||
|
Combination of both solves their shortcomings!
|
||||||
|
|
||||||
|
|
||||||
|
Overview
|
||||||
|
--------
|
||||||
|
|
||||||
|
This document briefly describes how to use DFU for
|
||||||
|
upgrading firmware (e.g. kernel, u-boot, rootfs, etc.)
|
||||||
|
via TFTP protocol.
|
||||||
|
|
||||||
|
By using Ethernet (TFTP protocol to be precise) it is
|
||||||
|
possible to overcome the major problem of USB based DFU -
|
||||||
|
the relatively low transfer speed for large files.
|
||||||
|
This was caused by DFU standard, which imposed utilization
|
||||||
|
of only EP0 for transfer. By using Ethernet we can circumvent
|
||||||
|
this shortcoming.
|
||||||
|
|
||||||
|
Beagle Bone Black rev. C (BBB) powered by TI's am335x CPU has
|
||||||
|
been used as a demo board.
|
||||||
|
|
||||||
|
To utilize this feature, one needs to first enable support
|
||||||
|
for USB based DFU (CONFIG_DFU_*) and DFU TFTP update
|
||||||
|
(CONFIG_DFU_TFTP) described in ./doc/README.update.
|
||||||
|
|
||||||
|
The "dfu" command has been extended to support transfer via TFTP - one
|
||||||
|
needs to type for example "dfu tftp 0 mmc 0"
|
||||||
|
|
||||||
|
This feature does not depend on "fitupd" command enabled.
|
||||||
|
|
||||||
|
As of this writing (SHA1:8d77576371381ade83de475bb639949b44941e8c v2015.10-rc2)
|
||||||
|
the update.c code is not enabled (CONFIG_UPDATE_TFTP) by any board in the
|
||||||
|
contemporary u-boot tree.
|
||||||
|
|
||||||
|
|
||||||
|
Environment variables
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The "dfu tftp" command can be used in the "preboot" environment variable
|
||||||
|
(when it is enabled by defining CONFIG_PREBOOT).
|
||||||
|
This is the preferable way of using this command in the early boot stage
|
||||||
|
as opposed to legacy update_tftp() function invocation.
|
||||||
|
|
||||||
|
|
||||||
|
Beagle Bone Black (BBB) setup
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
1. Setup tftp env variables:
|
||||||
|
* select desired eth device - 'ethact' variable ["ethact=cpsw"]
|
||||||
|
(use "bdinfo" to check current setting)
|
||||||
|
* setup "serverip" and "ipaddr" variables
|
||||||
|
* set "loadaddr" as a fixed buffer where incoming data is placed
|
||||||
|
["loadaddr=0x81000000"]
|
||||||
|
|
||||||
|
#########
|
||||||
|
# BONUS #
|
||||||
|
#########
|
||||||
|
It is possible to use USB interface to emulate ETH connection by setting
|
||||||
|
"ethact=usb_ether". In this way one can have very fast DFU transfer via USB.
|
||||||
|
|
||||||
|
For 33MiB test image the transfer rate was 1MiB/s for ETH over USB and 200KiB/s
|
||||||
|
for pure DFU USB transfer.
|
||||||
|
|
||||||
|
2. Setup update_tftp variables:
|
||||||
|
* set "updatefile" - the file name to be downloaded via TFTP (stored on
|
||||||
|
the HOST at e.g. /srv/tftp)
|
||||||
|
|
||||||
|
3. If required, to update firmware on boot, put the "dfu tftp 0 mmc 0" in the
|
||||||
|
"preboot" env variable. Otherwise use this command from u-boot prompt.
|
||||||
|
|
||||||
|
4. Inspect "dfu" specific variables:
|
||||||
|
* "dfu_alt_info" - information about available DFU entities
|
||||||
|
* "dfu_bufsiz" - variable to set buffer size [in bytes] - when it is not
|
||||||
|
possible to set large enough default buffer (8 MiB @ BBB)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
FIT image format for download
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
To create FIT image for download one should follow the update tftp README file
|
||||||
|
(./doc/README.update) with one notable difference:
|
||||||
|
|
||||||
|
The original snippet of ./doc/uImage.FIT/update_uboot.its
|
||||||
|
|
||||||
|
images {
|
||||||
|
update@1 {
|
||||||
|
description = "U-Boot binary";
|
||||||
|
|
||||||
|
should look like
|
||||||
|
|
||||||
|
images {
|
||||||
|
u-boot.bin@1 {
|
||||||
|
description = "U-Boot binary";
|
||||||
|
|
||||||
|
where "u-boot.bin" is the DFU entity name to be stored.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
To do
|
||||||
|
-----
|
||||||
|
|
||||||
|
* Extend dfu-util command to support TFTP based transfers
|
||||||
|
* Upload support (via TFTP)
|
@ -93,3 +93,10 @@ Example .its files
|
|||||||
An example containing three updates. It can be used to update Linux kernel,
|
An example containing three updates. It can be used to update Linux kernel,
|
||||||
ramdisk and FDT blob stored in Flash. The procedure for preparing the update
|
ramdisk and FDT blob stored in Flash. The procedure for preparing the update
|
||||||
file is similar to the example above.
|
file is similar to the example above.
|
||||||
|
|
||||||
|
TFTP update via DFU
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
- It is now possible to update firmware (bootloader, kernel, rootfs, etc.) via
|
||||||
|
TFTP by using DFU (Device Firmware Upgrade). More information can be found in
|
||||||
|
./doc/README.dfutftp documentation entry.
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
menu "DFU support"
|
||||||
|
|
||||||
|
config DFU_TFTP
|
||||||
|
bool "DFU via TFTP"
|
||||||
|
help
|
||||||
|
This option allows performing update of DFU managed medium with data
|
||||||
|
send via TFTP boot.
|
||||||
|
Detailed description of this feature can be found at ./doc/README.dfutftp
|
||||||
|
|
||||||
|
endmenu
|
@ -10,3 +10,4 @@ obj-$(CONFIG_DFU_MMC) += dfu_mmc.o
|
|||||||
obj-$(CONFIG_DFU_NAND) += dfu_nand.o
|
obj-$(CONFIG_DFU_NAND) += dfu_nand.o
|
||||||
obj-$(CONFIG_DFU_RAM) += dfu_ram.o
|
obj-$(CONFIG_DFU_RAM) += dfu_ram.o
|
||||||
obj-$(CONFIG_DFU_SF) += dfu_sf.o
|
obj-$(CONFIG_DFU_SF) += dfu_sf.o
|
||||||
|
obj-$(CONFIG_DFU_TFTP) += dfu_tftp.o
|
||||||
|
@ -76,7 +76,7 @@ int dfu_init_env_entities(char *interface, char *devstr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char *dfu_buf;
|
static unsigned char *dfu_buf;
|
||||||
static unsigned long dfu_buf_size = CONFIG_SYS_DFU_DATA_BUF_SIZE;
|
static unsigned long dfu_buf_size;
|
||||||
|
|
||||||
unsigned char *dfu_free_buf(void)
|
unsigned char *dfu_free_buf(void)
|
||||||
{
|
{
|
||||||
@ -568,3 +568,40 @@ int dfu_get_alt(char *name)
|
|||||||
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int dfu_write_from_mem_addr(struct dfu_entity *dfu, void *buf, int size)
|
||||||
|
{
|
||||||
|
unsigned long dfu_buf_size, write, left = size;
|
||||||
|
int i, ret = 0;
|
||||||
|
void *dp = buf;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here we must call dfu_get_buf(dfu) first to be sure that dfu_buf_size
|
||||||
|
* has been properly initialized - e.g. if "dfu_bufsiz" has been taken
|
||||||
|
* into account.
|
||||||
|
*/
|
||||||
|
dfu_get_buf(dfu);
|
||||||
|
dfu_buf_size = dfu_get_buf_size();
|
||||||
|
debug("%s: dfu buf size: %lu\n", __func__, dfu_buf_size);
|
||||||
|
|
||||||
|
for (i = 0; left > 0; i++) {
|
||||||
|
write = min(dfu_buf_size, left);
|
||||||
|
|
||||||
|
debug("%s: dp: 0x%p left: %lu write: %lu\n", __func__,
|
||||||
|
dp, left, write);
|
||||||
|
ret = dfu_write(dfu, dp, write, i);
|
||||||
|
if (ret) {
|
||||||
|
error("DFU write failed\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
dp += write;
|
||||||
|
left -= write;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = dfu_flush(dfu, NULL, 0, i);
|
||||||
|
if (ret)
|
||||||
|
error("DFU flush failed!");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
65
drivers/dfu/dfu_tftp.c
Normal file
65
drivers/dfu/dfu_tftp.c
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* (C) Copyright 2015
|
||||||
|
* Lukasz Majewski <l.majewski@majess.pl>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <dfu.h>
|
||||||
|
|
||||||
|
int dfu_tftp_write(char *dfu_entity_name, unsigned int addr, unsigned int len,
|
||||||
|
char *interface, char *devstring)
|
||||||
|
{
|
||||||
|
char *s, *sb;
|
||||||
|
int alt_setting_num, ret;
|
||||||
|
struct dfu_entity *dfu;
|
||||||
|
|
||||||
|
debug("%s: name: %s addr: 0x%x len: %d device: %s:%s\n", __func__,
|
||||||
|
dfu_entity_name, addr, len, interface, devstring);
|
||||||
|
|
||||||
|
ret = dfu_init_env_entities(interface, devstring);
|
||||||
|
if (ret)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to copy name pointed by *dfu_entity_name since this text
|
||||||
|
* is the integral part of the FDT image.
|
||||||
|
* Any implicit modification (i.e. done by strsep()) will corrupt
|
||||||
|
* the FDT image and prevent other images to be stored.
|
||||||
|
*/
|
||||||
|
s = strdup(dfu_entity_name);
|
||||||
|
sb = s;
|
||||||
|
if (!s) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
strsep(&s, "@");
|
||||||
|
debug("%s: image name: %s strlen: %d\n", __func__, sb, strlen(sb));
|
||||||
|
|
||||||
|
alt_setting_num = dfu_get_alt(sb);
|
||||||
|
free(sb);
|
||||||
|
if (alt_setting_num < 0) {
|
||||||
|
error("Alt setting [%d] to write not found!",
|
||||||
|
alt_setting_num);
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
dfu = dfu_get_entity(alt_setting_num);
|
||||||
|
if (!dfu) {
|
||||||
|
error("DFU entity for alt: %d not found!", alt_setting_num);
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = dfu_write_from_mem_addr(dfu, (void *)addr, len);
|
||||||
|
|
||||||
|
done:
|
||||||
|
dfu_free_entities();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
@ -123,6 +123,9 @@ static int process_rqt_cmd(const struct rqt_box *rqt)
|
|||||||
send_rsp(rsp);
|
send_rsp(rsp);
|
||||||
g_dnl_unregister();
|
g_dnl_unregister();
|
||||||
dfu_free_entities();
|
dfu_free_entities();
|
||||||
|
#ifdef CONFIG_THOR_RESET_OFF
|
||||||
|
return RESET_DONE;
|
||||||
|
#endif
|
||||||
run_command("reset", 0);
|
run_command("reset", 0);
|
||||||
break;
|
break;
|
||||||
case RQT_CMD_POWEROFF:
|
case RQT_CMD_POWEROFF:
|
||||||
@ -728,6 +731,10 @@ int thor_handle(void)
|
|||||||
|
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
ret = process_data();
|
ret = process_data();
|
||||||
|
#ifdef CONFIG_THOR_RESET_OFF
|
||||||
|
if (ret == RESET_DONE)
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
@ -768,7 +775,7 @@ static int thor_func_bind(struct usb_configuration *c, struct usb_function *f)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
dev->req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE,
|
dev->req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE,
|
||||||
gadget->ep0->maxpacket);
|
THOR_PACKET_SIZE);
|
||||||
if (!dev->req->buf) {
|
if (!dev->req->buf) {
|
||||||
status = -ENOMEM;
|
status = -ENOMEM;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -121,4 +121,7 @@ struct f_thor {
|
|||||||
#define F_NAME_BUF_SIZE 32
|
#define F_NAME_BUF_SIZE 32
|
||||||
#define THOR_PACKET_SIZE SZ_1M /* 1 MiB */
|
#define THOR_PACKET_SIZE SZ_1M /* 1 MiB */
|
||||||
#define THOR_STORE_UNIT_SIZE SZ_32M /* 32 MiB */
|
#define THOR_STORE_UNIT_SIZE SZ_32M /* 32 MiB */
|
||||||
|
#ifdef CONFIG_THOR_RESET_OFF
|
||||||
|
#define RESET_DONE 0xFFFFFFFF
|
||||||
|
#endif
|
||||||
#endif /* _USB_THOR_H_ */
|
#endif /* _USB_THOR_H_ */
|
||||||
|
@ -1645,8 +1645,10 @@ int ehci_register(struct udevice *dev, struct ehci_hccr *hccr,
|
|||||||
ctrl->hcor = hcor;
|
ctrl->hcor = hcor;
|
||||||
ctrl->priv = ctrl;
|
ctrl->priv = ctrl;
|
||||||
|
|
||||||
if (init == USB_INIT_DEVICE)
|
ctrl->init = init;
|
||||||
|
if (ctrl->init == USB_INIT_DEVICE)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
ret = ehci_reset(ctrl);
|
ret = ehci_reset(ctrl);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
@ -1666,6 +1668,9 @@ int ehci_deregister(struct udevice *dev)
|
|||||||
{
|
{
|
||||||
struct ehci_ctrl *ctrl = dev_get_priv(dev);
|
struct ehci_ctrl *ctrl = dev_get_priv(dev);
|
||||||
|
|
||||||
|
if (ctrl->init == USB_INIT_DEVICE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
ehci_shutdown(ctrl);
|
ehci_shutdown(ctrl);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -242,6 +242,7 @@ struct ehci_ops {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ehci_ctrl {
|
struct ehci_ctrl {
|
||||||
|
enum usb_init_type init;
|
||||||
struct ehci_hccr *hccr; /* R/O registers, not need for volatile */
|
struct ehci_hccr *hccr; /* R/O registers, not need for volatile */
|
||||||
struct ehci_hcor *hcor;
|
struct ehci_hcor *hcor;
|
||||||
int rootdev;
|
int rootdev;
|
||||||
|
@ -153,4 +153,23 @@
|
|||||||
#define CONFIG_G_DNL_PRODUCT_NUM 0x0d02 /* nexus one */
|
#define CONFIG_G_DNL_PRODUCT_NUM 0x0d02 /* nexus one */
|
||||||
#define CONFIG_G_DNL_MANUFACTURER "Broadcom Corporation"
|
#define CONFIG_G_DNL_MANUFACTURER "Broadcom Corporation"
|
||||||
|
|
||||||
|
/* Fastboot and USB OTG */
|
||||||
|
#define CONFIG_USB_FUNCTION_FASTBOOT
|
||||||
|
#define CONFIG_CMD_FASTBOOT
|
||||||
|
#define CONFIG_FASTBOOT_FLASH
|
||||||
|
#define CONFIG_FASTBOOT_FLASH_MMC_DEV 0
|
||||||
|
#define CONFIG_SYS_CACHELINE_SIZE 64
|
||||||
|
#define CONFIG_USB_FASTBOOT_BUF_SIZE (CONFIG_SYS_SDRAM_SIZE - SZ_1M)
|
||||||
|
#define CONFIG_USB_FASTBOOT_BUF_ADDR CONFIG_SYS_SDRAM_BASE
|
||||||
|
#define CONFIG_USB_GADGET
|
||||||
|
#define CONFIG_USB_GADGET_DUALSPEED
|
||||||
|
#define CONFIG_USB_GADGET_VBUS_DRAW 0
|
||||||
|
#define CONFIG_USB_GADGET_S3C_UDC_OTG
|
||||||
|
#define CONFIG_USB_GADGET_BCM_UDC_OTG_PHY
|
||||||
|
#define CONFIG_USB_GADGET_DOWNLOAD
|
||||||
|
#define CONFIG_USBID_ADDR 0x34052c46
|
||||||
|
#define CONFIG_G_DNL_VENDOR_NUM 0x18d1 /* google */
|
||||||
|
#define CONFIG_G_DNL_PRODUCT_NUM 0x0d02 /* nexus one */
|
||||||
|
#define CONFIG_G_DNL_MANUFACTURER "Broadcom Corporation"
|
||||||
|
|
||||||
#endif /* __BCM28155_AP_H */
|
#endif /* __BCM28155_AP_H */
|
||||||
|
@ -162,6 +162,21 @@ bool dfu_usb_get_reset(void);
|
|||||||
int dfu_read(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
|
int dfu_read(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
|
||||||
int dfu_write(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
|
int dfu_write(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
|
||||||
int dfu_flush(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
|
int dfu_flush(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dfu_write_from_mem_addr - write data from memory to DFU managed medium
|
||||||
|
*
|
||||||
|
* This function adds support for writing data starting from fixed memory
|
||||||
|
* address (like $loadaddr) to dfu managed medium (e.g. NAND, MMC, file system)
|
||||||
|
*
|
||||||
|
* @param dfu - dfu entity to which we want to store data
|
||||||
|
* @param buf - fixed memory addres from where data starts
|
||||||
|
* @param size - number of bytes to write
|
||||||
|
*
|
||||||
|
* @return - 0 on success, other value on failure
|
||||||
|
*/
|
||||||
|
int dfu_write_from_mem_addr(struct dfu_entity *dfu, void *buf, int size);
|
||||||
|
|
||||||
/* Device specific */
|
/* Device specific */
|
||||||
#ifdef CONFIG_DFU_MMC
|
#ifdef CONFIG_DFU_MMC
|
||||||
extern int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s);
|
extern int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s);
|
||||||
@ -207,5 +222,31 @@ static inline int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dfu_tftp_write - Write TFTP data to DFU medium
|
||||||
|
*
|
||||||
|
* This function is storing data received via TFTP on DFU supported medium.
|
||||||
|
*
|
||||||
|
* @param dfu_entity_name - name of DFU entity to write
|
||||||
|
* @param addr - address of data buffer to write
|
||||||
|
* @param len - number of bytes
|
||||||
|
* @param interface - destination DFU medium (e.g. "mmc")
|
||||||
|
* @param devstring - instance number of destination DFU medium (e.g. "1")
|
||||||
|
*
|
||||||
|
* @return 0 on success, otherwise error code
|
||||||
|
*/
|
||||||
|
#ifdef CONFIG_DFU_TFTP
|
||||||
|
int dfu_tftp_write(char *dfu_entity_name, unsigned int addr, unsigned int len,
|
||||||
|
char *interface, char *devstring);
|
||||||
|
#else
|
||||||
|
static inline int dfu_tftp_write(char *dfu_entity_name, unsigned int addr,
|
||||||
|
unsigned int len, char *interface,
|
||||||
|
char *devstring)
|
||||||
|
{
|
||||||
|
puts("TFTP write support for DFU not available!\n");
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int dfu_add(struct usb_configuration *c);
|
int dfu_add(struct usb_configuration *c);
|
||||||
#endif /* __DFU_ENTITY_H_ */
|
#endif /* __DFU_ENTITY_H_ */
|
||||||
|
@ -813,8 +813,18 @@ void copy_filename(char *dst, const char *src, int size);
|
|||||||
/* get a random source port */
|
/* get a random source port */
|
||||||
unsigned int random_port(void);
|
unsigned int random_port(void);
|
||||||
|
|
||||||
/* Update U-Boot over TFTP */
|
/**
|
||||||
int update_tftp(ulong addr);
|
* update_tftp - Update firmware over TFTP (via DFU)
|
||||||
|
*
|
||||||
|
* This function updates board's firmware via TFTP
|
||||||
|
*
|
||||||
|
* @param addr - memory address where data is stored
|
||||||
|
* @param interface - the DFU medium name - e.g. "mmc"
|
||||||
|
* @param devstring - the DFU medium number - e.g. "1"
|
||||||
|
*
|
||||||
|
* @return - 0 on success, other value on failure
|
||||||
|
*/
|
||||||
|
int update_tftp(ulong addr, char *interface, char *devstring);
|
||||||
|
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <command.h>
|
#include <command.h>
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
|
#include <net/tftp.h>
|
||||||
#include "bootp.h"
|
#include "bootp.h"
|
||||||
#include "tftp.h"
|
|
||||||
#include "nfs.h"
|
#include "nfs.h"
|
||||||
#ifdef CONFIG_STATUS_LED
|
#ifdef CONFIG_STATUS_LED
|
||||||
#include <status_led.h>
|
#include <status_led.h>
|
||||||
|
@ -86,6 +86,7 @@
|
|||||||
#include <environment.h>
|
#include <environment.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
|
#include <net/tftp.h>
|
||||||
#if defined(CONFIG_STATUS_LED)
|
#if defined(CONFIG_STATUS_LED)
|
||||||
#include <miiphy.h>
|
#include <miiphy.h>
|
||||||
#include <status_led.h>
|
#include <status_led.h>
|
||||||
@ -105,7 +106,6 @@
|
|||||||
#if defined(CONFIG_CMD_SNTP)
|
#if defined(CONFIG_CMD_SNTP)
|
||||||
#include "sntp.h"
|
#include "sntp.h"
|
||||||
#endif
|
#endif
|
||||||
#include "tftp.h"
|
|
||||||
|
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
@ -8,10 +8,10 @@
|
|||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <command.h>
|
#include <command.h>
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
|
#include <net/tftp.h>
|
||||||
#include "nfs.h"
|
#include "nfs.h"
|
||||||
#include "bootp.h"
|
#include "bootp.h"
|
||||||
#include "rarp.h"
|
#include "rarp.h"
|
||||||
#include "tftp.h"
|
|
||||||
|
|
||||||
#define TIMEOUT 5000UL /* Milliseconds before trying BOOTP again */
|
#define TIMEOUT 5000UL /* Milliseconds before trying BOOTP again */
|
||||||
#ifndef CONFIG_NET_RETRY_COUNT
|
#ifndef CONFIG_NET_RETRY_COUNT
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include <command.h>
|
#include <command.h>
|
||||||
#include <mapmem.h>
|
#include <mapmem.h>
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
#include "tftp.h"
|
#include <net/tftp.h>
|
||||||
#include "bootp.h"
|
#include "bootp.h"
|
||||||
#ifdef CONFIG_SYS_DIRECT_FLASH_TFTP
|
#ifdef CONFIG_SYS_DIRECT_FLASH_TFTP
|
||||||
#include <flash.h>
|
#include <flash.h>
|
||||||
|
@ -26,12 +26,19 @@ Example usage:
|
|||||||
setenv dfu_alt_info dfu_test.bin fat 0 6\;dfudummy.bin fat 0 6
|
setenv dfu_alt_info dfu_test.bin fat 0 6\;dfudummy.bin fat 0 6
|
||||||
dfu 0 mmc 0
|
dfu 0 mmc 0
|
||||||
2. On the host:
|
2. On the host:
|
||||||
test/dfu/dfu_gadget_test.sh X Y [test file name]
|
test/dfu/dfu_gadget_test.sh X Y [test file name] [usb device vendor:product]
|
||||||
e.g. test/dfu/dfu_gadget_test.sh 0 1
|
e.g. test/dfu/dfu_gadget_test.sh 0 1
|
||||||
or
|
or
|
||||||
e.g. test/dfu/dfu_gadget_test.sh 0 1 ./dat_960.img
|
e.g. test/dfu/dfu_gadget_test.sh 0 1 ./dat_960.img
|
||||||
|
or
|
||||||
|
e.g. test/dfu/dfu_gadget_test.sh 0 1 0451:d022
|
||||||
|
or
|
||||||
|
e.g. test/dfu/dfu_gadget_test.sh 0 1 ./dat_960.img 0451:d022
|
||||||
|
|
||||||
... where X and Y are dfu_test.bin's and dfudummy.bin's alt setting numbers.
|
... where X and Y are dfu_test.bin's and dfudummy.bin's alt setting numbers.
|
||||||
They can be obtained from dfu-util -l or $dfu_alt_info.
|
They can be obtained from dfu-util -l or $dfu_alt_info.
|
||||||
It is also possible to pass optional [test file name] to force the script to
|
It is also possible to pass optional [test file name] to force the script to
|
||||||
test one particular file.
|
test one particular file.
|
||||||
|
If many DFU devices are connected, it may be useful to filter on USB
|
||||||
|
vendor/product ID (0451:d022).
|
||||||
|
One can get them by running "lsusb" command on a host PC.
|
||||||
|
@ -45,18 +45,18 @@ dfu_test_file () {
|
|||||||
printf "$COLOUR_GREEN ========================================================================================= $COLOUR_DEFAULT\n"
|
printf "$COLOUR_GREEN ========================================================================================= $COLOUR_DEFAULT\n"
|
||||||
printf "File:$COLOUR_GREEN %s $COLOUR_DEFAULT\n" $1
|
printf "File:$COLOUR_GREEN %s $COLOUR_DEFAULT\n" $1
|
||||||
|
|
||||||
dfu-util -D $1 -a $TARGET_ALT_SETTING >> $LOG_FILE 2>&1 || die $?
|
dfu-util $USB_DEV -D $1 -a $TARGET_ALT_SETTING >> $LOG_FILE 2>&1 || die $?
|
||||||
|
|
||||||
echo -n "TX: "
|
echo -n "TX: "
|
||||||
calculate_md5sum $1
|
calculate_md5sum $1
|
||||||
|
|
||||||
MD5_TX=$MD5SUM
|
MD5_TX=$MD5SUM
|
||||||
|
|
||||||
dfu-util -D ${DIR}/dfudummy.bin -a $TARGET_ALT_SETTING_B >> $LOG_FILE 2>&1 || die $?
|
dfu-util $USB_DEV -D ${DIR}/dfudummy.bin -a $TARGET_ALT_SETTING_B >> $LOG_FILE 2>&1 || die $?
|
||||||
|
|
||||||
N_FILE=$DIR$RCV_DIR${1:2}"_rcv"
|
N_FILE=$DIR$RCV_DIR${1:2}"_rcv"
|
||||||
|
|
||||||
dfu-util -U $N_FILE -a $TARGET_ALT_SETTING >> $LOG_FILE 2>&1 || die $?
|
dfu-util $USB_DEV -U $N_FILE -a $TARGET_ALT_SETTING >> $LOG_FILE 2>&1 || die $?
|
||||||
|
|
||||||
echo -n "RX: "
|
echo -n "RX: "
|
||||||
calculate_md5sum $N_FILE
|
calculate_md5sum $N_FILE
|
||||||
@ -89,13 +89,17 @@ fi
|
|||||||
TARGET_ALT_SETTING=$1
|
TARGET_ALT_SETTING=$1
|
||||||
TARGET_ALT_SETTING_B=$2
|
TARGET_ALT_SETTING_B=$2
|
||||||
|
|
||||||
if [ -n "$3" ]
|
file=$3
|
||||||
|
[[ $3 == *':'* ]] && USB_DEV="-d $3" && file=""
|
||||||
|
[ $# -eq 4 ] && USB_DEV="-d $4"
|
||||||
|
|
||||||
|
if [ -n "$file" ]
|
||||||
then
|
then
|
||||||
dfu_test_file $3
|
dfu_test_file $file
|
||||||
else
|
else
|
||||||
for file in $DIR*.$SUFFIX
|
for f in $DIR*.$SUFFIX
|
||||||
do
|
do
|
||||||
dfu_test_file $file
|
dfu_test_file $f
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user