L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
part_device.h
1/*
2 * Copyright (C) 2018-2022 Kernkonzept GmbH.
3 * Author(s): Sarah Hoffmann <sarah.hoffmann@kernkonzept.com>
4 *
5 * This file is distributed under the terms of the GNU General Public
6 * License, version 2. Please see the COPYING-GPL-2 file for details.
7 */
8#pragma once
9
10#include <l4/cxx/ref_ptr>
11
12#include <l4/libblock-device/device.h>
13#include <l4/libblock-device/partition.h>
14
15#include <string>
16#include <locale>
17#include <codecvt>
18
19namespace Block_device {
20
21namespace Impl {
22
27 template <typename PART_DEV, typename BASE_DEV,
28 bool = std::is_base_of<Device_discard_feature, BASE_DEV>::value>
29 class Partitioned_device_discard_mixin : public BASE_DEV {};
30
37 template <typename PART_DEV, typename BASE_DEV>
38 class Partitioned_device_discard_mixin<PART_DEV, BASE_DEV, true>
39 : public BASE_DEV
40 {
41 using Base = BASE_DEV;
42 using Part_device = PART_DEV;
43
44 public:
45 typename Base::Discard_info discard_info() const override
46 {
47 return dev()->parent()->discard_info();
48 }
49
50 int discard(l4_uint64_t offset, Inout_block const &blocks,
51 Inout_callback const &cb, bool discard) override
52 {
53 auto sz = dev()->partition_size();
54
55 if (offset > sz)
56 return -L4_EINVAL;
57
58 Inout_block const *cur = &blocks;
59 while (cur)
60 {
61 if (cur->sector >= sz - offset)
62 return -L4_EINVAL;
63 if (cur->num_sectors > sz)
64 return -L4_EINVAL;
65 if (offset + cur->sector > sz - cur->num_sectors)
66 return -L4_EINVAL;
67
68 cur = cur->next.get();
69 }
70
71 auto start = offset + dev()->partition_start();
72 Dbg::trace("partition")
73 .printf("Starting sector on disk: 0x%llx\n", start);
74 return dev()->parent()->discard(start, blocks, cb, discard);
75 }
76
77 private:
78 Part_device const *dev() const
79 { return static_cast<Part_device const *>(this); }
80 };
81
82}
83
91template <typename BASE_DEV = Device>
93: public Impl::Partitioned_device_discard_mixin<Partitioned_device<BASE_DEV>, BASE_DEV>
94{
95public:
96 using Device_type = BASE_DEV;
97
99 unsigned partition_id, Partition_info const &pi)
100 : _name(pi.name),
101 _parent(dev),
102 _start(pi.first),
103 _size(pi.last - pi.first + 1)
104 {
105 if (pi.last < pi.first)
107 "Last sector of partition before first sector.");
108
109 if (partition_id > 999)
111 "Partition ID must be smaller than 1000.");
112
113 snprintf(_partition_id, sizeof(_partition_id), "%d", partition_id);
114
115 static_assert(sizeof(_guid) == sizeof(pi.guid), "String size mismatch");
116 memcpy(_guid, pi.guid, sizeof(_guid));
117 }
118
119 Notification_domain const *notification_domain() const override
120 { return _parent->notification_domain(); }
121
122 bool is_read_only() const override
123 { return _parent->is_read_only(); }
124
125 bool match_hid(cxx::String const &hid) const override
126 {
127 if (hid == cxx::String(_guid, 36))
128 return true;
129
130 std::u16string whid =
131 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}
132 .from_bytes(std::string(hid.start(), hid.len()));
133 if (whid == _name)
134 return true;
135
136 // check for identifier of form: <device_name>:<partition id>
137 char const *delim = ":";
138 char const *pos = hid.rfind(delim);
139
140 if (pos == hid.end() || !_parent->match_hid(cxx::String(hid.start(), pos)))
141 return false;
142
143 return cxx::String(pos + 1, hid.end()) == cxx::String(_partition_id);
144 }
145
146 l4_uint64_t capacity() const override
147 { return _size * _parent->sector_size(); }
148
149 l4_size_t sector_size() const override
150 { return _parent->sector_size(); }
151
152 l4_size_t max_size() const override
153 { return _parent->max_size(); }
154
155 unsigned max_segments() const override
156 { return _parent->max_segments(); }
157
158 void reset() override
159 {}
160
161 int dma_map(Block_device::Mem_region *region, l4_addr_t offset,
162 l4_size_t num_sectors, L4Re::Dma_space::Direction dir,
163 L4Re::Dma_space::Dma_addr *phys) override
164 { return _parent->dma_map(region, offset, num_sectors, dir, phys); }
165
166 int dma_unmap(L4Re::Dma_space::Dma_addr phys, l4_size_t num_sectors,
167 L4Re::Dma_space::Direction dir) override
168 { return _parent->dma_unmap(phys, num_sectors, dir); }
169
170 int inout_data(l4_uint64_t sector, Inout_block const &blocks,
171 Inout_callback const &cb,
172 L4Re::Dma_space::Direction dir) override
173 {
174 if (sector >= _size)
175 return -L4_EINVAL;
176
177 l4_uint64_t total = 0;
178 Inout_block const *cur = &blocks;
179 while (cur)
180 {
181 total += cur->num_sectors;
182 cur = cur->next.get();
183 }
184
185 if (total > _size - sector)
186 return -L4_EINVAL;
187
188 Dbg::trace("partition").printf("Sector on disk: 0x%llx\n", sector + _start);
189 return _parent->inout_data(sector + _start, blocks, cb, dir);
190 }
191
192 int flush(Inout_callback const &cb) override
193 {
194 return _parent->flush(cb);
195 }
196
197 void start_device_scan(Block_device::Errand::Callback const &callback) override
198 { callback(); }
199
200 l4_uint64_t partition_size() const
201 { return _size; }
202
203 l4_uint64_t partition_start() const
204 { return _start; }
205
206 Device_type *parent() const
207 { return _parent.get(); }
208
209
210private:
211 char _guid[37];
212 std::u16string _name;
213 char _partition_id[4];
215 l4_uint64_t _start;
216 l4_uint64_t _size;
217};
218
219} // name space
Dummy class used when the device class is not derived from Device_discard_feature.
Definition part_device.h:29
A partition device for the given device interface.
Definition part_device.h:94
l4_uint64_t Dma_addr
Data type for DMA addresses.
Definition dma_space:70
Direction
Direction of the DMA transfers.
Definition dma_space:76
Region of driver memory, that shall be managed locally.
Definition l4virtio:451
A reference-counting pointer with automatic cleanup.
Definition ref_ptr:82
T * get() const noexcept)
Return a raw pointer to the object this shared pointer points to.
Definition ref_ptr:132
Allocation free string class with explicit length field.
Definition string:42
Index start() const
Pointer to first character.
Definition string:65
Index end() const
Pointer to first byte behind the string.
Definition string:67
char const * rfind(char const *c) const
Find right-most character. Return end() if not found.
Definition string:143
int len() const
Length.
Definition string:69
unsigned int l4_size_t
Unsigned size type.
Definition l4int.h:35
unsigned long l4_addr_t
Address type.
Definition l4int.h:45
unsigned long long l4_uint64_t
Unsigned 64bit value.
Definition l4int.h:42
@ L4_EINVAL
Invalid argument.
Definition err.h:57
long chksys(long err, char const *extra="", long ret=0)
Generate C++ exception on error.
Definition error_helper:68
Description of an inout block to be sent to the device.
Definition types.h:68
l4_uint64_t sector
Initial sector. Used only by DISCARD / WRITE_ZEROES requests.
Definition types.h:72
Opaque type for representing a notification domain.
Definition device.h:34
Information about a single partition.
Definition partition.h:31
char guid[37]
ID of the partition.
Definition partition.h:32
l4_uint64_t last
Last valid sector.
Definition partition.h:35
l4_uint64_t first
First valid sector.
Definition partition.h:34
std::u16string name
UTF16 name of the partition.
Definition partition.h:33