Commit 549d3c2f authored by FUJITA Tomonori's avatar FUJITA Tomonori Committed by Miguel Ojeda
Browse files

rust: add 'firmware' field support to module! macro



This adds 'firmware' field support to module! macro, corresponds to
MODULE_FIRMWARE macro. You can specify the file names of binary
firmware that the kernel module requires. The information is embedded
in the modinfo section of the kernel module. For example, a tool to
build an initramfs uses this information to put the firmware files
into the initramfs image.

Signed-off-by: default avatarFUJITA Tomonori <fujita.tomonori@gmail.com>
Reviewed-by: default avatarBenno Lossin <benno.lossin@proton.me>
Link: https://lore.kernel.org/r/20240501123548.51769-1-fujita.tomonori@gmail.com


Signed-off-by: default avatarMiguel Ojeda <ojeda@kernel.org>
parent 63249a07
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -56,6 +56,36 @@
/// }
/// ```
///
/// ## Firmware
///
/// The following example shows how to declare a kernel module that needs
/// to load binary firmware files. You need to specify the file names of
/// the firmware in the `firmware` field. The information is embedded
/// in the `modinfo` section of the kernel module. For example, a tool to
/// build an initramfs uses this information to put the firmware files into
/// the initramfs image.
///
/// ```ignore
/// use kernel::prelude::*;
///
/// module!{
///     type: MyDeviceDriverModule,
///     name: "my_device_driver_module",
///     author: "Rust for Linux Contributors",
///     description: "My device driver requires firmware",
///     license: "GPL",
///     firmware: ["my_device_firmware1.bin", "my_device_firmware2.bin"],
/// }
///
/// struct MyDeviceDriverModule;
///
/// impl kernel::Module for MyDeviceDriverModule {
///     fn init() -> Result<Self> {
///         Ok(Self)
///     }
/// }
/// ```
///
/// # Supported argument types
///   - `type`: type which implements the [`Module`] trait (required).
///   - `name`: ASCII string literal of the name of the kernel module (required).
@@ -63,6 +93,8 @@
///   - `description`: string literal of the description of the kernel module.
///   - `license`: ASCII string literal of the license of the kernel module (required).
///   - `alias`: array of ASCII string literals of the alias names of the kernel module.
///   - `firmware`: array of ASCII string literals of the firmware files of
/// the kernel module.
#[proc_macro]
pub fn module(ts: TokenStream) -> TokenStream {
    module::module(ts)
+16 −2
Original line number Diff line number Diff line
@@ -97,14 +97,22 @@ struct ModuleInfo {
    author: Option<String>,
    description: Option<String>,
    alias: Option<Vec<String>>,
    firmware: Option<Vec<String>>,
}

impl ModuleInfo {
    fn parse(it: &mut token_stream::IntoIter) -> Self {
        let mut info = ModuleInfo::default();

        const EXPECTED_KEYS: &[&str] =
            &["type", "name", "author", "description", "license", "alias"];
        const EXPECTED_KEYS: &[&str] = &[
            "type",
            "name",
            "author",
            "description",
            "license",
            "alias",
            "firmware",
        ];
        const REQUIRED_KEYS: &[&str] = &["type", "name", "license"];
        let mut seen_keys = Vec::new();

@@ -131,6 +139,7 @@ fn parse(it: &mut token_stream::IntoIter) -> Self {
                "description" => info.description = Some(expect_string(it)),
                "license" => info.license = expect_string_ascii(it),
                "alias" => info.alias = Some(expect_string_array(it)),
                "firmware" => info.firmware = Some(expect_string_array(it)),
                _ => panic!(
                    "Unknown key \"{}\". Valid keys are: {:?}.",
                    key, EXPECTED_KEYS
@@ -186,6 +195,11 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
            modinfo.emit("alias", &alias);
        }
    }
    if let Some(firmware) = info.firmware {
        for fw in firmware {
            modinfo.emit("firmware", &fw);
        }
    }

    // Built-in modules also export the `file` modinfo string.
    let file =