Skip to content

Commit fa5a57d

Browse files
lyakhlgirdwood
authored andcommitted
llext: add support for library building
Build libraries of modules, as specified in their cmake files. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
1 parent 1240efb commit fa5a57d

2 files changed

Lines changed: 122 additions & 45 deletions

File tree

scripts/llext_offset_calc.py

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import argparse
77
import pathlib
88
import os
9+
from elftools.elf.elffile import ELFFile
10+
from elftools.elf.constants import SH_FLAGS
911

1012
args = None
1113

@@ -21,6 +23,34 @@ def parse_args():
2123

2224
args = parser.parse_args()
2325

26+
def get_elf_size(elf_name):
27+
start = 0xffffffff
28+
# SOF_MODULE_DRAM_LINK_END
29+
min_start = 0x08000000
30+
end = 0
31+
with open(elf_name, 'rb') as f_elf:
32+
elf = ELFFile(f_elf)
33+
34+
for section in elf.iter_sections():
35+
s_flags = section.header['sh_flags']
36+
37+
if not s_flags & SH_FLAGS.SHF_ALLOC:
38+
continue
39+
40+
# Ignore detached sections, to be used in DRAM, their addresses
41+
# are below min_start
42+
if section.header['sh_addr'] < min_start:
43+
continue
44+
45+
if section.header['sh_addr'] < start:
46+
start = section.header['sh_addr']
47+
if section.header['sh_addr'] + section.header['sh_size'] > end:
48+
end = section.header['sh_addr'] + section.header['sh_size']
49+
50+
size = end - start
51+
52+
return size
53+
2454
def main():
2555
global args
2656

@@ -34,13 +64,12 @@ def main():
3464
except OSError:
3565
size = 0
3666

37-
# Failure will raise an exception
38-
f_size = open(f_output, "w")
39-
67+
size += get_elf_size(args.input) + 0xfff
4068
# align to a page border
41-
size += os.path.getsize(args.input) + 0xfff
4269
size &= ~0xfff
4370

71+
# Failure will raise an exception
72+
f_size = open(f_output, "w")
4473
f_size.write(f'0x{size:x}\n')
4574

4675
if __name__ == "__main__":

scripts/xtensa-build-zephyr.py

Lines changed: 89 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -948,19 +948,26 @@ def build_platforms():
948948
symlinks=True, ignore_dangling_symlinks=True, dirs_exist_ok=True)
949949

950950

951-
def install_lib(sof_lib_dir, abs_build_dir, platform_wconfig):
951+
def install_lib(platform, sof_output_dir, abs_build_dir, platform_wconfig):
952952
"""[summary] Sign loadable llext modules, if any, copy them to the
953953
deployment tree and create UUID links for the kernel to find and load
954954
them."""
955955

956956
global signing_key
957957

958-
with os.scandir(str(abs_build_dir)) as iter:
959-
if args.key_type_subdir != "none":
960-
sof_lib_dir = sof_lib_dir / args.key_type_subdir
958+
libs = dict()
959+
lib_uuids = dict()
960+
rimage_cmd = shlex.split(platform_wconfig.get('rimage.path'))[0]
961+
_ws_args = platform_wconfig.get("rimage.extra-args")
962+
963+
sof_lib_dir = sof_output_dir / '..' / 'sof-ipc4-lib' / platform
961964

962-
sof_lib_dir.mkdir(parents=True, exist_ok=True)
965+
if args.key_type_subdir != "none":
966+
sof_lib_dir = sof_lib_dir / args.key_type_subdir
967+
968+
sof_lib_dir.mkdir(parents=True, exist_ok=True)
963969

