build_atf_image.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #!/usr/bin/env python3
  2. #
  3. # Build ATF image file
  4. #
  5. # Copyright (c) 2019 Actions Semiconductor Co., Ltd
  6. #
  7. # SPDX-License-Identifier: Apache-2.0
  8. #
  9. import os
  10. import sys
  11. import struct
  12. import argparse
  13. import zlib
  14. ATF_DATA_ALIGN_SIZE = 512
  15. ATF_MAX_FILE_CNT = 15
  16. ATF_VERSION = 0x01000000
  17. '''
  18. /* ATF image */
  19. typedef struct
  20. {
  21. uint8 magic[8];
  22. uint8 sdk_version[4];
  23. uint8 file_total;
  24. uint8 reserved[19];
  25. atf_dir_t atf_dir[15];
  26. }atf_head_t;
  27. typedef struct
  28. {
  29. uint8 filename[12];
  30. uint8 reserved1[4];
  31. uint32 offset;
  32. uint32 length;
  33. uint8 reserved2[4];
  34. uint32 checksum;
  35. }atf_dir_t;
  36. '''
  37. class atf_dir:
  38. def __init__(self):
  39. self.name = ''
  40. self.offset = 0
  41. self.length = 0
  42. self.aligned_length = 0
  43. self.checksum = 0
  44. self.data = None
  45. atf_file_list = []
  46. cur_data_offset = ATF_DATA_ALIGN_SIZE
  47. atf_header = None
  48. def atf_add_crc(filename):
  49. if os.path.isfile(filename):
  50. # update data crc
  51. with open(filename, 'rb+') as f:
  52. #skip magic header
  53. f.read(512)
  54. crc = zlib.crc32(f.read(), 0) & 0xffffffff
  55. #update crc field in header
  56. f.seek(24)
  57. f.write(struct.pack('<I',crc))
  58. # update head crc
  59. with open(filename, 'rb+') as f:
  60. #skip magic header
  61. f.read(12)
  62. crc = zlib.crc32(f.read(512 - 12), 0) & 0xffffffff
  63. #update crc field in header
  64. f.seek(8)
  65. f.write(struct.pack('<I',crc))
  66. def atf_add_file(fpath):
  67. global atf_file_list, cur_data_offset
  68. if not os.path.isfile(fpath):
  69. print('ATF: file %s is not exist' %(fpath));
  70. return False
  71. with open(fpath, 'rb') as f:
  72. fdata = f.read()
  73. af = atf_dir()
  74. af.name = os.path.basename(fpath)
  75. # check filename: 8.3
  76. if len(af.name) > 12:
  77. print('ATF: file %s name is too long' %(fpath))
  78. return False
  79. af.length = len(fdata)
  80. if af.length == 0:
  81. print('ATF: file %s length is zero' %(fpath))
  82. return False
  83. padsize = ATF_DATA_ALIGN_SIZE - af.length % ATF_DATA_ALIGN_SIZE
  84. af.aligned_length = af.length + padsize
  85. af.data = fdata + bytearray(padsize)
  86. af.offset = cur_data_offset
  87. # caculate file crc
  88. af.checksum = zlib.crc32(fdata, 0) & 0xffffffff
  89. cur_data_offset = cur_data_offset + af.aligned_length
  90. atf_file_list.append(af)
  91. return True
  92. def atf_gen_header():
  93. global atf_header
  94. atf_dir = bytearray(0)
  95. if len(atf_file_list) == 0:
  96. return;
  97. for af in atf_file_list:
  98. atf_dir = atf_dir + struct.pack('<12s4xII4xI', af.name.encode('utf8'), \
  99. af.offset, af.length, af.checksum)
  100. total_len = cur_data_offset
  101. atf_header = bytearray("ACTTEST0", 'utf8') + \
  102. struct.pack('<IB3xIII4x', 0, len(atf_file_list), ATF_VERSION, total_len, 0)
  103. atf_header = atf_header + atf_dir
  104. padsize = ATF_DATA_ALIGN_SIZE - len(atf_header) % ATF_DATA_ALIGN_SIZE
  105. atf_header = atf_header + bytearray(padsize)
  106. def main(argv):
  107. global atf_header
  108. parser = argparse.ArgumentParser(
  109. description='Build ATT firmware image',
  110. )
  111. parser.add_argument('-o', dest = 'output_file')
  112. parser.add_argument('input_files', nargs = '*')
  113. args = parser.parse_args();
  114. print('ATF: Build ATT firmware image: %s' %args.output_file)
  115. if len(args.input_files) > ATF_MAX_FILE_CNT:
  116. print('ATF: too much input files')
  117. sys.exit(1)
  118. for input_file in args.input_files:
  119. if not os.path.isfile(input_file):
  120. continue
  121. print('ATF: Add file: %s' %input_file)
  122. if atf_add_file(input_file) != True:
  123. sys.exit(1)
  124. atf_gen_header()
  125. # write the merged property file
  126. with open(args.output_file, 'wb+') as f:
  127. f.write(atf_header)
  128. for af in atf_file_list:
  129. f.write(af.data)
  130. atf_add_crc(args.output_file)
  131. if __name__ == "__main__":
  132. main(sys.argv)