[PATCH 1/2] powerpc/pseries: fix endian bugs in mobility RTAS calls
Cyril Bur
cyril.bur at au1.ibm.com
Tue Sep 16 10:25:27 EST 2014
These calls use a buffer shared memory buffer to comunicate device tree
updates.
PAPR specifies that RTAS buffers are to be written in big endian.
Signed-off-by: Cyril Bur <cyril.bur at au1.ibm.com>
---
arch/powerpc/platforms/pseries/mobility.c | 50 ++++++++++++++++---------------
1 file changed, 26 insertions(+), 24 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c
index e7cb6d4..09bef23 100644
--- a/arch/powerpc/platforms/pseries/mobility.c
+++ b/arch/powerpc/platforms/pseries/mobility.c
@@ -40,7 +40,7 @@ struct update_props_workarea {
#define MIGRATION_SCOPE (1)
-static int mobility_rtas_call(int token, char *buf, s32 scope)
+static int mobility_rtas_call(int token, __be32 *buf, s32 scope)
{
int rc;
@@ -129,14 +129,14 @@ static int update_dt_property(struct device_node *dn, struct property **prop,
static int update_dt_node(u32 phandle, s32 scope)
{
- struct update_props_workarea *upwa;
+ struct update_props_workarea upwa;
struct device_node *dn;
struct property *prop = NULL;
int i, rc, rtas_rc;
- char *prop_data;
- char *rtas_buf;
int update_properties_token;
+ char *prop_data;
u32 vd;
+ __be32 *rtas_buf;
update_properties_token = rtas_token("ibm,update-properties");
if (update_properties_token == RTAS_UNKNOWN_SERVICE)
@@ -152,16 +152,17 @@ static int update_dt_node(u32 phandle, s32 scope)
return -ENOENT;
}
- upwa = (struct update_props_workarea *)&rtas_buf[0];
- upwa->phandle = phandle;
-
+ *rtas_buf = cpu_to_be32(phandle);
do {
rtas_rc = mobility_rtas_call(update_properties_token, rtas_buf,
scope);
if (rtas_rc < 0)
break;
-
- prop_data = rtas_buf + sizeof(*upwa);
+ upwa.phandle = be32_to_cpu(*rtas_buf);
+ upwa.state = be32_to_cpu(*(rtas_buf + 1));
+ upwa.reserved = be64_to_cpu(*((__be64 *)(rtas_buf + 2)));
+ upwa.nprops = be32_to_cpu(*(rtas_buf + 4));
+ prop_data = ((char *)rtas_buf) + sizeof(upwa);
/* On the first call to ibm,update-properties for a node the
* the first property value descriptor contains an empty
@@ -169,18 +170,18 @@ static int update_dt_node(u32 phandle, s32 scope)
* and the property value is the node path being updated.
*/
if (*prop_data == 0) {
- prop_data++;
- vd = *(u32 *)prop_data;
+ prop_data += sizeof(u32);
+ vd = be32_to_cpu(*(__be32 *)prop_data);
prop_data += vd + sizeof(vd);
- upwa->nprops--;
+ upwa.nprops--;
}
- for (i = 0; i < upwa->nprops; i++) {
+ for (i = 0; i < upwa.nprops; i++) {
char *prop_name;
prop_name = prop_data;
prop_data += strlen(prop_name) + 1;
- vd = *(u32 *)prop_data;
+ vd = be32_to_cpu(*(__be32 *)prop_data);
prop_data += sizeof(vd);
switch (vd) {
@@ -236,10 +237,11 @@ static int add_dt_node(u32 parent_phandle, u32 drc_index)
int pseries_devicetree_update(s32 scope)
{
- char *rtas_buf;
- u32 *data;
+ __be32 *rtas_buf;
int update_nodes_token;
int rc;
+ __be32 *data;
+ u32 node;
update_nodes_token = rtas_token("ibm,update-nodes");
if (update_nodes_token == RTAS_UNKNOWN_SERVICE)
@@ -253,17 +255,16 @@ int pseries_devicetree_update(s32 scope)
rc = mobility_rtas_call(update_nodes_token, rtas_buf, scope);
if (rc && rc != 1)
break;
+ data = rtas_buf + 4;
+ node = be32_to_cpu(*data++);
- data = (u32 *)rtas_buf + 4;
- while (*data & NODE_ACTION_MASK) {
+ while (node & NODE_ACTION_MASK) {
int i;
- u32 action = *data & NODE_ACTION_MASK;
- int node_count = *data & NODE_COUNT_MASK;
-
- data++;
+ u32 action = node & NODE_ACTION_MASK;
+ int node_count = node & NODE_COUNT_MASK;
for (i = 0; i < node_count; i++) {
- u32 phandle = *data++;
+ u32 phandle = be32_to_cpu(*data++);
u32 drc_index;
switch (action) {
@@ -274,11 +275,12 @@ int pseries_devicetree_update(s32 scope)
update_dt_node(phandle, scope);
break;
case ADD_DT_NODE:
- drc_index = *data++;
+ drc_index = be32_to_cpu(*data++);
add_dt_node(phandle, drc_index);
break;
}
}
+ node = be32_to_cpu(*data++);
}
} while (rc == 1);
--
1.9.1
More information about the Linuxppc-dev
mailing list