3 # SPDX-License-Identifier: GPL-2.0+
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)
9 # usage: $0 <dt_name> [<dt_name> [<dt_name] ...]
17 # pip install pyelftools
18 from elftools
.elf
.elffile
import ELFFile
20 ELF_SEG_P_TYPE
= 'p_type'
21 ELF_SEG_P_PADDR
= 'p_paddr'
22 ELF_SEG_P_VADDR
= 'p_vaddr'
23 ELF_SEG_P_OFFSET
= 'p_offset'
24 ELF_SEG_P_FILESZ
= 'p_filesz'
25 ELF_SEG_P_MEMSZ
= 'p_memsz'
29 * This is a generated file.
34 description = "FIT image for U-Boot with bl31 (TF-A)";
42 description = "U-Boot (64-bit)";
43 data = /incbin/("u-boot-nodtb.bin");
53 DT_IMAGES_NODE_END
= """ };
59 def append_bl31_node(file, atf_index
, phy_addr
, elf_entry
):
60 # Append BL31 DT node to input FIT dts file.
61 data
= 'bl31_0x%08x.bin' % phy_addr
62 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
)
71 file.write('\t\t\tentry = <0x%08x>;\n' % elf_entry
)
72 file.write('\t\t};\n')
75 def append_fdt_node(file, dtbs
):
79 dtname
= os
.path
.basename(dtb
)
80 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')
89 def append_conf_section(file, cnt
, dtname
, segments
):
90 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')
93 file.write('\t\t\tloadables = "uboot"')
96 for i
in range(1, segments
):
97 file.write('"atf_%d"' % (i
+ 1))
98 if i
!= (segments
- 1):
104 file.write('\t\t\tfdt = "fdt_1";\n')
105 file.write('\t\t};\n')
108 def append_conf_node(file, dtbs
, segments
):
109 # Append configeration nodes.
111 file.write('\tconfigurations {\n')
112 file.write('\t\tdefault = "config_1";\n')
114 dtname
= os
.path
.basename(dtb
)
115 append_conf_section(file, cnt
, dtname
, segments
)
120 def generate_atf_fit_dts_uboot(fit_file
, uboot_file_name
):
123 with
open(uboot_file_name
, 'rb') as uboot_file
:
124 uboot
= ELFFile(uboot_file
)
125 for i
in range(uboot
.num_segments()):
126 seg
= uboot
.get_segment(i
)
127 if seg
.__getitem
__(ELF_SEG_P_TYPE
) == 'PT_LOAD':
128 p_paddr
= seg
.__getitem
__(ELF_SEG_P_PADDR
)
129 num_load_seg
= num_load_seg
+ 1
131 assert (p_paddr
!= 0xFFFFFFFF and num_load_seg
== 1)
133 fit_file
.write(DT_UBOOT
% p_paddr
)
135 def generate_atf_fit_dts_bl31(fit_file
, bl31_file_name
, dtbs_file_name
):
136 with
open(bl31_file_name
, 'rb') as bl31_file
:
137 bl31
= ELFFile(bl31_file
)
138 elf_entry
= bl31
.header
['e_entry']
139 segments
= bl31
.num_segments()
140 for i
in range(segments
):
141 seg
= bl31
.get_segment(i
)
142 if seg
.__getitem
__(ELF_SEG_P_TYPE
) == 'PT_LOAD':
143 paddr
= seg
.__getitem
__(ELF_SEG_P_PADDR
)
144 append_bl31_node(fit_file
, i
+ 1, paddr
, elf_entry
)
145 append_fdt_node(fit_file
, dtbs_file_name
)
146 fit_file
.write(DT_IMAGES_NODE_END
)
147 append_conf_node(fit_file
, dtbs_file_name
, segments
)
149 def 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")
154 fit_file
= sys
.stdout
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
)
161 if fit_file_name
!= sys
.stdout
:
164 def generate_atf_binary(bl31_file_name
):
165 with
open(bl31_file_name
, 'rb') as bl31_file
:
166 bl31
= ELFFile(bl31_file
)
168 num
= bl31
.num_segments()
170 seg
= bl31
.get_segment(i
)
171 if seg
.__getitem
__(ELF_SEG_P_TYPE
) == 'PT_LOAD':
172 paddr
= seg
.__getitem
__(ELF_SEG_P_PADDR
)
173 file_name
= 'bl31_0x%08x.bin' % paddr
174 with
open(file_name
, "wb") as atf
:
175 atf
.write(seg
.data())
178 uboot_elf
= "./u-boot"
180 if "BL31" in os
.environ
:
181 bl31_elf
=os
.getenv("BL31");
182 elif os
.path
.isfile("./bl31.elf"):
183 bl31_elf
= "./bl31.elf"
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')
192 opts
, args
= getopt
.getopt(sys
.argv
[1:], "o:u:b:h")
193 for opt
, val
in opts
:
206 generate_atf_fit_dts(fit_its
, bl31_elf
, uboot_elf
, dtbs
)
207 generate_atf_binary(bl31_elf
)
209 if __name__
== "__main__":