# Copyright (c) 2023 Intel Corporation
# SPDX-License-Identifier: Apache-2.0

menuconfig LLEXT
	bool "Linkable loadable extensions"
	select CACHE_MANAGEMENT if DCACHE
	select KERNEL_WHOLE_ARCHIVE
	help
	  Enable the linkable loadable extension subsystem

if LLEXT

choice LLEXT_BINARY_TYPE
	prompt "Binary object type for llext"
	default LLEXT_TYPE_ELF_OBJECT if ARM || ARM64
	default LLEXT_TYPE_ELF_SHAREDLIB if XTENSA
	default LLEXT_TYPE_ELF_RELOCATABLE if RISCV
	help
	  Object type for llext

config LLEXT_TYPE_ELF_OBJECT
	bool "Single object ELF file"
	depends on !RISCV
	help
	  Build and expect object files as binary object type for the
	  llext subsystem. A single compiler invocation is used to
	  generate the object file. Currently not supported on RISC-V.

config LLEXT_TYPE_ELF_RELOCATABLE
	bool "Relocatable ELF file"
	help
	  Build and expect relocatable (partially linked) files as the
	  binary object type for the llext subsystem. These object files
	  are generated by the linker by combining multiple object files
	  into a single one.

config LLEXT_TYPE_ELF_SHAREDLIB
	bool "Shared library ELF file"
	help
	  Build and expect shared libraries as binary object type for
	  the llext subsystem. The usual linking process is used to
	  generate the shared library from multiple object files.

endchoice

config LLEXT_HEAP_DYNAMIC
	bool "Do not allocate static LLEXT heap"
	help
	  Some applications require loading extensions into the memory which does not
	  exist during the boot time and cannot be allocated statically. Make the application
	  responsible for LLEXT heap allocation. Do not allocate LLEXT heap statically.

	  Application must call llext_heap_init() in order to assign a buffer to be used
	  as the LLEXT heap, otherwise LLEXT modules will not load. When the application
	  does not need LLEXT functionality any more, it should call llext_heap_uninit(),
	  which releases control of the buffer back to the application.

choice LLEXT_HEAP_MANAGEMENT
	prompt "llext heap memory management"
	default LLEXT_HEAP_K_HEAP
	help
	  Select the memory management API used to store extension regions in
	  LLEXT heap memory. This choice does not affect LLEXT metadata, which is always
	  managed with k_heap.

config LLEXT_HEAP_K_HEAP
	bool "Use k_heap"
	help
	  Use the k_heap API to manage LLEXT heap memory for extension regions.
	  k_heap allocates additional memory for bookkeeping data after the
	  requested allocation, which increases the memory overhead slightly
	  and may cause misalignment with MPU regions.

config LLEXT_HEAP_MEMBLK
	bool "Use sys_mem_blocks"
	depends on !LLEXT_HEAP_DYNAMIC
	select SYS_MEM_BLOCKS
	help
	  Use sys_mem_blocks API to manage LLEXT heap memory for extension regions.
	  A minimum of one block will be allocated per region. Block size must be
	  selected with care to ensure proper alignment for extension regions.

endchoice

config LLEXT_HEAP_SIZE
	int "llext heap memory size in kilobytes"
	depends on !LLEXT_HEAP_DYNAMIC && !HARVARD && !LLEXT_HEAP_MEMBLK
	default 8
	help
	  Heap size in kilobytes available to llext for dynamic allocation. Replaced by
	  LLEXT_INSTR_HEAP_SIZE and LLEXT_DATA_HEAP_SIZE if HARVARD is selected.

if LLEXT_HEAP_MEMBLK

config LLEXT_METADATA_HEAP_SIZE
	int "llext metadata heap memory size in kilobytes"
	default 4
	help
	  Heap size in kilobytes available for LLEXT metadata.

config LLEXT_EXT_HEAP_SIZE
	int "llext extension heap memory size in kilobytes"
	depends on !HARVARD
	default 16
	help
	  Heap size in kilobytes available for LLEXT extension regions. Must be a multiple
	  of LLEXT_HEAP_MEMBLK_BLOCK_SIZE. Replaced by LLEXT_INSTR_HEAP_SIZE and
	  LLEXT_DATA_HEAP_SIZE if HARVARD is selected.

