diff options
Diffstat (limited to 'kernel/source/storage.cpp')
-rw-r--r-- | kernel/source/storage.cpp | 67 |
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; + + } + +} |