[build] add cvitek build scripts

Change-Id: If63ce4a669e5d4d72b8e3b9253336dd99bf74c30
This commit is contained in:
sam.xiang
2023-02-23 11:21:38 +08:00
parent cbb030f19f
commit a4f213ceb0
1219 changed files with 149149 additions and 0 deletions

View File

@ -0,0 +1,119 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import logging
import os
import re
import sys
import xml.etree.ElementTree as ET
FORMAT = "%(levelname)s: %(message)s"
logging.basicConfig(level=logging.INFO, format=FORMAT)
Storage_EMMC = 0
Storage_SPINAND = 1
Storage_SPINOR = 2
LBA_SIZE = 512
class XmlParser:
@staticmethod
def parse_size(size):
units = {"B": 1, "K": 2 ** 10, "M": 2 ** 20, "G": 2 ** 30, "T": 2 ** 40}
size = size.upper()
logging.debug("parsing size %s" % size)
if not re.match(r" ", size):
size = re.sub(r"([BKMGT])", r" \1", size)
try:
number, unit = [string.strip() for string in size.split()]
except ValueError:
number = size
unit = "B"
ret = int(float(number) * units[unit])
return ret
def parse(self, install=None):
try:
tree = ET.parse(self.xml)
except Exception:
logging.error(self.xml + " is not a vaild xml file")
raise
root = tree.getroot()
self.storage = root.attrib["type"]
install_dir = install
parts = []
for part in root:
p = dict()
if "size_in_kb" in part.attrib:
p["part_size"] = int(part.attrib["size_in_kb"]) * 1024
elif "size_in_b" in part.attrib:
p["part_size"] = int(part.attrib["size_in_b"])
else:
p["part_size"] = sys.maxsize
# Assign 0 means biggest number
if part.attrib["file"] and install_dir is not None:
path = os.path.join(install_dir, part.attrib["file"])
try:
file_size = os.stat(path).st_size
except Exception:
file_size = 0
if file_size > p["part_size"]:
logging.error(
"Image: %s(%d) is larger than partition size(%d)"
% (part.attrib["file"], file_size, p["part_size"])
)
raise OverflowError
p["file_path"] = path
logging.debug("size of " + path + " : " + str(file_size))
else:
file_size = 0
p["file_size"] = int(file_size)
p["file_name"] = part.attrib["file"]
p["label"] = part.attrib["label"]
p["mountpoint"] = (
part.attrib["mountpoint"] if "mountpoint" in part.attrib else None
)
p["type"] = part.attrib["type"] if "type" in part.attrib else ""
p["options"] = part.attrib["options"] if "options" in part.attrib else None
parts.append(p)
if self.storage == "emmc":
self.__calEmmcOffset(parts)
elif self.storage == "spinor":
self.__calNorOffset(parts)
elif self.storage == "spinand":
self.__calNandOffset(parts)
else:
logging.error("Unknown storage type")
raise ValueError(self.storage)
return parts
def __calEmmcOffset(self, parts):
# EMMC will program gpt in the beggining of the emmc, start from 8192
start = 8192
for p in parts:
p["offset"] = start
start += int((p["part_size"] + LBA_SIZE - 1) / LBA_SIZE)
def __calNandOffset(self, parts):
start = 0
for p in parts:
p["offset"] = start
start += p["part_size"]
def __calNorOffset(self, parts):
start = 0
for p in parts:
p["offset"] = start
start += p["part_size"]
def getStorage(self):
return self.storage
def __init__(self, xml):
self.xml = xml
self.storage = "emmc"

View File

@ -0,0 +1,6 @@
CC = gcc -s
all: fip_maker
clean:
$(RM) fip_maker

View File

