zephyr/scripts/gen_app_partitions.py

113 lines
3.7 KiB
Python

#!/usr/bin/env python3
import sys
import argparse
import os
import re
import string
from elf_helper import ElfHelper
from elftools.elf.elffile import ELFFile
# This script will create linker comands for power of two aligned MPU
# when APP_SHARED_MEM is enabled.
print_template = """
/* Auto generated code do not modify */
. = ALIGN( 1 << LOG2CEIL(data_smem_{0}b_end - data_smem_{0}));
data_smem_{0} = .;
KEEP(*(SORT(data_smem_{0}*)))
. = ALIGN(_app_data_align);
. = ALIGN( 1 << LOG2CEIL(data_smem_{0}b_end - data_smem_{0}));
data_smem_{0}b_end = .;
"""
linker_start_seq = """
SECTION_PROLOGUE(_APP_SMEM_SECTION_NAME, (OPTIONAL),)
{
APP_SHARED_ALIGN;
_image_ram_start = .;
_app_smem_start = .;
"""
linker_end_seq = """
_app_smem_end = .;
APP_SHARED_ALIGN;
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
"""
size_cal_string = """
data_smem_{0}_size = data_smem_{0}b_end - data_smem_{0};
"""
def find_partitions(filename, full_list_of_partitions, partitions_source_file):
with open(filename, 'rb') as f:
full_lib = ELFFile( f)
if (not full_lib):
print("Error parsing file: ",filename)
os.exit(1)
sections = [ x for x in full_lib.iter_sections()]
for section in sections:
if ("smem" in section.name and not ".rel" in section.name):
partition_name = section.name.split("data_smem_")[1]
if partition_name not in full_list_of_partitions:
full_list_of_partitions.append(partition_name)
if args.verbose:
partitions_source_file.update({partition_name: filename})
return( full_list_of_partitions, partitions_source_file)
def cleanup_remove_bss_regions(full_list_of_partitions):
for partition in full_list_of_partitions:
if (partition+"b" in full_list_of_partitions):
full_list_of_partitions.remove(partition+"b")
return full_list_of_partitions
def generate_final_linker(linker_file, full_list_of_partitions):
string = linker_start_seq
size_string = ''
for partition in full_list_of_partitions:
string += print_template.format(partition)
size_string += size_cal_string.format(partition)
string += linker_end_seq
string += size_string
with open(linker_file, "w") as fw:
fw.write(string)
def parse_args():
global args
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("-d", "--directory", required=True,
help="Root build directory")
parser.add_argument("-o", "--output", required=False,
help="Output ld file")
parser.add_argument("-v", "--verbose", action="count", default =0,
help="Verbose Output")
args = parser.parse_args()
def main():
parse_args()
root_directory = args.directory
linker_file = args.output
full_list_of_partitions = []
partitions_source_file= {}
for dirpath, dirs, files in os.walk(root_directory):
for filename in files:
if re.match(".*\.obj$",filename):
fullname = os.path.join(dirpath, filename)
full_list_of_partitions, partitions_source_file = find_partitions(fullname, full_list_of_partitions, partitions_source_file)
full_list_of_partitions = cleanup_remove_bss_regions(full_list_of_partitions)
generate_final_linker(linker_file, full_list_of_partitions)
if args.verbose:
print("Partitions retrieved: PARTITION, FILENAME")
print([key + " "+ partitions_source_file[key] for key in full_list_of_partitions])
if __name__ == '__main__':
main()