20160802_jeffrey - silenceuncrio/diary GitHub Wiki
- 0920 - review
-
0925 - trace
imx-kobs
recipe - main - init_main - padding_1k_in_head -
1045 -
rom_mtd_init()
-v4_rom_mtd_init()
-
1055 -
rom_mtd_commit_structures()
-v6_rom_mtd_commit_structures()
-
1120 -
write_boot_stream()
-
1130 - 好好了解
write_boot_stream()
的行為 - 1150 - bitbake fsl-image-mfgtool-initramfs
-
1300 -
<BUILD_DIR>
-<IMX_KOBS_SRC>
-
1400 - 修改
<IMX_KOBS_SRC>
- compile - 燒錄 - console 看到 debug information -
1505 -
fill_fcb()
-imx-kobs
怎麼來使用/dev/mtd0
這一塊 NAND Flash - 1730 - MfgTool 被我弄亂了 - 燒錄完開不起來
- 1750 - 之前 mfgtools 燒錄完開的起來
-
1805 - 修改
mx6ul_14x14_evk.h
- 讓 boot mtd 只占 3m - 原本是 64m - 1830 - 理論 - 複製一個 3m 的 image 從頭 燒錄到 NAND Flash 去 - 可以開機
review
搭配 2016-07-25-MfgTool.no.14.nand-scrub.chip.log trace imx-kobs
recipe 的 source code
傳入的 command 為 kobs-ng init -x -v --chip_0_device_path=/dev/mtd0 $FILE
main.c
int main(int argc, char **argv)
{
argc--;
argv++;
if (strcmp(argv[0], "init") == 0)
return init_main(argc, argv);
}
argv[0]
所指的字串為 init
int init_main(int argc, char **argv)
{
int i, j, r;
struct mtd_data *md;
int flags, image;
char *infile = NULL;
FILE *infp;
loff_t ofs;
int padding = 0;
struct mtd_config cfg;
uint8_t key[16];
char ascii[20 * 2 + 1];
uint8_t *keyp;
memset(key, 0, sizeof(key));
/* copy defaults */
memcpy(&cfg, &default_mtd_config, sizeof(cfg));
/* first parse kobs */
mtd_parse_kobs(&cfg, ".kobs", false);
/* then the arguments */
mtd_parse_args(&cfg, argc, argv);
image = 0; /* first image */
flags = 0;
j = 0;
for (i = 1; i < argc; i++) {
if (argv[i][0] != '-') {
if (infile == NULL)
infile = argv[i];
continue;
}
switch (argv[i][1]) {
case 'x':
padding = 1;
break;
case 'v':
flags |= F_VERBOSE;
break;
}
}
if (flags & F_VERBOSE)
mtd_cfg_dump(&cfg);
/*
* We are using the kernel 3.5.7 now.
* The latest uboot does not have the 1k-padding in the head.
* So we have to add the 1k-padding ourselves.
* Note: We only burn the uboot to nand in the kernel 3.5.7.
*/
if (padding) {
infile = padding_1k_in_head(infile);
if (flags & F_VERBOSE)
printf("\t -- We add the 1k-padding to the uboot.\n");
}
infp = fopen(infile, "rb");
keyp = key;
if (flags & F_VERBOSE)
printf("%s: verifying using key '%s'\n", infile,
vec_ascii(keyp, ascii));
r = bootstream_verify(flags, infp, keyp, NULL);
if (flags & F_VERBOSE)
printf("%s: is %s bootstream for key '%s'\n", infile,
r == 0 ? "a valid" : "an INVALID",
vec_ascii(keyp, ascii));
md = mtd_open(&cfg, flags);
/* keep the file name in the private. */
md->private = infile;
r = plat_config_data->rom_mtd_init(md, infp);
if (flags & F_VERBOSE)
mtd_dump_structure(md);
r = plat_config_data->rom_mtd_commit_structures(md, infp, UPDATE_ALL);
fclose(infp);
/* delete the temporary file. */
if (padding)
remove(infile);
return 0;
}
因為 -x
和 -v
所以會作以下兩件事
padding = 1;
flags |= F_VERBOSE;
if (padding) {
infile = padding_1k_in_head(infile);
if (flags & F_VERBOSE)
printf("\t -- We add the 1k-padding to the uboot.\n");
}
因為 padding
為 1 所以會作 infile = padding_1k_in_head(infile);
infile
便是我們的 U-Boot image 了
看一下 padding_1k_in_head
我們新建立一個 file tmp_file
offset 1k 後再把 U-Boot image 複製到該 file
然後 return 該 file
static char *padding_1k_in_head(char *file_name)
{
int to, from;
int ret;
int sz = getpagesize();
from = open(file_name, O_RDONLY, S_IRUSR | S_IWUSR);
to = open(tmp_file, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
/* Padding 1k in the head. */
lseek(to, 1024, SEEK_SET);
do {
/* copy a page each time. */
ret = sendfile(to, from, NULL, sz);
} while (ret > 0);
close(to);
close(from);
/* change to the temporary file. */
return tmp_file;
}
再來看到 r = plat_config_data->rom_mtd_init(md, infp);
plat_config_data
應該是在 discover_boot_rom_version()
裡被指定成 mx6ul_boot_config
mx6ul_boot_config
在 plat_boot_config.c
定義如下
static platform_config mx6ul_boot_config = {
.m_u32RomVer = ROM_Version_5,
.m_u32EnDISBBM = 0,
.m_u32EnBootStreamVerify = 0,
.m_u32UseNfcGeo = 0,
.m_u32UseMultiBootArea = 0,
.m_u32UseSinglePageStride = 0,
.m_u32DBBT_FingerPrint = DBBT_FINGERPRINT2,
.m_u32MaxEccStrength = 40,
.rom_mtd_init = v4_rom_mtd_init,
.rom_mtd_commit_structures = v6_rom_mtd_commit_structures,
};
所以 plat_config_data->rom_mtd_init(md, infp)
實際上是 v4_rom_mtd_init(md, infp)
int v4_rom_mtd_init(struct mtd_data *md, FILE *fp)
{
int ret;
ret = fill_fcb(md, fp);
if (ret)
return ret;
return fill_dbbt(md);
}
看到 r = plat_config_data->rom_mtd_commit_structures(md, infp, UPDATE_ALL);
實際上呼叫的是 v6_rom_mtd_commit_structures(md, infp, UPDATE_ALL)
int v6_rom_mtd_commit_structures(struct mtd_data *md, FILE *fp, int flags)
{
int size, i, r, chip = 0;
loff_t ofs;
struct mtd_config *cfg = &md->cfg;
/* [1] Write the FCB search area. */
size = mtd_writesize(md) + mtd_oobsize(md);
memset(md->buf, 0, size);
r = fcb_encrypt(&md->fcb, md->buf, size, 3);
if (r < 0)
return r;
mtd_commit_bcb(md, "FCB", 0, 0, 0, 1, size, false);
/* [2] Write the DBBT search area. */
memset(md->buf, 0, mtd_writesize(md));
memcpy(md->buf, &(md->dbbt50), sizeof(md->dbbt50));
mtd_commit_bcb(md, "DBBT", 1, 1, 1, 1, mtd_writesize(md), true);
/* Write the DBBT table area. */
memset(md->buf, 0, mtd_writesize(md));
if (md->dbbt50.DBBT_Block.v3.m_u32DBBTNumOfPages > 0 && md->bbtn[0] != NULL) {
memcpy(md->buf, md->bbtn[0], sizeof(*md->bbtn[0]));
ofs = cfg->search_area_size_in_bytes;
for (i = 0; i < 4; i++, ofs += cfg->stride_size_in_bytes) {
vp(md, "mtd: PUTTING down DBBT%d BBTN%d @0x%llx (0x%x)\n",
i, 0, ofs + 4 * mtd_writesize(md), mtd_writesize(md));
r = mtd_write_page(md, chip, ofs + 4 * mtd_writesize(md), 1);
if (r != mtd_writesize(md)) {
fprintf(stderr, "mtd: Failed to write BBTN @0x%llx (%d)\n", ofs, r);
}
}
}
/* [3] Write the two boot streams. */
return write_boot_stream(md, fp);
}
看最後的 write_boot_stream(md, fp)
整個 file 不知道又被寫了什麼
write_boot_stream
是最大的關鍵
想辦法看懂吧
int write_boot_stream(struct mtd_data *md, FILE *fp)
{
int startpage, start, size;
loff_t ofs, end;
int i, r, chunk;
int chip = 0;
struct fcb_block *fcb = &md->fcb.FCB_Block;
vp(md, "---------- Start to write the [ %s ]----\n", (char*)md->private);
for (i = 0; i < 2; i++) {
if (fp == NULL)
continue;
if (i == 0) {
startpage = fcb->m_u32Firmware1_startingPage;
size = fcb->m_u32PagesInFirmware1;
end = fcb->m_u32Firmware2_startingPage;
} else {
startpage = fcb->m_u32Firmware2_startingPage;
size = fcb->m_u32PagesInFirmware2;
end = mtd_size(md) / mtd_writesize(md);
}
start = startpage * mtd_writesize(md);
size = size * mtd_writesize(md);
end = end * mtd_writesize(md);
vp(md, "mtd: Writting %s: #%d @%d: 0x%08x - 0x%08x\n",
(char*)md->private, i, chip, start, start + size);
/* Begin to write the image. */
rewind(fp);
ofs = start;
while (ofs < end && size > 0) {
while (mtd_isbad(md, chip, ofs) == 1) {
vp(md, "mtd: Skipping bad block at 0x%llx\n", ofs);
ofs += mtd_erasesize(md);
}
chunk = size;
/*
* Check if we've entered a new block and, if so, erase
* it before beginning to write it.
*/
if ((ofs % mtd_erasesize(md)) == 0) {
r = mtd_erase_block(md, chip, ofs);
if (r < 0) {
fprintf(stderr, "mtd: Failed to erase block"
"@0x%llx\n", ofs);
ofs += mtd_erasesize(md);
continue;
}
}
if (chunk > mtd_writesize(md))
chunk = mtd_writesize(md);
r = fread(md->buf, 1, chunk, fp);
if (r < 0) {
fprintf(stderr, "mtd: Failed %d (fread %d)\n", r, chunk);
return -1;
}
if (r < chunk) {
memset(md->buf + r, 0, chunk - r);
vp(md, "mtd: The last page is not full : %d\n", r);
}
/* write page */
r = mtd_write_page(md, chip, ofs, 1);
if (r != mtd_writesize(md))
fprintf(stderr, "mtd: Failed to write BS @0x%llx (%d)\n",
ofs, r);
ofs += mtd_writesize(md);
size -= chunk;
}
/*
* Write one safe guard page:
* The Image_len of uboot is bigger then the real size of
* uboot by 1K. The ROM will get all 0xff error in this case.
* So we write one more page for safe guard.
*/
memset(md->buf, 0, mtd_writesize(md));
r = mtd_write_page(md, chip, ofs, 1);
if (r != mtd_writesize(md))
fprintf(stderr, "Failed to write safe page\n");
vp(md, "mtd: We write one page for save guard. *\n");
if (ofs >= end) {
fprintf(stderr, "mtd: Failed to write BS#%d\n", i);
return -1;
}
}
return 0;
}
想要好好了解 write_boot_stream
的行為不外乎直接修改它 放一些 debug message 然後實際操作去觀察它
參考 Freescale Yocto Project User's Guide
的
-
6 Image Deployment
6.2 Manufacturing Tool, MFGTool
利用 ubuntu_16
來做實驗 - bitbake fsl-image-mfgtool-initramfs
這個 build 看起來要花掉一些時間
build 好囉
我們一開始是在 ubuntu_16
的 ~/mfgtool_study/fsl-release-bsp/build_dir/
使用 bitbake fsl-image-mfgtool-initramfs
我們稱之為 <BUILD_DIR>
產生的 image 會在 <BUILD_DIR>/tmp/deploy/images/imx6ulevk
在 fsl-image-mfgtool-initramfs-imx6ulevk.manifest
會看到 imx-kobs cortexa7hf-vfp-neon 5.4
base-files imx6ulevk 3.0.14
bash cortexa7hf-vfp-neon 4.3.30
...
imx-kobs cortexa7hf-vfp-neon 5.4
...
使用 bitbake imx-kobs -c devshell
跳到 imx-kobs 的 source 目錄
<BUILD_DIR>/tmp/work/cortexa7hf-vfp-neon-poky-linux-gnueabi/imx-kobs/5.4-r0/imx-kobs-5.4
我們就稱之為 <IMX_KOBS_SRC>
好了
修改了 <IMX_KOBS_SRC>
之後
使用 bitbake imx-kobs -c compile -f
強制 conpile imx-kobs
再使用 bitbake fsl-image-mfgtool-initramfs
將 <BUILD_DIR>/tmp/deploy/images/imx6ulevk
的 fsl-image-mfgtool-initramfs-imx6ulevk.cpio.gz.u-boot
image
複製到 MfgTool 下的 Profiles\Linux\OS Firmware\firmware
rename 為 fsl-image-mfgtool-initramfs-imx_mfgtools.cpio.gz.u-boot
燒錄
從 console 就可以看到我們放的 debug information
從 fill_fcb()
可以了解到 imx-kobs
一開始是怎麼來使用 /dev/mtd0
這一塊 NAND Flash
MfgTool 被我弄得有點亂了
燒錄完竟然開不起來了
之前留的
- D:\m300\tools\L4.1.15_1.0.0_ga-mfg-tools\L4.1.15-1.0.0_ga-mfg-tools\mfgtools
燒錄完開的起來了
修改 mx6ul_14x14_evk.h
讓 boot mtd 只占 3m
mtdparts=gpmi-nand:3m(boot),16m(kernel),16m(dtb),-(rootfs)
原本是 64m
剛剛試過 2m... MfgTool 燒錄階段就出錯了
3m 確定可行
看到 2016-08-02-MfgTool.no.6.log 的
-------------- Start to write the [ FCB ] -----
mtd: erasing @0:0x0-0x20000
mtd: Writing FCB0 [ @0:0x0 ] (840) *
mtd: erasing @0:0x20000-0x40000
mtd: Writing FCB1 [ @0:0x20000 ] (840) *
mtd: erasing @0:0x40000-0x60000
mtd: Writing FCB2 [ @0:0x40000 ] (840) *
mtd: erasing @0:0x60000-0x80000
mtd: Writing FCB3 [ @0:0x60000 ] (840) *
mtd_commit_bcb(FCB): status 0
-------------- Start to write the [ DBBT ] -----
mtd: erasing @0:0x80000-0xa0000
mtd: Writing DBBT0 [ @0:0x80000 ] (800) *
mtd: erasing @0:0xa0000-0xc0000
mtd: Writing DBBT1 [ @0:0xa0000 ] (800) *
mtd: erasing @0:0xc0000-0xe0000
mtd: Writing DBBT2 [ @0:0xc0000 ] (800) *
mtd: erasing @0:0xe0000-0x100000
mtd: Writing DBBT3 [ @0:0xe0000 ] (800) *
mtd_commit_bcb(DBBT): status 0
---------- Start to write the [ .tmp_kobs_ng ]----
mtd: Writting .tmp_kobs_ng: #0 @0: 0x00100000 - 0x00165000
mtd: erasing @0:0x100000-0x120000
mtd: erasing @0:0x120000-0x140000
mtd: erasing @0:0x140000-0x160000
mtd: erasing @0:0x160000-0x180000
mtd: We write one page for save guard. *
mtd: Writting .tmp_kobs_ng: #1 @0: 0x00200000 - 0x00265000
mtd: erasing @0:0x200000-0x220000
mtd: erasing @0:0x220000-0x240000
mtd: erasing @0:0x240000-0x260000
mtd: erasing @0:0x260000-0x280000
mtd: We write one page for save guard. *
理論上... 我們應該可以複製一個 3m 的 image 跟 MfgTool 燒錄完的結果一模一樣
然後用很單純的方式從頭開始把這個 3m 的 image 燒錄到 NAND Flash 去
應該還是可以開機才對
明天來試試