xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/make_fit_atf.py (revision 45dfd9925e2c37c5535320c9e467c9d176f4a087)
1f562460aSKever Yang#!/usr/bin/env python2
2f562460aSKever Yang"""
3f562460aSKever YangA script to generate FIT image source for rockchip boards
4f562460aSKever Yangwith ARM Trusted Firmware
5f562460aSKever Yangand multiple device trees (given on the command line)
6f562460aSKever Yang
7f562460aSKever Yangusage: $0 <dt_name> [<dt_name> [<dt_name] ...]
8f562460aSKever Yang"""
9f562460aSKever Yang
10f562460aSKever Yangimport os
11f562460aSKever Yangimport sys
12f562460aSKever Yangimport getopt
13f562460aSKever Yang
14f562460aSKever Yang# pip install pyelftools
15f562460aSKever Yangfrom elftools.elf.elffile import ELFFile
16f562460aSKever Yangfrom elftools.elf.sections import SymbolTableSection
17f562460aSKever Yangfrom elftools.elf.segments import Segment, InterpSegment, NoteSegment
18f562460aSKever Yang
19f562460aSKever YangELF_SEG_P_TYPE='p_type'
20f562460aSKever YangELF_SEG_P_PADDR='p_paddr'
21f562460aSKever YangELF_SEG_P_VADDR='p_vaddr'
22f562460aSKever YangELF_SEG_P_OFFSET='p_offset'
23f562460aSKever YangELF_SEG_P_FILESZ='p_filesz'
24f562460aSKever YangELF_SEG_P_MEMSZ='p_memsz'
25f562460aSKever Yang
26f562460aSKever YangDT_HEADER="""/*
27f562460aSKever Yang * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd
28f562460aSKever Yang *
29f562460aSKever Yang * Minimal dts for a SPL FIT image payload.
30f562460aSKever Yang *
31f562460aSKever Yang * SPDX-License-Identifier: GPL-2.0+  X11
32f562460aSKever Yang */
33f562460aSKever Yang/dts-v1/;
34f562460aSKever Yang
35f562460aSKever Yang/ {
36f562460aSKever Yang	description = "Configuration to load ATF before U-Boot";
37f562460aSKever Yang	#address-cells = <1>;
38f562460aSKever Yang
39f562460aSKever Yang	images {
40*45dfd992SJoseph Chen		uboot {
41f562460aSKever Yang			description = "U-Boot (64-bit)";
42f562460aSKever Yang			data = /incbin/("u-boot-nodtb.bin");
43f562460aSKever Yang			type = "standalone";
44f562460aSKever Yang			os = "U-Boot";
45f562460aSKever Yang			arch = "arm64";
46f562460aSKever Yang			compression = "none";
47f562460aSKever Yang			load = <0x%08x>;
48*45dfd992SJoseph Chen			hash {
4953f956c2SJoseph Chen				algo = "sha256";
5053f956c2SJoseph Chen			};
51f562460aSKever Yang		};
52f562460aSKever Yang"""
53f562460aSKever Yang
54f562460aSKever YangDT_IMAGES_NODE_END="""
55f562460aSKever Yang	};
56f562460aSKever Yang"""
57f562460aSKever Yang
58f562460aSKever YangDT_END="""
59f562460aSKever Yang};
60f562460aSKever Yang"""
61f562460aSKever Yang
62f562460aSKever Yangdef append_atf_node(file, atf_index, phy_addr):
63f562460aSKever Yang    """
64f562460aSKever Yang    Append ATF DT node to input FIT dts file.
65f562460aSKever Yang    """
66f562460aSKever Yang    data = 'bl31_0x%08x.bin' % phy_addr
67f562460aSKever Yang    print >> file, '\t\tatf@%d {' % atf_index
68f562460aSKever Yang    print >> file, '\t\t\tdescription = \"ARM Trusted Firmware\";'
69f562460aSKever Yang    print >> file, '\t\t\tdata = /incbin/("%s");' % data
70f562460aSKever Yang    print >> file, '\t\t\ttype = "firmware";'
71f562460aSKever Yang    print >> file, '\t\t\tarch = "arm64";'
72f562460aSKever Yang    print >> file, '\t\t\tos = "arm-trusted-firmware";'
73f562460aSKever Yang    print >> file, '\t\t\tcompression = "none";'
74f562460aSKever Yang    print >> file, '\t\t\tload = <0x%08x>;' % phy_addr
75f562460aSKever Yang    if atf_index == 1:
76f562460aSKever Yang        print >> file, '\t\t\tentry = <0x%08x>;' % phy_addr
77*45dfd992SJoseph Chen    print >> file, '\t\t\thash {'
7853f956c2SJoseph Chen    print >> file, '\t\t\t\talgo = "sha256";'
7953f956c2SJoseph Chen    print >> file, '\t\t\t};'
80f562460aSKever Yang    print >> file, '\t\t};'
81f562460aSKever Yang    print >> file, ''
82f562460aSKever Yang
83f562460aSKever Yangdef append_fdt_node(file, dtbs):
84f562460aSKever Yang    """
85f562460aSKever Yang    Append FDT nodes.
86f562460aSKever Yang    """
87f562460aSKever Yang    cnt = 1
88f562460aSKever Yang    for dtb in dtbs:
89f562460aSKever Yang        dtname = os.path.basename(dtb)
90*45dfd992SJoseph Chen        print >> file, '\t\tfdt {'
9153f956c2SJoseph Chen        print >> file, '\t\t\tdescription = "U-Boot device tree blob";'
9253f956c2SJoseph Chen        print >> file, '\t\t\tdata = /incbin/("u-boot.dtb");'
93f562460aSKever Yang        print >> file, '\t\t\ttype = "flat_dt";'
94ba2acfb8SJoseph Chen        print >> file, '\t\t\tarch = "arm64";'
95f562460aSKever Yang        print >> file, '\t\t\tcompression = "none";'
96*45dfd992SJoseph Chen        print >> file, '\t\t\thash {'
9753f956c2SJoseph Chen        print >> file, '\t\t\t\talgo = "sha256";'
9853f956c2SJoseph Chen        print >> file, '\t\t\t};'
99f562460aSKever Yang        print >> file, '\t\t};'
100f562460aSKever Yang        print >> file, ''
101f562460aSKever Yang        cnt = cnt + 1
102f562460aSKever Yang
103f562460aSKever Yangdef append_conf_section(file, cnt, dtname, atf_cnt):
104*45dfd992SJoseph Chen    print >> file, '\t\tconfig {'
105ba2acfb8SJoseph Chen    print >> file, '\t\t\tdescription = "Rockchip armv8 with ATF";'
10610530d82SJoseph Chen    print >> file, '\t\t\trollback-index = <0x0>;'
107f562460aSKever Yang    print >> file, '\t\t\tfirmware = "atf@1";'
108*45dfd992SJoseph Chen    print >> file, '\t\t\tloadables = "uboot",',
109f562460aSKever Yang    for i in range(1, atf_cnt):
110f562460aSKever Yang        print >> file, '"atf@%d"' % (i+1),
111f562460aSKever Yang        if i != (atf_cnt - 1):
112f562460aSKever Yang            print >> file, ',',
113f562460aSKever Yang        else:
114f562460aSKever Yang            print >> file, ';'
115*45dfd992SJoseph Chen    print >> file, '\t\t\tfdt = "fdt";'
116*45dfd992SJoseph Chen    print >> file, '\t\t\tsignature {'
11753f956c2SJoseph Chen    print >> file, '\t\t\t\talgo = "sha256,rsa2048";'
118*45dfd992SJoseph Chen    print >> file, '\t\t\t\tpadding = "pss";'
11953f956c2SJoseph Chen    print >> file, '\t\t\t\tkey-name-hint = "dev";'
12053f956c2SJoseph Chen    print >> file, '\t\t\t\tsign-images = "fdt", "firmware", "loadables";'
12153f956c2SJoseph Chen    print >> file, '\t\t\t};'
122f562460aSKever Yang    print >> file, '\t\t};'
123f562460aSKever Yang    print >> file, ''
124f562460aSKever Yang
125f562460aSKever Yangdef append_conf_node(file, dtbs, atf_cnt):
126f562460aSKever Yang    """
127f562460aSKever Yang    Append configeration nodes.
128f562460aSKever Yang    """
129f562460aSKever Yang    cnt = 1
130f562460aSKever Yang    print >> file, '\tconfigurations {'
131*45dfd992SJoseph Chen    print >> file, '\t\tdefault = "config";'
132f562460aSKever Yang    for dtb in dtbs:
133f562460aSKever Yang        dtname = os.path.basename(dtb)
134f562460aSKever Yang        append_conf_section(file, cnt, dtname, atf_cnt)
135f562460aSKever Yang        cnt = cnt + 1
136f562460aSKever Yang    print >> file, '\t};'
137f562460aSKever Yang    print >> file, ''
138f562460aSKever Yang
139f562460aSKever Yangdef generate_atf_fit_dts(fit_file_name, bl31_file_name, uboot_file_name, dtbs_file_name):
140f562460aSKever Yang    """
141f562460aSKever Yang    Generate FIT script for ATF image.
142f562460aSKever Yang    """
143f562460aSKever Yang    if fit_file_name != sys.stdout:
144f562460aSKever Yang        fit_file = open(fit_file_name, "wb")
145f562460aSKever Yang    else:
146f562460aSKever Yang        fit_file = sys.stdout
147f562460aSKever Yang
148f562460aSKever Yang    num_load_seg = 0
149f562460aSKever Yang    p_paddr = 0xFFFFFFFF
150f562460aSKever Yang    with open(uboot_file_name) as uboot_file:
151f562460aSKever Yang        uboot = ELFFile(uboot_file)
152f562460aSKever Yang        for i in range(uboot.num_segments()):
153f562460aSKever Yang            seg = uboot.get_segment(i)
154f562460aSKever Yang            if ('PT_LOAD' == seg.__getitem__(ELF_SEG_P_TYPE)):
155f562460aSKever Yang                p_paddr = seg.__getitem__(ELF_SEG_P_PADDR)
156f562460aSKever Yang                num_load_seg = num_load_seg + 1
157f562460aSKever Yang
158f562460aSKever Yang    assert (p_paddr != 0xFFFFFFFF and num_load_seg == 1)
159f562460aSKever Yang
160f562460aSKever Yang    print >> fit_file, DT_HEADER % p_paddr
161f562460aSKever Yang
162f562460aSKever Yang    with open(bl31_file_name) as bl31_file:
163f562460aSKever Yang        bl31 = ELFFile(bl31_file)
164f562460aSKever Yang        for i in range(bl31.num_segments()):
165f562460aSKever Yang            seg = bl31.get_segment(i)
166f562460aSKever Yang            if ('PT_LOAD' == seg.__getitem__(ELF_SEG_P_TYPE)):
167f562460aSKever Yang                paddr = seg.__getitem__(ELF_SEG_P_PADDR)
168f562460aSKever Yang                p= seg.__getitem__(ELF_SEG_P_PADDR)
169f562460aSKever Yang                append_atf_node(fit_file, i+1, paddr)
170f562460aSKever Yang    atf_cnt = i+1
171f562460aSKever Yang    append_fdt_node(fit_file, dtbs_file_name)
172f562460aSKever Yang    print >> fit_file, '%s' % DT_IMAGES_NODE_END
173f562460aSKever Yang    append_conf_node(fit_file, dtbs_file_name, atf_cnt)
174f562460aSKever Yang    print >> fit_file, '%s' % DT_END
175f562460aSKever Yang
176f562460aSKever Yang    if fit_file_name != sys.stdout:
177f562460aSKever Yang        fit_file.close()
178f562460aSKever Yang
179f562460aSKever Yangdef generate_atf_binary(bl31_file_name):
180f562460aSKever Yang    with open(bl31_file_name) as bl31_file:
181f562460aSKever Yang        bl31 = ELFFile(bl31_file)
182f562460aSKever Yang
183f562460aSKever Yang        num = bl31.num_segments()
184f562460aSKever Yang        for i in range(num):
185f562460aSKever Yang            seg = bl31.get_segment(i)
186f562460aSKever Yang            if ('PT_LOAD' == seg.__getitem__(ELF_SEG_P_TYPE)):
187f562460aSKever Yang                paddr = seg.__getitem__(ELF_SEG_P_PADDR)
188f562460aSKever Yang                file_name = 'bl31_0x%08x.bin' % paddr
189f562460aSKever Yang                with open(file_name, "wb") as atf:
190f562460aSKever Yang                    atf.write(seg.data());
191f562460aSKever Yang
192f562460aSKever Yangdef get_bl31_segments_info(bl31_file_name):
193f562460aSKever Yang    """
194f562460aSKever Yang    Get load offset, physical offset, file size
195f562460aSKever Yang    from bl31 elf file program headers.
196f562460aSKever Yang    """
197f562460aSKever Yang    with open(bl31_file_name) as bl31_file:
198f562460aSKever Yang        bl31 = ELFFile(bl31_file)
199f562460aSKever Yang
200f562460aSKever Yang        num = bl31.num_segments()
201f562460aSKever Yang        print 'Number of Segments : %d' % bl31.num_segments()
202f562460aSKever Yang        for i in range(num):
203f562460aSKever Yang            print 'Segment %d' % i
204f562460aSKever Yang            seg = bl31.get_segment(i)
205f562460aSKever Yang            ptype = seg[ELF_SEG_P_TYPE]
206f562460aSKever Yang            poffset = seg[ELF_SEG_P_OFFSET]
207f562460aSKever Yang            pmemsz = seg[ELF_SEG_P_MEMSZ]
208f562460aSKever Yang            pfilesz = seg[ELF_SEG_P_FILESZ]
209f562460aSKever Yang            print 'type: %s\nfilesz: %08x\nmemsz: %08x\noffset: %08x' % (ptype, pfilesz, pmemsz, poffset)
210f562460aSKever Yang            paddr = seg[ELF_SEG_P_PADDR]
211f562460aSKever Yang            print 'paddr: %08x' % paddr
212f562460aSKever Yang
213f562460aSKever Yangdef main():
214f562460aSKever Yang    uboot_elf="./u-boot"
215f562460aSKever Yang    bl31_elf="./bl31.elf"
216f562460aSKever Yang    FIT_ITS=sys.stdout
217f562460aSKever Yang
218f562460aSKever Yang    opts, args = getopt.getopt(sys.argv[1:], "o:u:b:h")
219f562460aSKever Yang    for opt, val in opts:
220f562460aSKever Yang        if opt == "-o":
221f562460aSKever Yang            FIT_ITS=val
222f562460aSKever Yang        elif opt == "-u":
223f562460aSKever Yang            uboot_elf=val
224f562460aSKever Yang        elif opt == "-b":
225f562460aSKever Yang            bl31_elf=val
226f562460aSKever Yang        elif opt == "-h":
227f562460aSKever Yang            print __doc__
228f562460aSKever Yang            sys.exit(2)
229f562460aSKever Yang
230f562460aSKever Yang    dtbs = args
231f562460aSKever Yang    #get_bl31_segments_info("u-boot")
232f562460aSKever Yang    #get_bl31_segments_info("bl31.elf")
233f562460aSKever Yang
234f562460aSKever Yang    generate_atf_fit_dts(FIT_ITS, bl31_elf, uboot_elf, dtbs)
235f562460aSKever Yang    generate_atf_binary(bl31_elf);
236f562460aSKever Yang
237f562460aSKever Yangif __name__ == "__main__":
238f562460aSKever Yang    main()
239