1 // SPDX-License-Identifier: Apache-2.0
2 // Copyright (C) 2018 IBM Corp.
3 #include <errno.h>
4 #include <stdlib.h>
5
6 #include "backend.h"
7 #include "common.h"
8 #include "dbus.h"
9 #include "lpc.h"
10 #include "mboxd.h"
11 #include "protocol.h"
12 #include "windows.h"
13
control_ping(struct mbox_context * context)14 int control_ping(struct mbox_context *context __attribute__((unused)))
15 {
16 return 0;
17 }
18
control_daemon_state(struct mbox_context * context)19 int control_daemon_state(struct mbox_context *context)
20 {
21 return (context->state & STATE_SUSPENDED) ?
22 DAEMON_STATE_SUSPENDED : DAEMON_STATE_ACTIVE;
23 }
24
control_lpc_state(struct mbox_context * context)25 int control_lpc_state(struct mbox_context *context)
26 {
27 if ((context->state & MAPS_MEM) && !(context->state & MAPS_FLASH)) {
28 return LPC_STATE_MEM;
29 } else if (!(context->state & MAPS_MEM) &&
30 (context->state & MAPS_FLASH)) {
31 return LPC_STATE_FLASH;
32 }
33
34 return LPC_STATE_INVALID;
35 }
36
control_reset(struct mbox_context * context)37 int control_reset(struct mbox_context *context)
38 {
39 /* We don't let the host access flash if the daemon is suspened */
40 if (context->state & STATE_SUSPENDED) {
41 return -EBUSY;
42 }
43
44 /* FIXME: Comment below is wrong: windows_reset_all() does not flush! */
45 /*
46 * This will close (and flush) the current window and reset the lpc bus
47 * mapping back to flash, or memory in case we're using a virtual pnor.
48 * Better set the bmc event to notify the host of this.
49 */
50 return protocol_reset(context);
51 }
52
control_kill(struct mbox_context * context)53 int control_kill(struct mbox_context *context)
54 {
55 context->terminate = 1;
56
57 MSG_INFO("DBUS Kill - Exiting...\n");
58
59 return 0;
60 }
61
control_modified(struct mbox_context * context)62 int control_modified(struct mbox_context *context)
63 {
64 /* Flash has been modified - can no longer trust our erased bytemap */
65 backend_set_bytemap(&context->backend, 0, context->backend.flash_size,
66 FLASH_DIRTY);
67
68 /* Force daemon to reload all windows -> Set BMC event to notify host */
69 if (windows_reset_all(context)) {
70 protocol_events_set(context, BMC_EVENT_WINDOW_RESET);
71 }
72
73 return 0;
74 }
75
control_suspend(struct mbox_context * context)76 int control_suspend(struct mbox_context *context)
77 {
78 int rc;
79
80 if (context->state & STATE_SUSPENDED) {
81 /* Already Suspended */
82 return 0;
83 }
84
85 /* Nothing to check - Just set the bit to notify the host */
86 rc = protocol_events_set(context, BMC_EVENT_FLASH_CTRL_LOST);
87 if (rc < 0) {
88 return rc;
89 }
90
91 context->state |= STATE_SUSPENDED;
92
93 return rc;
94 }
95
control_resume(struct mbox_context * context,bool modified)96 int control_resume(struct mbox_context *context, bool modified)
97 {
98 int rc;
99
100 if (!(context->state & STATE_SUSPENDED)) {
101 /* We weren't suspended... */
102 return 0;
103 }
104
105 if (modified) {
106 /* Call the flash modified handler */
107 control_modified(context);
108 }
109
110 /* Clear the bit and send the BMC Event to the host */
111 rc = protocol_events_clear(context, BMC_EVENT_FLASH_CTRL_LOST);
112 if (rc < 0) {
113 return rc;
114 }
115 context->state &= ~STATE_SUSPENDED;
116
117 return rc;
118 }
119
control_set_backend(struct mbox_context * context,struct backend * backend,void * data)120 int control_set_backend(struct mbox_context *context, struct backend *backend,
121 void *data)
122 {
123 struct backend successor;
124 int rc;
125
126 if (context->state & STATE_SUSPENDED)
127 return -EINVAL;
128
129 rc = protocol_events_clear(context, BMC_EVENT_DAEMON_READY);
130 if (rc < 0)
131 return rc;
132
133 rc = backend_init(&successor, backend, data);
134 if (rc < 0)
135 return rc;
136
137 backend_free(&context->backend);
138
139 context->backend = successor;
140
141 rc = __protocol_reset(context);
142 if (rc < 0)
143 return rc;
144
145 return protocol_events_set(context,
146 BMC_EVENT_DAEMON_READY | BMC_EVENT_PROTOCOL_RESET);
147 }
148