@ -0,0 +1,342 @@
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
struct _spi_nand_info_t {
unsigned int version;
unsigned int id;
unsigned int page_size;
unsigned int spare_size;
unsigned int block_size;
unsigned int pages_per_block;
unsigned int fip_block_cnt;
unsigned char pages_per_block_shift;
unsigned char badblock_pos;
unsigned char dummy_data1[2];
unsigned int flags;
unsigned char ecc_en_feature_offset;
unsigned char ecc_en_mask;
unsigned char ecc_status_offset;
unsigned char ecc_status_mask;
unsigned char ecc_status_shift;
unsigned char ecc_status_uncorr_val;
unsigned char dummy_data2[2];
unsigned int erase_count; // erase count for sys base block
unsigned char sck_l;
unsigned char sck_h;
unsigned short max_freq;
unsigned int sample_param;
unsigned char xtal_switch;
unsigned char dummy_data3[71];
};
struct block_header_t {
unsigned char tag[4];
unsigned int bc_or_seq;
unsigned int checknum;
unsigned int dummy_2;
};
struct _fip_param1_t {
unsigned long magic1; /* fip magic number*/
unsigned int magic2;
unsigned int param_cksum;
struct _spi_nand_info_t nand_info;
};
#define PTR_INC(base, offset) (void *)((unsigned char *)(base) + (offset))
#define FIP_IMAGE_HEAD "FIPH" /* FIP Image Header 1 */
#define FIP_IMAGE_BODY "FIPB" /* FIP Image body */
#define FIP_MAGIC_NUMBER "CVBL01\n\0"
#define SPI_NAND_VERSION (0x1823a001)
#define BIT(nr) (1UL << (nr))
#define FLAGS_SET_PLANE_BIT (BIT(0))
#define FLAGS_SET_QE_BIT (BIT(1))
#define FLAGS_ENABLE_X2_BIT (BIT(2))
#define FLAGS_ENABLE_X4_BIT (BIT(3))
#define FLAGS_OW_SETTING_BIT (BIT(4))
#define BBP_LAST_PAGE 0x01
#define BBP_FIRST_PAGE 0x02
#define BBP_FIRST_2_PAGE 0x03
/* Table of CRC constants - implements x^16+x^12+x^5+1 */
static const unsigned short crc16_tab[] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
};
unsigned short crc16_ccitt(unsigned short cksum, const unsigned char *buf, int len)
{
for (int i = 0; i < len; i++)
cksum = crc16_tab[((cksum>>8) ^ *buf++) & 0xff] ^ (cksum << 8);
return cksum;
}
static unsigned int spi_nand_crc16_ccitt_with_tag(unsigned char *buf, int len)
{
unsigned int crc = 0;
crc = crc16_ccitt(0, buf, len);
crc |= 0xCAFE0000;
return crc;
}
#define _2K (0x800UL)
#define _4K (0x1000UL)
#define _128K (0x20000UL)
#define _256K (0x40000UL)
void set_spi_nand_info(struct _spi_nand_info_t *nand)
{
nand->version = SPI_NAND_VERSION;
nand->id = 0xffff;
nand->page_size = 2048;
nand->spare_size = 64;
nand->block_size = 0x20000;
nand->pages_per_block = 64;
nand->badblock_pos = BBP_FIRST_PAGE;
nand->fip_block_cnt = 20;
nand->pages_per_block_shift = 6;
nand->flags = FLAGS_SET_QE_BIT | FLAGS_ENABLE_X2_BIT | FLAGS_ENABLE_X4_BIT;
nand->ecc_en_feature_offset = 0xB0;
nand->ecc_en_mask = 1 << 4;
nand->ecc_status_offset = 0xC0;
nand->ecc_status_mask = 0x30;
nand->ecc_status_shift = 4;
nand->ecc_status_uncorr_val = 0x2;
nand->sck_l = 1;
nand->sck_h = 0;
nand->max_freq = 6;
nand->sample_param = 0x40001000;
nand->xtal_switch = 1;
}
int main(int argc, char const *argv[])
{
FILE *inf, *outf;
struct stat statbuf;
int size;
struct _spi_nand_info_t nand;
unsigned char *buff;
unsigned char *out_buff;
void *src_buf_addr;
void *dst_buf_addr;
struct block_header_t bk_header;
unsigned int pg_sz, pg_per_blk, bk_sz, id;
unsigned int total_len, ttl_block_cnt_to_write, ttl_pg_cnt_to_write, out_len;
unsigned int bk_overhead; /* used to calculate total block header size in page 0 of each block */
unsigned int blk_idx = 0;
unsigned int blk_id = 0;
int ret = 0;
if (argc < 5) {
printf("Usage: ./fip_maker pagesize id input_path out_path\n");
return -1;
}
memset(&nand, 0, sizeof(struct _spi_nand_info_t));
/* default parameter */
set_spi_nand_info(&nand);
pg_sz = strtoul(argv[1], NULL, 0);
if (pg_sz != _2K && pg_sz != _4K) {
printf("do not support page size:%u\n", pg_sz);
return -1;
}
bk_sz = (pg_sz == _2K) ? _128K : _256K;
id = strtoul(argv[2], NULL, 0);
nand.page_size = pg_sz;
nand.block_size = bk_sz;
nand.id = id;
if (access(argv[3], F_OK | R_OK)) {
printf("fip.bin is not exist at %s\n", argv[2]);
return -1;
}
stat(argv[3], &statbuf);
size = statbuf.st_size;
printf("fip.bin size is %d\n", size);
buff = (unsigned char *)malloc(size);
if (!buff) {
printf("buff is invalid\n");
return -1;
}
inf = fopen(argv[3], "rb");
if (!inf) {
printf("open fip.bin failed\n");
ret = -1;
goto free_src;
}
fread(buff, sizeof(unsigned char), size, inf);
outf = fopen(argv[4], "wb");
ttl_block_cnt_to_write = size / bk_sz;
if (size % bk_sz != 0)
ttl_block_cnt_to_write += 1;
bk_overhead = sizeof(struct block_header_t);
memset(&bk_header, 0, sizeof(struct block_header_t));
total_len = (size + (ttl_block_cnt_to_write * bk_overhead));
out_len = (total_len / bk_sz) * bk_sz;
if ((total_len % bk_sz) != 0)
out_len += bk_sz;
out_buff = (unsigned char *)malloc(out_len);
memset(out_buff, 0xff, out_len);
dst_buf_addr = PTR_INC(out_buff, 0);
ttl_pg_cnt_to_write = total_len / pg_sz;
if (total_len % pg_sz != 0)
ttl_pg_cnt_to_write += 1; /* add 1 page to write remaining data */
ttl_block_cnt_to_write = total_len / bk_sz; /* re-calculate new block count */
if (total_len % bk_sz != 0)
ttl_block_cnt_to_write += 1;
//printf("totol_len=%d, bk_overhead=%d, ttl_page_cnt_to_write=%d, ttl_block_cnt_to_write=%d\n",
// total_len, bk_overhead, ttl_pg_cnt_to_write, ttl_block_cnt_to_write);
pg_per_blk = nand.pages_per_block;
unsigned int offset_in_buf = 0;
unsigned char wrote_bk_cnt = 0;
unsigned char *temp_buf;
srand(time(NULL));
unsigned int checknum = rand();
temp_buf = (unsigned char *)malloc(pg_sz);
printf("original fip size=%d, total_len with header=%d, total write size=%d\n", size, total_len, out_len);
printf("total page to write=%d, total block to write=%d\n", ttl_pg_cnt_to_write, ttl_block_cnt_to_write);
printf("generated check number is 0x%x\n", checknum);
printf("Re-Assemble fip.bin to %s\n", argv[4]);
for (unsigned int pg_idx_in_buf = 0; pg_idx_in_buf < ttl_pg_cnt_to_write; pg_idx_in_buf++) {
unsigned int pg_idx_in_blk;
pg_idx_in_blk = pg_idx_in_buf % pg_per_blk;
blk_idx = pg_idx_in_buf / pg_per_blk;
src_buf_addr = PTR_INC(buff, offset_in_buf);
dst_buf_addr = PTR_INC(out_buff, (pg_idx_in_buf * pg_sz));
if (pg_idx_in_blk == 0) {
if (wrote_bk_cnt == 0) { /* Fill FIP image first block header */
struct _fip_param1_t *tmp_fip_param;
unsigned int crc = 0;
int param_crc_size;
memcpy(bk_header.tag, FIP_IMAGE_HEAD, 4);
bk_header.bc_or_seq = (unsigned int)ttl_block_cnt_to_write;
bk_header.checknum = checknum;
memcpy(temp_buf, &bk_header, bk_overhead);
tmp_fip_param = src_buf_addr;
memcpy(&(tmp_fip_param->nand_info), &nand, sizeof(struct _spi_nand_info_t));
param_crc_size = 0x800 - offsetof(struct _fip_param1_t, nand_info);
crc = spi_nand_crc16_ccitt_with_tag((unsigned char *)&tmp_fip_param->nand_info
, param_crc_size);
tmp_fip_param->param_cksum = crc;
printf("get CRC = 0x%x, spare_size=0x%x\n", crc, nand.spare_size);
memcpy((temp_buf + bk_overhead), src_buf_addr, (pg_sz - bk_overhead));
} else { /* Fill remaining FIP image body */
memcpy(bk_header.tag, FIP_IMAGE_BODY, 4);
bk_header.bc_or_seq = (unsigned int)wrote_bk_cnt;
bk_header.checknum = checknum;
memcpy(temp_buf, &bk_header, bk_overhead);
if (pg_idx_in_buf == (ttl_pg_cnt_to_write - 1)) { /* last page */
if ((size - offset_in_buf) >= pg_sz)
printf("## WARNING 1 ## data size %d to be wrote is wrong!!\n",
(size - offset_in_buf));
memcpy((temp_buf + bk_overhead), src_buf_addr, (size - offset_in_buf));
} else
memcpy((temp_buf + bk_overhead), src_buf_addr, (pg_sz - bk_overhead));
}
wrote_bk_cnt++;
offset_in_buf = offset_in_buf + (pg_sz - bk_overhead); /* Insert fip header in page 0 */
} else {
if (pg_idx_in_buf == (ttl_pg_cnt_to_write - 1)) { /* last page */
if ((size - offset_in_buf) > pg_sz)
printf("## WARNING 2 ## data size %d to be wrote is wrong!!\n",
(size - offset_in_buf));
memcpy(temp_buf, src_buf_addr, (size - offset_in_buf));
} else
memcpy(temp_buf, src_buf_addr, pg_sz);
offset_in_buf = offset_in_buf + pg_sz;
}
if (pg_idx_in_blk == 0) {
/* pg_idx_in_blk == 0 means need a new block */
/* damage == 1 means need to find next block*/
blk_id++;
printf("allocate blk_id=%d\n", (blk_id - 1));
}
memcpy(dst_buf_addr, temp_buf, pg_sz);
}
fwrite(out_buff, sizeof(unsigned char), out_len, outf);
printf("fip.bin --> %s is completed!!\n", argv[4]);
fclose(inf);
fclose(outf);
free(temp_buf);
free_dst:
free(out_buff);
free_src:
free(buff);
return ret;
}

