| Message ID | 20251105093710.19582-12-Quirin.Gylstorff@siemens.com |
|---|---|
| State | Superseded |
| Headers | show |
| Series | Add support for dracut | expand |
On 05.11.25 10:29, Quirin Gylstorff wrote: > From: Quirin Gylstorff <quirin.gylstorff@siemens.com> > > This adds a helper class similar to initramfs-hook > to generate a dracut module based on dpkg-raw. > > Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com> > --- > meta/classes/dracut-module.bbclass | 87 +++++++++++++++++++ I would recommend using classes-recipe directly, then our series do not need to synchronize. Jan > .../dracut-module/files/module-setup.sh.tmpl | 42 +++++++++ > 2 files changed, 129 insertions(+) > create mode 100644 meta/classes/dracut-module.bbclass > create mode 100644 meta/recipes-initramfs/dracut-module/files/module-setup.sh.tmpl > > diff --git a/meta/classes/dracut-module.bbclass b/meta/classes/dracut-module.bbclass > new file mode 100644 > index 00000000..364fb5b4 > --- /dev/null > +++ b/meta/classes/dracut-module.bbclass > @@ -0,0 +1,87 @@ > +# > +# Copyright (c) Siemens AG, 2025 > +# > +# Authors: > +# Quirin Gylstorff <quirin.gylstorff@siemens.com> > +# > +# SPDX-License-Identifier: MIT > +# > + > +inherit dpkg-raw > + > +FILESPATH:append = ":${LAYERDIR_core}/recipes-initramfs/dracut-module/files" > + > +DPKG_ARCH = "all" > + > +DRACUT_MODULE_SETUP = "module-setup.sh" > +SRC_URI:append = "file://${DRACUT_MODULE_SETUP}.tmpl" > + > +DRACUT_MODULE_NO ??= "50" > +DRACUT_MODULE_NAME ?= "${@ d.getVar('PN')[7:] if d.getVar('PN').startswith('dracut-') else d.getVAR('PN')}" > + > +DEBIAN_DEPENDS = "dracut-core" > +DRACUT_MODULE_PATH = "${D}/usr/lib/dracut/modules.d/${DRACUT_MODULE_NO}${DRACUT_MODULE_NAME}/" > + > +DRACUT_REQUIRED_BINARIES ??= "" > +DRACUT_MODULE_DEPENDENCIES ??= "" > +DRACUT_CHECK_CONTENT_FILE_NAME ??= "" > +DRACUT_DEPENDS_CONTENT_FILE_NAME ??= "" > +DRACUT_CMDLINE_CONTENT_FILE_NAME ??= "" > +DRACUT_INSTALL_CONTENT_FILE_NAME ??= "" > +DRACUT_INSTALLKERNEL_CONTENT_FILE_NAME ??= "" > + > +def add_file_if_variable_is_set(d, variable_name, prefix): > + variable = d.getVar(variable_name) or '' > + if variable: > + return f"{prefix}{variable}" > + return '' > + > +def replace_marker_with_file_content(template_file, content_file, marker): > + with open(template_file, 'r') as template_fd: > + tmpl_content = template_fd.read() > + > + with open(content_file, 'r') as content_fd: > + content = content_fd.read() > + > + new_tpml_content = tmpl_content.replace(marker, content) > + with open(template_file, 'w') as tmpl_fd: > + tmpl_fd.write(new_tpml_content) > + > +SRC_URI:append = " ${@ add_file_if_variable_is_set(d, 'DRACUT_CHECK_CONTENT_FILE_NAME', 'file://')} \ > + ${@ add_file_if_variable_is_set(d, 'DRACUT_DEPENDS_CONTENT_FILE_NAME', 'file://')} \ > + ${@ add_file_if_variable_is_set(d, 'DRACUT_CMDLINE_CONTENT_FILE_NAME', 'file://')} \ > + ${@ add_file_if_variable_is_set(d, 'DRACUT_INSTALL_CONTENT_FILE_NAME', 'file://')} \ > + ${@ add_file_if_variable_is_set(d, 'DRACUT_INSTALLKERNEL_CONTENT_FILE_NAME', 'file://')}" > + > +TEMPLATE_FILES:append = " \ > + ${DRACUT_MODULE_SETUP}.tmpl \ > + " > + > +TEMPLATE_VARS:append = " \ > + DRACUT_REQUIRED_BINARIES \ > + DRACUT_MODULE_DEPENDENCIES \ > + " > +python do_add_additional_dracut_configuration() { > + workdir = os.path.normpath(d.getVar('WORKDIR')) > + module_setup = d.getVar('DRACUT_MODULE_SETUP') > + module_setup_tpml = f"{module_setup}.tmpl" > + content_file_name_to_marker = { > + "DRACUT_CHECK_CONTENT_FILE_NAME" : "# ISAR_DRACUT_CHECK", > + "DRACUT_DEPENDS_CONTENT_FILE_NAME" : "# ISAR_DRACUT_DEPENDS", > + "DRACUT_CMDLINE_CONTENT_FILE_NAME" : "# ISAR_DRACUT_CMDLINE", > + "DRACUT_INSTALL_CONTENT_FILE_NAME" : "# ISAR_DRACUT_INSTALL", > + "DRACUT_INSTALLKERNEL_CONTENT_FILE_NAME" : "# ISAR_DRACUT_KERNELINSTALL" > + } > + > + for var_name, marker in content_file_name_to_marker.items(): > + file_name = d.getVar(var_name) or '' > + if file_name: > + replace_marker_with_file_content(f"{workdir}/{module_setup_tpml}", > + f"{workdir}/{file_name}", marker) > +} > +addtask add_additional_dracut_configuration before do_transform_template after do_patch > + > +do_install[cleandirs] += "${DRACUT_MODULE_PATH}" > +do_install:append() { > + install -m 770 ${WORKDIR}/${DRACUT_MODULE_SETUP} ${DRACUT_MODULE_PATH} > +} > diff --git a/meta/recipes-initramfs/dracut-module/files/module-setup.sh.tmpl b/meta/recipes-initramfs/dracut-module/files/module-setup.sh.tmpl > new file mode 100644 > index 00000000..be0f4c54 > --- /dev/null > +++ b/meta/recipes-initramfs/dracut-module/files/module-setup.sh.tmpl > @@ -0,0 +1,42 @@ > +#!/bin/bash > + > +# called by dracut > +check() { > + > + # If the binary(s) requirements are not fulfilled the module can't be installed. > + require_binaries \ > + ${DRACUT_REQUIRED_BINARIES} \ > + || return 1 > + # ISAR_DRACUT_CHECK > + return 0 > + > +} > + > +# Module dependency requirements. > +depends() { > + echo "${DRACUT_MODULE_DEPENDENCIES}" > + # ISAR_DRACUT_DEPENDS > + return 0 > + > +} > +installkernel() { > + # ISAR_DRACUT_KERNELINSTALL > + return 0 > +} > + > +cmdline() { > + # ISAR_DRACUT_CMDLINE > + return 0 > +} > + > +install() { > + for executable in ${DRACUT_REQUIRED_BINARIES}; do > + if exec_path=$(command -v $executable 2>/dev/null); then > + inst_binary "$exec_path" > + else > + echo "(ERROR): Unable to copy $executable" >&2 > + exit 1 > + fi > + done > + # ISAR_DRACUT_INSTALL > +}
diff --git a/meta/classes/dracut-module.bbclass b/meta/classes/dracut-module.bbclass new file mode 100644 index 00000000..364fb5b4 --- /dev/null +++ b/meta/classes/dracut-module.bbclass @@ -0,0 +1,87 @@ +# +# Copyright (c) Siemens AG, 2025 +# +# Authors: +# Quirin Gylstorff <quirin.gylstorff@siemens.com> +# +# SPDX-License-Identifier: MIT +# + +inherit dpkg-raw + +FILESPATH:append = ":${LAYERDIR_core}/recipes-initramfs/dracut-module/files" + +DPKG_ARCH = "all" + +DRACUT_MODULE_SETUP = "module-setup.sh" +SRC_URI:append = "file://${DRACUT_MODULE_SETUP}.tmpl" + +DRACUT_MODULE_NO ??= "50" +DRACUT_MODULE_NAME ?= "${@ d.getVar('PN')[7:] if d.getVar('PN').startswith('dracut-') else d.getVAR('PN')}" + +DEBIAN_DEPENDS = "dracut-core" +DRACUT_MODULE_PATH = "${D}/usr/lib/dracut/modules.d/${DRACUT_MODULE_NO}${DRACUT_MODULE_NAME}/" + +DRACUT_REQUIRED_BINARIES ??= "" +DRACUT_MODULE_DEPENDENCIES ??= "" +DRACUT_CHECK_CONTENT_FILE_NAME ??= "" +DRACUT_DEPENDS_CONTENT_FILE_NAME ??= "" +DRACUT_CMDLINE_CONTENT_FILE_NAME ??= "" +DRACUT_INSTALL_CONTENT_FILE_NAME ??= "" +DRACUT_INSTALLKERNEL_CONTENT_FILE_NAME ??= "" + +def add_file_if_variable_is_set(d, variable_name, prefix): + variable = d.getVar(variable_name) or '' + if variable: + return f"{prefix}{variable}" + return '' + +def replace_marker_with_file_content(template_file, content_file, marker): + with open(template_file, 'r') as template_fd: + tmpl_content = template_fd.read() + + with open(content_file, 'r') as content_fd: + content = content_fd.read() + + new_tpml_content = tmpl_content.replace(marker, content) + with open(template_file, 'w') as tmpl_fd: + tmpl_fd.write(new_tpml_content) + +SRC_URI:append = " ${@ add_file_if_variable_is_set(d, 'DRACUT_CHECK_CONTENT_FILE_NAME', 'file://')} \ + ${@ add_file_if_variable_is_set(d, 'DRACUT_DEPENDS_CONTENT_FILE_NAME', 'file://')} \ + ${@ add_file_if_variable_is_set(d, 'DRACUT_CMDLINE_CONTENT_FILE_NAME', 'file://')} \ + ${@ add_file_if_variable_is_set(d, 'DRACUT_INSTALL_CONTENT_FILE_NAME', 'file://')} \ + ${@ add_file_if_variable_is_set(d, 'DRACUT_INSTALLKERNEL_CONTENT_FILE_NAME', 'file://')}" + +TEMPLATE_FILES:append = " \ + ${DRACUT_MODULE_SETUP}.tmpl \ + " + +TEMPLATE_VARS:append = " \ + DRACUT_REQUIRED_BINARIES \ + DRACUT_MODULE_DEPENDENCIES \ + " +python do_add_additional_dracut_configuration() { + workdir = os.path.normpath(d.getVar('WORKDIR')) + module_setup = d.getVar('DRACUT_MODULE_SETUP') + module_setup_tpml = f"{module_setup}.tmpl" + content_file_name_to_marker = { + "DRACUT_CHECK_CONTENT_FILE_NAME" : "# ISAR_DRACUT_CHECK", + "DRACUT_DEPENDS_CONTENT_FILE_NAME" : "# ISAR_DRACUT_DEPENDS", + "DRACUT_CMDLINE_CONTENT_FILE_NAME" : "# ISAR_DRACUT_CMDLINE", + "DRACUT_INSTALL_CONTENT_FILE_NAME" : "# ISAR_DRACUT_INSTALL", + "DRACUT_INSTALLKERNEL_CONTENT_FILE_NAME" : "# ISAR_DRACUT_KERNELINSTALL" + } + + for var_name, marker in content_file_name_to_marker.items(): + file_name = d.getVar(var_name) or '' + if file_name: + replace_marker_with_file_content(f"{workdir}/{module_setup_tpml}", + f"{workdir}/{file_name}", marker) +} +addtask add_additional_dracut_configuration before do_transform_template after do_patch + +do_install[cleandirs] += "${DRACUT_MODULE_PATH}" +do_install:append() { + install -m 770 ${WORKDIR}/${DRACUT_MODULE_SETUP} ${DRACUT_MODULE_PATH} +} diff --git a/meta/recipes-initramfs/dracut-module/files/module-setup.sh.tmpl b/meta/recipes-initramfs/dracut-module/files/module-setup.sh.tmpl new file mode 100644 index 00000000..be0f4c54 --- /dev/null +++ b/meta/recipes-initramfs/dracut-module/files/module-setup.sh.tmpl @@ -0,0 +1,42 @@ +#!/bin/bash + +# called by dracut +check() { + + # If the binary(s) requirements are not fulfilled the module can't be installed. + require_binaries \ + ${DRACUT_REQUIRED_BINARIES} \ + || return 1 + # ISAR_DRACUT_CHECK + return 0 + +} + +# Module dependency requirements. +depends() { + echo "${DRACUT_MODULE_DEPENDENCIES}" + # ISAR_DRACUT_DEPENDS + return 0 + +} +installkernel() { + # ISAR_DRACUT_KERNELINSTALL + return 0 +} + +cmdline() { + # ISAR_DRACUT_CMDLINE + return 0 +} + +install() { + for executable in ${DRACUT_REQUIRED_BINARIES}; do + if exec_path=$(command -v $executable 2>/dev/null); then + inst_binary "$exec_path" + else + echo "(ERROR): Unable to copy $executable" >&2 + exit 1 + fi + done + # ISAR_DRACUT_INSTALL +}