📄 u-boot代码记录.c
字号:
Void flash_protect (int flag, ulong from, ulong to, flash_info_t *info)
{
ulong b_end = info->start[0] + info->size - 1; /* flash的最后地址 */
short s_end = info->sector_count - 1; /* 扇区的最后一个index */
int i;
debug ("flash_protect %s: from 0x%08lX to 0x%08lX\n",
(flag & FLAG_PROTECT_SET) ? "ON" :(flag & FLAG_PROTECT_CLEAR) ? "OFF" : "???",
from, to);
/* Do nothing if input data is bad. */
if (info->sector_count == 0 || info->size == 0 || to < from)
{
return;
}
/* There is nothing to do if we have no data about the flash
* or the protect range and flash range don't overlap.
*/
if (info->flash_id == FLASH_UNKNOWN ||to < info->start[0] || from > b_end)
{
return;
}
for (i=0; i<info->sector_count; ++i)
{
ulong end; /* last address in current sect */
end = (i == s_end) ? b_end : info->start[i + 1] - 1; //条件表达式当i=0时得到的第一个扇区的最后地址
/* Update protection if any part of the sector
* is in the specified range.
*/
if (from <= end && to >= info->start[i])
{
if (flag & FLAG_PROTECT_CLEAR)
{
#if defined(CFG_FLASH_PROTECTION)
flash_real_protect(info, i, 0);
#else
info->protect[i] = 0;
#endif /* CFG_FLASH_PROTECTION */
debug ("protect off %d\n", i);
}
else if (flag & FLAG_PROTECT_SET)
{
#if defined(CFG_FLASH_PROTECTION)
flash_real_protect(info, i, 1);
#else
info->protect[i] = 1;
#endif /* CFG_FLASH_PROTECTION */
debug ("protect on %d\n", i);
}
}
}
}
void env_relocate (void)
{
DEBUGF ("%s[%d] offset = 0x%lx\n", __FUNCTION__,__LINE__,gd->reloc_off);
#ifdef CONFIG_AMIGAONEG3SE
enable_nvram();
#endif
#ifdef ENV_IS_EMBEDDED
/*
* The environment buffer is embedded with the text segment,
* just relocate the environment pointer
*/
env_ptr = (env_t *)((ulong)env_ptr + gd->reloc_off);
DEBUGF ("%s[%d] embedded ENV at %p\n", __FUNCTION__,__LINE__,env_ptr);
#else
/*
* We must allocate a buffer for the environment
*/
env_ptr = (env_t *)malloc (CFG_ENV_SIZE);
DEBUGF ("%s[%d] malloced ENV at %p\n", __FUNCTION__,__LINE__,env_ptr);
#endif
/*
* After relocation to RAM, we can always use the "memory" functions
*/
env_get_char = env_get_char_memory;
if (gd->env_valid == 0)
{
#if defined(CONFIG_GTH) || defined(CFG_ENV_IS_NOWHERE) /* Environment not changable */
puts ("Using default environment\n\n");
#else
puts ("*** Warning - bad CRC, using default environment\n\n");
SHOW_BOOT_PROGRESS (-1);
#endif
if (sizeof(default_environment) > ENV_SIZE)
{
puts ("*** Error - default environment is too large\n\n");
return;
}
memset (env_ptr, 0, sizeof(env_t));
memcpy (env_ptr->data,
default_environment,
sizeof(default_environment));
#ifdef CFG_REDUNDAND_ENVIRONMENT
env_ptr->flags = 0xFF;
#endif
env_crc_update ();
gd->env_valid = 1;
}
else
{
env_relocate_spec ();
}
gd->env_addr = (ulong)&(env_ptr->data);
#ifdef CONFIG_AMIGAONEG3SE
disable_nvram();
#endif
}
/***************************************************************************
* find command table entry for a command
*/
cmd_tbl_t *find_cmd (const char *cmd)
{
cmd_tbl_t *cmdtp;
cmd_tbl_t *cmdtp_temp = &__u_boot_cmd_start; /*Init value */
const char *p;
int len;
int n_found = 0;
/*
* Some commands allow length modifiers (like "cp.b");
* compare command name only until first dot.
*/
len = ((p = strchr(cmd, '.')) == NULL) ? strlen (cmd) : (p - cmd);
for (cmdtp = &__u_boot_cmd_start;cmdtp != &__u_boot_cmd_end; cmdtp++)
{
if (strncmp (cmd, cmdtp->name, len) == 0)
{
if (len == strlen (cmdtp->name))
return cmdtp; /* full match */
cmdtp_temp = cmdtp; /* abbreviated command ? */
n_found++;
}
}
if (n_found == 1)
{ /* exactly one match */
return cmdtp_temp;
}
return NULL; /* not found or ambiguous command */
}
int do_flerase (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
flash_info_t *info;
ulong bank, addr_first, addr_last;
int n, sect_first, sect_last;
#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
struct mtd_device *dev;
struct part_info *part;
u8 dev_type, dev_num, pnum;
#endif
int rcode = 0;
if (argc < 2) //当命令行参数小于2时 输出使用说明
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
if (strcmp(argv[1], "all") == 0) //当第2个参数是 all的时候 搽掉整个bank
{
for (bank=1; bank<=CFG_MAX_FLASH_BANKS; ++bank)
{
printf ("Erase Flash Bank # %ld ", bank);
info = &flash_info[bank-1];
rcode = flash_erase (info, 0, info->sector_count-1);
}
return rcode;
}
///////////////////////////如果参数的个数大于或则等于2//////////////////////////////////////////
if ((n = abbrev_spec(argv[1], &info, §_first, §_last)) != 0)
{
if (n < 0)
{
puts ("Bad sector specification\n");
return 1;
}
printf ("Erase Flash Sectors %d-%d in Bank # %d ",sect_first, sect_last, (info-flash_info)+1);
rcode = flash_erase(info, sect_first, sect_last);
return rcode;
}
if (argc != 3) //如果参数不为3
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
if (strcmp(argv[1], "bank") == 0)
{
bank = simple_strtoul(argv[2], NULL, 16);
if ((bank < 1) || (bank > CFG_MAX_FLASH_BANKS))
{
printf ("Only FLASH Banks # 1 ... # %d supported\n",
CFG_MAX_FLASH_BANKS);
return 1;
}
printf ("Erase Flash Bank # %ld ", bank);
info = &flash_info[bank-1];
rcode = flash_erase (info, 0, info->sector_count-1);
return rcode;
}
if (addr_spec(argv[1], argv[2], &addr_first, &addr_last) < 0)
{
printf ("Bad address format\n");
return 1;
}
if (addr_first >= addr_last)
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
rcode = flash_sect_erase(addr_first, addr_last);//addr_first,和addr_last得到的是十进制的物理地址
return rcode;
}
int flash_sect_erase (ulong addr_first, ulong addr_last)
{
flash_info_t *info;
ulong bank;
#ifdef CFG_MAX_FLASH_BANKS_DETECT
int s_first[CFG_MAX_FLASH_BANKS_DETECT], s_last[CFG_MAX_FLASH_BANKS_DETECT];
#else
int s_first[CFG_MAX_FLASH_BANKS], s_last[CFG_MAX_FLASH_BANKS];//定义两个数组
#endif
int erased = 0;
int planned;
int rcode = 0;
rcode = flash_fill_sect_ranges (addr_first, addr_last,s_first, s_last, &planned );//planned返回的是扇区的个数
if (planned && (rcode == 0)) //只有要擦除的地址符合扇区边界的要求就可以执行
{
for (bank=0,info=&flash_info[0];(bank < CFG_MAX_FLASH_BANKS) && (rcode == 0);++bank, ++info)
{
if (s_first[bank]>=0)
{
erased += s_last[bank] - s_first[bank] + 1;
debug ("Erase Flash from 0x%08lx to 0x%08lx ""in Bank # %ld ",info->start[s_first[bank]],(s_last[bank] == info->sector_count) ?info->start[0] + info->size - 1:info->start[s_last[bank]+1] - 1,bank+1);
rcode = flash_erase (info, s_first[bank], s_last[bank]); //传递进去的是扇区的索引,从哪个扇区到那个扇区
}
}
printf ("Erased %d sectors\n", erased); //打印出擦除扇区的个数
}
else if (rcode == 0)
{
puts ("Error: start and/or end address"
" not on sector boundary\n");
rcode = 1;
}
return rcode;
}
/*
* The user interface starts numbering for Flash banks with 1
* for historical reasons.
*/
/*
* this routine looks for an abbreviated flash range specification.
* the syntax is B:SF[-SL], where B is the bank number, SF is the first
* sector to erase, and SL is the last sector to erase (defaults to SF).
* bank numbers start at 1 to be consistent with other specs, sector numbers
* start at zero.
*
* returns: 1 - correct spec; *pinfo, *psf and *psl are
* set appropriately
* 0 - doesn't look like an abbreviated spec
* -1 - looks like an abbreviated spec, but got
* a parsing error, a number out of range,
* or an invalid flash bank.
*/
static int abbrev_spec (char *str, flash_info_t ** pinfo, int *psf, int *psl)
{
flash_info_t *fp;
int bank, first, last;
char *p, *ep;
if ((p = strchr (str, ':')) == NULL)
return 0;
*p++ = '\0';
bank = simple_strtoul (str, &ep, 10);
if (ep == str || *ep != '\0' ||bank < 1 || bank > CFG_MAX_FLASH_BANKS ||
(fp = &flash_info[bank - 1])->flash_id == FLASH_UNKNOWN)
return -1;
str = p;
if ((p = strchr (str, '-')) != NULL)
*p++ = '\0';
first = simple_strtoul (str, &ep, 10);
if (ep == str || *ep != '\0' || first >= fp->sector_count)
return -1;
if (p != NULL)
{
last = simple_strtoul (p, &ep, 10);
if (ep == p || *ep != '\0' ||last < first || last >= fp->sector_count)
return -1;
}
else
{
last = first;
}
*pinfo = fp;
*psf = first;
*psl = last;
return 1;
}
static int flash_fill_sect_ranges (ulong addr_first, ulong addr_last,int *s_first, int *s_last,int *s_count )
{
flash_info_t *info;
ulong bank;
int rcode = 0;
*s_count = 0;
for (bank=0; bank < CFG_MAX_FLASH_BANKS; ++bank)
{
s_first[bank] = -1; /* first sector to erase */
s_last [bank] = -1; /* last sector to erase */
}
for (bank=0,info=&flash_info[0];(bank < CFG_MAX_FLASH_BANKS) && (addr_first <= addr_last);++bank, ++info)
{
ulong b_end;
int sect;
short s_end;
if (info->flash_id == FLASH_UNKNOWN)
{
continue;
}
b_end = info->start[0] + info->size - 1; /* bank end addr *///flash的最后地址
s_end = info->sector_count - 1; /* last sector */ //最后一个扇区的索引
for (sect=0; sect < info->sector_count; ++sect)
{
ulong end; /* last address in current sect */
end = (sect == s_end) ? b_end : info->start[sect + 1] - 1; //当前扇区的结束地址
if (addr_first > end) //如果erase 的第一个参数大于该扇区的结束地址,则查找下一个扇区
continue;
if (addr_last < info->start[sect]) //当前扇区的起始地址
continue;
//找出erase的两个地址位于 哪两个扇区之间
if (addr_first == info->start[sect]) //判断其始地址是不是当前扇区的起始物理地址
{
s_first[bank] = sect;
}
if (addr_last == end)
{
s_last[bank] = sect;
}
}
if (s_first[bank] >= 0) //如果成立,说明扇区的起始地址是符合要求的
{
if (s_last[bank] < 0) //如果结束地址不在 某个扇区的结束地址
{
if (addr_last > b_end) //还要判断结束地址是不是超出了flash地址的范围
{
s_last[bank] = s_end; //超出,则赋予最后一个扇区的索引
}
else //没有超出且 结束地址不在某个扇区的结束地址
{
puts ("Error: end address" " not on sector boundary\n");
rcode = 1;
break;
}
}
if (s_last[bank] < s_first[bank])
{
puts ("Error: end sector" " precedes start sector\n");
rcode = 1;
break;
}
sect = s_last[bank];
addr_first = (sect == s_end) ? b_end + 1: info->start[sect + 1];
(*s_count) += s_last[bank] - s_first[bank] + 1; //返回要插除扇区的个数
}
else if (addr_first >= info->start[0] && addr_first < b_end) //如果地址在flash的地址范围内
{
puts ("Error: start address not on sector boundary\n"); //
rcode = 1;
break;
}
else if (s_last[bank] >= 0)
{
puts ("Error: cannot span across banks when they are"
" mapped in reverse order\n");
rcode = 1;
break;
}
}
return rcode;
}
int flash_erase (flash_info_t * info, int s_first, int s_last)
{
ushort result;
int iflag, cflag, prot, sect;
int rc = ERR_OK;
int chip;
/* first look for protection bits */
if (info->flash_id == FLASH_UNKNOWN)
return ERR_UNKNOWN_FLASH_TYPE;
if ((s_first < 0) || (s_first > s_last))
{
return ERR_INVAL;
}
if ((info->flash_id & FLASH_VENDMASK) !=(AMD_MANUFACT & FLASH_VENDMASK))
{
return ERR_UNKNOWN_FLASH_VENDOR;
}
prot = 0;
for (sect = s_first; sect <= s_last; ++sect) //判断哪些扇区受保护
{
if (info->protect[sect])
{
prot++;
}
}
if (prot)
return ERR_PROTECTED; //如果擦除的扇区是受到保护的,则返回
/*
* Disable interrupts which might cause a timeout
* here. Remember that our exception vectors are
* at address 0 in the flash, and we don't want a
* (ticker) exception to happen while the flash
* chip is in programming mode.
*/
cflag = icache_status ();
icache_disable ();
iflag = disable_interrupts ();
/* Start erase on unprotected sectors */
for (sect = s_first; sect <= s_last && !ctrlc (); sect++)
{
printf ("Erasing sector %2d ... ", sect);
/* arm simple, non interrupt dependent timer */
reset_timer_masked ();
if (info->protect[sect] == 0)
{ /* not protected */
vu_short *addr = (vu_short *) (info->start[sect]);
MEM_FLASH_ADDR1 = CMD_UNLOCK1;
MEM_FLASH_ADDR2 = CMD_UNLOCK2;
MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
MEM_FLASH_ADDR1 = CMD_UNLOCK1;
MEM_FLASH_ADDR2 = CMD_UNLOCK2;
*addr = CMD_ERASE_CONFIRM;
/* wait until flash is ready */
chip = 0;
do
{
result = *addr;
/* check timeout */
if (get_timer_masked () >
CFG_FLASH_ERASE_TOUT)
{
MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
chip = TMO;
break;
}
if (!chip&& (result & 0xFFFF) & BIT_ERASE_DONE)
chip = READY;
if (!chip&& (result & 0xFFFF) & BIT_PROGRAM_ERROR)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -