summaryrefslogtreecommitdiff
path: root/kernel/source/storage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/source/storage.cpp')
-rw-r--r--kernel/source/storage.cpp67
1 files changed, 67 insertions, 0 deletions
diff --git a/kernel/source/storage.cpp b/kernel/source/storage.cpp
new file mode 100644
index 0000000..b6b1a04
--- /dev/null
+++ b/kernel/source/storage.cpp
@@ -0,0 +1,67 @@
+#include <hilbert/kernel/storage.hpp>
+
+namespace hilbert::kernel::storage {
+
+ bd_result block_device::load_cache_block(uint64_t i) {
+
+ if (block_cache_i == i)
+ return bd_result::success;
+
+ bd_result result = read_blocks_no_cache(i, 1, block_cache);
+
+ if (result != bd_result::success) {
+ block_cache_i = block_count;
+ return result;
+ }
+
+ block_cache_i = i;
+ return bd_result::success;
+
+ }
+
+ bd_result block_device::read_bytes(
+ uint64_t start, uint64_t count, void *into
+ ) {
+
+ if (start + count > block_size * block_count)
+ return bd_result::out_of_bounds;
+
+ uint8_t *into_u8 = (uint8_t *)into;
+
+ if (start % block_size != 0) {
+ uint64_t prefix_len = block_size - start % block_size;
+ bd_result result = load_cache_block(start / block_size);
+ if (result != bd_result::success)
+ return result;
+ for (uint64_t i = 0; i < prefix_len; ++i)
+ into_u8[i] = block_cache[start % block_size + i];
+ into_u8 += prefix_len;
+ start += prefix_len;
+ count -= prefix_len;
+ }
+
+ uint64_t postfix_start = ((start + count) / block_size) * block_size;
+
+ if (postfix_start != start) {
+ bd_result result = read_blocks_no_cache(
+ start / block_size, (postfix_start - start) / block_size, into_u8);
+ if (result != bd_result::success)
+ return result;
+ count -= postfix_start - start;
+ into_u8 += postfix_start - start;
+ start = postfix_start;
+ }
+
+ if (count != 0) {
+ bd_result result = load_cache_block(start / block_size);
+ if (result != bd_result::success)
+ return result;
+ for (uint64_t i = 0; i < count; ++i)
+ into_u8[i] = block_cache[i];
+ }
+
+ return bd_result::success;
+
+ }
+
+}