[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/bsp/scatter/Android.mk b/src/bsp/scatter/Android.mk
new file mode 100644
index 0000000..b01788f
--- /dev/null
+++ b/src/bsp/scatter/Android.mk
@@ -0,0 +1,20 @@
+LOCAL_PATH := $(call my-dir)
+EMMC_ROOT_DIR := ${PWD}/$(LOCAL_PATH)
+NEW_EMMC_ROOT_DIR := ${PWD}/$(LOCAL_PATH)/../project/recipes-bsp/scatter/files
+INSTALLED_MMCO_TARGET := $(PRODUCT_OUT)/MBR_EMMC
+BUILT_MMCO_TARGET := $(PRODUCT_OUT)/MBR_EMMC_BOOT0
+SCATTER_SRC := ${PWD}/$(LOCAL_PATH)/scripts
+
+$(BUILT_MMCO_TARGET):
+ $(hide) $(EMMC_ROOT_DIR)/scripts/gen-partitions.sh $(NEW_EMMC_ROOT_DIR)/$(SCATTER_PROJECT) ${PRODUCT_OUT} ${BOOTDEV_TYPE} ${SCATTER_SRC} ${NAND_CHIP_NAME} ${NAND_HEADER_VERSION}
+
+
+ ifneq ($(INSTALLED_MMCO_TARGET),$(BUILT_MMCO_TARGET))
+$(INSTALLED_MMCO_TARGET): $(BUILT_MMCO_TARGET)
+ endif
+
+.PHONY: mmco
+droidcore: $(INSTALLED_MMCO_TARGET)
+mmco: $(INSTALLED_MMCO_TARGET)
+
+ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_MMCO_TARGET)
diff --git a/src/bsp/scatter/LICENSE b/src/bsp/scatter/LICENSE
new file mode 100755
index 0000000..6e16090
--- /dev/null
+++ b/src/bsp/scatter/LICENSE
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+the prior written permission of MediaTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MediaTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MediaTek Inc. (C) 2017. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
diff --git a/src/bsp/scatter/README b/src/bsp/scatter/README
new file mode 100644
index 0000000..c452cae
--- /dev/null
+++ b/src/bsp/scatter/README
@@ -0,0 +1,2 @@
+The "scatter" directory is intended for Mediatek solution Scatter File.
+
diff --git a/src/bsp/scatter/scripts/dev-info-hdr-tool.py b/src/bsp/scatter/scripts/dev-info-hdr-tool.py
new file mode 100644
index 0000000..3084eef
--- /dev/null
+++ b/src/bsp/scatter/scripts/dev-info-hdr-tool.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python3
+
+import argparse
+import os
+import struct
+import sys
+
+def read(path):
+ with open(path, "rb") as f:
+ return f.read()
+
+def write(path, data):
+ with open(path, "wb") as f:
+ f.write(data)
+
+def padding(data, size, pattern = b'\0'):
+ return data + pattern * (size - len(data))
+
+def align(data, size, pattern = b'\0'):
+ return padding(data, (len(data) + (size - 1)) & ~(size - 1), pattern)
+
+def gen_nor_bl_img(data):
+ data = align(data, 512, '\xff')
+ header = (padding(struct.pack("<12sII", "SF_BOOT", 1, 512), 512, '\xff') +
+ padding(struct.pack("<8sIIIIIIII", "BRLYT", 1, 2048, 2048 + len(data),
+ 0x42424242, 0x00010007, 2048, 2048 + len(data), 1) + '\0' * 140, 512, '\xff') +
+ '\0' * 1024)
+ return header + data
+
+def gen_emmc_bl_img(data):
+ data = align(data, 512, b'\xff')
+ header = (padding(struct.pack("<12sII", b"EMMC_BOOT", 1, 512), 512, b'\xff') +
+ padding(struct.pack("<8sIIIIIIII", b"BRLYT", 1, 2048, 2048 + len(data),
+ 0x42424242, 0x00010005, 2048, 2048 + len(data), 1) + b'\0' * 140, 512, b'\xff') +
+ b'\0' * 1024)
+ return header + data
+
+def gen_sdcard_bl_img(data):
+ data = align(data, 512, '\xff')
+ header = (padding(struct.pack("<12sII", "SDMMC_BOOT", 1, 512), 512, '\xff') +
+ padding(struct.pack("<8sIIIIIIII", "BRLYT", 1, 2048, 2048 + len(data),
+ 0x42424242, 0x00010008, 2048, 2048 + len(data), 1) + '\0' * 140, 512, '\xff') +
+ '\0' * 1024)
+ return header + data
+
+def get_page_size(nand_name):
+ with open("scripts/nand-setting.txt", "r") as f:
+ for l in f:
+ s = l.split("\t")
+ if s[0] == nand_name:
+ return int(s[1])
+ raise KeyError("not support " + nand_name)
+
+def gen_nand_bl_img(data, nand_name, page_number_bl1, page_number_bl2):
+ hdr1 = "temp1.hdr"
+ hdr2 = "temp2.hdr"
+ page_size = get_page_size(nand_name)
+ data = align(data, 128*page_size, '\xff')
+ os.system("./tools/bch h {0} null {1} 1 {2} 0 0".format(nand_name, hdr1, page_number_bl1))
+ os.system("./tools/bch h {0} null {1} 1 {2} 0 0".format(nand_name, hdr2, page_number_bl2))
+ header1 = padding(read(hdr1), 256*page_size, '\xff')
+ header2 = padding(read(hdr2), 256*page_size, '\xff')
+ os.remove(hdr1)
+ os.remove(hdr2)
+ return header1 + header2 + data + data
+
+def main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('type', default='emmc', help='emmc | nand | nor | sdcard')
+ parser.add_argument('in_image', help='input file path')
+ parser.add_argument('out_image', help='output image path')
+ parser.add_argument('nand_name', nargs='?', help='nand chip name')
+ parser.add_argument('bl1', type=int, nargs='?', default=0, help='page number of bl1. default=0')
+ parser.add_argument('bl2', type=int, nargs='?', default=0, help='page number of bl2. default=0')
+ args = parser.parse_args()
+
+ if args.type == 'emmc':
+ r = gen_emmc_bl_img(read(args.in_image))
+ elif args.type == 'nor':
+ r = gen_nor_bl_img(read(args.in_image))
+ elif args.type == 'sdcard':
+ r = gen_sdcard_bl_img(read(args.in_image))
+ elif args.type == 'nand':
+ r = gen_nand_bl_img(read(args.in_image), args.nand_name, args.bl1, args.bl2)
+ else:
+ print("unknown type: " + args.type)
+ return 1
+
+ write(args.out_image, r)
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/src/bsp/scatter/scripts/gen-partition-nand.py b/src/bsp/scatter/scripts/gen-partition-nand.py
new file mode 100755
index 0000000..365a0ea
--- /dev/null
+++ b/src/bsp/scatter/scripts/gen-partition-nand.py
@@ -0,0 +1,208 @@
+#!/usr/bin/env python3
+
+from __future__ import print_function
+import binascii
+import json
+import os
+import struct
+import sys
+import uuid
+import xml.dom.minidom
+
+NumberOfPartitionEntries = 128
+SizeOfPartitionEntry = 128
+
+def write(path, data):
+ with open(path, "wb+") as f:
+ f.write(data)
+
+def crc32(data):
+ return binascii.crc32(data) & 0xffffffff
+
+def padding(data, size):
+ return data + b'\0' * (size - len(data))
+
+def gen_gpt(partition):
+ pmbr = (b'\0' * 446 +
+ b"\x00\x00\x02\x00\xee\xff\xff\xff\x01\x00\x00\x00\xff\xff\xff\xff" +
+ b'\0' * 48 + b"\x55\xaa")
+ entries = b''
+ for node in partition.childNodes:
+ if node.nodeName != "entry":
+ continue
+ type = uuid.UUID(node.getAttribute("type"))
+ uniq = node.getAttribute("uuid")
+ uniq = uniq and uuid.UUID(uniq) or uuid.uuid4()
+ start = eval(node.getAttribute("start"))
+ end = eval(node.getAttribute("end"))
+ attr = node.getAttribute("attributes")
+ attr = attr and eval(attr) or 0
+ name = node.getAttribute("name")
+ entries += struct.pack("<16s16sQQQ72s",
+ type.bytes_le,
+ uniq.bytes_le,
+ int(start), end, attr,
+ name.encode("utf-16le"))
+ entries = padding(entries, NumberOfPartitionEntries * SizeOfPartitionEntry)
+ lba = eval(partition.getAttribute("lba"))
+ lbs = partition.getAttribute("lbs")
+ lbs = lbs and eval(lbs) or 512
+ FirstUsableLBA = 2 + (NumberOfPartitionEntries * SizeOfPartitionEntry / lbs)
+ uniq = partition.getAttribute("uuid")
+ uniq = uniq and uuid.UUID(uniq) or uuid.uuid4()
+ pmbr = padding(pmbr, lbs)
+ header = struct.pack("<8sIIIIQQQQ16sQIII",
+ b"EFI PART", 0x00010000, 92, 0, 0,
+ 1, # MyLBA
+ 1, #lba - 1, # AlternateLBA
+ int(FirstUsableLBA),
+ int(lba - FirstUsableLBA), # LastUsableLBA
+ uniq.bytes_le,
+ 2, int(NumberOfPartitionEntries), int(SizeOfPartitionEntry), crc32(entries))
+ header = padding(header[:16] +
+ struct.pack('I', crc32(header)) +
+ header[20:], lbs)
+ return pmbr + header + entries
+
+def write_scatter_partition(f, entry):
+ if entry.get("file_name", "NONE") != "NONE":
+ entry.setdefault("is_download", True)
+ entry.setdefault("operation_type", "UPDATE")
+ entry.setdefault("type", "NORMAL_ROM")
+ f.write(
+"""- partition_index: %s
+ partition_name: %s
+ file_name: %s
+ is_download: %s
+ type: %s
+ linear_start_addr: %s
+ physical_start_addr: %s
+ partition_size: %s
+ region: %s
+ storage: %s
+ boundary_check: %s
+ is_reserved: %s
+ operation_type: %s
+ d_type: LOW_PAGE
+ slc_percentage: 0
+ is_upgradable: true
+ reserve: %s
+
+""" % (entry["partition_index"], entry["partition_name"], entry.get("file_name", "NONE"),
+entry.get("is_download", False) and "true" or "false", entry.get("type", "NONE"), hex(entry["linear_start_addr"]),
+hex(entry["physical_start_addr"]), hex(entry["partition_size"]), entry.get("region", "NONE"),
+entry.get("storage", "HW_STORAGE_NAND"), entry.get("boundary_check", True) and "true" or "false",
+entry.get("is_reserved", False) and "true" or "false", entry.get("operation_type", "PROTECTED"),
+hex(entry.get("reserve", 0))))
+
+def write_scatter(f, partition, d):
+ f.write(
+"""############################################################################################################
+#
+# General Setting
+#
+############################################################################################################
+- general: MTK_PLATFORM_CFG
+ info:
+ - config_version: %s
+ platform: %s
+ project: %s
+ storage: %s
+ boot_channel: %s
+ block_size: %s
+ skip_pmt_operate: %s
+############################################################################################################
+#
+# Layout Setting
+#
+############################################################################################################
+""" % (d["MTK_PLATFORM_CFG"]["config_version"], d["MTK_PLATFORM_CFG"]["platform"], d["MTK_PLATFORM_CFG"]["project"],
+ d["MTK_PLATFORM_CFG"]["storage"], d["MTK_PLATFORM_CFG"]["boot_channel"], d["MTK_PLATFORM_CFG"]["block_size"],
+ d["MTK_PLATFORM_CFG"].get("skip_pmt_operate", True) and "true" or "false"))
+# d["PRELOADER"]["partition_index"] = "SYS0"
+ d["MBR"]["partition_index"] = "SYS0"
+# write_scatter_partition(f, d["PRELOADER"])
+ write_scatter_partition(f, d["MBR"])
+ lbs = partition.getAttribute("lbs")
+ lbs = lbs and eval(lbs) or 512
+ i = 1
+ for node in partition.childNodes:
+ if node.nodeName != "entry":
+ continue
+ start = eval(node.getAttribute("start"))
+ end = eval(node.getAttribute("end"))
+ name = node.getAttribute("name")
+ if name not in d:
+ continue
+ entry = d[name]
+ entry["partition_name"] = name
+ entry["partition_index"] = "SYS%d" % i
+ i += 1
+ entry["linear_start_addr"] = start * lbs
+ entry["physical_start_addr"] = start * lbs
+ if end != start:
+ entry["partition_size"] = (end + 1 - start) * lbs
+ else:
+ entry["partition_size"] = 0
+ write_scatter_partition(f, entry)
+ if (d["MTK_PLATFORM_CFG"].get("skip_pmt_operate", True) and "true" or "false") == "false":
+ d["sgpt"]["partition_index"] = "SYS%d" % i
+ write_scatter_partition(f, d["sgpt"])
+
+
+def sanity_check(path, partition):
+ err = 0
+ lba = eval(partition.getAttribute("lba"))
+ lbs = partition.getAttribute("lbs")
+ lbs = lbs and eval(lbs) or 512
+ FirstUsableLBA = 2 + (NumberOfPartitionEntries * SizeOfPartitionEntry / lbs)
+ usable = (FirstUsableLBA, lba - FirstUsableLBA)
+ used = {}
+ for node in partition.childNodes:
+ if node.nodeName != "entry":
+ continue
+ name = node.getAttribute("name")
+ start = eval(node.getAttribute("start"))
+ end = eval(node.getAttribute("end"))
+ if start > end:
+ print("%s: error: partition '%s': start lba (%d) > end lba (%d)" %
+ (path, name, start, end), file = sys.stderr)
+ err += 1
+ if start < usable[0] or end > usable[1]:
+ print("%s: error: partition '%s': (%d...%d) out of usable range (%d...%d)" %
+ (path, name, start, end, usable[0], usable[1]), file = sys.stderr)
+ err += 1
+ for i in used:
+ if (used[i][0] <= start and start <= used[i][1] or
+ used[i][0] <= end and end <= used[i][1]):
+ print("%s: error: partition '%s': (%d...%d) overlapped with partition '%s' (%d...%d)" %
+ (path, name, start, end, i, used[i][0], used[i][1]), file = sys.stderr)
+ err += 1
+ used[name] = (start, end)
+ return err
+
+def main(argv):
+ if len(argv) == 5: # normal argument list len(argv) = 5 #
+ print ("len:%d .py=%s .xml=%s .json=%s MBR=%s .txt=%s" %
+ (len(argv), argv[0], argv[1], argv[2], argv[3], argv[4]))
+ if len(argv) <= 3: # len(argv) = 4 for mt2701 spi nor boot (scatter.txt isn't needed) #
+ print("Usage: len:%d,%s partition_*.xml scatter_*.json [MBR] [scatter.txt] " % (len(argv), argv[0]))
+ exit(1)
+ root = xml.dom.minidom.parse(argv[1])
+ for partition in root.childNodes:
+ if partition.nodeName == "partition":
+ break
+ else:
+ raise Exception("partition not found")
+ if sanity_check(argv[1], partition):
+ return 1
+ write(argv[3], gen_gpt(partition))
+ if len(argv) == 5:
+ with open(os.path.join(os.path.dirname(__file__), argv[2]), "r") as f:
+ d = json.load(f)
+ with open(argv[4], "w") as f:
+ write_scatter(f, partition, d)
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/src/bsp/scatter/scripts/gen-partition-nand_merge.py b/src/bsp/scatter/scripts/gen-partition-nand_merge.py
new file mode 100755
index 0000000..3ce67f0
--- /dev/null
+++ b/src/bsp/scatter/scripts/gen-partition-nand_merge.py
@@ -0,0 +1,248 @@
+#!/usr/bin/env python3
+
+from __future__ import print_function
+import binascii
+import json
+import os
+import struct
+import sys
+import uuid
+import xml.dom.minidom
+
+NumberOfPartitionEntries = 64
+SizeOfPartitionEntry = 128
+
+def write(path, data):
+ with open(path, "wb+") as f:
+ f.write(data)
+
+def crc32(data):
+ return binascii.crc32(data) & 0xffffffff
+
+def padding(data, size):
+ return data + b'\0' * (size - len(data))
+
+def gen_gpt(partition):
+ pmbr = (b'\0' * 446 +
+ b"\x00\x00\x02\x00\xee\xff\xff\xff\x01\x00\x00\x00\xff\xff\xff\xff" +
+ b'\0' * 48 + b"\x55\xaa")
+ entries = b''
+ entries2k = b''
+ lba = partition.getAttribute("lba")
+ lba = lba and eval(lba) or 130560
+ lbs = partition.getAttribute("lbs")
+ lbs = lbs and eval(lbs) or 4096
+ for node in partition.childNodes:
+ if node.nodeName != "entry":
+ continue
+ type = uuid.UUID(node.getAttribute("type"))
+ uniq = node.getAttribute("uuid")
+ uniq = uniq and uuid.UUID(uniq) or uuid.uuid4()
+ start = eval(node.getAttribute("start"))
+ end = eval(node.getAttribute("end"))
+ attr = node.getAttribute("attributes")
+ attr = attr and eval(attr) or 0
+ name = node.getAttribute("name")
+ if (name == b"userdata") and (end == 0):
+ end = lba - 1
+ if attr == 4:
+ start2k = (start / 256) * 256 + 8
+ entries2k += struct.pack("<16s16sQQQ72s",
+ type.bytes_le,
+ uniq.bytes_le,
+ int(start2k), end, 4,
+ name.encode("utf-16le"))
+ if ((start % 256) == 0):
+ start = (start / 256) * 256 + 4
+ entries += struct.pack("<16s16sQQQ72s",
+ type.bytes_le,
+ uniq.bytes_le,
+ int(start), end, attr,
+ name.encode("utf-16le"))
+ entries = padding(entries, NumberOfPartitionEntries * SizeOfPartitionEntry)
+ entries2k = padding(entries2k, 2048)
+ FirstUsableLBA = 2 + (NumberOfPartitionEntries * SizeOfPartitionEntry / lbs)
+ uniq = partition.getAttribute("uuid")
+ uniq = uniq and uuid.UUID(uniq) or uuid.uuid4()
+ if lbs == 4096:
+ pmbr = padding(pmbr, 2048)
+ else:
+ pmbr = padding(pmbr, lbs)
+ header2k = struct.pack("<8sIIIIQQQQ16sQIII",
+ b"EFI PART", 0x00010000, 92, 0, 0,
+ 1, # MyLBA
+ 1, #lba - 1, # AlternateLBA
+ int(FirstUsableLBA),
+ int(lba - FirstUsableLBA), # LastUsableLBA
+ uniq.bytes_le,
+ 3, 4, int(SizeOfPartitionEntry), crc32(entries2k))
+ header2k = padding(header2k[:16] +
+ struct.pack('I', crc32(header2k)) +
+ header2k[20:], 2048)
+ header = struct.pack("<8sIIIIQQQQ16sQIII",
+ b"EFI PART", 0x00010000, 92, 0, 0,
+ 1, # MyLBA
+ 1, #lba - 1, # AlternateLBA
+ int(FirstUsableLBA),
+ int(lba - FirstUsableLBA), # LastUsableLBA
+ uniq.bytes_le,
+ 2, int(NumberOfPartitionEntries), int(SizeOfPartitionEntry), crc32(entries))
+ if lbs == 4096:
+ header = padding(header[:16] +
+ struct.pack('I', crc32(header)) +
+ header[20:], 2048)
+ else:
+ header = padding(header[:16] +
+ struct.pack('I', crc32(header)) +
+ header[20:], lbs)
+ if lbs == 4096:
+ return pmbr + header2k + header + entries2k + entries
+ else:
+ return pmbr + header + entries
+
+def write_scatter_partition(f, entry):
+ if entry.get("file_name", "NONE") != "NONE":
+ entry.setdefault("is_download", True)
+ entry.setdefault("operation_type", "UPDATE")
+ entry.setdefault("type", "NORMAL_ROM")
+ f.write(
+"""- partition_index: %s
+ partition_name: %s
+ file_name: %s
+ is_download: %s
+ type: %s
+ linear_start_addr: %s
+ physical_start_addr: %s
+ partition_size: %s
+ region: %s
+ storage: %s
+ boundary_check: %s
+ is_reserved: %s
+ operation_type: %s
+ d_type: LOW_PAGE
+ slc_percentage: 0
+ is_upgradable: true
+ reserve: %s
+
+""" % (entry["partition_index"], entry["partition_name"], entry.get("file_name", "NONE"),
+entry.get("is_download", False) and "true" or "false", entry.get("type", "NONE"), hex(entry["linear_start_addr"]),
+hex(entry["physical_start_addr"]), hex(entry["partition_size"]), entry.get("region", "NONE"),
+entry.get("storage", "HW_STORAGE_NAND"), entry.get("boundary_check", True) and "true" or "false",
+entry.get("is_reserved", False) and "true" or "false", entry.get("operation_type", "PROTECTED"),
+hex(entry.get("reserve", 0))))
+
+def write_scatter(f, partition, d):
+ f.write(
+"""############################################################################################################
+#
+# General Setting
+#
+############################################################################################################
+- general: MTK_PLATFORM_CFG
+ info:
+ - config_version: %s
+ platform: %s
+ project: %s
+ storage: %s
+ boot_channel: %s
+ block_size: %s
+ skip_pmt_operate: %s
+############################################################################################################
+#
+# Layout Setting
+#
+############################################################################################################
+""" % (d["MTK_PLATFORM_CFG"]["config_version"], d["MTK_PLATFORM_CFG"]["platform"], d["MTK_PLATFORM_CFG"]["project"],
+ d["MTK_PLATFORM_CFG"]["storage"], d["MTK_PLATFORM_CFG"]["boot_channel"], d["MTK_PLATFORM_CFG"]["block_size"],
+ d["MTK_PLATFORM_CFG"].get("skip_pmt_operate", True) and "true" or "false"))
+# d["PRELOADER"]["partition_index"] = "SYS0"
+ d["MBR"]["partition_index"] = "SYS0"
+# write_scatter_partition(f, d["PRELOADER"])
+ write_scatter_partition(f, d["MBR"])
+ lbs = partition.getAttribute("lbs")
+ lbs = lbs and eval(lbs) or 4096
+ i = 1
+ for node in partition.childNodes:
+ if node.nodeName != "entry":
+ continue
+ start = eval(node.getAttribute("start"))
+ end = eval(node.getAttribute("end"))
+ name = node.getAttribute("name")
+ if name not in d:
+ continue
+ entry = d[name]
+ entry["partition_name"] = name
+ entry["partition_index"] = "SYS%d" % i
+ i += 1
+ entry["linear_start_addr"] = start * lbs
+ entry["physical_start_addr"] = start * lbs
+ if end != start:
+ entry["partition_size"] = (end + 1 - start) * lbs
+ else:
+ entry["partition_size"] = 0
+ write_scatter_partition(f, entry)
+ if (d["MTK_PLATFORM_CFG"].get("skip_pmt_operate", True) and "true" or "false") == "false":
+ d["sgpt"]["partition_index"] = "SYS%d" % i
+ write_scatter_partition(f, d["sgpt"])
+
+
+def sanity_check(path, partition):
+ err = 0
+ lba = partition.getAttribute("lba")
+ lba = lba and eval(lba) or 130560
+ lbs = partition.getAttribute("lbs")
+ lbs = lbs and eval(lbs) or 4096
+ FirstUsableLBA = 2 + (NumberOfPartitionEntries * SizeOfPartitionEntry / lbs)
+# usable = (FirstUsableLBA, lba - FirstUsableLBA)
+ usable = (0, lba)
+ used = {}
+ for node in partition.childNodes:
+ if node.nodeName != "entry":
+ continue
+ name = node.getAttribute("name")
+ start = eval(node.getAttribute("start"))
+ end = eval(node.getAttribute("end"))
+ if (name == "userdata") and (end == 0):
+ end = lba - 1
+ if start > end:
+ print("%s: error: partition '%s': start lba (%d) > end lba (%d)" %
+ (path, name, start, end), file = sys.stderr)
+ err += 1
+ if start < usable[0] or end > usable[1]:
+ print("%s: error: partition '%s': (%d...%d) out of usable range (%d...%d)" %
+ (path, name, start, end, usable[0], usable[1]), file = sys.stderr)
+ err += 1
+ for i in used:
+ if (used[i][0] <= start and start <= used[i][1] or
+ used[i][0] <= end and end <= used[i][1]):
+ print("%s: error: partition '%s': (%d...%d) overlapped with partition '%s' (%d...%d)" %
+ (path, name, start, end, i, used[i][0], used[i][1]), file = sys.stderr)
+ err += 1
+ used[name] = (start, end)
+ return err
+
+def main(argv):
+ if len(argv) == 5: # normal argument list len(argv) = 5 #
+ print ("len:%d .py=%s .xml=%s .json=%s MBR=%s .txt=%s" %
+ (len(argv), argv[0], argv[1], argv[2], argv[3], argv[4]))
+ if len(argv) <= 3: # len(argv) = 4 for mt2701 spi nor boot (scatter.txt isn't needed) #
+ print("Usage: len:%d,%s partition_*.xml scatter_*.json [MBR] [scatter.txt] " % (len(argv), argv[0]))
+ exit(1)
+ root = xml.dom.minidom.parse(argv[1])
+ for partition in root.childNodes:
+ if partition.nodeName == "partition":
+ break
+ else:
+ raise Exception("partition not found")
+ if sanity_check(argv[1], partition):
+ return 1
+ write(argv[3], gen_gpt(partition))
+ if len(argv) == 5:
+ with open(os.path.join(os.path.dirname(__file__), argv[2]), "r") as f:
+ d = json.load(f)
+ with open(argv[4], "w") as f:
+ write_scatter(f, partition, d)
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
\ No newline at end of file
diff --git a/src/bsp/scatter/scripts/gen-partition.py b/src/bsp/scatter/scripts/gen-partition.py
new file mode 100755
index 0000000..42d0b82
--- /dev/null
+++ b/src/bsp/scatter/scripts/gen-partition.py
@@ -0,0 +1,206 @@
+#!/usr/bin/env python
+
+from __future__ import print_function
+import binascii
+import json
+import os
+import struct
+import sys
+import uuid
+import xml.dom.minidom
+
+NumberOfPartitionEntries = 128
+SizeOfPartitionEntry = 128
+
+def write(path, data):
+ with open(path, "wb+") as f:
+ f.write(data)
+
+def crc32(data):
+ return binascii.crc32(data) & 0xffffffff
+
+def padding(data, size):
+ return data + b'\0' * (size - len(data))
+
+def gen_gpt(partition):
+ pmbr = (b'\0' * 446 +
+ b"\x00\x00\x02\x00\xee\xff\xff\xff\x01\x00\x00\x00\xff\xff\xff\xff" +
+ b'\0' * 48 + b"\x55\xaa")
+ entries = b''
+ for node in partition.childNodes:
+ if node.nodeName != "entry":
+ continue
+ type = uuid.UUID(node.getAttribute("type"))
+ uniq = node.getAttribute("uuid")
+ uniq = uniq and uuid.UUID(uniq) or uuid.uuid4()
+ start = eval(node.getAttribute("start"))
+ end = eval(node.getAttribute("end"))
+ attr = node.getAttribute("attributes")
+ attr = attr and eval(attr) or 0
+ name = node.getAttribute("name")
+ entries += struct.pack("<16s16sQQQ72s",
+ type.bytes_le,
+ uniq.bytes_le,
+ start, end, attr,
+ name.encode("utf-16le"))
+ entries = padding(entries, NumberOfPartitionEntries * SizeOfPartitionEntry)
+ lba = eval(partition.getAttribute("lba"))
+ lbs = partition.getAttribute("lbs")
+ lbs = lbs and eval(lbs) or 512
+ FirstUsableLBA = 2 + (NumberOfPartitionEntries * SizeOfPartitionEntry / lbs)
+ uniq = partition.getAttribute("uuid")
+ uniq = uniq and uuid.UUID(uniq) or uuid.uuid4()
+ pmbr = padding(pmbr, lbs)
+ header = struct.pack("<8sIIIIQQQQ16sQIII",
+ b"EFI PART", 0x00010000, 92, 0, 0,
+ 1, # MyLBA
+ 1, #lba - 1, # AlternateLBA
+ int(FirstUsableLBA),
+ int(lba - FirstUsableLBA), # LastUsableLBA
+ uniq.bytes_le,
+ 2, NumberOfPartitionEntries, SizeOfPartitionEntry, crc32(entries))
+ header = padding(header[:16] +
+ struct.pack('I', crc32(header)) +
+ header[20:], lbs)
+ return pmbr + header + entries
+
+def write_scatter_partition(f, entry):
+ if entry.get("file_name", "NONE") != "NONE":
+ entry.setdefault("is_download", True)
+ entry.setdefault("operation_type", "UPDATE")
+ entry.setdefault("type", "NORMAL_ROM")
+ f.write(
+"""- partition_index: %s
+ partition_name: %s
+ file_name: %s
+ is_download: %s
+ type: %s
+ linear_start_addr: %s
+ physical_start_addr: %s
+ partition_size: %s
+ region: %s
+ storage: %s
+ boundary_check: %s
+ is_reserved: %s
+ operation_type: %s
+ d_type: FALSE
+ reserve: %s
+
+""" % (entry["partition_index"], entry["partition_name"], entry.get("file_name", "NONE"),
+entry.get("is_download", False) and "true" or "false", entry.get("type", "NONE"), hex(entry["linear_start_addr"]),
+hex(entry["physical_start_addr"]), hex(entry["partition_size"]), entry.get("region", "EMMC_USER"),
+entry.get("storage", "HW_STORAGE_EMMC"), entry.get("boundary_check", True) and "true" or "false",
+entry.get("is_reserved", False) and "true" or "false", entry.get("operation_type", "PROTECTED"),
+hex(entry.get("reserve", 0))))
+
+def write_scatter(f, partition, d):
+ f.write(
+"""############################################################################################################
+#
+# General Setting
+#
+############################################################################################################
+- general: MTK_PLATFORM_CFG
+ info:
+ - config_version: %s
+ platform: %s
+ project: %s
+ storage: %s
+ boot_channel: %s
+ block_size: %s
+ skip_pmt_operate: %s
+############################################################################################################
+#
+# Layout Setting
+#
+############################################################################################################
+""" % (d["MTK_PLATFORM_CFG"]["config_version"], d["MTK_PLATFORM_CFG"]["platform"], d["MTK_PLATFORM_CFG"]["project"],
+ d["MTK_PLATFORM_CFG"]["storage"], d["MTK_PLATFORM_CFG"]["boot_channel"], d["MTK_PLATFORM_CFG"]["block_size"],
+ d["MTK_PLATFORM_CFG"].get("skip_pmt_operate", True) and "true" or "false"))
+ d["PRELOADER"]["partition_index"] = "SYS0"
+ d["MBR"]["partition_index"] = "SYS1"
+ write_scatter_partition(f, d["PRELOADER"])
+ write_scatter_partition(f, d["MBR"])
+ i = 2
+ for node in partition.childNodes:
+ if node.nodeName != "entry":
+ continue
+ start = eval(node.getAttribute("start"))
+ end = eval(node.getAttribute("end"))
+ name = node.getAttribute("name")
+ if name not in d:
+ continue
+ entry = d[name]
+ entry["partition_name"] = name
+ entry["partition_index"] = "SYS%d" % i
+ i += 1
+ entry["linear_start_addr"] = start * 512
+ entry["physical_start_addr"] = start * 512
+ if (end != start and name != "userdata"):
+ entry["partition_size"] = (end + 1 - start) * 512
+ else:
+ entry["partition_size"] = 0
+ write_scatter_partition(f, entry)
+ if (d["MTK_PLATFORM_CFG"].get("skip_pmt_operate", True) and "true" or "false") == "false":
+ d["sgpt"]["partition_index"] = "SYS%d" % i
+ d["sgpt"]["linear_start_addr"] = 0xffff0080
+ d["sgpt"]["physical_start_addr"] = 0xffff0080
+ write_scatter_partition(f, d["sgpt"])
+
+
+def sanity_check(path, partition):
+ err = 0
+ lba = eval(partition.getAttribute("lba"))
+ lbs = partition.getAttribute("lbs")
+ lbs = lbs and eval(lbs) or 512
+ FirstUsableLBA = 2 + (NumberOfPartitionEntries * SizeOfPartitionEntry / lbs)
+ usable = (FirstUsableLBA, lba - FirstUsableLBA)
+ used = {}
+ for node in partition.childNodes:
+ if node.nodeName != "entry":
+ continue
+ name = node.getAttribute("name")
+ start = eval(node.getAttribute("start"))
+ end = eval(node.getAttribute("end"))
+ if start > end:
+ print("%s: error: partition '%s': start lba (%d) > end lba (%d)" %
+ (path, name, start, end), file = sys.stderr)
+ err += 1
+ if start < usable[0] or end > usable[1]:
+ print("%s: error: partition '%s': (%d...%d) out of usable range (%d...%d)" %
+ (path, name, start, end, usable[0], usable[1]), file = sys.stderr)
+ err += 1
+ for i in used:
+ if (used[i][0] <= start and start <= used[i][1] or
+ used[i][0] <= end and end <= used[i][1]):
+ print("%s: error: partition '%s': (%d...%d) overlapped with partition '%s' (%d...%d)" %
+ (path, name, start, end, i, used[i][0], used[i][1]), file = sys.stderr)
+ err += 1
+ used[name] = (start, end)
+ return err
+
+def main(argv):
+ if len(argv) == 5: # normal argument list len(argv) = 5 #
+ print ("len:%d .py=%s .xml=%s .json=%s MBR=%s .txt=%s" %
+ (len(argv), argv[0], argv[1], argv[2], argv[3], argv[4]))
+ if len(argv) <= 3: # len(argv) = 4 for mt2701 spi nor boot (scatter.txt isn't needed) #
+ print("Usage: len:%d,%s partition_*.xml scatter_*.json [MBR] [scatter.txt] " % (len(argv), argv[0]))
+ exit(1)
+ root = xml.dom.minidom.parse(argv[1])
+ for partition in root.childNodes:
+ if partition.nodeName == "partition":
+ break
+ else:
+ raise Exception("partition not found")
+ if sanity_check(argv[1], partition):
+ return 1
+ write(argv[3], gen_gpt(partition))
+ if len(argv) == 5:
+ with open(os.path.join(os.path.dirname(__file__), argv[2]), "r") as f:
+ d = json.load(f)
+ with open(argv[4], "w") as f:
+ write_scatter(f, partition, d)
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/src/bsp/scatter/scripts/gen-partitions.sh b/src/bsp/scatter/scripts/gen-partitions.sh
new file mode 100755
index 0000000..4cbee84
--- /dev/null
+++ b/src/bsp/scatter/scripts/gen-partitions.sh
@@ -0,0 +1,119 @@
+#! /bin/sh
+
+PROJECT=$1
+OUT=$2
+BOOTDEV_TYPE=$3
+SCATTER_SRC=$4
+NAND_CHIP_NAME=$5
+NAND_HEADER_VERSION=$6
+HEADER_LK_MERGE=$7
+
+
+if [ ! -e ${PROJECT}/gen-partitions.ini ]; then
+ echo ERROR: can not find $1
+ exit 1
+fi
+
+mkdir -p ${OUT}
+cat ${PROJECT}/gen-partitions.ini | while read p s m t
+do
+ if [ "$t" = "" ]; then
+ if [ "${BOOTDEV_TYPE}" = "nand" ]; then
+ if [ "${HEADER_LK_MERGE}" = "yes" ]; then
+ python3 scripts/gen-partition-nand_merge.py ${PROJECT}/$p ${PROJECT}/$s ${OUT}/$m
+ else
+ python3 scripts/gen-partition-nand.py ${PROJECT}/$p ${PROJECT}/$s ${OUT}/$m
+ fi
+ else
+ python3 ${SCATTER_SRC}/gen-partition.py ${PROJECT}/$p ${PROJECT}/$s ${OUT}/$m
+ fi
+ else
+ if [ "${BOOTDEV_TYPE}" = "nand" ]; then
+ if [ "${HEADER_LK_MERGE}" = "yes" ]; then
+ python3 scripts/gen-partition-nand_merge.py ${PROJECT}/$p ${PROJECT}/$s ${OUT}/$m ${OUT}/$t
+ else
+ python3 scripts/gen-partition-nand.py ${PROJECT}/$p ${PROJECT}/$s ${OUT}/$m ${OUT}/$t
+ fi
+ else
+ python3 ${SCATTER_SRC}/gen-partition.py ${PROJECT}/$p ${PROJECT}/$s ${OUT}/$m ${OUT}/$t
+ fi
+ fi
+
+ if [ "${BOOTDEV_TYPE}" = "nand" ]; then
+ if [ "${NAND_HEADER_VERSION}" = "2.0" ]; then
+ if [ "$m" = "MBR_NAND" ]; then
+ python3 -B ${PWD}/tools/nand-utils/gen_nand_header.py ${NAND_CHIP_NAME} ${OUT}/$m
+ fi
+ elif [ "${NAND_HEADER_VERSION}" = "1.1" ]; then
+ lk_start=$(grep 'name="bl2"' ${PROJECT}/$p | grep -o 'start="[0-9]*"' | grep -o [0-9]*)
+ if [ "${lk_start}" = "" ]; then
+ echo ERROR: can not find UBOOT in ${PROJECT}/$p
+ exit 1
+ fi
+ temp_header_file="temp_nand_header.bin"
+ python3 -B ${PWD}/tools/nand-utils/gen_nand_header_v11.py ${NAND_CHIP_NAME} ${lk_start} ${OUT}/${temp_header_file}
+ cat ${OUT}/$m >> ${OUT}/${temp_header_file}
+ rm ${OUT}/$m
+ mv ${OUT}/${temp_header_file} ${OUT}/$m
+ elif [ "${NAND_HEADER_VERSION}" = "1.2" ]; then
+ temp_header_file="temp_nand_header.bin"
+ python3 -B ${PWD}/tools/nand-utils/gen_nand_header_v12.py ${NAND_CHIP_NAME} ${OUT}/${temp_header_file}
+ dd if=${OUT}/${temp_header_file} of=${OUT}/$m conv=notrunc
+ rm ${OUT}/${temp_header_file}
+ elif [ "${NAND_HEADER_VERSION}" = "1.3" ]; then
+ preloader_start=$(grep 'name="preloader"' ${PROJECT}/$p | grep -o 'start="[0-9]*"' | grep -o [0-9]*)
+ if [ "${preloader_start}" = "" ]; then
+ echo ERROR: can not find preloader in ${PROJECT}/$p
+ exit 1
+ fi
+ temp_header_file="temp_nand_header.bin"
+ python3 -B ${PWD}/tools/nand-utils/gen_nand_header_v13.py ${NAND_CHIP_NAME} ${preloader_start} ${OUT}/${temp_header_file}
+ cat ${OUT}/$m >> ${OUT}/${temp_header_file}
+ rm ${OUT}/$m
+ mv ${OUT}/${temp_header_file} ${OUT}/$m
+ elif [ "${NAND_HEADER_VERSION}" = "1.4" ]; then
+ temp_header_file="temp_nand_header.bin"
+ python -B ${PWD}/tools/nand-utils/gen_nand_header_v14.py ${NAND_CHIP_NAME} ${OUT}/${temp_header_file}
+ dd if=${OUT}/${temp_header_file} of=${OUT}/$m conv=notrunc
+ rm ${OUT}/${temp_header_file}
+ elif [ "${NAND_HEADER_VERSION}" = "3.0" ]; then
+ if [ "$m" = "MBR_NAND" ]; then
+ python -B ${PWD}/tools/nand-utils/gen_nand_header_mt2731.py ${NAND_CHIP_NAME} ${OUT}/$m
+ fi
+ elif [ "${NAND_HEADER_VERSION}" = "4.0" ]; then
+ if [ "$m" = "MBR_NAND" ]; then
+ python3 -B ${PWD}/tools/nand-utils/gen_nand_header_v4.py ${NAND_CHIP_NAME} ${OUT}/$m
+ fi
+ elif [ "${NAND_HEADER_VERSION}" = "5.0" ]; then
+ if [ "$m" = "MBR_NAND" ]; then
+ python -B ${PWD}/tools/nand-utils/gen_nand_header_mt2735_hsm.py ${NAND_CHIP_NAME} ${OUT}/$m
+ fi
+ else
+ if [ "${NAND_CHIP_NAME}" = "" ]; then
+ echo ERROR: please check NAND_CHIP_NAME ${NAND_CHIP_NAME}
+ exit 2
+ fi
+
+ PAGE_SIZE=$(grep -o '^'${NAND_CHIP_NAME}' [0-9]*' nand-setting.txt | grep -o '[0-9]*$')
+ LBS=$(grep -o 'lbs="[0-9]*"' ${PROJECT}/$p | grep -o [0-9]*)
+ if [ "${PAGE_SIZE}" != "${LBS}" ]; then
+ echo ERROR: PAGE_SIZE ${PAGE_SIZE} of NAND ${NAND_CHIP_NAME} != LBS ${LBS} of partition table ${PROJECT}/$p
+ exit 3
+ fi
+
+ LK1=$(grep 'name="LK1"' ${PROJECT}/$p | grep -o 'start="[0-9]*"' | grep -o [0-9]*)
+ if [ "${LK1}" = "" ]; then
+ echo ERROR: can not find LK1 in ${PROJECT}/$p
+ exit 4
+ fi
+
+ LK2=$(grep 'name="LK2"' ${PROJECT}/$p | grep -o 'start="[0-9]*"' | grep -o [0-9]*)
+ if [ "${LK2}" = "" ]; then
+ echo ERROR: can not find LK2 in ${PROJECT}/$p
+ exit 5
+ fi
+
+ python3 scripts/dev-info-hdr-tool.py ${BOOTDEV_TYPE} ${OUT}/$m ${OUT}/$m ${NAND_CHIP_NAME} ${LK1} ${LK2}
+ fi
+ fi
+done
diff --git a/src/bsp/scatter/scripts/nand-setting.txt b/src/bsp/scatter/scripts/nand-setting.txt
new file mode 100644
index 0000000..5d76981
--- /dev/null
+++ b/src/bsp/scatter/scripts/nand-setting.txt
@@ -0,0 +1,2 @@
+MX30LF1G18AC 2048
+MX30LF4G18AC 2048
diff --git a/src/bsp/scatter/tools/bch b/src/bsp/scatter/tools/bch
new file mode 100755
index 0000000..4954ae1
--- /dev/null
+++ b/src/bsp/scatter/tools/bch
Binary files differ
diff --git a/src/bsp/scatter/tools/nand-utils/README b/src/bsp/scatter/tools/nand-utils/README
new file mode 100644
index 0000000..16294ea
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/README
@@ -0,0 +1,12 @@
+usage
+
+1. ramdomizer.py: in_image, out_image, randomizer_type, sec_reseed enable, page size, spare size, sector size, page per block, ppen, vendor
+e.g: python randomizer.py nand_storage_image/TC58TEG5DCJTA00_rand_off_ecc.bin nand_storage_image/random.bin 'SS' 1 16384 1280 1024 256 0 "TSB"
+
+2. gen_storage_image.py: NAND device name(reference nand_device_list.txt), in_image, out_image, rand_en
+e.g: python gen_storage_image.py F59D4G81A-45TG-18V nand_storage_image/GPT_2048_W1_64_FIT.bin nand_storage_image/F59D4G81A-45TG-18V-storage-image.bin 0
+
+3. gen_nand_header.py: NAND device name(reference nand_device_list.txt)
+e.g: python gen_nand_header.py TH58TFG8DDLAB4C
+
+If want to ignore .pyc file, please use python -B xxx.py
diff --git a/src/bsp/scatter/tools/nand-utils/__init__.py b/src/bsp/scatter/tools/nand-utils/__init__.py
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/__init__.py
diff --git a/src/bsp/scatter/tools/nand-utils/ac_calculator/ac_calculator.py b/src/bsp/scatter/tools/nand-utils/ac_calculator/ac_calculator.py
new file mode 100755
index 0000000..4fe91b7
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/ac_calculator/ac_calculator.py
@@ -0,0 +1,493 @@
+#!/usr/bin/env python
+
+import argparse
+import sys
+import struct
+import os
+import math
+import xml.dom.minidom
+
+# max strobe delay cycle
+max_strobe_dly = 3
+
+def calculate_sdr_acccon(ac, rate):
+ # turn clock rate from HZ into KHZ
+ rate /= 1000
+ # calculate tpoecs
+ tpoecs = max(ac["tALH"], ac["tCLH"])
+ tpoecs = int(math.ceil(float(tpoecs) * rate / 1000000))
+ tpoecs &= 0xf
+ # calculate tprecs
+ tprecs = max(ac["tCLS"], ac["tALS"])
+ tprecs = int(math.ceil(float(tprecs) * rate / 1000000))
+ tprecs &= 0x3f
+ # calculate tc2r
+ tc2r = int(math.ceil(float(ac["tCR"]) * rate / 1000000)) - 1
+ tc2r = int(math.ceil(float(tc2r) / 2))
+ tc2r &= 0x3f
+ # calculate tw2r
+ tw2r = int(math.ceil(float(ac["tWHR"]) * rate / 1000000)) - 1
+ tw2r = int(math.ceil(float(tw2r) / 2))
+ tw2r &= 0xf;
+ # calculate twh
+ twh = max(ac["tREH"], ac["tWH"])
+ twh = int(math.ceil(float(twh) * rate / 1000000)) - 1
+ twh &= 0xf
+ # calculate twst
+ twst = 0
+ if (twh + 1) * 1000000 / rate < ac["tWC"]:
+ twst = ac["tWC"] - (twh + 1) * 1000000 / rate
+ twst = max(ac["tWP"], twst)
+ twst = int(math.ceil(float(twst) * rate / 1000000)) - 1
+ twst &= 0xf
+ # calculate trlt
+ trlt = 0
+ if (twh + 1) * 1000000 / rate < ac["tRC"]:
+ trlt = ac["tRC"] - (twh + 1) * 1000000 / rate
+ trlt = max(ac["tRP"], trlt)
+ trlt = int(math.ceil(float(trlt) * rate / 1000000)) - 1
+ trlt &= 0xf
+ # calculate strobe sel
+ tsel = 0
+ if (trlt + 1) * 1000000 / rate < ac["tREA"]:
+ tsel = int(math.ceil(float(ac["tREA"]) * rate / 1000000))
+ tsel -= trlt + 1
+ if tsel > max_strobe_dly:
+ trlt += tsel - max_strobe_dly
+ tsel = max_strobe_dly
+ # get acccon
+ acccon = (tpoecs) << 28 | (tprecs) << 22 | (tc2r) << 16 | (tw2r) << 12 | (twh) << 8 | (twst) << 4 | (trlt)
+
+ return (acccon, tsel)
+
+def check_sdr_acccon_match_spec(ac, rate, acccon):
+ # turn clock rate from HZ into KHZ
+ rate /= 1000
+ # check tWH
+ twh = ((acccon >> 8) & 0xf) + 1
+ if twh * 1000000 / rate < ac["tWH"]:
+ return 1
+ # check tREH
+ if twh * 1000000 / rate < ac["tREH"]:
+ return 1
+ # check tWP
+ twst = ((acccon >> 4) & 0xf) + 1
+ if twst * 1000000 / rate < ac["tWP"]:
+ return 1
+ # check tRP
+ trlt = (acccon & 0xf) + 1
+ if trlt * 1000000 / rate < ac["tRP"]:
+ return 1
+ # check tWC
+ if (twh + twst) * 1000000 / rate < ac["tWC"]:
+ return 1
+ # check tRC
+ if (twh + trlt) * 1000000 / rate < ac["tRC"]:
+ return 1
+ # check more below
+
+ return 0
+
+def calculate_sdr_speed(ac, acccon, array, rate):
+ # turn clock rate from HZ into KHZ
+ rate /= 1000
+
+ twh = ((acccon >> 8) & 0xf) + 1
+ twst = ((acccon >> 4) & 0xf) + 1
+ trlt = (acccon & 0xf) + 1
+ chunk = array["page_size"] + array["spare_size"]
+
+ # read speed
+ tread = (float)(twh + trlt) * 1000000 / rate
+ tread *= chunk
+ tread += ac["tR"]
+ tread /= 1000
+ rspeed = 1000000 / tread
+ rspeed *= array["page_size"] / 1024
+
+ # write speed
+ twrite = (float)(twh + twst) * 1000000 / rate
+ twrite *= chunk
+ twrite += ac["tPROG"]
+ twrite /= 1000
+ wspeed = 1000000 / twrite
+ wspeed *= array["page_size"] / 1024
+
+ # erase speed
+ terase = ac["tBERS"] / 1000
+ espeed = 1000000 / terase
+ espeed *= array["page_size"] * array["page_per_block"] / 1024
+
+ return (rspeed, wspeed, espeed)
+
+def get_array_para(nand):
+ array = {}
+ for node in nand.childNodes:
+ if node.nodeName != "entry":
+ continue
+ artype = node.getAttribute("type")
+ if artype == "name":
+ array["name"] = node.getAttribute("value")
+ elif artype == "page_size":
+ array["page_size"] = eval(node.getAttribute("value"))
+ elif artype == "spare_size":
+ array["spare_size"] = eval(node.getAttribute("value"))
+ elif artype == "page_per_block":
+ array["page_per_block"] = eval(node.getAttribute("value"))
+ print ("NAND: %s, page size: %d, spare size: %d, page per block: %d" %
+ (array["name"], array["page_size"], array["spare_size"], array["page_per_block"]))
+
+ return array
+
+def get_sdr_ac_timing(ac_timing):
+ # get AC timing parameter value
+ ac = {}
+ for node in ac_timing.childNodes:
+ if node.nodeName != "entry":
+ continue
+ actype = node.getAttribute("type")
+ if actype == "tREA":
+ ac["tREA"] = eval(node.getAttribute("value"))
+ elif actype == "tREH":
+ ac["tREH"] = eval(node.getAttribute("value"))
+ elif actype == "tCR":
+ ac["tCR"] = eval(node.getAttribute("value"))
+ elif actype == "tRP":
+ ac["tRP"] = eval(node.getAttribute("value"))
+ elif actype == "tWP":
+ ac["tWP"] = eval(node.getAttribute("value"))
+ elif actype == "tWH":
+ ac["tWH"] = eval(node.getAttribute("value"))
+ elif actype == "tWHR":
+ ac["tWHR"] = eval(node.getAttribute("value"))
+ elif actype == "tCLS":
+ ac["tCLS"] = eval(node.getAttribute("value"))
+ elif actype == "tALS":
+ ac["tALS"] = eval(node.getAttribute("value"))
+ elif actype == "tCLH":
+ ac["tCLH"] = eval(node.getAttribute("value"))
+ elif actype == "tALH":
+ ac["tALH"] = eval(node.getAttribute("value"))
+ elif actype == "tWC":
+ ac["tWC"] = eval(node.getAttribute("value"))
+ elif actype == "tRC":
+ ac["tRC"] = eval(node.getAttribute("value"))
+ elif actype == "tR":
+ ac["tR"] = eval(node.getAttribute("value"))
+ elif actype == "tPROG":
+ ac["tPROG"] = eval(node.getAttribute("value"))
+ elif actype == "tBERS":
+ ac["tBERS"] = eval(node.getAttribute("value"))
+ print ("tR: %d, tPROG: %d, tBERS: %d ns" % (ac["tR"], ac["tPROG"], ac["tBERS"]))
+ return ac
+
+def sdr_calculator(nand, freq):
+ print ("This is SDR mode calculator!!")
+ nand_file = "./sdr/" + nand
+ doc_nand = xml.dom.minidom.parse(nand_file)
+ root_nand = doc_nand.documentElement
+ for nand_node in root_nand.childNodes:
+ if nand_node.nodeName == "ac_timing":
+ ac = get_sdr_ac_timing(nand_node)
+ elif nand_node.nodeName == "array":
+ array = get_array_para(nand_node)
+
+ # get frequency
+ freq_file = "./freq/" + freq
+ root_freq = xml.dom.minidom.parse(freq_file)
+ for frequency in root_freq.childNodes:
+ if frequency.nodeName == "frequency":
+ break
+
+ divider = eval(frequency.getAttribute("divider"))
+
+ # calculate acccon, stobe, performance
+ print ("Read IO speed: %.2f KB/s, Write IO speed: %.2f KB/s" %
+ ((1000000000 / float(ac["tRC"]) / 1024), (1000000000 / float(ac["tWC"]) / 1024)))
+ out_format = "{:^12}\t{:^12}\t{:^5}\t{:^12}\t{:^12}\t{:^12}\t"
+ print (out_format.format("freq","acccon","strobe","read(KB/s)","write(KB/s)", "erase(KB/s)"))
+ performance = []
+ for node in frequency.childNodes:
+ if node.nodeName != "entry":
+ continue
+ rate = eval(node.getAttribute("value"))
+ rate /= divider
+ freq_name = node.getAttribute("name")
+ (acccon, strobe) = calculate_sdr_acccon(ac, rate)
+ acccon_match = check_sdr_acccon_match_spec(ac, rate, acccon)
+ if acccon_match > 1:
+ print ("acccon %#x strobe %d not match spec" % (acccon, strobe))
+ raise Exception("not match spec")
+ (rspeed, wspeed, espeed) = calculate_sdr_speed(ac, acccon, array, rate)
+ rate *= divider
+ print (out_format.format(rate, hex(acccon), strobe, format(rspeed, ".2f"), \
+ format(wspeed, ".2f"), espeed))
+ performance.append({"rate":rate, "acccon":hex(acccon), "strobe":strobe, \
+ "rspeed":rspeed, "wspeed":wspeed, "espeed":espeed})
+
+ best_read = best_write = 0
+ for best in performance:
+ if best["rspeed"] > best_read:
+ best_read = best["rspeed"]
+ best_read_idx = performance.index(best)
+ if best["wspeed"] > best_write:
+ best_write = best["wspeed"]
+ best_write_idx = performance.index(best)
+ print ("frequency[%d] has the best read performance [%.2f KB/s]" %
+ (performance[best_read_idx]["rate"], performance[best_read_idx]["rspeed"]))
+ print ("frequency[%d] has the best write performance [%.2f KB/s]" %
+ (performance[best_write_idx]["rate"], performance[best_read_idx]["wspeed"]))
+
+def get_onfi_ac_timing(ac_timing):
+ # get AC timing parameter value
+ ac = {}
+ for node in ac_timing.childNodes:
+ if node.nodeName != "entry":
+ continue
+ actype = node.getAttribute("type")
+ if actype == "tCAD":
+ ac["tCAD"] = eval(node.getAttribute("value"))
+ elif actype == "tWRCK":
+ ac["tWRCK"] = eval(node.getAttribute("value"))
+ elif actype == "tDQSCK":
+ ac["tDQSCK"] = eval(node.getAttribute("value"))
+ elif actype == "tWHR":
+ ac["tWHR"] = eval(node.getAttribute("value"))
+ elif actype == "tWPRE":
+ ac["tWPRE"] = eval(node.getAttribute("value"))
+ elif actype == "tWPST":
+ ac["tWPST"] = eval(node.getAttribute("value"))
+ elif actype == "rate_max":
+ ac["rate_max"] = eval(node.getAttribute("value"))
+ elif actype == "tR":
+ ac["tR"] = eval(node.getAttribute("value"))
+ elif actype == "tPROG":
+ ac["tPROG"] = eval(node.getAttribute("value"))
+ elif actype == "tBERS":
+ ac["tBERS"] = eval(node.getAttribute("value"))
+ print ("tR: %d, tPROG: %d, tBERS: %d ns" % (ac["tR"], ac["tPROG"], ac["tBERS"]))
+
+ ac["tCKWR"] = ac["tDQSCK"]
+
+ return ac
+
+def calculate_onfi_acccon(ac, rate):
+ # turn clock rate from HZ into KHZ
+ rate /= 1000
+ # calculate tWPRE, tWRST, tCKWR
+ ac["tWPRE_real"] = int(math.ceil(float(ac["tWPRE"]) * 1000000 / rate))
+ ac["tWPST_real"] = int(math.ceil(float(ac["tWPST"]) * 1000000 / rate))
+ ac["tCKWR"] = int(math.ceil(math.ceil(float(ac["tDQSCK"]) * rate / 1000000) * 1000000 / rate))
+ # acccon register setting
+ # calculate tprecs
+ tprecs = max(ac["tCAD"], ac["tWRCK"])
+ if ac["tWPRE_real"] > int(math.ceil(1.5 * 1000000 / rate)):
+ tprecs = max(tprecs, ac["tWPRE_real"] - int(math.ceil(1.5 * 1000000 / rate)))
+ tprecs = int(math.ceil(float(tprecs) * rate / 1000000))
+ tprecs &= 0x3f;
+ # calculate tw2r
+ tw2r = int(math.ceil(float(ac["tWHR"]) * rate / 1000000))
+ tw2r = int(math.ceil(float(tw2r - 1) / 2))
+ tw2r &= 0xf
+ acccon = (tprecs) << 22 | (tw2r) << 12
+
+ # acccon1 register setting
+ # calculate trdpst
+ trdpst = int(math.ceil(float(ac["tCKWR"]) * rate / 1000000)) - 1
+ trdpst &= 0x3f
+ # calculate twrpst
+ twrpst = int(math.ceil(float(ac["tWPST_real"]) * rate / 1000000)) - 1
+ twrpst &= 0x3f
+ acccon1 = (trdpst) << 8 | (twrpst)
+
+ return (acccon, acccon1)
+
+def get_toggle_ac_timing(ac_timing):
+ # get AC timing parameter value
+ ac = {}
+ for node in ac_timing.childNodes:
+ if node.nodeName != "entry":
+ continue
+ actype = node.getAttribute("type")
+ if actype == "tCH":
+ ac["tCH"] = eval(node.getAttribute("value"))
+ elif actype == "tCALS":
+ ac["tCALS"] = eval(node.getAttribute("value"))
+ elif actype == "tCALH":
+ ac["tCALH"] = eval(node.getAttribute("value"))
+ elif actype == "tWPRE":
+ ac["tWPRE"] = eval(node.getAttribute("value"))
+ elif actype == "tWPST":
+ ac["tWPST"] = eval(node.getAttribute("value"))
+ elif actype == "tWPSTH":
+ ac["tWPSTH"] = eval(node.getAttribute("value"))
+ elif actype == "tCR":
+ ac["tCR"] = eval(node.getAttribute("value"))
+ elif actype == "tDQSRE":
+ ac["tDQSRE"] = eval(node.getAttribute("value"))
+ elif actype == "tRPSTH":
+ ac["tRPSTH"] = eval(node.getAttribute("value"))
+ elif actype == "tCDQSS":
+ ac["tCDQSS"] = eval(node.getAttribute("value"))
+ elif actype == "tWHR":
+ ac["tWHR"] = eval(node.getAttribute("value"))
+ elif actype == "rate_max":
+ ac["rate_max"] = eval(node.getAttribute("value"))
+ elif actype == "tR":
+ ac["tR"] = eval(node.getAttribute("value"))
+ elif actype == "tPROG":
+ ac["tPROG"] = eval(node.getAttribute("value"))
+ elif actype == "tBERS":
+ ac["tBERS"] = eval(node.getAttribute("value"))
+ print ("tR: %d, tPROG: %d, tBERS: %d ns" % (ac["tR"], ac["tPROG"], ac["tBERS"]))
+
+ return ac
+
+def calculate_toggle_acccon(ac, rate):
+ # turn clock rate from HZ into KHZ
+ rate /= 1000
+ # calculate tRPST
+ ac["tRPST"] = ac["tDQSRE"] + 0.5 * 1000000 / rate
+ # acccon register setting
+ # calculate tpoecs
+ tpoecs = max(max(ac["tCALH"], ac["tWPSTH"]), ac["tRPSTH"])
+ tpoecs = int(math.ceil(float(tpoecs) * rate / 1000000)) - 1
+ tpoecs &= 0xf
+ # calculate tprecs
+ tprecs = max(ac["tCALS"], ac["tCDQSS"])
+ tprecs = int(math.ceil(float(tprecs) * rate / 1000000)) - 1
+ tprecs &= 0x3f
+ # calculate tc2r
+ tc2r = math.ceil(float(ac["tCR"]) * rate / 1000000) - 1
+ tc2r = int(math.ceil(tc2r / 2))
+ tc2r &= 0x3f
+ # calculate tw2r
+ tw2r = math.ceil(float(ac["tWHR"]) * rate / 1000000) - 1
+ tw2r = int(math.ceil(tw2r / 2))
+ tw2r &= 0x3f
+ # calculate twh
+ twh = max(ac["tCH"], ac["tCALH"])
+ twh = int(math.ceil(float(twh) * rate / 1000000)) - 1
+ twh &= 0xf
+ # calculate twst
+ twst = int(math.ceil(float(ac["tCALS"]) * rate / 1000000)) - 1
+ twst &= 0xf
+ trlt = 0
+ acccon = (tpoecs) << 28 | (tprecs) << 22 | (tc2r) << 16 | (tw2r) << 12 | (twh) << 8 | (twst) << 4 | (trlt)
+
+ # acccon1 register setting
+ # calculate trdpre
+ trdpre = int(math.ceil(float(ac["tWPRE"]) * rate / 1000000)) - 1
+ trdpre &= 0x3f
+ # calculate trdpst
+ trdpst = int(math.ceil(float(ac["tRPST"]) * rate / 1000000)) - 1
+ trdpst &= 0x3f
+ # calculate twrpre
+ twrpre = int(math.ceil(float(ac["tWPRE"]) * rate / 1000000)) - 1
+ twrpre &= 0x3f
+ # calculate twrpst
+ twrpst = int(math.ceil(float(ac["tWPST"]) * rate / 1000000)) - 1
+ twrpst &= 0x3f
+ acccon1 = (trdpre << 24) | (twrpre) << 16 | (trdpst) << 8 | (twrpst)
+
+ return (acccon, acccon1)
+
+def calculate_ddr_speed(ac, array, rate):
+ # turn clock rate from HZ into KHZ
+ rate /= 1000
+
+ chunk = array["page_size"] + array["spare_size"]
+
+ # read speed
+ tread = 1000000 / float(rate * 2)
+ tread *= chunk
+ tread += ac["tR"]
+ tread /= 1000
+ rspeed = 1000000 / tread
+ rspeed *= array["page_size"] / 1024
+
+ # write speed
+ twrite = 1000000 / float(rate * 2)
+ twrite *= chunk
+ twrite += ac["tPROG"]
+ twrite /= 1000
+ wspeed = 1000000 / twrite
+ wspeed *= array["page_size"] / 1024
+
+ # erase speed
+ terase = ac["tBERS"] / 1000
+ espeed = 1000000 / terase
+ espeed *= array["page_size"] * array["page_per_block"] / 1024
+
+ return (rspeed, wspeed, espeed)
+
+def ddr_calculator(nand, freq, mode):
+ print ("This is %s mode calculator!!" % mode)
+ nand_file = "./" + mode + "/" + nand
+ doc_nand = xml.dom.minidom.parse(nand_file)
+ root_nand = doc_nand.documentElement
+ for nand_node in root_nand.childNodes:
+ if nand_node.nodeName == "ac_timing":
+ if mode == "ddr_onfi":
+ ac = get_onfi_ac_timing(nand_node)
+ elif mode == "ddr_toggle":
+ ac = get_toggle_ac_timing(nand_node)
+ else:
+ raise Exception("unsupported ddr mode!!")
+ elif nand_node.nodeName == "array":
+ array = get_array_para(nand_node)
+
+ # get frequency
+ freq_file = "./freq/" + freq
+ root_freq = xml.dom.minidom.parse(freq_file)
+ for frequency in root_freq.childNodes:
+ if frequency.nodeName == "frequency":
+ break
+
+ divider = eval(frequency.getAttribute("divider"))
+
+ out_format = "{:^12}\t{:^12}\t{:^12}\t{:^12}\t{:^12}\t{:^12}\t"
+ print (out_format.format("freq","acccon","acccon1","read(KB/s)","write(KB/s)", "erase(KB/s)"))
+ rate_invalid = []
+ for node in frequency.childNodes:
+ if node.nodeName != "entry":
+ continue
+ rate = eval(node.getAttribute("value"))
+ rate /= divider
+ if rate > ac["rate_max"]:
+ rate_invalid.append(rate * divider)
+ continue
+ freq_name = node.getAttribute("name")
+ if mode == "ddr_onfi":
+ (acccon, acccon1) = calculate_onfi_acccon(ac, rate)
+ elif mode == "ddr_toggle":
+ (acccon, acccon1) = calculate_toggle_acccon(ac, rate)
+ else:
+ raise Exception("unsupported ddr mode!!")
+ (rspeed, wspeed, espeed) = calculate_ddr_speed(ac, array, rate)
+ rate *= divider
+ print (out_format.format(rate, hex(acccon), hex(acccon1), format(rspeed, ".2f"), \
+ format(wspeed, ".2f"), espeed))
+
+ for rate in rate_invalid:
+ print ("rate[%d] not supported!" % rate)
+
+def ddr_toggle_calculator(nand, freq):
+ print ("This is Toggle DDR mode calculator!!")
+
+def main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('mode', help = 'working mode: sdr, ddr_onfi, ddr_toggle')
+ parser.add_argument('nand', help= 'nand AC timing xml file')
+ parser.add_argument('freq', help = 'frequency file')
+ args = parser.parse_args()
+
+ if args.mode == "sdr":
+ sdr_calculator(args.nand, args.freq)
+ elif args.mode == "ddr_onfi" or args.mode == "ddr_toggle":
+ ddr_calculator(args.nand, args.freq, args.mode)
+ else:
+ raise Exception("Working mode not supported!")
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/src/bsp/scatter/tools/nand-utils/ac_calculator/ddr_onfi/MT29F64G08CBCGB.xml b/src/bsp/scatter/tools/nand-utils/ac_calculator/ddr_onfi/MT29F64G08CBCGB.xml
new file mode 100644
index 0000000..026a9d8
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/ac_calculator/ddr_onfi/MT29F64G08CBCGB.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nand>
+ <array>
+ <!--size value must be with "byte" unit-->
+ <entry type="name" value="MT29F64G08CBCGB" descript="nand name"/>
+ <entry type="page_size" value="16384" descript="page size"/>
+ <entry type="spare_size" value="2208" descript="spare size"/>
+ <entry type="page_per_block" value="512" descript="page per block"/>
+ </array>
+ <ac_timing>
+ <!--timing value not highlight must be with "ns" unit-->
+ <entry type="tCAD" value="25" descript="Command, address data delay"/>
+ <entry type="tWPRE" value="1.5" descript="unit tCK, DQS write preamble"/>
+ <entry type="tWPST" value="1.5" descript="unit tCK, DQS write postamble"/>
+ <entry type="tWRCK" value="20" descript="W/R# low to data output cycle"/>
+ <entry type="tDQSCK" value="20" descript="Access window of DQS from CLK"/>
+ <entry type="tCKWR" value="div_round_up(tDQSCK, tCK)" descript="unit tCK, Data output end to W/R# high"/>
+ <entry type="tWHR" value="80" descript="Command cycle to data output"/>
+ <entry type="tR" value="52000" descript="data transfer from cell to data register"/>
+ <entry type="tPROG" value="330000" descript="page program time"/>
+ <entry type="tBERS" value="10000000" descript="block erase time"/>
+ <entry type="rate_max" value="100000000" descript="max frequency supported (HZ)"/>
+ </ac_timing>
+</nand>
diff --git a/src/bsp/scatter/tools/nand-utils/ac_calculator/ddr_toggle/TC58TEG6DDLTA00.xml b/src/bsp/scatter/tools/nand-utils/ac_calculator/ddr_toggle/TC58TEG6DDLTA00.xml
new file mode 100644
index 0000000..f669901
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/ac_calculator/ddr_toggle/TC58TEG6DDLTA00.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nand>
+ <array>
+ <!--size value must be with "byte" unit-->
+ <entry type="name" value="TC58TEG6DDLTA00" descript="nand name"/>
+ <entry type="page_size" value="16384" descript="page size"/>
+ <entry type="spare_size" value="1280" descript="spare size"/>
+ <entry type="page_per_block" value="256" descript="page per block"/>
+ </array>
+ <ac_timing>
+ <!--timing value not highlight must be with "ns" unit-->
+ <entry type="tCH" value="5" descript="CE# hold time"/>
+ <entry type="tCALS" value="15" descript="CLE/ALE setup time"/>
+ <entry type="tCALH" value="5" descript="CLE/ALE hold time"/>
+ <entry type="tWPRE" value="15" descript="Write preamble"/>
+ <entry type="tWPST" value="6.5" descript="Write postamble"/>
+ <entry type="tWPSTH" value="25" descript="Write postamble hold time"/>
+ <entry type="tCR" value="10" descript="CE# low to RE# low"/>
+ <entry type="tDQSRE" value="25" descript="RE# to DQS and DQ delay"/>
+ <entry type="tRPST" value="tDQSRE+0.5*tRC" descript="Read postamble"/>
+ <entry type="tRPSTH" value="25" descript="Read postamble hold time"/>
+ <entry type="tCDQSS" value="100" descript="DQS setup time for data input mode start"/>
+ <entry type="tWHR" value="120" descript="WE# high to RE# low"/>
+ <entry type="tR" value="50000" descript="data transfer from cell to data register"/>
+ <entry type="tPROG" value="1400000" descript="page program time"/>
+ <entry type="tBERS" value="5000000" descript="block erase time"/>
+ <entry type="rate_max" value="100000000" descript="max frequency supported (HZ)"/>
+ </ac_timing>
+</nand>
diff --git a/src/bsp/scatter/tools/nand-utils/ac_calculator/freq/mt8133.xml b/src/bsp/scatter/tools/nand-utils/ac_calculator/freq/mt8133.xml
new file mode 100644
index 0000000..c791fd2
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/ac_calculator/freq/mt8133.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--divider: 1: clocks below are 1x clock, 2: clocks below are 2x clock-->
+<frequency divider="2">
+ <!--rate unit: HZ-->
+ <entry name="26m" value="26000000"/>
+ <entry name="syspll2_d2" value="182000000"/>
+ <entry name="syspll_d7" value="156000000"/>
+ <entry name="syspll_d3" value="364000000"/>
+ <entry name="syspll2_d4" value="91000000"/>
+ <entry name="msdcpll_d2" value="200000000"/>
+ <entry name="univpll1_d2" value="312000000"/>
+ <entry name="univpll_d5" value="249600000"/>
+</frequency>
diff --git a/src/bsp/scatter/tools/nand-utils/ac_calculator/sdr/W29N08GZSIBA.xml b/src/bsp/scatter/tools/nand-utils/ac_calculator/sdr/W29N08GZSIBA.xml
new file mode 100644
index 0000000..85cf677
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/ac_calculator/sdr/W29N08GZSIBA.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nand>
+ <array>
+ <!--size value must be with "byte" unit-->
+ <entry type="name" value="W29N08GZSIBA" descript="nand name"/>
+ <entry type="page_size" value="2048" descript="page size"/>
+ <entry type="spare_size" value="64" descript="spare size"/>
+ <entry type="page_per_block" value="64" descript="page per block"/>
+ </array>
+ <ac_timing>
+ <!--timing value must be with "ns" unit-->
+ <entry type="tREA" value="25" descript="RE# access time"/>
+ <entry type="tREH" value="10" descript="RE# high hold time"/>
+ <entry type="tCR" value="0" descript="CE# low to RE# low. If no this para, set 0"/>
+ <entry type="tRP" value="12" descript="RE# pulse width"/>
+ <entry type="tWP" value="12" descript="WE# pulse width"/>
+ <entry type="tWH" value="10" descript="WE# high hold time"/>
+ <entry type="tWHR" value="80" descript="WE# high to RE# low"/>
+ <entry type="tCLS" value="10" descript="CLE setup time"/>
+ <entry type="tALS" value="10" descript="ALE setup time"/>
+ <entry type="tCLH" value="5" descript="CLE hold time"/>
+ <entry type="tALH" value="5" descript="ALE hold time"/>
+ <entry type="tWC" value="35" descript="write cycle time"/>
+ <entry type="tRC" value="35" descript="read cycle time"/>
+ <entry type="tR" value="25000" descript="data transfer from cell to data register"/>
+ <entry type="tPROG" value="250000" descript="page program time"/>
+ <entry type="tBERS" value="2000000" descript="block erase time"/>
+ </ac_timing>
+</nand>
diff --git a/src/bsp/scatter/tools/nand-utils/ecc_bch.py b/src/bsp/scatter/tools/nand-utils/ecc_bch.py
new file mode 100755
index 0000000..6e2c80e
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/ecc_bch.py
@@ -0,0 +1,690 @@
+#!/usr/bin/env python3
+
+import math
+
+M_14_4 = ((0x85,0x5c,0x9a,0x89,0x8a,0x48,0x9b,0x01),
+ (0x0a,0xb9,0x34,0x13,0x15,0x91,0x36,0x03),
+ (0x14,0x72,0x69,0x26,0x2a,0x22,0x6d,0x06),
+ (0x28,0xe4,0xd2,0x4c,0x54,0x44,0xda,0x0c),
+ (0x50,0xc8,0xa5,0x99,0xa8,0x88,0xb4,0x19),
+ (0xa0,0x90,0x4b,0x33,0x51,0x11,0x69,0x33),
+ (0x40,0x21,0x97,0x66,0xa2,0x22,0xd2,0x66),
+ (0x80,0x42,0x2e,0xcd,0x44,0x45,0xa4,0xcd))
+
+M_14_6 = ((0xf9,0x0f,0x2a,0x86,0x79,0xef,0x10,0x33,0xaf,0x5c,0x12,0x00),
+ (0xf2,0x1f,0x54,0x0c,0xf3,0xde,0x21,0x66,0x5e,0xb9,0x24,0x00),
+ (0xe4,0x3f,0xa8,0x18,0xe6,0xbd,0x43,0xcc,0xbc,0x72,0x49,0x00),
+ (0xc8,0x7f,0x50,0x31,0xcc,0x7b,0x87,0x98,0x79,0xe5,0x92,0x00),
+ (0x90,0xff,0xa0,0x62,0x98,0xf7,0x0e,0x31,0xf3,0xca,0x25,0x01),
+ (0x20,0xff,0x41,0xc5,0x30,0xef,0x1d,0x62,0xe6,0x95,0x4b,0x02),
+ (0x40,0xfe,0x83,0x8a,0x61,0xde,0x3b,0xc4,0xcc,0x2b,0x97,0x04),
+ (0x80,0xfc,0x07,0x15,0xc3,0xbc,0x77,0x88,0x99,0x57,0x2e,0x09))
+
+M_14_8 = ((0xff,0xbc,0xd3,0xff,0x94,0x43,0x78,0xdc,0x34,0x8f,0x9c,0x67,0x75,0x68,0x01),
+ (0xfe,0x79,0xa7,0xff,0x29,0x87,0xf0,0xb8,0x69,0x1e,0x39,0xcf,0xea,0xd0,0x02),
+ (0xfc,0xf3,0x4e,0xff,0x53,0x0e,0xe1,0x71,0xd3,0x3c,0x72,0x9e,0xd5,0xa1,0x05),
+ (0xf8,0xe7,0x9d,0xfe,0xa7,0x1c,0xc2,0xe3,0xa6,0x79,0xe4,0x3c,0xab,0x43,0x0b),
+ (0xf0,0xcf,0x3b,0xfd,0x4f,0x39,0x84,0xc7,0x4d,0xf3,0xc8,0x79,0x56,0x87,0x16),
+ (0xe0,0x9f,0x77,0xfa,0x9f,0x72,0x08,0x8f,0x9b,0xe6,0x91,0xf3,0xac,0x0e,0x2d),
+ (0xc0,0x3f,0xef,0xf4,0x3f,0xe5,0x10,0x1e,0x37,0xcd,0x23,0xe7,0x59,0x1d,0x5a),
+ (0x80,0x7f,0xde,0xe9,0x7f,0xca,0x21,0x3c,0x6e,0x9a,0x47,0xce,0xb3,0x3a,0xb4))
+
+M_14_10 = ((0x39,0xb4,0xc5,0x64,0x41,0x71,0xe9,0xdc,0x14,0x76,0x1f,0x20,0xc4,0xdb,0xb7,0xb4,0x92,0x16,0x00),
+ (0x72,0x68,0x8b,0xc9,0x82,0xe2,0xd2,0xb9,0x29,0xec,0x3e,0x40,0x88,0xb7,0x6f,0x69,0x25,0x2d,0x00),
+ (0xe4,0xd0,0x16,0x93,0x05,0xc5,0xa5,0x73,0x53,0xd8,0x7d,0x80,0x10,0x6f,0xdf,0xd2,0x4a,0x5a,0x00),
+ (0xc8,0xa1,0x2d,0x26,0x0b,0x8a,0x4b,0xe7,0xa6,0xb0,0xfb,0x00,0x21,0xde,0xbe,0xa5,0x95,0xb4,0x00),
+ (0x90,0x43,0x5b,0x4c,0x16,0x14,0x97,0xce,0x4d,0x61,0xf7,0x01,0x42,0xbc,0x7d,0x4b,0x2b,0x69,0x01),
+ (0x20,0x87,0xb6,0x98,0x2c,0x28,0x2e,0x9d,0x9b,0xc2,0xee,0x03,0x84,0x78,0xfb,0x96,0x56,0xd2,0x02),
+ (0x40,0x0e,0x6d,0x31,0x59,0x50,0x5c,0x3a,0x37,0x85,0xdd,0x07,0x08,0xf1,0xf6,0x2d,0xad,0xa4,0x05),
+ (0x80,0x1c,0xda,0x62,0xb2,0xa0,0xb8,0x74,0x6e,0x0a,0xbb,0x0f,0x10,0xe2,0xed,0x5b,0x5a,0x49,0x0b))
+
+M_14_12 = ((0x09,0xba,0x4b,0x25,0xd5,0xac,0x8b,0x18,0x40,0xfa,0x59,0x74,0xbd,0x76,0x3c,0xaf,0x8e,0x99,0x61,0xd4,0x60,0x01),
+ (0x12,0x74,0x97,0x4a,0xaa,0x59,0x17,0x31,0x80,0xf4,0xb3,0xe8,0x7a,0xed,0x78,0x5e,0x1d,0x33,0xc3,0xa8,0xc1,0x02),
+ (0x24,0xe8,0x2e,0x95,0x54,0xb3,0x2e,0x62,0x00,0xe9,0x67,0xd1,0xf5,0xda,0xf1,0xbc,0x3a,0x66,0x86,0x51,0x83,0x05),
+ (0x48,0xd0,0x5d,0x2a,0xa9,0x66,0x5d,0xc4,0x00,0xd2,0xcf,0xa2,0xeb,0xb5,0xe3,0x79,0x75,0xcc,0x0c,0xa3,0x06,0x0b),
+ (0x90,0xa0,0xbb,0x54,0x52,0xcd,0xba,0x88,0x01,0xa4,0x9f,0x45,0xd7,0x6b,0xc7,0xf3,0xea,0x98,0x19,0x46,0x0d,0x16),
+ (0x20,0x41,0x77,0xa9,0xa4,0x9a,0x75,0x11,0x03,0x48,0x3f,0x8b,0xae,0xd7,0x8e,0xe7,0xd5,0x31,0x33,0x8c,0x1a,0x2c),
+ (0x40,0x82,0xee,0x52,0x49,0x35,0xeb,0x22,0x06,0x90,0x7e,0x16,0x5d,0xaf,0x1d,0xcf,0xab,0x63,0x66,0x18,0x35,0x58),
+ (0x80,0x04,0xdd,0xa5,0x92,0x6a,0xd6,0x45,0x0c,0x20,0xfd,0x2c,0xba,0x5e,0x3b,0x9e,0x57,0xc7,0xcc,0x30,0x6a,0xb0))
+
+M_14_14 = (
+ (0x99,0xb1,0x75,0x12,0xb5,0xb2,0xee,0x98,0xe1,0x46,0x4a,0x20,0xd7,0xc9,0xfd,0x38,0xff,0x67,0xc8,0xff,0xa6,0xe7,0xcb,0xe5,0x13,0x00),
+ (0x32,0x63,0xeb,0x24,0x6a,0x65,0xdd,0x31,0xc3,0x8d,0x94,0x40,0xae,0x93,0xfb,0x71,0xfe,0xcf,0x90,0xff,0x4d,0xcf,0x97,0xcb,0x27,0x00),
+ (0x64,0xc6,0xd6,0x49,0xd4,0xca,0xba,0x63,0x86,0x1b,0x29,0x81,0x5c,0x27,0xf7,0xe3,0xfc,0x9f,0x21,0xff,0x9b,0x9e,0x2f,0x97,0x4f,0x00),
+ (0xc8,0x8c,0xad,0x93,0xa8,0x95,0x75,0xc7,0x0c,0x37,0x52,0x02,0xb9,0x4e,0xee,0xc7,0xf9,0x3f,0x43,0xfe,0x37,0x3d,0x5f,0x2e,0x9f,0x00),
+ (0x90,0x19,0x5b,0x27,0x51,0x2b,0xeb,0x8e,0x19,0x6e,0xa4,0x04,0x72,0x9d,0xdc,0x8f,0xf3,0x7f,0x86,0xfc,0x6f,0x7a,0xbe,0x5c,0x3e,0x01),
+ (0x20,0x33,0xb6,0x4e,0xa2,0x56,0xd6,0x1d,0x33,0xdc,0x48,0x09,0xe4,0x3a,0xb9,0x1f,0xe7,0xff,0x0c,0xf9,0xdf,0xf4,0x7c,0xb9,0x7c,0x02),
+ (0x40,0x66,0x6c,0x9d,0x44,0xad,0xac,0x3b,0x66,0xb8,0x91,0x12,0xc8,0x75,0x72,0x3f,0xce,0xff,0x19,0xf2,0xbf,0xe9,0xf9,0x72,0xf9,0x04),
+ (0x80,0xcc,0xd8,0x3a,0x89,0x5a,0x59,0x77,0xcc,0x70,0x23,0x25,0x90,0xeb,0xe4,0x7e,0x9c,0xff,0x33,0xe4,0x7f,0xd3,0xf3,0xe5,0xf2,0x09))
+
+M_14_16 = (
+ (0x67,0x48,0x60,0x1c,0xa4,0x8a,0x25,0x51,0x86,0x8a,0x12,0x09,0x34,0xe5,0xfd,
+ 0xd7,0x8f,0x87,0x57,0x33,0x44,0x2e,0x6f,0x23,0xab,0x82,0xdd,0xe6,0x01),
+ (0xce,0x90,0xc0,0x38,0x48,0x15,0x4b,0xa2,0x0c,0x15,0x25,0x12,0x68,0xca,0xfb,
+ 0xaf,0x1f,0x0f,0xaf,0x66,0x88,0x5c,0xde,0x46,0x56,0x05,0xbb,0xcd,0x03),
+ (0x9c,0x21,0x81,0x71,0x90,0x2a,0x96,0x44,0x19,0x2a,0x4a,0x24,0xd0,0x94,0xf7,
+ 0x5f,0x3f,0x1e,0x5e,0xcd,0x10,0xb9,0xbc,0x8d,0xac,0x0a,0x76,0x9b,0x07),
+ (0x38,0x43,0x02,0xe3,0x20,0x55,0x2c,0x89,0x32,0x54,0x94,0x48,0xa0,0x29,0xef,
+ 0xbf,0x7e,0x3c,0xbc,0x9a,0x21,0x72,0x79,0x1b,0x59,0x15,0xec,0x36,0x0f),
+ (0x70,0x86,0x04,0xc6,0x41,0xaa,0x58,0x12,0x65,0xa8,0x28,0x91,0x40,0x53,0xde,
+ 0x7f,0xfd,0x78,0x78,0x35,0x43,0xe4,0xf2,0x36,0xb2,0x2a,0xd8,0x6d,0x1e),
+ (0xe0,0x0c,0x09,0x8c,0x83,0x54,0xb1,0x24,0xca,0x50,0x51,0x22,0x81,0xa6,0xbc,
+ 0xff,0xfa,0xf1,0xf0,0x6a,0x86,0xc8,0xe5,0x6d,0x64,0x55,0xb0,0xdb,0x3c),
+ (0xc0,0x19,0x12,0x18,0x07,0xa9,0x62,0x49,0x94,0xa1,0xa2,0x44,0x02,0x4d,0x79,
+ 0xff,0xf5,0xe3,0xe1,0xd5,0x0c,0x91,0xcb,0xdb,0xc8,0xaa,0x60,0xb7,0x79),
+ (0x80,0x33,0x24,0x30,0x0e,0x52,0xc5,0x92,0x28,0x43,0x45,0x89,0x04,0x9a,0xf2,
+ 0xfe,0xeb,0xc7,0xc3,0xab,0x19,0x22,0x97,0xb7,0x91,0x55,0xc1,0x6e,0xf3))
+
+M_14_18 = (
+ (0x05,0x2c,0x4b,0x17,0x5e,0x12,0x96,0x3a,0x12,0x8e,0x9d,0x4b,0xcb,0x85,0x8d,
+ 0xa5,0x7d,0x91,0x59,0x4e,0x86,0xb6,0x5a,0xca,0xc7,0x0c,0x3f,0x1c,0x20,0xd3,0x7e,0x1a,0x00),
+ (0x0a,0x58,0x96,0x2e,0xbc,0x24,0x2c,0x75,0x24,0x1c,0x3b,0x97,0x96,0x0b,0x1b,
+ 0x4b,0xfb,0x22,0xb3,0x9c,0x0c,0x6d,0xb5,0x94,0x8f,0x19,0x7e,0x38,0x40,0xa6,0xfd,0x34,0x00),
+ (0x14,0xb0,0x2c,0x5d,0x78,0x49,0x58,0xea,0x48,0x38,0x76,0x2e,0x2d,0x17,0x36,
+ 0x96,0xf6,0x45,0x66,0x39,0x19,0xda,0x6a,0x29,0x1f,0x33,0xfc,0x70,0x80,0x4c,0xfb,0x69,0x00),
+ (0x28,0x60,0x59,0xba,0xf0,0x92,0xb0,0xd4,0x91,0x70,0xec,0x5c,0x5a,0x2e,0x6c,
+ 0x2c,0xed,0x8b,0xcc,0x72,0x32,0xb4,0xd5,0x52,0x3e,0x66,0xf8,0xe1,0x00,0x99,0xf6,0xd3,0x00),
+ (0x50,0xc0,0xb2,0x74,0xe1,0x25,0x61,0xa9,0x23,0xe1,0xd8,0xb9,0xb4,0x5c,0xd8,
+ 0x58,0xda,0x17,0x99,0xe5,0x64,0x68,0xab,0xa5,0x7c,0xcc,0xf0,0xc3,0x01,0x32,0xed,0xa7,0x01),
+ (0xa0,0x80,0x65,0xe9,0xc2,0x4b,0xc2,0x52,0x47,0xc2,0xb1,0x73,0x69,0xb9,0xb0,
+ 0xb1,0xb4,0x2f,0x32,0xcb,0xc9,0xd0,0x56,0x4b,0xf9,0x98,0xe1,0x87,0x03,0x64,0xda,0x4f,0x03),
+ (0x40,0x01,0xcb,0xd2,0x85,0x97,0x84,0xa5,0x8e,0x84,0x63,0xe7,0xd2,0x72,0x61,
+ 0x63,0x69,0x5f,0x64,0x96,0x93,0xa1,0xad,0x96,0xf2,0x31,0xc3,0x0f,0x07,0xc8,0xb4,0x9f,0x06),
+ (0x80,0x02,0x96,0xa5,0x0b,0x2f,0x09,0x4b,0x1d,0x09,0xc7,0xce,0xa5,0xe5,0xc2,
+ 0xc6,0xd2,0xbe,0xc8,0x2c,0x27,0x43,0x5b,0x2d,0xe5,0x63,0x86,0x1f,0x0e,0x90,0x69,0x3f,0x0d))
+M_14_20 = (
+ (0xe1,0xa2,0x8a,0xab,0x20,0x3f,0xfa,0x57,0x9f,0x6b,0xe5,0x09,0x6b,0xb4,0xc2,0x9a,
+ 0x1d,0xaa,0xd3,0xde,0xd7,0x84,0x38,0x7a,0x50,0x9b,0x98,0x15,0xf1,0xd5,0xb5,0x2c,0x13,0x87,0x35,0x01),
+ (0xc2,0x45,0x15,0x57,0x41,0x7e,0xf4,0xaf,0x3e,0xd7,0xca,0x13,0xd6,0x68,0x85,0x35,
+ 0x3b,0x54,0xa7,0xbd,0xaf,0x09,0x71,0xf4,0xa0,0x36,0x31,0x2b,0xe2,0xab,0x6b,0x59,0x26,0x0e,0x6b,0x02),
+ (0x84,0x8b,0x2a,0xae,0x82,0xfc,0xe8,0x5f,0x7d,0xae,0x95,0x27,0xac,0xd1,0x0a,0x6b,
+ 0x76,0xa8,0x4e,0x7b,0x5f,0x13,0xe2,0xe8,0x41,0x6d,0x62,0x56,0xc4,0x57,0xd7,0xb2,0x4c,0x1c,0xd6,0x04),
+ (0x08,0x17,0x55,0x5c,0x05,0xf9,0xd1,0xbf,0xfa,0x5c,0x2b,0x4f,0x58,0xa3,0x15,0xd6,
+ 0xec,0x50,0x9d,0xf6,0xbe,0x26,0xc4,0xd1,0x83,0xda,0xc4,0xac,0x88,0xaf,0xae,0x65,0x99,0x38,0xac,0x09),
+ (0x10,0x2e,0xaa,0xb8,0x0a,0xf2,0xa3,0x7f,0xf5,0xb9,0x56,0x9e,0xb0,0x46,0x2b,0xac,
+ 0xd9,0xa1,0x3a,0xed,0x7d,0x4d,0x88,0xa3,0x07,0xb5,0x89,0x59,0x11,0x5f,0x5d,0xcb,0x32,0x71,0x58,0x13),
+ (0x20,0x5c,0x54,0x71,0x15,0xe4,0x47,0xff,0xea,0x73,0xad,0x3c,0x61,0x8d,0x56,0x58,
+ 0xb3,0x43,0x75,0xda,0xfb,0x9a,0x10,0x47,0x0f,0x6a,0x13,0xb3,0x22,0xbe,0xba,0x96,0x65,0xe2,0xb0,0x26),
+ (0x40,0xb8,0xa8,0xe2,0x2a,0xc8,0x8f,0xfe,0xd5,0xe7,0x5a,0x79,0xc2,0x1a,0xad,0xb0,
+ 0x66,0x87,0xea,0xb4,0xf7,0x35,0x21,0x8e,0x1e,0xd4,0x26,0x66,0x45,0x7c,0x75,0x2d,0xcb,0xc4,0x61,0x4d),
+ (0x80,0x70,0x51,0xc5,0x55,0x90,0x1f,0xfd,0xab,0xcf,0xb5,0xf2,0x84,0x35,0x5a,0x61,
+ 0xcd,0x0e,0xd5,0x69,0xef,0x6b,0x42,0x1c,0x3d,0xa8,0x4d,0xcc,0x8a,0xf8,0xea,0x5a,0x96,0x89,0xc3,0x9a))
+
+M_14_22 = (
+ (0x33,0xdb,0xdc,0x30,0x9c,0xe3,0xd0,0x5d,0x4f,0xfe,0x2f,0x46,0xe6,0x42,0xf9,0x14,0x3b,0xbf,
+ 0x84,0xff,0xc6,0x12,0xc8,0x8e,0x88,0x2d,0x62,0xf7,0xd7,0xdf,0x4a,0xfa,0x92,0x8a,0xd6,0x0c,0xb3,0xc9,0x13,0x00),
+ (0x66,0xb6,0xb9,0x61,0x38,0xc7,0xa1,0xbb,0x9e,0xfc,0x5f,0x8c,0xcc,0x85,0xf2,0x29,0x76,0x7e,
+ 0x09,0xff,0x8d,0x25,0x90,0x1d,0x11,0x5b,0xc4,0xee,0xaf,0xbf,0x95,0xf4,0x25,0x15,0xad,0x19,0x66,0x93,0x27,0x00),
+ (0xcc,0x6c,0x73,0xc3,0x70,0x8e,0x43,0x77,0x3d,0xf9,0xbf,0x18,0x99,0x0b,0xe5,0x53,0xec,0xfc,
+ 0x12,0xfe,0x1b,0x4b,0x20,0x3b,0x22,0xb6,0x88,0xdd,0x5f,0x7f,0x2b,0xe9,0x4b,0x2a,0x5a,0x33,0xcc,0x26,0x4f,0x00),
+ (0x98,0xd9,0xe6,0x86,0xe1,0x1c,0x87,0xee,0x7a,0xf2,0x7f,0x31,0x32,0x17,0xca,0xa7,0xd8,0xf9,
+ 0x25,0xfc,0x37,0x96,0x40,0x76,0x44,0x6c,0x11,0xbb,0xbf,0xfe,0x56,0xd2,0x97,0x54,0xb4,0x66,0x98,0x4d,0x9e,0x00),
+ (0x30,0xb3,0xcd,0x0d,0xc3,0x39,0x0e,0xdd,0xf5,0xe4,0xff,0x62,0x64,0x2e,0x94,0x4f,0xb1,0xf3,
+ 0x4b,0xf8,0x6f,0x2c,0x81,0xec,0x88,0xd8,0x22,0x76,0x7f,0xfd,0xad,0xa4,0x2f,0xa9,0x68,0xcd,0x30,0x9b,0x3c,0x01),
+ (0x60,0x66,0x9b,0x1b,0x86,0x73,0x1c,0xba,0xeb,0xc9,0xff,0xc5,0xc8,0x5c,0x28,0x9f,0x62,0xe7,
+ 0x97,0xf0,0xdf,0x58,0x02,0xd9,0x11,0xb1,0x45,0xec,0xfe,0xfa,0x5b,0x49,0x5f,0x52,0xd1,0x9a,0x61,0x36,0x79,0x02),
+ (0xc0,0xcc,0x36,0x37,0x0c,0xe7,0x38,0x74,0xd7,0x93,0xff,0x8b,0x91,0xb9,0x50,0x3e,0xc5,0xce,
+ 0x2f,0xe1,0xbf,0xb1,0x04,0xb2,0x23,0x62,0x8b,0xd8,0xfd,0xf5,0xb7,0x92,0xbe,0xa4,0xa2,0x35,0xc3,0x6c,0xf2,0x04),
+ (0x80,0x99,0x6d,0x6e,0x18,0xce,0x71,0xe8,0xae,0x27,0xff,0x17,0x23,0x73,0xa1,0x7c,0x8a,0x9d,
+ 0x5f,0xc2,0x7f,0x63,0x09,0x64,0x47,0xc4,0x16,0xb1,0xfb,0xeb,0x6f,0x25,0x7d,0x49,0x45,0x6b,0x86,0xd9,0xe4,0x09))
+
+M_14_24 = (
+ (0xe3,0x52,0x0e,0x48,0x62,0x13,0x72,0xa9,0x45,0x49,0x9d,0x16,0x6f,0x37,0x17,0x32,0xfe,0x9c,0xe1,0xe2,
+ 0x62,0xc9,0x86,0x96,0x28,0x92,0x8b,0x0b,0x24,0xb4,0x17,0xaa,0xed,0xa0,0x25,0x93,0xb2,0x58,0xad,0x57,0x18,0xee,0x01),
+ (0xc6,0xa5,0x1c,0x90,0xc4,0x26,0xe4,0x52,0x8b,0x92,0x3a,0x2d,0xde,0x6e,0x2e,0x64,0xfc,0x39,0xc3,0xc5,
+ 0xc5,0x92,0x0d,0x2d,0x51,0x24,0x17,0x17,0x48,0x68,0x2f,0x54,0xdb,0x41,0x4b,0x26,0x65,0xb1,0x5a,0xaf,0x30,0xdc,0x03),
+ (0x8c,0x4b,0x39,0x20,0x89,0x4d,0xc8,0xa5,0x16,0x25,0x75,0x5a,0xbc,0xdd,0x5c,0xc8,0xf8,0x73,0x86,0x8b,
+ 0x8b,0x25,0x1b,0x5a,0xa2,0x48,0x2e,0x2e,0x90,0xd0,0x5e,0xa8,0xb6,0x83,0x96,0x4c,0xca,0x62,0xb5,0x5e,0x61,0xb8,0x07),
+ (0x18,0x97,0x72,0x40,0x12,0x9b,0x90,0x4b,0x2d,0x4a,0xea,0xb4,0x78,0xbb,0xb9,0x90,0xf1,0xe7,0x0c,0x17,
+ 0x17,0x4b,0x36,0xb4,0x44,0x91,0x5c,0x5c,0x20,0xa1,0xbd,0x50,0x6d,0x07,0x2d,0x99,0x94,0xc5,0x6a,0xbd,0xc2,0x70,0x0f),
+ (0x30,0x2e,0xe5,0x80,0x24,0x36,0x21,0x97,0x5a,0x94,0xd4,0x69,0xf1,0x76,0x73,0x21,0xe3,0xcf,0x19,0x2e,
+ 0x2e,0x96,0x6c,0x68,0x89,0x22,0xb9,0xb8,0x40,0x42,0x7b,0xa1,0xda,0x0e,0x5a,0x32,0x29,0x8b,0xd5,0x7a,0x85,0xe1,0x1e),
+ (0x60,0x5c,0xca,0x01,0x49,0x6c,0x42,0x2e,0xb5,0x28,0xa9,0xd3,0xe2,0xed,0xe6,0x42,0xc6,0x9f,0x33,0x5c,
+ 0x5c,0x2c,0xd9,0xd0,0x12,0x45,0x72,0x71,0x81,0x84,0xf6,0x42,0xb5,0x1d,0xb4,0x64,0x52,0x16,0xab,0xf5,0x0a,0xc3,0x3d),
+ (0xc0,0xb8,0x94,0x03,0x92,0xd8,0x84,0x5c,0x6a,0x51,0x52,0xa7,0xc5,0xdb,0xcd,0x85,0x8c,0x3f,0x67,0xb8,
+ 0xb8,0x58,0xb2,0xa1,0x25,0x8a,0xe4,0xe2,0x02,0x09,0xed,0x85,0x6a,0x3b,0x68,0xc9,0xa4,0x2c,0x56,0xeb,0x15,0x86,0x7b),
+ (0x80,0x71,0x29,0x07,0x24,0xb1,0x09,0xb9,0xd4,0xa2,0xa4,0x4e,0x8b,0xb7,0x9b,0x0b,0x19,0x7f,0xce,0x70,
+ 0x71,0xb1,0x64,0x43,0x4b,0x14,0xc9,0xc5,0x05,0x12,0xda,0x0b,0xd5,0x76,0xd0,0x92,0x49,0x59,0xac,0xd6,0x2b,0x0c,0xf7))
+
+M_14_28 = (
+ (0x71,0x5c,0xcd,0xf7,0x4c,0x41,0x3d,0x9b,0xa0,0x5e,0x93,0x46,0x1b,0x6e,0x2d,0x27,0xe6,0x50,
+ 0xd8,0xf6,0x31,0x0c,0x17,0xdc,0xee,0x29,0xf5,0x71,0x0a,0x34,0xb7,0xa8,0x40,0x3a,0xe1,
+ 0xc9,0x00,0xfb,0x50,0xd3,0x64,0x27,0x9f,0xe9,0x2f,0x15,0xed,0x99,0x19,0x01),
+ (0xe2,0xb8,0x9a,0xef,0x99,0x82,0x7a,0x36,0x41,0xbd,0x26,0x8d,0x36,0xdc,0x5a,0x4e,0xcc,0xa1,
+ 0xb0,0xed,0x63,0x18,0x2e,0xb8,0xdd,0x53,0xea,0xe3,0x14,0x68,0x6e,0x51,0x81,0x74,0xc2,
+ 0x93,0x01,0xf6,0xa1,0xa6,0xc9,0x4e,0x3e,0xd3,0x5f,0x2a,0xda,0x33,0x33,0x02),
+ (0xc4,0x71,0x35,0xdf,0x33,0x05,0xf5,0x6c,0x82,0x7a,0x4d,0x1a,0x6d,0xb8,0xb5,0x9c,0x98,0x43,
+ 0x61,0xdb,0xc7,0x30,0x5c,0x70,0xbb,0xa7,0xd4,0xc7,0x29,0xd0,0xdc,0xa2,0x02,0xe9,0x84,
+ 0x27,0x03,0xec,0x43,0x4d,0x93,0x9d,0x7c,0xa6,0xbf,0x54,0xb4,0x67,0x66,0x04),
+ (0x88,0xe3,0x6a,0xbe,0x67,0x0a,0xea,0xd9,0x04,0xf5,0x9a,0x34,0xda,0x70,0x6b,0x39,0x31,0x87,
+ 0xc2,0xb6,0x8f,0x61,0xb8,0xe0,0x76,0x4f,0xa9,0x8f,0x53,0xa0,0xb9,0x45,0x05,0xd2,0x09,
+ 0x4f,0x06,0xd8,0x87,0x9a,0x26,0x3b,0xf9,0x4c,0x7f,0xa9,0x68,0xcf,0xcc,0x08),
+ (0x10,0xc7,0xd5,0x7c,0xcf,0x14,0xd4,0xb3,0x09,0xea,0x35,0x69,0xb4,0xe1,0xd6,0x72,0x62,0x0e,
+ 0x85,0x6d,0x1f,0xc3,0x70,0xc1,0xed,0x9e,0x52,0x1f,0xa7,0x40,0x73,0x8b,0x0a,0xa4,0x13,
+ 0x9e,0x0c,0xb0,0x0f,0x35,0x4d,0x76,0xf2,0x99,0xfe,0x52,0xd1,0x9e,0x99,0x11),
+ (0x20,0x8e,0xab,0xf9,0x9e,0x29,0xa8,0x67,0x13,0xd4,0x6b,0xd2,0x68,0xc3,0xad,0xe5,0xc4,0x1c,
+ 0x0a,0xdb,0x3e,0x86,0xe1,0x82,0xdb,0x3d,0xa5,0x3e,0x4e,0x81,0xe6,0x16,0x15,0x48,0x27,
+ 0x3c,0x19,0x60,0x1f,0x6a,0x9a,0xec,0xe4,0x33,0xfd,0xa5,0xa2,0x3d,0x33,0x23),
+ (0x40,0x1c,0x57,0xf3,0x3d,0x53,0x50,0xcf,0x26,0xa8,0xd7,0xa4,0xd1,0x86,0x5b,0xcb,0x89,0x39,
+ 0x14,0xb6,0x7d,0x0c,0xc3,0x05,0xb7,0x7b,0x4a,0x7d,0x9c,0x02,0xcd,0x2d,0x2a,0x90,0x4e,
+ 0x78,0x32,0xc0,0x3e,0xd4,0x34,0xd9,0xc9,0x67,0xfa,0x4b,0x45,0x7b,0x66,0x46),
+ (0x80,0x38,0xae,0xe6,0x7b,0xa6,0xa0,0x9e,0x4d,0x50,0xaf,0x49,0xa3,0x0d,0xb7,0x96,0x13,0x73,
+ 0x28,0x6c,0xfb,0x18,0x86,0x0b,0x6e,0xf7,0x94,0xfa,0x38,0x05,0x9a,0x5b,0x54,0x20,0x9d,
+ 0xf0,0x64,0x80,0x7d,0xa8,0x69,0xb2,0x93,0xcf,0xf4,0x97,0x8a,0xf6,0xcc,0x8c))
+
+M_14_32 = (
+ (0xe9,0xad,0x1d,0x01,0x8d,0x7a,0xce,0xe3,0x9d,0xea,0x5f,0x5b,0x0b,0xc1,0x33,0x1b,0x1e,0xc4,0xeb,
+ 0x8d,0x56,0x0a,0x03,0xb3,0x6c,0x36,0x35,0x60,0xc7,0x66,0xdc,0x33,0x1f,0xb7,0x9a,0x24,0x75,0x5c,0xf9,
+ 0x64,0xdb,0x1e,0x71,0x7a,0xfd,0x91,0x36,0x72,0xfd,0xf0,0xa3,0xab,0x90,0xf2,0xf1,0x13,0x01),
+ (0xd2,0x5b,0x3b,0x02,0x1a,0xf5,0x9c,0xc7,0x3b,0xd5,0xbf,0xb6,0x16,0x82,0x67,0x36,0x3c,0x88,0xd7,
+ 0x1b,0xad,0x14,0x06,0x66,0xd9,0x6c,0x6a,0xc0,0x8e,0xcd,0xb8,0x67,0x3e,0x6e,0x35,0x49,0xea,0xb8,0xf2,
+ 0xc9,0xb6,0x3d,0xe2,0xf4,0xfa,0x23,0x6d,0xe4,0xfa,0xe1,0x47,0x57,0x21,0xe5,0xe3,0x27,0x02),
+ (0xa4,0xb7,0x76,0x04,0x34,0xea,0x39,0x8f,0x77,0xaa,0x7f,0x6d,0x2d,0x04,0xcf,0x6c,0x78,0x10,0xaf,
+ 0x37,0x5a,0x29,0x0c,0xcc,0xb2,0xd9,0xd4,0x80,0x1d,0x9b,0x71,0xcf,0x7c,0xdc,0x6a,0x92,0xd4,0x71,0xe5,
+ 0x93,0x6d,0x7b,0xc4,0xe9,0xf5,0x47,0xda,0xc8,0xf5,0xc3,0x8f,0xae,0x42,0xca,0xc7,0x4f,0x04),
+ (0x48,0x6f,0xed,0x08,0x68,0xd4,0x73,0x1e,0xef,0x54,0xff,0xda,0x5a,0x08,0x9e,0xd9,0xf0,0x20,0x5e,
+ 0x6f,0xb4,0x52,0x18,0x98,0x65,0xb3,0xa9,0x01,0x3b,0x36,0xe3,0x9e,0xf9,0xb8,0xd5,0x24,0xa9,0xe3,0xca,
+ 0x27,0xdb,0xf6,0x88,0xd3,0xeb,0x8f,0xb4,0x91,0xeb,0x87,0x1f,0x5d,0x85,0x94,0x8f,0x9f,0x08),
+ (0x90,0xde,0xda,0x11,0xd0,0xa8,0xe7,0x3c,0xde,0xa9,0xfe,0xb5,0xb5,0x10,0x3c,0xb3,0xe1,0x41,0xbc,
+ 0xde,0x68,0xa5,0x30,0x30,0xcb,0x66,0x53,0x03,0x76,0x6c,0xc6,0x3d,0xf3,0x71,0xab,0x49,0x52,0xc7,0x95,
+ 0x4f,0xb6,0xed,0x11,0xa7,0xd7,0x1f,0x69,0x23,0xd7,0x0f,0x3f,0xba,0x0a,0x29,0x1f,0x3f,0x11),
+ (0x20,0xbd,0xb5,0x23,0xa0,0x51,0xcf,0x79,0xbc,0x53,0xfd,0x6b,0x6b,0x21,0x78,0x66,0xc3,0x83,0x78,
+ 0xbd,0xd1,0x4a,0x61,0x60,0x96,0xcd,0xa6,0x06,0xec,0xd8,0x8c,0x7b,0xe6,0xe3,0x56,0x93,0xa4,0x8e,0x2b,
+ 0x9f,0x6c,0xdb,0x23,0x4e,0xaf,0x3f,0xd2,0x46,0xae,0x1f,0x7e,0x74,0x15,0x52,0x3e,0x7e,0x22),
+ (0x40,0x7a,0x6b,0x47,0x40,0xa3,0x9e,0xf3,0x78,0xa7,0xfa,0xd7,0xd6,0x42,0xf0,0xcc,0x86,0x07,0xf1,
+ 0x7a,0xa3,0x95,0xc2,0xc0,0x2c,0x9b,0x4d,0x0d,0xd8,0xb1,0x19,0xf7,0xcc,0xc7,0xad,0x26,0x49,0x1d,0x57,
+ 0x3e,0xd9,0xb6,0x47,0x9c,0x5e,0x7f,0xa4,0x8d,0x5c,0x3f,0xfc,0xe8,0x2a,0xa4,0x7c,0xfc,0x44),
+ (0x80,0xf4,0xd6,0x8e,0x80,0x46,0x3d,0xe7,0xf1,0x4e,0xf5,0xaf,0xad,0x85,0xe0,0x99,0x0d,0x0f,0xe2,
+ 0xf5,0x46,0x2b,0x85,0x81,0x59,0x36,0x9b,0x1a,0xb0,0x63,0x33,0xee,0x99,0x8f,0x5b,0x4d,0x92,0x3a,0xae,
+ 0x7c,0xb2,0x6d,0x8f,0x38,0xbd,0xfe,0x48,0x1b,0xb9,0x7e,0xf8,0xd1,0x55,0x48,0xf9,0xf8,0x89))
+
+M_14_36 = (
+ (0x0b,0x60,0xbf,0x81,0x57,0x76,0xb3,0x6c,0xaa,0xd3,0xb7,0xc1,0x3b,0xf7,0x8f,0x6c,0xef,0x2a,0x35,0x63,
+ 0x0c,0xad,0xc0,0xdb,0x40,0x49,0x27,0x9c,0x40,0x1f,0xfc,0x83,0xe4,0x85,0x3f,0x75,0x0b,0x7f,0x60,0x3c,0x73,
+ 0xcd,0x64,0x3c,0x0d,0xd9,0xf2,0x17,0xf0,0x3e,0x1c,0xe4,0x3c,0xe4,0xa1,0x9e,0xba,0x51,0xd5,0xfd,0x09,0x56,0x6c,0x01),
+ (0x16,0xc0,0x7e,0x03,0xaf,0xec,0x66,0xd9,0x54,0xa7,0x6f,0x83,0x77,0xee,0x1f,0xd9,0xde,0x55,0x6a,0xc6,
+ 0x18,0x5a,0x81,0xb7,0x81,0x92,0x4e,0x38,0x81,0x3e,0xf8,0x07,0xc9,0x0b,0x7f,0xea,0x16,0xfe,0xc0,0x78,0xe6,
+ 0x9a,0xc9,0x78,0x1a,0xb2,0xe5,0x2f,0xe0,0x7d,0x38,0xc8,0x79,0xc8,0x43,0x3d,0x75,0xa3,0xaa,0xfb,0x13,0xac,0xd8,0x02),
+ (0x2c,0x80,0xfd,0x06,0x5e,0xd9,0xcd,0xb2,0xa9,0x4e,0xdf,0x06,0xef,0xdc,0x3f,0xb2,0xbd,0xab,0xd4,0x8c,
+ 0x31,0xb4,0x02,0x6f,0x03,0x25,0x9d,0x70,0x02,0x7d,0xf0,0x0f,0x92,0x17,0xfe,0xd4,0x2d,0xfc,0x81,0xf1,0xcc,
+ 0x35,0x93,0xf1,0x34,0x64,0xcb,0x5f,0xc0,0xfb,0x70,0x90,0xf3,0x90,0x87,0x7a,0xea,0x46,0x55,0xf7,0x27,0x58,0xb1,0x05),
+ (0x58,0x00,0xfb,0x0d,0xbc,0xb2,0x9b,0x65,0x53,0x9d,0xbe,0x0d,0xde,0xb9,0x7f,0x64,0x7b,0x57,0xa9,0x19,
+ 0x63,0x68,0x05,0xde,0x06,0x4a,0x3a,0xe1,0x04,0xfa,0xe0,0x1f,0x24,0x2f,0xfc,0xa9,0x5b,0xf8,0x03,0xe3,0x99,
+ 0x6b,0x26,0xe3,0x69,0xc8,0x96,0xbf,0x80,0xf7,0xe1,0x20,0xe7,0x21,0x0f,0xf5,0xd4,0x8d,0xaa,0xee,0x4f,0xb0,0x62,0x0b),
+ (0xb0,0x00,0xf6,0x1b,0x78,0x65,0x37,0xcb,0xa6,0x3a,0x7d,0x1b,0xbc,0x73,0xff,0xc8,0xf6,0xae,0x52,0x33,
+ 0xc6,0xd0,0x0a,0xbc,0x0d,0x94,0x74,0xc2,0x09,0xf4,0xc1,0x3f,0x48,0x5e,0xf8,0x53,0xb7,0xf0,0x07,0xc6,0x33,
+ 0xd7,0x4c,0xc6,0xd3,0x90,0x2d,0x7f,0x01,0xef,0xc3,0x41,0xce,0x43,0x1e,0xea,0xa9,0x1b,0x55,0xdd,0x9f,0x60,0xc5,0x16),
+ (0x60,0x01,0xec,0x37,0xf0,0xca,0x6e,0x96,0x4d,0x75,0xfa,0x36,0x78,0xe7,0xfe,0x91,0xed,0x5d,0xa5,0x66,
+ 0x8c,0xa1,0x15,0x78,0x1b,0x28,0xe9,0x84,0x13,0xe8,0x83,0x7f,0x90,0xbc,0xf0,0xa7,0x6e,0xe1,0x0f,0x8c,0x67,
+ 0xae,0x99,0x8c,0xa7,0x21,0x5b,0xfe,0x02,0xde,0x87,0x83,0x9c,0x87,0x3c,0xd4,0x53,0x37,0xaa,0xba,0x3f,0xc1,0x8a,0x2d),
+ (0xc0,0x02,0xd8,0x6f,0xe0,0x95,0xdd,0x2c,0x9b,0xea,0xf4,0x6d,0xf0,0xce,0xfd,0x23,0xdb,0xbb,0x4a,0xcd,
+ 0x18,0x43,0x2b,0xf0,0x36,0x50,0xd2,0x09,0x27,0xd0,0x07,0xff,0x20,0x79,0xe1,0x4f,0xdd,0xc2,0x1f,0x18,0xcf,
+ 0x5c,0x33,0x19,0x4f,0x43,0xb6,0xfc,0x05,0xbc,0x0f,0x07,0x39,0x0f,0x79,0xa8,0xa7,0x6e,0x54,0x75,0x7f,0x82,0x15,0x5b),
+ (0x80,0x05,0xb0,0xdf,0xc0,0x2b,0xbb,0x59,0x36,0xd5,0xe9,0xdb,0xe0,0x9d,0xfb,0x47,0xb6,0x77,0x95,0x9a,
+ 0x31,0x86,0x56,0xe0,0x6d,0xa0,0xa4,0x13,0x4e,0xa0,0x0f,0xfe,0x41,0xf2,0xc2,0x9f,0xba,0x85,0x3f,0x30,0x9e,
+ 0xb9,0x66,0x32,0x9e,0x86,0x6c,0xf9,0x0b,0x78,0x1f,0x0e,0x72,0x1e,0xf2,0x50,0x4f,0xdd,0xa8,0xea,0xfe,0x04,0x2b,0xb6))
+
+M_14_40 = (
+ (0x07,0xfc,0x23,0x1b,0x0b,0x76,0x74,0xd3,0x0c,0xf3,0x99,0x16,0x24,0xcd,0x55,0xde,0xf6,0x72,0xe5,0x93,
+ 0x5f,0xc9,0xef,0x51,0xee,0x1b,0x7e,0x95,0x33,0x51,0x2b,0x68,0x66,0x93,0x54,0x29,0x02,0x18,0xc4,0x7d,
+ 0xef,0xf8,0x99,0xa3,0x34,0x6f,0xf4,0x8b,0x10,0xea,0x8f,0xee,0xf7,0xeb,0x96,0x44,0xf6,0x19,0x65,0x4b,
+ 0xc1,0x8d,0xda,0x49,0x0a,0x80,0x72,0xee,0x69,0x07,0x01),
+ (0x0e,0xf8,0x47,0x36,0x16,0xec,0xe8,0xa6,0x19,0xe6,0x33,0x2d,0x48,0x9a,0xab,0xbc,0xed,0xe5,0xca,0x27,
+ 0xbf,0x92,0xdf,0xa3,0xdc,0x37,0xfc,0x2a,0x67,0xa2,0x56,0xd0,0xcc,0x26,0xa9,0x52,0x04,0x30,0x88,0xfb,
+ 0xde,0xf1,0x33,0x47,0x69,0xde,0xe8,0x17,0x21,0xd4,0x1f,0xdd,0xef,0xd7,0x2d,0x89,0xec,0x33,0xca,0x96,
+ 0x82,0x1b,0xb5,0x93,0x14,0x00,0xe5,0xdc,0xd3,0x0e,0x02),
+ (0x1c,0xf0,0x8f,0x6c,0x2c,0xd8,0xd1,0x4d,0x33,0xcc,0x67,0x5a,0x90,0x34,0x57,0x79,0xdb,0xcb,0x95,0x4f,
+ 0x7e,0x25,0xbf,0x47,0xb9,0x6f,0xf8,0x55,0xce,0x44,0xad,0xa0,0x99,0x4d,0x52,0xa5,0x08,0x60,0x10,0xf7,
+ 0xbd,0xe3,0x67,0x8e,0xd2,0xbc,0xd1,0x2f,0x42,0xa8,0x3f,0xba,0xdf,0xaf,0x5b,0x12,0xd9,0x67,0x94,0x2d,
+ 0x05,0x37,0x6a,0x27,0x29,0x00,0xca,0xb9,0xa7,0x1d,0x04),
+ (0x38,0xe0,0x1f,0xd9,0x58,0xb0,0xa3,0x9b,0x66,0x98,0xcf,0xb4,0x20,0x69,0xae,0xf2,0xb6,0x97,0x2b,0x9f,
+ 0xfc,0x4a,0x7e,0x8f,0x72,0xdf,0xf0,0xab,0x9c,0x89,0x5a,0x41,0x33,0x9b,0xa4,0x4a,0x11,0xc0,0x20,0xee,
+ 0x7b,0xc7,0xcf,0x1c,0xa5,0x79,0xa3,0x5f,0x84,0x50,0x7f,0x74,0xbf,0x5f,0xb7,0x24,0xb2,0xcf,0x28,0x5b,
+ 0x0a,0x6e,0xd4,0x4e,0x52,0x00,0x94,0x73,0x4f,0x3b,0x08),
+ (0x70,0xc0,0x3f,0xb2,0xb1,0x60,0x47,0x37,0xcd,0x30,0x9f,0x69,0x41,0xd2,0x5c,0xe5,0x6d,0x2f,0x57,0x3e,
+ 0xf9,0x95,0xfc,0x1e,0xe5,0xbe,0xe1,0x57,0x39,0x13,0xb5,0x82,0x66,0x36,0x49,0x95,0x22,0x80,0x41,0xdc,
+ 0xf7,0x8e,0x9f,0x39,0x4a,0xf3,0x46,0xbf,0x08,0xa1,0xfe,0xe8,0x7e,0xbf,0x6e,0x49,0x64,0x9f,0x51,0xb6,
+ 0x14,0xdc,0xa8,0x9d,0xa4,0x00,0x28,0xe7,0x9e,0x76,0x10),
+ (0xe0,0x80,0x7f,0x64,0x63,0xc1,0x8e,0x6e,0x9a,0x61,0x3e,0xd3,0x82,0xa4,0xb9,0xca,0xdb,0x5e,0xae,0x7c,
+ 0xf2,0x2b,0xf9,0x3d,0xca,0x7d,0xc3,0xaf,0x72,0x26,0x6a,0x05,0xcd,0x6c,0x92,0x2a,0x45,0x00,0x83,0xb8,
+ 0xef,0x1d,0x3f,0x73,0x94,0xe6,0x8d,0x7e,0x11,0x42,0xfd,0xd1,0xfd,0x7e,0xdd,0x92,0xc8,0x3e,0xa3,0x6c,
+ 0x29,0xb8,0x51,0x3b,0x49,0x01,0x50,0xce,0x3d,0xed,0x20),
+ (0xc0,0x01,0xff,0xc8,0xc6,0x82,0x1d,0xdd,0x34,0xc3,0x7c,0xa6,0x05,0x49,0x73,0x95,0xb7,0xbd,0x5c,0xf9,
+ 0xe4,0x57,0xf2,0x7b,0x94,0xfb,0x86,0x5f,0xe5,0x4c,0xd4,0x0a,0x9a,0xd9,0x24,0x55,0x8a,0x00,0x06,0x71,
+ 0xdf,0x3b,0x7e,0xe6,0x28,0xcd,0x1b,0xfd,0x22,0x84,0xfa,0xa3,0xfb,0xfd,0xba,0x25,0x91,0x7d,0x46,0xd9,
+ 0x52,0x70,0xa3,0x76,0x92,0x02,0xa0,0x9c,0x7b,0xda,0x41),
+ (0x80,0x03,0xfe,0x91,0x8d,0x05,0x3b,0xba,0x69,0x86,0xf9,0x4c,0x0b,0x92,0xe6,0x2a,0x6f,0x7b,0xb9,0xf2,
+ 0xc9,0xaf,0xe4,0xf7,0x28,0xf7,0x0d,0xbf,0xca,0x99,0xa8,0x15,0x34,0xb3,0x49,0xaa,0x14,0x01,0x0c,0xe2,
+ 0xbe,0x77,0xfc,0xcc,0x51,0x9a,0x37,0xfa,0x45,0x08,0xf5,0x47,0xf7,0xfb,0x75,0x4b,0x22,0xfb,0x8c,0xb2,
+ 0xa5,0xe0,0x46,0xed,0x24,0x05,0x40,0x39,0xf7,0xb4,0x83))
+
+M_14_44 = (
+ (0x7d,0xa2,0x90,0xd1,0x9e,0x20,0xfb,0xa2,0xfc,0xec,0x54,0xbe,0xe8,0x7c,0xc7,0xcf,0x35,0xe2,0x9e,0x88,
+ 0xbb,0x90,0x85,0x87,0xb0,0xce,0x13,0x68,0xe7,0xa1,0xfc,0xd7,0xe0,0x8b,0x65,0x5a,0xad,0xf2,0xfd,0x0c,
+ 0x14,0x48,0x8c,0xa1,0x2c,0x93,0xc1,0xac,0x2c,0x90,0x73,0x0e,0xe7,0xcb,0xf9,0x3c,0xef,0xb4,0xd8,0x6e,
+ 0x6e,0xed,0x5a,0x44,0xe9,0xde,0x74,0xfc,0xec,0x76,0x29,0xcb,0x9d,0x46,0x3a,0xd9,0x98,0x01),
+ (0xfa,0x44,0x21,0xa3,0x3d,0x41,0xf6,0x45,0xf9,0xd9,0xa9,0x7c,0xd1,0xf9,0x8e,0x9f,0x6b,0xc4,0x3d,0x11,
+ 0x77,0x21,0x0b,0x0f,0x61,0x9d,0x27,0xd0,0xce,0x43,0xf9,0xaf,0xc1,0x17,0xcb,0xb4,0x5a,0xe5,0xfb,0x19,
+ 0x28,0x90,0x18,0x43,0x59,0x26,0x83,0x59,0x59,0x20,0xe7,0x1c,0xce,0x97,0xf3,0x79,0xde,0x69,0xb1,0xdd,
+ 0xdc,0xda,0xb5,0x88,0xd2,0xbd,0xe9,0xf8,0xd9,0xed,0x52,0x96,0x3b,0x8d,0x74,0xb2,0x31,0x03),
+ (0xf4,0x89,0x42,0x46,0x7b,0x82,0xec,0x8b,0xf2,0xb3,0x53,0xf9,0xa2,0xf3,0x1d,0x3f,0xd7,0x88,0x7b,0x22,
+ 0xee,0x42,0x16,0x1e,0xc2,0x3a,0x4f,0xa0,0x9d,0x87,0xf2,0x5f,0x83,0x2f,0x96,0x69,0xb5,0xca,0xf7,0x33,
+ 0x50,0x20,0x31,0x86,0xb2,0x4c,0x06,0xb3,0xb2,0x40,0xce,0x39,0x9c,0x2f,0xe7,0xf3,0xbc,0xd3,0x62,0xbb,
+ 0xb9,0xb5,0x6b,0x11,0xa5,0x7b,0xd3,0xf1,0xb3,0xdb,0xa5,0x2c,0x77,0x1a,0xe9,0x64,0x63,0x06),
+ (0xe8,0x13,0x85,0x8c,0xf6,0x04,0xd9,0x17,0xe5,0x67,0xa7,0xf2,0x45,0xe7,0x3b,0x7e,0xae,0x11,0xf7,0x44,
+ 0xdc,0x85,0x2c,0x3c,0x84,0x75,0x9e,0x40,0x3b,0x0f,0xe5,0xbf,0x06,0x5f,0x2c,0xd3,0x6a,0x95,0xef,0x67,
+ 0xa0,0x40,0x62,0x0c,0x65,0x99,0x0c,0x66,0x65,0x81,0x9c,0x73,0x38,0x5f,0xce,0xe7,0x79,0xa7,0xc5,0x76,
+ 0x73,0x6b,0xd7,0x22,0x4a,0xf7,0xa6,0xe3,0x67,0xb7,0x4b,0x59,0xee,0x34,0xd2,0xc9,0xc6,0x0c),
+ (0xd0,0x27,0x0a,0x19,0xed,0x09,0xb2,0x2f,0xca,0xcf,0x4e,0xe5,0x8b,0xce,0x77,0xfc,0x5c,0x23,0xee,0x89,
+ 0xb8,0x0b,0x59,0x78,0x08,0xeb,0x3c,0x81,0x76,0x1e,0xca,0x7f,0x0d,0xbe,0x58,0xa6,0xd5,0x2a,0xdf,0xcf,
+ 0x40,0x81,0xc4,0x18,0xca,0x32,0x19,0xcc,0xca,0x02,0x39,0xe7,0x70,0xbe,0x9c,0xcf,0xf3,0x4e,0x8b,0xed,
+ 0xe6,0xd6,0xae,0x45,0x94,0xee,0x4d,0xc7,0xcf,0x6e,0x97,0xb2,0xdc,0x69,0xa4,0x93,0x8d,0x19),
+ (0xa0,0x4f,0x14,0x32,0xda,0x13,0x64,0x5f,0x94,0x9f,0x9d,0xca,0x17,0x9d,0xef,0xf8,0xb9,0x46,0xdc,0x13,
+ 0x71,0x17,0xb2,0xf0,0x10,0xd6,0x79,0x02,0xed,0x3c,0x94,0xff,0x1a,0x7c,0xb1,0x4c,0xab,0x55,0xbe,0x9f,
+ 0x81,0x02,0x89,0x31,0x94,0x65,0x32,0x98,0x95,0x05,0x72,0xce,0xe1,0x7c,0x39,0x9f,0xe7,0x9d,0x16,0xdb,
+ 0xcd,0xad,0x5d,0x8b,0x28,0xdd,0x9b,0x8e,0x9f,0xdd,0x2e,0x65,0xb9,0xd3,0x48,0x27,0x1b,0x33),
+ (0x40,0x9f,0x28,0x64,0xb4,0x27,0xc8,0xbe,0x28,0x3f,0x3b,0x95,0x2f,0x3a,0xdf,0xf1,0x73,0x8d,0xb8,0x27,
+ 0xe2,0x2e,0x64,0xe1,0x21,0xac,0xf3,0x04,0xda,0x79,0x28,0xff,0x35,0xf8,0x62,0x99,0x56,0xab,0x7c,0x3f,
+ 0x03,0x05,0x12,0x63,0x28,0xcb,0x64,0x30,0x2b,0x0b,0xe4,0x9c,0xc3,0xf9,0x72,0x3e,0xcf,0x3b,0x2d,0xb6,
+ 0x9b,0x5b,0xbb,0x16,0x51,0xba,0x37,0x1d,0x3f,0xbb,0x5d,0xca,0x72,0xa7,0x91,0x4e,0x36,0x66),
+ (0x80,0x3e,0x51,0xc8,0x68,0x4f,0x90,0x7d,0x51,0x7e,0x76,0x2a,0x5f,0x74,0xbe,0xe3,0xe7,0x1a,0x71,0x4f,
+ 0xc4,0x5d,0xc8,0xc2,0x43,0x58,0xe7,0x09,0xb4,0xf3,0x50,0xfe,0x6b,0xf0,0xc5,0x32,0xad,0x56,0xf9,0x7e,
+ 0x06,0x0a,0x24,0xc6,0x50,0x96,0xc9,0x60,0x56,0x16,0xc8,0x39,0x87,0xf3,0xe5,0x7c,0x9e,0x77,0x5a,0x6c,
+ 0x37,0xb7,0x76,0x2d,0xa2,0x74,0x6f,0x3a,0x7e,0x76,0xbb,0x94,0xe5,0x4e,0x23,0x9d,0x6c,0xcc))
+
+M_14_48 = (
+ (0x35,0x47,0xc2,0xf2,0xec,0xd9,0xb1,0x4c,0x34,0xd1,0x12,0x79,0x34,0xab,0x17,0x76,0x39,0x6a,0x37,0x7b,0x4d,
+ 0xfe,0xb6,0x97,0xee,0xe9,0x71,0x1d,0xf6,0x99,0xf7,0x8e,0x9a,0x1f,0x05,0x13,0x6f,0xcc,0xb9,0xce,0xcf,0x60,
+ 0xb9,0x66,0x35,0xa2,0xfc,0x8e,0x9a,0x40,0xdc,0x24,0xf6,0x6b,0xd9,0x96,0xfa,0xa1,0xfb,0x5f,0xc1,0xc2,0x6a,
+ 0x84,0x88,0x13,0x48,0x43,0xcb,0xcb,0x77,0x63,0xc1,0xfa,0xf9,0x16,0xd4,0x69,0xd8,0x98,0x96,0x38,0x8f,0xae,0x01),
+ (0x6a,0x8e,0x84,0xe5,0xd9,0xb3,0x63,0x99,0x68,0xa2,0x25,0xf2,0x68,0x56,0x2f,0xec,0x72,0xd4,0x6e,0xf6,0x9a,
+ 0xfc,0x6d,0x2f,0xdd,0xd3,0xe3,0x3a,0xec,0x33,0xef,0x1d,0x35,0x3f,0x0a,0x26,0xde,0x98,0x73,0x9d,0x9f,0xc1,
+ 0x72,0xcd,0x6a,0x44,0xf9,0x1d,0x35,0x81,0xb8,0x49,0xec,0xd7,0xb2,0x2d,0xf5,0x43,0xf7,0xbf,0x82,0x85,0xd5,
+ 0x08,0x11,0x27,0x90,0x86,0x96,0x97,0xef,0xc6,0x82,0xf5,0xf3,0x2d,0xa8,0xd3,0xb0,0x31,0x2d,0x71,0x1e,0x5d,0x03),
+ (0xd4,0x1c,0x09,0xcb,0xb3,0x67,0xc7,0x32,0xd1,0x44,0x4b,0xe4,0xd1,0xac,0x5e,0xd8,0xe5,0xa8,0xdd,0xec,0x35,
+ 0xf9,0xdb,0x5e,0xba,0xa7,0xc7,0x75,0xd8,0x67,0xde,0x3b,0x6a,0x7e,0x14,0x4c,0xbc,0x31,0xe7,0x3a,0x3f,0x83,
+ 0xe5,0x9a,0xd5,0x88,0xf2,0x3b,0x6a,0x02,0x71,0x93,0xd8,0xaf,0x65,0x5b,0xea,0x87,0xee,0x7f,0x05,0x0b,0xab,
+ 0x11,0x22,0x4e,0x20,0x0d,0x2d,0x2f,0xdf,0x8d,0x05,0xeb,0xe7,0x5b,0x50,0xa7,0x61,0x63,0x5a,0xe2,0x3c,0xba,0x06),
+ (0xa8,0x39,0x12,0x96,0x67,0xcf,0x8e,0x65,0xa2,0x89,0x96,0xc8,0xa3,0x59,0xbd,0xb0,0xcb,0x51,0xbb,0xd9,0x6b,
+ 0xf2,0xb7,0xbd,0x74,0x4f,0x8f,0xeb,0xb0,0xcf,0xbc,0x77,0xd4,0xfc,0x28,0x98,0x78,0x63,0xce,0x75,0x7e,0x06,
+ 0xcb,0x35,0xab,0x11,0xe5,0x77,0xd4,0x04,0xe2,0x26,0xb1,0x5f,0xcb,0xb6,0xd4,0x0f,0xdd,0xff,0x0a,0x16,0x56,
+ 0x23,0x44,0x9c,0x40,0x1a,0x5a,0x5e,0xbe,0x1b,0x0b,0xd6,0xcf,0xb7,0xa0,0x4e,0xc3,0xc6,0xb4,0xc4,0x79,0x74,0x0d),
+ (0x50,0x73,0x24,0x2c,0xcf,0x9e,0x1d,0xcb,0x44,0x13,0x2d,0x91,0x47,0xb3,0x7a,0x61,0x97,0xa3,0x76,0xb3,0xd7,
+ 0xe4,0x6f,0x7b,0xe9,0x9e,0x1e,0xd7,0x61,0x9f,0x79,0xef,0xa8,0xf9,0x51,0x30,0xf1,0xc6,0x9c,0xeb,0xfc,0x0c,
+ 0x96,0x6b,0x56,0x23,0xca,0xef,0xa8,0x09,0xc4,0x4d,0x62,0xbf,0x96,0x6d,0xa9,0x1f,0xba,0xff,0x15,0x2c,0xac,
+ 0x46,0x88,0x38,0x81,0x34,0xb4,0xbc,0x7c,0x37,0x16,0xac,0x9f,0x6f,0x41,0x9d,0x86,0x8d,0x69,0x89,0xf3,0xe8,0x1a),
+ (0xa0,0xe6,0x48,0x58,0x9e,0x3d,0x3b,0x96,0x89,0x26,0x5a,0x22,0x8f,0x66,0xf5,0xc2,0x2e,0x47,0xed,0x66,0xaf,
+ 0xc9,0xdf,0xf6,0xd2,0x3d,0x3d,0xae,0xc3,0x3e,0xf3,0xde,0x51,0xf3,0xa3,0x60,0xe2,0x8d,0x39,0xd7,0xf9,0x19,
+ 0x2c,0xd7,0xac,0x46,0x94,0xdf,0x51,0x13,0x88,0x9b,0xc4,0x7e,0x2d,0xdb,0x52,0x3f,0x74,0xff,0x2b,0x58,0x58,
+ 0x8d,0x10,0x71,0x02,0x69,0x68,0x79,0xf9,0x6e,0x2c,0x58,0x3f,0xdf,0x82,0x3a,0x0d,0x1b,0xd3,0x12,0xe7,0xd1,0x35),
+ (0x40,0xcd,0x91,0xb0,0x3c,0x7b,0x76,0x2c,0x13,0x4d,0xb4,0x44,0x1e,0xcd,0xea,0x85,0x5d,0x8e,0xda,0xcd,0x5e,
+ 0x93,0xbf,0xed,0xa5,0x7b,0x7a,0x5c,0x87,0x7d,0xe6,0xbd,0xa3,0xe6,0x47,0xc1,0xc4,0x1b,0x73,0xae,0xf3,0x33,
+ 0x58,0xae,0x59,0x8d,0x28,0xbf,0xa3,0x26,0x10,0x37,0x89,0xfd,0x5a,0xb6,0xa5,0x7e,0xe8,0xfe,0x57,0xb0,0xb0,
+ 0x1a,0x21,0xe2,0x04,0xd2,0xd0,0xf2,0xf2,0xdd,0x58,0xb0,0x7e,0xbe,0x05,0x75,0x1a,0x36,0xa6,0x25,0xce,0xa3,0x6b),
+ (0x80,0x9a,0x23,0x61,0x79,0xf6,0xec,0x58,0x26,0x9a,0x68,0x89,0x3c,0x9a,0xd5,0x0b,0xbb,0x1c,0xb5,0x9b,0xbd,
+ 0x26,0x7f,0xdb,0x4b,0xf7,0xf4,0xb8,0x0e,0xfb,0xcc,0x7b,0x47,0xcd,0x8f,0x82,0x89,0x37,0xe6,0x5c,0xe7,0x67,
+ 0xb0,0x5c,0xb3,0x1a,0x51,0x7e,0x47,0x4d,0x20,0x6e,0x12,0xfb,0xb5,0x6c,0x4b,0xfd,0xd0,0xfd,0xaf,0x60,0x61,
+ 0x35,0x42,0xc4,0x09,0xa4,0xa1,0xe5,0xe5,0xbb,0xb1,0x60,0xfd,0x7c,0x0b,0xea,0x34,0x6c,0x4c,0x4b,0x9c,0x47,0xd7))
+
+M_14_52 = (
+ (0x59,0x1e,0x2c,0xdc,0xd7,0x83,0xf5,0xe2,0x0b,0x8f,0x38,0xb3,0x18,0xaf,0x4d,0xc3,0xec,0x44,0x65,0xad,0xbf,
+ 0x7a,0xd7,0xd9,0x60,0x25,0x18,0x74,0xa4,0x00,0x48,0xce,0x0d,0xb8,0x77,0x76,0x2a,0x13,0xe3,0x63,0x93,0xd3,
+ 0xa4,0x17,0x9b,0x05,0x74,0x05,0x3d,0xad,0xa6,0xe6,0xcc,0x03,0xdf,0x2e,0xce,0xf5,0x32,0xd8,0x6f,0x76,0x16,
+ 0x4f,0x9c,0xbf,0x61,0x7e,0x04,0x1f,0x57,0xf6,0x68,0x01,0xff,0x7c,0x10,0xb1,0x7a,0x5e,0xb5,0xdd,0xae,0xef,
+ 0xe3,0xf7,0xa7,0x23,0xda,0xec,0xbd,0x01),
+ (0xb2,0x3c,0x58,0xb8,0xaf,0x07,0xeb,0xc5,0x17,0x1e,0x71,0x66,0x31,0x5e,0x9b,0x86,0xd9,0x89,0xca,0x5a,0x7f,
+ 0xf5,0xae,0xb3,0xc1,0x4a,0x30,0xe8,0x48,0x01,0x90,0x9c,0x1b,0x70,0xef,0xec,0x54,0x26,0xc6,0xc7,0x26,0xa7,
+ 0x49,0x2f,0x36,0x0b,0xe8,0x0a,0x7a,0x5a,0x4d,0xcd,0x99,0x07,0xbe,0x5d,0x9c,0xeb,0x65,0xb0,0xdf,0xec,0x2c,
+ 0x9e,0x38,0x7f,0xc3,0xfc,0x08,0x3e,0xae,0xec,0xd1,0x02,0xfe,0xf9,0x20,0x62,0xf5,0xbc,0x6a,0xbb,0x5d,0xdf,
+ 0xc7,0xef,0x4f,0x47,0xb4,0xd9,0x7b,0x03),
+ (0x64,0x79,0xb0,0x70,0x5f,0x0f,0xd6,0x8b,0x2f,0x3c,0xe2,0xcc,0x62,0xbc,0x36,0x0d,0xb3,0x13,0x95,0xb5,0xfe,
+ 0xea,0x5d,0x67,0x83,0x95,0x60,0xd0,0x91,0x02,0x20,0x39,0x37,0xe0,0xde,0xd9,0xa9,0x4c,0x8c,0x8f,0x4d,0x4e,
+ 0x93,0x5e,0x6c,0x16,0xd0,0x15,0xf4,0xb4,0x9a,0x9a,0x33,0x0f,0x7c,0xbb,0x38,0xd7,0xcb,0x60,0xbf,0xd9,0x59,
+ 0x3c,0x71,0xfe,0x86,0xf9,0x11,0x7c,0x5c,0xd9,0xa3,0x05,0xfc,0xf3,0x41,0xc4,0xea,0x79,0xd5,0x76,0xbb,0xbe,
+ 0x8f,0xdf,0x9f,0x8e,0x68,0xb3,0xf7,0x06),
+ (0xc8,0xf2,0x60,0xe1,0xbe,0x1e,0xac,0x17,0x5f,0x78,0xc4,0x99,0xc5,0x78,0x6d,0x1a,0x66,0x27,0x2a,0x6b,0xfd,
+ 0xd5,0xbb,0xce,0x06,0x2b,0xc1,0xa0,0x23,0x05,0x40,0x72,0x6e,0xc0,0xbd,0xb3,0x53,0x99,0x18,0x1f,0x9b,0x9c,
+ 0x26,0xbd,0xd8,0x2c,0xa0,0x2b,0xe8,0x69,0x35,0x35,0x67,0x1e,0xf8,0x76,0x71,0xae,0x97,0xc1,0x7e,0xb3,0xb3,
+ 0x78,0xe2,0xfc,0x0d,0xf3,0x23,0xf8,0xb8,0xb2,0x47,0x0b,0xf8,0xe7,0x83,0x88,0xd5,0xf3,0xaa,0xed,0x76,0x7d,
+ 0x1f,0xbf,0x3f,0x1d,0xd1,0x66,0xef,0x0d),
+ (0x90,0xe5,0xc1,0xc2,0x7d,0x3d,0x58,0x2f,0xbe,0xf0,0x88,0x33,0x8b,0xf1,0xda,0x34,0xcc,0x4e,0x54,0xd6,0xfa,
+ 0xab,0x77,0x9d,0x0d,0x56,0x82,0x41,0x47,0x0a,0x80,0xe4,0xdc,0x80,0x7b,0x67,0xa7,0x32,0x31,0x3e,0x36,0x39,
+ 0x4d,0x7a,0xb1,0x59,0x40,0x57,0xd0,0xd3,0x6a,0x6a,0xce,0x3c,0xf0,0xed,0xe2,0x5c,0x2f,0x83,0xfd,0x66,0x67,
+ 0xf1,0xc4,0xf9,0x1b,0xe6,0x47,0xf0,0x71,0x65,0x8f,0x16,0xf0,0xcf,0x07,0x11,0xab,0xe7,0x55,0xdb,0xed,0xfa,
+ 0x3e,0x7e,0x7f,0x3a,0xa2,0xcd,0xde,0x1b),
+ (0x20,0xcb,0x83,0x85,0xfb,0x7a,0xb0,0x5e,0x7c,0xe1,0x11,0x67,0x16,0xe3,0xb5,0x69,0x98,0x9d,0xa8,0xac,0xf5,
+ 0x57,0xef,0x3a,0x1b,0xac,0x04,0x83,0x8e,0x14,0x00,0xc9,0xb9,0x01,0xf7,0xce,0x4e,0x65,0x62,0x7c,0x6c,0x72,
+ 0x9a,0xf4,0x62,0xb3,0x80,0xae,0xa0,0xa7,0xd5,0xd4,0x9c,0x79,0xe0,0xdb,0xc5,0xb9,0x5e,0x06,0xfb,0xcd,0xce,
+ 0xe2,0x89,0xf3,0x37,0xcc,0x8f,0xe0,0xe3,0xca,0x1e,0x2d,0xe0,0x9f,0x0f,0x22,0x56,0xcf,0xab,0xb6,0xdb,0xf5,
+ 0x7d,0xfc,0xfe,0x74,0x44,0x9b,0xbd,0x37),
+ (0x40,0x96,0x07,0x0b,0xf7,0xf5,0x60,0xbd,0xf8,0xc2,0x23,0xce,0x2c,0xc6,0x6b,0xd3,0x30,0x3b,0x51,0x59,0xeb,
+ 0xaf,0xde,0x75,0x36,0x58,0x09,0x06,0x1d,0x29,0x00,0x92,0x73,0x03,0xee,0x9d,0x9d,0xca,0xc4,0xf8,0xd8,0xe4,
+ 0x34,0xe9,0xc5,0x66,0x01,0x5d,0x41,0x4f,0xab,0xa9,0x39,0xf3,0xc0,0xb7,0x8b,0x73,0xbd,0x0c,0xf6,0x9b,0x9d,
+ 0xc5,0x13,0xe7,0x6f,0x98,0x1f,0xc1,0xc7,0x95,0x3d,0x5a,0xc0,0x3f,0x1f,0x44,0xac,0x9e,0x57,0x6d,0xb7,0xeb,
+ 0xfb,0xf8,0xfd,0xe9,0x88,0x36,0x7b,0x6f),
+ (0x80,0x2c,0x0f,0x16,0xee,0xeb,0xc1,0x7a,0xf1,0x85,0x47,0x9c,0x59,0x8c,0xd7,0xa6,0x61,0x76,0xa2,0xb2,0xd6,
+ 0x5f,0xbd,0xeb,0x6c,0xb0,0x12,0x0c,0x3a,0x52,0x00,0x24,0xe7,0x06,0xdc,0x3b,0x3b,0x95,0x89,0xf1,0xb1,0xc9,
+ 0x69,0xd2,0x8b,0xcd,0x02,0xba,0x82,0x9e,0x56,0x53,0x73,0xe6,0x81,0x6f,0x17,0xe7,0x7a,0x19,0xec,0x37,0x3b,
+ 0x8b,0x27,0xce,0xdf,0x30,0x3f,0x82,0x8f,0x2b,0x7b,0xb4,0x80,0x7f,0x3e,0x88,0x58,0x3d,0xaf,0xda,0x6e,0xd7,
+ 0xf7,0xf1,0xfb,0xd3,0x11,0x6d,0xf6,0xde))
+
+M_14_56 = (
+ (0x09,0x0c,0xd9,0xd0,0xcb,0xbe,0x78,0x3e,0x36,0xc1,0x98,0xbd,0x12,0x71,0x0c,0x3f,0x74,0x83,0x2f,0x15,0x56,
+ 0xbf,0xd7,0xb9,0x1d,0x07,0x43,0xe8,0x19,0x60,0x3e,0xe4,0x9c,0x9e,0xfd,0xad,0x6e,0x9e,0xda,0x69,0xc9,0x52,
+ 0x2d,0xf5,0xe3,0x8e,0xe4,0x45,0x4a,0x34,0x7b,0x2d,0xce,0x27,0x8d,0x97,0x4a,0xa9,0xfc,0xd0,0xe0,0x99,0x90,
+ 0xb0,0x8e,0x7a,0xcf,0x2a,0xa1,0x9c,0xcb,0x1f,0x96,0x32,0xa3,0x19,0xd8,0x42,0x67,0x08,0x6e,0xf3,0xb0,0xd1,
+ 0x38,0xf3,0x05,0x88,0x34,0x5a,0x46,0x68,0x83,0x7d,0xa2,0xf9,0xf7,0x1d,0x01),
+ (0x12,0x18,0xb2,0xa1,0x97,0x7d,0xf1,0x7c,0x6c,0x82,0x31,0x7b,0x25,0xe2,0x18,0x7e,0xe8,0x06,0x5f,0x2a,0xac,
+ 0x7e,0xaf,0x73,0x3b,0x0e,0x86,0xd0,0x33,0xc0,0x7c,0xc8,0x39,0x3d,0xfb,0x5b,0xdd,0x3c,0xb5,0xd3,0x92,0xa5,
+ 0x5a,0xea,0xc7,0x1d,0xc9,0x8b,0x94,0x68,0xf6,0x5a,0x9c,0x4f,0x1a,0x2f,0x95,0x52,0xf9,0xa1,0xc1,0x33,0x21,
+ 0x61,0x1d,0xf5,0x9e,0x55,0x42,0x39,0x97,0x3f,0x2c,0x65,0x46,0x33,0xb0,0x85,0xce,0x10,0xdc,0xe6,0x61,0xa3,
+ 0x71,0xe6,0x0b,0x10,0x69,0xb4,0x8c,0xd0,0x06,0xfb,0x44,0xf3,0xef,0x3b,0x02),
+ (0x24,0x30,0x64,0x43,0x2f,0xfb,0xe2,0xf9,0xd8,0x04,0x63,0xf6,0x4a,0xc4,0x31,0xfc,0xd0,0x0d,0xbe,0x54,0x58,
+ 0xfd,0x5e,0xe7,0x76,0x1c,0x0c,0xa1,0x67,0x80,0xf9,0x90,0x73,0x7a,0xf6,0xb7,0xba,0x79,0x6a,0xa7,0x25,0x4b,
+ 0xb5,0xd4,0x8f,0x3b,0x92,0x17,0x29,0xd1,0xec,0xb5,0x38,0x9f,0x34,0x5e,0x2a,0xa5,0xf2,0x43,0x83,0x67,0x42,
+ 0xc2,0x3a,0xea,0x3d,0xab,0x84,0x72,0x2e,0x7f,0x58,0xca,0x8c,0x66,0x60,0x0b,0x9d,0x21,0xb8,0xcd,0xc3,0x46,
+ 0xe3,0xcc,0x17,0x20,0xd2,0x68,0x19,0xa1,0x0d,0xf6,0x89,0xe6,0xdf,0x77,0x04),
+ (0x48,0x60,0xc8,0x86,0x5e,0xf6,0xc5,0xf3,0xb1,0x09,0xc6,0xec,0x95,0x88,0x63,0xf8,0xa1,0x1b,0x7c,0xa9,0xb0,
+ 0xfa,0xbd,0xce,0xed,0x38,0x18,0x42,0xcf,0x00,0xf3,0x21,0xe7,0xf4,0xec,0x6f,0x75,0xf3,0xd4,0x4e,0x4b,0x96,
+ 0x6a,0xa9,0x1f,0x77,0x24,0x2f,0x52,0xa2,0xd9,0x6b,0x71,0x3e,0x69,0xbc,0x54,0x4a,0xe5,0x87,0x06,0xcf,0x84,
+ 0x84,0x75,0xd4,0x7b,0x56,0x09,0xe5,0x5c,0xfe,0xb0,0x94,0x19,0xcd,0xc0,0x16,0x3a,0x43,0x70,0x9b,0x87,0x8d,
+ 0xc6,0x99,0x2f,0x40,0xa4,0xd1,0x32,0x42,0x1b,0xec,0x13,0xcd,0xbf,0xef,0x08),
+ (0x90,0xc0,0x90,0x0d,0xbd,0xec,0x8b,0xe7,0x63,0x13,0x8c,0xd9,0x2b,0x11,0xc7,0xf0,0x43,0x37,0xf8,0x52,0x61,
+ 0xf5,0x7b,0x9d,0xdb,0x71,0x30,0x84,0x9e,0x01,0xe6,0x43,0xce,0xe9,0xd9,0xdf,0xea,0xe6,0xa9,0x9d,0x96,0x2c,
+ 0xd5,0x52,0x3f,0xee,0x48,0x5e,0xa4,0x44,0xb3,0xd7,0xe2,0x7c,0xd2,0x78,0xa9,0x94,0xca,0x0f,0x0d,0x9e,0x09,
+ 0x09,0xeb,0xa8,0xf7,0xac,0x12,0xca,0xb9,0xfc,0x61,0x29,0x33,0x9a,0x81,0x2d,0x74,0x86,0xe0,0x36,0x0f,0x1b,
+ 0x8d,0x33,0x5f,0x80,0x48,0xa3,0x65,0x84,0x36,0xd8,0x27,0x9a,0x7f,0xdf,0x11),
+ (0x20,0x81,0x21,0x1b,0x7a,0xd9,0x17,0xcf,0xc7,0x26,0x18,0xb3,0x57,0x22,0x8e,0xe1,0x87,0x6e,0xf0,0xa5,0xc2,
+ 0xea,0xf7,0x3a,0xb7,0xe3,0x60,0x08,0x3d,0x03,0xcc,0x87,0x9c,0xd3,0xb3,0xbf,0xd5,0xcd,0x53,0x3b,0x2d,0x59,
+ 0xaa,0xa5,0x7e,0xdc,0x91,0xbc,0x48,0x89,0x66,0xaf,0xc5,0xf9,0xa4,0xf1,0x52,0x29,0x95,0x1f,0x1a,0x3c,0x13,
+ 0x12,0xd6,0x51,0xef,0x59,0x25,0x94,0x73,0xf9,0xc3,0x52,0x66,0x34,0x03,0x5b,0xe8,0x0c,0xc1,0x6d,0x1e,0x36,
+ 0x1a,0x67,0xbe,0x00,0x91,0x46,0xcb,0x08,0x6d,0xb0,0x4f,0x34,0xff,0xbe,0x23),
+ (0x40,0x02,0x43,0x36,0xf4,0xb2,0x2f,0x9e,0x8f,0x4d,0x30,0x66,0xaf,0x44,0x1c,0xc3,0x0f,0xdd,0xe0,0x4b,0x85,
+ 0xd5,0xef,0x75,0x6e,0xc7,0xc1,0x10,0x7a,0x06,0x98,0x0f,0x39,0xa7,0x67,0x7f,0xab,0x9b,0xa7,0x76,0x5a,0xb2,
+ 0x54,0x4b,0xfd,0xb8,0x23,0x79,0x91,0x12,0xcd,0x5e,0x8b,0xf3,0x49,0xe3,0xa5,0x52,0x2a,0x3f,0x34,0x78,0x26,
+ 0x24,0xac,0xa3,0xde,0xb3,0x4a,0x28,0xe7,0xf2,0x87,0xa5,0xcc,0x68,0x06,0xb6,0xd0,0x19,0x82,0xdb,0x3c,0x6c,
+ 0x34,0xce,0x7c,0x01,0x22,0x8d,0x96,0x11,0xda,0x60,0x9f,0x68,0xfe,0x7d,0x47),
+ (0x80,0x04,0x86,0x6c,0xe8,0x65,0x5f,0x3c,0x1f,0x9b,0x60,0xcc,0x5e,0x89,0x38,0x86,0x1f,0xba,0xc1,0x97,0x0a,
+ 0xab,0xdf,0xeb,0xdc,0x8e,0x83,0x21,0xf4,0x0c,0x30,0x1f,0x72,0x4e,0xcf,0xfe,0x56,0x37,0x4f,0xed,0xb4,0x64,
+ 0xa9,0x96,0xfa,0x71,0x47,0xf2,0x22,0x25,0x9a,0xbd,0x16,0xe7,0x93,0xc6,0x4b,0xa5,0x54,0x7e,0x68,0xf0,0x4c,
+ 0x48,0x58,0x47,0xbd,0x67,0x95,0x50,0xce,0xe5,0x0f,0x4b,0x99,0xd1,0x0c,0x6c,0xa1,0x33,0x04,0xb7,0x79,0xd8,
+ 0x68,0x9c,0xf9,0x02,0x44,0x1a,0x2d,0x23,0xb4,0xc1,0x3e,0xd1,0xfc,0xfb,0x8e))
+
+M_14_60 = (
+ (0xb3,0xf4,0x1b,0x06,0x78,0x68,0xf9,0xe5,0xe9,0x1f,0xc1,0xce,0x37,0x6f,0x39,0xbd,0x28,0xc4,0xd3,0x49,0xd6,
+ 0x9f,0x34,0x0b,0x67,0xb7,0x6d,0x3c,0xb6,0x8c,0xcc,0xa2,0xfd,0x37,0x17,0xd9,0x85,0x02,0x1e,0x86,0x7d,0xc0,
+ 0xcc,0x64,0x92,0xc2,0x66,0x9a,0x36,0x77,0xb1,0xa8,0xa5,0xb9,0x47,0x22,0x75,0xde,0x09,0xe9,0x63,0xd6,0xf5,
+ 0x1b,0xd0,0xfd,0xfb,0x8f,0x3a,0xcd,0x4c,0xac,0xaa,0xe6,0xda,0x43,0xf5,0x2d,0xd3,0x1e,0xd8,0x78,0x21,0x8d,
+ 0x00,0xdf,0x88,0xd5,0x7b,0xaf,0xb3,0xd6,0x1c,0x80,0x5f,0x7c,0x37,0x9d,0xd7,0xea,0x4c,0x4f,0x8b,0xa1,0xc8,0x01),
+ (0x66,0xe9,0x37,0x0c,0xf0,0xd0,0xf2,0xcb,0xd3,0x3f,0x82,0x9d,0x6f,0xde,0x72,0x7a,0x51,0x88,0xa7,0x93,0xac,
+ 0x3f,0x69,0x16,0xce,0x6e,0xdb,0x78,0x6c,0x19,0x99,0x45,0xfb,0x6f,0x2e,0xb2,0x0b,0x05,0x3c,0x0c,0xfb,0x80,
+ 0x99,0xc9,0x24,0x85,0xcd,0x34,0x6d,0xee,0x62,0x51,0x4b,0x73,0x8f,0x44,0xea,0xbc,0x13,0xd2,0xc7,0xac,0xeb,
+ 0x37,0xa0,0xfb,0xf7,0x1f,0x75,0x9a,0x99,0x58,0x55,0xcd,0xb5,0x87,0xea,0x5b,0xa6,0x3d,0xb0,0xf1,0x42,0x1a,
+ 0x01,0xbe,0x11,0xab,0xf7,0x5e,0x67,0xad,0x39,0x00,0xbf,0xf8,0x6e,0x3a,0xaf,0xd5,0x99,0x9e,0x16,0x43,0x91,0x03),
+ (0xcc,0xd2,0x6f,0x18,0xe0,0xa1,0xe5,0x97,0xa7,0x7f,0x04,0x3b,0xdf,0xbc,0xe5,0xf4,0xa2,0x10,0x4f,0x27,0x59,
+ 0x7f,0xd2,0x2c,0x9c,0xdd,0xb6,0xf1,0xd8,0x32,0x32,0x8b,0xf6,0xdf,0x5c,0x64,0x17,0x0a,0x78,0x18,0xf6,0x01,
+ 0x33,0x93,0x49,0x0a,0x9b,0x69,0xda,0xdc,0xc5,0xa2,0x96,0xe6,0x1e,0x89,0xd4,0x79,0x27,0xa4,0x8f,0x59,0xd7,
+ 0x6f,0x40,0xf7,0xef,0x3f,0xea,0x34,0x33,0xb1,0xaa,0x9a,0x6b,0x0f,0xd5,0xb7,0x4c,0x7b,0x60,0xe3,0x85,0x34,
+ 0x02,0x7c,0x23,0x56,0xef,0xbd,0xce,0x5a,0x73,0x00,0x7e,0xf1,0xdd,0x74,0x5e,0xab,0x33,0x3d,0x2d,0x86,0x22,0x07),
+ (0x98,0xa5,0xdf,0x30,0xc0,0x43,0xcb,0x2f,0x4f,0xff,0x08,0x76,0xbe,0x79,0xcb,0xe9,0x45,0x21,0x9e,0x4e,0xb2,
+ 0xfe,0xa4,0x59,0x38,0xbb,0x6d,0xe3,0xb1,0x65,0x64,0x16,0xed,0xbf,0xb9,0xc8,0x2e,0x14,0xf0,0x30,0xec,0x03,
+ 0x66,0x26,0x93,0x14,0x36,0xd3,0xb4,0xb9,0x8b,0x45,0x2d,0xcd,0x3d,0x12,0xa9,0xf3,0x4e,0x48,0x1f,0xb3,0xae,
+ 0xdf,0x80,0xee,0xdf,0x7f,0xd4,0x69,0x66,0x62,0x55,0x35,0xd7,0x1e,0xaa,0x6f,0x99,0xf6,0xc0,0xc6,0x0b,0x69,
+ 0x04,0xf8,0x46,0xac,0xde,0x7b,0x9d,0xb5,0xe6,0x00,0xfc,0xe2,0xbb,0xe9,0xbc,0x56,0x67,0x7a,0x5a,0x0c,0x45,0x0e),
+ (0x30,0x4b,0xbf,0x61,0x80,0x87,0x96,0x5f,0x9e,0xfe,0x11,0xec,0x7c,0xf3,0x96,0xd3,0x8b,0x42,0x3c,0x9d,0x64,
+ 0xfd,0x49,0xb3,0x70,0x76,0xdb,0xc6,0x63,0xcb,0xc8,0x2c,0xda,0x7f,0x73,0x91,0x5d,0x28,0xe0,0x61,0xd8,0x07,
+ 0xcc,0x4c,0x26,0x29,0x6c,0xa6,0x69,0x73,0x17,0x8b,0x5a,0x9a,0x7b,0x24,0x52,0xe7,0x9d,0x90,0x3e,0x66,0x5d,
+ 0xbf,0x01,0xdd,0xbf,0xff,0xa8,0xd3,0xcc,0xc4,0xaa,0x6a,0xae,0x3d,0x54,0xdf,0x32,0xed,0x81,0x8d,0x17,0xd2,
+ 0x08,0xf0,0x8d,0x58,0xbd,0xf7,0x3a,0x6b,0xcd,0x01,0xf8,0xc5,0x77,0xd3,0x79,0xad,0xce,0xf4,0xb4,0x18,0x8a,0x1c),
+ (0x60,0x96,0x7e,0xc3,0x00,0x0f,0x2d,0xbf,0x3c,0xfd,0x23,0xd8,0xf9,0xe6,0x2d,0xa7,0x17,0x85,0x78,0x3a,0xc9,
+ 0xfa,0x93,0x66,0xe1,0xec,0xb6,0x8d,0xc7,0x96,0x91,0x59,0xb4,0xff,0xe6,0x22,0xbb,0x50,0xc0,0xc3,0xb0,0x0f,
+ 0x98,0x99,0x4c,0x52,0xd8,0x4c,0xd3,0xe6,0x2e,0x16,0xb5,0x34,0xf7,0x48,0xa4,0xce,0x3b,0x21,0x7d,0xcc,0xba,
+ 0x7e,0x03,0xba,0x7f,0xff,0x51,0xa7,0x99,0x89,0x55,0xd5,0x5c,0x7b,0xa8,0xbe,0x65,0xda,0x03,0x1b,0x2f,0xa4,
+ 0x11,0xe0,0x1b,0xb1,0x7a,0xef,0x75,0xd6,0x9a,0x03,0xf0,0x8b,0xef,0xa6,0xf3,0x5a,0x9d,0xe9,0x69,0x31,0x14,0x39),
+ (0xc0,0x2c,0xfd,0x86,0x01,0x1e,0x5a,0x7e,0x79,0xfa,0x47,0xb0,0xf3,0xcd,0x5b,0x4e,0x2f,0x0a,0xf1,0x74,0x92,
+ 0xf5,0x27,0xcd,0xc2,0xd9,0x6d,0x1b,0x8f,0x2d,0x23,0xb3,0x68,0xff,0xcd,0x45,0x76,0xa1,0x80,0x87,0x61,0x1f,
+ 0x30,0x33,0x99,0xa4,0xb0,0x99,0xa6,0xcd,0x5d,0x2c,0x6a,0x69,0xee,0x91,0x48,0x9d,0x77,0x42,0xfa,0x98,0x75,
+ 0xfd,0x06,0x74,0xff,0xfe,0xa3,0x4e,0x33,0x13,0xab,0xaa,0xb9,0xf6,0x50,0x7d,0xcb,0xb4,0x07,0x36,0x5e,0x48,
+ 0x23,0xc0,0x37,0x62,0xf5,0xde,0xeb,0xac,0x35,0x07,0xe0,0x17,0xdf,0x4d,0xe7,0xb5,0x3a,0xd3,0xd3,0x62,0x28,0x72),
+ (0x80,0x59,0xfa,0x0d,0x03,0x3c,0xb4,0xfc,0xf2,0xf4,0x8f,0x60,0xe7,0x9b,0xb7,0x9c,0x5e,0x14,0xe2,0xe9,0x24,
+ 0xeb,0x4f,0x9a,0x85,0xb3,0xdb,0x36,0x1e,0x5b,0x46,0x66,0xd1,0xfe,0x9b,0x8b,0xec,0x42,0x01,0x0f,0xc3,0x3e,
+ 0x60,0x66,0x32,0x49,0x61,0x33,0x4d,0x9b,0xbb,0x58,0xd4,0xd2,0xdc,0x23,0x91,0x3a,0xef,0x84,0xf4,0x31,0xeb,
+ 0xfa,0x0d,0xe8,0xfe,0xfd,0x47,0x9d,0x66,0x26,0x56,0x55,0x73,0xed,0xa1,0xfa,0x96,0x69,0x0f,0x6c,0xbc,0x90,
+ 0x46,0x80,0x6f,0xc4,0xea,0xbd,0xd7,0x59,0x6b,0x0e,0xc0,0x2f,0xbe,0x9b,0xce,0x6b,0x75,0xa6,0xa7,0xc5,0x50,0xe4))
+
+M_14_68 = (
+ (0x69,0xca,0x0b,0xcf,0x38,0x48,0x00,0xd2,0xb9,0x9f,0x98,0x8a,0xe6,0x14,0xb2,0x89,0x11,0x91,0xa9,0xb8,0x25,
+ 0x5e,0xfa,0xc6,0x5b,0x19,0x78,0xe6,0x47,0x46,0x13,0x3e,0xb8,0x62,0x2f,0xaa,0xcf,0x9c,0x80,0x2a,0xe2,0x8c,
+ 0x9a,0x48,0x0a,0xa7,0x09,0xf6,0x7a,0x9f,0x91,0x1e,0xbf,0xa1,0x2f,0xa7,0x4e,0xaf,0x9f,0x83,0xc3,0xbe,0x7c,
+ 0x1e,0x71,0x64,0xf0,0x68,0x20,0x66,0x35,0xb6,0xf7,0x82,0x44,0xde,0xf5,0xc3,0x50,0xfe,0xc7,0x51,0xf1,0x06,
+ 0xd9,0xad,0xfc,0xd3,0x2c,0x3a,0x57,0x0a,0xf3,0x0d,0xe5,0x2a,0x88,0xbf,0x5c,0xa6,0xa9,0x53,0xeb,0xa7,0x94,
+ 0xf2,0x81,0x2a,0xbb,0xaa,0x43,0x4e,0x47,0x40,0xe1,0x5d,0x0f,0x1a,0x02,0x00),
+ (0xd2,0x94,0x17,0x9e,0x71,0x90,0x00,0xa4,0x73,0x3f,0x31,0x15,0xcd,0x29,0x64,0x13,0x23,0x22,0x53,0x71,0x4b,
+ 0xbc,0xf4,0x8d,0xb7,0x32,0xf0,0xcc,0x8f,0x8c,0x26,0x7c,0x70,0xc5,0x5e,0x54,0x9f,0x39,0x01,0x55,0xc4,0x19,
+ 0x35,0x91,0x14,0x4e,0x13,0xec,0xf5,0x3e,0x23,0x3d,0x7e,0x43,0x5f,0x4e,0x9d,0x5e,0x3f,0x07,0x87,0x7d,0xf9,
+ 0x3c,0xe2,0xc8,0xe0,0xd1,0x40,0xcc,0x6a,0x6c,0xef,0x05,0x89,0xbc,0xeb,0x87,0xa1,0xfc,0x8f,0xa3,0xe2,0x0d,
+ 0xb2,0x5b,0xf9,0xa7,0x59,0x74,0xae,0x14,0xe6,0x1b,0xca,0x55,0x10,0x7f,0xb9,0x4c,0x53,0xa7,0xd6,0x4f,0x29,
+ 0xe5,0x03,0x55,0x76,0x55,0x87,0x9c,0x8e,0x80,0xc2,0xbb,0x1e,0x34,0x04,0x00),
+ (0xa4,0x29,0x2f,0x3c,0xe3,0x20,0x01,0x48,0xe7,0x7e,0x62,0x2a,0x9a,0x53,0xc8,0x26,0x46,0x44,0xa6,0xe2,0x96,
+ 0x78,0xe9,0x1b,0x6f,0x65,0xe0,0x99,0x1f,0x19,0x4d,0xf8,0xe0,0x8a,0xbd,0xa8,0x3e,0x73,0x02,0xaa,0x88,0x33,
+ 0x6a,0x22,0x29,0x9c,0x26,0xd8,0xeb,0x7d,0x46,0x7a,0xfc,0x86,0xbe,0x9c,0x3a,0xbd,0x7e,0x0e,0x0e,0xfb,0xf2,
+ 0x79,0xc4,0x91,0xc1,0xa3,0x81,0x98,0xd5,0xd8,0xde,0x0b,0x12,0x79,0xd7,0x0f,0x43,0xf9,0x1f,0x47,0xc5,0x1b,
+ 0x64,0xb7,0xf2,0x4f,0xb3,0xe8,0x5c,0x29,0xcc,0x37,0x94,0xab,0x20,0xfe,0x72,0x99,0xa6,0x4e,0xad,0x9f,0x52,
+ 0xca,0x07,0xaa,0xec,0xaa,0x0e,0x39,0x1d,0x01,0x85,0x77,0x3d,0x68,0x08,0x00),
+ (0x48,0x53,0x5e,0x78,0xc6,0x41,0x02,0x90,0xce,0xfd,0xc4,0x54,0x34,0xa7,0x90,0x4d,0x8c,0x88,0x4c,0xc5,0x2d,
+ 0xf1,0xd2,0x37,0xde,0xca,0xc0,0x33,0x3f,0x32,0x9a,0xf0,0xc1,0x15,0x7b,0x51,0x7d,0xe6,0x04,0x54,0x11,0x67,
+ 0xd4,0x44,0x52,0x38,0x4d,0xb0,0xd7,0xfb,0x8c,0xf4,0xf8,0x0d,0x7d,0x39,0x75,0x7a,0xfd,0x1c,0x1c,0xf6,0xe5,
+ 0xf3,0x88,0x23,0x83,0x47,0x03,0x31,0xab,0xb1,0xbd,0x17,0x24,0xf2,0xae,0x1f,0x86,0xf2,0x3f,0x8e,0x8a,0x37,
+ 0xc8,0x6e,0xe5,0x9f,0x66,0xd1,0xb9,0x52,0x98,0x6f,0x28,0x57,0x41,0xfc,0xe5,0x32,0x4d,0x9d,0x5a,0x3f,0xa5,
+ 0x94,0x0f,0x54,0xd9,0x55,0x1d,0x72,0x3a,0x02,0x0a,0xef,0x7a,0xd0,0x10,0x00),
+ (0x90,0xa6,0xbc,0xf0,0x8c,0x83,0x04,0x20,0x9d,0xfb,0x89,0xa9,0x68,0x4e,0x21,0x9b,0x18,0x11,0x99,0x8a,0x5b,
+ 0xe2,0xa5,0x6f,0xbc,0x95,0x81,0x67,0x7e,0x64,0x34,0xe1,0x83,0x2b,0xf6,0xa2,0xfa,0xcc,0x09,0xa8,0x22,0xce,
+ 0xa8,0x89,0xa4,0x70,0x9a,0x60,0xaf,0xf7,0x19,0xe9,0xf1,0x1b,0xfa,0x72,0xea,0xf4,0xfa,0x39,0x38,0xec,0xcb,
+ 0xe7,0x11,0x47,0x06,0x8f,0x06,0x62,0x56,0x63,0x7b,0x2f,0x48,0xe4,0x5d,0x3f,0x0c,0xe5,0x7f,0x1c,0x15,0x6f,
+ 0x90,0xdd,0xca,0x3f,0xcd,0xa2,0x73,0xa5,0x30,0xdf,0x50,0xae,0x82,0xf8,0xcb,0x65,0x9a,0x3a,0xb5,0x7e,0x4a,
+ 0x29,0x1f,0xa8,0xb2,0xab,0x3a,0xe4,0x74,0x04,0x14,0xde,0xf5,0xa0,0x21,0x00),
+ (0x20,0x4d,0x79,0xe1,0x19,0x07,0x09,0x40,0x3a,0xf7,0x13,0x53,0xd1,0x9c,0x42,0x36,0x31,0x22,0x32,0x15,0xb7,
+ 0xc4,0x4b,0xdf,0x78,0x2b,0x03,0xcf,0xfc,0xc8,0x68,0xc2,0x07,0x57,0xec,0x45,0xf5,0x99,0x13,0x50,0x45,0x9c,
+ 0x51,0x13,0x49,0xe1,0x34,0xc1,0x5e,0xef,0x33,0xd2,0xe3,0x37,0xf4,0xe5,0xd4,0xe9,0xf5,0x73,0x70,0xd8,0x97,
+ 0xcf,0x23,0x8e,0x0c,0x1e,0x0d,0xc4,0xac,0xc6,0xf6,0x5e,0x90,0xc8,0xbb,0x7e,0x18,0xca,0xff,0x38,0x2a,0xde,
+ 0x20,0xbb,0x95,0x7f,0x9a,0x45,0xe7,0x4a,0x61,0xbe,0xa1,0x5c,0x05,0xf1,0x97,0xcb,0x34,0x75,0x6a,0xfd,0x94,
+ 0x52,0x3e,0x50,0x65,0x57,0x75,0xc8,0xe9,0x08,0x28,0xbc,0xeb,0x41,0x43,0x00),
+ (0x40,0x9a,0xf2,0xc2,0x33,0x0e,0x12,0x80,0x74,0xee,0x27,0xa6,0xa2,0x39,0x85,0x6c,0x62,0x44,0x64,0x2a,0x6e,
+ 0x89,0x97,0xbe,0xf1,0x56,0x06,0x9e,0xf9,0x91,0xd1,0x84,0x0f,0xae,0xd8,0x8b,0xea,0x33,0x27,0xa0,0x8a,0x38,
+ 0xa3,0x26,0x92,0xc2,0x69,0x82,0xbd,0xde,0x67,0xa4,0xc7,0x6f,0xe8,0xcb,0xa9,0xd3,0xeb,0xe7,0xe0,0xb0,0x2f,
+ 0x9f,0x47,0x1c,0x19,0x3c,0x1a,0x88,0x59,0x8d,0xed,0xbd,0x20,0x91,0x77,0xfd,0x30,0x94,0xff,0x71,0x54,0xbc,
+ 0x41,0x76,0x2b,0xff,0x34,0x8b,0xce,0x95,0xc2,0x7c,0x43,0xb9,0x0a,0xe2,0x2f,0x97,0x69,0xea,0xd4,0xfa,0x29,
+ 0xa5,0x7c,0xa0,0xca,0xae,0xea,0x90,0xd3,0x11,0x50,0x78,0xd7,0x83,0x86,0x00),
+ (0x80,0x34,0xe5,0x85,0x67,0x1c,0x24,0x00,0xe9,0xdc,0x4f,0x4c,0x45,0x73,0x0a,0xd9,0xc4,0x88,0xc8,0x54,0xdc,
+ 0x12,0x2f,0x7d,0xe3,0xad,0x0c,0x3c,0xf3,0x23,0xa3,0x09,0x1f,0x5c,0xb1,0x17,0xd5,0x67,0x4e,0x40,0x15,0x71,
+ 0x46,0x4d,0x24,0x85,0xd3,0x04,0x7b,0xbd,0xcf,0x48,0x8f,0xdf,0xd0,0x97,0x53,0xa7,0xd7,0xcf,0xc1,0x61,0x5f,
+ 0x3e,0x8f,0x38,0x32,0x78,0x34,0x10,0xb3,0x1a,0xdb,0x7b,0x41,0x22,0xef,0xfa,0x61,0x28,0xff,0xe3,0xa8,0x78,
+ 0x83,0xec,0x56,0xfe,0x69,0x16,0x9d,0x2b,0x85,0xf9,0x86,0x72,0x15,0xc4,0x5f,0x2e,0xd3,0xd4,0xa9,0xf5,0x53,
+ 0x4a,0xf9,0x40,0x95,0x5d,0xd5,0x21,0xa7,0x23,0xa0,0xf0,0xae,0x07,0x0d,0x01))
+
+M_14_72 = (
+ (0x2d,0xdb,0xaa,0xfd,0x80,0xd2,0xff,0x17,0x22,0xad,0xb3,0x0d,0xbe,0x69,0x1c,0xe6,0xbc,0x6e,0x4a,0x07,0x64,
+ 0x01,0xd4,0x0a,0x01,0x7f,0xfc,0x49,0x87,0xdc,0xed,0x3d,0xe7,0x4f,0x48,0x0a,0xef,0x1e,0xbf,0xfd,0x6b,0x2b,
+ 0x6c,0x66,0x8c,0x5f,0xd1,0xe9,0x09,0xb3,0x75,0x13,0x80,0x24,0xd6,0xc9,0xcb,0xe7,0x91,0xad,0xc2,0x88,0xbe,
+ 0x84,0x25,0x42,0x40,0xd6,0xdc,0x89,0x0f,0xa5,0xeb,0x8b,0x84,0x34,0xd6,0x47,0xc7,0x0c,0xc9,0xe4,0xbb,0xfa,
+ 0x00,0xde,0x97,0x72,0x6f,0xf3,0xec,0x8e,0x26,0xf5,0x3a,0x44,0x21,0xea,0xb3,0xb0,0x40,0xab,0x2c,0xfc,0xd7,
+ 0x45,0x88,0x90,0x6d,0x4d,0x74,0x2a,0x8a,0xc2,0xbb,0x1d,0x98,0x70,0xcf,0x43,0x63,0x18,0x02,0x6f,0x5c,0x02,0x00),
+ (0x5a,0xb6,0x55,0xfb,0x01,0xa5,0xff,0x2f,0x44,0x5a,0x67,0x1b,0x7c,0xd3,0x38,0xcc,0x79,0xdd,0x94,0x0e,0xc8,
+ 0x02,0xa8,0x15,0x02,0xfe,0xf8,0x93,0x0e,0xb9,0xdb,0x7b,0xce,0x9f,0x90,0x14,0xde,0x3d,0x7e,0xfb,0xd7,0x56,
+ 0xd8,0xcc,0x18,0xbf,0xa2,0xd3,0x13,0x66,0xeb,0x26,0x00,0x49,0xac,0x93,0x97,0xcf,0x23,0x5b,0x85,0x11,0x7d,
+ 0x09,0x4b,0x84,0x80,0xac,0xb9,0x13,0x1f,0x4a,0xd7,0x17,0x09,0x69,0xac,0x8f,0x8e,0x19,0x92,0xc9,0x77,0xf5,
+ 0x01,0xbc,0x2f,0xe5,0xde,0xe6,0xd9,0x1d,0x4d,0xea,0x75,0x88,0x42,0xd4,0x67,0x61,0x81,0x56,0x59,0xf8,0xaf,
+ 0x8b,0x10,0x21,0xdb,0x9a,0xe8,0x54,0x14,0x85,0x77,0x3b,0x30,0xe1,0x9e,0x87,0xc6,0x30,0x04,0xde,0xb8,0x04,0x00),
+ (0xb4,0x6c,0xab,0xf6,0x03,0x4a,0xff,0x5f,0x88,0xb4,0xce,0x36,0xf8,0xa6,0x71,0x98,0xf3,0xba,0x29,0x1d,0x90,
+ 0x05,0x50,0x2b,0x04,0xfc,0xf1,0x27,0x1d,0x72,0xb7,0xf7,0x9c,0x3f,0x21,0x29,0xbc,0x7b,0xfc,0xf6,0xaf,0xad,
+ 0xb0,0x99,0x31,0x7e,0x45,0xa7,0x27,0xcc,0xd6,0x4d,0x00,0x92,0x58,0x27,0x2f,0x9f,0x47,0xb6,0x0a,0x23,0xfa,
+ 0x12,0x96,0x08,0x01,0x59,0x73,0x27,0x3e,0x94,0xae,0x2f,0x12,0xd2,0x58,0x1f,0x1d,0x33,0x24,0x93,0xef,0xea,
+ 0x03,0x78,0x5f,0xca,0xbd,0xcd,0xb3,0x3b,0x9a,0xd4,0xeb,0x10,0x85,0xa8,0xcf,0xc2,0x02,0xad,0xb2,0xf0,0x5f,
+ 0x17,0x21,0x42,0xb6,0x35,0xd1,0xa9,0x28,0x0a,0xef,0x76,0x60,0xc2,0x3d,0x0f,0x8d,0x61,0x08,0xbc,0x71,0x09,0x00),
+ (0x68,0xd9,0x56,0xed,0x07,0x94,0xfe,0xbf,0x10,0x69,0x9d,0x6d,0xf0,0x4d,0xe3,0x30,0xe7,0x75,0x53,0x3a,0x20,
+ 0x0b,0xa0,0x56,0x08,0xf8,0xe3,0x4f,0x3a,0xe4,0x6e,0xef,0x39,0x7f,0x42,0x52,0x78,0xf7,0xf8,0xed,0x5f,0x5b,
+ 0x61,0x33,0x63,0xfc,0x8a,0x4e,0x4f,0x98,0xad,0x9b,0x00,0x24,0xb1,0x4e,0x5e,0x3e,0x8f,0x6c,0x15,0x46,0xf4,
+ 0x25,0x2c,0x11,0x02,0xb2,0xe6,0x4e,0x7c,0x28,0x5d,0x5f,0x24,0xa4,0xb1,0x3e,0x3a,0x66,0x48,0x26,0xdf,0xd5,
+ 0x07,0xf0,0xbe,0x94,0x7b,0x9b,0x67,0x77,0x34,0xa9,0xd7,0x21,0x0a,0x51,0x9f,0x85,0x05,0x5a,0x65,0xe1,0xbf,
+ 0x2e,0x42,0x84,0x6c,0x6b,0xa2,0x53,0x51,0x14,0xde,0xed,0xc0,0x84,0x7b,0x1e,0x1a,0xc3,0x10,0x78,0xe3,0x12,0x00),
+ (0xd0,0xb2,0xad,0xda,0x0f,0x28,0xfd,0x7f,0x21,0xd2,0x3a,0xdb,0xe0,0x9b,0xc6,0x61,0xce,0xeb,0xa6,0x74,0x40,
+ 0x16,0x40,0xad,0x10,0xf0,0xc7,0x9f,0x74,0xc8,0xdd,0xde,0x73,0xfe,0x84,0xa4,0xf0,0xee,0xf1,0xdb,0xbf,0xb6,
+ 0xc2,0x66,0xc6,0xf8,0x15,0x9d,0x9e,0x30,0x5b,0x37,0x01,0x48,0x62,0x9d,0xbc,0x7c,0x1e,0xd9,0x2a,0x8c,0xe8,
+ 0x4b,0x58,0x22,0x04,0x64,0xcd,0x9d,0xf8,0x50,0xba,0xbe,0x48,0x48,0x63,0x7d,0x74,0xcc,0x90,0x4c,0xbe,0xab,
+ 0x0f,0xe0,0x7d,0x29,0xf7,0x36,0xcf,0xee,0x68,0x52,0xaf,0x43,0x14,0xa2,0x3e,0x0b,0x0b,0xb4,0xca,0xc2,0x7f,
+ 0x5d,0x84,0x08,0xd9,0xd6,0x44,0xa7,0xa2,0x28,0xbc,0xdb,0x81,0x09,0xf7,0x3c,0x34,0x86,0x21,0xf0,0xc6,0x25,0x00),
+ (0xa0,0x65,0x5b,0xb5,0x1f,0x50,0xfa,0xff,0x42,0xa4,0x75,0xb6,0xc1,0x37,0x8d,0xc3,0x9c,0xd7,0x4d,0xe9,0x80,
+ 0x2c,0x80,0x5a,0x21,0xe0,0x8f,0x3f,0xe9,0x90,0xbb,0xbd,0xe7,0xfc,0x09,0x49,0xe1,0xdd,0xe3,0xb7,0x7f,0x6d,
+ 0x85,0xcd,0x8c,0xf1,0x2b,0x3a,0x3d,0x61,0xb6,0x6e,0x02,0x90,0xc4,0x3a,0x79,0xf9,0x3c,0xb2,0x55,0x18,0xd1,
+ 0x97,0xb0,0x44,0x08,0xc8,0x9a,0x3b,0xf1,0xa1,0x74,0x7d,0x91,0x90,0xc6,0xfa,0xe8,0x98,0x21,0x99,0x7c,0x57,
+ 0x1f,0xc0,0xfb,0x52,0xee,0x6d,0x9e,0xdd,0xd1,0xa4,0x5e,0x87,0x28,0x44,0x7d,0x16,0x16,0x68,0x95,0x85,0xff,
+ 0xba,0x08,0x11,0xb2,0xad,0x89,0x4e,0x45,0x51,0x78,0xb7,0x03,0x13,0xee,0x79,0x68,0x0c,0x43,0xe0,0x8d,0x4b,0x00),
+ (0x40,0xcb,0xb6,0x6a,0x3f,0xa0,0xf4,0xff,0x85,0x48,0xeb,0x6c,0x83,0x6f,0x1a,0x87,0x39,0xaf,0x9b,0xd2,0x01,
+ 0x59,0x00,0xb5,0x42,0xc0,0x1f,0x7f,0xd2,0x21,0x77,0x7b,0xcf,0xf9,0x13,0x92,0xc2,0xbb,0xc7,0x6f,0xff,0xda,
+ 0x0a,0x9b,0x19,0xe3,0x57,0x74,0x7a,0xc2,0x6c,0xdd,0x04,0x20,0x89,0x75,0xf2,0xf2,0x79,0x64,0xab,0x30,0xa2,
+ 0x2f,0x61,0x89,0x10,0x90,0x35,0x77,0xe2,0x43,0xe9,0xfa,0x22,0x21,0x8d,0xf5,0xd1,0x31,0x43,0x32,0xf9,0xae,
+ 0x3e,0x80,0xf7,0xa5,0xdc,0xdb,0x3c,0xbb,0xa3,0x49,0xbd,0x0e,0x51,0x88,0xfa,0x2c,0x2c,0xd0,0x2a,0x0b,0xff,
+ 0x75,0x11,0x22,0x64,0x5b,0x13,0x9d,0x8a,0xa2,0xf0,0x6e,0x07,0x26,0xdc,0xf3,0xd0,0x18,0x86,0xc0,0x1b,0x97,0x00),
+ (0x80,0x96,0x6d,0xd5,0x7e,0x40,0xe9,0xff,0x0b,0x91,0xd6,0xd9,0x06,0xdf,0x34,0x0e,0x73,0x5e,0x37,0xa5,0x03,
+ 0xb2,0x00,0x6a,0x85,0x80,0x3f,0xfe,0xa4,0x43,0xee,0xf6,0x9e,0xf3,0x27,0x24,0x85,0x77,0x8f,0xdf,0xfe,0xb5,
+ 0x15,0x36,0x33,0xc6,0xaf,0xe8,0xf4,0x84,0xd9,0xba,0x09,0x40,0x12,0xeb,0xe4,0xe5,0xf3,0xc8,0x56,0x61,0x44,
+ 0x5f,0xc2,0x12,0x21,0x20,0x6b,0xee,0xc4,0x87,0xd2,0xf5,0x45,0x42,0x1a,0xeb,0xa3,0x63,0x86,0x64,0xf2,0x5d,
+ 0x7d,0x00,0xef,0x4b,0xb9,0xb7,0x79,0x76,0x47,0x93,0x7a,0x1d,0xa2,0x10,0xf5,0x59,0x58,0xa0,0x55,0x16,0xfe,
+ 0xeb,0x22,0x44,0xc8,0xb6,0x26,0x3a,0x15,0x45,0xe1,0xdd,0x0e,0x4c,0xb8,0xe7,0xa1,0x31,0x0c,0x81,0x37,0x2e,0x01))
+
+M_14_80 = (
+ (0x15,0x5e,0x86,0xe5,0xe1,0xb8,0x22,0x20,0x32,0xf5,0xca,0x86,0x4b,0x13,0xa3,0x49,0x5c,0x5a,0x83,0x37,0xfa,
+ 0x23,0x9e,0xd3,0x30,0x7b,0xae,0xfa,0x43,0x2c,0xfa,0x61,0xf0,0x67,0x71,0xb4,0x6f,0x54,0x73,0x8d,0x2a,0x77,
+ 0x78,0x38,0x7e,0x3c,0xe9,0x0b,0x79,0xd7,0x48,0xbf,0x4c,0xd8,0x21,0x77,0x26,0x23,0x51,0x23,0x85,0x89,0x97,
+ 0xa9,0xd2,0xe2,0xe1,0x0a,0x9c,0x3e,0xc7,0x51,0xa9,0x6d,0x73,0x88,0x69,0xb6,0xb3,0x1a,0xf1,0xa2,0x62,0xb7,
+ 0x4e,0x92,0xc0,0x21,0x31,0x93,0xbd,0xd6,0xe0,0x04,0x47,0x58,0xaf,0x70,0xc1,0x20,0x08,0xc3,0xd4,0x58,0x99,
+ 0x77,0x23,0xc5,0xd0,0x2e,0x1e,0x70,0xa7,0xbc,0xfb,0x25,0x3a,0x27,0x96,0x7b,0x44,0x44,0x1e,0xf5,0xb1,0x5e,
+ 0x2a,0x8e,0x30,0xe7,0x72,0x04,0x82,0xa4,0x73,0xf7,0xa0,0x9a,0xd7,0x02,0x00),
+ (0x2a,0xbc,0x0c,0xcb,0xc3,0x71,0x45,0x40,0x64,0xea,0x95,0x0d,0x97,0x26,0x46,0x93,0xb8,0xb4,0x06,0x6f,0xf4,
+ 0x47,0x3c,0xa7,0x61,0xf6,0x5c,0xf5,0x87,0x58,0xf4,0xc3,0xe0,0xcf,0xe2,0x68,0xdf,0xa8,0xe6,0x1a,0x55,0xee,
+ 0xf0,0x70,0xfc,0x78,0xd2,0x17,0xf2,0xae,0x91,0x7e,0x99,0xb0,0x43,0xee,0x4c,0x46,0xa2,0x46,0x0a,0x13,0x2f,
+ 0x53,0xa5,0xc5,0xc3,0x15,0x38,0x7d,0x8e,0xa3,0x52,0xdb,0xe6,0x10,0xd3,0x6c,0x67,0x35,0xe2,0x45,0xc5,0x6e,
+ 0x9d,0x24,0x81,0x43,0x62,0x26,0x7b,0xad,0xc1,0x09,0x8e,0xb0,0x5e,0xe1,0x82,0x41,0x10,0x86,0xa9,0xb1,0x32,
+ 0xef,0x46,0x8a,0xa1,0x5d,0x3c,0xe0,0x4e,0x79,0xf7,0x4b,0x74,0x4e,0x2c,0xf7,0x88,0x88,0x3c,0xea,0x63,0xbd,
+ 0x54,0x1c,0x61,0xce,0xe5,0x08,0x04,0x49,0xe7,0xee,0x41,0x35,0xaf,0x05,0x00),
+ (0x54,0x78,0x19,0x96,0x87,0xe3,0x8a,0x80,0xc8,0xd4,0x2b,0x1b,0x2e,0x4d,0x8c,0x26,0x71,0x69,0x0d,0xde,0xe8,
+ 0x8f,0x78,0x4e,0xc3,0xec,0xb9,0xea,0x0f,0xb1,0xe8,0x87,0xc1,0x9f,0xc5,0xd1,0xbe,0x51,0xcd,0x35,0xaa,0xdc,
+ 0xe1,0xe1,0xf8,0xf1,0xa4,0x2f,0xe4,0x5d,0x23,0xfd,0x32,0x61,0x87,0xdc,0x99,0x8c,0x44,0x8d,0x14,0x26,0x5e,
+ 0xa6,0x4a,0x8b,0x87,0x2b,0x70,0xfa,0x1c,0x47,0xa5,0xb6,0xcd,0x21,0xa6,0xd9,0xce,0x6a,0xc4,0x8b,0x8a,0xdd,
+ 0x3a,0x49,0x02,0x87,0xc4,0x4c,0xf6,0x5a,0x83,0x13,0x1c,0x61,0xbd,0xc2,0x05,0x83,0x20,0x0c,0x53,0x63,0x65,
+ 0xde,0x8d,0x14,0x43,0xbb,0x78,0xc0,0x9d,0xf2,0xee,0x97,0xe8,0x9c,0x58,0xee,0x11,0x11,0x79,0xd4,0xc7,0x7a,
+ 0xa9,0x38,0xc2,0x9c,0xcb,0x11,0x08,0x92,0xce,0xdd,0x83,0x6a,0x5e,0x0b,0x00),
+ (0xa8,0xf0,0x32,0x2c,0x0f,0xc7,0x15,0x01,0x91,0xa9,0x57,0x36,0x5c,0x9a,0x18,0x4d,0xe2,0xd2,0x1a,0xbc,0xd1,
+ 0x1f,0xf1,0x9c,0x86,0xd9,0x73,0xd5,0x1f,0x62,0xd1,0x0f,0x83,0x3f,0x8b,0xa3,0x7d,0xa3,0x9a,0x6b,0x54,0xb9,
+ 0xc3,0xc3,0xf1,0xe3,0x49,0x5f,0xc8,0xbb,0x46,0xfa,0x65,0xc2,0x0e,0xb9,0x33,0x19,0x89,0x1a,0x29,0x4c,0xbc,
+ 0x4c,0x95,0x16,0x0f,0x57,0xe0,0xf4,0x39,0x8e,0x4a,0x6d,0x9b,0x43,0x4c,0xb3,0x9d,0xd5,0x88,0x17,0x15,0xbb,
+ 0x75,0x92,0x04,0x0e,0x89,0x99,0xec,0xb5,0x06,0x27,0x38,0xc2,0x7a,0x85,0x0b,0x06,0x41,0x18,0xa6,0xc6,0xca,
+ 0xbc,0x1b,0x29,0x86,0x76,0xf1,0x80,0x3b,0xe5,0xdd,0x2f,0xd1,0x39,0xb1,0xdc,0x23,0x22,0xf2,0xa8,0x8f,0xf5,
+ 0x52,0x71,0x84,0x39,0x97,0x23,0x10,0x24,0x9d,0xbb,0x07,0xd5,0xbc,0x16,0x00),
+ (0x50,0xe1,0x65,0x58,0x1e,0x8e,0x2b,0x02,0x22,0x53,0xaf,0x6c,0xb8,0x34,0x31,0x9a,0xc4,0xa5,0x35,0x78,0xa3,
+ 0x3f,0xe2,0x39,0x0d,0xb3,0xe7,0xaa,0x3f,0xc4,0xa2,0x1f,0x06,0x7f,0x16,0x47,0xfb,0x46,0x35,0xd7,0xa8,0x72,
+ 0x87,0x87,0xe3,0xc7,0x93,0xbe,0x90,0x77,0x8d,0xf4,0xcb,0x84,0x1d,0x72,0x67,0x32,0x12,0x35,0x52,0x98,0x78,
+ 0x99,0x2a,0x2d,0x1e,0xae,0xc0,0xe9,0x73,0x1c,0x95,0xda,0x36,0x87,0x98,0x66,0x3b,0xab,0x11,0x2f,0x2a,0x76,
+ 0xeb,0x24,0x09,0x1c,0x12,0x33,0xd9,0x6b,0x0d,0x4e,0x70,0x84,0xf5,0x0a,0x17,0x0c,0x82,0x30,0x4c,0x8d,0x95,
+ 0x79,0x37,0x52,0x0c,0xed,0xe2,0x01,0x77,0xca,0xbb,0x5f,0xa2,0x73,0x62,0xb9,0x47,0x44,0xe4,0x51,0x1f,0xeb,
+ 0xa5,0xe2,0x08,0x73,0x2e,0x47,0x20,0x48,0x3a,0x77,0x0f,0xaa,0x79,0x2d,0x00),
+ (0xa0,0xc2,0xcb,0xb0,0x3c,0x1c,0x57,0x04,0x44,0xa6,0x5e,0xd9,0x70,0x69,0x62,0x34,0x89,0x4b,0x6b,0xf0,0x46,
+ 0x7f,0xc4,0x73,0x1a,0x66,0xcf,0x55,0x7f,0x88,0x45,0x3f,0x0c,0xfe,0x2c,0x8e,0xf6,0x8d,0x6a,0xae,0x51,0xe5,
+ 0x0e,0x0f,0xc7,0x8f,0x27,0x7d,0x21,0xef,0x1a,0xe9,0x97,0x09,0x3b,0xe4,0xce,0x64,0x24,0x6a,0xa4,0x30,0xf1,
+ 0x32,0x55,0x5a,0x3c,0x5c,0x81,0xd3,0xe7,0x38,0x2a,0xb5,0x6d,0x0e,0x31,0xcd,0x76,0x56,0x23,0x5e,0x54,0xec,
+ 0xd6,0x49,0x12,0x38,0x24,0x66,0xb2,0xd7,0x1a,0x9c,0xe0,0x08,0xeb,0x15,0x2e,0x18,0x04,0x61,0x98,0x1a,0x2b,
+ 0xf3,0x6e,0xa4,0x18,0xda,0xc5,0x03,0xee,0x94,0x77,0xbf,0x44,0xe7,0xc4,0x72,0x8f,0x88,0xc8,0xa3,0x3e,0xd6,
+ 0x4b,0xc5,0x11,0xe6,0x5c,0x8e,0x40,0x90,0x74,0xee,0x1e,0x54,0xf3,0x5a,0x00),
+ (0x40,0x85,0x97,0x61,0x79,0x38,0xae,0x08,0x88,0x4c,0xbd,0xb2,0xe1,0xd2,0xc4,0x68,0x12,0x97,0xd6,0xe0,0x8d,
+ 0xfe,0x88,0xe7,0x34,0xcc,0x9e,0xab,0xfe,0x10,0x8b,0x7e,0x18,0xfc,0x59,0x1c,0xed,0x1b,0xd5,0x5c,0xa3,0xca,
+ 0x1d,0x1e,0x8e,0x1f,0x4f,0xfa,0x42,0xde,0x35,0xd2,0x2f,0x13,0x76,0xc8,0x9d,0xc9,0x48,0xd4,0x48,0x61,0xe2,
+ 0x65,0xaa,0xb4,0x78,0xb8,0x02,0xa7,0xcf,0x71,0x54,0x6a,0xdb,0x1c,0x62,0x9a,0xed,0xac,0x46,0xbc,0xa8,0xd8,
+ 0xad,0x93,0x24,0x70,0x48,0xcc,0x64,0xaf,0x35,0x38,0xc1,0x11,0xd6,0x2b,0x5c,0x30,0x08,0xc2,0x30,0x35,0x56,
+ 0xe6,0xdd,0x48,0x31,0xb4,0x8b,0x07,0xdc,0x29,0xef,0x7e,0x89,0xce,0x89,0xe5,0x1e,0x11,0x91,0x47,0x7d,0xac,
+ 0x97,0x8a,0x23,0xcc,0xb9,0x1c,0x81,0x20,0xe9,0xdc,0x3d,0xa8,0xe6,0xb5,0x00),
+ (0x80,0x0a,0x2f,0xc3,0xf2,0x70,0x5c,0x11,0x10,0x99,0x7a,0x65,0xc3,0xa5,0x89,0xd1,0x24,0x2e,0xad,0xc1,0x1b,
+ 0xfd,0x11,0xcf,0x69,0x98,0x3d,0x57,0xfd,0x21,0x16,0xfd,0x30,0xf8,0xb3,0x38,0xda,0x37,0xaa,0xb9,0x46,0x95,
+ 0x3b,0x3c,0x1c,0x3f,0x9e,0xf4,0x85,0xbc,0x6b,0xa4,0x5f,0x26,0xec,0x90,0x3b,0x93,0x91,0xa8,0x91,0xc2,0xc4,
+ 0xcb,0x54,0x69,0xf1,0x70,0x05,0x4e,0x9f,0xe3,0xa8,0xd4,0xb6,0x39,0xc4,0x34,0xdb,0x59,0x8d,0x78,0x51,0xb1,
+ 0x5b,0x27,0x49,0xe0,0x90,0x98,0xc9,0x5e,0x6b,0x70,0x82,0x23,0xac,0x57,0xb8,0x60,0x10,0x84,0x61,0x6a,0xac,
+ 0xcc,0xbb,0x91,0x62,0x68,0x17,0x0f,0xb8,0x53,0xde,0xfd,0x12,0x9d,0x13,0xcb,0x3d,0x22,0x22,0x8f,0xfa,0x58,
+ 0x2f,0x15,0x47,0x98,0x73,0x39,0x02,0x41,0xd2,0xb9,0x7b,0x50,0xcd,0x6b,0x01))
+
+def bch_enc_14(data, enc_len, level):
+ """ bch ecc encode function, parity bits is 14.
+ data is the source buffer
+ enc_len is the encode length
+ level is the ecc level used """
+
+ #print "bch encode length is %d, " % enc_len,
+ #print "ecc level is %d " % level
+
+ # select proper matrix for the ecc level assigned #
+ parity_byte = int(math.ceil(float(level) * 14 / 8))
+ #temp = 'matrix = M_14_' + str(level)
+ #exec(temp)
+ if str(level) == "4":
+ matrix = M_14_4
+ elif str(level) == "6":
+ matrix = M_14_6
+ elif str(level) == "8":
+ matrix = M_14_8
+ elif str(level) == "10":
+ matrix = M_14_10
+ elif str(level) == "12":
+ matrix = M_14_12
+ elif str(level) == "14":
+ matrix = M_14_14
+ elif str(level) == "16":
+ matrix = M_14_16
+ elif str(level) == "18":
+ matrix = M_14_18
+ elif str(level) == "20":
+ matrix = M_14_20
+ elif str(level) == "22":
+ matrix = M_14_22
+ elif str(level) == "24":
+ matrix = M_14_24
+ elif str(level) == "28":
+ matrix = M_14_28
+ elif str(level) == "32":
+ matrix = M_14_32
+ elif str(level) == "36":
+ matrix = M_14_36
+ elif str(level) == "40":
+ matrix = M_14_40
+ elif str(level) == "44":
+ matrix = M_14_44
+ elif str(level) == "48":
+ matrix = M_14_48
+ elif str(level) == "52":
+ matrix = M_14_52
+ elif str(level) == "56":
+ matrix = M_14_56
+ elif str(level) == "60":
+ matrix = M_14_60
+ elif str(level) == "68":
+ matrix = M_14_68
+ elif str(level) == "72":
+ matrix = M_14_72
+ elif str(level) == "80":
+ matrix = M_14_80
+
+ # fetch raw data #
+ raw = data + (b'\0' * parity_byte)
+ raw = bytearray(raw)
+
+ for i in range(enc_len):
+ for j in range(8):
+ if (raw[i] & (1 << j)) != 0:
+ for k in range(parity_byte + 1):
+ raw[i + k] ^= matrix[j][k]
+
+ # feedback parity data generated #
+ #raw = raw.decode()#str(raw)
+ parity_data = raw[enc_len:]
+ return parity_data
+
+if __name__ == "__main__":
+ """ this is bch encode function. """
+ print("this is bch encode function.")
\ No newline at end of file
diff --git a/src/bsp/scatter/tools/nand-utils/ecc_bch_13.py b/src/bsp/scatter/tools/nand-utils/ecc_bch_13.py
new file mode 100755
index 0000000..ce7685f
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/ecc_bch_13.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+
+import math
+
+M_13_4 = ((0x45,0x89,0x41,0xb8,0x3a,0xac,0x1a,0x00),
+ (0x8a,0x12,0x83,0x70,0x75,0x58,0x35,0x00),
+ (0x14,0x25,0x06,0xe1,0xea,0xb0,0x6a,0x00),
+ (0x28,0x4a,0x0c,0xc2,0xd5,0x61,0xd5,0x00),
+ (0x50,0x94,0x18,0x84,0xab,0xc3,0xaa,0x01),
+ (0xa0,0x28,0x31,0x08,0x57,0x87,0x55,0x03),
+ (0x40,0x51,0x62,0x10,0xae,0x0e,0xab,0x06),
+ (0x80,0xa2,0xc4,0x20,0x5c,0x1d,0x56,0x0d))
+
+M_13_6 = ((0x7f,0x9e,0x49,0x86,0x93,0x87,0x9d,0xce,0x46,0x5f,0x00),
+ (0xfe,0x3c,0x93,0x0c,0x27,0x0f,0x3b,0x9d,0x8d,0xbe,0x00),
+ (0xfc,0x79,0x26,0x19,0x4e,0x1e,0x76,0x3a,0x1b,0x7d,0x01),
+ (0xf8,0xf3,0x4c,0x32,0x9c,0x3c,0xec,0x74,0x36,0xfa,0x02),
+ (0xf0,0xe7,0x99,0x64,0x38,0x79,0xd8,0xe9,0x6c,0xf4,0x05),
+ (0xe0,0xcf,0x33,0xc9,0x70,0xf2,0xb0,0xd3,0xd9,0xe8,0x0b),
+ (0xc0,0x9f,0x67,0x92,0xe1,0xe4,0x61,0xa7,0xb3,0xd1,0x17),
+ (0x80,0x3f,0xcf,0x24,0xc3,0xc9,0xc3,0x4e,0x67,0xa3,0x2f))
+
+M_13_8 = ((0x51,0x3f,0x51,0x0e,0xbc,0x61,0x90,0xc3,0x05,0x47,0x47,0xbe,0x89,0x01),
+ (0xa2,0x7e,0xa2,0x1c,0x78,0xc3,0x20,0x87,0x0b,0x8e,0x8e,0x7c,0x13,0x03),
+ (0x44,0xfd,0x44,0x39,0xf0,0x86,0x41,0x0e,0x17,0x1c,0x1d,0xf9,0x26,0x06),
+ (0x88,0xfa,0x89,0x72,0xe0,0x0d,0x83,0x1c,0x2e,0x38,0x3a,0xf2,0x4d,0x0c),
+ (0x10,0xf5,0x13,0xe5,0xc0,0x1b,0x06,0x39,0x5c,0x70,0x74,0xe4,0x9b,0x18),
+ (0x20,0xea,0x27,0xca,0x81,0x37,0x0c,0x72,0xb8,0xe0,0xe8,0xc8,0x37,0x31),
+ (0x40,0xd4,0x4f,0x94,0x03,0x6f,0x18,0xe4,0x70,0xc1,0xd1,0x91,0x6f,0x62),
+ (0x80,0xa8,0x9f,0x28,0x07,0xde,0x30,0xc8,0xe1,0x82,0xa3,0x23,0xdf,0xc4))
+
+M_13_10 = ((0xd3,0x92,0x7b,0x58,0x0a,0x9f,0x2c,0x92,0xdb,0x83,0x6a,0x40,0xf5,0x83,0x66,0x9f,0x04,0x00),
+ (0xa6,0x25,0xf7,0xb0,0x14,0x3e,0x59,0x24,0xb7,0x07,0xd5,0x80,0xea,0x07,0xcd,0x3e,0x09,0x00),
+ (0x4c,0x4b,0xee,0x61,0x29,0x7c,0xb2,0x48,0x6e,0x0f,0xaa,0x01,0xd5,0x0f,0x9a,0x7d,0x12,0x00),
+ (0x98,0x96,0xdc,0xc3,0x52,0xf8,0x64,0x91,0xdc,0x1e,0x54,0x03,0xaa,0x1f,0x34,0xfb,0x24,0x00),
+ (0x30,0x2d,0xb9,0x87,0xa5,0xf0,0xc9,0x22,0xb9,0x3d,0xa8,0x06,0x54,0x3f,0x68,0xf6,0x49,0x00),
+ (0x60,0x5a,0x72,0x0f,0x4b,0xe1,0x93,0x45,0x72,0x7b,0x50,0x0d,0xa8,0x7e,0xd0,0xec,0x93,0x00),
+ (0xc0,0xb4,0xe4,0x1e,0x96,0xc2,0x27,0x8b,0xe4,0xf6,0xa0,0x1a,0x50,0xfd,0xa0,0xd9,0x27,0x01),
+ (0x80,0x69,0xc9,0x3d,0x2c,0x85,0x4f,0x16,0xc9,0xed,0x41,0x35,0xa0,0xfa,0x41,0xb3,0x4f,0x02))
+
+M_13_12 = ((0x4f,0xc2,0x99,0xd4,0x10,0xb5,0xd4,0x3c,0xa4,0x2c,0x05,0x4a,0xc6,0xce,0xd6,0x0f,0x09,0xf4,0x40,0x11,0x00),
+ (0x9e,0x84,0x33,0xa9,0x21,0x6a,0xa9,0x79,0x48,0x59,0x0a,0x94,0x8c,0x9d,0xad,0x1f,0x12,0xe8,0x81,0x22,0x00),
+ (0x3c,0x09,0x67,0x52,0x43,0xd4,0x52,0xf3,0x90,0xb2,0x14,0x28,0x19,0x3b,0x5b,0x3f,0x24,0xd0,0x03,0x45,0x00),
+ (0x78,0x12,0xce,0xa4,0x86,0xa8,0xa5,0xe6,0x21,0x65,0x29,0x50,0x32,0x76,0xb6,0x7e,0x48,0xa0,0x07,0x8a,0x00),
+ (0xf0,0x24,0x9c,0x49,0x0d,0x51,0x4b,0xcd,0x43,0xca,0x52,0xa0,0x64,0xec,0x6c,0xfd,0x90,0x40,0x0f,0x14,0x01),
+ (0xe0,0x49,0x38,0x93,0x1a,0xa2,0x96,0x9a,0x87,0x94,0xa5,0x40,0xc9,0xd8,0xd9,0xfa,0x21,0x81,0x1e,0x28,0x02),
+ (0xc0,0x93,0x70,0x26,0x35,0x44,0x2d,0x35,0x0f,0x29,0x4b,0x81,0x92,0xb1,0xb3,0xf5,0x43,0x02,0x3d,0x50,0x04),
+ (0x80,0x27,0xe1,0x4c,0x6a,0x88,0x5a,0x6a,0x1e,0x52,0x96,0x02,0x25,0x63,0x67,0xeb,0x87,0x04,0x7a,0xa0,0x08))
+
+M_13_14 = ((0xeb,0xee,0x73,0xc9,0x34,0x8a,0xc0,0x32,0x03,0x65,0x1f,0x54,0x4b,0xad,0x2b,0xd4,0xe0,0x15,0x23,0xc2,0x08,0x65,0x4a,0x00),
+ (0xd6,0xdd,0xe7,0x92,0x69,0x14,0x81,0x65,0x06,0xca,0x3e,0xa8,0x96,0x5a,0x57,0xa8,0xc1,0x2b,0x46,0x84,0x11,0xca,0x94,0x00),
+ (0xac,0xbb,0xcf,0x25,0xd3,0x28,0x02,0xcb,0x0c,0x94,0x7d,0x50,0x2d,0xb5,0xae,0x50,0x83,0x57,0x8c,0x08,0x23,0x94,0x29,0x01),
+ (0x58,0x77,0x9f,0x4b,0xa6,0x51,0x04,0x96,0x19,0x28,0xfb,0xa0,0x5a,0x6a,0x5d,0xa1,0x06,0xaf,0x18,0x11,0x46,0x28,0x53,0x02),
+ (0xb0,0xee,0x3e,0x97,0x4c,0xa3,0x08,0x2c,0x33,0x50,0xf6,0x41,0xb5,0xd4,0xba,0x42,0x0d,0x5e,0x31,0x22,0x8c,0x50,0xa6,0x04),
+ (0x60,0xdd,0x7d,0x2e,0x99,0x46,0x11,0x58,0x66,0xa0,0xec,0x83,0x6a,0xa9,0x75,0x85,0x1a,0xbc,0x62,0x44,0x18,0xa1,0x4c,0x09),
+ (0xc0,0xba,0xfb,0x5c,0x32,0x8d,0x22,0xb0,0xcc,0x40,0xd9,0x07,0xd5,0x52,0xeb,0x0a,0x35,0x78,0xc5,0x88,0x30,0x42,0x99,0x12),
+ (0x80,0x75,0xf7,0xb9,0x64,0x1a,0x45,0x60,0x99,0x81,0xb2,0x0f,0xaa,0xa5,0xd6,0x15,0x6a,0xf0,0x8a,0x11,0x61,0x84,0x32,0x25))
+
+M_13_16 = ((0xa7,0xfb,0xf8,0x61,0xfb,0x46,0x8d,0x5b,0xbf,0x09,0xfe,0xc1,0xdf,0xab,0x44,0xff,0x81,0xec,0x9b,0x3d,0xca,0x00,0x67,0x17,0x7e,0x17,0x01),
+ (0x4e,0xf7,0xf1,0xc3,0xf6,0x8d,0x1a,0xb7,0x7e,0x13,0xfc,0x83,0xbf,0x57,0x89,0xfe,0x03,0xd9,0x37,0x7b,0x94,0x01,0xce,0x2e,0xfc,0x2e,0x02),
+ (0x9c,0xee,0xe3,0x87,0xed,0x1b,0x35,0x6e,0xfd,0x26,0xf8,0x07,0x7f,0xaf,0x12,0xfd,0x07,0xb2,0x6f,0xf6,0x28,0x03,0x9c,0x5d,0xf8,0x5d,0x04),
+ (0x38,0xdd,0xc7,0x0f,0xdb,0x37,0x6a,0xdc,0xfa,0x4d,0xf0,0x0f,0xfe,0x5e,0x25,0xfa,0x0f,0x64,0xdf,0xec,0x51,0x06,0x38,0xbb,0xf0,0xbb,0x08),
+ (0x70,0xba,0x8f,0x1f,0xb6,0x6f,0xd4,0xb8,0xf5,0x9b,0xe0,0x1f,0xfc,0xbd,0x4a,0xf4,0x1f,0xc8,0xbe,0xd9,0xa3,0x0c,0x70,0x76,0xe1,0x77,0x11),
+ (0xe0,0x74,0x1f,0x3f,0x6c,0xdf,0xa8,0x71,0xeb,0x37,0xc1,0x3f,0xf8,0x7b,0x95,0xe8,0x3f,0x90,0x7d,0xb3,0x47,0x19,0xe0,0xec,0xc2,0xef,0x22),
+ (0xc0,0xe9,0x3e,0x7e,0xd8,0xbe,0x51,0xe3,0xd6,0x6f,0x82,0x7f,0xf0,0xf7,0x2a,0xd1,0x7f,0x20,0xfb,0x66,0x8f,0x32,0xc0,0xd9,0x85,0xdf,0x45),
+ (0x80,0xd3,0x7d,0xfc,0xb0,0x7d,0xa3,0xc6,0xad,0xdf,0x04,0xff,0xe0,0xef,0x55,0xa2,0xff,0x40,0xf6,0xcd,0x1e,0x65,0x80,0xb3,0x0b,0xbf,0x8b))
+
+def bch_enc_13(data, enc_len, level):
+ """ bch ecc encode function, parity bits is 13.
+ data is the source buffer
+ enc_len is the encode length
+ level is the ecc level used """
+
+ #print "bch encode length is %d, " % enc_len,
+ #print "ecc level is %d " % level
+
+ # select proper matrix for the ecc level assigned #
+ parity_byte = int(math.ceil(float(level) * 13 / 8))
+ temp = 'matrix = M_13_' + str(level)
+ exec(temp)
+
+ # fetch raw data #
+ raw = data + ('\0' * parity_byte)
+ raw = bytearray(raw)
+
+ for i in range(enc_len):
+ for j in range(8):
+ if (raw[i] & (1 << j)) != 0:
+ for k in range(parity_byte + 1):
+ raw[i + k] ^= matrix[j][k]
+
+ # feedback parity data generated #
+ raw = str(raw)
+ parity_data = raw[enc_len:]
+ return parity_data
+
+if __name__ == "__main__":
+ """ this is bch encode function. """
+ print "this is bch encode function."
diff --git a/src/bsp/scatter/tools/nand-utils/gen-nand-burn-img.sh b/src/bsp/scatter/tools/nand-utils/gen-nand-burn-img.sh
new file mode 100755
index 0000000..1608eaa
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/gen-nand-burn-img.sh
@@ -0,0 +1,147 @@
+#! /bin/sh
+
+NAND_HEADER_VERSION=$1
+NAND_CHIP_NAME=$2
+PARTITION_XML=$3
+
+if [ "${NAND_CHIP_NAME}" = "" ]; then
+ echo "ERROR: please input NAND_CHIP_NAME"
+ exit 1
+else
+ echo "NAND: ${NAND_CHIP_NAME}"
+fi
+
+if [ "${NAND_HEADER_VERSION}" = "" ]; then
+ echo "ERROR: please input NAND_HEADER_VERSION"
+ exit 2
+else
+ echo "NAND_HEADER_VERSION: ${NAND_HEADER_VERSION}"
+ if [ "${NAND_HEADER_VERSION}" = "2.0" ]; then
+ RANDOM_EN=0
+ elif [ "${NAND_HEADER_VERSION}" = "1.1" ]; then
+ RANDOM_EN=1
+ fi
+fi
+
+if [ "${PARTITION_XML}" = "" ]; then
+ echo "ERROR: please input PARTITION_XML"
+ exit 3
+else
+ echo "PARTITION_XML: ${PARTITION_XML}"
+fi
+
+OUTPUT_FLD="output"
+IMAGE_FLD="images"
+BURN_SUFFIX="-burn"
+BURN_IMG="${PWD}/${OUTPUT_FLD}/nand-burn.img"
+BURN_LIST_CSV="${PWD}/${OUTPUT_FLD}/partition_table.csv"
+BURN_LIST_DEF="${PWD}/${OUTPUT_FLD}/partition_table.def"
+rm -rf ${PWD}/${OUTPUT_FLD}/*${BURN_SUFFIX}
+rm -rf ${BURN_IMG}
+touch ${BURN_IMG}
+
+rm -rf ${BURN_LIST_CSV}
+touch ${BURN_LIST_CSV}
+rm -rf ${BURN_LIST_DEF}
+touch ${BURN_LIST_DEF}
+
+python ${PWD}/tools/nand-utils/gen_burner_partition_table_def.py ${NAND_CHIP_NAME} \
+ ${NAND_HEADER_VERSION} ${BURN_LIST_DEF} 0 0 0 0
+
+LBS=$(grep -o 'lbs="[0-9]*"' ${PARTITION_XML} | grep -o [0-9]*)
+
+MBR_NAND="MBR_NAND"
+MBR_NAND_BRUN="MBR_NAND-burn"
+PART_IDX=0
+
+cat ${PARTITION_XML} | while read line
+do
+ IMAGE_NAME=""
+ LBA_START=""
+ LBA_END=""
+ CHECK=$(echo $line | grep "name")
+ if [ "${CHECK}" != "" ]; then
+ PARTITION=${line#*name=}
+ PARTITION=${PARTITION#*\"}
+ PARTITION=${PARTITION%%\"*}
+ else
+ PARTITION=""
+ fi
+ if [ "${PARTITION}" = "UBOOT" ]; then
+ IMAGE_NAME="lk.img"
+ fi
+ if [ "${PARTITION}" = "TEE1" -o "${PARTITION}" = "TEE2" ]; then
+ IMAGE_NAME="tz.img"
+ fi
+ if [ "${PARTITION}" = "USRDATA" ]; then
+ IMAGE_NAME="userdata.ubi"
+ fi
+ if [ "${PARTITION}" = "BOOTIMG1" -o "${PARTITION}" = "BOOTIMG2" ]; then
+ IMAGE_NAME="boot.img"
+ fi
+ if [ "${PARTITION}" = "ROOTFS1" -o "${PARTITION}" = "ROOTFS2" ]; then
+ IMAGE_NAME="rootfs.ubi"
+ fi
+
+ if [ "${PARTITION}" != "" ]; then
+ echo ${PART_IDX} ${PARTITION}
+ if [ "${IMAGE_NAME}" != "" -a ! -f "${PWD}/${IMAGE_FLD}/${IMAGE_NAME}" ]; then
+ echo "file "${PWD}/${IMAGE_FLD}/${IMAGE_NAME}" not exist!! "
+ IMAGE_NAME=""
+ fi
+ LBA_START=${line#*start=}
+ LBA_START=${LBA_START#*\"}
+ LBA_START=${LBA_START%%\"*}
+ LBA_END=${line#*end=}
+ LBA_END=${LBA_END#*\"}
+ LBA_END=${LBA_END%%\"*}
+ ((LBA_NUM=${LBA_END}-${LBA_START}+1))
+ ((PART_SIZE=${LBS}*${LBA_NUM}))
+ ((PART_START_ADDR=${LBS}*${LBA_START}))
+
+ if [ "${PART_IDX}" = "0" ]; then
+ ((MBR_PART_SIZE=${LBS}*${LBA_START}))
+ ((MBR_LBA_END=${LBA_START}-1))
+ python ${PWD}/tools/nand-utils/gen_burner_image.pyc ${NAND_CHIP_NAME} \
+ ${PWD}/${IMAGE_FLD}/${MBR_NAND} ${PWD}/${OUTPUT_FLD}/${MBR_NAND_BRUN} ${NAND_HEADER_VERSION} ${RANDOM_EN}
+ touch ${PWD}/${IMAGE_FLD}/${MBR_NAND_BRUN}
+ cat ${PWD}/${OUTPUT_FLD}/${MBR_NAND_BRUN} >> ${PWD}/${IMAGE_FLD}/${MBR_NAND_BRUN}
+ python ${PWD}/tools/nand-utils/pad_dummy_data_by_partition.pyc ${NAND_CHIP_NAME} \
+ ${PWD}/${IMAGE_FLD}/${MBR_NAND_BRUN} ${MBR_PART_SIZE} ${NAND_HEADER_VERSION}
+ cat ${PWD}/${IMAGE_FLD}/${MBR_NAND_BRUN} > ${BURN_IMG}
+ python ${PWD}/tools/nand-utils/gen_burner_partition_table_def.py ${NAND_CHIP_NAME} \
+ ${NAND_HEADER_VERSION} ${BURN_LIST_DEF} ${PWD}/${OUTPUT_FLD}/${MBR_NAND_BRUN} 0 ${MBR_LBA_END} 1
+ python ${PWD}/tools/nand-utils/gen_burner_partition_table_csv.py ${NAND_CHIP_NAME} \
+ ${NAND_HEADER_VERSION} ${BURN_LIST_CSV} ${PWD}/${OUTPUT_FLD}/${MBR_NAND_BRUN} 0 ${MBR_LBA_END} "MBR_NAND"
+ fi
+
+ fi
+
+ if [ "${IMAGE_NAME}" != "" ]; then
+ PART_IDX=$((${PART_IDX}+1))
+ if [ ! -f "${PWD}/${IMAGE_FLD}/${IMAGE_NAME}${BURN_SUFFIX}" ]; then
+ python ${PWD}/tools/nand-utils/gen_burner_image.pyc ${NAND_CHIP_NAME} \
+ ${PWD}/${IMAGE_FLD}/${IMAGE_NAME} ${PWD}/${OUTPUT_FLD}/${IMAGE_NAME}${BURN_SUFFIX} ${NAND_HEADER_VERSION} ${RANDOM_EN}
+ touch ${PWD}/${IMAGE_FLD}/${IMAGE_NAME}${BURN_SUFFIX}
+ cat ${PWD}/${OUTPUT_FLD}/${IMAGE_NAME}${BURN_SUFFIX} >> ${PWD}/${IMAGE_FLD}/${IMAGE_NAME}${BURN_SUFFIX}
+ python ${PWD}/tools/nand-utils/pad_dummy_data_by_partition.pyc ${NAND_CHIP_NAME} \
+ ${PWD}/${IMAGE_FLD}/${IMAGE_NAME}${BURN_SUFFIX} ${PART_SIZE} ${NAND_HEADER_VERSION}
+ fi
+ cat ${PWD}/${IMAGE_FLD}/${IMAGE_NAME}${BURN_SUFFIX} >> ${BURN_IMG}
+ python ${PWD}/tools/nand-utils/gen_burner_partition_table_def.py ${NAND_CHIP_NAME} \
+ ${NAND_HEADER_VERSION} ${BURN_LIST_DEF} ${PWD}/${OUTPUT_FLD}/${IMAGE_NAME}${BURN_SUFFIX} ${LBA_START} ${LBA_END} 1
+ python ${PWD}/tools/nand-utils/gen_burner_partition_table_csv.py ${NAND_CHIP_NAME} \
+ ${NAND_HEADER_VERSION} ${BURN_LIST_CSV} ${PWD}/${OUTPUT_FLD}/${IMAGE_NAME}${BURN_SUFFIX} ${LBA_START} ${LBA_END} ${PARTITION}
+ elif [ "${PARTITION}" != "" ]; then
+ PART_IDX=$((${PART_IDX}+1))
+ touch ${PWD}/${IMAGE_FLD}/${PARTITION}${BURN_SUFFIX}
+ python ${PWD}/tools/nand-utils/pad_dummy_data_by_partition.pyc ${NAND_CHIP_NAME} \
+ ${PWD}/${IMAGE_FLD}/${PARTITION}${BURN_SUFFIX} ${PART_SIZE} ${NAND_HEADER_VERSION}
+ cat ${PWD}/${IMAGE_FLD}/${PARTITION}${BURN_SUFFIX} >> ${BURN_IMG}
+ fi
+done
+
+python ${PWD}/tools/nand-utils/gen_burner_partition_table_def.py ${NAND_CHIP_NAME} \
+ ${NAND_HEADER_VERSION} ${BURN_LIST_DEF} 0 0 0 2
+
+rm -f ${PWD}/${IMAGE_FLD}/*${BURN_SUFFIX}
diff --git a/src/bsp/scatter/tools/nand-utils/gen_burner_image.py b/src/bsp/scatter/tools/nand-utils/gen_burner_image.py
new file mode 100644
index 0000000..a6acb1a
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/gen_burner_image.py
@@ -0,0 +1,133 @@
+#!/usr/bin/env python
+
+import argparse
+import sys
+import os
+import math
+import shutil
+import pp_tbl
+import gen_nand_header
+import gen_nand_header_v11
+import randomizer
+from pad_ecc_by_sector import pad_ecc
+from randomizer import randomizer
+
+def padding(data, size):
+ return data + '\0' * (size - len(data))
+
+def main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('nand_name', help = 'nand device name')
+ parser.add_argument('in_image', help = 'raw input image')
+ parser.add_argument('out_image', help = 'the output burn image ')
+ parser.add_argument('version', help= 'nand header version')
+ parser.add_argument('rand_en', help = 'if randomizer is enabled')
+ args = parser.parse_args()
+ version = float(args.version)
+ rand_en = int(args.rand_en)
+
+ if version == 2.0:
+ (vendor, fdm_size, fdmecc_size, ecc_strength, spare_size, page_size, ppen, ppb) = gen_nand_header.gen_header(args.nand_name)
+ bad_swap = 1
+ elif version == 1.1:
+ (vendor, fdm_size, fdmecc_size, ecc_strength, spare_size, page_size, ppen, ppb) = gen_nand_header_v11.gen_header(args.nand_name, 192, args.nand_name + '_header.bin')
+ bad_swap = 0
+
+ ecc_file = args.out_image
+ rand_file = args.out_image
+ if rand_en == 1:
+ ecc_file = args.nand_name + '_ecc.bin'
+ if ppen == 1:
+ paired = raw_input("insert empty paired page ? Y/y or N/n ")
+ if paired in ['Y', 'y']:
+ rand_file = args.nand_name + '_rand.bin'
+ ecc_file = args.nand_name + '_ecc.bin'
+ sector_size = 1024 if page_size > 512 else 512
+ sector_per_page = page_size / sector_size
+ sector_spare_size = spare_size / sector_per_page
+ # input image page size alignment #
+ file_len = os.path.getsize(args.in_image)
+ pages = int(math.ceil(float(file_len) / page_size))
+ in_file = "temp_in.bin"
+ with open(args.in_image, "rb") as f_in:
+ with open(in_file, "wb") as f_temp:
+ f_temp.write(padding(f_in.read(), pages * page_size))
+ pad_ecc(in_file, ecc_file, sector_size, fdm_size, fdmecc_size, ecc_strength, sector_spare_size, page_size, bad_swap)
+
+ if rand_en == 1:
+ randomizer(ecc_file, rand_file, "SS", 1, page_size, spare_size, sector_size, ppb, ppen, vendor)
+
+ # MT8516 force sector spare size from 56, 54, to be 52
+ if version == 1.1:
+ # spare settings must match 8516 BOOT ROM, The sector size default is 1024 bytes.
+ SPARES = [32, 52, 64, 80, 88, 96, 100, 104, 122, 124]
+ sector_spare_size_adjust = sector_spare_size
+
+ for i in range(len(SPARES)):
+ if (sector_spare_size <= SPARES[i]):
+ if sector_spare_size == SPARES[i]:
+ sector_spare_size_adjust = SPARES[i]
+ if (sector_spare_size < SPARES[i]) and (i != 0):
+ sector_spare_size_adjust = SPARES[i - 1]
+ break
+ k = 0
+ pad_data = (sector_spare_size - sector_spare_size_adjust) * sector_per_page
+ adjust_file = rand_file + '_adjust'
+ f_in = open(rand_file, "rb")
+ f_out = open(adjust_file, "wb")
+ for i in range(pages * sector_per_page):
+ f_in.seek(((sector_size + sector_spare_size) * i), 0)
+ sector_data = f_in.read(sector_size + sector_spare_size_adjust)
+ if (i % sector_per_page) == (sector_per_page - 1):
+ sector_data += '\xff' * pad_data
+ if (i) > 0 and (i % sector_per_page) == 0:
+ k = k + 1
+ f_out.seek(((sector_size + sector_spare_size) * i), 0)
+ else:
+ f_out.seek((sector_size + sector_spare_size_adjust) * i + (k * pad_data), 0)
+
+ f_out.write(sector_data)
+
+ f_in.close()
+ f_out.close()
+ shutil.copyfile(adjust_file, rand_file)
+ # remove temp files #
+ os.remove(adjust_file)
+ # insert empty paired page #
+ if ppen == 1 and paired in ['Y', 'y']:
+ if rand_en == 1:
+ pp_file = rand_file
+ else:
+ pp_file = ecc_file
+ if vendor == 'TSB':
+ PP = pp_tbl.TSB_PP
+ else:
+ raise Exception("unsupport %s pp table " % vendor)
+ f_pp = open(pp_file, "rb")
+ f_out = open(args.out_image, "wb")
+
+ if (os.path.getsize(in_file) % page_size) != 0:
+ raise Exception("input image size is not page size aligned")
+ page_number = os.path.getsize(in_file) / page_size
+ block_number = int(math.ceil(float(page_number) / (ppb / 2)))
+ print "page num %d block num %d" % (page_number, block_number)
+ for i in range(ppb * block_number):
+ if page_number > 0 and (i % ppb) in PP:
+ f_out.write(f_pp.read(page_size + spare_size))
+ page_number -= 1
+ else:
+ f_out.write('\xff' * (page_size + spare_size))
+ f_pp.close()
+ f_out.close()
+ # remove temp files #
+ os.remove(pp_file)
+
+ if rand_en == 1:
+ os.remove(ecc_file)
+
+ # remove temp files #
+ os.remove(args.nand_name + '_header.bin')
+ os.remove(in_file)
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/src/bsp/scatter/tools/nand-utils/gen_burner_partition_table_csv.py b/src/bsp/scatter/tools/nand-utils/gen_burner_partition_table_csv.py
new file mode 100755
index 0000000..c2adf29
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/gen_burner_partition_table_csv.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+
+import argparse
+import csv
+import sys
+import struct
+import os
+import math
+import gen_nand_header
+import gen_nand_header_v11
+
+def main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('nand_name', help = 'nand device name')
+ parser.add_argument('version', help= 'nand header version')
+ parser.add_argument('table_file', help = 'partition table file')
+ parser.add_argument('image', help = 'image file name')
+ parser.add_argument('start_page', help = 'partition start page index')
+ parser.add_argument('end_page', help = 'partition end page index')
+ parser.add_argument('part_name', help = 'partition name')
+ args = parser.parse_args()
+
+ version = float(args.version)
+ start_page = int(args.start_page)
+ end_page = int(args.end_page)
+ if version == 2.0:
+ (vendor, fdm_size, fdmecc_size, ecc_strength, spare_size, page_size, ppen, ppb) = gen_nand_header.gen_header(args.nand_name)
+ elif version == 1.1:
+ (vendor, fdm_size, fdmecc_size, ecc_strength, spare_size, page_size, ppen, ppb) = gen_nand_header_v11.gen_header(args.nand_name, 192, args.nand_name + '_header.bin')
+
+ file_len = os.path.getsize(args.image)
+ if (file_len % (page_size + spare_size)) != 0:
+ raise Exception("image size is not full page size aligned")
+ block_num = int(math.ceil(float(file_len) / ((page_size + spare_size) * ppb)))
+ if (start_page % ppb) != 0:
+ raise Exception("partition start page is not block align")
+ start_blk = start_page / ppb
+ if ((end_page + 1) % ppb) != 0:
+ raise Exception("partition end page is not block align")
+ end_blk = end_page / ppb
+ line_info = [start_blk, end_blk, block_num, '0xffffffff', args.part_name]
+
+ with open(args.table_file, "ab") as csvf:
+ csvwriter = csv.writer(csvf, delimiter=';')
+ csvwriter.writerow(line_info)
+
+ # remove temp files #
+ os.remove(args.nand_name + '_header.bin')
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/src/bsp/scatter/tools/nand-utils/gen_burner_partition_table_def.py b/src/bsp/scatter/tools/nand-utils/gen_burner_partition_table_def.py
new file mode 100755
index 0000000..61c81dd
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/gen_burner_partition_table_def.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+
+import argparse
+import sys
+import struct
+import os
+import math
+import gen_nand_header
+import gen_nand_header_v11
+
+def main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('nand_name', help = 'nand device name')
+ parser.add_argument('version', help= 'nand header version')
+ parser.add_argument('table_file', help = 'partition table file')
+ parser.add_argument('image', help = 'image file name')
+ parser.add_argument('start_page', help = 'partition start page index')
+ parser.add_argument('end_page', help = 'partition end page index')
+ parser.add_argument('pad', help = '0: pad header, 1: no pad, 2: pad tail')
+ args = parser.parse_args()
+ pad = int(args.pad)
+
+ if pad == 0:
+ line_info = "GROUP DEFINE2" + (3 * '\0')
+ elif pad == 2:
+ line_info = 16 * '\xff'
+ elif pad == 1:
+ version = float(args.version)
+ start_page = int(args.start_page)
+ end_page = int(args.end_page)
+ if version == 2.0:
+ (vendor, fdm_size, fdmecc_size, ecc_strength, spare_size, page_size, ppen, ppb) = gen_nand_header.gen_header(args.nand_name)
+ elif version == 1.1:
+ (vendor, fdm_size, fdmecc_size, ecc_strength, spare_size, page_size, ppen, ppb) = gen_nand_header_v11.gen_header(args.nand_name, 192, args.nand_name + '_header.bin')
+
+ file_len = os.path.getsize(args.image)
+ if (file_len % (page_size + spare_size)) != 0:
+ raise Exception("image size is not full page size aligned")
+ block_num = int(math.ceil(float(file_len) / ((page_size + spare_size) * ppb)))
+ if (start_page % ppb) != 0:
+ raise Exception("partition start page is not block align")
+ start_blk = start_page / ppb
+ if ((end_page + 1) % ppb) != 0:
+ raise Exception("partition end page is not block align")
+ end_blk = end_page / ppb
+
+ data_type = 1
+
+ line_info = struct.pack("I", data_type)
+ line_info += struct.pack("I", start_blk)
+ line_info += struct.pack("I", end_blk)
+ line_info += struct.pack("I", block_num)
+
+ # remove temp files #
+ os.remove(args.nand_name + '_header.bin')
+ else:
+ raise Exception("wrong pad type")
+
+ with open(args.table_file, "ab") as f:
+ f.write(line_info)
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/src/bsp/scatter/tools/nand-utils/gen_nand_header.py b/src/bsp/scatter/tools/nand-utils/gen_nand_header.py
new file mode 100755
index 0000000..fa71e74
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/gen_nand_header.py
@@ -0,0 +1,135 @@
+#!/usr/bin/env python
+
+import ecc_bch
+import sys
+import os
+import struct
+import argparse
+import pp_tbl
+
+def gen_header(nand_name):
+ """ device info:
+ name vendor totalsize(MB) pagesize(B) sparesize(B) pageperblock cycle eccstrength
+ interface acccon acccon1 dqsdlymux dqsdlyctrl nfidlyctrl pptableenable lbasize
+ fastclock usedma fdmsize fdmeccsize strobesel
+ """
+ with open(os.getcwd() + "/tools/nand-utils/nand_device_list.txt", "r") as f:
+ found = 0
+ for l in f:
+ s = l.split()
+ if s[0] == nand_name:
+ found = 1
+ vendor = s[1]
+ total_size = int(s[2])
+ page_size = int(s[3])
+ #page_shift = len(bin(page_size).replace('0b','')) - 1
+ page_shift = 16 if page_size > 512 else 8
+ spare_size = int(s[4])
+ page_per_block = int(s[5])
+ address_cycle = int(s[6])
+ ecc_strength = int(s[7])
+ interface = int(s[8])
+ acccon = eval(s[9])
+ acccon1 = eval(s[10])
+ dqsdlymux = int(s[11])
+ dqsdlyctrl = eval(s[12])
+ nfidlyctrl = eval(s[13])
+ pptableen = int(s[14])
+ lba_size = int(s[15])
+ fast_clk = int(s[16])
+ use_dma = int(s[17])
+ fdm_size = int(s[18])
+ fdmecc_size = int(s[19])
+ strobesel = int(s[20])
+
+ # meaningless, just set pptableen value as BROM test code #
+ if not pptableen:
+ pptableen = 0xffff
+
+ break
+
+ if not found:
+ raise KeyError("not support " + nand_name)
+
+ #print s[0]
+ #print "vendor %s, total size %d(MB) page size %d, page shift %d, spare size %d, page per block %d" \
+ # % (vendor, total_size, page_size, page_shift, spare_size, page_per_block)
+ #print "address cycle %d, ecc strength %d, interface %d, acccon 0x%x, acccon1 0x%x" \
+ # % (address_cycle, ecc_strength, interface, acccon, acccon1)
+ #print "dqsdlymux %d, dqsdlyctrl 0x%x, nfidlyctrl 0x%x, pptable enable %d, lba size %d" \
+ # % (dqsdlymux, dqsdlyctrl, nfidlyctrl, pptableen, lba_size)
+ #print "fast clock enable %d, use dma %d, fdm size %d, fdmecc size %d" \
+ # % (fast_clk, use_dma, fdm_size, fdmecc_size)
+ #raise KeyError("not support " + nand_name)
+
+ # nand header is total 440B include ecc parity 140B #
+ header_size = 300
+ pptbl_size = 128
+
+ header = "NANDCONFIG!" + '\0'
+ header += struct.pack("I", total_size)
+ header += struct.pack("H", page_size)
+ header += struct.pack("H", address_cycle)
+ header += struct.pack("H", spare_size)
+ header += struct.pack("H", interface)
+ header += struct.pack("I", ecc_strength)
+ header += struct.pack("H", page_per_block)
+ header += struct.pack("H", page_shift)
+ header += struct.pack("H", pptableen)
+ header += struct.pack("H", dqsdlymux)
+ header += struct.pack("I", dqsdlyctrl)
+ header += struct.pack("I", acccon)
+ header += struct.pack("I", acccon1)
+ header += struct.pack("I", nfidlyctrl)
+ header += struct.pack("H", lba_size)
+ header += struct.pack("H", fast_clk)
+ header += struct.pack("H", use_dma)
+ header += struct.pack("H", strobesel)
+ header += struct.pack("H", fdm_size)
+ header += struct.pack("H", fdmecc_size)
+
+ # pad dummy byte #
+ header += '\x5a' * (header_size - len(header) - pptbl_size)
+ if pptableen == 1:
+ # add pptable #
+ if vendor == 'TSB':
+ header += str(bytearray(pp_tbl.TSB_PP))
+ else:
+ raise KeyError(" no %s pptable " % vendor)
+ else:
+ header += '\xff' * pptbl_size
+
+ # calculate header ecc parity #
+ header_size = 300
+ ecc_level = 80
+ ecc = ecc_bch.bch_enc_14(header, header_size, ecc_level)
+ header += ecc
+
+ header_file = nand_name + '_header.bin'
+ with open(header_file, "wb") as f:
+ f.write(header)
+
+ return (vendor, fdm_size, fdmecc_size, ecc_strength, spare_size, page_size, pptableen, page_per_block)
+
+def main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('nand_name', help = 'nand device name')
+ parser.add_argument('gpt_image', help = 'pmbr + gpt entry image ')
+ args = parser.parse_args()
+
+ # generate nand device header #
+ gen_header(args.nand_name)
+
+ # pad nand header #
+ with open(args.nand_name + '_header.bin', "rb") as f_h:
+ h_buf = f_h.read()
+ with open(args.gpt_image, "rb+") as f_g:
+ f_g.seek(440, 0)
+ h_buf = h_buf + f_g.read()
+ f_g.seek(0, 0)
+ f_g.write(h_buf)
+
+ os.remove(args.nand_name + '_header.bin')
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/src/bsp/scatter/tools/nand-utils/gen_nand_header_mt2731.py b/src/bsp/scatter/tools/nand-utils/gen_nand_header_mt2731.py
new file mode 100755
index 0000000..cea124e
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/gen_nand_header_mt2731.py
@@ -0,0 +1,141 @@
+#// SPDX-License-Identifier: MediaTekProprietary
+#!/usr/bin/env python
+
+import ecc_bch
+import sys
+import os
+import struct
+import argparse
+import pp_tbl
+
+def gen_header(nand_name):
+ """ device info:
+ name vendor totalsize(MB) pagesize(B) sparesize(B) pageperblock cycle eccstrength
+ interface acccon acccon1 dqsdlymux dqsdlyctrl nfidlyctrl pptableenable lbasize
+ fastclock usedma fdmsize fdmeccsize strobesel
+ """
+ with open(os.getcwd() + "/tools/nand-utils/nand_device_list_mt2731.txt", "r") as f:
+ found = 0
+ for l in f:
+ s = l.split()
+ if s[0] == nand_name:
+ found = 1
+ vendor = s[1]
+ total_size = int(s[2])
+ page_size = int(s[3])
+ #page_shift = len(bin(page_size).replace('0b','')) - 1
+ page_shift = 16 if page_size > 512 else 8
+ spare_size = int(s[4])
+ page_per_block = int(s[5])
+ address_cycle = int(s[6])
+ ecc_strength = int(s[7])
+ interface = int(s[8])
+ acccon = eval(s[9])
+ acccon1 = eval(s[10])
+ dqsdlymux = int(s[11])
+ dqsdlyctrl = eval(s[12])
+ nfidlyctrl = eval(s[13])
+ pptableen = int(s[14])
+ lba_size = int(s[15])
+ fast_clk = int(s[16])
+ use_dma = int(s[17])
+ fdm_size = int(s[18])
+ fdmecc_size = int(s[19])
+ strobesel = int(s[20])
+
+ # meaningless, just set pptableen value as BROM test code #
+ if not pptableen:
+ pptableen = 0xffff
+
+ break
+
+ if not found:
+ raise KeyError("not support " + nand_name)
+
+ #print s[0]
+ #print "vendor %s, total size %d(MB) page size %d, page shift %d, spare size %d, page per block %d" \
+ # % (vendor, total_size, page_size, page_shift, spare_size, page_per_block)
+ #print "address cycle %d, ecc strength %d, interface %d, acccon 0x%x, acccon1 0x%x" \
+ # % (address_cycle, ecc_strength, interface, acccon, acccon1)
+ #print "dqsdlymux %d, dqsdlyctrl 0x%x, nfidlyctrl 0x%x, pptable enable %d, lba size %d" \
+ # % (dqsdlymux, dqsdlyctrl, nfidlyctrl, pptableen, lba_size)
+ #print "fast clock enable %d, use dma %d, fdm size %d, fdmecc size %d" \
+ # % (fast_clk, use_dma, fdm_size, fdmecc_size)
+ #raise KeyError("not support " + nand_name)
+
+ # nand header is total 440B include ecc parity 140B #
+ header_size = 398
+ pptbl_size = 128
+
+ # the reserved region is for SGPT and BBT
+ reserved_size = page_size * page_per_block * 8 / 1024
+ # As NAND totol size for 2731 BROM is unit as Mega, the reserved size need to be the unit of Mega
+ if (reserved_size % 1024) == 0:
+ total_size = total_size - reserved_size / 1024
+
+ header = "NANDCONFIG!" + '\0'
+ header += struct.pack("I", total_size)
+ header += struct.pack("H", page_size)
+ header += struct.pack("H", address_cycle)
+ header += struct.pack("H", spare_size)
+ header += struct.pack("H", interface)
+ header += struct.pack("I", ecc_strength)
+ header += struct.pack("H", page_per_block)
+ header += struct.pack("H", page_shift)
+ header += struct.pack("H", pptableen)
+ header += struct.pack("H", dqsdlymux)
+ header += struct.pack("I", dqsdlyctrl)
+ header += struct.pack("I", acccon)
+ header += struct.pack("I", acccon1)
+ header += struct.pack("I", nfidlyctrl)
+ header += struct.pack("H", lba_size)
+ header += struct.pack("H", fast_clk)
+ header += struct.pack("H", use_dma)
+ header += struct.pack("H", strobesel)
+ header += struct.pack("H", fdm_size)
+ header += struct.pack("H", fdmecc_size)
+ # pad dummy byte #
+ header += '\x5a' * (header_size - len(header) - pptbl_size)
+ if pptableen == 1:
+ # add pptable #
+ if vendor == 'TSB':
+ header += str(bytearray(pp_tbl.TSB_PP))
+ else:
+ raise KeyError(" no %s pptable " % vendor)
+ else:
+ header += '\xff' * pptbl_size
+
+ # calculate header ecc parity #
+ header_size = 398
+ ecc_level = 24
+ ecc = ecc_bch.bch_enc_14(header, header_size, ecc_level)
+ header += ecc
+
+ header_file = nand_name + '_header.bin'
+ with open(header_file, "wb") as f:
+ f.write(header)
+
+ return (vendor, fdm_size, fdmecc_size, ecc_strength, spare_size, page_size, pptableen, page_per_block)
+
+def main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('nand_name', help = 'nand device name')
+ parser.add_argument('gpt_image', help = 'pmbr + gpt entry image ')
+ args = parser.parse_args()
+
+ # generate nand device header #
+ gen_header(args.nand_name)
+
+ # pad nand header #
+ with open(args.nand_name + '_header.bin', "rb") as f_h:
+ h_buf = f_h.read()
+ with open(args.gpt_image, "rb+") as f_g:
+ f_g.seek(440, 0)
+ h_buf = h_buf + f_g.read()
+ f_g.seek(0, 0)
+ f_g.write(h_buf)
+
+ os.remove(args.nand_name + '_header.bin')
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/src/bsp/scatter/tools/nand-utils/gen_nand_header_mt2735_hsm.py b/src/bsp/scatter/tools/nand-utils/gen_nand_header_mt2735_hsm.py
new file mode 100755
index 0000000..13932c7
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/gen_nand_header_mt2735_hsm.py
@@ -0,0 +1,106 @@
+#!/usr/bin/env python
+
+import ecc_bch
+import sys
+import os
+import struct
+import argparse
+
+def gen_header(nand_name, header_file):
+ """ device info:
+ name vendor pagesize(B) sparesize(B) pageperblock blocks cycle
+ """
+ with open(os.getcwd() + "/tools/nand-utils/nand_device_list_mt2735_hsm.txt", "r") as f:
+ found = 0
+ for l in f:
+ s = l.split()
+ if s[0] == nand_name:
+ found = 1
+ vendor = s[1]
+ page_size = int(s[2])
+ spare_size = int(s[3])
+ pages_per_block = int(s[4])
+ blocks = int(s[5])
+ cycle = int(s[6])
+ if not found:
+ raise KeyError("not support " + nand_name)
+
+ # step1: generate nand header info #
+ header = "NANDCFG!"
+ version = 1
+ # dma mode enable, normal speed
+ config = 0x1
+ sector_size = 1024
+ fdm_size = 8
+ fdmecc_size = 1
+ lbs = 0
+ header += struct.pack("IIIIII", version, config, sector_size,\
+ fdm_size, fdmecc_size, lbs)
+ plane_sel_poi = 12
+ # parameter page is enabled
+ parameter_page_en = (1 << 2)
+ if (config & parameter_page_en):
+ nand = struct.pack("IIIII", 0, 0,\
+ 0, 0,\
+ plane_sel_poi)
+ else:
+ nand = struct.pack("IIIII", page_size, spare_size,\
+ pages_per_block, blocks,\
+ plane_sel_poi)
+ header += nand
+ pll = 0
+ # normal speed, acccon do not need to be set, BROM use default 0x30C77FFF
+ acccon = 0
+ # normal speed, strobe_sel do not need to be set
+ strobe_sel = 0
+ acccon1 = 0
+ dqs_delay_mux = 0
+ dqs_delay_ctrl = 0
+ delay_ctrl = 0
+ latch_lat = 0
+ sam_dly = 0
+ driving = 0
+ high_speed = struct.pack("IIIIIIIIII", pll, acccon, strobe_sel,\
+ acccon1, dqs_delay_mux,\
+ dqs_delay_ctrl, delay_ctrl,\
+ latch_lat, sam_dly, driving)
+ header += high_speed
+ bl_start = 0
+ bl_end = 0
+ header += struct.pack("II", bl_start, bl_end)
+ ecc_level = 24
+ header_size = len(header) + ecc_level * 14 / 8
+ print "header_size: %d" % header_size
+
+ ecc = ecc_bch.bch_enc_14(header, len(header), ecc_level)
+ header += ecc
+
+ with open(header_file, "wb") as f:
+ f.write(header)
+
+ return (header_size, sector_size, fdm_size, fdmecc_size, lbs)
+
+def main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('nand_name', help = 'nand device name')
+ parser.add_argument('gpt_image', help = 'pmbr + gpt entry image ')
+ args = parser.parse_args()
+
+ header_file = args.nand_name + '_header.bin'
+ # generate nand device header #
+ gen_header(args.nand_name, header_file)
+
+ # pad nand header #
+ with open(header_file, "rb") as f_h:
+ h_buf = f_h.read()
+ with open(args.gpt_image, "rb+") as f_g:
+ f_g.seek(440, 0)
+ h_buf += '\x00' * (440 - len(h_buf))
+ h_buf = h_buf + f_g.read()
+ f_g.seek(0, 0)
+ f_g.write(h_buf)
+
+ os.remove(header_file)
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/src/bsp/scatter/tools/nand-utils/gen_nand_header_v11.py b/src/bsp/scatter/tools/nand-utils/gen_nand_header_v11.py
new file mode 100755
index 0000000..742c17a
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/gen_nand_header_v11.py
@@ -0,0 +1,121 @@
+#!/usr/bin/env python
+
+import ecc_bch
+import sys
+import os
+import struct
+import argparse
+
+def gen_header(nand_name, lk_start_addr, out_image):
+ """ device info:
+ name vendor interface pagesize(B) cycle sparesize(B) pageperblock total_blocks
+ page_shift block_shift ecc_strength
+ """
+ with open(os.getcwd() + "/tools/nand-utils/nand_device_list_v11.txt", "r") as f:
+ found = 0
+ for l in f:
+ s = l.split()
+ if s[0] == nand_name:
+ found = 1
+ vendor = s[1]
+ interface = eval(s[2])
+ page_size = int(s[3])
+ address_cycle = int(s[4])
+ spare_size = int(s[5])
+ page_per_block = int(s[6])
+ total_blocks = int(s[7])
+ page_shift = int(s[8])
+ block_shift = int(s[9])
+ ecc_strength = int(s[10])
+
+ if not found:
+ raise KeyError("not support " + nand_name)
+
+ #print s[0]
+ #print "vendor %s, page size %d, page shift %d, spare size %d, page per block %d" \
+ # % (vendor, page_size, page_shift, spare_size, page_per_block)
+ #print "address cycle %d, ecc strength %d, interface %d block_shift %d total_blocks %d" \
+ # % (address_cycle, ecc_strength, interface, block_shift, total_blocks)
+
+ # step1: generate nand header info #
+ header = "BOOTLOADER!" + '\0'
+ header += "V006"
+ header += "NFIINFO" + '\0'
+ header += struct.pack("H", interface)
+ header += struct.pack("H", page_size)
+ header += struct.pack("H", address_cycle)
+ # pad 0 for nand type, means slc nand#
+ header += struct.pack("H", 0)
+ # pad tlc control #
+ header += '\0' * 12
+ header += struct.pack("H", spare_size)
+ header += struct.pack("H", page_per_block)
+ header += struct.pack("H", total_blocks)
+ header += struct.pack("H", page_shift)
+ header += struct.pack("H", block_shift)
+ # pad arm align data #
+ header += '\0' * 2
+ # pad mlc control #
+ header += '\0' * 20
+ # pad dummy #
+ header += '\0' * (4 + 4 + 28)
+ # calculate header ecc parity #
+ header_size = 112
+ ecc_level = 80
+ ecc = ecc_bch.bch_enc_14(header, header_size, ecc_level)
+ header += ecc
+ # pad 4B dummy #
+ header += '\0' * 4
+ # double nfb header #
+ header += header
+ # pad page size align dummy data #
+ header += '\0' * (page_size - 512)
+
+ # step2: generate brlyt #
+ header += "BRLYT" + ('\0' * 3)
+ brlyt_version = 1
+ header += struct.pack("I", brlyt_version)
+ boot_region_addr = lk_start_addr
+ header += struct.pack("I", boot_region_addr)
+ main_region_addr = boot_region_addr + (4 * page_per_block)
+ header += struct.pack("I", main_region_addr)
+ bl_desc_magic = 0x42424242
+ header += struct.pack("I", bl_desc_magic)
+ bl_desc_dev = 0x2
+ header += struct.pack("H", bl_desc_dev)
+ bl_desc_type = 0x1
+ header += struct.pack("H", bl_desc_type)
+ header += struct.pack("I", boot_region_addr)
+ header += struct.pack("I", main_region_addr)
+ bl_desc_attribute = 1
+ header += struct.pack("I", bl_desc_attribute)
+ # pad 7 descripters #
+ header += '\0' * 7 * 20
+ # pad page size align dummy data #
+ header += '\0' * (page_size - 180)
+
+ # step3: pad dummy data till GPT LBA #
+ # let us have an agreement that GPT alwasy be at LBA 128 for SLC NAND #
+ # should be the same LBA in lk and kernel to find GPT #
+ gpt_lba = 128
+ header += '\0' * page_size * (gpt_lba - 2)
+
+ with open(out_image, "wb") as f:
+ f.write(header)
+
+ #return (vendor, fdm_size, fdmecc_size, ecc_strength, spare_size, page_size, pptableen, page_per_block)
+ return (vendor, 8, 8, ecc_strength, spare_size, page_size, 0, page_per_block)
+
+def main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('nand_name', help = 'nand device name')
+ parser.add_argument('lk_start_addr', help = 'lk start address in page unit')
+ parser.add_argument('out_image', help = 'the output header file')
+ args = parser.parse_args()
+ lk_start_addr = int(args.lk_start_addr)
+
+ # generate nand device header #
+ gen_header(args.nand_name, lk_start_addr, args.out_image)
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/src/bsp/scatter/tools/nand-utils/gen_nand_header_v12.py b/src/bsp/scatter/tools/nand-utils/gen_nand_header_v12.py
new file mode 100755
index 0000000..8d9b55f
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/gen_nand_header_v12.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python3
+
+import ecc_bch
+import sys
+import os
+import struct
+import argparse
+
+def gen_header(nand_name, out_image):
+ """ device info:
+ name interface pagesize(B) cycle sparesize(B) pageperblock total_blocks ecc_strength
+ """
+ with open(os.getcwd() + "/tools/nand-utils/nand_device_list_v12.txt", "r") as f:
+ found = 0
+ for l in f:
+ s = l.split()
+ if s[0] == nand_name:
+ found = 1
+ interface = eval(s[1])
+ page_size = int(s[2])
+ address_cycle = int(s[3])
+ spare_size = int(s[4])
+ page_per_block = int(s[5])
+ total_blocks = int(s[6])
+ ecc_strength = int(s[7])
+
+ if not found:
+ raise KeyError("not support " + nand_name)
+
+ # step1: generate nand header info #
+ header = b"BOOTLOADER!" + b'\0'
+ header += b"V006"
+ header += b"NFIINFO" + b'\0'
+ header += struct.pack("H", interface)
+ header += struct.pack("H", page_size)
+ header += struct.pack("H", address_cycle)
+ header += struct.pack("H", spare_size)
+ header += struct.pack("H", page_per_block)
+ header += struct.pack("H", total_blocks)
+ header += b'\0' * 24
+ # defualt not use ahb mode
+ header += struct.pack("H", 0)
+ header += struct.pack("B", int(ecc_strength))
+ # fdmecc size usually is 1
+ header += struct.pack("B", 1)
+ header += b'\0' * 16
+ # calculate header ecc parity #
+ header_size = 80
+ ecc_level = 24
+ ecc = ecc_bch.bch_enc_14(header, header_size, ecc_level)
+ header += ecc
+ header += b'\0' * 6
+ # double nfb header #
+ header += header
+
+ with open(out_image, "wb+") as f:
+ f.write(header)
+
+def main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('nand_name', help = 'nand device name')
+ parser.add_argument('out_image', help = 'the output header file')
+ args = parser.parse_args()
+
+ # generate nand device header #
+ gen_header(args.nand_name, args.out_image)
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
\ No newline at end of file
diff --git a/src/bsp/scatter/tools/nand-utils/gen_nand_header_v13.py b/src/bsp/scatter/tools/nand-utils/gen_nand_header_v13.py
new file mode 100644
index 0000000..43f3d8a
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/gen_nand_header_v13.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python
+
+import ecc_bch
+import sys
+import os
+import struct
+import argparse
+
+def gen_header(nand_name, preloader_start_addr, out_image):
+ """ device info:
+ name vendor interface pagesize(B) cycle sparesize(B) pageperblock total_blocks
+ page_shift block_shift ecc_strength
+ """
+ with open(os.getcwd() + "/tools/nand-utils/nand_device_list_v13.txt", "r") as f:
+ found = 0
+ for l in f:
+ s = l.split()
+ if s[0] == nand_name:
+ found = 1
+ vendor = s[1]
+ interface = eval(s[2])
+ page_size = int(s[3])
+ address_cycle = int(s[4])
+ spare_size = int(s[5])
+ page_per_block = int(s[6])
+ total_blocks = int(s[7])
+ page_shift = int(s[8])
+ block_shift = int(s[9])
+ ecc_strength = int(s[10])
+
+ if not found:
+ raise KeyError("not support " + nand_name)
+
+ #print s[0]
+ #print "vendor %s, page size %d, page shift %d, spare size %d, page per block %d" \
+ # % (vendor, page_size, page_shift, spare_size, page_per_block)
+ #print "address cycle %d, ecc strength %d, interface %d block_shift %d total_blocks %d" \
+ # % (address_cycle, ecc_strength, interface, block_shift, total_blocks)
+
+ # step1: generate nand header info #
+ header = "BOOTLOADER!" + '\0'
+ header += "V006"
+ header += "NFIINFO" + '\0'
+ # nfi_info #
+ header += struct.pack("H", interface)
+ header += struct.pack("H", page_size)
+ header += struct.pack("H", address_cycle)
+ header += struct.pack("H", spare_size)
+ header += struct.pack("H", page_per_block)
+ header += struct.pack("H", total_blocks)
+ header += struct.pack("H", page_shift)
+ header += struct.pack("H", block_shift)
+ # pad mlc control #
+ header += '\0' * 20
+ # pad tlc control #
+ header += '\0' * 3
+ header += struct.pack("B", 1) #b_Randomizer_En
+ header += '\0' * 14
+ # pad dummy #
+ header += '\0' * 2
+ # reserved #
+ header += '\0' * 32
+ # calculate header ecc parity #
+ header_size = 112
+ ecc_level = 80
+ ecc = ecc_bch.bch_enc_14(header, header_size, ecc_level)
+ header += ecc
+ # pad 4B dummy #
+ header += '\0' * 4 # pad 4 bytes to align total 256 bytes
+ # double nfb header #
+ header += header
+ # pad page size align dummy data #
+ header += '\0' * (page_size - 512) # fill the nand information to whole page, since it occupy one page
+
+ # step2: generate brlyt #
+ header += "BRLYT" + ('\0' * 3)
+ brlyt_version = 1
+ header += struct.pack("I", brlyt_version)
+ boot_region_addr = preloader_start_addr
+ header += struct.pack("I", boot_region_addr)
+ main_region_addr = boot_region_addr + (4 * page_per_block) # avoid if have bad block, so remain 4 blocks. need the same as partition_nand.xml
+ header += struct.pack("I", main_region_addr)
+ bl_desc_magic = 0x42424242
+ header += struct.pack("I", bl_desc_magic)
+ bl_desc_dev = 0x2
+ header += struct.pack("H", bl_desc_dev)
+ bl_desc_type = 0x1
+ header += struct.pack("H", bl_desc_type)
+ header += struct.pack("I", boot_region_addr)
+ header += struct.pack("I", main_region_addr)
+ bl_desc_attribute = 1
+ header += struct.pack("I", bl_desc_attribute)
+ # pad 7 descripters #
+ header += '\0' * 7 * 20
+ # pad page size align dummy data #
+ header += '\0' * (page_size - 180)
+
+ # step3: pad dummy data till GPT LBA #
+ # let us have an agreement that GPT alwasy be at LBA 128 for SLC NAND #
+ # should be the same LBA in lk and kernel to find GPT #
+ gpt_lba = 128
+ header += '\0' * page_size * (gpt_lba - 2)
+
+ with open(out_image, "wb") as f:
+ f.write(header)
+
+ #return (vendor, fdm_size, fdmecc_size, ecc_strength, spare_size, page_size, pptableen, page_per_block)
+ return (vendor, 8, 8, ecc_strength, spare_size, page_size, 0, page_per_block)
+
+def main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('nand_name', help = 'nand device name')
+ parser.add_argument('preloader_start_addr', help = 'preloader start address in page unit')
+ parser.add_argument('out_image', help = 'the output header file')
+ args = parser.parse_args()
+ preloader_start_addr = int(args.preloader_start_addr)
+
+ # generate nand device header #
+ gen_header(args.nand_name, preloader_start_addr, args.out_image)
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/src/bsp/scatter/tools/nand-utils/gen_nand_header_v14.py b/src/bsp/scatter/tools/nand-utils/gen_nand_header_v14.py
new file mode 100644
index 0000000..2abf043
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/gen_nand_header_v14.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+
+import ecc_bch
+import sys
+import os
+import struct
+import argparse
+
+def gen_header(nand_name, out_image):
+ """ device info:
+ name interface pagesize cycle sparesize pageperblock total_blocks nand_cfg accon fdmecc_size ecc_fdm plane_sel_poi
+ """
+ with open(os.getcwd() + "/tools/nand-utils/nand_device_list_v14.txt", "r") as f:
+ found = 0
+ for l in f:
+ s = l.split()
+ if s[0] == nand_name:
+ found = 1
+ interface = eval(s[1])
+ page_size = int(s[2])
+ address_cycle = int(s[3])
+ spare_size = int(s[4])
+ page_per_block = int(s[5])
+ total_blocks = int(s[6])
+ nand_cfg = int(s[7], 16)
+ accon = int(s[8])
+ fdmecc_size = int(s[9])
+ ecc_fdm = int(s[10])
+ plane_sel_poi = int(s[11])
+
+ if not found:
+ raise KeyError("not support " + nand_name)
+
+ # step1: generate nand header info #
+ header = "BOOTLOADER!" + '\0'
+ header += "V006"
+ header += struct.pack("H", interface)
+ header += struct.pack("H", page_size)
+ header += struct.pack("H", address_cycle)
+ header += struct.pack("H", spare_size)
+ header += struct.pack("H", page_per_block)
+ header += struct.pack("H", total_blocks)
+ header += struct.pack("I", nand_cfg)
+ header += '\0' * 8
+ header += struct.pack("I", accon)
+ header += '\0' * 8
+
+ bl_start = 1
+ bl_end = 255
+ header += struct.pack("BBHII", fdmecc_size, ecc_fdm, plane_sel_poi, bl_start,\
+ bl_end)
+ #16 dummy bytes
+ header += '\0' * 16
+ # calculate header ecc parity #
+ ecc_level = 24
+ header_size = len(header)
+ ecc = ecc_bch.bch_enc_14(header, header_size, ecc_level)
+ header += ecc
+ header += '\0' * (128 - len(header))
+ # double nfb header #
+ header += header
+
+ with open(out_image, "wb") as f:
+ f.write(header)
+
+def main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('nand_name', help = 'nand device name')
+ parser.add_argument('out_image', help = 'the output header file')
+ args = parser.parse_args()
+
+ # generate nand device header #
+ gen_header(args.nand_name, args.out_image)
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/src/bsp/scatter/tools/nand-utils/gen_nand_header_v4.py b/src/bsp/scatter/tools/nand-utils/gen_nand_header_v4.py
new file mode 100644
index 0000000..e6ef349
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/gen_nand_header_v4.py
@@ -0,0 +1,227 @@
+#!/usr/bin/env python3
+
+import ecc_bch
+import sys
+import os
+import struct
+import argparse
+import pp_tbl
+
+def calc_bcc(buf, buf_len):
+ raw = bytearray(buf)
+ bcc = 0
+
+ for i in range(buf_len):
+ bcc ^= raw[i]
+
+ return bcc
+
+def gen_header(nand_name):
+ print ("NAND: %s" % (nand_name))
+ with open(os.getcwd() + "/tools/nand-utils/nand_device_list_v4.txt", "r") as f:
+ found = 0
+ info_valid = 0
+ nfi_valid = 0
+ mag_valid = 0
+ pp_valid = 0
+ for l in f:
+ s = l.split()
+ if s[0] == nand_name:
+ found = 1
+ nfi_start_idx = 0
+ mag_start_idx = 0
+
+ enable_header = int(s[1])
+ if enable_header == 0:
+ break
+ info_valid = int(s[2])
+ nfi_valid = int(s[3])
+ mag_valid = int(s[4])
+ pp_valid = int(s[5])
+ pp_type = s[6]
+ if info_valid == 1:
+ nand_type = int(s[7])
+ io_width = int(s[8])
+ addr_cycle = int(s[9])
+ target_num = int(s[10])
+ lun_num = int(s[11])
+ plane_num = int(s[12])
+ program_order_type = int(s[13])
+ address_table_type = int(s[14])
+ bad_block_type = int(s[15])
+ read_retry_type = int(s[16])
+ interface_type = int(s[17])
+ sdr_timing_type = int(s[18])
+ ddr_timing_type = int(s[19])
+ block_num = int(s[20])
+ block_size = int(s[21])
+ page_size = int(s[22])
+ spare_size = int(s[23])
+ mode_type = int(s[24])
+ slc_pe_cycle = int(s[25])
+ slc_ecc_required = int(s[26])
+ slc_bitflip_thres = int(s[27])
+ xlc_pe_cycle = int(s[28])
+ xlc_ecc_required = int(s[29])
+ xlc_bitflip_thres = int(s[30])
+ nfi_start_idx = 31
+ mag_start_idx = 31
+ if nand_type == 0:
+ nfc_format = 1
+ rand_en = 0
+ else:
+ nfc_format = 0
+ rand_en = 1
+ if nfi_valid == 1:
+ dqs_dly_sel = int(s[nfi_start_idx])
+ dqs_dly_mux = int(s[nfi_start_idx + 1])
+ rd_dqs_ddr_timing = int(s[nfi_start_idx + 2])
+ mag_start_idx = nfi_start_idx + 3
+ if mag_valid == 1:
+ bm_type = int(s[mag_start_idx])
+ dma_en = int(s[mag_start_idx + 1])
+ ddr_en = int(s[mag_start_idx + 2])
+ nfc_format = int(s[mag_start_idx + 3])
+ break #found
+
+ if not found:
+ raise KeyError("not support " + nand_name)
+
+ # nand header is total 440B include ecc parity 140B #
+ header_size = 300
+ info_size = 64
+ setting_size = 16
+ mag_size = 8
+ pptbl_size = 128
+ dummy_size = header_size - 4 - info_size - setting_size - mag_size - pptbl_size - 3
+
+ header = b"NAND"
+
+ # struct nand_info #
+ if info_valid == 0:
+ header += '\x00' * info_size
+ bcc_chip = '\xff'
+ else:
+ info_buf = b"INFO"
+ info_buf += struct.pack("B", nand_type)
+ info_buf += struct.pack("B", io_width)
+ info_buf += struct.pack("B", addr_cycle)
+ info_buf += struct.pack("B", target_num)
+ info_buf += struct.pack("B", lun_num)
+ info_buf += struct.pack("B", plane_num)
+ info_buf += struct.pack("B", program_order_type)
+ info_buf += struct.pack("B", address_table_type)
+ info_buf += struct.pack("B", bad_block_type)
+ info_buf += struct.pack("B", read_retry_type)
+ info_buf += struct.pack("B", interface_type)
+ info_buf += struct.pack("B", sdr_timing_type)
+ info_buf += struct.pack("B", ddr_timing_type)
+ info_buf += b'\xff' * 3
+ info_buf += struct.pack("I", block_num)
+ info_buf += struct.pack("I", block_size)
+ info_buf += struct.pack("I", page_size)
+ info_buf += struct.pack("I", spare_size)
+ info_buf += struct.pack("I", mode_type)
+ info_buf += struct.pack("I", slc_pe_cycle)
+ info_buf += struct.pack("I", slc_ecc_required)
+ info_buf += struct.pack("I", slc_bitflip_thres)
+ info_buf += struct.pack("I", xlc_pe_cycle)
+ info_buf += struct.pack("I", xlc_ecc_required)
+ info_buf += struct.pack("I", xlc_bitflip_thres)
+ header += info_buf
+ bcc_chip = calc_bcc(info_buf, info_size)
+ bcc_chip = struct.pack("B", bcc_chip)
+
+ # struct nfi_setting #
+ if nfi_valid == 0:
+ header += b'\x00' * setting_size
+ bcc_setting = b'\xff'
+ else:
+ setting_buf = "NFIS"
+ setting_buf += struct.pack("I", dqs_dly_sel)
+ setting_buf += struct.pack("I", dqs_dly_mux)
+ setting_buf += struct.pack("I", rd_dqs_ddr_timing)
+ header += setting_buf
+ bcc_setting = calc_bcc(setting_buf, setting_size)
+ bcc_setting = struct.pack("B", bcc_setting)
+
+ # struct nand_manage #
+ if mag_valid == 0:
+ header += b'\x00' * mag_size
+ bcc_mag = b'\xff'
+ else:
+ mag_buf = "MANG"
+ mag_buf += struct.pack("B", bm_type)
+ mag_buf += struct.pack("B", dma_en)
+ mag_buf += struct.pack("B", ddr_en)
+ mag_buf += struct.pack("B", nfc_format)
+ header += mag_buf
+ bcc_mag = calc_bcc(mag_buf, mag_size)
+ bcc_mag = struct.pack("B", bcc_mag)
+
+ # bcc code #
+ header += bcc_chip
+ header += bcc_setting
+ header += bcc_mag
+
+ # pad dummy byte #
+ header += b'\xff' * dummy_size
+
+ if pp_valid == 1:
+ # add pptable #
+ if pp_type == 'TSB':
+ header += str(bytearray(pp_tbl.TSB_PP))
+ else:
+ raise KeyError(" no %s pptable " % vendor)
+ else:
+ header += b'\xff' * pptbl_size
+
+ # calculate header ecc parity #
+ ecc_level = 80
+ ecc = ecc_bch.bch_enc_14(header, header_size, ecc_level)
+ header += ecc
+
+ header_file = nand_name + '_header.bin'
+ with open(header_file, "wb") as f:
+ f.write(header)
+
+ if info_valid == 0:
+ print ("NAND info invalid, return!")
+ return
+
+ # feedback ecc & randomizer generateion info
+ fdm_size = spare_size / (page_size / 1024) - (xlc_ecc_required * 14 + 7) / 8
+ if fdm_size > 8:
+ fdm_size = 8
+ if nfc_format == 0:
+ fdmecc_size = fdm_size
+ bad_swap = 0
+ else:
+ fdmecc_size = 1
+ bad_swap = 1
+ ppb = block_size / page_size
+
+ return (pp_type, fdm_size, fdmecc_size, xlc_ecc_required, spare_size, page_size, pp_valid, ppb, bad_swap, rand_en)
+
+def main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('nand_name', help = 'nand device name')
+ parser.add_argument('gpt_image', help = 'pmbr + gpt entry image ')
+ args = parser.parse_args()
+
+ # generate nand device header #
+ gen_header(args.nand_name)
+
+ # pad nand header #
+ with open(args.nand_name + '_header.bin', "rb") as f_h:
+ h_buf = f_h.read()
+ with open(args.gpt_image, "rb+") as f_g:
+ f_g.seek(440, 0)
+ h_buf = h_buf + f_g.read()
+ f_g.seek(0, 0)
+ f_g.write(h_buf)
+
+ os.remove(args.nand_name + '_header.bin')
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/src/bsp/scatter/tools/nand-utils/gen_storage_image.py b/src/bsp/scatter/tools/nand-utils/gen_storage_image.py
new file mode 100644
index 0000000..cd0e2ec
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/gen_storage_image.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+
+import argparse
+import sys
+import os
+import math
+import pp_tbl
+from gen_nand_header import gen_header
+from pad_ecc_by_sector import pad_ecc
+from randomizer import randomizer
+
+def main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('nand_name', help = 'nand device name')
+ parser.add_argument('in_image', help = 'raw input image which has GPT')
+ parser.add_argument('out_image', help = 'the output storage image ')
+ parser.add_argument('rand_en', help = 'if randomizer is enabled')
+ args = parser.parse_args()
+
+ rand_en = int(args.rand_en)
+
+ header_file = args.nand_name + '_header.bin'
+ header_size = 440
+
+ with open(args.in_image, "rb") as f_in:
+ f_in.seek(header_size, 0)
+ in_data = f_in.read()
+
+ (vendor, fdm_size, fdmecc_size, ecc_strength, spare_size, page_size, ppen, ppb) = gen_header(args.nand_name)
+ with open(header_file, "rb+") as hf:
+ hf_data = hf.read()
+ hf.write(in_data)
+
+ ecc_file = args.out_image
+ rand_file = args.out_image
+ if rand_en == 1:
+ ecc_file = args.nand_name + '_ecc.bin'
+ if ppen == 1:
+ paired = raw_input("insert empty paired page ? Y/y or N/n ")
+ if paired in ['Y', 'y']:
+ if rand_en == 1:
+ rand_file = args.nand_name + '_rand.bin'
+ else:
+ ecc_file = args.nand_name + '_ecc.bin'
+ sector_size = 1024 if page_size > 512 else 512
+ sector_spare_size = spare_size / (page_size / sector_size)
+ pad_ecc(header_file, ecc_file, sector_size, fdm_size, fdmecc_size, ecc_strength, sector_spare_size, page_size, 1)
+
+ if rand_en == 1:
+ randomizer(ecc_file, rand_file, "SS", 1, page_size, spare_size, sector_size, ppb, ppen, vendor)
+
+ # insert empty paired page #
+ if ppen == 1 and paired in ['Y', 'y']:
+ if rand_en == 1:
+ pp_file = rand_file
+ else:
+ pp_file = ecc_file
+ if vendor == 'TSB':
+ PP = pp_tbl.TSB_PP
+ else:
+ raise Exception("unsupport %s pp table " % vendor)
+ f_pp = open(pp_file, "rb")
+ f_out = open(args.out_image, "wb")
+
+ if (os.path.getsize(header_file) % page_size) != 0:
+ raise Exception("input image size is not page size aligned")
+ page_number = os.path.getsize(header_file) / page_size
+ block_number = int(math.ceil(float(page_number) / (ppb / 2)))
+ print "page num %d block num %d" % (page_number, block_number)
+ for i in range(ppb * block_number):
+ if page_number > 0 and (i % ppb) in PP:
+ f_out.write(f_pp.read(page_size + spare_size))
+ page_number -= 1
+ else:
+ f_out.write('\xff' * (page_size + spare_size))
+ f_pp.close()
+ f_out.close()
+ # remove temp files #
+ os.remove(pp_file)
+
+ if rand_en == 1:
+ os.remove(ecc_file)
+
+ os.remove(header_file)
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/src/bsp/scatter/tools/nand-utils/gpt_analyser.py b/src/bsp/scatter/tools/nand-utils/gpt_analyser.py
new file mode 100755
index 0000000..296c04b
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/gpt_analyser.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+
+#to do:
+#extract pmbr + gpt header + gpt entry
+#add txt file output
+#add picture file output
+
+import sys
+import os
+
+def main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('in_image', help = 'input image with GPT')
+ args = parser.parse_args()
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/src/bsp/scatter/tools/nand-utils/nand_device_list.txt b/src/bsp/scatter/tools/nand-utils/nand_device_list.txt
new file mode 100644
index 0000000..bf40f3c
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/nand_device_list.txt
@@ -0,0 +1,6 @@
+Attention: use SPACE to input next parameter
+name vendor totalsize(MB) pagesize(B) sparesize(B) pageperblock cycle eccstrength interface acccon acccon1 dqsdlymux dqsdlyctrl nfidlyctrl pptableenable lbasize fastclock usedma fdmsize fdmeccsize strobesel
+F59D4G81A-45TG-18V ESMT 512 2048 64 64 5 4 1 0x10400111 0 0 0 0 0 0 0 0 8 1 0
+MT29F4G08ABAEAWP MCN 512 4096 224 64 5 16 1 0x10400111 0 0 0 0 0 0 0 0 8 1 0
+TH58TFG8DDLAB4C TSB 4096 16384 1280 256 5 40 2 0x22005010 0x01010200 0 0 0 1 0 0 0 8 1 0
+MT29F16G08ADBCA MCN 2048 4096 224 64 5 24 1 0x10404011 0 0 0 0 0 0 7 1 8 1 0
diff --git a/src/bsp/scatter/tools/nand-utils/nand_device_list_mt2731.txt b/src/bsp/scatter/tools/nand-utils/nand_device_list_mt2731.txt
new file mode 100644
index 0000000..c343093
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/nand_device_list_mt2731.txt
@@ -0,0 +1,10 @@
+Attention: use SPACE to input next parameter
+name vendor totalsize(MB) pagesize(B) sparesize(B) pageperblock cycle eccstrength interface acccon acccon1 dqsdlymux dqsdlyctrl nfidlyctrl pptableenable lbasize fastclock usedma fdmsize fdmeccsize strobesel
+F59D4G81A-45TG-18V ESMT 512 2048 64 64 5 4 1 0x10400111 0 0 0 0 0 0 0 0 8 1 0
+MT29F4G08ABAEAWP MCN 512 4096 224 64 5 16 1 0x10400111 0 0 0 0 0 0 0 0 8 1 0
+TH58TFG8DDLAB4C TSB 4096 16384 1280 256 5 40 2 0x22005010 0x01010200 0 0 0 1 0 0 0 8 1 0
+MT29F16G08ADBCA MCN 2048 4096 224 64 5 24 1 0x10404011 0 0 0 0 0 0 7 1 8 1 0
+MT29F4G08ABBFAH MCN 512 4096 256 64 5 12 1 0x10400111 0 0 0 0 0 0 0 0 8 1 0
+MT29F4G08ABBDA MCN 512 2048 64 64 5 4 1 0x10404012 0 0 0 0 0 0 0 0 8 1 0
+MT29F4G08ABBFA MCN 512 4096 256 64 5 12 1 0x10400111 0 0 0 0 0 0 0 0 8 1 0
+MT29F8G08ADBFA MCN 1024 4096 256 64 5 12 1 0x10400111 0 0 0 0 0 0 0 0 8 1 0
diff --git a/src/bsp/scatter/tools/nand-utils/nand_device_list_mt2735_hsm.txt b/src/bsp/scatter/tools/nand-utils/nand_device_list_mt2735_hsm.txt
new file mode 100644
index 0000000..0354dce
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/nand_device_list_mt2735_hsm.txt
@@ -0,0 +1,3 @@
+Attention: use SPACE to input next parameter
+name vendor pagesize(B) sparesize(B) pageperblock blocks cycle
+MT29F8G08ABBCAH4 Micron 4096 224 64 4096 5
diff --git a/src/bsp/scatter/tools/nand-utils/nand_device_list_v11.txt b/src/bsp/scatter/tools/nand-utils/nand_device_list_v11.txt
new file mode 100755
index 0000000..c3a966e
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/nand_device_list_v11.txt
@@ -0,0 +1,10 @@
+Attention: use SPACE to input next parameter
+name vendor interface pagesize(B) cycle sparesize(B) pageperblock total_blocks page_shift block_shift ecc_strength
+MX30LF1G18AC MXIC 0x100 2048 5 64 64 1024 16 22 12
+TC58NVG0S3HTA00 TOSHIBA 0x100 2048 5 128 64 1024 16 22 32
+MT29F2G08ABAEA MICRON 0x100 2048 5 64 64 2048 16 22 12
+MT29F2G08ABAGA MICRON 0x100 2048 5 128 64 2048 16 22 32
+MX30LF4G18AC MXIC 0x100 2048 5 64 64 4096 16 22 12
+MT29F4G08ABAEA MICRON 0x100 4096 5 224 64 2048 16 22 24
+TC58NVG2S0HTA00 TOSHIBA 0x100 4096 5 256 64 2048 16 22 32
+TC58NVG3S0HTA00 TOSHIBA 0x100 4096 5 256 64 4096 16 22 32
\ No newline at end of file
diff --git a/src/bsp/scatter/tools/nand-utils/nand_device_list_v12.txt b/src/bsp/scatter/tools/nand-utils/nand_device_list_v12.txt
new file mode 100644
index 0000000..7b24c12
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/nand_device_list_v12.txt
@@ -0,0 +1,6 @@
+Attention: use SPACE to input next parameter
+name interface pagesize(B) cycle sparesize(B) pageperblock total_blocks ecc_strength
+MT29F4G01ABAFDWB 0x100 4096 5 256 64 2048 12
+MX30LF4G18AC 0x100 2048 5 64 64 4096 12
+TC58NVG2S0HTA00 0x100 4096 5 256 64 2048 24
+COMMONSLC 0x100 0 5 0 0 0 0
diff --git a/src/bsp/scatter/tools/nand-utils/nand_device_list_v13.txt b/src/bsp/scatter/tools/nand-utils/nand_device_list_v13.txt
new file mode 100755
index 0000000..b73c660
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/nand_device_list_v13.txt
@@ -0,0 +1,3 @@
+Attention: use SPACE to input next parameter
+name vendor interface pagesize(B) cycle sparesize(B) pageperblock total_blocks page_shift block_shift ecc_strength
+NM1482KSLAXCL-3B TOSHIBA 0x100 4096 5 256 64 2048 16 22 32
diff --git a/src/bsp/scatter/tools/nand-utils/nand_device_list_v14.txt b/src/bsp/scatter/tools/nand-utils/nand_device_list_v14.txt
new file mode 100755
index 0000000..7fda451
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/nand_device_list_v14.txt
@@ -0,0 +1,8 @@
+Attention: use SPACE to input next parameter
+name interface pagesize cycle sparesize pageperblock total_blocks nand_cfg accon fdmecc_size ecc_fdm plane_sel_poi
+pnand_4k_256 0x100 4096 5 256 64 2048 0x0 0 1 24 0
+pnand_2k_64 0x100 2048 5 64 64 2048 0x0 0 1 12 0
+snand_4k_256 0x100 4096 5 256 64 2048 0x0 0 1 8 12
+snand_2k_64 0x100 2048 5 64 64 2048 0x0 0 1 8 12
+COMMONSLC 0x100 4096 5 256 64 2048 0x2 0 1 24 0
+COMMONSPI 0x100 4096 5 256 64 2048 0x2 0 1 8 12
\ No newline at end of file
diff --git a/src/bsp/scatter/tools/nand-utils/nand_device_list_v4.txt b/src/bsp/scatter/tools/nand-utils/nand_device_list_v4.txt
new file mode 100644
index 0000000..036995f
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/nand_device_list_v4.txt
@@ -0,0 +1,16 @@
+#Attention: use SPACE to input next parameter
+#name enable info_valid nfi_valid mag_valid pp_valid pp_type <info> nand_type io_width addr_cycle
+#target_num lun_num plane_num program_order_type address_table_type bad_block_type
+#read_retry_type interface_type sdr_timing_type ddr_timing_type block_num
+#block_size page_size spare_size mode_type slc_pe_cycle slc_ecc_required
+#slc_bitflip_thres xlc_pe_cycle xlc_ecc_required xlc_bitflip_thres </info>
+#<nfi> dqs_dly_sel dqs_dly_mux rd_dqs_ddr_timing </nfi> <mag> bm_type dma_en
+#ddr_en nfc_format </mag>
+NAND_COMMON 0
+W29N08GZSIBA 1 1 0 0 0 NONE 0 0 5 1 1 1 0 0 0 0 0 7 0 8192 131072 2048 64 0 50000 12 8 500000 12 8
+SDTNSIAMA016G 1 1 0 0 0 NONE 2 0 5 1 1 2 1 2 2 12 2 0 0 1446 6291456 16384 1952 1 500 68 46 50000 68 46
+SDTNSGAMA008G 1 1 0 0 0 NONE 1 0 5 1 1 2 0 5 2 5 2 9 4 1074 4194304 16384 1280 1 30000 40 30 3000 40 30
+TC58TEG7THLTA00 1 1 0 0 0 NONE 2 0 5 1 1 2 1 2 0 13 2 0 0 1446 6291456 16384 1952 1 500 68 46 50000 68 46
+TC58TFG7DDLTA0D 1 1 0 0 0 NONE 1 0 5 1 1 2 0 5 0 7 2 9 4 2106 4194304 16384 1280 8 30000 40 30 3000 40 30
+MT29F4G08ABAEAWP 1 1 0 0 0 NONE 0 0 5 1 1 2 0 0 0 0 0 8 0 1024 262144 4096 224 0 50000 24 18 50000 24 18
+TC58TEG6TCKTA00 1 1 0 0 0 NONE 2 0 5 1 1 1 1 3 0 13 2 0 0 2092 4227072 16384 1952 1 30000 60 45 3000 60 45
diff --git a/src/bsp/scatter/tools/nand-utils/pad_dummy_data.py b/src/bsp/scatter/tools/nand-utils/pad_dummy_data.py
new file mode 100755
index 0000000..ccfba4b
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/pad_dummy_data.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+
+import argparse
+import sys
+import os
+
+def padding(data, size):
+ return data + '\xff' * (size - len(data))
+
+def main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('in_image', help = 'raw input image which has GPT')
+ parser.add_argument('part_size', help = 'partition size')
+ args = parser.parse_args()
+ part_size = int(args.part_size, 16)
+ file_len = os.path.getsize(args.in_image)
+
+ with open(args.in_image, "rb+") as f:
+ f.read()
+ f.write('\xff' * (part_size - file_len))
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/src/bsp/scatter/tools/nand-utils/pad_dummy_data.sh b/src/bsp/scatter/tools/nand-utils/pad_dummy_data.sh
new file mode 100755
index 0000000..bea14d4
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/pad_dummy_data.sh
@@ -0,0 +1,11 @@
+#! /bin/sh
+
+python -B pad_dummy_data.py ../build_imags/MBR_NAND_ECC 0x84000
+python -B pad_dummy_data.py ../build_imags/lk_ecc.img 0x84000
+python -B pad_dummy_data.py ../build_imags/boot_ecc.img 0x1080000
+python -B pad_dummy_data.py ../build_imags/tz_ecc.img 0x42000
+
+cat ../build_imags/MBR_NAND_ECC >> ../build_imags/burner.img
+cat ../build_imags/lk_ecc.img >> ../build_imags/burner.img
+cat ../build_imags/boot_ecc.img >> ../build_imags/burner.img
+cat ../build_imags/tz_ecc.img >> ../build_imags/burner.img
diff --git a/src/bsp/scatter/tools/nand-utils/pad_dummy_data_by_partition.py b/src/bsp/scatter/tools/nand-utils/pad_dummy_data_by_partition.py
new file mode 100755
index 0000000..1d11424
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/pad_dummy_data_by_partition.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+
+import argparse
+import sys
+import os
+import math
+import pp_tbl
+import gen_nand_header
+import gen_nand_header_v11
+from pad_ecc_by_sector import pad_ecc
+
+def padding(data, size):
+ return data + '\xff' * (size - len(data))
+
+def main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('nand_name', help = 'nand device name')
+ parser.add_argument('in_image', help = 'raw input image')
+ parser.add_argument('part_size', help = 'partition size')
+ parser.add_argument('version', help= 'nand header version')
+ args = parser.parse_args()
+ version = float(args.version)
+
+ if version == 2.0:
+ (vendor, fdm_size, fdmecc_size, ecc_strength, spare_size, page_size, ppen, ppb) = gen_nand_header.gen_header(args.nand_name)
+ elif version == 1.1:
+ (vendor, fdm_size, fdmecc_size, ecc_strength, spare_size, page_size, ppen, ppb) = gen_nand_header_v11.gen_header(args.nand_name, 192, args.nand_name + '_header.bin')
+
+ # input image page size alignment #
+ file_len = os.path.getsize(args.in_image)
+ pages = int(int(args.part_size) / page_size)
+ part_size = pages * (page_size + spare_size)
+ with open(args.in_image, "rb+") as f:
+ f.read()
+ f.seek(0, 2)
+ f.write('\xff' * (part_size - file_len))
+
+ os.remove(args.nand_name + '_header.bin')
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/src/bsp/scatter/tools/nand-utils/pad_ecc_by_sector.py b/src/bsp/scatter/tools/nand-utils/pad_ecc_by_sector.py
new file mode 100755
index 0000000..ef91095
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/pad_ecc_by_sector.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+
+import argparse
+import sys
+import os
+import math
+import ecc_bch
+
+def pad_ecc(in_image, out_image, sector_size, fdm_size, fdmecc_size, ecc_level, spare_size, page_size, bad_swap):
+ # file size check #
+ file_len = os.path.getsize(in_image)
+ if (file_len % sector_size) != 0:
+ raise Exception("input image size is not sector size aligned")
+ sector_num = file_len / sector_size
+
+ # calculate parity byte number #
+ parity_byte = int(math.ceil(float(ecc_level) * 14 / 8))
+
+ # bad block mark control setting #
+ if bad_swap != 0:
+ bad_sec = page_size / (sector_size + spare_size)
+ bad_pos = page_size % (sector_size + spare_size)
+ sec_per_page = page_size / sector_size
+ print "bad sector %d, bad position %d, sector number per page %d " \
+ % (bad_sec, bad_pos, sec_per_page)
+
+ f_in = open(in_image, "rb")
+ f_out = open(out_image, "wb")
+
+ for i in range(sector_num):
+ percent = float(i) / float(sector_num) * 100
+ sys.stdout.writelines("%.1f"%percent)
+ sys.stdout.writelines("%\r")
+ sys.stdout.flush();
+ f_in.seek(sector_size * i, 0)
+ f_out.seek((sector_size + spare_size) * i, 0)
+ sector_data = f_in.read(sector_size)
+ sector_data += '\xff' * fdmecc_size
+ # bad mark swap #
+ if bad_swap != 0:
+ if (i % sec_per_page) == bad_sec:
+ temp_buf = bytearray(sector_data)
+ temp_byte = temp_buf[bad_pos]
+ temp_buf[bad_pos] = temp_buf[sector_size]
+ temp_buf[sector_size] = temp_byte
+ sector_data = str(temp_buf)
+ parity_data = ecc_bch.bch_enc_14(sector_data, sector_size + fdmecc_size, ecc_level)
+ sector_data += '\xff' * (fdm_size - fdmecc_size)
+ sector_data += parity_data
+ sector_data += '\xff' * (spare_size - fdm_size - parity_byte)
+ f_out.write(sector_data)
+
+ f_in.close()
+ f_out.close()
+
+def main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('in_image', help = 'raw input image')
+ parser.add_argument('out_image', help = 'ecc padded image')
+ parser.add_argument('sector_size', help = 'sector size')
+ parser.add_argument('fdm_size', help = 'FDM size')
+ parser.add_argument('fdmecc_size', help = 'FDM ECC size')
+ parser.add_argument('ecc_level', help = 'ECC level')
+ parser.add_argument('spare_size', help = 'spare size per sector')
+ parser.add_argument('page_size', help = 'page size')
+ parser.add_argument('bad_swap', help = 'whether do bad mark swap')
+ args = parser.parse_args()
+
+ sector_size = int(args.sector_size)
+ fdm_size = int(args.fdm_size)
+ fdmecc_size = int(args.fdmecc_size)
+ ecc_level = int(args.ecc_level)
+ spare_size = int(args.spare_size)
+ page_size = int(args.page_size)
+ parity_byte = int(math.ceil(float(ecc_level) * 14 / 8))
+ bad_swap = int(args.bad_swap)
+
+ print "secsize %d, fdmsz %d, fdmeccsz %d, lel %d, spare %d, parity_byte %d page size %d bad_swap %d" \
+ % (sector_size, fdm_size, fdmecc_size, ecc_level, spare_size, parity_byte, page_size, bad_swap)
+
+ pad_ecc(args.in_image, args.out_image, sector_size, fdm_size, fdmecc_size, ecc_level, spare_size, page_size, bad_swap)
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/src/bsp/scatter/tools/nand-utils/pp_tbl.py b/src/bsp/scatter/tools/nand-utils/pp_tbl.py
new file mode 100755
index 0000000..b5a5ecf
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/pp_tbl.py
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+
+TSB_PP = (
+ 0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29,
+ 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61,
+ 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93,
+ 95, 97, 99, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125,
+ 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157,
+ 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189,
+ 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221,
+ 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253)
+
+if __name__ == "__main__":
+ """ this file is used to define pair page table """
diff --git a/src/bsp/scatter/tools/nand-utils/randomizer.py b/src/bsp/scatter/tools/nand-utils/randomizer.py
new file mode 100755
index 0000000..b3fe76a
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/randomizer.py
@@ -0,0 +1,123 @@
+#!/usr/bin/env python
+
+import sys
+import os
+import argparse
+import pp_tbl
+
+SS_SEED = (
+ 0x576A, 0x05E8, 0x629D, 0x45A3, 0x649C, 0x4BF0, 0x2342, 0x272E,
+ 0x7358, 0x4FF3, 0x73EC, 0x5F70, 0x7A60, 0x1AD8, 0x3472, 0x3612,
+ 0x224F, 0x0454, 0x030E, 0x70A5, 0x7809, 0x2521, 0x484F, 0x5A2D,
+ 0x492A, 0x043D, 0x7F61, 0x3969, 0x517A, 0x3B42, 0x769D, 0x0647,
+ 0x7E2A, 0x1383, 0x49D9, 0x07B8, 0x2578, 0x4EEC, 0x4423, 0x352F,
+ 0x5B22, 0x72B9, 0x367B, 0x24B6, 0x7E8E, 0x2318, 0x6BD0, 0x5519,
+ 0x1783, 0x18A7, 0x7B6E, 0x7602, 0x4B7F, 0x3648, 0x2C53, 0x6B99,
+ 0x0C23, 0x67CF, 0x7E0E, 0x4D8C, 0x5079, 0x209D, 0x244A, 0x747B,
+ 0x350B, 0x0E4D, 0x7004, 0x6AC3, 0x7F3E, 0x21F5, 0x7A15, 0x2379,
+ 0x1517, 0x1ABA, 0x4E77, 0x15A1, 0x04FA, 0x2D61, 0x253A, 0x1302,
+ 0x1F63, 0x5AB3, 0x049A, 0x5AE8, 0x1CD7, 0x4A00, 0x30C8, 0x3247,
+ 0x729C, 0x5034, 0x2B0E, 0x57F2, 0x00E4, 0x575B, 0x6192, 0x38F8,
+ 0x2F6A, 0x0C14, 0x45FC, 0x41DF, 0x38DA, 0x7AE1, 0x7322, 0x62DF,
+ 0x5E39, 0x0E64, 0x6D85, 0x5951, 0x5937, 0x6281, 0x33A1, 0x6A32,
+ 0x3A5A, 0x2BAC, 0x743A, 0x5E74, 0x3B2E, 0x7EC7, 0x4FD2, 0x5D28,
+ 0x751F, 0x3EF8, 0x39B1, 0x4E49, 0x746B, 0x6EF6, 0x44BE, 0x6DB7)
+
+def fetch_seed(ran_type, seeds, idx):
+ if ran_type == "SS":
+ seed_page = seeds[idx % len(seeds)]
+ seed_page &= 0x7fff
+ key = seed_page
+ return (key, seed_page)
+ else:
+ pass
+
+def pn_gen(ran_type, src_len, key):
+ pn_buf = []
+ for i in range(src_len):
+ pn_buf.append(0)
+ if ran_type == "SS":
+ for j in range(8):
+ if bool(key & 0x4000) != bool(key & 0x2000):
+ key <<= 1
+ key &= 0x7ffe
+ key += 1
+ pn_buf[i] += 1 << j
+ else:
+ key <<= 1
+ key &= 0x7ffe
+ else:
+ pass
+ return (key, pn_buf)
+
+def randomizer(in_image, out_image, ran_type, sec_reseed, page_size, spare_size, sector_size, page_per_block, ppen, vendor):
+ # check file length #
+ if (os.path.getsize(in_image) % (page_size + spare_size)) != 0:
+ raise Exception("input image size is not page size aligned")
+
+ page_number = os.path.getsize(in_image) / (page_size + spare_size)
+ sec_per_page = page_size / sector_size
+ spare_per_sec = spare_size / sec_per_page
+
+ if ran_type == "SS":
+ seeds = SS_SEED
+ else:
+ raise Exception("not support %s randomizer" % ran_type)
+ if ppen == 1:
+ if vendor == 'TSB':
+ PP = pp_tbl.TSB_PP
+ else:
+ raise Exception("unsupport %s pp table " % vendor)
+
+ f_in = open(in_image, "rb")
+ f_out = open(out_image, "wb")
+
+ for i in range(page_number):
+ percent = float(i) / float(page_number) * 100
+ sys.stdout.writelines("%.1f"%percent)
+ sys.stdout.writelines("%\r")
+ sys.stdout.flush();
+ if ppen == 1:
+ seed_idx = PP[i % (page_per_block / 2)]
+ else:
+ seed_idx = i % page_per_block
+ (key, seed_page) = fetch_seed(ran_type, seeds, seed_idx)
+ for j in range(sec_per_page):
+ if sec_reseed:
+ key = seed_page
+
+ (key, pn_buf) = pn_gen(ran_type, sector_size + spare_per_sec, key)
+
+ in_buf = f_in.read(sector_size + spare_per_sec)
+ if not in_buf:
+ break
+ in_buf = bytearray(in_buf)
+
+ for k in range(sector_size + spare_per_sec):
+ in_buf[k] ^= pn_buf[k]
+
+ in_buf = str(in_buf)
+ f_out.write(in_buf)
+
+ f_in.close()
+ f_out.close()
+
+def main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('in_image', help = 'input image w/o random ')
+ parser.add_argument('out_image', help = 'output image w/ random ')
+ parser.add_argument('ran_type', default = 'SS', help = 'randomizer algorithm: SS or TSB')
+ parser.add_argument('sec_reseed', default = '1', help = 'whether reseed each sector')
+ parser.add_argument('page_size', help = 'page size')
+ parser.add_argument('spare_size', help = 'page spare size')
+ parser.add_argument('sector_size', help = 'sector size')
+ parser.add_argument('page_per_block', help = 'page per block number')
+ parser.add_argument('ppen', help = 'whether paired page is enabled')
+ parser.add_argument('vendor', help = 'vendor name')
+ args = parser.parse_args()
+
+ randomizer(args.in_image, args.out_image, args.ran_type, int(args.sec_reseed), int(args.page_size), \
+ int(args.spare_size), int(args.sector_size), int(args.page_per_block), int(args.ppen), args.vendor)
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/src/bsp/scatter/tools/nand-utils/start-burn.sh b/src/bsp/scatter/tools/nand-utils/start-burn.sh
new file mode 100755
index 0000000..29af331
--- /dev/null
+++ b/src/bsp/scatter/tools/nand-utils/start-burn.sh
@@ -0,0 +1,3 @@
+#! /bin/sh
+
+source ${PWD}/tools/nand-utils/gen-nand-burn-img.sh 1.1 MX30LF4G18AC ./project/aud8516-slc/partition_nand.xml
diff --git a/src/bsp/scatter/tools/partition_editor.html b/src/bsp/scatter/tools/partition_editor.html
new file mode 100644
index 0000000..0463856
--- /dev/null
+++ b/src/bsp/scatter/tools/partition_editor.html
@@ -0,0 +1,187 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
+<script>
+$(document).ready(function() {
+ let xmldoc = null;
+
+ function check() {
+ $("#out").text("");
+ let hdr = xmldoc.getElementsByTagName("partition")[0];
+ if (hdr == null) {
+ $("#out").text("Error: invlaid partition file\n");
+ return;
+ }
+
+ let entries = xmldoc.getElementsByTagName("entry");
+ for (let i=0; i<entries.length; i++) {
+ if (parseInt(entries[i].getAttribute("end")) >= parseInt(hdr.getAttribute("lba"))) {
+ let error_msg = "Error: end lba of " + entries[i].getAttribute("name") + " (" + entries[i].getAttribute("end") + ") >= total lba (" + hdr.getAttribute("lba") + ")\n\n";
+ $("#out").text(error_msg);
+ return;
+ }
+ }
+ }
+
+ function show() {
+ if (xmldoc == null)
+ return;
+
+ $("#total_size").text((eval($("#total_lba").val()) * eval($("#lbs").val()) / 1024 / 1024) + "MB");
+ $("#start_addr").text((eval($("#start_lba").val()) * eval($("#lbs").val()) / 1024 / 1024) + "MB");
+
+ let text = "";
+ text = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + xmldoc.documentElement.outerHTML;
+ text = text.replace(/>\s*</gm, ">\n<");
+ text = text.replace(/^<entry/gm, "\t<entry");
+ text = text.replace(/^\s+\n/gm, "");
+ $("#out").text($("#out").text() + text);
+ }
+
+ function init_editor() {
+ if (xmldoc == null)
+ return;
+
+ let hdr = xmldoc.getElementsByTagName("partition")[0];
+ $("#total_lba").val(hdr.getAttribute("lba"));
+ if (hdr.getAttribute("lbs") != null)
+ $("#lbs").val(hdr.getAttribute("lbs"));
+ else
+ $("#lbs").val(512);
+
+ let entries = xmldoc.getElementsByTagName("entry");
+ $("#start_lba").val(entries[0].getAttribute("start"));
+
+ let text = "";
+ for (let i=0; i<entries.length; i++) {
+ let size = ((entries[i].getAttribute("end") - entries[i].getAttribute("start") + 1)*$("#lbs").val()/1024);
+ text += (entries[i].getAttribute("name") + " " + size + "\n");
+ }
+ $("#entry_editor").val(text);
+ }
+
+ function update_xml() {
+ if (xmldoc == null)
+ return;
+
+ let hdr = xmldoc.getElementsByTagName("partition")[0];
+ hdr.setAttribute("lba", eval($("#total_lba").val()));
+
+ if (eval($("#lbs").val()) == 512)
+ hdr.removeAttribute("lbs");
+ else
+ hdr.setAttribute("lbs", eval($("#lbs").val()));
+
+ let entries = xmldoc.getElementsByTagName("entry");
+ let entry_strs = $("#entry_editor").val().split("\n");
+
+ let entry_cnt = 0;
+ for (let i=0; i<entry_strs.length; i++) {
+ if (entry_strs[i] == "")
+ continue;
+
+ if (entry_cnt >= entries.length) {
+ let newEle = xmldoc.createElement("entry");
+ newEle.setAttribute("type", entries[entry_cnt-1].getAttribute("type"));
+ hdr.appendChild(newEle);
+ entries = xmldoc.getElementsByTagName("entry");
+ }
+
+ entry = entry_strs[i].trim().split(/\s+/);
+ if (entry.length < 2)
+ continue;
+ if (entry_cnt == 0)
+ entries[entry_cnt].setAttribute("start", eval($("#start_lba").val()));
+ else
+ entries[entry_cnt].setAttribute("start", parseInt(entries[entry_cnt-1].getAttribute("end")) + 1);
+ entries[entry_cnt].setAttribute("end", (parseInt(entries[entry_cnt].getAttribute("start")) + eval(entry[1])*1024/eval($("#lbs").val()) - 1));
+ entries[entry_cnt].setAttribute("name", entry[0]);
+ entry_cnt++;
+ }
+
+ for (; entry_cnt < entries.length;) {
+ hdr.removeChild(entries[entry_cnt]);
+ entries = xmldoc.getElementsByTagName("entry");
+ }
+ }
+
+ $("#partition").change(function() {
+ let reader = new FileReader();
+ reader.onload = function() {
+ let parser = new DOMParser();
+ xmldoc = parser.parseFromString(reader.result, "application/xml");
+ init_editor();
+ check();
+ show();
+ };
+ reader.readAsText($("#partition")[0].files[0]);
+ });
+
+ $(":text,#entry_editor").keyup(function(){
+ update_xml();
+ check();
+ show();
+ });
+
+ $(":text").change(function(){
+ $(":focus").val(eval($(":focus").val()));
+ });
+
+ $("#entry_editor").change(function(){
+ let text = "";
+ let entry_strs = $("#entry_editor").val().split("\n");
+
+ for (let i=0; i<entry_strs.length; i++) {
+ if (entry_strs[i] == "")
+ continue;
+
+ let entry = entry_strs[i].trim().split(/\s+/);
+ if (entry.length < 2)
+ continue;
+
+ text += entry[0] + " " + eval(entry[1]) + "\n";
+ }
+
+ $("#entry_editor").val(text);
+ });
+
+});
+</script>
+</head>
+<body>
+<label>partition file:
+<input type=file id="partition">
+</label>
+<br>
+<hr>
+
+<label>lba size(lbs):
+<input type=text id="lbs">
+</label>
+<br>
+<label>total lba:
+<input type=text id="total_lba">
+</label>
+<label id="total_size">
+</label>
+<br>
+<hr>
+
+<label>start lba of the first partition:
+<input type=text id="start_lba">
+</label>
+<label id="start_addr">
+</label>
+<br>
+<label> name size(KB)
+</label>
+<br>
+<textarea id=entry_editor rows=20>
+</textarea>
+<br>
+<hr>
+
+<pre id="out"></pre>
+</body>
+</html>
diff --git a/src/bsp/scatter/tools/partition_editor.sh b/src/bsp/scatter/tools/partition_editor.sh
new file mode 100644
index 0000000..a01d283
--- /dev/null
+++ b/src/bsp/scatter/tools/partition_editor.sh
@@ -0,0 +1,106 @@
+#!/bin/bash
+
+if [ -z "$1" ]
+then
+ # Show the partition layout if no argument input
+ echo 'Usage:'
+ echo ' Show current Partitions layout:'
+ echo ' sh partition_editor.sh ${XMLFILE}'
+ exit 1
+fi
+
+if [ ! -f "$1" ]
+then
+ echo $1': File not exist!'
+ exit 1
+fi
+
+# Show the partition layout in better interactive mode
+tmpfile=".part.tmp"
+xmlfile=$1
+
+# LBS(size defined in tmp file is KB based)
+lbs_exist=`grep -o "\<lbs\>" ${xmlfile}`
+if [ -z $lbs_exist ]
+then
+ # For eMMC/Nor, only support 1024-aligned by now
+ lbs=1
+else
+ lbs=`awk -F'"' '/lbs=/{print $4}' ${xmlfile}`
+ lbs=$(($lbs/1024))
+fi
+# LBA(Total page number)
+lba_exist=`grep -o "\<lba\>" ${xmlfile}`
+if [ -z $lba_exist ]
+then
+ lba=0
+else
+ lba=`awk -F'"' '/lba=/{print $2}' ${xmlfile}`
+fi
+# reserved some blocks to store BBT
+reserved_exist=`grep -o "\<reserved\>" ${xmlfile}`
+if [ -z $reserved_exist ]
+then
+ reserved=0
+else
+ reserved=`awk -F'"' '/reserved=/{print $6}' ${xmlfile}`
+fi
+
+# Generate temporary file for interactive modifing and editing
+echo '*** You can delete/insert/modify(partname/size) partitions ***' > ${tmpfile}
+echo '*** Partition size must be ERASE_BLOCK_SIZE(define in Nand SPEC) aligned ***' >> ${tmpfile}
+echo '' >> ${tmpfile}
+echo 'Part_name Size(KB) Attr' >> ${tmpfile}
+`sed -nr 's/^.+start=\"(\w+)\"\s*end=\"(\w+)\"\s*(attributes=\"(\w+)\"\s*)?name=\"(\w+)\".+$/\5 \1 \2 \4/p' ${xmlfile} |
+ awk -v blk_size=$lbs '{printf "%-15s\t\t%d\t\t%s\n", $1, ($3-$2+1)*blk_size, $4}' >> ${tmpfile}`
+
+# Edit the partition layout via vim
+vim ${tmpfile}
+
+# The new partition layout
+part_name=(`awk '/^\w+\s+[0-9]+/{print $1}' ${tmpfile}`)
+part_size=(`awk '/^\w+\s+[0-9]+/{print $2}' ${tmpfile}`)
+part_attr=(`awk '/^\w+\s+[0-9]+/{if ($3 == "") print "-"; else print $3}' ${tmpfile}`)
+# How many elements in the array
+newcnt=$((${#part_name[@]}-1))
+# Generate the temporary xml file
+xmltmp=".xml.tmp"
+`cp -f ${xmlfile} ${xmltmp}`
+`sed -i '/name=/d' ${xmltmp}`
+# Modify the temporary xml file
+str1=' <entry type="{0FC63DAF-8483-4772-8E79-3D69D8477DE4}" start="'
+str2='" end="'
+strattr='" attributes="'
+str3='" name="'
+str4='" />'
+# first start address
+sa=`awk -F'"' '/name=/{print $4; exit;}' ${xmlfile}`
+# last end address
+lea=`sed -n '/name=/p' ${xmlfile} | sed -n '$p' | awk -F'"' '{print $6}'`
+for ((i=0; i<=$newcnt; i++)) {
+ len=${part_size[i]}
+ if [ $i -eq $newcnt ]
+ then
+ ea=$lea
+ if [ $lba -ne 0 -a $reserved -ne 0 ]
+ then
+ ea=$(($lba-$reserved-1))
+ fi
+ else
+ ea=$(($sa+$len/$lbs-1))
+ fi
+ name=${part_name[i]}
+ attr=${part_attr[i]}
+ if [ "$attr" == "-" ]
+ then
+ `sed -i '/<\/partition>/i \'"$str1$sa$str2$ea$str3$name$str4"'' ${xmltmp}`
+ else
+ `sed -i '/<\/partition>/i \'"$str1$sa$str2$ea$strattr$attr$str3$name$str4"'' ${xmltmp}`
+ fi
+ sa=$(($ea+1))
+}
+# Replace the xml file with the temp xml file, delete useless temporary files
+`cp -f ${xmltmp} ${xmlfile}`
+`rm -f ${xmltmp} ${tmpfile}`
+
+exit 0