@@ -1,4 +1,4 @@
-/* Copyright 2013-2018 IBM Corp.
+/* Copyright 2013-2019 IBM Corp.
* Copyright 2018 Raptor Engineering, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -24,6 +24,7 @@
#include <device.h>
#include <libflash/libflash.h>
#include <libflash/libffs.h>
+#include <libflash/ipmi-hiomap.h>
#include <libflash/blocklevel.h>
#include <libflash/ecc.h>
#include <libstb/secureboot.h>
@@ -88,6 +89,17 @@ void flash_release(void)
unlock(&flash_lock);
}
+bool flash_unregister(void)
+{
+ struct blocklevel_device *bl = system_flash->bl;
+
+ if (bl->exit)
+ return bl->exit(bl);
+
+ prlog(PR_NOTICE, "FLASH: Unregister flash device is not supported\n");
+ return true;
+}
+
static int flash_nvram_info(uint32_t *total_size)
{
int rc;
@@ -962,6 +962,12 @@ void p9_sbe_terminate(void)
if (!dt_find_by_path(opal_node, "dump"))
return;
+ /* Unregister flash. It will request BMC MBOX reset */
+ if (!flash_unregister()) {
+ prlog(PR_DEBUG, "Failed to reset BMC MBOX\n");
+ return;
+ }
+
/* Save crashing CPU details */
opal_mpipl_save_crashing_pir();
@@ -1,4 +1,4 @@
-/* Copyright 2013-2014 IBM Corp.
+/* Copyright 2013-2019 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -224,6 +224,7 @@ extern int flash_start_preload_resource(enum resource_id id, uint32_t subid,
extern int flash_resource_loaded(enum resource_id id, uint32_t idx);
extern bool flash_reserve(void);
extern void flash_release(void);
+extern bool flash_unregister(void);
#define FLASH_SUBPART_ALIGNMENT 0x1000
#define FLASH_SUBPART_HEADER_SIZE FLASH_SUBPART_ALIGNMENT
extern int flash_subpart_info(void *part_header, uint32_t header_len,
@@ -47,6 +47,7 @@ struct blocklevel_device {
int (*erase)(struct blocklevel_device *bl, uint64_t pos, uint64_t len);
int (*get_info)(struct blocklevel_device *bl, const char **name, uint64_t *total_size,
uint32_t *erase_granule);
+ bool (*exit)(struct blocklevel_device *bl);
/*
* Keep the erase mask so that blocklevel_erase() can do sanity checking
@@ -223,6 +223,7 @@ static void ipmi_hiomap_cmd_cb(struct ipmi_msg *msg)
case HIOMAP_C_FLUSH:
case HIOMAP_C_ACK:
case HIOMAP_C_ERASE:
+ case HIOMAP_C_RESET:
if (msg->resp_size != 2) {
prerror("%u: Unexpected response size: %u\n", msg->data[0],
msg->resp_size);
@@ -529,6 +530,29 @@ static int hiomap_erase(struct ipmi_hiomap *ctx, uint64_t offset,
return 0;
}
+static bool hiomap_reset(struct ipmi_hiomap *ctx)
+{
+ RESULT_INIT(res, ctx);
+ unsigned char req[2];
+ struct ipmi_msg *msg;
+
+ prlog(PR_NOTICE, "Reset\n");
+
+ req[0] = HIOMAP_C_RESET;
+ req[1] = ++ctx->seq;
+ msg = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE,
+ bmc_platform->sw->ipmi_oem_hiomap_cmd,
+ ipmi_hiomap_cmd_cb, &res, req, sizeof(req), 2);
+ ipmi_queue_msg_sync(msg);
+
+ if (res.cc != IPMI_CC_NO_ERROR) {
+ prlog(PR_ERR, "%s failed: %d\n", __func__, res.cc);
+ return false;
+ }
+
+ return true;
+}
+
static void hiomap_event(uint8_t events, void *context)
{
struct ipmi_hiomap *ctx = context;
@@ -919,6 +943,7 @@ int ipmi_hiomap_init(struct blocklevel_device **bl)
ctx->bl.write = &ipmi_hiomap_write;
ctx->bl.erase = &ipmi_hiomap_erase;
ctx->bl.get_info = &ipmi_hiomap_get_flash_info;
+ ctx->bl.exit = &ipmi_hiomap_exit;
hiomap_init(ctx);
@@ -968,11 +993,16 @@ err:
return rc;
}
-void ipmi_hiomap_exit(struct blocklevel_device *bl)
+bool ipmi_hiomap_exit(struct blocklevel_device *bl)
{
+ bool status = true;
+
struct ipmi_hiomap *ctx;
if (bl) {
ctx = container_of(bl, struct ipmi_hiomap, bl);
+ status = hiomap_reset(ctx);
free(ctx);
}
+
+ return status;
}
@@ -53,6 +53,6 @@ struct ipmi_hiomap {
};
int ipmi_hiomap_init(struct blocklevel_device **bl);
-void ipmi_hiomap_exit(struct blocklevel_device *bl);
+bool ipmi_hiomap_exit(struct blocklevel_device *bl);
#endif /* __LIBFLASH_IPMI_HIOMAP_H */
@@ -816,6 +816,28 @@ static int mbox_flash_read(struct blocklevel_device *bl, uint64_t pos,
return rc;
}
+static bool mbox_flash_reset(struct blocklevel_device *bl)
+{
+ int rc;
+ struct mbox_flash_data *mbox_flash;
+ struct bmc_mbox_msg msg = MSG_CREATE(MBOX_C_RESET_STATE);
+
+ prlog(PR_NOTICE, "MBOX reset\n");
+ mbox_flash = container_of(bl, struct mbox_flash_data, bl);
+
+ rc = msg_send(mbox_flash, &msg, mbox_flash->timeout);
+ if (rc) {
+ prlog(PR_ERR, "Failed to enqueue/send BMC MBOX RESET msg\n");
+ return false;
+ }
+ if (wait_for_bmc(mbox_flash, mbox_flash->timeout)) {
+ prlog(PR_ERR, "Error waiting for BMC\n");
+ return false;
+ }
+
+ return true;
+}
+
static int mbox_flash_get_info(struct blocklevel_device *bl, const char **name,
uint64_t *total_size, uint32_t *erase_granule)
{
@@ -1151,6 +1173,7 @@ int mbox_flash_init(struct blocklevel_device **bl)
mbox_flash->bl.write = &mbox_flash_write;
mbox_flash->bl.erase = &mbox_flash_erase_v2;
mbox_flash->bl.get_info = &mbox_flash_get_info;
+ mbox_flash->bl.exit = &mbox_flash_exit;
if (bmc_mbox_get_attn_reg() & MBOX_ATTN_BMC_REBOOT)
rc = handle_reboot(mbox_flash);
@@ -1167,11 +1190,15 @@ int mbox_flash_init(struct blocklevel_device **bl)
return 0;
}
-void mbox_flash_exit(struct blocklevel_device *bl)
+bool mbox_flash_exit(struct blocklevel_device *bl)
{
+ bool status = true;
struct mbox_flash_data *mbox_flash;
if (bl) {
+ status = mbox_flash_reset(bl);
mbox_flash = container_of(bl, struct mbox_flash_data, bl);
free(mbox_flash);
}
+
+ return status;
}
@@ -19,7 +19,7 @@
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);
+bool mbox_flash_exit(struct blocklevel_device *bl);
#endif /* __LIBFLASH_MBOX_FLASH_H */
@@ -286,6 +286,7 @@ int bmc_mbox_enqueue(struct bmc_mbox_msg *msg,
switch (msg->command) {
case MBOX_C_RESET_STATE:
prlog(PR_INFO, "RESET_STATE\n");
+ server_state.win_type = WIN_CLOSED;
rc = open_window(msg, false, 0, LPC_BLOCKS);
memset(msg->args, 0, sizeof(msg->args));
break;
@@ -476,10 +476,101 @@ static const struct scenario_event hiomap_erase_qs0l1_call = {
},
};
+static const struct scenario_event hiomap_reset_call_seq_4 = {
+ .type = scenario_cmd,
+ .c = {
+ .req = {
+ .cmd = HIOMAP_C_RESET,
+ .seq = 4,
+ },
+ .cc = IPMI_CC_NO_ERROR,
+ .resp = {
+ .cmd = HIOMAP_C_RESET,
+ .seq = 4,
+ },
+ },
+};
+
+static const struct scenario_event hiomap_reset_call_seq_5 = {
+ .type = scenario_cmd,
+ .c = {
+ .req = {
+ .cmd = HIOMAP_C_RESET,
+ .seq = 5,
+ },
+ .cc = IPMI_CC_NO_ERROR,
+ .resp = {
+ .cmd = HIOMAP_C_RESET,
+ .seq = 5,
+ },
+ },
+};
+
+static const struct scenario_event hiomap_reset_call_seq_6 = {
+ .type = scenario_cmd,
+ .c = {
+ .req = {
+ .cmd = HIOMAP_C_RESET,
+ .seq = 6,
+ },
+ .cc = IPMI_CC_NO_ERROR,
+ .resp = {
+ .cmd = HIOMAP_C_RESET,
+ .seq = 6,
+ },
+ },
+};
+
+static const struct scenario_event hiomap_reset_call_seq_7 = {
+ .type = scenario_cmd,
+ .c = {
+ .req = {
+ .cmd = HIOMAP_C_RESET,
+ .seq = 7,
+ },
+ .cc = IPMI_CC_NO_ERROR,
+ .resp = {
+ .cmd = HIOMAP_C_RESET,
+ .seq = 7,
+ },
+ },
+};
+
+static const struct scenario_event hiomap_reset_call_seq_9 = {
+ .type = scenario_cmd,
+ .c = {
+ .req = {
+ .cmd = HIOMAP_C_RESET,
+ .seq = 9,
+ },
+ .cc = IPMI_CC_NO_ERROR,
+ .resp = {
+ .cmd = HIOMAP_C_RESET,
+ .seq = 9,
+ },
+ },
+};
+
+static const struct scenario_event hiomap_reset_call_seq_a = {
+ .type = scenario_cmd,
+ .c = {
+ .req = {
+ .cmd = HIOMAP_C_RESET,
+ .seq = 0xa,
+ },
+ .cc = IPMI_CC_NO_ERROR,
+ .resp = {
+ .cmd = HIOMAP_C_RESET,
+ .seq = 0xa,
+ },
+ },
+};
+
static const struct scenario_event scenario_hiomap_init[] = {
{ .type = scenario_event_p, .p = &hiomap_ack_call, },
{ .type = scenario_event_p, .p = &hiomap_get_info_call, },
{ .type = scenario_event_p, .p = &hiomap_get_flash_info_call, },
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_4, },
SCENARIO_SENTINEL,
};
@@ -498,6 +589,7 @@ static const struct scenario_event scenario_hiomap_event_daemon_ready[] = {
{ .type = scenario_event_p, .p = &hiomap_get_info_call, },
{ .type = scenario_event_p, .p = &hiomap_get_flash_info_call, },
{ .type = scenario_sel, .s = { .bmc_state = HIOMAP_E_DAEMON_READY } },
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_4, },
SCENARIO_SENTINEL,
};
@@ -520,6 +612,7 @@ static const struct scenario_event scenario_hiomap_event_daemon_stopped[] = {
{ .type = scenario_event_p, .p = &hiomap_get_flash_info_call, },
{ .type = scenario_sel, .s = { .bmc_state = HIOMAP_E_DAEMON_READY } },
{ .type = scenario_sel, .s = { .bmc_state = HIOMAP_E_PROTOCOL_RESET } },
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_4, },
SCENARIO_SENTINEL,
};
@@ -543,6 +636,7 @@ static const struct scenario_event scenario_hiomap_event_daemon_restarted[] = {
{ .type = scenario_sel, .s = { .bmc_state = HIOMAP_E_DAEMON_READY } },
{ .type = scenario_sel, .s = { .bmc_state = HIOMAP_E_PROTOCOL_RESET } },
{ .type = scenario_sel, .s = { .bmc_state = HIOMAP_E_DAEMON_READY } },
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_4, },
SCENARIO_SENTINEL,
};
@@ -572,6 +666,7 @@ scenario_hiomap_event_daemon_lost_flash_control[] = {
| HIOMAP_E_FLASH_LOST),
}
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_5, },
SCENARIO_SENTINEL,
};
@@ -677,6 +772,7 @@ scenario_hiomap_event_daemon_regained_flash_control_dirty[] = {
},
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_7, },
SCENARIO_SENTINEL,
};
@@ -819,6 +915,7 @@ static const struct scenario_event scenario_hiomap_protocol_reset_recovery[] = {
},
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_9, },
SCENARIO_SENTINEL,
};
@@ -851,6 +948,7 @@ scenario_hiomap_protocol_read_one_block[] = {
.type = scenario_event_p,
.p = &hiomap_create_read_window_qs0l1_rs0l1_call,
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_5, },
SCENARIO_SENTINEL,
};
@@ -924,6 +1022,7 @@ scenario_hiomap_protocol_read_two_blocks[] = {
},
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_6, },
SCENARIO_SENTINEL,
};
@@ -976,6 +1075,7 @@ scenario_hiomap_protocol_read_one_block_twice[] = {
.type = scenario_event_p,
.p = &hiomap_create_read_window_qs0l1_rs0l1_call,
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_5, },
SCENARIO_SENTINEL,
};
@@ -1011,6 +1111,7 @@ scenario_hiomap_protocol_event_before_action[] = {
HIOMAP_E_FLASH_LOST,
}
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_5, },
SCENARIO_SENTINEL,
};
@@ -1044,6 +1145,7 @@ scenario_hiomap_protocol_event_during_read[] = {
HIOMAP_E_FLASH_LOST,
}
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_5, },
SCENARIO_SENTINEL,
};
@@ -1079,6 +1181,7 @@ scenario_hiomap_protocol_write_one_block[] = {
},
{ .type = scenario_event_p, .p = &hiomap_mark_dirty_qs0l1_call, },
{ .type = scenario_event_p, .p = &hiomap_flush_call, },
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_7, },
SCENARIO_SENTINEL,
};
@@ -1163,6 +1266,7 @@ scenario_hiomap_protocol_write_two_blocks[] = {
},
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_a, },
SCENARIO_SENTINEL,
};
@@ -1245,6 +1349,7 @@ scenario_hiomap_protocol_write_one_block_twice[] = {
},
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_9, },
SCENARIO_SENTINEL,
};
@@ -1298,6 +1403,7 @@ scenario_hiomap_protocol_event_during_write[] = {
HIOMAP_E_FLASH_LOST,
}
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_6, },
SCENARIO_SENTINEL,
};
@@ -1339,6 +1445,7 @@ scenario_hiomap_protocol_erase_one_block[] = {
.type = scenario_event_p,
.p = &hiomap_flush_call,
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_7, },
SCENARIO_SENTINEL,
};
@@ -1387,6 +1494,7 @@ scenario_hiomap_protocol_erase_two_blocks[] = {
},
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_a, },
SCENARIO_SENTINEL,
};
@@ -1446,6 +1554,7 @@ scenario_hiomap_protocol_erase_one_block_twice[] = {
},
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_9, },
SCENARIO_SENTINEL,
};
@@ -1513,6 +1622,7 @@ scenario_hiomap_protocol_event_during_erase[] = {
HIOMAP_E_FLASH_LOST,
}
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_6, },
SCENARIO_SENTINEL,
};
@@ -1617,6 +1727,7 @@ scenario_hiomap_protocol_get_flash_info[] = {
},
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_5, },
SCENARIO_SENTINEL,
};
@@ -1643,6 +1754,7 @@ scenario_hiomap_protocol_persistent_error[] = {
{ .type = scenario_event_p, .p = &hiomap_get_info_call, },
{ .type = scenario_event_p, .p = &hiomap_get_flash_info_call, },
{ .type = scenario_sel, .s = { .bmc_state = HIOMAP_E_PROTOCOL_RESET } },
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_6, },
SCENARIO_SENTINEL,
};
@@ -1741,6 +1853,7 @@ scenario_hiomap_create_read_window_error[] = {
.cc = IPMI_INVALID_COMMAND_ERR,
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_5, },
SCENARIO_SENTINEL,
};
@@ -1782,6 +1895,7 @@ scenario_hiomap_create_write_window_error[] = {
.cc = IPMI_INVALID_COMMAND_ERR,
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_5, },
SCENARIO_SENTINEL,
};
@@ -1826,6 +1940,7 @@ static const struct scenario_event scenario_hiomap_mark_dirty_error[] = {
.cc = IPMI_INVALID_COMMAND_ERR,
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_6, },
SCENARIO_SENTINEL,
};
@@ -1867,6 +1982,7 @@ static const struct scenario_event scenario_hiomap_flush_error[] = {
.cc = IPMI_INVALID_COMMAND_ERR,
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_7, },
SCENARIO_SENTINEL,
};
@@ -1917,6 +2033,7 @@ static const struct scenario_event scenario_hiomap_erase_error[] = {
.cc = IPMI_INVALID_COMMAND_ERR,
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_6, },
SCENARIO_SENTINEL,
};
@@ -2137,6 +2254,7 @@ scenario_hiomap_create_read_window_malformed_small[] = {
},
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_5, },
SCENARIO_SENTINEL,
};
@@ -2184,6 +2302,7 @@ scenario_hiomap_create_read_window_malformed_large[] = {
},
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_5, },
SCENARIO_SENTINEL,
};
@@ -2230,6 +2349,7 @@ scenario_hiomap_create_write_window_malformed_small[] = {
},
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_5, },
SCENARIO_SENTINEL,
};
@@ -2277,6 +2397,7 @@ scenario_hiomap_create_write_window_malformed_large[] = {
},
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_5, },
SCENARIO_SENTINEL,
};
@@ -2326,6 +2447,7 @@ scenario_hiomap_mark_dirty_malformed_small[] = {
},
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_6, },
SCENARIO_SENTINEL,
};
@@ -2376,6 +2498,7 @@ scenario_hiomap_mark_dirty_malformed_large[] = {
},
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_6, },
SCENARIO_SENTINEL,
};
@@ -2422,6 +2545,7 @@ scenario_hiomap_flush_malformed_small[] = {
},
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_7, },
SCENARIO_SENTINEL,
};
@@ -2469,6 +2593,7 @@ scenario_hiomap_flush_malformed_large[] = {
},
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_7, },
SCENARIO_SENTINEL,
};
@@ -2518,6 +2643,7 @@ scenario_hiomap_erase_malformed_small[] = {
},
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_6, },
SCENARIO_SENTINEL,
};
@@ -2563,6 +2689,7 @@ scenario_hiomap_erase_malformed_large[] = {
},
},
},
+ { .type = scenario_event_p, .p = &hiomap_reset_call_seq_6, },
SCENARIO_SENTINEL,
};
@@ -2768,6 +2895,20 @@ scenario_hiomap_protocol_recovery_failure_ack[] = {
},
},
},
+ {
+ .type = scenario_cmd,
+ .c = {
+ .req = {
+ .cmd = HIOMAP_C_RESET,
+ .seq = 14,
+ },
+ .cc = IPMI_CC_NO_ERROR,
+ .resp = {
+ .cmd = HIOMAP_C_RESET,
+ .seq = 14,
+ },
+ },
+ },
SCENARIO_SENTINEL,
};
@@ -2938,6 +3079,20 @@ scenario_hiomap_protocol_recovery_failure_get_info[] = {
},
},
},
+ {
+ .type = scenario_cmd,
+ .c = {
+ .req = {
+ .cmd = HIOMAP_C_RESET,
+ .seq = 15,
+ },
+ .cc = IPMI_CC_NO_ERROR,
+ .resp = {
+ .cmd = HIOMAP_C_RESET,
+ .seq = 15,
+ },
+ },
+ },
SCENARIO_SENTINEL,
};
@@ -3107,6 +3262,20 @@ scenario_hiomap_protocol_recovery_failure_get_flash_info[] = {
},
},
},
+ {
+ .type = scenario_cmd,
+ .c = {
+ .req = {
+ .cmd = HIOMAP_C_RESET,
+ .seq = 16,
+ },
+ .cc = IPMI_CC_NO_ERROR,
+ .resp = {
+ .cmd = HIOMAP_C_RESET,
+ .seq = 16,
+ },
+ },
+ },
SCENARIO_SENTINEL,
};