1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#include "dm_common.hpp"
4
5#include <iostream>
6#include <libconfig/libconfig.h>
7#include <spawn.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12bool start_load_drivers()
13{
14 const auto loads = dm_config.get_entries(section_name: "loads");
15
16 for (const auto &[_, driver] : loads)
17 {
18 pid_t driver_pid;
19 posix_spawn(pid: &driver_pid, path: driver.c_str(), NULL, NULL, NULL, NULL);
20 if (driver_pid <= 0)
21 std::cerr << "Failed to start driver: " << driver << std::endl;
22 }
23
24 return true;
25}
26
27bool try_start_driver(u16 vendor, u16 device, u32 location, u64 mmio_base)
28{
29 char vendor_str[5];
30 char vendor_device_str[10];
31 snprintf(buffer: vendor_str, max_size: sizeof(vendor_str), format: "%04x", vendor);
32 snprintf(buffer: vendor_device_str, max_size: sizeof(vendor_device_str), format: "%04x:%04x", vendor, device);
33
34 // first try to find a driver for the specific device
35 auto driver_paths = dm_config.get_entry(section_name: "drivers", key: vendor_device_str);
36
37 // if that fails, try to find a driver for the vendor
38 if (driver_paths.empty())
39 driver_paths = dm_config.get_entry(section_name: "drivers", key: vendor_str);
40
41 // if the driver is still not found, leave
42 if (driver_paths.empty())
43 return false;
44
45 if (driver_paths.size() > 1)
46 puts(string: "Multiple drivers found for device, using the first one");
47
48 const auto driver_path = driver_paths[0].second;
49
50 char device_str[16];
51 char location_str[16];
52 char mmio_base_str[16];
53 snprintf(buffer: device_str, max_size: sizeof(device_str), format: "%04x", device);
54 snprintf(buffer: location_str, max_size: sizeof(location_str), format: "%04x", location);
55 snprintf(buffer: mmio_base_str, max_size: sizeof(mmio_base_str), format: "%llx", mmio_base);
56
57 const char *argv[] = {
58 driver_path.c_str(), //
59 "--vendor-id", vendor_str, //
60 "--device-id", device_str, //
61 "--location", location_str, //
62 "--mmio-base", mmio_base_str, NULL, //
63 };
64 printf(format: "Starting driver:");
65 for (size_t i = 0; argv[i]; i++)
66 printf(format: " %s", argv[i]);
67 putchar(c: '\n');
68
69 pid_t driver_pid;
70 posix_spawn(pid: &driver_pid, path: driver_path.c_str(), NULL, NULL, argv: (char *const *) argv, NULL);
71
72 return driver_pid > 0;
73}
74