summaryrefslogtreecommitdiffstats
path: root/mboxd_flash_virtual.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mboxd_flash_virtual.cpp')
-rw-r--r--mboxd_flash_virtual.cpp53
1 files changed, 46 insertions, 7 deletions
diff --git a/mboxd_flash_virtual.cpp b/mboxd_flash_virtual.cpp
index 1b94ca9..42d4ee6 100644
--- a/mboxd_flash_virtual.cpp
+++ b/mboxd_flash_virtual.cpp
@@ -18,6 +18,7 @@ extern "C" {
#include "mboxd_flash.h"
#include "mboxd_pnor_partition_table.h"
#include "pnor_partition.hpp"
+#include "pnor_partition_table.hpp"
#include "xyz/openbmc_project/Common/error.hpp"
#include <phosphor-logging/log.hpp>
#include <phosphor-logging/elog-errors.hpp>
@@ -27,6 +28,9 @@ extern "C" {
#include <exception>
#include <stdexcept>
+namespace err = sdbusplus::xyz::openbmc_project::Common::Error;
+namespace vpnor = openpower::virtual_pnor;
+
/** @brief unique_ptr functor to release a char* reference. */
struct StringDeleter
{
@@ -167,9 +171,25 @@ int64_t copy_flash(struct mbox_context* context, uint32_t offset, void* mem,
munmap(mapped_mem, partitionInfo->data.actual);
}
}
- catch (InternalFailure& e)
+ catch (vpnor::UnmappedOffset& e)
+ {
+ /*
+ * Hooo boy. Pretend that this is valid flash so we don't have
+ * discontiguous regions presented to the host. Instead, fill a window
+ * with 0xff so the 'flash' looks erased. Writes to such regions are
+ * dropped on the floor, see the implementation of write_flash() below.
+ */
+ MSG_INFO("Host requested unmapped region of %" PRId32
+ " bytes at offset 0x%" PRIx32 "\n",
+ size, offset);
+ uint32_t span = e.next - e.base;
+ rc = std::min(size, span);
+ memset(mem, 0xff, rc);
+ }
+ catch (std::exception& e)
{
- commit<InternalFailure>();
+ MSG_ERR("%s\n", e.what());
+ phosphor::logging::commit<err::InternalFailure>();
rc = -MBOX_R_SYSTEM_ERROR;
}
return rc;
@@ -216,12 +236,16 @@ int write_flash(struct mbox_context* context, uint32_t offset, void* buf,
// if the asked offset + no of bytes to write is greater
// then size of the partition file then throw error.
+ //
+ // FIXME: Don't use .actual, use (.size << ctx->block_size_shift),
+ // otherwise we can't grow the size of the data to fill the partition
if ((offset + count) > (baseOffset + partitionInfo->data.actual))
{
- MSG_ERR("Offset is beyond the partition file length[0x%.8x]\n",
- partitionInfo->data.actual);
munmap(mapped_mem, partitionInfo->data.actual);
- elog<InternalFailure>();
+ std::stringstream err;
+ err << "Write extends beyond the partition length " << std::hex
+ << partitionInfo->data.actual;
+ throw vpnor::OutOfBoundsOffset(err.str());
}
auto diffOffset = offset - baseOffset;
@@ -230,9 +254,24 @@ int write_flash(struct mbox_context* context, uint32_t offset, void* buf,
set_flash_bytemap(context, offset, count, FLASH_DIRTY);
}
- catch (InternalFailure& e)
+ catch (vpnor::UnmappedOffset& e)
+ {
+ /* Paper over the fact that the write isn't persistent */
+ MSG_INFO("Dropping %d bytes host wrote to unmapped offset 0x%" PRIx32
+ "\n",
+ count, offset);
+ return 0;
+ }
+ catch (const vpnor::OutOfBoundsOffset& e)
+ {
+ MSG_ERR("%s\n", e.what());
+ return -MBOX_R_PARAM_ERROR;
+ }
+ catch (const std::exception& e)
{
- rc = -1;
+ MSG_ERR("%s\n", e.what());
+ phosphor::logging::commit<err::InternalFailure>();
+ return -MBOX_R_SYSTEM_ERROR;
}
return rc;
}
OpenPOWER on IntegriCloud