partinfogen.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. #!/usr/bin/env python3
  2. # Copyright (C) 2018 RDA Technologies Limited and/or its affiliates("RDA").
  3. # All rights reserved.
  4. #
  5. # This software is supplied "AS IS" without any warranties.
  6. # RDA assumes no responsibility or liability for the use of the software,
  7. # conveys no license or title under any patent, copyright, or mask work
  8. # right to the product. RDA reserves the right to make changes in the
  9. # software without notification. RDA also make no representation or
  10. # warranty that such application will be suitable for the specified use
  11. # without further testing or modification.
  12. import argparse
  13. import sys
  14. import os
  15. import struct
  16. import json
  17. import binascii
  18. DESCRIPTION = """
  19. Generate binary partition information file from json.
  20. Configuration json format:
  21. * version: it should be 0x100 now
  22. * descriptions (array)
  23. * flash block device
  24. * type: FBD1 or FBD2
  25. * flash: SFL1 or SFL2 (for external flash)
  26. * name: device name, will be referred later
  27. * offset: flash offset
  28. * size: block device size in byte
  29. * erase_block: erase block size
  30. * logic_block: logic block size
  31. * bootloader_ignore: (optional) flag for ignore by bootloader
  32. * application_ignore: (optional) flag for ignore by application
  33. * bootloader_format_on_fail: (optional) flag for format on fail in bootloader
  34. * application_format_on_fail: (optional) flag for format on fail in application
  35. * SFFS file system
  36. * type: SFFS
  37. * device: block device or partition name
  38. * mount: mount point
  39. * reserve_block: (optional) safe file reserved block count
  40. * bootloader_ignore: (optional) flag for ignore by bootloader
  41. * application_ignore: (optional) flag for ignore by application
  42. * bootloader_ro: (optional) flag for read only by bootloader
  43. * application_ro: (optional) flag for read only by application
  44. * bootloader_format_on_fail: (optional) flag for format on fail in bootloader
  45. * application_format_on_fail: (optional) flag for format on fail in application
  46. * macros: it will only be used to generate partinfo.cmake for definitions
  47. all keys start with "CONFIG_" will be written to cmake.
  48. """
  49. MAGIC = b'PRTI'
  50. VERSION = 0x100
  51. HEADER_SIZE = 16
  52. BOOTLOADER_RO = 0x01
  53. APPLICATION_RO = 0x02
  54. BOOTLOADER_IGNORE = 0x04
  55. APPLICATION_IGNORE = 0x08
  56. BOOTLOADER_FORMAT_ON_FAIL = 0x10
  57. APPLICATION_FORMAT_ON_FAIL = 0x20
  58. class Partinfo(object):
  59. def __init__(self):
  60. self._des = []
  61. pass
  62. def loadjson(self, fname):
  63. fh = open(fname, "r")
  64. self._des = json.load(fh)
  65. fh.close()
  66. def storebin(self, fname):
  67. data = bytearray()
  68. for p in self._des['descriptions']:
  69. dtype = p['type']
  70. if dtype == 'FBD1' or dtype == 'FBD2':
  71. flags = 0
  72. if p.get('bootloader_ignore', False):
  73. flags |= BOOTLOADER_IGNORE
  74. if p.get('application_ignore', False):
  75. flags |= APPLICATION_IGNORE
  76. if p.get('bootloader_format_on_fail', False):
  77. flags |= BOOTLOADER_FORMAT_ON_FAIL
  78. if p.get('application_format_on_fail', False):
  79. flags |= APPLICATION_FORMAT_ON_FAIL
  80. pdata = struct.pack(
  81. '4s4s4siiiii',
  82. bytes(dtype, 'utf-8'),
  83. bytes(p['flash'], 'utf-8'),
  84. bytes(p['name'], 'utf-8'),
  85. int(p['offset'], 0),
  86. int(p['size'], 0),
  87. int(p['erase_block'], 0),
  88. int(p['logic_block'], 0),
  89. flags)
  90. data += pdata
  91. elif dtype == 'BPRT':
  92. flags = 0
  93. if p.get('bootloader_ignore', False):
  94. flags |= BOOTLOADER_IGNORE
  95. if p.get('application_ignore', False):
  96. flags |= APPLICATION_IGNORE
  97. pdata = struct.pack(
  98. '4s4s4siii',
  99. bytes(dtype, 'utf-8'),
  100. bytes(p['device'], 'utf-8'),
  101. bytes(p['name'], 'utf-8'),
  102. int(p['offset'], 0),
  103. int(p['count'], 0),
  104. flags)
  105. data += pdata
  106. elif dtype == 'SFFS':
  107. flags = 0
  108. if p.get('bootloader_ro', False):
  109. flags |= BOOTLOADER_RO
  110. if p.get('application_ro', False):
  111. flags |= APPLICATION_RO
  112. if p.get('bootloader_ignore', False):
  113. flags |= BOOTLOADER_IGNORE
  114. if p.get('application_ignore', False):
  115. flags |= APPLICATION_IGNORE
  116. if p.get('bootloader_format_on_fail', False):
  117. flags |= BOOTLOADER_FORMAT_ON_FAIL
  118. if p.get('application_format_on_fail', False):
  119. flags |= APPLICATION_FORMAT_ON_FAIL
  120. reserve_block = 0
  121. if 'reserve_block' in p:
  122. reserve_block = int(p['reserve_block'], 0)
  123. pdata = struct.pack(
  124. '4s4s64sii',
  125. bytes(dtype, 'utf-8'),
  126. bytes(p['device'], 'utf-8'),
  127. bytes(p['mount'], 'utf-8'),
  128. reserve_block,
  129. flags)
  130. data += pdata
  131. size = HEADER_SIZE + len(data)
  132. version = struct.pack('ii', size, VERSION)
  133. crc = binascii.crc32(version + data)
  134. header = struct.pack('4sIii', MAGIC, crc, size, VERSION)
  135. if not os.path.exists(os.path.dirname(fname)):
  136. os.makedirs(os.path.dirname(fname))
  137. fh = open(fname, 'wb')
  138. fh.write(header)
  139. fh.write(data)
  140. fh.close()
  141. def storecmake(self, fname, json_fname):
  142. if not os.path.exists(os.path.dirname(fname)):
  143. os.makedirs(os.path.dirname(fname))
  144. fh = open(fname, "w")
  145. fh.write("# Auto Generated\n")
  146. kv = self._des.get("macros", {})
  147. for k, v in kv.items():
  148. if k.startswith("CONFIG_"):
  149. fh.write("set(%s %s)\n" % (k, v))
  150. fh.close()
  151. def main():
  152. parser = argparse.ArgumentParser(description=DESCRIPTION,
  153. formatter_class=argparse.RawTextHelpFormatter)
  154. parser.add_argument("json", help="partinfo.json for partition information")
  155. parser.add_argument("bin", help="partinfo.bin for partition information")
  156. parser.add_argument("cmake", help="partinfo.cmake for definitions")
  157. args = parser.parse_args()
  158. parti = Partinfo()
  159. parti.loadjson(args.json)
  160. parti.storebin(args.bin)
  161. parti.storecmake(args.cmake, args.json)
  162. if __name__ == "__main__":
  163. main()