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