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 | |
18 | using namespace mosrpc::blockdev; |
19 | |
20 | std::unique_ptr<BlockdevManagerStub> manager = nullptr; |
21 | |
22 | static 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 | |
41 | static 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 | |
80 | int 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 | |