rjw | 1f88458 | 2022-01-06 17:20:42 +0800 | [diff] [blame^] | 1 | #!/usr/bin/env python |
| 2 | |
| 3 | import ecc_bch |
| 4 | import sys |
| 5 | import os |
| 6 | import struct |
| 7 | import argparse |
| 8 | import pp_tbl |
| 9 | |
| 10 | def gen_header(nand_name): |
| 11 | """ device info: |
| 12 | name vendor totalsize(MB) pagesize(B) sparesize(B) pageperblock cycle eccstrength |
| 13 | interface acccon acccon1 dqsdlymux dqsdlyctrl nfidlyctrl pptableenable lbasize |
| 14 | fastclock usedma fdmsize fdmeccsize strobesel |
| 15 | """ |
| 16 | with open(os.getcwd() + "/tools/nand-utils/nand_device_list.txt", "r") as f: |
| 17 | found = 0 |
| 18 | for l in f: |
| 19 | s = l.split() |
| 20 | if s[0] == nand_name: |
| 21 | found = 1 |
| 22 | vendor = s[1] |
| 23 | total_size = int(s[2]) |
| 24 | page_size = int(s[3]) |
| 25 | #page_shift = len(bin(page_size).replace('0b','')) - 1 |
| 26 | page_shift = 16 if page_size > 512 else 8 |
| 27 | spare_size = int(s[4]) |
| 28 | page_per_block = int(s[5]) |
| 29 | address_cycle = int(s[6]) |
| 30 | ecc_strength = int(s[7]) |
| 31 | interface = int(s[8]) |
| 32 | acccon = eval(s[9]) |
| 33 | acccon1 = eval(s[10]) |
| 34 | dqsdlymux = int(s[11]) |
| 35 | dqsdlyctrl = eval(s[12]) |
| 36 | nfidlyctrl = eval(s[13]) |
| 37 | pptableen = int(s[14]) |
| 38 | lba_size = int(s[15]) |
| 39 | fast_clk = int(s[16]) |
| 40 | use_dma = int(s[17]) |
| 41 | fdm_size = int(s[18]) |
| 42 | fdmecc_size = int(s[19]) |
| 43 | strobesel = int(s[20]) |
| 44 | |
| 45 | # meaningless, just set pptableen value as BROM test code # |
| 46 | if not pptableen: |
| 47 | pptableen = 0xffff |
| 48 | |
| 49 | break |
| 50 | |
| 51 | if not found: |
| 52 | raise KeyError("not support " + nand_name) |
| 53 | |
| 54 | #print s[0] |
| 55 | #print "vendor %s, total size %d(MB) page size %d, page shift %d, spare size %d, page per block %d" \ |
| 56 | # % (vendor, total_size, page_size, page_shift, spare_size, page_per_block) |
| 57 | #print "address cycle %d, ecc strength %d, interface %d, acccon 0x%x, acccon1 0x%x" \ |
| 58 | # % (address_cycle, ecc_strength, interface, acccon, acccon1) |
| 59 | #print "dqsdlymux %d, dqsdlyctrl 0x%x, nfidlyctrl 0x%x, pptable enable %d, lba size %d" \ |
| 60 | # % (dqsdlymux, dqsdlyctrl, nfidlyctrl, pptableen, lba_size) |
| 61 | #print "fast clock enable %d, use dma %d, fdm size %d, fdmecc size %d" \ |
| 62 | # % (fast_clk, use_dma, fdm_size, fdmecc_size) |
| 63 | #raise KeyError("not support " + nand_name) |
| 64 | |
| 65 | # nand header is total 440B include ecc parity 140B # |
| 66 | header_size = 300 |
| 67 | pptbl_size = 128 |
| 68 | |
| 69 | header = "NANDCONFIG!" + '\0' |
| 70 | header += struct.pack("I", total_size) |
| 71 | header += struct.pack("H", page_size) |
| 72 | header += struct.pack("H", address_cycle) |
| 73 | header += struct.pack("H", spare_size) |
| 74 | header += struct.pack("H", interface) |
| 75 | header += struct.pack("I", ecc_strength) |
| 76 | header += struct.pack("H", page_per_block) |
| 77 | header += struct.pack("H", page_shift) |
| 78 | header += struct.pack("H", pptableen) |
| 79 | header += struct.pack("H", dqsdlymux) |
| 80 | header += struct.pack("I", dqsdlyctrl) |
| 81 | header += struct.pack("I", acccon) |
| 82 | header += struct.pack("I", acccon1) |
| 83 | header += struct.pack("I", nfidlyctrl) |
| 84 | header += struct.pack("H", lba_size) |
| 85 | header += struct.pack("H", fast_clk) |
| 86 | header += struct.pack("H", use_dma) |
| 87 | header += struct.pack("H", strobesel) |
| 88 | header += struct.pack("H", fdm_size) |
| 89 | header += struct.pack("H", fdmecc_size) |
| 90 | |
| 91 | # pad dummy byte # |
| 92 | header += '\x5a' * (header_size - len(header) - pptbl_size) |
| 93 | if pptableen == 1: |
| 94 | # add pptable # |
| 95 | if vendor == 'TSB': |
| 96 | header += str(bytearray(pp_tbl.TSB_PP)) |
| 97 | else: |
| 98 | raise KeyError(" no %s pptable " % vendor) |
| 99 | else: |
| 100 | header += '\xff' * pptbl_size |
| 101 | |
| 102 | # calculate header ecc parity # |
| 103 | header_size = 300 |
| 104 | ecc_level = 80 |
| 105 | ecc = ecc_bch.bch_enc_14(header, header_size, ecc_level) |
| 106 | header += ecc |
| 107 | |
| 108 | header_file = nand_name + '_header.bin' |
| 109 | with open(header_file, "wb") as f: |
| 110 | f.write(header) |
| 111 | |
| 112 | return (vendor, fdm_size, fdmecc_size, ecc_strength, spare_size, page_size, pptableen, page_per_block) |
| 113 | |
| 114 | def main(argv): |
| 115 | parser = argparse.ArgumentParser() |
| 116 | parser.add_argument('nand_name', help = 'nand device name') |
| 117 | parser.add_argument('gpt_image', help = 'pmbr + gpt entry image ') |
| 118 | args = parser.parse_args() |
| 119 | |
| 120 | # generate nand device header # |
| 121 | gen_header(args.nand_name) |
| 122 | |
| 123 | # pad nand header # |
| 124 | with open(args.nand_name + '_header.bin', "rb") as f_h: |
| 125 | h_buf = f_h.read() |
| 126 | with open(args.gpt_image, "rb+") as f_g: |
| 127 | f_g.seek(440, 0) |
| 128 | h_buf = h_buf + f_g.read() |
| 129 | f_g.seek(0, 0) |
| 130 | f_g.write(h_buf) |
| 131 | |
| 132 | os.remove(args.nand_name + '_header.bin') |
| 133 | |
| 134 | if __name__ == "__main__": |
| 135 | sys.exit(main(sys.argv)) |