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