blob: 212bd0a8543cc21c8a395c265da63f8b065073eb [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
15
16# pip install pyelftools
17from elftools.elf.elffile import ELFFile
Kever Yangcbe50372017-12-15 11:15:03 +080018
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020019ELF_SEG_P_TYPE = 'p_type'
20ELF_SEG_P_PADDR = 'p_paddr'
21ELF_SEG_P_VADDR = 'p_vaddr'
22ELF_SEG_P_OFFSET = 'p_offset'
23ELF_SEG_P_FILESZ = 'p_filesz'
24ELF_SEG_P_MEMSZ = 'p_memsz'
Kever Yangcbe50372017-12-15 11:15:03 +080025
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020026DT_HEADER = """
Tom Rini83d290c2018-05-06 17:58:06 -040027/*
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020028 * This is a generated file.
Kever Yangcbe50372017-12-15 11:15:03 +080029 */
30/dts-v1/;
31
32/ {
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020033 description = "FIT image for U-Boot with bl31 (TF-A)";
Kever Yangcbe50372017-12-15 11:15:03 +080034 #address-cells = <1>;
35
36 images {
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020037"""
38
39DT_UBOOT = """
Kever Yangf00273a2018-08-23 11:01:08 +080040 uboot {
Kever Yangcbe50372017-12-15 11:15:03 +080041 description = "U-Boot (64-bit)";
42 data = /incbin/("u-boot-nodtb.bin");
43 type = "standalone";
44 os = "U-Boot";
45 arch = "arm64";
46 compression = "none";
47 load = <0x%08x>;
48 };
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +020049
Kever Yangcbe50372017-12-15 11:15:03 +080050"""
51
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020052DT_IMAGES_NODE_END = """ };
53
Kever Yangcbe50372017-12-15 11:15:03 +080054"""
55
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020056DT_END = "};"
Kever Yangcbe50372017-12-15 11:15:03 +080057
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020058def append_bl31_node(file, atf_index, phy_addr, elf_entry):
59 # Append BL31 DT node to input FIT dts file.
Kever Yangcbe50372017-12-15 11:15:03 +080060 data = 'bl31_0x%08x.bin' % phy_addr
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +020061 file.write('\t\tatf_%d {\n' % atf_index)
62 file.write('\t\t\tdescription = \"ARM Trusted Firmware\";\n')
63 file.write('\t\t\tdata = /incbin/("%s");\n' % data)
64 file.write('\t\t\ttype = "firmware";\n')
65 file.write('\t\t\tarch = "arm64";\n')
66 file.write('\t\t\tos = "arm-trusted-firmware";\n')
67 file.write('\t\t\tcompression = "none";\n')
68 file.write('\t\t\tload = <0x%08x>;\n' % phy_addr)
Kever Yangcbe50372017-12-15 11:15:03 +080069 if atf_index == 1:
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +020070 file.write('\t\t\tentry = <0x%08x>;\n' % elf_entry)
71 file.write('\t\t};\n')
72 file.write('\n')
Kever Yangcbe50372017-12-15 11:15:03 +080073
74def append_fdt_node(file, dtbs):
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020075 # Append FDT nodes.
Kever Yangcbe50372017-12-15 11:15:03 +080076 cnt = 1
77 for dtb in dtbs:
78 dtname = os.path.basename(dtb)
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +020079 file.write('\t\tfdt_%d {\n' % cnt)
80 file.write('\t\t\tdescription = "%s";\n' % dtname)
81 file.write('\t\t\tdata = /incbin/("%s");\n' % dtb)
82 file.write('\t\t\ttype = "flat_dt";\n')
83 file.write('\t\t\tcompression = "none";\n')
84 file.write('\t\t};\n')
85 file.write('\n')
Kever Yangcbe50372017-12-15 11:15:03 +080086 cnt = cnt + 1
87
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020088def append_conf_section(file, cnt, dtname, segments):
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +020089 file.write('\t\tconfig_%d {\n' % cnt)
90 file.write('\t\t\tdescription = "%s";\n' % dtname)
91 file.write('\t\t\tfirmware = "atf_1";\n')
92 file.write('\t\t\tloadables = "uboot",')
Christoph Muellnerb238e4b2019-05-07 11:11:01 +020093 for i in range(1, segments):
94 file.write('"atf_%d"' % (i))
95 if i != (segments - 1):
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +020096 file.write(',')
Kever Yangcbe50372017-12-15 11:15:03 +080097 else:
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +020098 file.write(';\n')
99 file.write('\t\t\tfdt = "fdt_1";\n')
100 file.write('\t\t};\n')
101 file.write('\n')
Kever Yangcbe50372017-12-15 11:15:03 +0800102
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200103def append_conf_node(file, dtbs, segments):
104 # Append configeration nodes.
Kever Yangcbe50372017-12-15 11:15:03 +0800105 cnt = 1
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +0200106 file.write('\tconfigurations {\n')
107 file.write('\t\tdefault = "config_1";\n')
Kever Yangcbe50372017-12-15 11:15:03 +0800108 for dtb in dtbs:
109 dtname = os.path.basename(dtb)
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200110 append_conf_section(file, cnt, dtname, segments)
Kever Yangcbe50372017-12-15 11:15:03 +0800111 cnt = cnt + 1
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +0200112 file.write('\t};\n')
113 file.write('\n')
Kever Yangcbe50372017-12-15 11:15:03 +0800114
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200115def generate_atf_fit_dts_uboot(fit_file, uboot_file_name):
Kever Yangcbe50372017-12-15 11:15:03 +0800116 num_load_seg = 0
117 p_paddr = 0xFFFFFFFF
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +0200118 with open(uboot_file_name, 'rb') as uboot_file:
Kever Yangcbe50372017-12-15 11:15:03 +0800119 uboot = ELFFile(uboot_file)
120 for i in range(uboot.num_segments()):
121 seg = uboot.get_segment(i)
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200122 if seg.__getitem__(ELF_SEG_P_TYPE) == 'PT_LOAD':
Kever Yangcbe50372017-12-15 11:15:03 +0800123 p_paddr = seg.__getitem__(ELF_SEG_P_PADDR)
124 num_load_seg = num_load_seg + 1
125
126 assert (p_paddr != 0xFFFFFFFF and num_load_seg == 1)
127
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200128 fit_file.write(DT_UBOOT % p_paddr)
Kever Yangcbe50372017-12-15 11:15:03 +0800129
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200130def generate_atf_fit_dts_bl31(fit_file, bl31_file_name, dtbs_file_name):
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +0200131 with open(bl31_file_name, 'rb') as bl31_file:
Kever Yangcbe50372017-12-15 11:15:03 +0800132 bl31 = ELFFile(bl31_file)
Mian Yousaf Kaukabe4011e82018-06-08 10:47:09 +0200133 elf_entry = bl31.header['e_entry']
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200134 segments = bl31.num_segments()
135 for i in range(segments):
Kever Yangcbe50372017-12-15 11:15:03 +0800136 seg = bl31.get_segment(i)
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200137 if seg.__getitem__(ELF_SEG_P_TYPE) == 'PT_LOAD':
Kever Yangcbe50372017-12-15 11:15:03 +0800138 paddr = seg.__getitem__(ELF_SEG_P_PADDR)
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200139 append_bl31_node(fit_file, i + 1, paddr, elf_entry)
Kever Yangcbe50372017-12-15 11:15:03 +0800140 append_fdt_node(fit_file, dtbs_file_name)
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200141 fit_file.write(DT_IMAGES_NODE_END)
142 append_conf_node(fit_file, dtbs_file_name, segments)
143
144def generate_atf_fit_dts(fit_file_name, bl31_file_name, uboot_file_name, dtbs_file_name):
145 # Generate FIT script for ATF image.
146 if fit_file_name != sys.stdout:
147 fit_file = open(fit_file_name, "wb")
148 else:
149 fit_file = sys.stdout
150
151 fit_file.write(DT_HEADER)
152 generate_atf_fit_dts_uboot(fit_file, uboot_file_name)
153 generate_atf_fit_dts_bl31(fit_file, bl31_file_name, dtbs_file_name)
154 fit_file.write(DT_END)
Kever Yangcbe50372017-12-15 11:15:03 +0800155
156 if fit_file_name != sys.stdout:
157 fit_file.close()
158
159def generate_atf_binary(bl31_file_name):
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +0200160 with open(bl31_file_name, 'rb') as bl31_file:
Kever Yangcbe50372017-12-15 11:15:03 +0800161 bl31 = ELFFile(bl31_file)
162
163 num = bl31.num_segments()
164 for i in range(num):
165 seg = bl31.get_segment(i)
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200166 if seg.__getitem__(ELF_SEG_P_TYPE) == 'PT_LOAD':
Kever Yangcbe50372017-12-15 11:15:03 +0800167 paddr = seg.__getitem__(ELF_SEG_P_PADDR)
168 file_name = 'bl31_0x%08x.bin' % paddr
169 with open(file_name, "wb") as atf:
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200170 atf.write(seg.data())
Kever Yangcbe50372017-12-15 11:15:03 +0800171
172def main():
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200173 uboot_elf = "./u-boot"
174 bl31_elf = "./bl31.elf"
175 fit_its = sys.stdout
Kever Yangcbe50372017-12-15 11:15:03 +0800176
177 opts, args = getopt.getopt(sys.argv[1:], "o:u:b:h")
178 for opt, val in opts:
179 if opt == "-o":
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200180 fit_its = val
Kever Yangcbe50372017-12-15 11:15:03 +0800181 elif opt == "-u":
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200182 uboot_elf = val
Kever Yangcbe50372017-12-15 11:15:03 +0800183 elif opt == "-b":
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200184 bl31_elf = val
Kever Yangcbe50372017-12-15 11:15:03 +0800185 elif opt == "-h":
Mian Yousaf Kaukab7009eae2018-06-08 10:47:10 +0200186 print(__doc__)
Kever Yangcbe50372017-12-15 11:15:03 +0800187 sys.exit(2)
188
189 dtbs = args
Kever Yangcbe50372017-12-15 11:15:03 +0800190
Christoph Muellnerb238e4b2019-05-07 11:11:01 +0200191 generate_atf_fit_dts(fit_its, bl31_elf, uboot_elf, dtbs)
192 generate_atf_binary(bl31_elf)
Kever Yangcbe50372017-12-15 11:15:03 +0800193
194if __name__ == "__main__":
195 main()