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