blob: db0ae96ca84b81bf3a36fc0c8ce3ee6b42a9706f [file] [log] [blame]
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +02001#!/usr/bin/env python
Kever Yangcbe50372017-12-15 11:15:03 +08002"""
Christoph Muellnerb238e4b2019-05-07 11:11:01 +02003# SPDX-License-Identifier: GPL-2.0+
4#
5# A script to generate FIT image source for rockchip boards
6# with ARM Trusted Firmware
7# and multiple device trees (given on the command line)
8#
9# usage: $0 <dt_name> [<dt_name> [<dt_name] ...]
Kever Yangcbe50372017-12-15 11:15:03 +080010"""
11
12import os
13import sys
14import getopt
Jagan Teki96070462019-06-20 16:29:22 +053015import logging
Kever Yangcbe50372017-12-15 11:15:03 +080016
17# pip install pyelftools
18from elftools.elf.elffile import ELFFile
Kever Yangcbe50372017-12-15 11:15:03 +080019
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020020ELF_SEG_P_TYPE = 'p_type'
21ELF_SEG_P_PADDR = 'p_paddr'
22ELF_SEG_P_VADDR = 'p_vaddr'
23ELF_SEG_P_OFFSET = 'p_offset'
24ELF_SEG_P_FILESZ = 'p_filesz'
25ELF_SEG_P_MEMSZ = 'p_memsz'
Kever Yangcbe50372017-12-15 11:15:03 +080026
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020027DT_HEADER = """
Tom Rini83d290c2018-05-06 17:58:06 -040028/*
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020029 * This is a generated file.
Kever Yangcbe50372017-12-15 11:15:03 +080030 */
31/dts-v1/;
32
33/ {
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020034 description = "FIT image for U-Boot with bl31 (TF-A)";
Kever Yangcbe50372017-12-15 11:15:03 +080035 #address-cells = <1>;
36
37 images {
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020038"""
39
40DT_UBOOT = """
Kever Yangf00273a2018-08-23 11:01:08 +080041 uboot {
Kever Yangcbe50372017-12-15 11:15:03 +080042 description = "U-Boot (64-bit)";
43 data = /incbin/("u-boot-nodtb.bin");
44 type = "standalone";
45 os = "U-Boot";
46 arch = "arm64";
47 compression = "none";
48 load = <0x%08x>;
49 };
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +020050
Kever Yangcbe50372017-12-15 11:15:03 +080051"""
52
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020053DT_IMAGES_NODE_END = """ };
54
Kever Yangcbe50372017-12-15 11:15:03 +080055"""
56
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020057DT_END = "};"
Kever Yangcbe50372017-12-15 11:15:03 +080058
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020059def append_bl31_node(file, atf_index, phy_addr, elf_entry):
60 # Append BL31 DT node to input FIT dts file.
Kever Yangcbe50372017-12-15 11:15:03 +080061 data = 'bl31_0x%08x.bin' % phy_addr
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +020062 file.write('\t\tatf_%d {\n' % atf_index)
63 file.write('\t\t\tdescription = \"ARM Trusted Firmware\";\n')
64 file.write('\t\t\tdata = /incbin/("%s");\n' % data)
65 file.write('\t\t\ttype = "firmware";\n')
66 file.write('\t\t\tarch = "arm64";\n')
67 file.write('\t\t\tos = "arm-trusted-firmware";\n')
68 file.write('\t\t\tcompression = "none";\n')
69 file.write('\t\t\tload = <0x%08x>;\n' % phy_addr)
Kever Yangcbe50372017-12-15 11:15:03 +080070 if atf_index == 1:
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +020071 file.write('\t\t\tentry = <0x%08x>;\n' % elf_entry)
72 file.write('\t\t};\n')
73 file.write('\n')
Kever Yangcbe50372017-12-15 11:15:03 +080074
75def append_fdt_node(file, dtbs):
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020076 # Append FDT nodes.
Kever Yangcbe50372017-12-15 11:15:03 +080077 cnt = 1
78 for dtb in dtbs:
79 dtname = os.path.basename(dtb)
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +020080 file.write('\t\tfdt_%d {\n' % cnt)
81 file.write('\t\t\tdescription = "%s";\n' % dtname)
82 file.write('\t\t\tdata = /incbin/("%s");\n' % dtb)
83 file.write('\t\t\ttype = "flat_dt";\n')
84 file.write('\t\t\tcompression = "none";\n')
85 file.write('\t\t};\n')
86 file.write('\n')
Kever Yangcbe50372017-12-15 11:15:03 +080087 cnt = cnt + 1
88
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020089def append_conf_section(file, cnt, dtname, segments):
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +020090 file.write('\t\tconfig_%d {\n' % cnt)
91 file.write('\t\t\tdescription = "%s";\n' % dtname)
92 file.write('\t\t\tfirmware = "atf_1";\n')
Jagan Teki96070462019-06-20 16:29:22 +053093 file.write('\t\t\tloadables = "uboot"')
94 if segments != 0:
95 file.write(',')
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020096 for i in range(1, segments):
Andy Yan619f0022019-07-04 17:44:40 +080097 file.write('"atf_%d"' % (i + 1))
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020098 if i != (segments - 1):
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +020099 file.write(',')
Kever Yangcbe50372017-12-15 11:15:03 +0800100 else:
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +0200101 file.write(';\n')
Jagan Teki96070462019-06-20 16:29:22 +0530102 if segments == 0:
103 file.write(';\n')
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +0200104 file.write('\t\t\tfdt = "fdt_1";\n')
105 file.write('\t\t};\n')
106 file.write('\n')
Kever Yangcbe50372017-12-15 11:15:03 +0800107
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200108def append_conf_node(file, dtbs, segments):
109 # Append configeration nodes.
Kever Yangcbe50372017-12-15 11:15:03 +0800110 cnt = 1
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +0200111 file.write('\tconfigurations {\n')
112 file.write('\t\tdefault = "config_1";\n')
Kever Yangcbe50372017-12-15 11:15:03 +0800113 for dtb in dtbs:
114 dtname = os.path.basename(dtb)
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200115 append_conf_section(file, cnt, dtname, segments)
Kever Yangcbe50372017-12-15 11:15:03 +0800116 cnt = cnt + 1
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +0200117 file.write('\t};\n')
118 file.write('\n')
Kever Yangcbe50372017-12-15 11:15:03 +0800119
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200120def generate_atf_fit_dts_uboot(fit_file, uboot_file_name):
Kever Yangcbe50372017-12-15 11:15:03 +0800121 num_load_seg = 0
122 p_paddr = 0xFFFFFFFF
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +0200123 with open(uboot_file_name, 'rb') as uboot_file:
Kever Yangcbe50372017-12-15 11:15:03 +0800124 uboot = ELFFile(uboot_file)
125 for i in range(uboot.num_segments()):
126 seg = uboot.get_segment(i)
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200127 if seg.__getitem__(ELF_SEG_P_TYPE) == 'PT_LOAD':
Kever Yangcbe50372017-12-15 11:15:03 +0800128 p_paddr = seg.__getitem__(ELF_SEG_P_PADDR)
129 num_load_seg = num_load_seg + 1
130
131 assert (p_paddr != 0xFFFFFFFF and num_load_seg == 1)
132
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200133 fit_file.write(DT_UBOOT % p_paddr)
Kever Yangcbe50372017-12-15 11:15:03 +0800134
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200135def generate_atf_fit_dts_bl31(fit_file, bl31_file_name, dtbs_file_name):
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +0200136 with open(bl31_file_name, 'rb') as bl31_file:
Kever Yangcbe50372017-12-15 11:15:03 +0800137 bl31 = ELFFile(bl31_file)
Mian Yousaf Kaukabe4011e82018-06-08 10:47:09 +0200138 elf_entry = bl31.header['e_entry']
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200139 segments = bl31.num_segments()
140 for i in range(segments):
Kever Yangcbe50372017-12-15 11:15:03 +0800141 seg = bl31.get_segment(i)
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200142 if seg.__getitem__(ELF_SEG_P_TYPE) == 'PT_LOAD':
Kever Yangcbe50372017-12-15 11:15:03 +0800143 paddr = seg.__getitem__(ELF_SEG_P_PADDR)
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200144 append_bl31_node(fit_file, i + 1, paddr, elf_entry)
Kever Yangcbe50372017-12-15 11:15:03 +0800145 append_fdt_node(fit_file, dtbs_file_name)
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200146 fit_file.write(DT_IMAGES_NODE_END)
147 append_conf_node(fit_file, dtbs_file_name, segments)
148
149def generate_atf_fit_dts(fit_file_name, bl31_file_name, uboot_file_name, dtbs_file_name):
150 # Generate FIT script for ATF image.
151 if fit_file_name != sys.stdout:
152 fit_file = open(fit_file_name, "wb")
153 else:
154 fit_file = sys.stdout
155
156 fit_file.write(DT_HEADER)
157 generate_atf_fit_dts_uboot(fit_file, uboot_file_name)
158 generate_atf_fit_dts_bl31(fit_file, bl31_file_name, dtbs_file_name)
159 fit_file.write(DT_END)
Kever Yangcbe50372017-12-15 11:15:03 +0800160
161 if fit_file_name != sys.stdout:
162 fit_file.close()
163
164def generate_atf_binary(bl31_file_name):
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +0200165 with open(bl31_file_name, 'rb') as bl31_file:
Kever Yangcbe50372017-12-15 11:15:03 +0800166 bl31 = ELFFile(bl31_file)
167
168 num = bl31.num_segments()
169 for i in range(num):
170 seg = bl31.get_segment(i)
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200171 if seg.__getitem__(ELF_SEG_P_TYPE) == 'PT_LOAD':
Kever Yangcbe50372017-12-15 11:15:03 +0800172 paddr = seg.__getitem__(ELF_SEG_P_PADDR)
173 file_name = 'bl31_0x%08x.bin' % paddr
174 with open(file_name, "wb") as atf:
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200175 atf.write(seg.data())
Kever Yangcbe50372017-12-15 11:15:03 +0800176
177def main():
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200178 uboot_elf = "./u-boot"
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200179 fit_its = sys.stdout
Jagan Teki96070462019-06-20 16:29:22 +0530180 if "BL31" in os.environ:
181 bl31_elf=os.getenv("BL31");
182 elif os.path.isfile("./bl31.elf"):
183 bl31_elf = "./bl31.elf"
184 else:
185 os.system("echo 'int main(){}' > bl31.c")
186 os.system("${CROSS_COMPILE}gcc -c bl31.c -o bl31.elf")
187 bl31_elf = "./bl31.elf"
188 logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)
189 logging.warning(' BL31 file bl31.elf NOT found, resulting binary is non-functional')
190 logging.warning(' Please read Building section in doc/README.rockchip')
Kever Yangcbe50372017-12-15 11:15:03 +0800191
192 opts, args = getopt.getopt(sys.argv[1:], "o:u:b:h")
193 for opt, val in opts:
194 if opt == "-o":
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200195 fit_its = val
Kever Yangcbe50372017-12-15 11:15:03 +0800196 elif opt == "-u":
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200197 uboot_elf = val
Kever Yangcbe50372017-12-15 11:15:03 +0800198 elif opt == "-b":
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200199 bl31_elf = val
Kever Yangcbe50372017-12-15 11:15:03 +0800200 elif opt == "-h":
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +0200201 print(__doc__)
Kever Yangcbe50372017-12-15 11:15:03 +0800202 sys.exit(2)
203
204 dtbs = args
Kever Yangcbe50372017-12-15 11:15:03 +0800205
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200206 generate_atf_fit_dts(fit_its, bl31_elf, uboot_elf, dtbs)
207 generate_atf_binary(bl31_elf)
Kever Yangcbe50372017-12-15 11:15:03 +0800208
209if __name__ == "__main__":
210 main()