uboot/common/flash.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2000
   4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   5 */
   6
   7/* #define DEBUG */
   8
   9#include <common.h>
  10#include <flash.h>
  11#include <log.h>
  12#include <uuid.h>
  13
  14#include <mtd/cfi_flash.h>
  15
  16extern flash_info_t  flash_info[]; /* info for FLASH chips */
  17
  18/*-----------------------------------------------------------------------
  19 * Functions
  20 */
  21
  22/*-----------------------------------------------------------------------
  23 * Set protection status for monitor sectors
  24 *
  25 * The monitor is always located in the _first_ Flash bank.
  26 * If necessary you have to map the second bank at lower addresses.
  27 */
  28void
  29flash_protect(int flag, ulong from, ulong to, flash_info_t *info)
  30{
  31        ulong b_end;
  32        short s_end;
  33        int i;
  34
  35        /* Do nothing if input data is bad. */
  36        if (!info || info->sector_count == 0 || info->size == 0 || to < from) {
  37                return;
  38        }
  39
  40        s_end = info->sector_count - 1; /* index of last sector */
  41        b_end = info->start[0] + info->size - 1;        /* bank end address */
  42
  43        debug("%s %s: from 0x%08lX to 0x%08lX\n", __func__,
  44              (flag & FLAG_PROTECT_SET) ? "ON" :
  45              (flag & FLAG_PROTECT_CLEAR) ? "OFF" : "???",
  46              from, to);
  47
  48        /* There is nothing to do if we have no data about the flash
  49         * or the protect range and flash range don't overlap.
  50         */
  51        if (info->flash_id == FLASH_UNKNOWN ||
  52            to < info->start[0] || from > b_end) {
  53                return;
  54        }
  55
  56        for (i=0; i<info->sector_count; ++i) {
  57                ulong end;              /* last address in current sect */
  58
  59                end = (i == s_end) ? b_end : info->start[i + 1] - 1;
  60
  61                /* Update protection if any part of the sector
  62                 * is in the specified range.
  63                 */
  64                if (from <= end && to >= info->start[i]) {
  65                        if (flag & FLAG_PROTECT_CLEAR) {
  66#if defined(CONFIG_SYS_FLASH_PROTECTION)
  67                                flash_real_protect(info, i, 0);
  68#else
  69                                info->protect[i] = 0;
  70#endif  /* CONFIG_SYS_FLASH_PROTECTION */
  71                                debug("protect off %d\n", i);
  72                        }
  73                        else if (flag & FLAG_PROTECT_SET) {
  74#if defined(CONFIG_SYS_FLASH_PROTECTION)
  75                                flash_real_protect(info, i, 1);
  76#else
  77                                info->protect[i] = 1;
  78#endif  /* CONFIG_SYS_FLASH_PROTECTION */
  79                                debug("protect on %d\n", i);
  80                        }
  81                }
  82        }
  83}
  84
  85/*-----------------------------------------------------------------------
  86 */
  87
  88flash_info_t *
  89addr2info(ulong addr)
  90{
  91        flash_info_t *info;
  92        int i;
  93
  94        for (i=0, info = &flash_info[0]; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) {
  95                if (info->flash_id != FLASH_UNKNOWN &&
  96                    addr >= info->start[0] &&
  97                    /* WARNING - The '- 1' is needed if the flash
  98                     * is at the end of the address space, since
  99                     * info->start[0] + info->size wraps back to 0.
 100                     * Please don't change this unless you understand this.
 101                     */
 102                    addr <= info->start[0] + info->size - 1) {
 103                        return (info);
 104                }
 105        }
 106
 107        return (NULL);
 108}
 109
 110/*-----------------------------------------------------------------------
 111 * Copy memory to flash.
 112 * Make sure all target addresses are within Flash bounds,
 113 * and no protected sectors are hit.
 114 * Returns:
 115 * ERR_OK          0 - OK
 116 * ERR_TIMEOUT     1 - write timeout
 117 * ERR_NOT_ERASED  2 - Flash not erased
 118 * ERR_PROTECTED   4 - target range includes protected sectors
 119 * ERR_INVAL       8 - target address not in Flash memory
 120 * ERR_ALIGN       16 - target address not aligned on boundary
 121 *                      (only some targets require alignment)
 122 */
 123int
 124flash_write(char *src, ulong addr, ulong cnt)
 125{
 126        int i;
 127        ulong         end        = addr + cnt - 1;
 128        flash_info_t *info_first = addr2info(addr);
 129        flash_info_t *info_last  = addr2info(end);
 130        flash_info_t *info;
 131        __maybe_unused char *src_orig = src;
 132        __maybe_unused char *addr_orig = (char *)addr;
 133        __maybe_unused ulong cnt_orig = cnt;
 134
 135        if (cnt == 0) {
 136                return (ERR_OK);
 137        }
 138
 139        if (!info_first || !info_last) {
 140                return (ERR_INVAL);
 141        }
 142
 143        for (info = info_first; info <= info_last; ++info) {
 144                ulong b_end = info->start[0] + info->size;      /* bank end addr */
 145                short s_end = info->sector_count - 1;
 146                for (i=0; i<info->sector_count; ++i) {
 147                        ulong e_addr = (i == s_end) ? b_end : info->start[i + 1];
 148
 149                        if ((end >= info->start[i]) && (addr < e_addr) &&
 150                            (info->protect[i] != 0) ) {
 151                                return (ERR_PROTECTED);
 152                        }
 153                }
 154        }
 155
 156        /* finally write data to flash */
 157        for (info = info_first; info <= info_last && cnt>0; ++info) {
 158                ulong len;
 159
 160                len = info->start[0] + info->size - addr;
 161                if (len > cnt)
 162                        len = cnt;
 163                if ((i = write_buff(info, (uchar *)src, addr, len)) != 0) {
 164                        return (i);
 165                }
 166                cnt  -= len;
 167                addr += len;
 168                src  += len;
 169        }
 170
 171#if defined(CONFIG_FLASH_VERIFY)
 172        if (memcmp(src_orig, addr_orig, cnt_orig)) {
 173                printf("\nVerify failed!\n");
 174                return ERR_PROG_ERROR;
 175        }
 176#endif /* CONFIG_SYS_FLASH_VERIFY_AFTER_WRITE */
 177
 178        return (ERR_OK);
 179}
 180
 181/*-----------------------------------------------------------------------
 182 */
 183
 184void flash_perror(int err)
 185{
 186        switch (err) {
 187        case ERR_OK:
 188                break;
 189        case ERR_TIMEOUT:
 190                puts ("Timeout writing to Flash\n");
 191                break;
 192        case ERR_NOT_ERASED:
 193                puts ("Flash not Erased\n");
 194                break;
 195        case ERR_PROTECTED:
 196                puts ("Can't write to protected Flash sectors\n");
 197                break;
 198        case ERR_INVAL:
 199                puts ("Outside available Flash\n");
 200                break;
 201        case ERR_ALIGN:
 202                puts ("Start and/or end address not on sector boundary\n");
 203                break;
 204        case ERR_UNKNOWN_FLASH_VENDOR:
 205                puts ("Unknown Vendor of Flash\n");
 206                break;
 207        case ERR_UNKNOWN_FLASH_TYPE:
 208                puts ("Unknown Type of Flash\n");
 209                break;
 210        case ERR_PROG_ERROR:
 211                puts ("General Flash Programming Error\n");
 212                break;
 213        case ERR_ABORTED:
 214                puts("Flash Programming Aborted\n");
 215                break;
 216        default:
 217                printf ("%s[%d] FIXME: rc=%d\n", __FILE__, __LINE__, err);
 218                break;
 219        }
 220}
 221