blob: 4b73efafadbf40badd7014cc4e3941283af70a07 [file] [log] [blame]
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2018 IBM Corp.
#include <errno.h>
#include <stdlib.h>
#include "backend.h"
#include "common.h"
#include "dbus.h"
#include "lpc.h"
#include "mboxd.h"
#include "protocol.h"
#include "windows.h"
int control_ping(struct mbox_context *context)
{
return 0;
}
int control_daemon_state(struct mbox_context *context)
{
return (context->state & STATE_SUSPENDED) ?
DAEMON_STATE_SUSPENDED : DAEMON_STATE_ACTIVE;
}
int control_lpc_state(struct mbox_context *context)
{
if ((context->state & MAPS_MEM) && !(context->state & MAPS_FLASH)) {
return LPC_STATE_MEM;
} else if (!(context->state & MAPS_MEM) &&
(context->state & MAPS_FLASH)) {
return LPC_STATE_FLASH;
}
return LPC_STATE_INVALID;
}
int control_reset(struct mbox_context *context)
{
/* We don't let the host access flash if the daemon is suspened */
if (context->state & STATE_SUSPENDED) {
return -EBUSY;
}
/* FIXME: Comment below is wrong: windows_reset_all() does not flush! */
/*
* This will close (and flush) the current window and reset the lpc bus
* mapping back to flash, or memory in case we're using a virtual pnor.
* Better set the bmc event to notify the host of this.
*/
return protocol_reset(context);
}
int control_kill(struct mbox_context *context)
{
context->terminate = 1;
MSG_INFO("DBUS Kill - Exiting...\n");
return 0;
}
int control_modified(struct mbox_context *context)
{
/* Flash has been modified - can no longer trust our erased bytemap */
backend_set_bytemap(&context->backend, 0, context->backend.flash_size,
FLASH_DIRTY);
/* Force daemon to reload all windows -> Set BMC event to notify host */
if (windows_reset_all(context)) {
protocol_events_set(context, BMC_EVENT_WINDOW_RESET);
}
return 0;
}
int control_suspend(struct mbox_context *context)
{
int rc;
if (context->state & STATE_SUSPENDED) {
/* Already Suspended */
return 0;
}
/* Nothing to check - Just set the bit to notify the host */
rc = protocol_events_set(context, BMC_EVENT_FLASH_CTRL_LOST);
if (rc < 0) {
return rc;
}
context->state |= STATE_SUSPENDED;
return rc;
}
int control_resume(struct mbox_context *context, bool modified)
{
int rc;
if (!(context->state & STATE_SUSPENDED)) {
/* We weren't suspended... */
return 0;
}
if (modified) {
/* Call the flash modified handler */
control_modified(context);
}
/* Clear the bit and send the BMC Event to the host */
rc = protocol_events_clear(context, BMC_EVENT_FLASH_CTRL_LOST);
if (rc < 0) {
return rc;
}
context->state &= ~STATE_SUSPENDED;
return rc;
}
int control_set_backend(struct mbox_context *context, struct backend *backend,
void *data)
{
int rc;
if (context->state & STATE_SUSPENDED)
return -EINVAL;
rc = protocol_events_clear(context, BMC_EVENT_DAEMON_READY);
if (rc < 0)
return rc;
backend_free(&context->backend);
rc = backend_init(&context->backend, backend, data);
if (rc < 0)
return rc;
rc = __protocol_reset(context);
if (rc < 0)
return rc;
return protocol_events_set(context,
BMC_EVENT_DAEMON_READY | BMC_EVENT_PROTOCOL_RESET);
}