aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/flash.c58
-rw-r--r--hw/ipmi/ipmi-sel.c36
-rw-r--r--include/ipmi.h5
-rw-r--r--include/skiboot.h3
4 files changed, 94 insertions, 8 deletions
diff --git a/core/flash.c b/core/flash.c
index 3a06d1d..9912add 100644
--- a/core/flash.c
+++ b/core/flash.c
@@ -26,6 +26,7 @@
struct flash {
bool registered;
+ bool busy;
struct flash_chip *chip;
uint32_t size;
uint32_t block_size;
@@ -42,12 +43,39 @@ static struct lock flash_lock;
static struct flash *nvram_flash;
static u32 nvram_offset, nvram_size;
+bool flash_reserve(void)
+{
+ bool rc = false;
+
+ if (!try_lock(&flash_lock))
+ return false;
+
+ if (!system_flash->busy) {
+ system_flash->busy = true;
+ rc = true;
+ }
+ unlock(&flash_lock);
+
+ return rc;
+}
+
+void flash_release(void)
+{
+ lock(&flash_lock);
+ system_flash->busy = false;
+ unlock(&flash_lock);
+}
+
static int flash_nvram_info(uint32_t *total_size)
{
- int rc = OPAL_HARDWARE;
+ int rc;
lock(&flash_lock);
- if (nvram_flash) {
+ if (!nvram_flash) {
+ rc = OPAL_HARDWARE;
+ } else if (nvram_flash->busy) {
+ rc = OPAL_BUSY;
+ } else {
*total_size = nvram_size;
rc = OPAL_SUCCESS;
}
@@ -60,13 +88,19 @@ static int flash_nvram_start_read(void *dst, uint32_t src, uint32_t len)
{
int rc;
- lock(&flash_lock);
+ if (!try_lock(&flash_lock))
+ return OPAL_BUSY;
if (!nvram_flash) {
rc = OPAL_HARDWARE;
goto out;
}
+ if (nvram_flash->busy) {
+ rc = OPAL_BUSY;
+ goto out;
+ }
+
if ((src + len) > nvram_size) {
prerror("FLASH_NVRAM: read out of bound (0x%x,0x%x)\n",
src, len);
@@ -87,7 +121,13 @@ static int flash_nvram_write(uint32_t dst, void *src, uint32_t len)
{
int rc;
- lock(&flash_lock);
+ if (try_lock(&flash_lock))
+ return OPAL_BUSY;
+
+ if (nvram_flash->busy) {
+ rc = OPAL_BUSY;
+ goto out;
+ }
/* TODO: When we have async jobs for PRD, turn this into one */
@@ -235,6 +275,7 @@ int flash_register(struct flash_chip *chip, bool is_system_flash)
flash = &flashes[i];
flash->registered = true;
+ flash->busy = false;
flash->chip = chip;
flash->size = size;
flash->block_size = block_size;
@@ -286,6 +327,12 @@ static int64_t opal_flash_op(enum flash_op op, uint64_t id, uint64_t offset,
return OPAL_BUSY;
flash = &flashes[id];
+
+ if (flash->busy) {
+ rc = OPAL_BUSY;
+ goto err;
+ }
+
if (!flash->registered) {
rc = OPAL_PARAMETER;
goto err;
@@ -493,6 +540,9 @@ bool flash_load_resource(enum resource_id id, uint32_t subid,
flash = system_flash;
+ if (flash->busy)
+ goto out_unlock;
+
for (i = 0, name = NULL; i < ARRAY_SIZE(part_name_map); i++) {
if (part_name_map[i].id == id) {
name = part_name_map[i].name;
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);