2009年10月9日 星期五

如何寫一個sd fusing tool of Samsung s5pc1xx

在Samsung s5pc1xx 平台上要boot from SD/MMC card,須使用moviNAND_Fusing_Tool.exe(Windows程式)來製作該bootable SD/MMC card。現在我們感興趣的是該工具將uboot.bin, zImage 和rootfs.img分別寫到SD/MMC card的那一個offset上。

首先觀察u boot 的boot command是如何下的:

bootcmd=movi read kernel 20008000;movi read rootfs 20a00000 600000;bootm 20008000 20a00000


u boot 中有一個command叫movi (common/cmd_movi.c),指令可以讓我們做以下的事:

movi init - Initialize moviNAND and show card info
movi read {u-boot | kernel} {addr} - Read data from sd/mmc
movi write {u-boot | kernel} {addr} - Write data to sd/mmc
movi read rootfs {addr} [bytes(hex)] - Read rootfs data from sd/mmc by size
movi write rootfs {addr} [bytes(hex)] - Write rootfs data to sd/mmc by size
movi read {sector#} {bytes(hex)} {addr} - instead of this, you can use "mmcd"
movi write {sector#} {bytes(hex)} {addr} - instead of this, you can use "mmcte"


再觀察當在u boot下了"movi read kernel 20008000"會發生什麼事,看common/cmd_movi.c:

....
if (strcmp(argv[2], "kernel") == 0) {
printf("Reading kernel from sector %d (%d sectors).. ", ofsinfo.kernel, MOVI_ZIMAGE_BLKCNT);
movi_read((uint) addr, ofsinfo.kernel, MOVI_ZIMAGE_BLKCNT);
printf("completed\n");

}
....

所以"movi read kernel 20008000"的意思是從SD/MMC offset ofsinfo.kernel 讀MOVI_ZIMAGE_BLKCNT (512bytes-blocks)資料到記憶體位置0x20008000。所以


struct ofsinfo會在./lib_arm/boar.c被initialize

#if defined(CONFIG_SMDKC100)
#if defined(CONFIG_MMC)
....
movi_set_ofs(MOVI_TOTAL_BLKCNT);
.....
#endif
....
#endif

而movi_set_ofs()被定義在./cpu/s5pc1xx/movi.c:

int movi_set_ofs(uint last)
{
int changed = 0;

if (ofsinfo.last != last) {
ofsinfo.last = last - (eFUSE_SIZE / MOVI_BLKSIZE);
ofsinfo.bl1 = ofsinfo.last - MOVI_BL1_BLKCNT;
ofsinfo.env = ofsinfo.bl1 - MOVI_ENV_BLKCNT;
ofsinfo.bl2 = ofsinfo.bl1 - (MOVI_BL2_BLKCNT + MOVI_ENV_BLKCNT);
ofsinfo.kernel = ofsinfo.bl2 - MOVI_ZIMAGE_BLKCNT;
ofsinfo.rootfs = ofsinfo.kernel - MOVI_ROOTFS_BLKCNT;
changed = 1;
}

return changed;
}

所以由movi_set_ofs()的定義知道bootable SD/MMC的資料layout:

----------------------------------------- 0

----------------------------------------- ofsinfo.kernel - MOVI_ROOTFS_BLKCNT=ofsinfo.rootfs
rootfs
----------------------------------------- ofsinfo.bl2-MOVI_ZIMAGE_BLKCNT=ofsinfo.kernel
zImage
------------------------------------------ ofsinfo.env-MOVI_BL2_BLKCNT=ofsinfo.bl2
BL2
------------------------------------------ ofsinfo.bl1 - MOVI_ENV_BLKCNT=ofsinfo.env
u boot ENV
------------------------------------------- ofsinfo.last-MOVI_BL1_BLKCNT=ofsinfo.bl1
BL1
------------------------------------------- MOVI_TOTAL_BLKCNT-eFUSE_SIZE/MOVI_BLKSIZE=ofsinfo.last

eFUSE
------------------------------------------- MOVI_TOTAL_BLKCNT

上述的常數定義在include/movi.h

#define MOVI_TOTAL_BLKCNT *((volatile unsigned int*)(SDMMC_BLK_SIZE))

#define SS_SIZE (8 * 1024)
#define eFUSE_SIZE (1 * 1024) // 0.5k eFuse, 0.5k reserved
#define MOVI_BLKSIZE (1<<9) /* 512 bytes */

/* partition information */
#define PART_SIZE_BL (512 * 1024)
#define PART_SIZE_KERNEL (4 * 1024 * 1024)
#define PART_SIZE_ROOTFS (8 * 1024 * 1024)

#define MOVI_LAST_BLKPOS (MOVI_TOTAL_BLKCNT - (eFUSE_SIZE / MOVI_BLKSIZE))
#define MOVI_BL1_BLKCNT (SS_SIZE / MOVI_BLKSIZE)
#define MOVI_ENV_BLKCNT (CFG_ENV_SIZE / MOVI_BLKSIZE)
#define MOVI_BL2_BLKCNT (PART_SIZE_BL / MOVI_BLKSIZE)
#define MOVI_ZIMAGE_BLKCNT (PART_SIZE_KERNEL / MOVI_BLKSIZE)
#define MOVI_ROOTFS_BLKCNT (PART_SIZE_ROOTFS / MOVI_BLKSIZE)

而SDMMC_BLK_SIZE被定義在include/configs/smdkc100.h

#define SDMMC_BLK_SIZE (0xd0020230)

MOVI_TOTAL_BLKCNT的值其實是從I/O memory 位置 0xd0020230去取得,而該位置落在IRAM (0xd002_0000~0xD003_8000), BL0會將detect 到的SD/MMC的Total block count 紀錄於此。

依據以上研讀資訊,在Linux 下我們可以用dd 指令製作bootable SD/MMC card。

以4G SD card為例:

ofsinfo.bl1=7897070, MOVI_BL1_BLKCNT=16
ofsinfo.bl2=7896014, MOVI_BL2_BLKCNT=1024
ofsinfo.kernel=7887822, MOVI_ZIMAGE_BLKCNT=8192
ofsinfo.rootfs=7871438, MOVI_ROOTFS_BLKCNT=12288

sudo dd if=./u-boot.bin of=/dev/sdb bs=512 count=16 seek=7897070
sudo dd if=./u-boot.bin of=/dev/sdb bs=512 count=1024 seek=7896014
sudo dd if=./zImage of=/dev/sdb bs=512 count=8192 seek=7887822
sudo dd if=./rootfs.cramfs of=/dev/sdb bs=512 count=12288 seek=7871438

沒有留言: