[Skiboot] [PATCH 1/2] hw/ipmi: Disable flash access when requested

Jeremy Kerr jk at ozlabs.org
Fri Feb 27 21:18:19 AEDT 2015


From: Joel Stanley <joel at jms.id.au>

BMC based systems contain a PNOR to provide flash 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 flash that the device is busy by taking the
lock, which causes flash operations to return OPAL_BUSY.

Signed-off-by: Joel Stanley <joel at jms.id.au>

---
 core/flash.c       |   10 ++++++++++
 hw/ipmi/ipmi-sel.c |   36 ++++++++++++++++++++++++++++++++++--
 include/ipmi.h     |    5 +++--
 include/skiboot.h  |    3 +++
 4 files changed, 50 insertions(+), 4 deletions(-)

diff --git a/core/flash.c b/core/flash.c
index 187d7c2..704651d 100644
--- a/core/flash.c
+++ b/core/flash.c
@@ -42,6 +42,16 @@ static struct lock flash_lock;
 static struct flash *nvram_flash;
 static u32 nvram_offset, nvram_size;
 
+bool flash_reserve(void)
+{
+	return try_lock(&flash_lock);
+}
+
+void flash_release(void)
+{
+	unlock(&flash_lock);
+}
+
 static int flash_nvram_info(uint32_t *total_size)
 {
 	int rc = OPAL_HARDWARE;
diff --git a/hw/ipmi/ipmi-sel.c b/hw/ipmi/ipmi-sel.c
index 173b7be..c86c2c9 100644
--- a/hw/ipmi/ipmi-sel.c
+++ b/hw/ipmi/ipmi-sel.c
@@ -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,33 @@ int ipmi_elog_commit(struct errorlog *elog_buf)
 	return 0;
 }
 
+#define ACCESS_DENIED	0x00
+#define ACCESS_GRANTED	0x01
+
+static void sel_pnor(uint8_t access)
+{
+	struct ipmi_msg *msg;
+	uint8_t granted = ACCESS_GRANTED;
+
+	switch (access) {
+	case REQUEST_PNOR:
+		prlog(PR_NOTICE, "IPMI: PNOR access requested\n");
+		granted = flash_reserve();
+
+		/* Ack the request */
+		msg = ipmi_mkmsg_simple(IPMI_PNOR_ACCESS_STATUS, &granted, 1);
+		ipmi_queue_msg(msg);
+		break;
+	case RELEASE_PNOR:
+		prlog(PR_NOTICE, "IPMI: PNOR access released\n");
+		flash_release();
+		break;
+	default:
+		prlog(PR_ERR, "IPMI: invalid PNOR access requested: %02x\n",
+		      access);
+	}
+}
+
 static void sel_power(uint8_t power)
 {
 	switch (power) {
@@ -271,9 +301,11 @@ void ipmi_parse_sel(struct ipmi_msg *msg)
 		sel_occ_reset(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",
-		       sel.cmd);
+		prlog(PR_WARNING,
+		      "IPMI: unknown OEM SEL command %02x received\n",
+		      sel.cmd);
 	}
 }
diff --git a/include/ipmi.h b/include/ipmi.h
index 9e52916..de5a61b 100644
--- a/include/ipmi.h
+++ b/include/ipmi.h
@@ -91,7 +91,6 @@
 #define IPMI_NETFN_CHASSIS		0x00
 #define IPMI_NETFN_STORAGE		0x0a
 #define IPMI_NETFN_APP			0x06
-#define IPMI_NETFN_OEM			0x32
 
 #define IPMI_WRITE_FRU			IPMI_CODE(IPMI_NETFN_STORAGE, 0x12)
 #define IPMI_GET_SEL_INFO		IPMI_CODE(IPMI_NETFN_STORAGE, 0x40)
@@ -110,7 +109,9 @@
 #define IPMI_GET_MESSAGE		IPMI_CODE(IPMI_NETFN_APP, 0x33)
 #define IPMI_READ_EVENT			IPMI_CODE(IPMI_NETFN_APP, 0x35)
 
-#define IPMI_PARTIAL_ADD_ESEL		IPMI_CODE(IPMI_NETFN_OEM, 0xf0)
+/* AMI OEM comamnds. AMI uses NETFN 0x3a and 0x32 */
+#define IPMI_PARTIAL_ADD_ESEL		IPMI_CODE(0x32, 0xf0)
+#define IPMI_PNOR_ACCESS_STATUS 	IPMI_CODE(0x3a, 0x07)
 
 /*
  * IPMI response codes.
diff --git a/include/skiboot.h b/include/skiboot.h
index 9dfe0e7..beaa7db 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -201,6 +201,9 @@ struct flash_chip;
 extern int flash_register(struct flash_chip *chip, bool is_system_flash);
 extern bool flash_load_resource(enum resource_id id, uint32_t subid,
 		void *buf, size_t *len);
+extern bool flash_reserve(void);
+extern void flash_release(void);
+
 
 /* NVRAM support */
 extern void nvram_init(void);


More information about the Skiboot mailing list