blob: e68edfc486330129c0b5e11c6807a7a2b4a2479a [file] [log] [blame]
// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_DEVICES_BLOCK_LIB_COMMON_INCLUDE_COMMON_H_
#define SRC_DEVICES_BLOCK_LIB_COMMON_INCLUDE_COMMON_H_
#include <fuchsia/hardware/block/driver/cpp/banjo.h>
#include <zircon/types.h>
#include "sdk/lib/driver/logging/cpp/logger.h"
namespace block {
// Check whether the IO request fits within the block device.
template <typename T>
inline zx_status_t CheckIoRange(const T& io, uint64_t total_block_count, fdf::Logger& logger) {
if (io.length == 0 || io.length > total_block_count) {
FDF_LOGL(ERROR, logger,
"IO request length (%u blocks) is zero or exceeds the total block count (%lu).",
io.length, total_block_count);
return ZX_ERR_OUT_OF_RANGE;
}
if (io.offset_dev >= total_block_count || io.offset_dev > total_block_count - io.length) {
FDF_LOGL(ERROR, logger,
"IO request offset (%lu blocks) and length (%u blocks) does not fit within the total "
"block count (%lu).",
io.offset_dev, io.length, total_block_count);
return ZX_ERR_OUT_OF_RANGE;
}
return ZX_OK;
}
// Check whether the IO request fits within the block device.
// Also check that the IO request length does not exceed the max transfer size.
template <typename T>
inline zx_status_t CheckIoRange(const T& io, uint64_t total_block_count,
uint32_t max_tranfser_blocks, fdf::Logger& logger) {
if (io.length > max_tranfser_blocks) {
FDF_LOGL(ERROR, logger, "IO request length (%u blocks) exceeds max transfer size (%u blocks).",
io.length, max_tranfser_blocks);
return ZX_ERR_OUT_OF_RANGE;
}
return CheckIoRange(io, total_block_count, logger);
}
// Check that the data arguments are cleared for a flush request.
inline zx_status_t CheckFlushValid(const block_read_write& rw, fdf::Logger& logger) {
if (rw.vmo || rw.length || rw.offset_dev || rw.offset_vmo) {
FDF_LOGL(ERROR, logger,
"Flush request has data arguments: rw.vmo = %u, rw.length = %u, rw.offset_dev = %lu, "
"rw.offset_vmo = %lu.",
rw.vmo, rw.length, rw.offset_dev, rw.offset_vmo);
return ZX_ERR_INVALID_ARGS;
}
return ZX_OK;
}
inline uint32_t ReadFromBigEndian24(const uint8_t* ptr) {
return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
}
inline zx_status_t WriteToBigEndian24(uint32_t value, uint8_t* ptr) {
if (value > 0xffffff) {
return ZX_ERR_OUT_OF_RANGE;
}
ptr[0] = (value >> 16) & 0xff;
ptr[1] = (value >> 8) & 0xff;
ptr[2] = value & 0xff;
return ZX_OK;
}
inline uint32_t ReadFromLittleEndian24(const uint8_t* ptr) {
return ptr[2] << 16 | ptr[1] << 8 | ptr[0];
}
inline zx_status_t WriteToLittleEndian24(uint32_t value, uint8_t* ptr) {
if (value > 0xffffff) {
return ZX_ERR_OUT_OF_RANGE;
}
ptr[2] = (value >> 16) & 0xff;
ptr[1] = (value >> 8) & 0xff;
ptr[0] = value & 0xff;
return ZX_OK;
}
} // namespace block
#endif // SRC_DEVICES_BLOCK_LIB_COMMON_INCLUDE_COMMON_H_