970+
with os.scandir(str(abs_build_dir)) as iter:
964971
for entry in iter:
965972
if (not entry.is_dir or
966973
not entry.name.endswith('_llext')):
@@ -977,45 +984,87 @@ def install_lib(sof_lib_dir, abs_build_dir, platform_wconfig):
977984
# eq_iir_llext/eq_iir.llext
978985
llext_base = entry.name[:-6]
979986
llext_file = llext_base + '.llext'
980-
981-
dst = sof_lib_dir / llext_file
982-
983-
rimage_cfg = entry_path / 'rimage_config.toml'
984-
llext_input = entry_path / (llext_base + '.llext')
985-
llext_output = entry_path / (llext_file + '.ri')
986-
987-
# See why the shlex() parsing step is required at
988-
# https://docs.zephyrproject.org/latest/develop/west/sign.html#rimage
989-
# and in Zephyr commit 030b740bd1ec
990-
rimage_cmd = shlex.split(platform_wconfig.get('rimage.path'))[0]
991-
sign_cmd = [rimage_cmd, "-o", str(llext_output),
992-
"-e", "-c", str(rimage_cfg),
993-
"-k", str(signing_key), "-l", "-r"]
994-
_ws_args = platform_wconfig.get("rimage.extra-args")
995-
if _ws_args is not None:
996-
sign_cmd.extend(shlex.split(_ws_args))
997-
sign_cmd.append(str(llext_input))
998-
execute_command(sign_cmd, cwd=west_top)
999-
1000-
# An intuitive way to make this multiline would be
1001-
# with (open(dst, 'wb') as fdst, open(llext_output, 'rb') as fllext,
1002-
# open(llext_output.with_suffix('.llext.xman'), 'rb') as fman):
1003-
# but a Python version, used on Windows errored out on this.
1004-
# Thus we're left with a choice between a 150-character
1005-
# long line and an illogical split like this
1006-
with open(dst, 'wb') as fdst, open(llext_output, 'rb') as fllext, open(
1007-
llext_output.with_suffix('.ri.xman'), 'rb') as fman:
1008-
# Concatenate the manifest and the llext
1009-
shutil.copyfileobj(fman, fdst)
1010-
shutil.copyfileobj(fllext, fdst)
987+
lib_name = ''
988+
989+
lib_fname = entry_path / 'lib_name.txt'
990+
if os.path.exists(lib_fname):
991+
with open(lib_fname, 'r') as libs_f:
992+
lib_name = libs_f.read()
993+
if lib_name not in libs.keys():
994+
libs[lib_name] = []
995+
libs[lib_name].append(str(entry_path / llext_file))
996+
else:
997+
dst = sof_lib_dir / llext_file
998+
999+
rimage_cfg = entry_path / 'rimage_config.toml'
1000+
llext_input = entry_path / (llext_base + '.llext')
1001+
llext_output = entry_path / (llext_file + '.ri')
1002+
1003+
# See why the shlex() parsing step is required at
1004+
# https://docs.zephyrproject.org/latest/develop/west/sign.html#rimage
1005+
# and in Zephyr commit 030b740bd1ec
1006+
sign_cmd = [rimage_cmd, "-o", str(llext_output),
1007+
"-e", "-c", str(rimage_cfg),
1008+
"-k", str(signing_key), "-l", "-r"]
1009+
if _ws_args is not None:
1010+
sign_cmd.extend(shlex.split(_ws_args))
1011+
sign_cmd.append(str(llext_input))
1012+
execute_command(sign_cmd, cwd=west_top)
1013+
1014+
# An intuitive way to make this multiline would be
1015+
# with (open(dst, 'wb') as fdst, open(llext_output, 'rb') as fllext,
1016+
# open(llext_output.with_suffix('.llext.xman'), 'rb') as fman):
1017+
# but a Python version, used on Windows errored out on this.
1018+
# Thus we're left with a choice between a 150-character
1019+
# long line and an illogical split like this
1020+
with open(dst, 'wb') as fdst, open(llext_output, 'rb') as fllext, open(
1021+
llext_output.with_suffix('.ri.xman'), 'rb') as fman:
1022+
# Concatenate the manifest and the llext
1023+
shutil.copyfileobj(fman, fdst)
1024+
shutil.copyfileobj(fllext, fdst)
10111025

10121026
# Create symbolic links for all UUIDs
10131027
with open(uuids, 'r') as uuids_f:
10141028
for uuid in uuids_f:
1015-
linkname = uuid.strip() + '.bin'
1016-
symlink_or_copy(sof_lib_dir, llext_file,
1017-
sof_lib_dir, linkname)
1029+
if os.path.exists(lib_fname):
1030+
if lib_name not in lib_uuids.keys():
1031+
lib_uuids[lib_name] = []
1032+
lib_uuids[lib_name].append(uuid.strip())
1033+
else:
1034+
linkname = uuid.strip() + '.bin'
1035+
symlink_or_copy(sof_lib_dir, llext_file,
1036+
sof_lib_dir, linkname)
1037+
1038+
lib_install_dir = sof_output_dir / platform
1039+
if args.key_type_subdir != "none":
1040+
lib_install_dir = lib_install_dir / args.key_type_subdir
1041+
1042+
for key in libs.keys():
1043+
lib_path = abs_build_dir / ''.join(['lib', key, '.ri'])
1044+
sign_cmd = [rimage_cmd, "-o", str(lib_path), "-e",
1045+
"-c", str(abs_build_dir / 'misc' / 'generated' / 'rimage_config_full.toml'),
1046+
"-k", str(signing_key), "-l", "-r"]
1047+
if _ws_args is not None:
1048+
sign_cmd.extend(shlex.split(_ws_args))
1049+
sign_cmd.extend(libs[key])
1050+
execute_command(sign_cmd, cwd=west_top)
1051+
lib_name = ''.join(['sof-', platform, '-', key, '.ri'])
1052+
dst = lib_install_dir / lib_name
1053+
with open(dst, 'wb') as fdst, open(lib_path, 'rb') as fllext, open(
1054+
lib_path.with_suffix('.ri.xman'), 'rb') as fman:
1055+
# Concatenate the manifest and the llext
1056+
shutil.copyfileobj(fman, fdst)
1057+
shutil.copyfileobj(fllext, fdst)
1058+
1059+
for p_alias in platform_configs[platform].aliases:
1060+
lib_dir = sof_output_dir / p_alias
10181061

1062+
if args.key_type_subdir != "none":
1063+
lib_dir = lib_dir / args.key_type_subdir
1064+
lib_dir.mkdir(parents=True, exist_ok=True)
1065+
alias_libname = ''.join(['sof-', p_alias, '-', key, '.ri'])
1066+
symlink_or_copy(lib_install_dir, lib_name,
1067+
lib_dir, alias_libname)
10191068

10201069
def install_platform(platform, sof_output_dir, platf_build_environ, platform_wconfig):
10211070

@@ -1064,8 +1113,7 @@ def install_platform(platform, sof_output_dir, platf_build_environ, platform_wco
10641113
symlink_or_copy(install_key_dir, output_fwname, install_key_dir, f"sof-{p_alias}.ri")
10651114

10661115
if args.deployable_build and platform_configs[platform].ipc4:
1067-
install_lib(sof_output_dir / '..' / 'sof-ipc4-lib' / platform, abs_build_dir,
1068-
platform_wconfig)
1116+
install_lib(platform, sof_output_dir, abs_build_dir, platform_wconfig)
10691117

10701118

10711119
# sof-info/ directory

0 commit comments

Comments
 (0)