1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#include "layer-gpt.hpp"
4
5#include "blockdev.h"
6#include "gptdisk.hpp"
7
8#include <cstdlib>
9#include <memory>
10
11using namespace std::string_literals;
12
13std::unique_ptr<BlockdevManagerStub> manager = nullptr;
14
15GPTLayerServer::GPTLayerServer(std::shared_ptr<GPTDisk> disk, const std::string &servername) : IBlockdevLayerService(servername), disk(disk)
16{
17 const register_layer_server::request req = {
18 .server_name = strdup(string: servername.c_str()),
19 .partitions_count = disk->get_partition_count(),
20 .partitions = new mosrpc_blockdev_partition_info[disk->get_partition_count()],
21 };
22
23 for (size_t i = 0; i < disk->get_partition_count(); i++)
24 {
25 const auto devname = disk->name() + ".p" + std::to_string(val: i); // "virtblk.00:03:00.p1"
26 const auto partition = disk->get_partition(index: i);
27 req.partitions[i].name = strdup(string: devname.c_str());
28 req.partitions[i].size = (partition.last_lba - partition.first_lba + 1) * disk->get_block_size();
29 req.partitions[i].partid = i;
30 }
31
32 register_layer_server::response resp;
33 const auto result = manager->register_layer_server(request: &req, response: &resp);
34 if (result != RPC_RESULT_OK || !resp.result.success)
35 throw std::runtime_error("Failed to register GPT layer server"s + (resp.result.error ? ": "s + resp.result.error : ""s));
36
37 free(pointer: req.server_name);
38 for (size_t i = 0; i < disk->get_partition_count(); i++)
39 free(pointer: req.partitions[i].name);
40 delete[] req.partitions;
41}
42
43rpc_result_code_t GPTLayerServer::read_partition_block(rpc_context_t *context, mosrpc_blockdev_read_partition_block_request *req, read_block::response *resp)
44{
45 MOS_UNUSED(context);
46 const auto datasize = req->n_blocks * disk->get_block_size();
47 resp->data = (pb_bytes_array_t *) malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(datasize));
48 resp->data->size = datasize;
49 disk->read_partition_block(partition_index: req->partition.partid, blockoffset: req->n_boffset, buffer: resp->data->bytes, nblocks: req->n_blocks);
50
51 resp->result.success = true;
52 resp->result.error = nullptr;
53 return RPC_RESULT_OK;
54}
55
56rpc_result_code_t GPTLayerServer::write_partition_block(rpc_context_t *context, mosrpc_blockdev_write_partition_block_request *req, write_block::response *resp)
57{
58 MOS_UNUSED(context);
59 MOS_UNUSED(resp);
60 disk->write_partition_block(partition_index: req->partition.partid, blockoffset: req->n_boffset, buffer: req->data->bytes, nblocks: req->n_blocks);
61 return RPC_RESULT_OK;
62}
63