Binary file not shown.

View File

@ -0,0 +1,281 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import argparse
import logging
from os import path, getcwd
from XmlParser import XmlParser
from tempfile import mkdtemp
import sys
import subprocess
FORMAT = "%(levelname)s: %(message)s"
logging.basicConfig(level=logging.INFO, format=FORMAT)
def resource_path(relative_path):
""" Get absolute path to resource, works for dev and for PyInstaller """
try:
# PyInstaller creates a temp folder and stores path in _MEIPASS
base_path = sys._MEIPASS
except Exception:
base_path = path.dirname(path.realpath(__file__))
return path.join(base_path, relative_path)
def parse_Args():
parser = argparse.ArgumentParser(description="Create UBI image")
parser.add_argument("xml", help="path to partition xml")
parser.add_argument("label", help="label of the partition")
parser.add_argument(
"input_path", metavar="input", type=str, help="input file or folder for packing"
)
parser.add_argument(
"output_path",
metavar="output_file_path",
type=str,
help="the folder path to install dir inclued fip,rootfs and kernel",
)
parser.add_argument(
"-v", "--verbose", help="increase output verbosity", action="store_true"
)
parser.add_argument(
"-p",
"--pagesize",
help="page size of nand, default is 2Kib",
type=str,
default="2K",
)
parser.add_argument(
"-b",
"--blocksize",
help="block size of nand, default is 128Kib",
type=str,
default="128K",
)
parser.add_argument("--ubinize", help="path to ubinize", type=str)
parser.add_argument("--mkfs", help="path to mkfs.ubifs", type=str)
parser.add_argument(
"--ubionly",
help="create ubi image only",
action="store_true",
)
parser.add_argument(
"--maxsize",
help="Set max size for the partition"
"(For the partition without size assigned) ",
type=int,
)
parser.add_argument(
"--reserved",
help="Set reserved blocks percentage for the partition,"
"For example: --reserved 10 means 10%% reserved blocks."
"(For the partition without size assigned) ",
type=int,
)
args = parser.parse_args()
if args.verbose:
logging.debug("Enable more verbose output")
logging.getLogger().setLevel(level=logging.DEBUG)
if args.ubinize is None:
args.ubinize = resource_path("ubinize")
if args.mkfs is None:
args.mkfs = resource_path("mkfs.ubifs")
return args
def log_subprocess_output(pipe):
for line in iter(pipe.readline, b""): # b'\n'-separated lines
logging.debug("got line from subprocess: %r", line)
def create_ubicfg(img_path, part_size, label, output, ubionly=False):
with open(output, "w") as f:
f.write("[ubifs]\n")
f.write("mode=ubi\n")
f.write("image=%s\n" % img_path)
f.write("vol_id=0\n")
if not ubionly:
f.write("vol_size=%d\n" % part_size)
f.write("vol_type=dynamic\n")
f.write("vol_name=%s\n" % label)
f.write("vol_flags=autoresize\n")
# Debug message
logging.debug("[ubifs]")
logging.debug("[mode]=ubi")
logging.debug("image=%s" % img_path)
logging.debug("vol_id=0")
logging.debug("vol_size=%d" % part_size)
logging.debug("vol_type=dynamic")
logging.debug("vol_name=%s" % label)
logging.debug("vol_flags=autoresize")
def create_ubifs(
input_dir, output_dir, internal_part_size, pagesize, pebsize, mkfs, verbose=False
):
lebsize = pebsize - 2 * pagesize
part_lebcnt = internal_part_size / lebsize
ubifs_args = "-r %s -m %d -e %d -c %d -F" % (
input_dir,
pagesize,
lebsize,
part_lebcnt,
)
logging.debug("ubifs args %s", ubifs_args)
tmp_ubifs = path.join(output_dir, "tmp.ubifs")
mkfs_cmd = "%s %s -o %s" % (mkfs, ubifs_args, tmp_ubifs)
logging.debug("mkfs_cmd:%s", mkfs_cmd)
try:
process = subprocess.Popen(
mkfs_cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
cwd=getcwd(),
shell=True,
)
except Exception:
return -1
if verbose:
with process.stdout:
log_subprocess_output(process.stdout)
ret = process.wait()
return [ret, tmp_ubifs]
def create_ubi(img_path, cfg_path, output, pagesize, pebsize, ubinize, verbose=False):
ubi_args = "-p %d -m %d" % (pebsize, pagesize)
logging.debug("ubi args %s", ubi_args)
ubinize_cmd = "%s -o %s %s %s" % (ubinize, output, ubi_args, cfg_path)
logging.debug("ubinize_cmd:%s", ubinize_cmd)
try:
process = subprocess.Popen(
ubinize_cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
cwd=getcwd(),
shell=True,
)
except Exception:
return -1
if verbose:
with process.stdout:
log_subprocess_output(process.stdout)
ret = process.wait()
return ret
def main():
args = parse_Args()
parser = XmlParser(args.xml)
parts = parser.parse()
for p in parts:
# Since xml parser will parse with abspath and the user input path can
# be relative path, use file name to check.
if args.label == p["label"]:
part = p
break
try:
part_size = part["part_size"]
label = part["label"]
except Exception:
logging.error("label is not found in partition.xml, please check!")
return -1
logging.debug("get partition as below:")
logging.debug(p)
pagesize = XmlParser.parse_size(args.pagesize)
pebsize = XmlParser.parse_size(args.blocksize)
lebsize = pebsize - 2 * pagesize
if part_size == sys.maxsize:
if args.maxsize:
part_size = args.maxsize
else:
logging.error("please use --maxsize size to assign size")
return 1
# 1.
# 2 PEBs are used to store the volume table;
# 1 PEB is reserved for wear-leveling purposes;
# 1 PEB is reserved for the atomic LEB change operation;
# 2.
# some amount of PEBs are reserved for bad PEB handling;
# this is applicable for NAND flash but not for NOR flash
# the amount of reserved PEBs is configurable and is equal to
# 20 blocks per 1024 blocks by default.
# 3.
# UBI stores the EC and VID headers at the beginning of each PEB;
# the number of bytes used for these purposes depends on
# the flash type and is explained below.
# 4.
# According to above design, set at lease 5 blocks reserved
# Set extra reserved for bad blocks, at least 1 block or 1% of partition
# size for r/w partition
# 5.
# SP: PEB
# SL: LEB
# P: Total number of PEBs on the MTD device
# O: The overhead related to storing EC and VID headers in bytes, i.e. O = SP - SL
# B: Number of bad block handling
# UBI Overhead = (B + 4) * SP + O * (P - B - 4)
SP = pebsize
SL = lebsize
P = int(part_size / pebsize)
Ox = SP - SL
try:
B = max(1, int((args.reserved / 100) * P), int(0.01 * P))
except Exception:
B = max(int(0.01 * P), 1)
ubi_overhead = (B + 4) * SP + Ox * (P - B - 4)
lebcnt = int((part_size - ubi_overhead) / pebsize)
internal_part_size = lebcnt * lebsize
tmpdir = mkdtemp()
if not args.ubionly:
logging.info("Creating ubifs")
ret, fs_path = create_ubifs(
args.input_path,
tmpdir,
internal_part_size,
pagesize,
pebsize,
args.mkfs,
args.verbose,
)
if ret:
logging.error("create ubifs error, please enable verbose!")
return -1
else:
fs_path = args.input_path
tmp_cfg_path = path.join(tmpdir, "tmp.cfg")
create_ubicfg(
fs_path,
internal_part_size,
label,
tmp_cfg_path,
(args.ubionly or part_size == sys.maxsize),
)
ret = create_ubi(
fs_path,
tmp_cfg_path,
args.output_path,
pagesize,
pebsize,
args.ubinize,
args.verbose,
)
if ret:
logging.error("create ubi image error, please enable verbose!")
return -1
return 0
if __name__ == "__main__":
main()

