[Skiboot] [PATCH 6/7 v3] prd: Don't expose full opal_prd_msg to kernel

Jeremy Kerr jk at ozlabs.org
Tue May 19 19:05:38 AEST 2015


The kernel is only accessing part of struct opal_prd_msg, and doesn't
need to know about the rest. This change moves the "internal" parts of
opal_prd_msg to a separate header.

In order for the kernel to pass full messages between userspace and
firmware, it needs the total size of the struct. We put this in the
header for the kernel to access.

Signed-off-by: Jeremy Kerr <jk at ozlabs.org>

---
 hw/prd.c           |   24 ++++++++++++++++--------
 include/opal-api.h |   11 ++++++++---
 2 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/hw/prd.c b/hw/prd.c
index e775adb..87babd1 100644
--- a/hw/prd.c
+++ b/hw/prd.c
@@ -89,7 +89,7 @@ static void prd_msg_consumed(void *data)
 	uint8_t event = 0;
 
 	lock(&events_lock);
-	switch (msg->type) {
+	switch (msg->hdr.type) {
 	case OPAL_PRD_MSG_TYPE_ATTN:
 		proc = msg->attn.proc;
 
@@ -169,19 +169,20 @@ static void send_pending_events(void)
 
 	prd_msg_inuse = true;
 	prd_msg.token = 0;
+	prd_msg.hdr.size = sizeof(prd_msg);
 
 	if (event & EVENT_ATTN) {
-		prd_msg.type = OPAL_PRD_MSG_TYPE_ATTN;
+		prd_msg.hdr.type = OPAL_PRD_MSG_TYPE_ATTN;
 		populate_ipoll_msg(&prd_msg, proc);
 		event = EVENT_ATTN;
 
 	} else if (event & EVENT_OCC_ERROR) {
-		prd_msg.type = OPAL_PRD_MSG_TYPE_OCC_ERROR;
+		prd_msg.hdr.type = OPAL_PRD_MSG_TYPE_OCC_ERROR;
 		prd_msg.occ_error.chip = proc;
 		event = EVENT_OCC_ERROR;
 
 	} else if (event & EVENT_OCC_RESET) {
-		prd_msg.type = OPAL_PRD_MSG_TYPE_OCC_RESET;
+		prd_msg.hdr.type = OPAL_PRD_MSG_TYPE_OCC_RESET;
 		prd_msg.occ_reset.chip = proc;
 		event = EVENT_OCC_RESET;
 
@@ -325,13 +326,20 @@ static int64_t opal_prd_msg(struct opal_prd_msg *msg)
 {
 	int rc;
 
-	switch (msg->type) {
+	/* fini is a little special: the kernel (which may not have the entire
+	 * opal_prd_msg definition) can send a FINI message, so we don't check
+	 * the full size */
+	if (msg->hdr.size >= sizeof(struct opal_prd_msg_header) &&
+			msg->hdr.type == OPAL_PRD_MSG_TYPE_FINI)
+		return prd_msg_handle_fini();
+
+	if (msg->hdr.size != sizeof(*msg))
+		return OPAL_PARAMETER;
+
+	switch (msg->hdr.type) {
 	case OPAL_PRD_MSG_TYPE_INIT:
 		rc = prd_msg_handle_init(msg);
 		break;
-	case OPAL_PRD_MSG_TYPE_FINI:
-		rc = prd_msg_handle_fini();
-		break;
 	case OPAL_PRD_MSG_TYPE_ATTN_ACK:
 		rc = prd_msg_handle_attn_ack(msg);
 		break;
diff --git a/include/opal-api.h b/include/opal-api.h
index 29421c1..d58c8bf 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -848,16 +848,21 @@ typedef struct oppanel_line {
 
 enum opal_prd_msg_type {
 	OPAL_PRD_MSG_TYPE_INIT = 0,	/* HBRT --> OPAL */
-	OPAL_PRD_MSG_TYPE_FINI,		/* HBRT --> OPAL */
+	OPAL_PRD_MSG_TYPE_FINI,		/* HBRT/kernel --> OPAL */
 	OPAL_PRD_MSG_TYPE_ATTN,		/* HBRT <-- OPAL */
 	OPAL_PRD_MSG_TYPE_ATTN_ACK,	/* HBRT --> OPAL */
 	OPAL_PRD_MSG_TYPE_OCC_ERROR,	/* HBRT <-- OPAL */
 	OPAL_PRD_MSG_TYPE_OCC_RESET,	/* HBRT <-- OPAL */
 };
 
-struct opal_prd_msg {
+struct opal_prd_msg_header {
 	uint8_t		type;
-	uint8_t		pad[3];
+	uint8_t		pad[1];
+	__be16		size;
+};
+
+struct opal_prd_msg {
+	struct opal_prd_msg_header hdr;
 	__be32		token;
 	union {
 		struct {


More information about the Skiboot mailing list