1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#include "dm_common.hpp"
4#include "proto/services.pb.h"
5#include "proto/services.service.h"
6
7#include <iostream>
8#include <memory>
9#include <spawn.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <unistd.h>
13
14constexpr auto SERVICE_MANAGER_RPC_NAME = "mos.service_manager";
15const auto ServiceManager = std::make_shared<ServiceManagerStub>(args: SERVICE_MANAGER_RPC_NAME);
16
17bool try_start_driver(u16 vendor, u16 device, u8 busid, u8 devid, u8 funcid, u64 mmio_base)
18{
19 char vendor_str[7];
20 char device_str[7];
21 snprintf(buffer: vendor_str, max_size: sizeof(vendor_str), format: "0x%04x", vendor);
22 snprintf(buffer: device_str, max_size: sizeof(device_str), format: "0x%04x", device);
23
24 InstantiateUnitRequest req;
25 InstantiateUnitResponse resp;
26
27 req.template_id = strdup(string: "pci.device-template");
28 req.parameters_count = 5;
29 req.parameters = static_cast<KeyValuePair *>(malloc(size: 5 * sizeof(KeyValuePair)));
30 req.parameters[0].name = strdup(string: "vendor_id");
31 req.parameters[0].value = strdup(string: vendor_str);
32 req.parameters[1].name = strdup(string: "device_id");
33 req.parameters[1].value = strdup(string: device_str);
34 req.parameters[2].name = strdup(string: "bus");
35 req.parameters[2].value = strdup(string: std::to_string(val: busid).c_str());
36 req.parameters[3].name = strdup(string: "dev");
37 req.parameters[3].value = strdup(string: std::to_string(val: devid).c_str());
38 req.parameters[4].name = strdup(string: "func");
39 req.parameters[4].value = strdup(string: std::to_string(val: funcid).c_str());
40
41 std::cout << "Instantiating unit for device: " << vendor_str << ":" << device_str << " at bus " << (int) busid << ", dev " << (int) devid << ", func " << (int) funcid
42 << ", mmio_base " << std::hex << mmio_base << std::dec << std::endl;
43 ServiceManager->instantiate_unit(request: &req, response: &resp);
44 if (resp.unit_id == nullptr || resp.unit_id[0] == '\0')
45 {
46 std::cerr << "Failed to instantiate unit: " << req.template_id << std::endl;
47 return false;
48 }
49
50 StartUnitRequest start_req{
51 .unit_id = resp.unit_id,
52 };
53 StartUnitResponse start_resp;
54 ServiceManager->start_unit(request: &start_req, response: &start_resp);
55 if (!start_resp.success)
56 {
57 std::cerr << "Failed to start unit: " << req.template_id << std::endl;
58 return false;
59 }
60
61 std::cout << "Successfully started unit: " << req.template_id << " with ID: " << resp.unit_id << std::endl;
62 free(pointer: req.parameters[0].name);
63 free(pointer: req.parameters[0].value);
64 free(pointer: req.parameters[1].name);
65 free(pointer: req.parameters[1].value);
66 free(pointer: req.parameters[2].name);
67 free(pointer: req.parameters[2].value);
68 free(pointer: req.parameters[3].name);
69 free(pointer: req.parameters[3].value);
70 free(pointer: req.parameters[4].name);
71 free(pointer: req.parameters[4].value);
72 free(pointer: req.parameters);
73 free(pointer: resp.unit_id);
74 return true;
75}
76