config LLEXT_HEAP_MEMBLK_BLOCK_SIZE
	int "llext sys_mem_blocks block size in bytes"
	default 32
	help
	  Block size in bytes for LLEXT sys_mem_blocks heap(s). Must be equal to or
	  a multiple of LLEXT_PAGE_SIZE. The block size must also be equal to or a
	  multiple of the largest alignment needed for any extension region.
	  If MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT is selected and regions are large,
	  an unreasonably large block size may be needed to satisfy alignment requirements.

endif

config LLEXT_INSTR_HEAP_SIZE
	int "llext instruction heap memory size in kilobytes"
	depends on !LLEXT_HEAP_DYNAMIC && HARVARD
	default 4
	help
	  Instruction heap size in kilobytes available to llext.
	  Only executable regions will be placed in this heap.

config LLEXT_DATA_HEAP_SIZE
	int "llext data heap memory size in kilobytes"
	depends on !LLEXT_HEAP_DYNAMIC && HARVARD
	default 8
	help
	  Data heap size in kilobytes available to llext.

config LLEXT_BUILD_PIC
	bool "Use -fPIC when building LLEXT"
	depends on XTENSA
	default y if LLEXT_TYPE_ELF_SHAREDLIB
	help
	  By default LLEXT compilation is performed with -fno-pic -fno-pie compiler
	  flags. Some platforms can benefit from using -fPIC instead, in which case
	  most internal linking is performed by the linker at build time. Select "y"
	  to make use of that advantage.

config LLEXT_SHELL
	bool "llext shell commands"
	depends on SHELL
	help
	  Manage llext with shell commands for loading, unloading, and introspection

config LLEXT_SHELL_MAX_SIZE
	int "Maximum size of llext in bytes"
	depends on LLEXT_SHELL
	default 8192
	help
	  When loading llext with shell it is stored in a temporary buffer of this size

config LLEXT_STORAGE_WRITABLE
	bool "llext storage is writable"
	default y if XTENSA
	help
	  Select if LLEXT storage is writable, i.e. if extensions are stored in
	  RAM and can be modified in place

config LLEXT_RODATA_NO_RELOC
	bool "Keep read-only data without relocations in flash"
	depends on !MMU && !USERSPACE
	help
	  When enabled, read-only data sections (.rodata) that do not have
	  any relocations are kept in their original location (typically flash)
	  instead of being copied to RAM.

	  This is useful for large constant data like certificates, lookup
	  tables, or string literals that don't contain any pointers.

	  This feature requires the extension to manually tag that data with
	  the LLEXT_RODATA_NO_RELOC macro.

config LLEXT_EXPORT_DEVICES
	bool "Export all DT devices to llexts"
	select LLEXT_EXPORT_SYMBOL_GROUP_DEVICE
	help
	  When enabled, all Zephyr devices defined in the device tree are
	  made available to llexts via the standard DT_ / DEVICE_* macros.

config LLEXT_EXPORT_DEV_IDS_BY_HASH
	bool "Use hash of device path in device name"
	depends on LLEXT_EXPORT_SYMBOL_GROUP_DEVICE
	help
	  When enabled, exported device names are generated from a hash of the
	  node path instead of an ordinal number. Identifiers generated this
	  way are stable across rebuilds.

config LLEXT_EXPORT_BUILTINS_BY_SLID
	bool "Export built-in symbols to llexts via SLIDs"
	help
	  When enabled, symbols exported from the Zephyr kernel
	  or application (via EXPORT_SYMBOL) are linked to LLEXTs
	  via Symbol Link Identifiers (SLIDs) instead of name.

	  Enabling this option provides a huge size reduction,
	  makes the linking process faster and provides more
	  confidentiality, as exported symbol names are dropped
	  from the binary. However, it can make LLEXT debugging
	  harder and prevents usage of 'llext_find_sym' to look
	  up symbols from the built-in table by name. It also
	  requires the LLEXTs to be post-processed after build.

config LLEXT_IMPORT_ALL_GLOBALS
	bool "Import all global symbols from extensions"
	help
	  When loading an extension, by default only symbols that are mentioned
	  in the '.exported_sym' section (possibly via EXPORT_SYMBOL) are made
	  available to the Zephyr core.

	  This option instead allows all global symbols from extensions to be
	  used by the main application. This is useful to load basic extensions
	  that have been compiled without the full Zephyr EDK.

config LLEXT_EXPERIMENTAL
	bool "LLEXT experimental functionality"
	help
	  Include support for LLEXT experimental and unstable functionality that
	  has a very high likelihood to change in the future.

menu "Customize compiler options for LLEXT"

