1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#include "blockdev.h"
4#include "proto/blockdev.pb.h"
5#include "proto/blockdev.services.h"
6
7#include <iomanip>
8#include <iostream>
9#include <librpc/macro_magic.h>
10#include <librpc/rpc.h>
11#include <librpc/rpc_client.h>
12#include <memory>
13#include <mos/mos_global.h>
14#include <optional>
15#include <pb_decode.h>
16#include <string>
17
18using namespace mosrpc::blockdev;
19
20std::unique_ptr<BlockdevManagerStub> manager = nullptr;
21
22static const std::optional<mosrpc_blockdev_blockdev> do_open_device(const char *device_name)
23{
24 open_device::request request{ .device_name = strdup(string: device_name) };
25 open_device::response response;
26 const auto result = manager->open_device(request: &request, response: &response);
27 if (result != RPC_RESULT_OK || !response.result.success)
28 {
29 std::cerr << "Failed to open blockdev: error " << result << std::endl;
30 if (response.result.error)
31 std::cerr << "Error: " << response.result.error << std::endl;
32 return std::nullopt;
33 }
34
35 const auto dev = response.device;
36 pb_release(mosrpc_blockdev_open_device_request_fields, dest_struct: &request);
37 pb_release(mosrpc_blockdev_open_device_response_fields, dest_struct: &response);
38 return dev;
39}
40
41static void do_peek_blocks(const mosrpc_blockdev_blockdev &device, size_t start, u32 n_blocks)
42{
43 auto read_req = read_block::request{
44 .device = device,
45 .n_boffset = start,
46 .n_blocks = n_blocks,
47 };
48
49 read_block::response read_resp;
50
51 const auto result = manager->read_block(request: &read_req, response: &read_resp);
52 if (result != RPC_RESULT_OK)
53 {
54 std::cerr << "Failed to read block: error " << result << std::endl;
55 return;
56 }
57
58 if (!read_resp.result.success)
59 {
60 if (read_resp.result.error)
61 std::cerr << "Failed to read block: " << read_resp.result.error << std::endl;
62 else
63 std::cerr << "Failed to read block, unknown error." << std::endl;
64 return;
65 }
66
67 std::cout << "Read " << read_resp.data->size << " bytes" << std::endl;
68 std::cout << "Data: " << std::endl;
69 for (size_t i = 0; i < read_resp.data->size; i++)
70 {
71 std::cout << std::setw(2) << std::hex << static_cast<int>(read_resp.data->bytes[i]) << " ";
72 if ((i + 1) % 32 == 0)
73 std::cout << std::endl;
74 }
75
76 pb_release(mosrpc_blockdev_read_block_request_fields, dest_struct: &read_req);
77 pb_release(mosrpc_blockdev_read_block_response_fields, dest_struct: &read_resp);
78}
79
80int main(int argc, char **argv)
81{
82 if (argc != 4)
83 {
84 std::cout << "Peek Blocks" << std::endl;
85 std::cerr << "Usage: " << argv[0] << " <blockdev> <start> <count>" << std::endl;
86 std::cerr << "Example: " << argv[0] << " ramdisk 0 1" << std::endl;
87 return 1;
88 }
89
90 manager = std::make_unique<BlockdevManagerStub>(BLOCKDEV_MANAGER_RPC_SERVER_NAME);
91
92 const auto device = do_open_device(device_name: argv[1]);
93 if (!device)
94 {
95 std::cerr << "Failed to query server name" << std::endl;
96 return 1;
97 }
98
99 const auto start = std::stoll(str: argv[2]);
100 const auto count = std::stoll(str: argv[3]);
101 do_peek_blocks(device: *device, start, n_blocks: count);
102 return 0;
103}
104