20160802_jeffrey - silenceuncrio/diary GitHub Wiki

Index

  • 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 去 - 可以開機

0920

review

0925

搭配 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;
}

1045

再來看到 r = plat_config_data->rom_mtd_init(md, infp);

plat_config_data 應該是在 discover_boot_rom_version() 裡被指定成 mx6ul_boot_config

mx6ul_boot_configplat_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);
}

1055

看到 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 不知道又被寫了什麼

1120

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;
}

1130

想要好好了解 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

1150

這個 build 看起來要花掉一些時間

1300

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> 好了

1400

修改了 <IMX_KOBS_SRC> 之後

使用 bitbake imx-kobs -c compile -f 強制 conpile imx-kobs

再使用 bitbake fsl-image-mfgtool-initramfs

<BUILD_DIR>/tmp/deploy/images/imx6ulevkfsl-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

1505

fill_fcb() 可以了解到 imx-kobs 一開始是怎麼來使用 /dev/mtd0 這一塊 NAND Flash

1730

MfgTool 被我弄得有點亂了

燒錄完竟然開不起來了

1750

之前留的

  • D:\m300\tools\L4.1.15_1.0.0_ga-mfg-tools\L4.1.15-1.0.0_ga-mfg-tools\mfgtools

燒錄完開的起來了

1805

修改 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

1830

看到 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 去

應該還是可以開機才對

明天來試試

⚠️ **GitHub.com Fallback** ⚠️