@@ -25,6 +25,13 @@ static void *nvram_image;
static uint32_t nvram_size;
static bool nvram_ready;
+/* If another device (eg. BMC) is touching the nvram, we can mark it as busy
+ * to stop access */
+void nvram_set_ready(bool state)
+{
+ nvram_ready = state;
+}
+
static int64_t opal_read_nvram(uint64_t buffer, uint64_t size, uint64_t offset)
{
if (!nvram_ready)
@@ -41,6 +41,9 @@
#define SOFT_OFF 0x00
#define SOFT_REBOOT 0x01
+#define RELEASE_PNOR 0x00
+#define REQUEST_PNOR 0x01
+
struct oem_sel {
/* SEL header */
uint8_t id[2];
@@ -180,6 +183,24 @@ int ipmi_elog_commit(struct errorlog *elog_buf)
return 0;
}
+static void sel_pnor(uint8_t access)
+{
+ switch (access) {
+ case REQUEST_PNOR:
+ prlog(PR_NOTICE, "IPMI: PNOR access requested\n");
+ nvram_set_ready(false);
+ /* TODO: Ack the request */
+ break;
+ case RELEASE_PNOR:
+ prlog(PR_NOTICE, "IPMI: PNOR access released\n");
+ nvram_set_ready(true);
+ break;
+ default:
+ prlog(PR_ERR, "IPMI: invalid PNOR access requested: %02x\n",
+ access);
+ }
+}
+
static void sel_power(uint8_t power)
{
switch (power) {
@@ -248,6 +269,7 @@ void ipmi_parse_sel(struct ipmi_msg *msg)
sel_power(sel.data[0]);
break;
case CMD_AMI_PNOR_ACCESS:
+ sel_pnor(sel.data[0]);
break;
default:
printf("IPMI: unknown OEM SEL command %02x received\n",
@@ -199,6 +199,7 @@ extern void occ_fsp_init(void);
/* NVRAM support */
extern void nvram_init(void);
extern void nvram_read_complete(bool success);
+extern void nvram_set_ready(bool state);
/* NVRAM on flash helper */
struct flash_chip;
BMC based systems contain a PNOR to provide nvram storage. The host normally has exclusive access to the PNOR, however the BMC may use IPMI to request access to perform functions such as update the firmware. Indicate to users of the opal_vmram_{read,write} functions that the device is busy. Signed-off-by: Joel Stanley <joel@jms.id.au> --- core/nvram.c | 7 +++++++ hw/ipmi/ipmi-sel.c | 22 ++++++++++++++++++++++ include/skiboot.h | 1 + 3 files changed, 30 insertions(+)