bootloader会有一块环境变量分区,用来保存bootloader的参数,通常都会定义在bootloader附近的一块区域,大小一个block就够了,也就是128k。
1. loadEnv() --- 主程序调用该函数,用来读取env的内容
void loadEnv(uint32_t start, uint32_t end)
{
int err;
env = (uint8_t *)ENV_RAM_ADDR;
err = readenv(env, start, end);
if (err)
env = (uint8_t *)defaultEnv;
//如果读取错误,就会使用默认的env值
}
2. readenv() --- 具体还得靠它来实现
int readenv(uint8_t *buf, uint32_t start, uint32_t end)
{
env_t *hdr = (env_t *)buf;
uint32_t page = PAGE(start);
uint32_t endPage = PAGE(end);
uint32_t crc;
int size = 0, i = sizeof(hdr->crc);
//读取nandflash中env分区的内容,也就是起始页到结束页内容
page = ReadNandPages(page, buf, 1, endPage);
if (!page)
{
puts("ERROR: Cannot read env page\r\n");
return -1;
}
// env area is a bunch of \0 terminated strings where the end is an
// empty string.
do
{
while (buf[i++]) {
if (i >= PAGE_SIZE)
{
i -= PAGE_SIZE;
size += PAGE_SIZE;
buf += PAGE_SIZE;
page = ReadNandPages(page, buf, 1, endPage);
if (!page)
{
puts("ERROR: Cannot read env page\r\n");
return -1;
}
}
}
// Read in the next page if the \0 was at the end of the page.
if (i >= PAGE_SIZE)
{
i -= PAGE_SIZE;
size += PAGE_SIZE;
buf += PAGE_SIZE;
page = ReadNandPages(page, buf, 1, endPage);
if (!page)
{
puts("ERROR: Cannot read env page\r\n");
return -1;
}
}
} while (buf[i]);
size += i + 1 - sizeof(crc);
crc = crc32(0, hdr->data, size);
// 读出来之后,进行CRC 校验
if (hdr->crc != crc) {
puts("ERROR: env CRC mismatch: expected ");
writeHex(hdr->crc);
puts(", calculated ");
writeHex(crc);
puts(".\r\n");
return -1;
}
return 0;
}
3. env_t --- 环境变量区域的定义,都是先一个CRC值,然后是一堆'\0'结尾的字符
typedef struct {
uint32_t crc; /* CRC32 over data bytes */
uint8_t data[1]; /* Environment data */
} env_t;
4. envVar() --- 定位一个变量在env中的位置
char *envVar (uint8_t *env, char *name)
{
// skip CRC
env += 4;
while (*env) {
if (!strncmp(env, name, strlen(name))) {
env += strlen(name);
if (*env == '=')
return env + 1;
}
env += strlen(env) + 1;
}
return 0;
}