View File

@ -0,0 +1,107 @@
#!/bin/bash
function usage ()
{
echo "Usage: ${selfname} Chip Pagesize Blocksize Dir Size Tool_path Res"
echo " Chip Chip name. "
echo " Pagesize NAND page size. 2k/4k/8k."
echo " Blocksize NAND block size. 128k/256k/1M "
echo " Dir The directory you want to make ubifs"
echo " Size This ubifs partition size in NAND. 48M, ... 50M"
echo " UBI Tool The path of mkfs.ubifs and ubinize"
echo " Res Reserve ubiimg and ubifs both (1:Yes 0:No(default))"
echo ""
echo "Example:"
echo " ${selfname} hi35xx 2k 128k osdrv/pub/rootfs 50M osdrv/pub/bin/pc 0"
echo ""
exit 0
}
###############################################################################
function run ()
{
local cmd=$1
echo "${cmd}"
msg=$(eval "${cmd}"); result=$?
echo ${msg}
[ ${result} == 0 ] || exit ${result}
}
###############################################################################
function hstrtol ()
{
local hstr=$1
local zoom=1
local result=$(echo "${hstr}" | awk '{printf "%d",$0}')
if [ "$(echo ${hstr} | grep '[Gg]')" == "${hstr}" ]; then
zoom=1073741824
elif [ "$(echo ${hstr} | grep '[Mm]')" == "${hstr}" ]; then
zoom=1048576
elif [ "$(echo ${hstr} | grep '[Kk]')" == "${hstr}" ]; then
zoom=1024
fi
echo $((${result} * ${zoom}))
}
selfname=$(basename $0)
if [ $# != 7 ] && [ $# != 6 ]; then
usage;
fi
hpagesize=${2}
pagesize=$(hstrtol ${hpagesize})
hblocksize=${3}
blocksize=$(hstrtol ${hblocksize})
rootdir=$(echo $(echo "${4} " | sed 's/\/ //'))
#rootfs=${rootdir##*/}
rootfs=rootfs
hpartsize=${5}
partsize=$(hstrtol ${hpartsize})
chip=${1}
if [ ! -d ${rootdir} ]; then
echo "Directory ${rootdir} not exist."
exit 1;
fi
LEB=$((${blocksize} - ${pagesize} * 2))
MAX_LEB_CNT=$((${partsize} / ${blocksize}))
###############################################################################
ubiimg=${rootfs}_${chip}_${hpagesize}_${hblocksize}_${hpartsize}.ubiimg
ubifsimg=${rootfs}_${chip}_${hpagesize}_${hblocksize}_${hpartsize}.ubifs
ubicfg=${rootfs}_${chip}_${hpagesize}_${hblocksize}_${hpartsize}.ubicfg
MKUBIFS=$(echo $(echo "${6} " | sed 's/\/ //'))/mkfs.ubifs
MKUBI=$(echo $(echo "${6} " | sed 's/\/ //'))/ubinize
chmod +x ${MKUBIFS}
chmod +x ${MKUBI}
run "${MKUBIFS} -F -d ${rootdir} -m ${pagesize} -o ${ubiimg} -e ${LEB} -c ${MAX_LEB_CNT}"
{
echo "[ubifs-volumn]"
echo "mode=ubi"
echo "image=${ubiimg}"
echo "vol_id=0"
echo "vol_type=dynamic"
echo "vol_alignment=1"
echo "vol_name=ubifs"
echo "vol_flags=autoresize"
echo ""
} > ${ubicfg}
run "${MKUBI} -o ${ubifsimg} -m ${pagesize} -p ${blocksize} ${ubicfg}"
echo "--------- ${ubifsimg} is prepared !!"
if [ ! -n "${7}" ] || [ ${7} = 0 ]; then
rm -f ${ubiimg} ${ubicfg}
exit 1;
fi
echo "--------- ${ubiimg} is prepared !!"
echo "--------- ${ubicfg} is prepared !!"

View File

@ -0,0 +1,18 @@
CXX ?= g++
CXXFLAGS += "--std=c++11"
NANDBOOT_V2 ?= 0
ifeq ($(NANDBOOT_V2), 1)
CXXFLAGS += "-DNANDBOOT_V2"
endif
all:create_sv
create_sv:create_sv.cpp create_sv.h crc16.cpp crc.h
$(CXX) create_sv.cpp crc16.cpp -o create_sv $(CXXFLAGS)
run:create_sv
./create_sv
clean:
rm -rf create_sv

View File

@ -0,0 +1,43 @@
/*
*==========================================================================
*
* crc.h
*
* Interface for the CRC algorithms.
*
*==========================================================================
* SPDX-License-Identifier: eCos-2.0
*==========================================================================
*#####DESCRIPTIONBEGIN####
*
* Author(s): Andrew Lunn
* Contributors: Andrew Lunn
* Date: 2002-08-06
* Purpose:
* Description:
*
* This code is part of eCos (tm).
*
*####DESCRIPTIONEND####
*
*==========================================================================
*/
#ifndef _SERVICES_CRC_CRC_H_
#define _SERVICES_CRC_CRC_H_
#ifndef __externC
# ifdef __cplusplus
# define __externC extern "C"
# else
# define __externC extern
# endif
#endif
#include <stdint.h>
#include <sys/types.h>
/* 16 bit CRC with polynomial x^16+x^12+x^5+1 (CRC-CCITT) */
uint16_t crc16_ccitt(uint16_t crc_start, unsigned char *s, int len);
#endif /* _SERVICES_CRC_CRC_H_ */

View File

@ -0,0 +1,75 @@
/*
*==========================================================================
*
* crc16.c
*
* 16 bit CRC with polynomial x^16+x^12+x^5+1
*
*==========================================================================
* SPDX-License-Identifier: eCos-2.0
*==========================================================================
*#####DESCRIPTIONBEGIN####
*
* Author(s): gthomas
* Contributors: gthomas,asl
* Date: 2001-01-31
* Purpose:
* Description:
*
* This code is part of eCos (tm).
*
*####DESCRIPTIONEND####
*
*==========================================================================
*/
#include "crc.h"
#include <sys/types.h>
/* Table of CRC constants - implements x^16+x^12+x^5+1 */
static const uint16_t crc16_tab[] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
};
uint16_t crc16_ccitt(uint16_t crc_start, unsigned char *buf, int len)
{
int i;
uint16_t cksum;
cksum = crc_start;
for (i = 0; i < len; i++)
cksum = crc16_tab[((cksum>>8) ^ *buf++) & 0xff] ^ (cksum << 8);
return cksum;
}

