[U-Boot] [PATCH v3 2/2] arm64: zynqmp: add tool to convert PMU config object .c to binary
Luca Ceresoli
luca at lucaceresoli.net
Sat May 4 06:14:41 UTC 2019
Hi Michal,
On 04/05/19 00:31, Michal Simek wrote:
> Hi,
>
> On 15. 04. 19 9:47, Luca Ceresoli wrote:
>> The recently-added ZYNQMP_LOAD_PM_CFG_OBJ_FILE option allows SPL to load a
>> PMUFW configuration object from a binary blob. However the configuration
>> object is produced by Xilinx proprietary tools as a C source file and no
>> tool exists to easily convert it to a binary blob in an embedded Linux
>> build system for U-Boot to use.
>>
>> Add a simple Python script to do the conversion.
>>
>> It is definitely not a complete C language parser, but it is enough to
>> parse the known patterns generated by Xilinx tools, including:
>>
>> - defines
>> - literal integers, optionally with a 'U' suffix
>> - bitwise OR between them
>>
>> Signed-off-by: Luca Ceresoli <luca at lucaceresoli.net>
>> ---
>> arch/arm/mach-zynqmp/pm_cfg_obj_convert.py | 302 +++++++++++++++++++++
>> 1 file changed, 302 insertions(+)
>> create mode 100755 arch/arm/mach-zynqmp/pm_cfg_obj_convert.py
>>
>> diff --git a/arch/arm/mach-zynqmp/pm_cfg_obj_convert.py b/arch/arm/mach-zynqmp/pm_cfg_obj_convert.py
>> new file mode 100755
>> index 000000000000..5aea15860319
>> --- /dev/null
>> +++ b/arch/arm/mach-zynqmp/pm_cfg_obj_convert.py
>> @@ -0,0 +1,302 @@
>> +#!/usr/bin/env python3
>> +# SPDX-License-Identifier: GPL-2.0+
>> +# Copyright (C) 2019 Luca Ceresoli <luca at lucaceresoli.net>
>> +
>> +import sys
>> +import re
>> +import struct
>> +import logging
>> +import argparse
>> +
>> +parser = argparse.ArgumentParser(
>> + description='Convert a PMU configuration object from C source to a binary blob.',
>> + allow_abbrev=False)
>> +parser.add_argument('-D', '--debug', action="store_true")
>> +parser.add_argument(
>> + "in_file", metavar='INPUT_FILE',
>> + help='PMU configuration object (C source as produced by Xilinx XSDK)')
>> +parser.add_argument(
>> + "out_file", metavar='OUTPUT_FILE',
>> + help='PMU configuration object binary blob')
>> +args = parser.parse_args()
>> +
>> +logging.basicConfig(format='%(levelname)s:%(message)s',
>> + level=(logging.DEBUG if args.debug else logging.WARNING))
>> +
>> +pm_define = {
>> + 'PM_CAP_ACCESS' : 0x1,
>> + 'PM_CAP_CONTEXT' : 0x2,
>> + 'PM_CAP_WAKEUP' : 0x4,
>> +
>> + 'NODE_UNKNOWN' : 0,
>> + 'NODE_APU' : 1,
>> + 'NODE_APU_0' : 2,
>> + 'NODE_APU_1' : 3,
>> + 'NODE_APU_2' : 4,
>> + 'NODE_APU_3' : 5,
>> + 'NODE_RPU' : 6,
>> + 'NODE_RPU_0' : 7,
>> + 'NODE_RPU_1' : 8,
>> + 'NODE_PLD' : 9,
>> + 'NODE_FPD' : 10,
>> + 'NODE_OCM_BANK_0' : 11,
>> + 'NODE_OCM_BANK_1' : 12,
>> + 'NODE_OCM_BANK_2' : 13,
>> + 'NODE_OCM_BANK_3' : 14,
>> + 'NODE_TCM_0_A' : 15,
>> + 'NODE_TCM_0_B' : 16,
>> + 'NODE_TCM_1_A' : 17,
>> + 'NODE_TCM_1_B' : 18,
>> + 'NODE_L2' : 19,
>> + 'NODE_GPU_PP_0' : 20,
>> + 'NODE_GPU_PP_1' : 21,
>> + 'NODE_USB_0' : 22,
>> + 'NODE_USB_1' : 23,
>> + 'NODE_TTC_0' : 24,
>> + 'NODE_TTC_1' : 25,
>> + 'NODE_TTC_2' : 26,
>> + 'NODE_TTC_3' : 27,
>> + 'NODE_SATA' : 28,
>> + 'NODE_ETH_0' : 29,
>> + 'NODE_ETH_1' : 30,
>> + 'NODE_ETH_2' : 31,
>> + 'NODE_ETH_3' : 32,
>> + 'NODE_UART_0' : 33,
>> + 'NODE_UART_1' : 34,
>> + 'NODE_SPI_0' : 35,
>> + 'NODE_SPI_1' : 36,
>> + 'NODE_I2C_0' : 37,
>> + 'NODE_I2C_1' : 38,
>> + 'NODE_SD_0' : 39,
>> + 'NODE_SD_1' : 40,
>> + 'NODE_DP' : 41,
>> + 'NODE_GDMA' : 42,
>> + 'NODE_ADMA' : 43,
>> + 'NODE_NAND' : 44,
>> + 'NODE_QSPI' : 45,
>> + 'NODE_GPIO' : 46,
>> + 'NODE_CAN_0' : 47,
>> + 'NODE_CAN_1' : 48,
>> + 'NODE_EXTERN' : 49,
>> + 'NODE_APLL' : 50,
>> + 'NODE_VPLL' : 51,
>> + 'NODE_DPLL' : 52,
>> + 'NODE_RPLL' : 53,
>> + 'NODE_IOPLL' : 54,
>> + 'NODE_DDR' : 55,
>> + 'NODE_IPI_APU' : 56,
>> + 'NODE_IPI_RPU_0' : 57,
>> + 'NODE_GPU' : 58,
>> + 'NODE_PCIE' : 59,
>> + 'NODE_PCAP' : 60,
>> + 'NODE_RTC' : 61,
>> + 'NODE_LPD' : 62,
>> + 'NODE_VCU' : 63,
>> + 'NODE_IPI_RPU_1' : 64,
>> + 'NODE_IPI_PL_0' : 65,
>> + 'NODE_IPI_PL_1' : 66,
>> + 'NODE_IPI_PL_2' : 67,
>> + 'NODE_IPI_PL_3' : 68,
>> + 'NODE_PL' : 69,
>> + 'NODE_ID_MA' : 70,
>> +
>> + 'XILPM_RESET_PCIE_CFG' : 1000,
>> + 'XILPM_RESET_PCIE_BRIDGE' : 1001,
>> + 'XILPM_RESET_PCIE_CTRL' : 1002,
>> + 'XILPM_RESET_DP' : 1003,
>> + 'XILPM_RESET_SWDT_CRF' : 1004,
>> + 'XILPM_RESET_AFI_FM5' : 1005,
>> + 'XILPM_RESET_AFI_FM4' : 1006,
>> + 'XILPM_RESET_AFI_FM3' : 1007,
>> + 'XILPM_RESET_AFI_FM2' : 1008,
>> + 'XILPM_RESET_AFI_FM1' : 1009,
>> + 'XILPM_RESET_AFI_FM0' : 1010,
>> + 'XILPM_RESET_GDMA' : 1011,
>> + 'XILPM_RESET_GPU_PP1' : 1012,
>> + 'XILPM_RESET_GPU_PP0' : 1013,
>> + 'XILPM_RESET_GPU' : 1014,
>> + 'XILPM_RESET_GT' : 1015,
>> + 'XILPM_RESET_SATA' : 1016,
>> + 'XILPM_RESET_ACPU3_PWRON' : 1017,
>> + 'XILPM_RESET_ACPU2_PWRON' : 1018,
>> + 'XILPM_RESET_ACPU1_PWRON' : 1019,
>> + 'XILPM_RESET_ACPU0_PWRON' : 1020,
>> + 'XILPM_RESET_APU_L2' : 1021,
>> + 'XILPM_RESET_ACPU3' : 1022,
>> + 'XILPM_RESET_ACPU2' : 1023,
>> + 'XILPM_RESET_ACPU1' : 1024,
>> + 'XILPM_RESET_ACPU0' : 1025,
>> + 'XILPM_RESET_DDR' : 1026,
>> + 'XILPM_RESET_APM_FPD' : 1027,
>> + 'XILPM_RESET_SOFT' : 1028,
>> + 'XILPM_RESET_GEM0' : 1029,
>> + 'XILPM_RESET_GEM1' : 1030,
>> + 'XILPM_RESET_GEM2' : 1031,
>> + 'XILPM_RESET_GEM3' : 1032,
>> + 'XILPM_RESET_QSPI' : 1033,
>> + 'XILPM_RESET_UART0' : 1034,
>> + 'XILPM_RESET_UART1' : 1035,
>> + 'XILPM_RESET_SPI0' : 1036,
>> + 'XILPM_RESET_SPI1' : 1037,
>> + 'XILPM_RESET_SDIO0' : 1038,
>> + 'XILPM_RESET_SDIO1' : 1039,
>> + 'XILPM_RESET_CAN0' : 1040,
>> + 'XILPM_RESET_CAN1' : 1041,
>> + 'XILPM_RESET_I2C0' : 1042,
>> + 'XILPM_RESET_I2C1' : 1043,
>> + 'XILPM_RESET_TTC0' : 1044,
>> + 'XILPM_RESET_TTC1' : 1045,
>> + 'XILPM_RESET_TTC2' : 1046,
>> + 'XILPM_RESET_TTC3' : 1047,
>> + 'XILPM_RESET_SWDT_CRL' : 1048,
>> + 'XILPM_RESET_NAND' : 1049,
>> + 'XILPM_RESET_ADMA' : 1050,
>> + 'XILPM_RESET_GPIO' : 1051,
>> + 'XILPM_RESET_IOU_CC' : 1052,
>> + 'XILPM_RESET_TIMESTAMP' : 1053,
>> + 'XILPM_RESET_RPU_R50' : 1054,
>> + 'XILPM_RESET_RPU_R51' : 1055,
>> + 'XILPM_RESET_RPU_AMBA' : 1056,
>> + 'XILPM_RESET_OCM' : 1057,
>> + 'XILPM_RESET_RPU_PGE' : 1058,
>> + 'XILPM_RESET_USB0_CORERESET' : 1059,
>> + 'XILPM_RESET_USB1_CORERESET' : 1060,
>> + 'XILPM_RESET_USB0_HIBERRESET' : 1061,
>> + 'XILPM_RESET_USB1_HIBERRESET' : 1062,
>> + 'XILPM_RESET_USB0_APB' : 1063,
>> + 'XILPM_RESET_USB1_APB' : 1064,
>> + 'XILPM_RESET_IPI' : 1065,
>> + 'XILPM_RESET_APM_LPD' : 1066,
>> + 'XILPM_RESET_RTC' : 1067,
>> + 'XILPM_RESET_SYSMON' : 1068,
>> + 'XILPM_RESET_AFI_FM6' : 1069,
>> + 'XILPM_RESET_LPD_SWDT' : 1070,
>> + 'XILPM_RESET_FPD' : 1071,
>> + 'XILPM_RESET_RPU_DBG1' : 1072,
>> + 'XILPM_RESET_RPU_DBG0' : 1073,
>> + 'XILPM_RESET_DBG_LPD' : 1074,
>> + 'XILPM_RESET_DBG_FPD' : 1075,
>> + 'XILPM_RESET_APLL' : 1076,
>> + 'XILPM_RESET_DPLL' : 1077,
>> + 'XILPM_RESET_VPLL' : 1078,
>> + 'XILPM_RESET_IOPLL' : 1079,
>> + 'XILPM_RESET_RPLL' : 1080,
>> + 'XILPM_RESET_GPO3_PL_0' : 1081,
>> + 'XILPM_RESET_GPO3_PL_1' : 1082,
>> + 'XILPM_RESET_GPO3_PL_2' : 1083,
>> + 'XILPM_RESET_GPO3_PL_3' : 1084,
>> + 'XILPM_RESET_GPO3_PL_4' : 1085,
>> + 'XILPM_RESET_GPO3_PL_5' : 1086,
>> + 'XILPM_RESET_GPO3_PL_6' : 1087,
>> + 'XILPM_RESET_GPO3_PL_7' : 1088,
>> + 'XILPM_RESET_GPO3_PL_8' : 1089,
>> + 'XILPM_RESET_GPO3_PL_9' : 1090,
>> + 'XILPM_RESET_GPO3_PL_10' : 1091,
>> + 'XILPM_RESET_GPO3_PL_11' : 1092,
>> + 'XILPM_RESET_GPO3_PL_12' : 1093,
>> + 'XILPM_RESET_GPO3_PL_13' : 1094,
>> + 'XILPM_RESET_GPO3_PL_14' : 1095,
>> + 'XILPM_RESET_GPO3_PL_15' : 1096,
>> + 'XILPM_RESET_GPO3_PL_16' : 1097,
>> + 'XILPM_RESET_GPO3_PL_17' : 1098,
>> + 'XILPM_RESET_GPO3_PL_18' : 1099,
>> + 'XILPM_RESET_GPO3_PL_19' : 1100,
>> + 'XILPM_RESET_GPO3_PL_20' : 1101,
>> + 'XILPM_RESET_GPO3_PL_21' : 1102,
>> + 'XILPM_RESET_GPO3_PL_22' : 1103,
>> + 'XILPM_RESET_GPO3_PL_23' : 1104,
>> + 'XILPM_RESET_GPO3_PL_24' : 1105,
>> + 'XILPM_RESET_GPO3_PL_25' : 1106,
>> + 'XILPM_RESET_GPO3_PL_26' : 1107,
>> + 'XILPM_RESET_GPO3_PL_27' : 1108,
>> + 'XILPM_RESET_GPO3_PL_28' : 1109,
>> + 'XILPM_RESET_GPO3_PL_29' : 1110,
>> + 'XILPM_RESET_GPO3_PL_30' : 1111,
>> + 'XILPM_RESET_GPO3_PL_31' : 1112,
>> + 'XILPM_RESET_RPU_LS' : 1113,
>> + 'XILPM_RESET_PS_ONLY' : 1114,
>> + 'XILPM_RESET_PL' : 1115,
>> + 'XILPM_RESET_GPIO5_EMIO_92' : 1116,
>> + 'XILPM_RESET_GPIO5_EMIO_93' : 1117,
>> + 'XILPM_RESET_GPIO5_EMIO_94' : 1118,
>> + 'XILPM_RESET_GPIO5_EMIO_95' : 1119,
>> +
>> + 'PM_CONFIG_MASTER_SECTION_ID' : 0x101,
>> + 'PM_CONFIG_SLAVE_SECTION_ID' : 0x102,
>> + 'PM_CONFIG_PREALLOC_SECTION_ID' : 0x103,
>> + 'PM_CONFIG_POWER_SECTION_ID' : 0x104,
>> + 'PM_CONFIG_RESET_SECTION_ID' : 0x105,
>> + 'PM_CONFIG_SHUTDOWN_SECTION_ID' : 0x106,
>> + 'PM_CONFIG_SET_CONFIG_SECTION_ID' : 0x107,
>> + 'PM_CONFIG_GPO_SECTION_ID' : 0x108,
>> +
>> + 'PM_SLAVE_FLAG_IS_SHAREABLE' : 0x1,
>> + 'PM_MASTER_USING_SLAVE_MASK' : 0x2,
>> +
>> + 'PM_CONFIG_GPO1_MIO_PIN_34_MAP' : (1 << 10),
>> + 'PM_CONFIG_GPO1_MIO_PIN_35_MAP' : (1 << 11),
>> + 'PM_CONFIG_GPO1_MIO_PIN_36_MAP' : (1 << 12),
>> + 'PM_CONFIG_GPO1_MIO_PIN_37_MAP' : (1 << 13),
>> +
>> + 'PM_CONFIG_GPO1_BIT_2_MASK' : (1 << 2),
>> + 'PM_CONFIG_GPO1_BIT_3_MASK' : (1 << 3),
>> + 'PM_CONFIG_GPO1_BIT_4_MASK' : (1 << 4),
>> + 'PM_CONFIG_GPO1_BIT_5_MASK' : (1 << 5),
>> +
>> + 'SUSPEND_TIMEOUT' : 0xFFFFFFFF,
>> +
>> + 'PM_CONFIG_IPI_PSU_CORTEXA53_0_MASK' : 0x00000001,
>> + 'PM_CONFIG_IPI_PSU_CORTEXR5_0_MASK' : 0x00000100,
>> + 'PM_CONFIG_IPI_PSU_CORTEXR5_1_MASK' : 0x00000200,
>> +}
>> +
>> +in_file = open(args.in_file, mode='r')
>> +out_file = open(args.out_file, mode='wb')
>> +
>> +num_re = re.compile(r"^([0-9]+)U?$")
>> +const_re = re.compile(r"^([A-Z_][A-Z0-9_]*)$")
>> +
>> +def process_item(item):
>> + logging.debug("* ITEM " + item)
>> +
>> + value = 0
>> + for item in item.split('|'):
>> + item = item.strip()
>> +
>> + num_match = num_re .match(item)
>> + const_match = const_re.match(item)
>> +
>> + if num_match:
>> + num = int(num_match.group(1))
>> + logging.debug(" - num " + str(num))
>> + value |= num
>> + elif const_match:
>> + name = const_match.group(1)
>> + if not name in pm_define:
>> + sys.stderr.write("Unknown define " + name + "!\n")
>> + exit(1)
>> + num = pm_define[name]
>> + logging.debug(" - def " + hex(num))
>> + value |= num
>> +
>> + logging.debug(" = res " + hex(value))
>> + out_file.write(struct.pack('<L', value))
>> +
>> +
>> +# Read all code
>> +code = in_file.read()
>> +
>> +# remove comments
>> +code = re.sub('//.*?\n|/\*.*?\*/', '', code, flags=re.DOTALL)
>> +
>> +# remove everything outside the XPm_ConfigObject array definition
>> +code = re.search('const u32 XPm_ConfigObject.*= {\n(.*)};',
>> + code, flags=re.DOTALL).group(1)
>> +
>> +# Process each comma-separated array item
>> +for item in code.split(','):
>> + item = item.strip()
>> + if item:
>> + process_item(item.strip())
>> +
>> +print("Wrote %d bytes" % out_file.tell())
>>
>
>
> I have created simple script for extracting this object also from fsbl
> elf file. Maybe we should also publish it when this is out.
> For your reference.
>
> #!/bin/bash
> # Written by Michal Simek
>
> FSBL=zynqmp_fsbl
> PMCFG=pmcfg.bin
>
> PM_END=`aarch64-linux-gnu-objdump -D ${FSBL}.elf | sed -n
> '/XPm_ConfigObject/,/^$/p' | head -n -2 | tail -n 1 | cut -c 5-12 | awk
> '{printf ("0x%s",$1)}'`
> PM_START=`aarch64-linux-gnu-objdump -D ${FSBL}.elf | sed -n
> '/XPm_ConfigObject/,/^$/p' | head -n 1 | awk '{printf ("0x%s",$1)}'`
>
> FSBL_START=`aarch64-linux-gnu-readelf -a ${FSBL}.elf | grep "Entry point
> address" | awk '{print $4}'`
>
> PM_OBJECT_START=`echo $((${PM_START} - ${FSBL_START}))`
> PM_OBJECT_SIZE=`echo $((${PM_END} - ${PM_START}))`
>
> echo "FSBL starting address ${FSBL_START}"
> echo "FSBL object addresses ${PM_START} ${PM_END}"
> echo "OBJECT start ${PM_OBJECT_START} size ${PM_OBJECT_SIZE}"
>
> aarch64-linux-gnu-objcopy -O binary ${FSBL}.elf ${FSBL}.bin
>
> # Extracting config object
> dd if=${FSBL}.bin of=${PMCFG} bs=1 skip=${PM_OBJECT_START}
> count=${PM_OBJECT_SIZE} > /dev/null 2>&1
>
> echo "Your object ${PMCFG} is ready"
>
> rm -f ${FSBL}.bin *~
>
> Anyway this patch is good. I didn't test it but it looks ok.
Ok, thanks.
In the meantime I have been wondering whether it should be moved from
arch/arm/mach-zynqmp/pm_cfg_obj_convert.py to tools/ (and prefixed with
zynqmp_), where other tools are.
--
Luca
More information about the U-Boot
mailing list