[build] add cvitek build scripts
Change-Id: If63ce4a669e5d4d72b8e3b9253336dd99bf74c30
This commit is contained in:
119
build/tools/common/spinand_tool/XmlParser.py
Normal file
119
build/tools/common/spinand_tool/XmlParser.py
Normal 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"
|
||||
6
build/tools/common/spinand_tool/fip_maker/Makefile
Normal file
6
build/tools/common/spinand_tool/fip_maker/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
CC = gcc -s
|
||||
|
||||
all: fip_maker
|
||||
|
||||
clean:
|
||||
$(RM) fip_maker
|
||||
342
build/tools/common/spinand_tool/fip_maker/fip_maker.c
Normal file
342
build/tools/common/spinand_tool/fip_maker/fip_maker.c
Normal 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;
|
||||
}
|
||||
BIN
build/tools/common/spinand_tool/mkfs.ubifs
Executable file
BIN
build/tools/common/spinand_tool/mkfs.ubifs
Executable file
Binary file not shown.
281
build/tools/common/spinand_tool/mkubiimg.py
Executable file
281
build/tools/common/spinand_tool/mkubiimg.py
Executable 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()
|
||||
107
build/tools/common/spinand_tool/mkubiimg.sh
Executable file
107
build/tools/common/spinand_tool/mkubiimg.sh
Executable 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 !!"
|
||||
18
build/tools/common/spinand_tool/sv_tool/Makefile
Normal file
18
build/tools/common/spinand_tool/sv_tool/Makefile
Normal 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
|
||||
43
build/tools/common/spinand_tool/sv_tool/crc.h
Normal file
43
build/tools/common/spinand_tool/sv_tool/crc.h
Normal 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_ */
|
||||
75
build/tools/common/spinand_tool/sv_tool/crc16.cpp
Normal file
75
build/tools/common/spinand_tool/sv_tool/crc16.cpp
Normal 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;
|
||||
}
|
||||
175
build/tools/common/spinand_tool/sv_tool/create_sv.cpp
Normal file
175
build/tools/common/spinand_tool/sv_tool/create_sv.cpp
Normal 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;
|
||||
}
|
||||
134
build/tools/common/spinand_tool/sv_tool/create_sv.h
Normal file
134
build/tools/common/spinand_tool/sv_tool/create_sv.h
Normal 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
|
||||
BIN
build/tools/common/spinand_tool/ubinize
Executable file
BIN
build/tools/common/spinand_tool/ubinize
Executable file
Binary file not shown.
Reference in New Issue
Block a user