Skip to main content

starnix_modules_magma/
init.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::{GpuDeviceConfig, MagmaFile, get_magma_params};
6use anyhow::{Error, anyhow, bail};
7use bstr::BString;
8use starnix_core::device::DeviceOps;
9use starnix_core::task::{ArgNameAndValue, CurrentTask, Kernel};
10use starnix_core::vfs::{FileOps, NamespaceNode};
11
12use starnix_uapi::device_id::DeviceId;
13use starnix_uapi::errors::Errno;
14use starnix_uapi::open_flags::OpenFlags;
15
16const VENDOR_ARM: u16 = 0x13B5;
17const VENDOR_INTEL: u16 = 0x8086;
18
19fn parse_supported_vendors(args: &[&str]) -> Result<Vec<u16>, Error> {
20    let mut supported_vendors: Option<Vec<u16>> = None;
21    for &arg in args {
22        match ArgNameAndValue::from(arg) {
23            ArgNameAndValue { name: "supported_vendors", value: Some(vendors_arg) } => {
24                let vendors = vendors_arg
25                    .split(',')
26                    .map(|s| {
27                        let trimmed =
28                            s.strip_prefix("0x").or_else(|| s.strip_prefix("0X")).unwrap_or(s);
29                        u16::from_str_radix(trimmed, 16).map_err(|_| {
30                            anyhow!(
31                                "supported vendors must be comma-separated hex IDs: 0x1234[,0xabcd]"
32                            )
33                        })
34                    })
35                    .collect::<Result<Vec<u16>, Error>>()?;
36                supported_vendors = Some(vendors);
37            }
38            _ => bail!("invalid magma argument: {arg}"),
39        }
40    }
41    Ok(supported_vendors.unwrap_or_else(|| vec![VENDOR_ARM, VENDOR_INTEL]))
42}
43
44/// Validates `magma` module configuration `args`.
45pub fn validate_args(args: &[&str]) -> Result<(), Error> {
46    parse_supported_vendors(args).map(|_| ())
47}
48
49/// Returns the kernel command-line parameters for the `magma` module given its configuration `args`.
50pub fn cmdline_params(args: &[&str]) -> Result<BString, Error> {
51    let vendors = parse_supported_vendors(args)?;
52    Ok(get_magma_params(&vendors))
53}
54
55/// Initializes the Magma device from module configuration `args`.
56pub fn module_init(kernel: &Kernel, args: &[&str]) -> Result<(), Error> {
57    let supported_vendors = parse_supported_vendors(args)?;
58    let registry = &kernel.device_registry;
59    let builder = MagmaDeviceBuilder { supported_vendors };
60
61    registry
62        .add_dyn_device(kernel, "magma0".into(), registry.objects.starnix_class(), builder)
63        .expect("can add magma0");
64    crate::gpu_class_directory::register_gpu_devices(kernel, GpuDeviceConfig::default());
65    Ok(())
66}
67
68#[derive(Clone)]
69struct MagmaDeviceBuilder {
70    supported_vendors: Vec<u16>,
71}
72
73impl DeviceOps for MagmaDeviceBuilder {
74    fn open(
75        &self,
76        current_task: &CurrentTask,
77        id: DeviceId,
78        node: &NamespaceNode,
79        flags: OpenFlags,
80    ) -> Result<Box<dyn FileOps>, Errno> {
81        MagmaFile::new_file(
82            current_task,
83            id,
84            &node.entry.node,
85            flags,
86            self.supported_vendors.clone(),
87        )
88    }
89}