choice LLEXT_CODEGEN_VLIW
	prompt "VLIW code generation"
	default LLEXT_CODEGEN_VLIW_INHERIT
	help
	  This option allows customization of global compiler settings with regards to
	  generating VLIW (Very Long Instruction Word) instructions for all LLEXT
	  modules.

config LLEXT_CODEGEN_VLIW_INHERIT
	bool "Inherit settings"
	help
	  Preserve global complier settings with regards to VLIW.

config LLEXT_CODEGEN_VLIW_ENABLED
	bool "Generate VLIW"
	help
	  Customize global complier settings by instructing the compiler to generate
	  VLIW instructions for LLEXT modules if possible.

config LLEXT_CODEGEN_VLIW_DISABLED
	bool "DO NOT generate VLIW"
	help
	  Customize global complier settings by instructing the compiler to NEVER
	  generate VLIW instructions for LLEXT modules.

endchoice # LLEXT_CODEGEN_VLIW

endmenu # Customize Compiler Options for LLEXT

menu "Exported symbol groups"

config LLEXT_EXPORT_DEFAULT_GROUPS
	bool "Export the default set of Zephyr application symbols"
	default y
	help
	  Exports default, syscall and libc symbols

config LLEXT_EXPORT_SYMBOL_GROUP_UNASSIGNED
	bool "Export all symbols from the UNASSIGNED group"
	default y if LLEXT_EXPORT_DEFAULT_GROUPS
	help
	  Exports all symbols declared without an explicit group.

config LLEXT_EXPORT_SYMBOL_GROUP_SYSCALL
	bool "Export all syscalls"
	default y if LLEXT_EXPORT_DEFAULT_GROUPS
	help
	  Exports all syscall symbols.

config LLEXT_EXPORT_SYMBOL_GROUP_LIBC
	bool "Export standard library symbols"
	default y if LLEXT_EXPORT_DEFAULT_GROUPS
	help
	  Export symbols such as memcpy, memset, strlen.

config LLEXT_EXPORT_SYMBOL_GROUP_DEVICE
	bool "Export Zephyr devices"
	help
	  When enabled, all Zephyr devices defined in the device tree are
	  made available to llexts via the standard DT_ / DEVICE_* macros.

endmenu

module = LLEXT
module-str = llext
source "subsys/logging/Kconfig.template.log_config"

endif

menuconfig LLEXT_EDK
	bool "Linkable loadable Extension Development Kit (EDK)"
	default y if LLEXT
	help
	  Enable the generation of an Extension Development Kit (EDK) for the
	  Linkable Loadable Extension subsystem. The EDK is an archive that
	  contains the necessary files and build settings to build extensions
	  for Zephyr without the need to have the full Zephyr source tree.

if LLEXT_EDK

config LLEXT_EDK_NAME
	string "Name for llext EDK (Extension Development Kit)"
	default "llext-edk"
	help
	  <name> will be used when generating the EDK file; the appropriate
	  extension will be appended depending on the chosen output format.
	  It will also be used, normalized, as the prefix for the variable
	  stating EDK location, used on generated Makefile.cflags. For
	  instance, the default name, "llext-edk", becomes LLEXT_EDK_INSTALL_DIR.

choice LLEXT_EDK_FORMAT
	prompt "EDK compression and output format"
	default LLEXT_EDK_FORMAT_TAR_ZSTD if LLEXT_EDK_PRESERVE_INPUT_FOLDER
	default LLEXT_EDK_FORMAT_TAR_XZ

config LLEXT_EDK_FORMAT_TAR_XZ
	bool ".tar.xz"
	help
	  Use GNU tar with XZ compression for the EDK file. Highest compression
	  ratio, slower choice.

config LLEXT_EDK_FORMAT_TAR_ZSTD
	bool ".tar.Z"
	help
	  Use GNU tar with Zstd compression for the EDK file. Way faster than
	  XZ, but still with a high compression ratio.

config LLEXT_EDK_FORMAT_ZIP
	bool ".zip"
	help
	  Use Zip format and compression for the EDK file. This is the most
	  portable option, but it may not compress as well as XZ or Zstd.

endchoice

config LLEXT_EDK_USERSPACE_ONLY
	bool "Only generate the Userspace codepath on syscall stubs for the EDK"
	help
	  Syscall stubs can contain code that verifies if running code is at user
	  or kernel space and route the call accordingly. If the EDK is expected
	  to be used by userspace only extensions, this option will make EDK stubs
	  not contain the routing code, and only generate the userspace one.

config LLEXT_EDK_PRESERVE_INPUT_FOLDER
	bool "Don't delete the EDK source folder"

endif
