diff options
| author | liYangYang <[email protected]> | 2024-04-21 21:52:47 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-04-21 09:52:47 -0400 |
| commit | f13220d91111bbb48abaae26507917c2fc9c6d12 (patch) | |
| tree | 983a6d9d10c94fe16e51a0dba78b0bcec8650b31 /bsp/cvitek | |
| parent | 3ff2b08d82e590b3841f94cf05c756a693cfa8a8 (diff) | |
[bsp][cvitek] Milk-V Duo 256M Supports running ARM large core and RISCV small core
支持将rtthread.bin和dtb文件合成boot.sd文件,使用uboot直接通过bootcmd命令启动rtthread内核。
支持构建带有小核riscv程序的fip.bin文件,保证在运行arm大核的同时运行小核的riscv程序。
Diffstat (limited to 'bsp/cvitek')
15 files changed, 925 insertions, 1 deletions
diff --git a/bsp/cvitek/cv18xx_aarch64/.gitignore b/bsp/cvitek/cv18xx_aarch64/.gitignore new file mode 100755 index 0000000000..65b277bc26 --- /dev/null +++ b/bsp/cvitek/cv18xx_aarch64/.gitignore @@ -0,0 +1 @@ +Image
\ No newline at end of file diff --git a/bsp/cvitek/cv18xx_aarch64/README.md b/bsp/cvitek/cv18xx_aarch64/README.md index 4d85cb2d79..a5ceb07dbf 100644 --- a/bsp/cvitek/cv18xx_aarch64/README.md +++ b/bsp/cvitek/cv18xx_aarch64/README.md @@ -63,7 +63,7 @@ scons -j12 ## 3. 运行 -> 目前仅支持使用uboot对 `rtthread.bin` 文件进行加载,uboot对 `boot.sd` 的加载方式后续会实现。 +### 3.1 uboot加载rtthread.bin 1. 将 SD 卡分为 2 个分区,第 1 个分区用于存放 bin 文件,第 2 个分区用于作为数据存储分区,分区格式为 `FAT32`。 @@ -81,6 +81,22 @@ go 0x80200000 > 0x80200000为rtthread.bin加载到内存的位置,可在menuconfig中自己修改,注意不能与小核固件加载位置重叠。 +### 3.2 uboot加载boot.sd + +1. 将 SD 卡分为 2 个分区,第 1 个分区用于存放 bin 文件,第 2 个分区用于作为数据存储分区,分区格式为 `FAT32`。 + +2. 将bsp的boot目录下的 `fip.bin` 和编译生成的 `boot.sd` 复制 SD 卡第一个分区中。后续更新固件只需要复制 `boot.sd` 文件即可。 + +配置**串口0**参数: 115200 8N1 ,硬件和软件流控为关。 + +直接上电运行,uboot会自动调用bootcmd解析boot.sd文件,然后加载`rtthread.bin`运行。 + +### 3.3 如何生成fip.bin + +在本bsp的boot/milkv-duo256m目录下存放了所有需要构建出fip.bin的一些依赖文件和相关脚本。用户只需要在boot目录下执行`combine.sh`即可生成fip.bin。 + +> 如何用户编译了小核c906_little的bsp,那么`combine.sh`脚本将会生成带有小核程序的fip.bin。未编译则不会。 + 完成后可以看到串口的输出信息: **标准版log信息:** diff --git a/bsp/cvitek/cv18xx_aarch64/boot/combine.sh b/bsp/cvitek/cv18xx_aarch64/boot/combine.sh new file mode 100755 index 0000000000..e39f49dcbc --- /dev/null +++ b/bsp/cvitek/cv18xx_aarch64/boot/combine.sh @@ -0,0 +1,44 @@ +C906_LITTLE_BIN_PATH=../../c906_little/rtthread.bin +GEN_FIP_PATH=. +DEPENDS_FILE_PATH=${GEN_FIP_PATH}/milkv-duo256m + +BLCP_IMG_RUNADDR=0x05200200 +BLCP_PARAM_LOADADDR=0 +NAND_INFO=00000000 +NOR_INFO='FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' +FIP_COMPRESS=lzma + +CHIP_CONF_PATH=${DEPENDS_FILE_PATH}/chip_conf.bin +DDR_PARAM_TEST_PATH=${DEPENDS_FILE_PATH}/ddr_param.bin +BL2_PATH=${DEPENDS_FILE_PATH}/bl2.bin +BLCP_PATH=${DEPENDS_FILE_PATH}/empty.bin +MONITOR_PATH=${DEPENDS_FILE_PATH}/bl31.bin +LOADER_2ND_PATH=${DEPENDS_FILE_PATH}/u-boot-raw.bin + +if [ -f "$C906_LITTLE_BIN_PATH" ]; then + echo "The file $C906_LITTLE_BIN_PATH exist." + BLCP_2ND_PATH=${C906_LITTLE_BIN_PATH} +else + echo "The file $C906_LITTLE_BIN_PATH does not exist. Execute scons to compile it." +fi + +echo "Combining fip.bin..." +. ${DEPENDS_FILE_PATH}/blmacros.env && \ +${DEPENDS_FILE_PATH}/fiptool.py -v genfip \ +${GEN_FIP_PATH}/fip.bin \ +--MONITOR_RUNADDR="${MONITOR_RUNADDR}" \ +--BLCP_2ND_RUNADDR="${BLCP_2ND_RUNADDR}" \ +--CHIP_CONF=${CHIP_CONF_PATH} \ +--NOR_INFO=${NOR_INFO} \ +--NAND_INFO=${NAND_INFO} \ +--BL2=${BL2_PATH} \ +--BLCP_IMG_RUNADDR=${BLCP_IMG_RUNADDR} \ +--BLCP_PARAM_LOADADDR=${BLCP_PARAM_LOADADDR} \ +--BLCP=${BLCP_PATH} \ +--DDR_PARAM=${DDR_PARAM_TEST_PATH} \ +--BLCP_2ND=${BLCP_2ND_PATH} \ +--MONITOR=${MONITOR_PATH} \ +--LOADER_2ND=${LOADER_2ND_PATH} \ +--compress=${FIP_COMPRESS} + +echo "Combining fip.bin done!" diff --git a/bsp/cvitek/cv18xx_aarch64/boot/fip.bin b/bsp/cvitek/cv18xx_aarch64/boot/fip.bin Binary files differindex c406223010..be1eeeb042 100644 --- a/bsp/cvitek/cv18xx_aarch64/boot/fip.bin +++ b/bsp/cvitek/cv18xx_aarch64/boot/fip.bin diff --git a/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/bl2.bin b/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/bl2.bin Binary files differnew file mode 100755 index 0000000000..197e5a1f3a --- /dev/null +++ b/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/bl2.bin diff --git a/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/bl31.bin b/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/bl31.bin Binary files differnew file mode 100644 index 0000000000..cf38b2e291 --- /dev/null +++ b/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/bl31.bin diff --git a/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/blmacros.env b/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/blmacros.env new file mode 100644 index 0000000000..ae3059bd57 --- /dev/null +++ b/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/blmacros.env @@ -0,0 +1,2 @@ +MONITOR_RUNADDR=0x0000000080000000 +BLCP_2ND_RUNADDR=0x000000008fe00000 diff --git a/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/chip_conf.bin b/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/chip_conf.bin Binary files differnew file mode 100644 index 0000000000..d2dabd6868 --- /dev/null +++ b/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/chip_conf.bin diff --git a/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/ddr_param.bin b/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/ddr_param.bin Binary files differnew file mode 100644 index 0000000000..fb4c648fd7 --- /dev/null +++ b/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/ddr_param.bin diff --git a/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/empty.bin b/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/empty.bin new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/empty.bin diff --git a/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/fiptool.py b/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/fiptool.py new file mode 100755 index 0000000000..6943e5f799 --- /dev/null +++ b/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/fiptool.py @@ -0,0 +1,803 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-3-Clause +# PYTHON_ARGCOMPLETE_OK + +import sys +import logging +import os +import os.path +import argparse +from collections import OrderedDict +import binascii +from struct import pack, unpack +import lzma +import pprint + + +PYTHON_MIN_VERSION = (3, 5, 2) # Ubuntu 16.04 LTS contains Python v3.5.2 by default + + +if sys.version_info < PYTHON_MIN_VERSION: + print("Python >= %r is required" % (PYTHON_MIN_VERSION,)) + sys.exit(-1) + + +try: + import coloredlogs +except ImportError: + coloredlogs = None + +try: + import argcomplete +except ImportError: + argcomplete = None + + +LOADER_2ND_MAGIC_ORIG = b"BL33" +LOADER_2ND_MAGIC_LZMA = b"B3MA" +LOADER_2ND_MAGIC_LZ4 = b"B3Z4" + +LOADER_2ND_MAGIC_LIST = [ + LOADER_2ND_MAGIC_ORIG, + LOADER_2ND_MAGIC_LZMA, + LOADER_2ND_MAGIC_LZ4, +] + +IMAGE_ALIGN = 512 +PARAM1_SIZE = 0x1000 +PARAM1_SIZE_WO_SIG = 0x800 +PARAM2_SIZE = 0x1000 + + +def round_up(divident, divisor): + return ((divident + divisor - 1) // divisor) * divisor + + +def lzma_compress(body): + z = lzma.LZMACompressor(lzma.FORMAT_ALONE, preset=lzma.PRESET_EXTREME) + compressed = z.compress(body) + compressed += z.flush() + + return compressed + + +def lz4_compress(body): + try: + import lz4.frame + except ImportError: + logging.error("lz4 is not installed. Run 'pip install lz4'.") + raise + + compressed = lz4.frame.compress(body) + return compressed + + +class Entry: + __slots__ = "name", "type", "addr", "_content", "entry_size" + + def __init__(self): + self.addr = None + self._content = None + + @property + def end(self): + return self.addr + self.entry_size + + @property + def content(self): + return self._content + + @content.setter + def content(self, value): + if type(value) == int: + value = value.to_bytes(self.entry_size, "little") + + if self.entry_size is not None: + if len(value) > self.entry_size: + raise ValueError("%s (%d bytes) must <= %#r" % (self.name, len(value), self.entry_size)) + value = value + b"\0" * (self.entry_size - len(value)) + + self._content = value + + @classmethod + def make(cls, name, entry_size, _type, init=None): + entry = Entry() + entry.name = name + entry.type = _type + entry.entry_size = entry_size + + if type(init) in (bytes, bytearray): + entry.content = bytes(init) + elif entry_size is not None: + entry.content = b"\0" * entry.entry_size + else: + entry.content = b"" + + return (name, entry) + + def toint(self): + if self.type != int: + raise TypeError("%s is not int type" % self.name) + + return int.from_bytes(self.content, "little") + + def tostr(self): + v = self.content + if self.type == int: + v = "%#08x" % self.toint() + elif type(self.content) in [bytes, bytearray]: + v = v.hex() + if len(v) > 32: + v = v[:32] + "..." + + return v + + def __str__(self): + v = self.tostr() + return "<%s=%s (%dbytes)>" % (self.name, v, self.entry_size) + + def __repr__(self): + v = self.tostr() + return "<%s: a=%#x s=%#x c=%s %r>" % (self.name, self.addr, self.entry_size, v, self.type) + + +class FIP: + param1 = OrderedDict( + [ + Entry.make("MAGIC1", 8, int, b"CVBL01\n\0"), + Entry.make("MAGIC2", 4, int), + Entry.make("PARAM_CKSUM", 4, int), + Entry.make("NAND_INFO", 128, int), + Entry.make("NOR_INFO", 36, int), + Entry.make("FIP_FLAGS", 8, int), + Entry.make("CHIP_CONF_SIZE", 4, int), + Entry.make("BLCP_IMG_CKSUM", 4, int), + Entry.make("BLCP_IMG_SIZE", 4, int), + Entry.make("BLCP_IMG_RUNADDR", 4, int), + Entry.make("BLCP_PARAM_LOADADDR", 4, int), + Entry.make("BLCP_PARAM_SIZE", 4, int), + Entry.make("BL2_IMG_CKSUM", 4, int), + Entry.make("BL2_IMG_SIZE", 4, int), + Entry.make("BLD_IMG_SIZE", 4, int), + Entry.make("PARAM2_LOADADDR", 4, int), + Entry.make("RESERVED1", 4, int), + Entry.make("CHIP_CONF", 760, bytes), + Entry.make("BL_EK", 32, bytes), + Entry.make("ROOT_PK", 512, bytes), + Entry.make("BL_PK", 512, bytes), + Entry.make("BL_PK_SIG", 512, bytes), + Entry.make("CHIP_CONF_SIG", 512, bytes), + Entry.make("BL2_IMG_SIG", 512, bytes), + Entry.make("BLCP_IMG_SIG", 512, bytes), + ] + ) + + body1 = OrderedDict( + [ + Entry.make("BLCP", None, bytes), + Entry.make("BL2", None, bytes), + ] + ) + + param2 = OrderedDict( + [ + Entry.make("MAGIC1", 8, int, b"CVLD02\n\0"), + Entry.make("PARAM2_CKSUM", 4, int), + Entry.make("RESERVED1", 4, bytes), + # DDR param + Entry.make("DDR_PARAM_CKSUM", 4, int), + Entry.make("DDR_PARAM_LOADADDR", 4, int), + Entry.make("DDR_PARAM_SIZE", 4, int), + Entry.make("DDR_PARAM_RESERVED", 4, int), + # BLCP_2ND + Entry.make("BLCP_2ND_CKSUM", 4, int), + Entry.make("BLCP_2ND_LOADADDR", 4, int), + Entry.make("BLCP_2ND_SIZE", 4, int), + Entry.make("BLCP_2ND_RUNADDR", 4, int), + # ATF-BL31 or OpenSBI + Entry.make("MONITOR_CKSUM", 4, int), + Entry.make("MONITOR_LOADADDR", 4, int), + Entry.make("MONITOR_SIZE", 4, int), + Entry.make("MONITOR_RUNADDR", 4, int), + # u-boot + Entry.make("LOADER_2ND_RESERVED0", 4, int), + Entry.make("LOADER_2ND_LOADADDR", 4, int), + Entry.make("LOADER_2ND_RESERVED1", 4, int), + Entry.make("LOADER_2ND_RESERVED2", 4, int), + # Reserved + Entry.make("RESERVED_LAST", 4096 - 16 * 5, bytes), + ] + ) + + body2 = OrderedDict( + [ + Entry.make("DDR_PARAM", None, bytes), + Entry.make("BLCP_2ND", None, bytes), + Entry.make("MONITOR", None, bytes), + Entry.make("LOADER_2ND", None, bytes), + ] + ) + + ldr_2nd_hdr = OrderedDict( + [ + Entry.make("JUMP0", 4, int), + Entry.make("MAGIC", 4, int), + Entry.make("CKSUM", 4, int), + Entry.make("SIZE", 4, int), + Entry.make("RUNADDR", 8, int), + Entry.make("RESERVED1", 4, int), + Entry.make("RESERVED2", 4, int), + ] + ) + + FIP_FLAGS_SCS_MASK = 0x000c + FIP_FLAGS_ENCRYPTED_MASK = 0x0030 + + def _param_size(self, param): + return max((e.end for e in param.values())) + + def _gen_param(self): + addr = 0 + for entry in self.param1.values(): + entry.addr = addr + addr += entry.entry_size + + assert PARAM1_SIZE_WO_SIG == self.param1["BL_PK_SIG"].addr + + addr = 0 + for entry in self.param2.values(): + entry.addr = addr + addr += entry.entry_size + + assert PARAM2_SIZE == self.param2["RESERVED_LAST"].addr + self.param2["RESERVED_LAST"].entry_size + + addr = 0 + for entry in self.ldr_2nd_hdr.values(): + entry.addr = addr + addr += entry.entry_size + + def __init__(self): + self.compress_algo = None + self._gen_param() + + def image_crc(self, image): + crc = binascii.crc_hqx(image, 0) + crc = pack("<H", crc) + b"\xFE\xCA" + return crc + + def pad(self, data, block_size): + if type(data) not in [bytearray, bytes]: + raise TypeError("Need bytearray or bytes") + + r = len(data) % block_size + if r: + data += b"\0" * (block_size - r) + + return data + + def _pprint_attr(self, name): + v = getattr(self, name) + + if type(v) == OrderedDict: + v = list(v.values()) + logging.info("print(%s):\n" % name + pprint.pformat(v, 4, 140)) + + def print_fip_params(self): + self._pprint_attr("param1") + self._pprint_attr("param2") + self._pprint_attr("ldr_2nd_hdr") + + def read_fip(self, path): + logging.debug("read_fip:") + + with open(path, "rb") as fp: + fip_bin = fp.read() + + fip_bin = bytearray(fip_bin) + + e = self.param1["MAGIC1"] + if fip_bin[e.addr : e.end] != e.content: + raise ValueError("Unknown magic %r" % fip_bin[e.addr : e.end]) + + # Read param1 from fip.bin + for e in self.param1.values(): + e.content = fip_bin[e.addr : e.end] + + self.read_end = PARAM1_SIZE + + # Read BLCP + e = self.param1["BLCP_IMG_SIZE"] + blcp_img_size = unpack("<I", fip_bin[e.addr : e.end])[0] + if blcp_img_size: + start = self.read_end + self.read_end = start + blcp_img_size + self.body1["BLCP"].content = fip_bin[start : self.read_end] + + # Read FSBL as BL2 + e = self.param1["BL2_IMG_SIZE"] + bl2_img_size = unpack("<I", fip_bin[e.addr : e.end])[0] + if bl2_img_size: + start = self.read_end + self.read_end = start + bl2_img_size + self.body1["BL2"].content = fip_bin[start : self.read_end] + + logging.info("read_fip end=%#x", self.read_end) + self.rest_fip = fip_bin[self.read_end :] + + self.read_fip2(fip_bin) + + def read_fip2(self, fip_bin): + param2_loadaddr = self.param1["PARAM2_LOADADDR"].toint() + param2_bin = fip_bin[param2_loadaddr : param2_loadaddr + PARAM2_SIZE] + + for e in self.param2.values(): + e.content = param2_bin[e.addr : e.end] + + self.read_end = param2_loadaddr + PARAM2_SIZE + + # Read DDR_PARAM, BLCP_2ND, and MONITOR + for name in ["DDR_PARAM", "BLCP_2ND", "MONITOR"]: + size = self.param2[name + "_SIZE"].toint() + loadaddr = self.param2[name + "_LOADADDR"].toint() + self.body2[name].content = fip_bin[loadaddr : loadaddr + size] + self.read_end = loadaddr + size + + # Read LOADER_2ND + loader_2nd_loadaddr = self.param2["LOADER_2ND_LOADADDR"].toint() + if loader_2nd_loadaddr: + self.read_loader_2nd(fip_bin) + + logging.info("read_fip2 end=%#x", self.read_end) + self.rest_fip = fip_bin[self.read_end :] + + def read_loader_2nd(self, fip_bin): + loader_2nd_loadaddr = self.param2["LOADER_2ND_LOADADDR"].toint() + + self._parse_ldr_2nd_hdr(fip_bin[loader_2nd_loadaddr:]) + + if self.ldr_2nd_hdr["MAGIC"].content not in LOADER_2ND_MAGIC_LIST: + raise ValueError("%r" % self.ldr_2nd_hdr["MAGIC"].content) + + ldr_2nd_size = self.ldr_2nd_hdr["SIZE"].toint() + + self.body2["LOADER_2ND"].content = fip_bin[loader_2nd_loadaddr : loader_2nd_loadaddr + ldr_2nd_size] + + self.read_end = loader_2nd_loadaddr + ldr_2nd_size + self.rest_fip = fip_bin[self.read_end :] + + def add_chip_conf(self, args): + logging.debug("add_chip_conf:") + + with open(args.CHIP_CONF, "rb") as fp: + image = fp.read() + + if image.startswith(b"APLB"): + image = image[8:] # strip old BLP header + + self.param1["CHIP_CONF"].content = image + + def add_blcp(self, args): + logging.debug("add_blcp:") + + with open(args.BLCP, "rb") as fp: + image = fp.read() + + image = self.pad(image, IMAGE_ALIGN) + + self.param1["BLCP_IMG_RUNADDR"].content = args.BLCP_IMG_RUNADDR + self.body1["BLCP"].content = image + + def add_bl2(self, args): + logging.debug("add_bl2:") + + with open(args.BL2, "rb") as fp: + image = fp.read() + + bl2_fill = 0 + if args.BL2_FILL: + bl2_fill = args.BL2_FILL + + image += b"\xA9" * (bl2_fill - len(image)) + image = self.pad(image, IMAGE_ALIGN) + + self.body1["BL2"].content = image + + def add_nor_info(self, args): + logging.debug("add_nor_info:") + self.param1["NOR_INFO"].content = args.NOR_INFO + + def add_nand_info(self, args): + logging.debug("add_nand_info:") + self.param1["NAND_INFO"].content = args.NAND_INFO + + def update_param1_cksum(self, image): + image = bytearray(image) + crc = self.image_crc(image[self.param1["NAND_INFO"].addr : PARAM1_SIZE_WO_SIG]) + + param_cksum = self.param1["PARAM_CKSUM"] + param_cksum.content = crc + image[param_cksum.addr : param_cksum.end] = crc + return image + + def make_fip1(self): + logging.debug("make_fip1:") + + chip_conf = self.param1["CHIP_CONF"].content + self.param1["CHIP_CONF_SIZE"].content = len(chip_conf) + + blcp = self.body1["BLCP"].content + self.param1["BLCP_IMG_CKSUM"].content = self.image_crc(blcp) + self.param1["BLCP_IMG_SIZE"].content = len(blcp) + + bl2 = self.body1["BL2"].content + self.param1["BL2_IMG_CKSUM"].content = self.image_crc(bl2) + self.param1["BL2_IMG_SIZE"].content = len(bl2) + + # Pack body1 + body1_bin = b"" + for entry in self.body1.values(): + if len(entry.content) % IMAGE_ALIGN: + raise ValueError("%s (%d) is not align to %d" % (entry.name, len(entry.content), IMAGE_ALIGN)) + + logging.info("add %s (%#x)", entry.name, len(entry.content)) + body1_bin += entry.content + + logging.debug("len(body1_bin) is %d", len(body1_bin)) + + # Param1 cksum + param1_bin = b"".join((entry.content for entry in self.param1.values())) + param1_bin = self.update_param1_cksum(param1_bin) + + if len(param1_bin) != PARAM1_SIZE: + raise ValueError("param1_bin is %d bytes" % len(param1_bin)) + + fip1_bin = param1_bin + body1_bin + logging.debug("len(fip1_bin) is %d", len(fip1_bin)) + + return fip1_bin + + def add_ddr_param(self, args): + with open(args.DDR_PARAM, "rb") as fp: + ddr_param = fp.read() + + logging.debug("ddr_param=%#x bytes", len(ddr_param)) + self.body2["DDR_PARAM"].content = ddr_param + + def add_blcp_2nd(self, args): + with open(args.BLCP_2ND, "rb") as fp: + blcp_2nd = fp.read() + + logging.debug("blcp_2nd=%#x bytes", len(blcp_2nd)) + self.body2["BLCP_2ND"].content = blcp_2nd + + def add_monitor(self, args): + with open(args.MONITOR, "rb") as fp: + monitor = fp.read() + + logging.debug("monitor=%#x bytes", len(monitor)) + self.body2["MONITOR"].content = monitor + + def add_loader_2nd(self, args): + with open(args.LOADER_2ND, "rb") as fp: + loader_2nd = fp.read() + + logging.debug("loader_2nd=%#x bytes", len(loader_2nd)) + + e = self.ldr_2nd_hdr["MAGIC"] + magic = loader_2nd[e.addr : e.end] + if magic != LOADER_2ND_MAGIC_ORIG: + raise ValueError("loader_2nd's magic should be %r, but %r" % (LOADER_2ND_MAGIC_ORIG, magic)) + + self.compress_algo = args.compress + self.body2["LOADER_2ND"].content = loader_2nd + + def pack_ddr_param(self, fip_bin): + if not len(self.body2["DDR_PARAM"].content): + return + + fip_bin = self.pad(fip_bin, IMAGE_ALIGN) + + # Pack DDR_PARAM to body2 + ddr_param = self.pad(self.body2["DDR_PARAM"].content, IMAGE_ALIGN) + + self.param2["DDR_PARAM_CKSUM"].content = self.image_crc(ddr_param) + self.param2["DDR_PARAM_SIZE"].content = len(ddr_param) + self.param2["DDR_PARAM_LOADADDR"].content = len(fip_bin) + + return fip_bin + ddr_param + + def pack_blcp_2nd(self, fip_bin, blcp_2nd_runaddr): + logging.debug("pack_blcp_2nd:") + if not len(self.body2["BLCP_2ND"].content): + return + + runaddr = int(blcp_2nd_runaddr) + + fip_bin = self.pad(fip_bin, IMAGE_ALIGN) + + # Pack MONITOR to body2 + body = self.pad(self.body2["BLCP_2ND"].content, IMAGE_ALIGN) + + self.param2["BLCP_2ND_CKSUM"].content = self.image_crc(body) + self.param2["BLCP_2ND_SIZE"].content = len(body) + self.param2["BLCP_2ND_LOADADDR"].content = len(fip_bin) + self.param2["BLCP_2ND_RUNADDR"].content = runaddr + + return fip_bin + body + + def pack_monitor(self, fip_bin, monitor_runaddr): + logging.debug("pack_monitor:") + if not len(self.body2["MONITOR"].content): + return + + monitor_runaddr = int(monitor_runaddr) + + fip_bin = self.pad(fip_bin, IMAGE_ALIGN) + + # Pack MONITOR to body2 + monitor = self.pad(self.body2["MONITOR"].content, IMAGE_ALIGN) + + self.param2["MONITOR_CKSUM"].content = self.image_crc(monitor) + self.param2["MONITOR_SIZE"].content = len(monitor) + self.param2["MONITOR_LOADADDR"].content = len(fip_bin) + self.param2["MONITOR_RUNADDR"].content = monitor_runaddr + + return fip_bin + monitor + + def _parse_ldr_2nd_hdr(self, image): + for e in self.ldr_2nd_hdr.values(): + e.content = image[e.addr : e.end] + + def _update_ldr_2nd_hdr(self): + image = self.body2["LOADER_2ND"].content + hdr_size = self._param_size(self.ldr_2nd_hdr) + hdr, body = image[:hdr_size], image[hdr_size:] + + # Update SIZE + self.ldr_2nd_hdr["SIZE"].content = len(image) + + # Update CKSUM + hdr = bytearray(b"".join((e.content for e in self.ldr_2nd_hdr.values()))) + # CKSUM is calculated after "CKSUM" field + hdr_cksum = self.ldr_2nd_hdr["CKSUM"] + crc = self.image_crc((hdr + body)[hdr_cksum.end :]) + hdr_cksum.content = crc + hdr = bytearray(b"".join((e.content for e in self.ldr_2nd_hdr.values()))) + + self.body2["LOADER_2ND"].content = hdr + body + + def _compress_ldr_2nd(self): + image = self.body2["LOADER_2ND"].content + hdr_size = self._param_size(self.ldr_2nd_hdr) + hdr, body = image[:hdr_size], image[hdr_size:] + + magic = self.ldr_2nd_hdr["MAGIC"].content + if magic == LOADER_2ND_MAGIC_ORIG: + # if image is uncompressed, compress it. + if self.compress_algo is None: + pass + elif self.compress_algo == "lzma": + self.ldr_2nd_hdr["MAGIC"].content = LOADER_2ND_MAGIC_LZMA + body = lzma_compress(body) + logging.info("lzma loader_2nd=%#x bytes wo header", len(body)) + elif self.compress_algo == "lz4": + self.ldr_2nd_hdr["MAGIC"].content = LOADER_2ND_MAGIC_LZ4 + body = lz4_compress(body) + logging.info("lz4 loader_2nd=%#x bytes wo header", len(body)) + else: + raise NotImplementedError("'%r' is not supported." % self.compress_algo) + elif magic in LOADER_2ND_MAGIC_LIST: + logging.info("loader_2nd is already compressed") + else: + raise ValueError("unknown loader_2nd magic (%r)", magic) + + self.body2["LOADER_2ND"].content = self.pad(hdr + body, IMAGE_ALIGN) + + def pack_loader_2nd(self, fip_bin): + logging.debug("pack_loader_2nd:") + if not len(self.body2["LOADER_2ND"].content): + return + + fip_bin = self.pad(fip_bin, IMAGE_ALIGN) + self.param2["LOADER_2ND_LOADADDR"].content = len(fip_bin) + + self._parse_ldr_2nd_hdr(self.body2["LOADER_2ND"].content) + self._compress_ldr_2nd() + self._update_ldr_2nd_hdr() + + # Append LOADER_2ND to body2 + return fip_bin + self.body2["LOADER_2ND"].content + + def insert_param1(self, fip_bin, name, value): + fip_bin = bytearray(fip_bin) + e = self.param1[name] + e.content = value + fip_bin[e.addr : e.end] = value + return self.update_param1_cksum(fip_bin) + + def append_fip2(self, fip1_bin, args): + logging.debug("make_fip2:") + fip_bin = bytearray(fip1_bin) + + # Update PARAM2_LOADADDR + param2_loadaddr = len(fip1_bin) + fip_bin = self.insert_param1(fip_bin, "PARAM2_LOADADDR", pack("<I", param2_loadaddr)) + + # Add an empty PARAM2 + fip_bin += b"\0" * PARAM2_SIZE + + # Pack body + fip_bin = self.pack_ddr_param(fip_bin) + + if len(self.body2["BLCP_2ND"].content): + runaddr = self.param2["BLCP_2ND_RUNADDR"].toint() + if not runaddr: + runaddr = int(args.BLCP_2ND_RUNADDR) + fip_bin = self.pack_blcp_2nd(fip_bin, runaddr) + + if len(self.body2["MONITOR"].content): + runaddr = self.param2["MONITOR_RUNADDR"].toint() + if not runaddr: + runaddr = int(args.MONITOR_RUNADDR) + fip_bin = self.pack_monitor(fip_bin, runaddr) + + if len(self.body2["LOADER_2ND"].content): + fip_bin = self.pack_loader_2nd(fip_bin) + + # Pack param2_bin + param2_bin = b"".join((entry.content for entry in self.param2.values())) + self.param2["PARAM2_CKSUM"].content = self.image_crc(param2_bin[self.param2["PARAM2_CKSUM"].end :]) + param2_bin = b"".join((entry.content for entry in self.param2.values())) # update cksum + + logging.debug("len(param2_bin) is %d", len(param2_bin)) + assert len(param2_bin) == PARAM2_SIZE + + fip_bin[param2_loadaddr : param2_loadaddr + PARAM2_SIZE] = param2_bin + + return fip_bin + + def make(self, args=None): + fip_bin = self.make_fip1() + if len(self.body2["DDR_PARAM"].content): + fip_bin = self.append_fip2(fip_bin, args) + + logging.info("generated fip_bin is %d bytes", len(fip_bin)) + + if getattr(self, "rest_fip", None): + logging.error("the rest of fip is not used: %#x bytes ", len(self.rest_fip)) + + return fip_bin + + +METHODS = { + "NOR_INFO": FIP.add_nor_info, + "NAND_INFO": FIP.add_nand_info, + "CHIP_CONF": FIP.add_chip_conf, + "BLCP": FIP.add_blcp, + "BL2": FIP.add_bl2, + "DDR_PARAM": FIP.add_ddr_param, + "BLCP_2ND": FIP.add_blcp_2nd, + "MONITOR": FIP.add_monitor, + "LOADER_2ND": FIP.add_loader_2nd, +} + + +def generate_fip(args): + logging.debug("generate_fip:") + fip = FIP() + + if args.OLD_FIP: + fip.read_fip(args.OLD_FIP) + + for m, f in METHODS.items(): + if getattr(args, m): + f(fip, args) + + fip_bin = fip.make(args) + fip.print_fip_params() + + if args.output: + with open(args.output, "wb") as fp: + fp.write(fip_bin) + + +def parse_args(): + parser = argparse.ArgumentParser(description="FIP tools") + + parser.add_argument( + "-v", + "--verbose", + help="Increase output verbosity", + action="store_const", + const=logging.DEBUG, + default=logging.INFO, + ) + + subparsers = parser.add_subparsers(dest="subcmd", help="Sub-command help") + pr_gen = subparsers.add_parser("genfip", help="Generate keys") + + for name in list(METHODS): + if name in ["NOR_INFO", "NAND_INFO"]: + pr_gen.add_argument("--" + name, type=bytes.fromhex) + else: + pr_gen.add_argument("--" + name, dest=name, type=str, help="Add %s into FIP" % name) + + def auto_int(x): + return int(x, 0) + + pr_gen.add_argument("--BLCP_IMG_RUNADDR", type=auto_int) + pr_gen.add_argument("--BLCP_PARAM_LOADADDR", type=auto_int) + + pr_gen.add_argument("--BLCP_2ND_RUNADDR", type=auto_int) + + pr_gen.add_argument("--MONITOR_RUNADDR", type=auto_int) + + pr_gen.add_argument("--compress", choices=["lzma", "lz4", ""]) + + pr_gen.add_argument("--OLD_FIP", type=str) + pr_gen.add_argument("--BLOCK_SIZE", type=auto_int) + pr_gen.add_argument("--BL2_FILL", type=auto_int) + + pr_gen.add_argument("output", type=str, help="Output filename") + + pr_gen.set_defaults(func=generate_fip) + + if argcomplete: + argcomplete.autocomplete(parser) + + args = parser.parse_args() + init_logging(stdout_level=args.verbose) + logging.info("PROG: %s", parser.prog) + + if not args.subcmd: + parser.print_help() + raise SystemExit(1) + + for a, v in sorted(vars(args).items()): + logging.debug(" %s=%r", a, v) + + return args + + +def main(): + args = parse_args() + args.func(args) + + +def init_logging(log_file=None, file_level="DEBUG", stdout_level="WARNING"): + root_logger = logging.getLogger() + root_logger.setLevel(logging.NOTSET) + + fmt = "%(asctime)s %(levelname)8s:%(name)s:%(message)s" + + if log_file is not None: + file_handler = logging.FileHandler(log_file, encoding="utf-8") + file_handler.setFormatter(logging.Formatter(fmt)) + file_handler.setLevel(file_level) + root_logger.addHandler(file_handler) + + if coloredlogs: + os.environ["COLOREDLOGS_DATE_FORMAT"] = "%H:%M:%S" + + field_styles = { + "asctime": {"color": "green"}, + "hostname": {"color": "magenta"}, + "levelname": {"color": "black", "bold": True}, + "name": {"color": "blue"}, + "programname": {"color": "cyan"}, + } + + level_styles = coloredlogs.DEFAULT_LEVEL_STYLES + level_styles["debug"]["color"] = "cyan" + + coloredlogs.install( + level=stdout_level, + fmt=fmt, + field_styles=field_styles, + level_styles=level_styles, + milliseconds=True, + ) + + +if __name__ == "__main__": + main() diff --git a/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/u-boot-raw.bin b/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/u-boot-raw.bin Binary files differnew file mode 100644 index 0000000000..48e69e41eb --- /dev/null +++ b/bsp/cvitek/cv18xx_aarch64/boot/milkv-duo256m/u-boot-raw.bin diff --git a/bsp/cvitek/cv18xx_aarch64/dtb/milkv-duo256m/multi.its b/bsp/cvitek/cv18xx_aarch64/dtb/milkv-duo256m/multi.its new file mode 100644 index 0000000000..d3d76fd8ce --- /dev/null +++ b/bsp/cvitek/cv18xx_aarch64/dtb/milkv-duo256m/multi.its @@ -0,0 +1,56 @@ +/* + * U-Boot uImage source file with multiple kernels, ramdisks and FDT blobs + */ + +/dts-v1/; + +/ { + description = "Various kernels, ramdisks and FDT blobs"; + #address-cells = <2>; + + images { + kernel-1 { + description = "cvitek kernel"; + data = /incbin/("./Image.lzma"); + type = "kernel"; + arch = "arm64"; + os = "linux"; + compression = "lzma"; + load = <0x0 0x80200000>; + entry = <0x0 0x80200000>; + hash-2 { + algo = "crc32"; + }; + }; + + + /*FDT*/ + + fdt-sg2002_milkv_duo256m_arm_sd { + description = "cvitek device tree - sg2002_milkv_duo256m_arm_sd"; + data = /incbin/("./sg2002_milkv_duo256m_arm_sd.dtb"); + type = "flat_dt"; + arch = "arm64"; + compression = "none"; + hash-1 { + algo = "sha256"; + }; + }; + + + + }; + + /*CFG*/ + configurations { + + config-sg2002_milkv_duo256m_arm_sd { + description = "boot cvitek system with board sg2002_milkv_duo256m_arm_sd"; + kernel = "kernel-1"; + fdt = "fdt-sg2002_milkv_duo256m_arm_sd"; + }; + + }; + + +}; diff --git a/bsp/cvitek/cv18xx_aarch64/dtb/milkv-duo256m/sg2002_milkv_duo256m_arm_sd.dtb b/bsp/cvitek/cv18xx_aarch64/dtb/milkv-duo256m/sg2002_milkv_duo256m_arm_sd.dtb Binary files differnew file mode 100644 index 0000000000..6ef447d6e2 --- /dev/null +++ b/bsp/cvitek/cv18xx_aarch64/dtb/milkv-duo256m/sg2002_milkv_duo256m_arm_sd.dtb diff --git a/bsp/cvitek/cv18xx_aarch64/rtconfig.py b/bsp/cvitek/cv18xx_aarch64/rtconfig.py index c363513a18..54ea2201bb 100644 --- a/bsp/cvitek/cv18xx_aarch64/rtconfig.py +++ b/bsp/cvitek/cv18xx_aarch64/rtconfig.py @@ -45,3 +45,5 @@ if PLATFORM == 'gcc': DUMP_ACTION = OBJDUMP + ' -D -S $TARGET > rtt.asm\n' POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' +POST_ACTION += OBJCPY + ' -O binary $TARGET Image \n' + SIZE + ' $TARGET \n' +POST_ACTION += 'cd .. && bash mksdimg.sh ' + os.getcwd() + ' Image \n' |