View File

@ -0,0 +1,175 @@
#include <bits/stdint-uintn.h>
#include <iostream>
#include <sys/types.h>
#include <cstring>
#include <fstream>
#include "create_sv.h"
#include "crc.h"
#include <unistd.h> /* getopt */
using std::cout;
using std::endl;
using std::ios;
using std::string;
struct _spi_nand_info spinand_info;
struct _spi_nand_base_vector_t g_spi_nand_sys_vec;
void set_spi_nand_info(struct _spi_nand_info *nand_info)
{
nand_info->id = 0xefaa;
nand_info->page_size = _2K;
nand_info->spare_size = 64;
nand_info->pages_per_block = _128K / _2K;
nand_info->block_cnt = 32; // FIXME !!
nand_info->pages_per_block_shift = 6; // TODO: Caculate pages_per_block
nand_info->flags = 0;
#ifdef NANDBOOT_V2
// TODO: get ecc info form nand_chip_info
nand_info->ecc_en_feature_offset = 0xb0;
nand_info->ecc_en_mask = 1 << 4;
nand_info->ecc_status_offset = 0xc0;
nand_info->ecc_status_mask = 0x30;
nand_info->ecc_status_shift = 4;
nand_info->ecc_status_valid_val = 0xff;
#else
g_spi_nand_sys_vec.ecc_en_feature_offset = 0xb0;
g_spi_nand_sys_vec.ecc_en_mask = 1 << 4;
g_spi_nand_sys_vec.ecc_status_offset = 0xc0;
g_spi_nand_sys_vec.ecc_status_mask = 0x30;
g_spi_nand_sys_vec.ecc_status_shift = 4;
g_spi_nand_sys_vec.ecc_status_valid_val = 0xff;
#endif
}
int init_spi_nand_vect(int fip_blks_cnt = 1)
{
struct _spi_nand_base_vector_t *sv = &g_spi_nand_sys_vec;
struct _spi_nand_info *info = &spinand_info;
// struct cvsnfc_host *host = cvsnfc_get_host();
int i = 0, j = 0;
int blk_idx = 0;
memset(sv, 0, sizeof(struct _spi_nand_base_vector_t));
sv->signature = (uint32_t)SPI_NAND_VECTOR_SIGNATURE;
sv->version = SPI_NAND_VECTOR_VERSION;
sv->erase_count = 1;
sv->rsvd_block_count = SPI_NAND_BASE_BLOCK_COUNT;
sv->spi_nand_vector_length = sizeof(struct _spi_nand_base_vector_t);
sv->fip_bin_blk_cnt = fip_blks_cnt;
printf("sv length %d\n", sv->spi_nand_vector_length);
printf("fip_bin_blk_cnt %d\n", sv->fip_bin_blk_cnt);
// sv->bld_size = BLD_SIZE;
// sv->bld_loading_to_addr = (uintptr_t) BLD_BASE;
set_spi_nand_info(&sv->spi_nand_info);
/* memcpy(&sv->spi_nand_info, info, sizeof(struct _spi_nand_info)); */
// Useless parameters
// memcpy(sv->spi_nand_base_block_usage, spi_nand_defect_buf, SPI_NAND_BASE_BLOCK_MAX_COUNT_ENTRY);
// memcpy(sv->factory_defect_buf, spi_nand_defect_buf, sv->spi_nand_info.block_cnt / 8);
// fill_spi_nand_patch();
printf("[SPI_NAND][BASE]alloc spi_nand vector blocks\n");
// Alloc spi_nand vector blk
for (i = 0; i < SPI_NAND_BASE_DATA_BACKUP_COPY; i++) {
blk_idx = i;
sv->spi_nand_vector_blks[i] = blk_idx;
printf("[SPI_NAND][BASE]spi_nand vector block%d: %d\n", i,
blk_idx);
}
// Alloc fip.bin blocks
// fip = 640KB, blk sz = 128KB
for (i = 0; i < SPI_NAND_FIP_DATA_BACKUP_COUNT; i++) {
for (j = 0; j < sv->fip_bin_blk_cnt; j++) {
blk_idx = (i + 1) * 4 + j;
sv->fip_bin_blks[i][j] = blk_idx;
printf("[SPI_NAND][BASE] alloc fip block [%d][%d]: %d\n",
i, j, blk_idx);
}
}
#ifdef NANDBOOT_V2
sv->crc = crc16_ccitt(0, (unsigned char *)sv,
(int)(uintptr_t)&sv->crc - (uintptr_t)sv);
printf("[SPI_NAND][BASE] sv->crc:%d\n", sv->crc);
#endif
return 0;
}
void dump_nand_info(struct _spi_nand_info *nand_info)
{
cout << "ID:" << nand_info->id << endl;
cout << "Page size:" << nand_info->page_size << endl;
cout << "Spare size:" << nand_info->spare_size << endl;
cout << "pages_per_block:" << nand_info->pages_per_block << endl;
cout << "block count:" << nand_info->block_cnt << endl;
cout << "pages_per_block_shift" << nand_info->pages_per_block_shift
<< endl;
cout << "flags" << nand_info->flags << endl;
#ifdef NANDBOOT_V2
// TODO: get ecc info form nand_chip_info
printf("ecc_en_feature_offset:0x%x\n",
nand_info->ecc_en_feature_offset);
printf("ecc_en_mask:0x%x\n", nand_info->ecc_en_mask);
printf("ecc_status_offset:0x%x\n", nand_info->ecc_status_offset);
printf("ecc_status_mask:0x%x\n", nand_info->ecc_status_mask);
printf("ecc_status_shift:%d\n", nand_info->ecc_status_shift);
printf("ecc_status_valid_val:0x%x\n", nand_info->ecc_status_valid_val);
#endif
}
int main(int argc, char *argv[])
{
string output = "sv.bin";
int cmd_opt = 0;
int fip_blks_cnt = 1;
while (1) {
cmd_opt = getopt(argc, argv, "o:c:");
/* End condition always first */
if (cmd_opt == -1) {
break;
}
/* Print option when it is valid */
if (cmd_opt != '?') {
fprintf(stderr, "option:-%c\n", cmd_opt);
}
/* Lets parse */
switch (cmd_opt) {
/* No args */
case 'c':
fip_blks_cnt = atoi(optarg);
break;
case 'o':
output = optarg;
break;
/* Error handle: Mainly missing arg or illegal option */
case '?':
fprintf(stderr, "Illegal option:-%c\n",
isprint(optopt) ? optopt : '#');
break;
default:
fprintf(stderr, "Not supported option\n");
break;
}
}
std::ofstream ofs(output, ios::out | ios::binary);
init_spi_nand_vect(fip_blks_cnt);
dump_nand_info(&g_spi_nand_sys_vec.spi_nand_info);
cout << "Output: " << output << endl;
#ifdef NANDBOOT_V2
printf("sv crc:%x\n", g_spi_nand_sys_vec.crc);
#endif
char *output_buf = new char[_2K];
memset(output_buf, 0xff, _2K);
memcpy(output_buf, &g_spi_nand_sys_vec,
sizeof(_spi_nand_base_vector_t));
for (int i = 0; i < g_spi_nand_sys_vec.spi_nand_info.pages_per_block;
i++) {
ofs.write(output_buf, _2K);
}
ofs.close();
return 0;
}

