Branch data Line data Source code
1 : : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2 : : /* Copyright 2017-2018 IBM Corp. */
3 : :
4 : : #define pr_fmt(fmt) "MBOX-FLASH: " fmt
5 : :
6 : : #define _GNU_SOURCE
7 : : #include <errno.h>
8 : : #include <stdio.h>
9 : : #include <stdlib.h>
10 : : #include <string.h>
11 : :
12 : : #include <skiboot.h>
13 : : #include <inttypes.h>
14 : : #include <timebase.h>
15 : : #include <timer.h>
16 : : #include <libflash/libflash.h>
17 : : #include <libflash/mbox-flash.h>
18 : : #include <lpc.h>
19 : : #include <lpc-mbox.h>
20 : :
21 : : #include <ccan/container_of/container_of.h>
22 : :
23 : : #ifndef __SKIBOOT__
24 : : #ifndef __TEST__
25 : : #error "This libflash backend must be compiled with skiboot"
26 : : #endif
27 : : #endif
28 : :
29 : : /* Same technique as BUILD_BUG_ON from linux */
30 : : #define CHECK_HANDLER_SIZE(handlers) ((void)sizeof(char[1 - 2*!!(ARRAY_SIZE(handlers) != (MBOX_COMMAND_COUNT + 1))]))
31 : :
32 : : #define MBOX_DEFAULT_TIMEOUT 3 /* seconds */
33 : :
34 : : #define MSG_CREATE(init_command) { .command = init_command }
35 : :
36 : : struct mbox_flash_data;
37 : : typedef void (mbox_handler)(struct mbox_flash_data *, struct bmc_mbox_msg *);
38 : :
39 : : struct lpc_window {
40 : : uint32_t lpc_addr; /* Offset into LPC space */
41 : : uint32_t cur_pos; /* Current position of the window in the flash */
42 : : uint32_t size; /* Size of the window into the flash */
43 : : bool open;
44 : : };
45 : :
46 : : struct mbox_flash_data {
47 : : int version;
48 : : uint16_t timeout;
49 : : uint32_t shift;
50 : : struct lpc_window read;
51 : : struct lpc_window write;
52 : : struct blocklevel_device bl;
53 : : uint32_t total_size;
54 : : uint32_t erase_granule;
55 : : int rc;
56 : : bool reboot;
57 : : bool pause;
58 : : bool busy;
59 : : bool ack;
60 : : mbox_handler **handlers;
61 : : };
62 : :
63 : : static mbox_handler mbox_flash_do_nop;
64 : : static mbox_handler mbox_flash_do_illegal;
65 : :
66 : : /* Version 1, 2, 3 compatible */
67 : : static mbox_handler mbox_flash_do_get_mbox_info;
68 : :
69 : : /* Version 2 and 3 compatible */
70 : : static mbox_handler mbox_flash_do_get_flash_info;
71 : : static mbox_handler mbox_flash_do_get_flash_info_v1;
72 : :
73 : : /* Version 2 and 3 compatible */
74 : : static mbox_handler mbox_flash_do_create_read_window;
75 : : static mbox_handler mbox_flash_do_create_read_window_v1;
76 : :
77 : : /* Version 2 and 3 compatible */
78 : : static mbox_handler mbox_flash_do_create_write_window;
79 : : static mbox_handler mbox_flash_do_create_write_window_v1;
80 : :
81 : : /* Version 1, 2, 3 compatible */
82 : : static mbox_handler mbox_flash_do_close_window;
83 : :
84 : : /* Plus one, commands start at 1 */
85 : : static mbox_handler *handlers_v3[] = {
86 : : NULL,
87 : : &mbox_flash_do_nop,
88 : : &mbox_flash_do_get_mbox_info,
89 : : &mbox_flash_do_get_flash_info,
90 : : &mbox_flash_do_create_read_window,
91 : : &mbox_flash_do_close_window,
92 : : &mbox_flash_do_create_write_window,
93 : : &mbox_flash_do_nop,
94 : : &mbox_flash_do_nop,
95 : : &mbox_flash_do_nop,
96 : : &mbox_flash_do_nop,
97 : : &mbox_flash_do_nop,
98 : : &mbox_flash_do_nop
99 : : };
100 : :
101 : : /* Plus one, commands start at 1 */
102 : : static mbox_handler *handlers_v2[] = {
103 : : NULL,
104 : : &mbox_flash_do_nop,
105 : : &mbox_flash_do_get_mbox_info,
106 : : &mbox_flash_do_get_flash_info,
107 : : &mbox_flash_do_create_read_window,
108 : : &mbox_flash_do_close_window,
109 : : &mbox_flash_do_create_write_window,
110 : : &mbox_flash_do_nop,
111 : : &mbox_flash_do_nop,
112 : : &mbox_flash_do_nop,
113 : : &mbox_flash_do_nop,
114 : : &mbox_flash_do_illegal,
115 : : &mbox_flash_do_illegal
116 : : };
117 : :
118 : : /*
119 : : * Plus one, commands start at 1.
120 : : * V2 adds a command so there should never be a response for the last
121 : : * command.
122 : : * Ensure we print an error message with mbox_flash_do_illegal().
123 : : */
124 : : static mbox_handler *handlers_v1[] = {
125 : : NULL,
126 : : &mbox_flash_do_nop,
127 : : &mbox_flash_do_get_mbox_info,
128 : : &mbox_flash_do_get_flash_info_v1,
129 : : &mbox_flash_do_create_read_window_v1,
130 : : &mbox_flash_do_close_window,
131 : : &mbox_flash_do_create_write_window_v1,
132 : : &mbox_flash_do_nop,
133 : : &mbox_flash_do_nop,
134 : : &mbox_flash_do_nop,
135 : : &mbox_flash_do_illegal,
136 : : &mbox_flash_do_illegal,
137 : : &mbox_flash_do_illegal
138 : : };
139 : :
140 : :
141 : : static void mbox_flash_callback(struct bmc_mbox_msg *msg, void *priv);
142 : : static void mbox_flash_attn(uint8_t attn, void *priv);
143 : :
144 : : static int protocol_init(struct mbox_flash_data *mbox_flash, uint8_t shift);
145 : :
146 : 659 : static int lpc_window_read(struct mbox_flash_data *mbox_flash, uint32_t pos,
147 : : void *buf, uint32_t len)
148 : : {
149 : 659 : uint32_t off = mbox_flash->read.lpc_addr + (pos - mbox_flash->read.cur_pos);
150 : :
151 : 659 : prlog(PR_TRACE, "Reading at 0x%08x for 0x%08x offset: 0x%08x\n",
152 : : pos, len, off);
153 : :
154 : 659 : return lpc_fw_read(off, buf, len);
155 : : }
156 : :
157 : 96 : static int lpc_window_write(struct mbox_flash_data *mbox_flash, uint32_t pos,
158 : : const void *buf, uint32_t len)
159 : : {
160 : 96 : uint32_t off = mbox_flash->write.lpc_addr + (pos - mbox_flash->write.cur_pos);
161 : :
162 : 96 : return lpc_fw_write(off, buf, len);
163 : : }
164 : :
165 : 734 : static uint64_t mbox_flash_mask(struct mbox_flash_data *mbox_flash)
166 : : {
167 : 734 : return (1ULL << mbox_flash->shift) - 1;
168 : : }
169 : :
170 : 7 : __unused static uint8_t msg_get_u8(struct bmc_mbox_msg *msg, int i)
171 : : {
172 : 7 : return msg->args[i];
173 : : }
174 : :
175 : 11 : static void msg_put_u8(struct bmc_mbox_msg *msg, int i, uint8_t val)
176 : : {
177 : 11 : msg->args[i] = val;
178 : 11 : }
179 : :
180 : 1827 : static uint16_t msg_get_u16(struct bmc_mbox_msg *msg, int i)
181 : : {
182 : 1827 : return le16_to_cpu(*(__le16 *)(&msg->args[i]));
183 : : }
184 : :
185 : 908 : static void msg_put_u16(struct bmc_mbox_msg *msg, int i, uint16_t val)
186 : : {
187 : 908 : __le16 tmp = cpu_to_le16(val);
188 : 908 : memcpy(&msg->args[i], &tmp, sizeof(val));
189 : 908 : }
190 : :
191 : 2 : static uint32_t msg_get_u32(struct bmc_mbox_msg *msg, int i)
192 : : {
193 : 2 : return le32_to_cpu(*(__le32 *)(&msg->args[i]));
194 : : }
195 : :
196 : 24 : static void msg_put_u32(struct bmc_mbox_msg *msg, int i, uint32_t val)
197 : : {
198 : 24 : __le32 tmp = cpu_to_le32(val);
199 : 24 : memcpy(&msg->args[i], &tmp, sizeof(val));
200 : 24 : }
201 : :
202 : 1824 : static uint32_t blocks_to_bytes(struct mbox_flash_data *mbox_flash, uint16_t blocks)
203 : : {
204 : 1824 : return blocks << mbox_flash->shift;
205 : : }
206 : :
207 : 908 : static uint16_t bytes_to_blocks(struct mbox_flash_data *mbox_flash,
208 : : uint32_t bytes)
209 : : {
210 : 908 : return bytes >> mbox_flash->shift;
211 : : }
212 : :
213 : : /*
214 : : * The BMC may send is an out of band message to say that it doesn't
215 : : * own the flash anymore.
216 : : * It guarantees we can still access our (open) windows but it does
217 : : * not guarantee their contents until it clears the bit without
218 : : * sending us a corresponding bit to say that the windows are bad
219 : : * first.
220 : : * Since this is all things that will happen in the future, we should
221 : : * not perform any calls speculatively as its almost impossible to
222 : : * rewind.
223 : : */
224 : 1050 : static bool is_paused(struct mbox_flash_data *mbox_flash)
225 : : {
226 : 1050 : return mbox_flash->pause;
227 : : }
228 : :
229 : : /*
230 : : * After a read or a write it is wise to check that the window we just
231 : : * read/write to/from is still valid otherwise it is possible some of
232 : : * the data didn't make it.
233 : : * This check is an optimisation as we'll close all our windows on any
234 : : * notification from the BMC that the windows are bad. See the above
235 : : * comment about is_paused().
236 : : * A foolproof (but much closer) method of validating reads/writes
237 : : * would be to attempt to close the window, if that fails then we can
238 : : * be sure that the read/write was no good.
239 : : */
240 : 659 : static bool is_valid(struct mbox_flash_data *mbox_flash, struct lpc_window *win)
241 : : {
242 : 659 : return !is_paused(mbox_flash) && win->open;
243 : : }
244 : :
245 : : /*
246 : : * Check if we've received a BMC reboot notification.
247 : : * The strategy is to check on entry to mbox-flash and return a
248 : : * failure accordingly. Races will be handled by the fact that the BMC
249 : : * won't respond so timeouts will occur. As an added precaution
250 : : * msg_send() checks right before sending a message (to make the race
251 : : * as small as possible to avoid needless timeouts).
252 : : */
253 : 1335 : static bool is_reboot(struct mbox_flash_data *mbox_flash)
254 : : {
255 : 1335 : return mbox_flash->reboot;
256 : : }
257 : :
258 : 944 : static int msg_send(struct mbox_flash_data *mbox_flash, struct bmc_mbox_msg *msg,
259 : : unsigned int timeout_sec)
260 : : {
261 : 944 : if (is_reboot(mbox_flash))
262 : 0 : return FLASH_ERR_AGAIN;
263 : 944 : mbox_flash->busy = true;
264 : 944 : mbox_flash->rc = 0;
265 : 944 : return bmc_mbox_enqueue(msg, timeout_sec);
266 : : }
267 : :
268 : 944 : static int wait_for_bmc(struct mbox_flash_data *mbox_flash, unsigned int timeout_sec)
269 : : {
270 : 944 : unsigned long last = 1, start = tb_to_secs(mftb());
271 : 944 : prlog(PR_TRACE, "Waiting for BMC\n");
272 : 1888 : while (mbox_flash->busy && timeout_sec > last) {
273 : 944 : long now = tb_to_secs(mftb());
274 : 944 : if (now - start > last) {
275 : 0 : if (last < timeout_sec / 2)
276 : 0 : prlog(PR_TRACE, "Been waiting for the BMC for %lu secs\n", last);
277 : : else
278 : 0 : prlog(PR_ERR, "BMC NOT RESPONDING %lu second wait\n", last);
279 : 0 : last++;
280 : : }
281 : : /*
282 : : * Both functions are important.
283 : : * Well time_wait_ms() relaxes the spin... so... its nice
284 : : */
285 : 944 : check_timers(false);
286 : 944 : if (mbox_flash->busy)
287 : 0 : time_wait_ms(MBOX_DEFAULT_POLL_MS);
288 : 944 : asm volatile ("" ::: "memory");
289 : : }
290 : :
291 : 944 : if (mbox_flash->busy) {
292 : 0 : prlog(PR_ERR, "Timeout waiting for BMC\n");
293 : 0 : mbox_flash->busy = false;
294 : 0 : return MBOX_R_TIMEOUT;
295 : : }
296 : :
297 : 944 : return mbox_flash->rc;
298 : : }
299 : :
300 : 3 : static int mbox_flash_ack(struct mbox_flash_data *mbox_flash, uint8_t reg)
301 : : {
302 : 3 : struct bmc_mbox_msg msg = MSG_CREATE(MBOX_C_BMC_EVENT_ACK);
303 : : int rc;
304 : :
305 : 3 : msg_put_u8(&msg, 0, reg);
306 : :
307 : : /* Clear this first so msg_send() doesn't freak out */
308 : 3 : mbox_flash->reboot = false;
309 : :
310 : : /*
311 : : * Use a lower timeout - there is strong evidence to suggest the
312 : : * BMC won't respond, don't waste time spinning here just have the
313 : : * high levels retry when the BMC might be back
314 : : */
315 : 3 : rc = msg_send(mbox_flash, &msg, 3);
316 : :
317 : : /* Still need to deal with it, we've only acked it now. */
318 : 3 : mbox_flash->reboot = true;
319 : :
320 : 3 : if (rc) {
321 : 0 : prlog(PR_ERR, "Failed to enqueue/send BMC MBOX message\n");
322 : 0 : return rc;
323 : : }
324 : :
325 : : /*
326 : : * Use a lower timeout - there is strong evidence to suggest the
327 : : * BMC won't respond, don't waste time spinning here just have the
328 : : * high levels retry when the BMC might be back
329 : : */
330 : 3 : rc = wait_for_bmc(mbox_flash, 3);
331 : 3 : if (rc)
332 : 0 : prlog(PR_ERR, "Error waiting for BMC\n");
333 : :
334 : 3 : return rc;
335 : : }
336 : :
337 : 394 : static int do_acks(struct mbox_flash_data *mbox_flash)
338 : : {
339 : : int rc;
340 : :
341 : 394 : if (!mbox_flash->ack)
342 : 391 : return 0; /* Nothing to do */
343 : :
344 : 3 : rc = mbox_flash_ack(mbox_flash, bmc_mbox_get_attn_reg() & MBOX_ATTN_ACK_MASK);
345 : 3 : if (!rc)
346 : 3 : mbox_flash->ack = false;
347 : :
348 : 3 : return rc;
349 : : }
350 : :
351 : 202 : static void mbox_flash_do_nop(struct mbox_flash_data *mbox_flash __unused,
352 : : struct bmc_mbox_msg *msg __unused)
353 : : {
354 : 202 : }
355 : :
356 : 0 : static void mbox_flash_do_illegal(struct mbox_flash_data *mbox_flash __unused,
357 : : struct bmc_mbox_msg *msg __unused)
358 : : {
359 : 0 : prlog(PR_CRIT, "Got response to unknown message type\n");
360 : 0 : }
361 : :
362 : : /* Version 1, 2 and 3 compatible */
363 : 4 : static void mbox_flash_do_get_mbox_info(struct mbox_flash_data *mbox_flash,
364 : : struct bmc_mbox_msg *msg)
365 : : {
366 : :
367 : 4 : mbox_flash->version = msg_get_u8(msg, 0);
368 : 4 : switch (mbox_flash->version) {
369 : 1 : case 1:
370 : : /* Not all version 1 daemons set argument 5 correctly */
371 : 1 : mbox_flash->shift = 12; /* Protocol hardcodes to 4K anyway */
372 : 1 : mbox_flash->read.size = blocks_to_bytes(mbox_flash, msg_get_u16(msg, 1));
373 : 1 : mbox_flash->write.size = blocks_to_bytes(mbox_flash, msg_get_u16(msg, 3));
374 : 1 : break;
375 : 3 : case 3:
376 : : case 2:
377 : 3 : mbox_flash->shift = msg_get_u8(msg, 5);
378 : 3 : mbox_flash->timeout = msg_get_u16(msg, 6);
379 : 3 : if (mbox_flash->timeout == 0)
380 : 3 : mbox_flash->timeout = MBOX_DEFAULT_TIMEOUT;
381 : 3 : break;
382 : : }
383 : : /* Callers will handle the case where the version is not known
384 : : *
385 : : * Here we deliberately ignore the 'default' sizes.
386 : : * All windows opened will not provide a hint and we're
387 : : * happy to let the BMC figure everything out.
388 : : * Future optimisations may use the default size.
389 : : */
390 : 4 : }
391 : :
392 : : /* Version 2 and 3 compatible */
393 : 3 : static void mbox_flash_do_get_flash_info(struct mbox_flash_data *mbox_flash,
394 : : struct bmc_mbox_msg *msg)
395 : : {
396 : 3 : mbox_flash->total_size = blocks_to_bytes(mbox_flash, msg_get_u16(msg, 0));
397 : 3 : mbox_flash->erase_granule = blocks_to_bytes(mbox_flash, msg_get_u16(msg, 2));
398 : 3 : }
399 : :
400 : 1 : static void mbox_flash_do_get_flash_info_v1(struct mbox_flash_data *mbox_flash,
401 : : struct bmc_mbox_msg *msg)
402 : : {
403 : 1 : mbox_flash->total_size = msg_get_u32(msg, 0);
404 : 1 : mbox_flash->erase_granule = msg_get_u32(msg, 4);
405 : 1 : }
406 : :
407 : : /* Version 2 and 3 compatible */
408 : 471 : static void mbox_flash_do_create_read_window(struct mbox_flash_data *mbox_flash,
409 : : struct bmc_mbox_msg *msg)
410 : : {
411 : 471 : mbox_flash->read.lpc_addr = blocks_to_bytes(mbox_flash, msg_get_u16(msg, 0));
412 : 471 : mbox_flash->read.size = blocks_to_bytes(mbox_flash, msg_get_u16(msg, 2));
413 : 471 : mbox_flash->read.cur_pos = blocks_to_bytes(mbox_flash, msg_get_u16(msg, 4));
414 : 471 : mbox_flash->read.open = true;
415 : 471 : mbox_flash->write.open = false;
416 : 471 : }
417 : :
418 : 164 : static void mbox_flash_do_create_read_window_v1(struct mbox_flash_data *mbox_flash,
419 : : struct bmc_mbox_msg *msg)
420 : : {
421 : 164 : mbox_flash->read.lpc_addr = blocks_to_bytes(mbox_flash, msg_get_u16(msg, 0));
422 : 164 : mbox_flash->read.open = true;
423 : 164 : mbox_flash->write.open = false;
424 : 164 : }
425 : :
426 : : /* Version 2 and 3 compatible */
427 : 72 : static void mbox_flash_do_create_write_window(struct mbox_flash_data *mbox_flash,
428 : : struct bmc_mbox_msg *msg)
429 : : {
430 : 72 : mbox_flash->write.lpc_addr = blocks_to_bytes(mbox_flash, msg_get_u16(msg, 0));
431 : 72 : mbox_flash->write.size = blocks_to_bytes(mbox_flash, msg_get_u16(msg, 2));
432 : 72 : mbox_flash->write.cur_pos = blocks_to_bytes(mbox_flash, msg_get_u16(msg, 4));
433 : 72 : mbox_flash->write.open = true;
434 : 72 : mbox_flash->read.open = false;
435 : 72 : }
436 : :
437 : 23 : static void mbox_flash_do_create_write_window_v1(struct mbox_flash_data *mbox_flash,
438 : : struct bmc_mbox_msg *msg)
439 : : {
440 : 23 : mbox_flash->write.lpc_addr = blocks_to_bytes(mbox_flash, msg_get_u16(msg, 0));
441 : 23 : mbox_flash->write.open = true;
442 : 23 : mbox_flash->read.open = false;
443 : 23 : }
444 : :
445 : : /* Version 1 and Version 2 compatible */
446 : 0 : static void mbox_flash_do_close_window(struct mbox_flash_data *mbox_flash,
447 : : struct bmc_mbox_msg *msg __unused)
448 : : {
449 : 0 : mbox_flash->read.open = false;
450 : 0 : mbox_flash->write.open = false;
451 : 0 : }
452 : :
453 : 3 : static int handle_reboot(struct mbox_flash_data *mbox_flash)
454 : : {
455 : : int rc;
456 : :
457 : : /*
458 : : * If the BMC ready bit isn't present then we're basically
459 : : * guaranteed to timeout trying to talk to it so just fail
460 : : * whatever is trying to happen.
461 : : * Importantly, we can't trust that the presence of the bit means
462 : : * the daemon is ok - don't assume it is going to respond at all
463 : : * from here onwards
464 : : */
465 : 3 : if (!(bmc_mbox_get_attn_reg() & MBOX_ATTN_BMC_DAEMON_READY))
466 : 0 : return FLASH_ERR_AGAIN;
467 : :
468 : : /* Clear this first so msg_send() doesn't freak out */
469 : 3 : mbox_flash->reboot = false;
470 : :
471 : 3 : rc = do_acks(mbox_flash);
472 : 3 : if (rc) {
473 : 0 : if (rc == MBOX_R_TIMEOUT)
474 : 0 : rc = FLASH_ERR_AGAIN;
475 : 0 : mbox_flash->reboot = true;
476 : 0 : return rc;
477 : : }
478 : :
479 : 3 : rc = protocol_init(mbox_flash, 0);
480 : 3 : if (rc)
481 : 0 : mbox_flash->reboot = true;
482 : :
483 : 3 : return rc;
484 : : }
485 : :
486 : 391 : static bool do_delayed_work(struct mbox_flash_data *mbox_flash)
487 : : {
488 : 785 : return is_paused(mbox_flash) || do_acks(mbox_flash) ||
489 : 394 : (is_reboot(mbox_flash) && handle_reboot(mbox_flash));
490 : : }
491 : :
492 : 99 : static int mbox_flash_mark_write(struct mbox_flash_data *mbox_flash,
493 : : uint64_t pos, uint64_t len, int type)
494 : : {
495 : 99 : struct bmc_mbox_msg msg = MSG_CREATE(type);
496 : : int rc;
497 : :
498 : 99 : if (mbox_flash->version == 1) {
499 : 24 : uint32_t start = ALIGN_DOWN(pos, 1 << mbox_flash->shift);
500 : 24 : msg_put_u16(&msg, 0, bytes_to_blocks(mbox_flash, pos));
501 : : /*
502 : : * We need to make sure that we mark dirty until up to atleast
503 : : * pos + len.
504 : : */
505 : 24 : msg_put_u32(&msg, 2, pos + len - start);
506 : : } else {
507 : 75 : uint64_t window_pos = pos - mbox_flash->write.cur_pos;
508 : 75 : uint16_t start = bytes_to_blocks(mbox_flash, window_pos);
509 : 75 : uint16_t end = bytes_to_blocks(mbox_flash,
510 : 75 : ALIGN_UP(window_pos + len,
511 : : 1 << mbox_flash->shift));
512 : :
513 : 75 : msg_put_u16(&msg, 0, start);
514 : 75 : msg_put_u16(&msg, 2, end - start); /* Total Length */
515 : : }
516 : :
517 : 99 : rc = msg_send(mbox_flash, &msg, mbox_flash->timeout);
518 : 99 : if (rc) {
519 : 0 : prlog(PR_ERR, "Failed to enqueue/send BMC MBOX message\n");
520 : 0 : return rc;
521 : : }
522 : :
523 : 99 : rc = wait_for_bmc(mbox_flash, mbox_flash->timeout);
524 : 99 : if (rc)
525 : 0 : prlog(PR_ERR, "Error waiting for BMC\n");
526 : :
527 : 99 : return rc;
528 : : }
529 : :
530 : 96 : static int mbox_flash_dirty(struct mbox_flash_data *mbox_flash, uint64_t pos,
531 : : uint64_t len)
532 : : {
533 : 96 : if (!mbox_flash->write.open) {
534 : 0 : prlog(PR_ERR, "Attempting to dirty without an open write window\n");
535 : 0 : return FLASH_ERR_DEVICE_GONE;
536 : : }
537 : :
538 : 96 : return mbox_flash_mark_write(mbox_flash, pos, len,
539 : : MBOX_C_MARK_WRITE_DIRTY);
540 : : }
541 : :
542 : 3 : static int mbox_flash_erase(struct mbox_flash_data *mbox_flash, uint64_t pos,
543 : : uint64_t len)
544 : : {
545 : 3 : if (!mbox_flash->write.open) {
546 : 0 : prlog(PR_ERR, "Attempting to erase without an open write window\n");
547 : 0 : return FLASH_ERR_DEVICE_GONE;
548 : : }
549 : :
550 : 3 : return mbox_flash_mark_write(mbox_flash, pos, len,
551 : : MBOX_C_MARK_WRITE_ERASED);
552 : : }
553 : :
554 : 99 : static int mbox_flash_flush(struct mbox_flash_data *mbox_flash)
555 : : {
556 : 99 : struct bmc_mbox_msg msg = MSG_CREATE(MBOX_C_WRITE_FLUSH);
557 : : int rc;
558 : :
559 : 99 : if (!mbox_flash->write.open) {
560 : 0 : prlog(PR_ERR, "Attempting to flush without an open write window\n");
561 : 0 : return FLASH_ERR_DEVICE_GONE;
562 : : }
563 : :
564 : 99 : rc = msg_send(mbox_flash, &msg, mbox_flash->timeout);
565 : 99 : if (rc) {
566 : 0 : prlog(PR_ERR, "Failed to enqueue/send BMC MBOX message\n");
567 : 0 : return rc;
568 : : }
569 : :
570 : 99 : rc = wait_for_bmc(mbox_flash, mbox_flash->timeout);
571 : 99 : if (rc)
572 : 0 : prlog(PR_ERR, "Error waiting for BMC\n");
573 : :
574 : 99 : return rc;
575 : : }
576 : :
577 : : /* Is the current window able perform the complete operation */
578 : 762 : static bool mbox_window_valid(struct lpc_window *win, uint64_t pos,
579 : : uint64_t len)
580 : : {
581 : 762 : if (!win->open)
582 : 16 : return false;
583 : 746 : if (pos < win->cur_pos) /* start */
584 : 177 : return false;
585 : 569 : if ((pos + len) > (win->cur_pos + win->size)) /* end */
586 : 541 : return false;
587 : 28 : return true;
588 : : }
589 : :
590 : 762 : static int mbox_window_move(struct mbox_flash_data *mbox_flash,
591 : : struct lpc_window *win, uint8_t command,
592 : : uint64_t pos, uint64_t len, uint64_t *size)
593 : : {
594 : 762 : struct bmc_mbox_msg msg = MSG_CREATE(command);
595 : : int rc;
596 : :
597 : : /* Is the window currently open valid */
598 : 762 : if (mbox_window_valid(win, pos, len)) {
599 : 28 : *size = len;
600 : 28 : return 0;
601 : : }
602 : :
603 : : /* V1 needs to remember where it has opened the window, note it
604 : : * here.
605 : : * If we're running V2 the response to the CREATE_*_WINDOW command
606 : : * will overwrite what we've noted here.
607 : : */
608 : 734 : win->cur_pos = pos & ~mbox_flash_mask(mbox_flash);
609 : :
610 : 734 : msg_put_u16(&msg, 0, bytes_to_blocks(mbox_flash, pos));
611 : 734 : rc = msg_send(mbox_flash, &msg, mbox_flash->timeout);
612 : 734 : if (rc) {
613 : 0 : prlog(PR_ERR, "Failed to enqueue/send BMC MBOX message\n");
614 : 0 : return rc;
615 : : }
616 : :
617 : 734 : mbox_flash->read.open = false;
618 : 734 : mbox_flash->write.open = false;
619 : :
620 : 734 : rc = wait_for_bmc(mbox_flash, mbox_flash->timeout);
621 : 734 : if (rc) {
622 : 4 : prlog(PR_ERR, "Error waiting for BMC\n");
623 : 4 : return rc;
624 : : }
625 : :
626 : 730 : *size = len;
627 : : /* Is length past the end of the window? */
628 : 730 : if ((pos + len) > (win->cur_pos + win->size))
629 : : /* Adjust size to meet current window */
630 : 372 : *size = (win->cur_pos + win->size) - pos;
631 : :
632 : : /*
633 : : * It doesn't make sense for size to be zero if len isn't zero.
634 : : * If this condition happens we're most likely going to spin since
635 : : * the caller will likely decerement pos by zero then call this
636 : : * again.
637 : : * Debateable as to if this should return non zero. At least the
638 : : * bug will be obvious from the barf.
639 : : */
640 : 730 : if (len != 0 && *size == 0) {
641 : 0 : prlog(PR_ERR, "Failed read/write!\n");
642 : 0 : prlog(PR_ERR, "Please update your BMC firmware\n");
643 : 0 : prlog(PR_ERR, "Move window is indicating size zero!\n");
644 : 0 : prlog(PR_ERR, "pos: 0x%" PRIx64 ", len: 0x%" PRIx64 "\n", pos, len);
645 : 0 : prlog(PR_ERR, "win pos: 0x%08x win size: 0x%08x\n", win->cur_pos, win->size);
646 : : /*
647 : : * In practice skiboot gets stuck and this eventually
648 : : * brings down the host. Just fail pass the error back
649 : : * up and hope someone makes a good decision
650 : : */
651 : 0 : return MBOX_R_SYSTEM_ERROR;
652 : : }
653 : :
654 : 730 : return rc;
655 : : }
656 : :
657 : 20 : static int mbox_flash_write(struct blocklevel_device *bl, uint64_t pos,
658 : : const void *buf, uint64_t len)
659 : : {
660 : : struct mbox_flash_data *mbox_flash;
661 : : uint64_t size;
662 : :
663 : 20 : int rc = 0;
664 : :
665 : : /* LPC is only 32bit */
666 : 20 : if (pos > UINT_MAX || len > UINT_MAX)
667 : 0 : return FLASH_ERR_PARM_ERROR;
668 : :
669 : 20 : mbox_flash = container_of(bl, struct mbox_flash_data, bl);
670 : :
671 : 20 : if (do_delayed_work(mbox_flash))
672 : 0 : return FLASH_ERR_AGAIN;
673 : :
674 : 20 : prlog(PR_TRACE, "Flash write at %#" PRIx64 " for %#" PRIx64 "\n", pos, len);
675 : 116 : while (len > 0) {
676 : : /* Move window and get a new size to read */
677 : 96 : rc = mbox_window_move(mbox_flash, &mbox_flash->write,
678 : : MBOX_C_CREATE_WRITE_WINDOW, pos, len,
679 : : &size);
680 : 96 : if (rc)
681 : 0 : return rc;
682 : :
683 : : /* Perform the read for this window */
684 : 96 : rc = lpc_window_write(mbox_flash, pos, buf, size);
685 : 96 : if (rc)
686 : 0 : return rc;
687 : :
688 : 96 : rc = mbox_flash_dirty(mbox_flash, pos, size);
689 : 96 : if (rc)
690 : 0 : return rc;
691 : :
692 : : /*
693 : : * Must flush here as changing the window contents
694 : : * without flushing entitles the BMC to throw away the
695 : : * data. Unlike the read case there isn't a need to explicitly
696 : : * validate the window, the flush command will fail if the
697 : : * window was compromised.
698 : : */
699 : 96 : rc = mbox_flash_flush(mbox_flash);
700 : 96 : if (rc)
701 : 0 : return rc;
702 : :
703 : 96 : len -= size;
704 : 96 : pos += size;
705 : 96 : buf += size;
706 : : }
707 : 20 : return rc;
708 : : }
709 : :
710 : 367 : static int mbox_flash_read(struct blocklevel_device *bl, uint64_t pos,
711 : : void *buf, uint64_t len)
712 : : {
713 : : struct mbox_flash_data *mbox_flash;
714 : : uint64_t size;
715 : :
716 : 367 : int rc = 0;
717 : :
718 : : /* LPC is only 32bit */
719 : 367 : if (pos > UINT_MAX || len > UINT_MAX)
720 : 0 : return FLASH_ERR_PARM_ERROR;
721 : :
722 : 367 : mbox_flash = container_of(bl, struct mbox_flash_data, bl);
723 : :
724 : 367 : if (do_delayed_work(mbox_flash))
725 : 0 : return FLASH_ERR_AGAIN;
726 : :
727 : 367 : prlog(PR_TRACE, "Flash read at %#" PRIx64 " for %#" PRIx64 "\n", pos, len);
728 : 1026 : while (len > 0) {
729 : : /* Move window and get a new size to read */
730 : 663 : rc = mbox_window_move(mbox_flash, &mbox_flash->read,
731 : : MBOX_C_CREATE_READ_WINDOW, pos,
732 : : len, &size);
733 : 663 : if (rc)
734 : 4 : return rc;
735 : :
736 : : /* Perform the read for this window */
737 : 659 : rc = lpc_window_read(mbox_flash, pos, buf, size);
738 : 659 : if (rc)
739 : 0 : return rc;
740 : :
741 : 659 : len -= size;
742 : 659 : pos += size;
743 : 659 : buf += size;
744 : : /*
745 : : * Ensure my window is still open, if it isn't we can't trust
746 : : * what we read
747 : : */
748 : 659 : if (!is_valid(mbox_flash, &mbox_flash->read))
749 : 0 : return FLASH_ERR_AGAIN;
750 : : }
751 : 363 : return rc;
752 : : }
753 : :
754 : 1 : static bool mbox_flash_reset(struct blocklevel_device *bl)
755 : : {
756 : : int rc;
757 : : struct mbox_flash_data *mbox_flash;
758 : 1 : struct bmc_mbox_msg msg = MSG_CREATE(MBOX_C_RESET_STATE);
759 : :
760 : 1 : prlog(PR_NOTICE, "MBOX reset\n");
761 : 1 : mbox_flash = container_of(bl, struct mbox_flash_data, bl);
762 : :
763 : 1 : rc = msg_send(mbox_flash, &msg, mbox_flash->timeout);
764 : 1 : if (rc) {
765 : 0 : prlog(PR_ERR, "Failed to enqueue/send BMC MBOX RESET msg\n");
766 : 0 : return false;
767 : : }
768 : 1 : if (wait_for_bmc(mbox_flash, mbox_flash->timeout)) {
769 : 0 : prlog(PR_ERR, "Error waiting for BMC\n");
770 : 0 : return false;
771 : : }
772 : :
773 : 1 : return true;
774 : : }
775 : :
776 : 4 : static int mbox_flash_get_info(struct blocklevel_device *bl, const char **name,
777 : : uint64_t *total_size, uint32_t *erase_granule)
778 : : {
779 : 4 : struct bmc_mbox_msg msg = MSG_CREATE(MBOX_C_GET_FLASH_INFO);
780 : : struct mbox_flash_data *mbox_flash;
781 : : int rc;
782 : :
783 : 4 : mbox_flash = container_of(bl, struct mbox_flash_data, bl);
784 : :
785 : 4 : if (do_delayed_work(mbox_flash))
786 : 0 : return FLASH_ERR_AGAIN;
787 : :
788 : : /*
789 : : * We want to avoid runtime mallocs in skiboot. The expected
790 : : * behavour to uses of libflash is that one can free() the memory
791 : : * returned.
792 : : * NULL will do for now.
793 : : */
794 : 4 : if (name)
795 : 4 : *name = NULL;
796 : :
797 : 4 : mbox_flash->busy = true;
798 : 4 : rc = msg_send(mbox_flash, &msg, mbox_flash->timeout);
799 : 4 : if (rc) {
800 : 0 : prlog(PR_ERR, "Failed to enqueue/send BMC MBOX message\n");
801 : 0 : return rc;
802 : : }
803 : :
804 : 4 : if (wait_for_bmc(mbox_flash, mbox_flash->timeout)) {
805 : 0 : prlog(PR_ERR, "Error waiting for BMC\n");
806 : 0 : return rc;
807 : : }
808 : :
809 : 4 : mbox_flash->bl.erase_mask = mbox_flash->erase_granule - 1;
810 : :
811 : 4 : if (total_size)
812 : 4 : *total_size = mbox_flash->total_size;
813 : 4 : if (erase_granule)
814 : 4 : *erase_granule = mbox_flash->erase_granule;
815 : :
816 : 4 : return rc;
817 : : }
818 : :
819 : 3 : static int mbox_flash_erase_v2(struct blocklevel_device *bl, uint64_t pos,
820 : : uint64_t len)
821 : : {
822 : : struct mbox_flash_data *mbox_flash;
823 : :
824 : : /* LPC is only 32bit */
825 : 3 : if (pos > UINT_MAX || len > UINT_MAX)
826 : 0 : return FLASH_ERR_PARM_ERROR;
827 : :
828 : 3 : mbox_flash = container_of(bl, struct mbox_flash_data, bl);
829 : :
830 : 3 : prlog(PR_TRACE, "Flash erase at 0x%08x for 0x%08x\n", (u32) pos, (u32) len);
831 : 6 : while (len > 0) {
832 : : uint64_t size;
833 : : int rc;
834 : :
835 : : /* Move window and get a new size to erase */
836 : 3 : rc = mbox_window_move(mbox_flash, &mbox_flash->write,
837 : : MBOX_C_CREATE_WRITE_WINDOW, pos, len, &size);
838 : 3 : if (rc)
839 : 0 : return rc;
840 : :
841 : 3 : rc = mbox_flash_erase(mbox_flash, pos, size);
842 : 3 : if (rc)
843 : 0 : return rc;
844 : :
845 : : /*
846 : : * Flush directly, don't mark that region dirty otherwise it
847 : : * isn't clear if a write happened there or not
848 : : */
849 : :
850 : 3 : rc = mbox_flash_flush(mbox_flash);
851 : 3 : if (rc)
852 : 0 : return rc;
853 : :
854 : 3 : len -= size;
855 : 3 : pos += size;
856 : : }
857 : :
858 : 3 : return 0;
859 : : }
860 : :
861 : 1 : static int mbox_flash_erase_v1(struct blocklevel_device *bl __unused,
862 : : uint64_t pos __unused, uint64_t len __unused)
863 : : {
864 : : /*
865 : : * We can probably get away with doing nothing.
866 : : * TODO: Rethink this, causes interesting behaviour in pflash.
867 : : * Users do expect pflash -{e,E} to do something. This is because
868 : : * on real flash this would have set that region to all 0xFF but
869 : : * really the erase at the blocklevel interface was only designed
870 : : * to be "please make this region writeable".
871 : : * It may be wise (despite the large performance penalty) to
872 : : * actually write all 0xFF here. I'll leave that as an exercise
873 : : * for the future.
874 : : */
875 : :
876 : 1 : return 0;
877 : : }
878 : :
879 : : /* Called from interrupt handler, don't send any mbox messages */
880 : 3 : static void mbox_flash_attn(uint8_t attn, void *priv)
881 : : {
882 : 3 : struct mbox_flash_data *mbox_flash = priv;
883 : :
884 : 3 : if (attn & MBOX_ATTN_ACK_MASK)
885 : 3 : mbox_flash->ack = true;
886 : 3 : if (attn & MBOX_ATTN_BMC_REBOOT) {
887 : 3 : mbox_flash->reboot = true;
888 : 3 : mbox_flash->read.open = false;
889 : 3 : mbox_flash->write.open = false;
890 : 3 : attn &= ~MBOX_ATTN_BMC_REBOOT;
891 : : }
892 : :
893 : 3 : if (attn & MBOX_ATTN_BMC_WINDOW_RESET) {
894 : 0 : mbox_flash->read.open = false;
895 : 0 : mbox_flash->write.open = false;
896 : 0 : attn &= ~MBOX_ATTN_BMC_WINDOW_RESET;
897 : : }
898 : :
899 : 3 : if (attn & MBOX_ATTN_BMC_FLASH_LOST) {
900 : 0 : mbox_flash->pause = true;
901 : 0 : attn &= ~MBOX_ATTN_BMC_FLASH_LOST;
902 : : } else {
903 : 3 : mbox_flash->pause = false;
904 : : }
905 : 3 : }
906 : :
907 : 944 : static void mbox_flash_callback(struct bmc_mbox_msg *msg, void *priv)
908 : : {
909 : 944 : struct mbox_flash_data *mbox_flash = priv;
910 : :
911 : 944 : prlog(PR_TRACE, "BMC OK command %u\n", msg->command);
912 : :
913 : 944 : if (msg->response != MBOX_R_SUCCESS) {
914 : 4 : prlog(PR_ERR, "Bad response code from BMC %d\n", msg->response);
915 : 4 : mbox_flash->rc = msg->response;
916 : 4 : goto out;
917 : : }
918 : :
919 : 940 : if (msg->command > MBOX_COMMAND_COUNT) {
920 : 0 : prlog(PR_ERR, "Got response to unknown command %02x\n", msg->command);
921 : 0 : mbox_flash->rc = -1;
922 : 0 : goto out;
923 : : }
924 : :
925 : 940 : if (!mbox_flash->handlers[msg->command]) {
926 : 0 : prlog(PR_ERR, "Couldn't find handler for message! command: %u, seq: %u\n",
927 : : msg->command, msg->seq);
928 : 0 : mbox_flash->rc = MBOX_R_SYSTEM_ERROR;
929 : 0 : goto out;
930 : : }
931 : :
932 : 940 : mbox_flash->rc = 0;
933 : :
934 : 940 : mbox_flash->handlers[msg->command](mbox_flash, msg);
935 : :
936 : 944 : out:
937 : 944 : mbox_flash->busy = false;
938 : 944 : }
939 : :
940 : 4 : static int protocol_init(struct mbox_flash_data *mbox_flash, uint8_t shift)
941 : : {
942 : 4 : struct bmc_mbox_msg msg = MSG_CREATE(MBOX_C_GET_MBOX_INFO);
943 : : int rc;
944 : :
945 : 4 : mbox_flash->read.open = false;
946 : 4 : mbox_flash->write.open = false;
947 : :
948 : : /* Assume V2+ */
949 : 4 : mbox_flash->bl.read = &mbox_flash_read;
950 : 4 : mbox_flash->bl.write = &mbox_flash_write;
951 : 4 : mbox_flash->bl.erase = &mbox_flash_erase_v2;
952 : 4 : mbox_flash->bl.get_info = &mbox_flash_get_info;
953 : :
954 : : /* Assume V3 */
955 : 4 : mbox_flash->handlers = handlers_v3;
956 : :
957 : 4 : bmc_mbox_register_callback(&mbox_flash_callback, mbox_flash);
958 : 4 : bmc_mbox_register_attn(&mbox_flash_attn, mbox_flash);
959 : :
960 : : /*
961 : : * For V1 of the protocol this is fixed.
962 : : * V2+: The init code will update this
963 : : */
964 : 4 : mbox_flash->shift = 12;
965 : :
966 : : /*
967 : : * For V1 we'll use this value.
968 : : * V2+: The init code (may) update this
969 : : */
970 : 4 : mbox_flash->timeout = MBOX_DEFAULT_TIMEOUT;
971 : :
972 : : /*
973 : : * Always attempt init with highest version known.
974 : : * The GET_MBOX_INFO response will confirm that the other side can
975 : : * talk the highest version, we'll update this variable then if
976 : : * our highest version is not supported
977 : : */
978 : 4 : mbox_flash->version = 3;
979 : :
980 : 4 : negotiate_version:
981 : 4 : msg_put_u8(&msg, 0, mbox_flash->version);
982 : 4 : msg_put_u8(&msg, 1, shift);
983 : 4 : rc = msg_send(mbox_flash, &msg, mbox_flash->timeout);
984 : 4 : if (rc) {
985 : 0 : prlog(PR_ERR, "Failed to enqueue/send BMC MBOX message\n");
986 : 0 : return rc;
987 : : }
988 : :
989 : 4 : rc = wait_for_bmc(mbox_flash, mbox_flash->timeout);
990 : 4 : if (rc) {
991 : 0 : prlog(PR_ERR, "Error waiting for BMC\n");
992 : 0 : if (mbox_flash->version > 1) {
993 : 0 : mbox_flash->version--;
994 : 0 : prlog(PR_INFO, "Retrying MBOX negotiation with BMC"
995 : : " with MBOXv%d\n", mbox_flash->version);
996 : 0 : goto negotiate_version;
997 : : }
998 : 0 : return rc;
999 : : }
1000 : :
1001 : 4 : prlog(PR_INFO, "Detected mbox protocol version %d\n", mbox_flash->version);
1002 : 4 : switch (mbox_flash->version) {
1003 : 1 : case 1:
1004 : 1 : mbox_flash->bl.erase = &mbox_flash_erase_v1;
1005 : 1 : mbox_flash->handlers = handlers_v1;
1006 : 1 : break;
1007 : 2 : case 2:
1008 : 2 : mbox_flash->handlers = handlers_v2;
1009 : 2 : break;
1010 : 1 : case 3:
1011 : : /* Nothing to do we assumed it would be V3 */
1012 : 1 : break;
1013 : 0 : default:
1014 : : /*
1015 : : * The BMC is can only lower the requested version not do
1016 : : * anything else. FWIW there is no verion 0.
1017 : : */
1018 : 0 : prlog(PR_CRIT, "Bad version: %u\n", mbox_flash->version);
1019 : 0 : rc = FLASH_ERR_PARM_ERROR;
1020 : : }
1021 : :
1022 : 4 : return rc;
1023 : : }
1024 : :
1025 : 0 : int mbox_flash_lock(struct blocklevel_device *bl, uint64_t pos, uint64_t len)
1026 : : {
1027 : : struct mbox_flash_data *mbox_flash;
1028 : 0 : struct bmc_mbox_msg msg = MSG_CREATE(MBOX_C_MARK_LOCKED);
1029 : : int rc;
1030 : :
1031 : : /* mbox-flash only talks 32bit for now */
1032 : 0 : if (pos > UINT_MAX || len > UINT_MAX)
1033 : 0 : return FLASH_ERR_PARM_ERROR;
1034 : :
1035 : : /*
1036 : : * If the region isn't at least 4k aligned and in size then bail
1037 : : * out, the protocol won't allow for smaller block sizes.
1038 : : */
1039 : 0 : if (pos & ((1 << 12) - 1) || len & ((1 << 12) - 1))
1040 : 0 : return FLASH_ERR_PARM_ERROR;
1041 : :
1042 : 0 : mbox_flash = container_of(bl, struct mbox_flash_data, bl);
1043 : 0 : if ((pos & mbox_flash_mask(mbox_flash)) || (len & mbox_flash_mask(mbox_flash))) {
1044 : 0 : uint8_t shift = 0;
1045 : : /*
1046 : : * The current block size won't work for locking the requested
1047 : : * region must reinit.
1048 : : */
1049 : 0 : while (!((1 << shift) & pos) && !((1 << shift) & len))
1050 : 0 : shift++;
1051 : :
1052 : 0 : prlog(PR_INFO, "Locking flash requires re-init from shift of %d to shift of %d\n",
1053 : : mbox_flash->shift, shift);
1054 : :
1055 : 0 : rc = protocol_init(mbox_flash, shift);
1056 : 0 : if (rc)
1057 : 0 : return rc;
1058 : :
1059 : : /*
1060 : : * The daemon didn't agree with the requested shift - the
1061 : : * flash won't be able to be locked
1062 : : */
1063 : 0 : if (mbox_flash->shift > shift)
1064 : 0 : return FLASH_ERR_PARM_ERROR;
1065 : : }
1066 : :
1067 : 0 : msg_put_u16(&msg, 0, bytes_to_blocks(mbox_flash, pos));
1068 : 0 : msg_put_u16(&msg, 2, bytes_to_blocks(mbox_flash, len));
1069 : 0 : rc = msg_send(mbox_flash, &msg, mbox_flash->timeout);
1070 : 0 : if (rc) {
1071 : 0 : prlog(PR_ERR, "Failed to enqueue/send BMC MBOX message\n");
1072 : 0 : return rc;
1073 : : }
1074 : :
1075 : 0 : rc = wait_for_bmc(mbox_flash, mbox_flash->timeout);
1076 : 0 : if (rc)
1077 : 0 : prlog(PR_ERR, "Error waiting for BMC\n");
1078 : :
1079 : 0 : return rc;
1080 : : }
1081 : :
1082 : 1 : int mbox_flash_init(struct blocklevel_device **bl)
1083 : : {
1084 : : struct mbox_flash_data *mbox_flash;
1085 : : int rc;
1086 : :
1087 : : CHECK_HANDLER_SIZE(handlers_v3);
1088 : : CHECK_HANDLER_SIZE(handlers_v2);
1089 : : CHECK_HANDLER_SIZE(handlers_v1);
1090 : :
1091 : 1 : if (!bl)
1092 : 0 : return FLASH_ERR_PARM_ERROR;
1093 : :
1094 : : /* XXX: We only support one blocklevel flash device over mbox. If we
1095 : : * ever support more than one, move this out. The chances of that are
1096 : : * slim though due to circumstances.
1097 : : */
1098 : 1 : mbox_init();
1099 : :
1100 : 1 : *bl = NULL;
1101 : :
1102 : 1 : mbox_flash = zalloc(sizeof(struct mbox_flash_data));
1103 : 1 : if (!mbox_flash)
1104 : 0 : return FLASH_ERR_MALLOC_FAILED;
1105 : :
1106 : : /* Assume V2+ */
1107 : 1 : mbox_flash->bl.read = &mbox_flash_read;
1108 : 1 : mbox_flash->bl.write = &mbox_flash_write;
1109 : 1 : mbox_flash->bl.erase = &mbox_flash_erase_v2;
1110 : 1 : mbox_flash->bl.get_info = &mbox_flash_get_info;
1111 : 1 : mbox_flash->bl.exit = &mbox_flash_exit;
1112 : :
1113 : 1 : if (bmc_mbox_get_attn_reg() & MBOX_ATTN_BMC_REBOOT)
1114 : 0 : rc = handle_reboot(mbox_flash);
1115 : : else
1116 : 1 : rc = protocol_init(mbox_flash, 0);
1117 : 1 : if (rc) {
1118 : 0 : free(mbox_flash);
1119 : 0 : return rc;
1120 : : }
1121 : :
1122 : 1 : mbox_flash->bl.keep_alive = 0;
1123 : :
1124 : 1 : *bl = &(mbox_flash->bl);
1125 : 1 : return 0;
1126 : : }
1127 : :
1128 : 1 : bool mbox_flash_exit(struct blocklevel_device *bl)
1129 : : {
1130 : 1 : bool status = true;
1131 : : struct mbox_flash_data *mbox_flash;
1132 : 1 : if (bl) {
1133 : 1 : status = mbox_flash_reset(bl);
1134 : 1 : mbox_flash = container_of(bl, struct mbox_flash_data, bl);
1135 : 1 : free(mbox_flash);
1136 : : }
1137 : :
1138 : 1 : return status;
1139 : : }
|