1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3 * dfu.h - DFU flashable area description
4 *
5 * Copyright (C) 2012 Samsung Electronics
6 * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
7 * Lukasz Majewski <l.majewski@samsung.com>
8 */
9
10 #ifndef __DFU_ENTITY_H_
11 #define __DFU_ENTITY_H_
12
13 #include <linux/errno.h>
14 #include <linux/list.h>
15 #include <mmc.h>
16 #include <spi_flash.h>
17 #include <linux/usb/composite.h>
18
19 enum dfu_device_type {
20 DFU_DEV_MMC = 1,
21 DFU_DEV_ONENAND,
22 DFU_DEV_NAND,
23 DFU_DEV_RAM,
24 DFU_DEV_SF,
25 DFU_DEV_MTD,
26 DFU_DEV_VIRT,
27 DFU_DEV_SCSI,
28 };
29
30 enum dfu_layout {
31 DFU_RAW_ADDR = 1,
32 DFU_FS_FAT,
33 DFU_FS_EXT2,
34 DFU_FS_EXT3,
35 DFU_FS_EXT4,
36 DFU_RAM_ADDR,
37 DFU_SKIP,
38 DFU_SCRIPT,
39 };
40
41 enum dfu_op {
42 DFU_OP_READ = 1,
43 DFU_OP_WRITE,
44 DFU_OP_SIZE,
45 };
46
47 struct mmc_internal_data {
48 int dev_num;
49
50 /* RAW programming */
51 unsigned int lba_start;
52 unsigned int lba_size;
53 unsigned int lba_blk_size;
54
55 /* eMMC HW partition access */
56 int hw_partition;
57
58 /* FAT/EXT */
59 unsigned int dev;
60 unsigned int part;
61 };
62
63 struct mtd_internal_data {
64 struct mtd_info *info;
65
66 /* RAW programming */
67 u64 start;
68 u64 size;
69 /* for ubi partition */
70 unsigned int ubi;
71 };
72
73 struct nand_internal_data {
74 /* RAW programming */
75 u64 start;
76 u64 size;
77
78 unsigned int dev;
79 unsigned int part;
80 /* for nand/ubi use */
81 unsigned int ubi;
82 };
83
84 struct ram_internal_data {
85 unsigned long start;
86 unsigned int size;
87 };
88
89 struct sf_internal_data {
90 struct spi_flash *dev;
91
92 /* RAW programming */
93 u64 start;
94 u64 size;
95 /* for sf/ubi use */
96 unsigned int ubi;
97 };
98
99 struct virt_internal_data {
100 int dev_num;
101 };
102
103 struct scsi_internal_data {
104 int lun;
105
106 /* RAW programming */
107 unsigned int lba_start;
108 unsigned int lba_size;
109 unsigned int lba_blk_size;
110
111 /* FAT/EXT */
112 unsigned int dev; // Always 0???
113 unsigned int part;
114 };
115
116 #if defined(CONFIG_DFU_NAME_MAX_SIZE)
117 #define DFU_NAME_SIZE CONFIG_DFU_NAME_MAX_SIZE
118 #else
119 #define DFU_NAME_SIZE 32
120 #endif
121 #ifndef DFU_DEFAULT_POLL_TIMEOUT
122 #define DFU_DEFAULT_POLL_TIMEOUT 0
123 #endif
124 #ifndef DFU_MANIFEST_POLL_TIMEOUT
125 #define DFU_MANIFEST_POLL_TIMEOUT DFU_DEFAULT_POLL_TIMEOUT
126 #endif
127
128 struct dfu_entity {
129 char name[DFU_NAME_SIZE];
130 int alt;
131 void *dev_private;
132 enum dfu_device_type dev_type;
133 enum dfu_layout layout;
134 unsigned long max_buf_size;
135
136 union {
137 struct mmc_internal_data mmc;
138 struct mtd_internal_data mtd;
139 struct nand_internal_data nand;
140 struct ram_internal_data ram;
141 struct sf_internal_data sf;
142 struct virt_internal_data virt;
143 struct scsi_internal_data scsi;
144 } data;
145
146 int (*get_medium_size)(struct dfu_entity *dfu, u64 *size);
147
148 int (*read_medium)(struct dfu_entity *dfu,
149 u64 offset, void *buf, long *len);
150
151 int (*write_medium)(struct dfu_entity *dfu,
152 u64 offset, void *buf, long *len);
153
154 int (*flush_medium)(struct dfu_entity *dfu);
155 unsigned int (*poll_timeout)(struct dfu_entity *dfu);
156
157 void (*free_entity)(struct dfu_entity *dfu);
158
159 struct list_head list;
160
161 /* on the fly state */
162 u32 crc;
163 u64 offset;
164 int i_blk_seq_num;
165 u8 *i_buf;
166 u8 *i_buf_start;
167 u8 *i_buf_end;
168 u64 r_left;
169 long b_left;
170
171 u32 bad_skip; /* for nand use */
172
173 unsigned int inited:1;
174 };
175
176 extern struct list_head dfu_list;
177
178 #ifdef CONFIG_SET_DFU_ALT_INFO
179 /**
180 * set_dfu_alt_info() - set dfu_alt_info environment variable
181 *
182 * If CONFIG_SET_DFU_ALT_INFO=y, this board specific function is called to set
183 * environment variable dfu_alt_info.
184 *
185 * @interface: dfu interface, e.g. "mmc" or "nand"
186 * @devstr: device number as string
187 */
188 void set_dfu_alt_info(char *interface, char *devstr);
189 #endif
190
191 /**
192 * dfu_alt_init() - initialize buffer for dfu entities
193 *
194 * @num: number of entities
195 * @dfu: on return allocated buffer
196 * Return: 0 on success
197 */
198 int dfu_alt_init(int num, struct dfu_entity **dfu);
199
200 /**
201 * dfu_alt_add() - add alternate to dfu entity buffer
202 *
203 * @dfu: dfu entity
204 * @interface: dfu interface, e.g. "mmc" or "nand"
205 * @devstr: device number as string
206 * @s: string description of alternate
207 * Return: 0 on success
208 */
209 int dfu_alt_add(struct dfu_entity *dfu, char *interface, char *devstr, char *s);
210
211 /**
212 * dfu_config_entities() - initialize dfu entitities from envirionment
213 *
214 * Initialize the list of dfu entities from environment variable dfu_alt_info.
215 * The list must be freed by calling dfu_free_entities(). This function bypasses
216 * set_dfu_alt_info(). So typically you should use dfu_init_env_entities()
217 * instead.
218 *
219 * See function :c:func:`dfu_free_entities`
220 * See function :c:func:`dfu_init_env_entities`
221 *
222 * @s: string with alternates
223 * @interface: interface, e.g. "mmc" or "nand"
224 * @devstr: device number as string
225 * Return: 0 on success, a negative error code otherwise
226 */
227 int dfu_config_entities(char *s, char *interface, char *devstr);
228
229 /**
230 * dfu_free_entities() - free the list of dfu entities
231 *
232 * Free the internal list of dfu entities.
233 *
234 * See function :c:func:`dfu_init_env_entities`
235 */
236 void dfu_free_entities(void);
237
238 /**
239 * dfu_show_entities() - print DFU alt settings list
240 */
241 void dfu_show_entities(void);
242
243 /**
244 * dfu_get_alt_number() - get number of alternates
245 *
246 * Return: number of alternates in the dfu entities list
247 */
248 int dfu_get_alt_number(void);
249
250 /**
251 * dfu_get_dev_type() - get string representation for dfu device type
252 *
253 * @type: device type
254 * Return: string representation for device type
255 */
256 const char *dfu_get_dev_type(enum dfu_device_type type);
257
258 /**
259 * dfu_get_layout() - get string describing layout
260 *
261 * Internally layouts are represented by enum dfu_device_type values. This
262 * function translates an enum value to a human readable string, e.g. DFU_FS_FAT
263 * is translated to "FAT".
264 *
265 * @layout: layout
266 * Result: string representation for the layout
267 */
268 const char *dfu_get_layout(enum dfu_layout layout);
269
270 /**
271 * dfu_get_entity() - get dfu entity for an alternate id
272 *
273 * @alt: alternate id
274 * Return: dfu entity
275 */
276 struct dfu_entity *dfu_get_entity(int alt);
277
278 char *dfu_extract_token(char** e, int *n);
279
280 /**
281 * dfu_get_alt() - get alternate id for filename
282 *
283 * Environment variable dfu_alt_info defines the write destinations (alternates)
284 * for different filenames. This function get the index of the alternate for
285 * a filename. If an absolute filename is provided (starting with '/'), the
286 * directory path is ignored.
287 *
288 * @name: filename
289 * Return: id of the alternate or negative error number (-ENODEV)
290 */
291 int dfu_get_alt(char *name);
292
293 /**
294 * dfu_init_env_entities() - initialize dfu entitities from envirionment
295 *
296 * Initialize the list of dfu entities from environment variable dfu_alt_info.
297 * The list must be freed by calling dfu_free_entities().
298 * @interface and @devstr are used to select the relevant set of alternates
299 * from environment variable dfu_alt_info.
300 *
301 * If environment variable dfu_alt_info specifies the interface and the device,
302 * use NULL for @interface and @devstr.
303 *
304 * See function :c:func:`dfu_free_entities`
305 *
306 * @interface: interface, e.g. "mmc" or "nand"
307 * @devstr: device number as string
308 * Return: 0 on success, a negative error code otherwise
309 */
310 int dfu_init_env_entities(char *interface, char *devstr);
311
312 unsigned char *dfu_get_buf(struct dfu_entity *dfu);
313 unsigned char *dfu_free_buf(void);
314 unsigned long dfu_get_buf_size(void);
315 bool dfu_usb_get_reset(void);
316
317 #ifdef CONFIG_DFU_TIMEOUT
318 unsigned long dfu_get_timeout(void);
319 void dfu_set_timeout(unsigned long);
320 #endif
321
322 /**
323 * dfu_read() - read from dfu entity
324 *
325 * The block sequence number @blk_seq_num is a 16 bit counter that must be
326 * incremented with each call for the same dfu entity @de.
327 *
328 * @de: dfu entity
329 * @buf: buffer
330 * @size: size of buffer
331 * @blk_seq_num: block sequence number
332 * Return: 0 for success, -1 for error
333 */
334 int dfu_read(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
335
336 /**
337 * dfu_write() - write to dfu entity
338 *
339 * Write the contents of a buffer @buf to the dfu entity @de. After writing
340 * the last block call dfu_flush(). If a file is already loaded completely
341 * into memory it is preferable to use dfu_write_from_mem_addr() which takes
342 * care of blockwise transfer and flushing.
343 *
344 * The block sequence number @blk_seq_num is a 16 bit counter that must be
345 * incremented with each call for the same dfu entity @de.
346 *
347 * See function :c:func:`dfu_flush`
348 * See function :c:func:`dfu_write_from_mem_addr`
349 *
350 * @de: dfu entity
351 * @buf: buffer
352 * @size: size of buffer
353 * @blk_seq_num: block sequence number
354 * Return: 0 for success, -1 for error
355 */
356 int dfu_write(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
357
358 /**
359 * dfu_flush() - flush to dfu entity
360 *
361 * This function has to be called after writing the last block to the dfu
362 * entity @de.
363 *
364 * The block sequence number @blk_seq_num is a 16 bit counter that must be
365 * incremented with each call for the same dfu entity @de.
366 *
367 * See function :c:func:`dfu_write`
368 *
369 * @de: dfu entity
370 * @buf: ignored
371 * @size: ignored
372 * @blk_seq_num: block sequence number of last write - ignored
373 * Return: 0 for success, -1 for error
374 */
375 int dfu_flush(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
376
377 /**
378 * dfu_initiated_callback() - weak callback called on DFU transaction start
379 *
380 * It is a callback function called by DFU stack when a DFU transaction is
381 * initiated. This function allows to manage some board specific behavior on
382 * DFU targets.
383 *
384 * @dfu: pointer to the dfu_entity, which should be initialized
385 */
386 void dfu_initiated_callback(struct dfu_entity *dfu);
387
388 /**
389 * dfu_flush_callback() - weak callback called at the end of the DFU write
390 *
391 * It is a callback function called by DFU stack after DFU manifestation.
392 * This function allows to manage some board specific behavior on DFU targets
393 *
394 * @dfu: pointer to the dfu_entity, which should be flushed
395 */
396 void dfu_flush_callback(struct dfu_entity *dfu);
397
398 /**
399 * dfu_error_callback() - weak callback called at the DFU write error
400 *
401 * It is a callback function called by DFU stack after DFU write error.
402 * This function allows to manage some board specific behavior on DFU targets
403 *
404 * @dfu: pointer to the dfu_entity which cause the error
405 * @msg: the message of the error
406 */
407 void dfu_error_callback(struct dfu_entity *dfu, const char *msg);
408
409 int dfu_transaction_initiate(struct dfu_entity *dfu, bool read);
410 void dfu_transaction_cleanup(struct dfu_entity *dfu);
411
412 /*
413 * dfu_defer_flush - pointer to store dfu_entity for deferred flashing.
414 * It should be NULL when not used.
415 */
416 extern struct dfu_entity *dfu_defer_flush;
417
418 /**
419 * dfu_get_defer_flush() - get current value of dfu_defer_flush pointer
420 *
421 * Return: value of the dfu_defer_flush pointer
422 */
dfu_get_defer_flush(void)423 static inline struct dfu_entity *dfu_get_defer_flush(void)
424 {
425 return dfu_defer_flush;
426 }
427
428 /**
429 * dfu_set_defer_flush() - set the dfu_defer_flush pointer
430 *
431 * @dfu: pointer to the dfu_entity, which should be written
432 */
dfu_set_defer_flush(struct dfu_entity * dfu)433 static inline void dfu_set_defer_flush(struct dfu_entity *dfu)
434 {
435 dfu_defer_flush = dfu;
436 }
437
438 /**
439 * dfu_write_from_mem_addr() - write data from memory to DFU managed medium
440 *
441 * This function adds support for writing data starting from fixed memory
442 * address (like $loadaddr) to dfu managed medium (e.g. NAND, MMC, file system)
443 *
444 * @dfu: dfu entity to which we want to store data
445 * @buf: fixed memory address from where data starts
446 * @size: number of bytes to write
447 *
448 * Return: 0 on success, other value on failure
449 */
450 int dfu_write_from_mem_addr(struct dfu_entity *dfu, void *buf, int size);
451
452 /* Device specific */
453 /* Each entity has 5 arguments in maximum. */
454 #define DFU_MAX_ENTITY_ARGS 5
455
456 #if CONFIG_IS_ENABLED(DFU_MMC)
457 extern int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr,
458 char **argv, int argc);
459 #else
dfu_fill_entity_mmc(struct dfu_entity * dfu,char * devstr,char ** argv,int argc)460 static inline int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr,
461 char **argv, int argc)
462 {
463 puts("MMC support not available!\n");
464 return -1;
465 }
466 #endif
467
468 #if CONFIG_IS_ENABLED(DFU_NAND)
469 extern int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr,
470 char **argv, int argc);
471 #else
dfu_fill_entity_nand(struct dfu_entity * dfu,char * devstr,char ** argv,int argc)472 static inline int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr,
473 char **argv, int argc)
474 {
475 puts("NAND support not available!\n");
476 return -1;
477 }
478 #endif
479
480 #if CONFIG_IS_ENABLED(DFU_RAM)
481 extern int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr,
482 char **argv, int argc);
483 #else
dfu_fill_entity_ram(struct dfu_entity * dfu,char * devstr,char ** argv,int argc)484 static inline int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr,
485 char **argv, int argc)
486 {
487 puts("RAM support not available!\n");
488 return -1;
489 }
490 #endif
491
492 #if CONFIG_IS_ENABLED(DFU_SF)
493 extern int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr,
494 char **argv, int argc);
495 #else
dfu_fill_entity_sf(struct dfu_entity * dfu,char * devstr,char ** argv,int argc)496 static inline int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr,
497 char **argv, int argc)
498 {
499 puts("SF support not available!\n");
500 return -1;
501 }
502 #endif
503
504 #if CONFIG_IS_ENABLED(DFU_MTD)
505 extern int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr,
506 char **argv, int argc);
507 #else
dfu_fill_entity_mtd(struct dfu_entity * dfu,char * devstr,char ** argv,int argc)508 static inline int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr,
509 char **argv, int argc)
510 {
511 puts("MTD support not available!\n");
512 return -1;
513 }
514 #endif
515
516 #if CONFIG_IS_ENABLED(DFU_VIRT)
517 int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr,
518 char **argv, int argc);
519 int dfu_write_medium_virt(struct dfu_entity *dfu, u64 offset,
520 void *buf, long *len);
521 int dfu_get_medium_size_virt(struct dfu_entity *dfu, u64 *size);
522 int dfu_read_medium_virt(struct dfu_entity *dfu, u64 offset,
523 void *buf, long *len);
524 #else
dfu_fill_entity_virt(struct dfu_entity * dfu,char * devstr,char ** argv,int argc)525 static inline int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr,
526 char **argv, int argc)
527 {
528 puts("VIRT support not available!\n");
529 return -1;
530 }
531 #endif
532
533 #if CONFIG_IS_ENABLED(DFU_SCSI)
534 int dfu_fill_entity_scsi(struct dfu_entity *dfu, char *devstr,
535 char **argv, int argc);
536 #else
dfu_fill_entity_scsi(struct dfu_entity * dfu,char * devstr,char ** argv,int argc)537 static inline int dfu_fill_entity_scsi(struct dfu_entity *dfu, char *devstr,
538 char **argv, int argc)
539 {
540 puts("SCSI support not available!\n");
541 return -1;
542 }
543 #endif
544
545 extern bool dfu_reinit_needed;
546 extern bool dfu_alt_info_changed;
547
548 #if CONFIG_IS_ENABLED(DFU_WRITE_ALT)
549 /**
550 * dfu_write_by_name() - write data to DFU medium
551 * @dfu_entity_name: Name of DFU entity to write
552 * @addr: Address of data buffer to write
553 * @len: Number of bytes
554 * @interface: Destination DFU medium (e.g. "mmc")
555 * @devstring: Instance number of destination DFU medium (e.g. "1")
556 *
557 * This function is storing data received on DFU supported medium which
558 * is specified by @dfu_entity_name.
559 *
560 * Return: 0 - on success, error code - otherwise
561 */
562 int dfu_write_by_name(char *dfu_entity_name, void *addr,
563 unsigned int len, char *interface, char *devstring);
564
565 /**
566 * dfu_write_by_alt() - write data to DFU medium
567 * @dfu_alt_num: DFU alt setting number
568 * @addr: Address of data buffer to write
569 * @len: Number of bytes
570 * @interface: Destination DFU medium (e.g. "mmc")
571 * @devstring: Instance number of destination DFU medium (e.g. "1")
572 *
573 * This function is storing data received on DFU supported medium which
574 * is specified by @dfu_alt_name.
575 *
576 * Return: 0 - on success, error code - otherwise
577 */
578 int dfu_write_by_alt(int dfu_alt_num, void *addr, unsigned int len,
579 char *interface, char *devstring);
580 #else
dfu_write_by_name(char * dfu_entity_name,void * addr,unsigned int len,char * interface,char * devstring)581 static inline int dfu_write_by_name(char *dfu_entity_name, void *addr,
582 unsigned int len, char *interface,
583 char *devstring)
584 {
585 puts("write support for DFU not available!\n");
586 return -ENOSYS;
587 }
588
dfu_write_by_alt(int dfu_alt_num,void * addr,unsigned int len,char * interface,char * devstring)589 static inline int dfu_write_by_alt(int dfu_alt_num, void *addr,
590 unsigned int len, char *interface,
591 char *devstring)
592 {
593 puts("write support for DFU not available!\n");
594 return -ENOSYS;
595 }
596 #endif
597
598 int dfu_add(struct usb_configuration *c);
599 #endif /* __DFU_ENTITY_H_ */
600