View File

@ -0,0 +1,134 @@
#ifndef CREATE_SV_H
#define CREATE_SV_H
#include <sys/types.h>
#define SPI_NAND_VECTOR_SIGNATURE DESC_CONV("SPNV")
#define PRODUCTION_FW_SIGNATURE DESC_CONV("PTFM")
#define SPI_NAND_VECTOR_VERSION (0x18802001)
#define SPI_NAND_BASE_DATA_BACKUP_COPY (2)
#define SPI_NAND_FIP_DATA_BLOCK_COUNT (8)
#define SPI_NAND_FIP_DATA_BACKUP_COUNT (2)
#define SPI_NAND_FIP_RSVD_BLOCK_COUNT \
(4) // first 4 blocks are reserved for sys base vector
#define SPI_NAND_BASE_BLOCK_COUNT (32) // must aligned to 8
#define SPI_NAND_BASE_BLOCK_MAX_COUNT_ENTRY (SPI_NAND_BASE_BLOCK_COUNT / 8)
#define BIT(nr) (1UL << (nr))
#define MAX_SPARE_SIZE 128
#define MAX_BLOCK_CNT 4096
#define NUMBER_PATCH_SET 128
#define _512B (512)
#define _1K (1024)
#define _2K (2048)
#define _4K (4096)
#define _8K (8192)
#define _16K (16384)
#define _32K (32768)
#define _64K (0x10000UL)
#define _128K (0x20000UL)
#define _256K (0x40000UL)
#define _512K (0x80000UL)
#define _1M (0x100000UL)
#define _2M (0x200000UL)
#define _4M (0x400000UL)
#define _8M (0x800000UL)
#define _16M (0x1000000UL)
#define _32M (0x2000000UL)
#define _64M (0x4000000UL)
#define _128M (0x8000000UL)
#define _256M (0x10000000UL)
#define _512M (0x20000000UL)
#define _1G (0x40000000ULL)
#define _2G (0x80000000ULL)
#define _4G (0x100000000ULL)
#define _8G (0x200000000ULL)
#define _16G (0x400000000ULL)
#define _64G (0x1000000000ULL)
#define ECC_TYPE_0BIT 0x0
#define ECC_TYPE_8BIT 0x1
#define ECC_TYPE_16BIT 0x2
#define ECC_TYPE_24BIT 0x3
#define ECC_TYPE_28BIT 0x4
#define ECC_TYPE_40BIT 0x5
#define ECC_TYPE_64BIT 0x6
#define PAGE_SIZE_2KB 0x0
#define PAGE_SIZE_4KB 0x1
#define PAGE_SIZE_8KB 0x2
#define PAGE_SIZE_16KB 0x3
struct _patch_data_t {
uint32_t reg;
uint32_t value;
};
struct _spi_nand_info {
uint16_t id;
uint16_t page_size;
uint16_t spare_size;
uint16_t pages_per_block;
uint16_t block_cnt; // up to 32k block
uint8_t pages_per_block_shift;
uint8_t flags;
#ifdef NANDBOOT_V2
uint8_t ecc_en_feature_offset;
uint8_t ecc_en_mask;
uint8_t ecc_status_offset;
uint8_t ecc_status_mask;
uint8_t ecc_status_shift;
uint8_t ecc_status_valid_val;
#endif
};
struct _spi_nand_base_vector_t {
uint32_t signature;
uint32_t version;
uint16_t spi_nand_vector_blks[SPI_NAND_BASE_DATA_BACKUP_COPY];
uint16_t fip_bin_blk_cnt;
uint16_t fip_bin_blks[SPI_NAND_BASE_DATA_BACKUP_COPY]
[SPI_NAND_FIP_DATA_BLOCK_COUNT];
uint16_t erase_count; // erase count for sys base block
uint16_t rsvd_block_count; // how many blocks reserved for spi_nand_vect and fip.bin
uint32_t spi_nand_vector_length; // spi_nand vector struct length, must less than a page
uint8_t spi_nand_base_block_usage
[SPI_NAND_BASE_BLOCK_MAX_COUNT_ENTRY]; // 32 bits => 1 DW
struct _spi_nand_info spi_nand_info;
uint8_t factory_defect_buf[MAX_BLOCK_CNT /
8]; // factory defect block table, up to 512 bytes
uint32_t bld_size;
uintptr_t bld_loading_to_addr;
uint32_t valid_patch_num;
struct _patch_data_t patch_data[NUMBER_PATCH_SET];
#ifdef NANDBOOT_V2
uint16_t crc;
#else
uint8_t ecc_en_feature_offset;
uint8_t ecc_en_mask;
uint8_t ecc_status_offset;
uint8_t ecc_status_mask;
uint8_t ecc_status_shift;
uint8_t ecc_status_valid_val;
#endif
};
static inline uint32_t DESC_CONV(char *x)
{
return ((((((x[0] << 8) | x[1]) << 8) | x[2]) << 8) | x[3]);
}
#endif

Binary file not shown.