arm start.c: Make runtime function address calculation tolerant for more compilers
[barebox-mini2440.git] / commands / dfu.c
blob66fd6eaa62dfa330d400b278e65cc1f9bbfd678a
1 /*
2 * dfu.c - device firmware update command
4 * Copyright (c) 2009 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
6 * See file CREDITS for list of people who contributed to this
7 * project.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2
11 * as published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <common.h>
23 #include <command.h>
24 #include <errno.h>
25 #include <malloc.h>
26 #include <getopt.h>
27 #include <fs.h>
28 #include <xfuncs.h>
29 #include <usb/dfu.h>
31 #define PARSE_DEVICE 0
32 #define PARSE_NAME 1
33 #define PARSE_FLAGS 2
35 static int dfu_do_parse_one(char *partstr, char **endstr, struct usb_dfu_dev *dfu)
37 int i = 0, state = PARSE_DEVICE;
38 char device[PATH_MAX];
39 char name[PATH_MAX];
41 memset(device, 0, sizeof(device));
42 memset(name, 0, sizeof(name));
43 dfu->flags = 0;
45 while (*partstr && *partstr != ',') {
46 switch (state) {
47 case PARSE_DEVICE:
48 if (*partstr == '(') {
49 state = PARSE_NAME;
50 i = 0;
51 } else {
52 device[i++] = *partstr;
54 break;
55 case PARSE_NAME:
56 if (*partstr == ')') {
57 state = PARSE_FLAGS;
58 i = 0;
59 } else {
60 name[i++] = *partstr;
62 break;
63 case PARSE_FLAGS:
64 switch (*partstr) {
65 case 's':
66 dfu->flags |= DFU_FLAG_SAVE;
67 break;
68 case 'r':
69 dfu->flags |= DFU_FLAG_READBACK;
70 break;
71 default:
72 return -EINVAL;
74 break;
75 default:
76 return -EINVAL;
78 partstr++;
81 if (state != PARSE_FLAGS)
82 return -EINVAL;
84 dfu->name = xstrdup(name);
85 dfu->dev = xstrdup(device);
86 if (*partstr == ',')
87 partstr++;
88 *endstr = partstr;
90 return 0;
93 /* dfu /dev/self0(bootloader)sr,/dev/nand0.root.bb(root)
95 * s = save mode (download whole image before flashing)
96 * r = read back (firmware image can be downloaded back from host)
98 static int do_dfu(struct command *cmdtp, int argc, char *argv[])
100 int opt, n = 0;
101 struct usb_dfu_pdata pdata;
102 char *endptr, *argstr;
103 struct usb_dfu_dev *dfu_alts = NULL;
104 char *manufacturer = "barebox";
105 char *productname = CONFIG_BOARDINFO;
106 u16 idVendor = 0, idProduct = 0;
109 while((opt = getopt(argc, argv, "m:p:V:P:")) > 0) {
110 switch(opt) {
111 case 'm':
112 manufacturer = optarg;
113 break;
114 case 'p':
115 productname = optarg;
116 break;
117 case 'V':
118 idVendor = simple_strtoul(optarg, NULL, 0);
119 break;
120 case 'P':
121 idProduct = simple_strtoul(optarg, NULL, 0);
122 break;
126 if (argc != optind + 1)
127 return COMMAND_ERROR_USAGE;
129 argstr = argv[optind];
131 if (!idProduct || !idVendor) {
132 printf("productid or vendorid not given\n");
133 return 1;
136 for (n = 0; *argstr; n++) {
137 dfu_alts = xrealloc(dfu_alts, sizeof(*dfu_alts) * (n + 1));
138 if (dfu_do_parse_one(argstr, &endptr, &dfu_alts[n])) {
139 printf("parse error\n");
140 goto out;
142 argstr = endptr;
145 pdata.alts = dfu_alts;
146 pdata.num_alts = n;
148 pdata.manufacturer = manufacturer;
149 pdata.productname = productname;
150 pdata.idVendor = idVendor;
151 pdata.idProduct = idProduct;
153 usb_dfu_register(&pdata);
155 out:
156 while (n) {
157 n--;
158 free(dfu_alts[n].name);
159 free(dfu_alts[n].dev);
161 free(dfu_alts);
162 return 1;
165 static const __maybe_unused char cmd_dfu_help[] =
166 "Usage: dfu [OPTION]... description\n"
167 "start dfu firmware update\n"
168 " -m <str> Manufacturer string (barebox)\n"
169 " -p <str> product string (" CONFIG_BOARDINFO ")\n"
170 " -V <id> vendor id\n"
171 " -P <id> product id\n"
172 "description has the form\n"
173 "device1(name1)[sr],device2(name2)[sr]\n"
174 "where s is for save mode and r for read back of firmware\n";
176 BAREBOX_CMD_START(dfu)
177 .cmd = do_dfu,
178 .usage = "Device firmware update",
179 BAREBOX_CMD_HELP(cmd_dfu_help)
180 BAREBOX_CMD_END