diff --git a/drivers/bch/Kconfig b/drivers/bch/Kconfig index a8152e63b5a..39e2ab1c267 100644 --- a/drivers/bch/Kconfig +++ b/drivers/bch/Kconfig @@ -34,4 +34,13 @@ config BCH_DEVICE_READONLY ---help--- Set bch devices read-only +config BCH_FORCE_INDIRECT + bool "Force indirect transfers in BCH" + default n + ---help--- + Force all data transfers in BCH to be indirect, + using an intermediate buffer. + This is needed because in some use cases (e.g. when CONFIG_BUILD_KERNEL) + it is not possible to write directly from user buffer. + endif # BCH diff --git a/drivers/bch/bchlib_write.c b/drivers/bch/bchlib_write.c index 8d5977080f3..f35a35f7dcc 100644 --- a/drivers/bch/bchlib_write.c +++ b/drivers/bch/bchlib_write.c @@ -56,7 +56,9 @@ ssize_t bchlib_write(FAR void *handle, FAR const char *buffer, off_t offset, size_t len) { FAR struct bchlib_s *bch = (FAR struct bchlib_s *)handle; +#ifndef CONFIG_BCH_FORCE_INDIRECT size_t nsectors; +#endif size_t sector; uint16_t sectoffset; size_t nbytes; @@ -121,8 +123,48 @@ ssize_t bchlib_write(FAR void *handle, FAR const char *buffer, off_t offset, len -= nbytes; } - /* Then write all of the full sectors following the partial sector - * directly from the user buffer. + /* Then write all of the full sectors following the partial sector.. */ + +#ifdef CONFIG_BCH_FORCE_INDIRECT + + /* indirectly by using sector buffer. + */ + + while (len > 0) + { + /* Read the sector into the sector buffer */ + + ret = bchlib_readsector(bch, sector); + if (ret < 0) + { + return ret; + } + + /* Copy the data from the user buffer to the sector buffer */ + + nbytes = len > bch->sectsize ? bch->sectsize : len; + memcpy(bch->buffer, buffer, nbytes); + bch->dirty = true; + + /* Write the sector back to the block device */ + + ret = bchlib_flushsector(bch, false); + if (ret < 0) + { + ferr("ERROR: Flush failed: %d\n", ret); + return ret; + } + + /* Adjust pointers and counts */ + + buffer += nbytes; + len -= nbytes; + byteswritten += nbytes; + sector++; + } +#else + + /* directly from the user buffer. */ if (len >= bch->sectsize) @@ -189,6 +231,7 @@ ssize_t bchlib_write(FAR void *handle, FAR const char *buffer, off_t offset, byteswritten += len; } +#endif /* CONFIG_BCH_FORCE_INDIRECT */ return byteswritten; }