@@ -146,7 +146,7 @@ static mbox_handler *handlers_v1[MBOX_COMMAND_COUNT + 1] = {
static void mbox_flash_callback(struct bmc_mbox_msg *msg, void *priv);
static void mbox_flash_attn(uint8_t attn, void *priv);
-static int protocol_init(struct mbox_flash_data *mbox_flash);
+static int protocol_init(struct mbox_flash_data *mbox_flash, uint8_t shift);
static int lpc_window_read(struct mbox_flash_data *mbox_flash, uint32_t pos,
void *buf, uint32_t len)
@@ -533,7 +533,7 @@ static int handle_reboot(struct mbox_flash_data *mbox_flash)
return rc;
}
- rc = protocol_init(mbox_flash);
+ rc = protocol_init(mbox_flash, 0);
if (rc)
mbox_flash->reboot = true;
@@ -969,11 +969,14 @@ out:
mbox_flash->busy = false;
}
-static int protocol_init(struct mbox_flash_data *mbox_flash)
+static int protocol_init(struct mbox_flash_data *mbox_flash, uint8_t shift)
{
struct bmc_mbox_msg msg = MSG_CREATE(MBOX_C_GET_MBOX_INFO);
int rc;
+ mbox_flash->read.open = false;
+ mbox_flash->write.open = false;
+
/* Assume V2+ */
mbox_flash->bl.read = &mbox_flash_read;
mbox_flash->bl.write = &mbox_flash_write;
@@ -1007,7 +1010,7 @@ static int protocol_init(struct mbox_flash_data *mbox_flash)
mbox_flash->version = 3;
msg_put_u8(&msg, 0, mbox_flash->version);
- msg_put_u8(&msg, 1, 0); /* Don't request a shift, let the BMC give us one */
+ msg_put_u8(&msg, 1, shift);
rc = msg_send(mbox_flash, &msg, mbox_flash->timeout);
if (rc) {
prlog(PR_ERR, "Failed to enqueue/send BMC MBOX message\n");
@@ -1044,6 +1047,63 @@ static int protocol_init(struct mbox_flash_data *mbox_flash)
return rc;
}
+int mbox_flash_lock(struct blocklevel_device *bl, uint64_t pos, uint64_t len)
+{
+ struct mbox_flash_data *mbox_flash;
+ struct bmc_mbox_msg msg = MSG_CREATE(MBOX_C_MARK_LOCKED);
+ int rc;
+
+ /* mbox-flash only talks 32bit for now */
+ if (pos > UINT_MAX || len > UINT_MAX)
+ return FLASH_ERR_PARM_ERROR;
+
+ /*
+ * If the region isn't at least 4k aligned and in size then bail
+ * out, the protocol won't allow for smaller block sizes.
+ */
+ if (pos & ((1 << 12) - 1) || len & ((1 << 12) - 1))
+ return FLASH_ERR_PARM_ERROR;
+
+ mbox_flash = container_of(bl, struct mbox_flash_data, bl);
+ if ((pos & mbox_flash_mask(mbox_flash)) || (len & mbox_flash_mask(mbox_flash))) {
+ uint8_t shift = 0;
+ /*
+ * The current block size won't work for locking the requested
+ * region must reinit.
+ */
+ while (!((1 << shift) & pos) && !((1 << shift) & len))
+ shift++;
+
+ prlog(PR_INFO, "Locking flash requires re-init from shift of %d to shift of %d\n",
+ mbox_flash->shift, shift);
+
+ rc = protocol_init(mbox_flash, shift);
+ if (rc)
+ return rc;
+
+ /*
+ * The daemon didn't agree with the requested shift - the
+ * flash won't be able to be locked
+ */
+ if (mbox_flash->shift > shift)
+ return FLASH_ERR_PARM_ERROR;
+ }
+
+ msg_put_u16(&msg, 0, bytes_to_blocks(mbox_flash, pos));
+ msg_put_u16(&msg, 2, bytes_to_blocks(mbox_flash, len));
+ rc = msg_send(mbox_flash, &msg, mbox_flash->timeout);
+ if (rc) {
+ prlog(PR_ERR, "Failed to enqueue/send BMC MBOX message\n");
+ return rc;
+ }
+
+ rc = wait_for_bmc(mbox_flash, mbox_flash->timeout);
+ if (rc)
+ prlog(PR_ERR, "Error waiting for BMC\n");
+
+ return rc;
+}
+
int mbox_flash_init(struct blocklevel_device **bl)
{
struct mbox_flash_data *mbox_flash;
@@ -1067,7 +1127,7 @@ int mbox_flash_init(struct blocklevel_device **bl)
if (bmc_mbox_get_attn_reg() & MBOX_ATTN_BMC_REBOOT)
rc = handle_reboot(mbox_flash);
else
- rc = protocol_init(mbox_flash);
+ rc = protocol_init(mbox_flash, 0);
if (rc) {
free(mbox_flash);
return rc;
@@ -17,6 +17,7 @@
#ifndef __LIBFLASH_MBOX_FLASH_H
#define __LIBFLASH_MBOX_FLASH_H
+int mbox_flash_lock(struct blocklevel_device *bl, uint64_t pos, uint64_t len);
int mbox_flash_init(struct blocklevel_device **bl);
void mbox_flash_exit(struct blocklevel_device *bl);
#endif /* __LIBFLASH_MBOX_FLASH_H */
Signed-off-by: Cyril Bur <cyril.bur@au1.ibm.com> --- libflash/mbox-flash.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++---- libflash/mbox-flash.h | 1 + 2 files changed, 66 insertions(+), 5 deletions(-)