📄 flash.c
字号:
} /* erase */ report(" erase flash [0x%08lx ~ 0x%08lx]\n", addr, addr+size-1); if (size) do { bool res; report("\r erase at 0x%08lx", addr); res = iflash_erase_block((void *)addr); if (!res){ failed("\n error : failed to erase block. check lock.\n"); return false; } addr += flash->blksize; size -= flash->blksize; } while (size > 0); report("\r erase at 0x%08lx : done\n", addr); return true;invalid : erase_usage(); return false;}static void erase_usage(void){ usage_format("erase {loader/kernel/root/ramdisk}", "erase flash blocks of area"); //usage_format("erase addr [size]", "erase one flash block"); return;}static bool do_lock(int argc, char **argv){ bool res; ulong addr, size, tmp; if (argc == 2){ struct map *mp; if (!strcmp(argv[1], "all")){ /* lock all */ addr = flash->base; size = flash->size; } else if ((mp = find_map(argv[1]))){ /* lock {loader/kernel/ramdisk/root} */ addr = mp->sramb; size = mp->maxs; } else if (strtoul(argv[1], &tmp, 16)){ /* lock address */ addr = tmp; size = flash->blksize; } else goto invalid; } else if (argc == 3){ res = strtoul(argv[1], &tmp, 16); if (!res) goto invalid; addr = tmp; res = strtoul(argv[2], &tmp, 16); if (!res) goto invalid; size = tmp; } else goto invalid; /* check address and size */ if (addr % flash->blksize){ failed(" error : address is not base of flash block.(blksize=%lx)\n", flash->blksize); return false; } if (size % flash->blksize){ failed(" error : size is not multifly of block size.(blksize=%lx)\n", flash->blksize); return false; } /* lock */ report(" lock flash [0x%08lx ~ 0x%08lx]\n", addr, addr+size-1); if (size) do { bool res; res = iflash_lock_block((void *)addr); if (!res){ failed(" error : lock block.[0x%08lx]\n", addr); return false; } addr += flash->blksize; size -= flash->blksize; } while (size); return true;invalid : lock_usage(); return false;}static void lock_usage(void){ usage_format("lock {all/loader/kernel/root/ramdisk}", "set flash lock-bit of area"); usage_format("lock addr [size]", "set flash lock-bit of one block"); return;}static bool do_unlock(int argc, char **argv){ bool res; ulong addr, size, tmp; if (argc == 2){ struct map *mp; if (!strcmp(argv[1], "all")){ /* unlock all */ addr = flash->base; size = flash->size; } else if ((mp = find_map(argv[1]))){ /* unlock {loader/kernel/ramdisk/root} */ addr = mp->sramb; size = mp->maxs; } else if (strtoul(argv[1], &tmp, 16)){ /* unlock address */ addr = tmp; size = flash->blksize; } else goto invalid; } else if (argc == 3){ res = strtoul(argv[1], &tmp, 16); if (!res) goto invalid; addr = tmp; res = strtoul(argv[2], &tmp, 16); if (!res) goto invalid; size = tmp; } else goto invalid; /* check address and size */ if (addr % flash->blksize){ failed(" error : address is not base of flash block.(blksize=%lx)\n", flash->blksize); return false; } if (size % flash->blksize){ failed(" error : size is not multifly of block size.(blksize=%lx)\n", flash->blksize); return false; } /* unlock */ report(" unlock flash [0x%08lx ~ 0x%08lx]\n", addr, addr+size-1); if (size) do { bool res; res = iflash_unlock_block((void *)addr); if (!res){ failed(" error : unlock block.[0x%08lx]\n", addr); return false; } addr += flash->blksize; size -= flash->blksize; } while (size); return true;invalid : unlock_usage(); return false;}static void unlock_usage(void){ usage_format("unlock addr [size]", "clear lock-bit of one block"); return;}extern bool flash_write(void *dest, const void *src, uint cnt){ bool res; uchar buff_base[flash->blksize]; ulong buff_offset; ulong write_cnt; void *block_base; const void *copyfrom; res = true; while (cnt > 0){ block_base = (void *)((ulong)dest & ~(flash->blksize-1)); /* block base in flash */ buff_offset = (ulong)dest & (flash->blksize-1); /* offset */ write_cnt = (buff_offset + cnt <= flash->blksize ? cnt : flash->blksize - buff_offset); if (!buff_offset && write_cnt == flash->blksize){ copyfrom = src; } else { memcpy(buff_base, block_base, flash->blksize); /* backup to buff_base */ memcpy(buff_base+buff_offset, src, write_cnt); /* overwrite will be changed */ copyfrom = buff_base; } res = iflash_erase_block(block_base); /* erase block */ if (!res) break; res = iflash_write_block(block_base, copyfrom); /* write to flash block */ if (!res) break; res = blkcmp(block_base, copyfrom, flash->blksize) ? false : true; if (!res) break; dest += write_cnt; /* for next */ src += write_cnt; cnt -= write_cnt; } return res;}static inline void write_data(void *dest, const void *src, int count){ if (flash->buswidth == 1){ uint8 *d=dest; const uint8 *s=src; while (count--) *d++ = *s++; } else if (flash->buswidth == 2){ uint16 *d=dest; const uint16 *s=src; while (count--) *d++ = *s++; } else if (flash->buswidth == 4){ uint32 *d=dest; const uint32 *s=src; while (count--) *d++ = *s++; } return;}static bool iflash_write_block(void *dest, const void *src){ bool res; int i, count; /* unlock block */ res = iflash_unlock_block(dest); if (!res) return false; /* write block */ count = flash->buff_size / flash->buswidth; for (i=0; i < flash->blksize/flash->buff_size; i++){ iflash_write_cmd(dest, flash->buswidth, WRITE_BUF); wait_while_busy(dest); iflash_write_cmd(dest, flash->buswidth, count - 1); write_data(dest, src, count); iflash_write_cmd(dest, flash->buswidth, WRITE_BUF_COMFIRM); res = iflash_status_check(dest, ACT_WRITE_BUF); if (!res) return false; dest = (uchar *)dest + flash->buff_size; src = (uchar *)src + flash->buff_size; } return true;}static inline bool check_erased(void *addr){ int count; uint32 *p = addr; count = flash->blksize / sizeof(uint32) / 4; do { if (*p++ != 0xFFFFFFFF) return false; if (*p++ != 0xFFFFFFFF) return false; if (*p++ != 0xFFFFFFFF) return false; if (*p++ != 0xFFFFFFFF) return false; } while (--count); return true;}static bool iflash_erase_block(void *addr){ bool res; if ((ulong)addr & (flash->blksize-1)) return false; /* unlock block */ res = iflash_unlock_block(addr); if (!res) return false; res = check_erased(addr); if (res) return true; /* erase block */ iflash_write_cmd(addr, flash->buswidth, ERASE_SETUP); iflash_write_cmd(addr, flash->buswidth, ERASE_CONFIRM); return iflash_status_check(addr, ACT_ERASE);}static bool iflash_lock_block(void *addr){ if ((ulong)addr % flash->blksize) return false; iflash_write_cmd(addr, flash->buswidth, FLASH_SETUP); iflash_write_cmd(addr, flash->buswidth, BLOCK_LOCK_BIT_SET); return iflash_status_check(addr, ACT_LOCK);}static bool iflash_unlock_block(void *addr){ iflash_write_cmd(addr, flash->buswidth, FLASH_SETUP); iflash_write_cmd(addr, flash->buswidth, BLOCK_LOCK_BIT_CLEAR); return iflash_status_check(addr, ACT_UNLOCK);}static void iflash_write_cmd(void *addr, int buswidth, int c){ if (buswidth == 1) *(uint8 *)addr = (uint8)c; else if (buswidth == 2) *(uint16 *)addr = (uint16)c; else if (buswidth == 4) *(uint32 *)addr = (uint32)c | ((uint32)c << 16); return;}static bool iflash_status_check(void *addr, enum action which){ uint32 status=0, busy; iflash_write_cmd(addr, flash->buswidth, STATUS_READ); if (flash->buswidth == 2){ busy = (uint16)STATUS_BUSY; while (1){ status = readw(addr); if ((status & busy) == busy) break; } } else if (flash->buswidth == 4){ busy = (uint32)STATUS_BUSY; while (1){ status = readl(addr); if ((status & busy) == busy) break; } } else return false; status &= ~STATUS_BUSY; if (status) iflash_write_cmd(addr, flash->buswidth, STATUS_CLEAR); iflash_write_cmd(addr, flash->buswidth, READ_ARRAY); return status ? false : true;}static void wait_while_busy(void *addr){ uint32 busy; if (flash->buswidth == 2){ busy = (uint16)STATUS_BUSY; while ((readw(addr) & busy) != busy); } else if (flash->buswidth == 4){ busy = (uint32)STATUS_BUSY; while ((readl(addr) & busy) != busy); } return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -