Skip to content

Commit

Permalink
vpd: Sanitize VPD data
Browse files Browse the repository at this point in the history
On OpenPower system, VPD keyword size tells us the maximum size of the data.
But they fill trailing end with space (0x20) instead of NULL. Also spec
doesn't stop user to have space (0x20) within actual data.

This patch discards trailing spaces before populating device tree.

Reported-by: Pridhiviraj Paidipeddi <ppaidipe@linux.vnet.ibm.com>
Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
[stewart: fixup make check]
Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
  • Loading branch information
Vasant Hegde authored and stewartsmith committed Jun 27, 2018
1 parent af1cbe3 commit 77f510d
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 24 deletions.
2 changes: 1 addition & 1 deletion hdata/test/p8-840-spira.dts
Original file line number Diff line number Diff line change
Expand Up @@ -900,7 +900,7 @@
card-type = [80 b5 00];
hw-characteristics = [00];
ccin = "2B08";
description = "CEC OP PANEL ";
description = "CEC OP PANEL";
};

power-supply@3102 {
Expand Down
2 changes: 1 addition & 1 deletion hdata/test/p81-811.spira.dts
Original file line number Diff line number Diff line change
Expand Up @@ -2119,7 +2119,7 @@
card-type = [80 b5 00];
hw-characteristics = [00];
ccin = "2B08";
description = "CEC OP PANEL ";
description = "CEC OP PANEL";
};

power-supply@3100 {
Expand Down
71 changes: 49 additions & 22 deletions hdata/vpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <device.h>
#include "hdata.h"
#include <inttypes.h>
#include <mem_region-malloc.h>

struct card_info {
const char *ccin; /* Customer card identification number */
Expand Down Expand Up @@ -221,6 +222,32 @@ static const struct card_info *card_info_lookup(char *ccin)
return NULL;
}

/* Discard trailing spaces and populate device tree */
static struct dt_property *dt_add_prop_sanitize_val(struct dt_node *node,
const char *name, const char *val, int vlen)
{
char *prop = zalloc(vlen + 1);
int i;
struct dt_property *p = NULL;

if (!prop)
return p;

memcpy(prop, val, vlen);
for (i = vlen - 1; i >= 0; i--) {
if (prop[i] != 0x20) {
prop[i + 1] = '\0';
break;
}
}

if (i >= 0 && !dt_find_property(node, name))
p = dt_add_property_string(node, name, prop);

free(prop);
return p;
}

/*
* For OpenPOWER, we only decipher OPFR records. While OP HDAT have VINI
* records too, populating the fields in there is optional. Also, there
Expand All @@ -235,27 +262,27 @@ static void vpd_opfr_parse(struct dt_node *node,
/* Vendor Name */
kw = vpd_find(fruvpd, fruvpd_sz, "OPFR", "VN", &sz);
if (kw)
dt_add_property_nstr(node, "vendor", kw, sz);
dt_add_prop_sanitize_val(node, "vendor", kw, sz);

/* FRU Description */
kw = vpd_find(fruvpd, fruvpd_sz, "OPFR", "DR", &sz);
if (kw)
dt_add_property_nstr(node, "description", kw, sz);
dt_add_prop_sanitize_val(node, "description", kw, sz);

/* Part number */
kw = vpd_find(fruvpd, fruvpd_sz, "OPFR", "VP", &sz);
if (kw)
dt_add_property_nstr(node, "part-number", kw, sz);
dt_add_prop_sanitize_val(node, "part-number", kw, sz);

/* Serial number */
kw = vpd_find(fruvpd, fruvpd_sz, "OPFR", "VS", &sz);
if (kw)
dt_add_property_nstr(node, "serial-number", kw, sz);
dt_add_prop_sanitize_val(node, "serial-number", kw, sz);

/* Build date in BCD */
kw = vpd_find(fruvpd, fruvpd_sz, "OPFR", "MB", &sz);
if (kw)
dt_add_property_nstr(node, "build-date", kw, sz);
dt_add_prop_sanitize_val(node, "build-date", kw, sz);

return;
}
Expand All @@ -272,12 +299,12 @@ static void vpd_vrml_parse(struct dt_node *node,
/* Part number */
kw = vpd_find(fruvpd, fruvpd_sz, "VRML", "PN", &sz);
if (kw)
dt_add_property_nstr(node, "part-number", kw, sz);
dt_add_prop_sanitize_val(node, "part-number", kw, sz);

/* Serial number */
kw = vpd_find(fruvpd, fruvpd_sz, "VRML", "SN", &sz);
if (kw)
dt_add_property_nstr(node, "serial-number", kw, sz);
dt_add_prop_sanitize_val(node, "serial-number", kw, sz);

return;
}
Expand All @@ -292,47 +319,47 @@ static void vpd_vini_parse(struct dt_node *node,
/* FRU Stocking Part Number */
kw = vpd_find(fruvpd, fruvpd_sz, "VINI", "FN", &sz);
if (kw)
dt_add_property_nstr(node, "fru-number", kw, sz);
dt_add_prop_sanitize_val(node, "fru-number", kw, sz);

/* Serial Number */
kw = vpd_find(fruvpd, fruvpd_sz, "VINI", "SN", &sz);
if (kw)
dt_add_property_nstr(node, "serial-number", kw, sz);
dt_add_prop_sanitize_val(node, "serial-number", kw, sz);

/* Part Number */
kw = vpd_find(fruvpd, fruvpd_sz, "VINI", "PN", &sz);
if (kw)
dt_add_property_nstr(node, "part-number", kw, sz);
dt_add_prop_sanitize_val(node, "part-number", kw, sz);

/* Vendor Name */
kw = vpd_find(fruvpd, fruvpd_sz, "VINI", "VN", &sz);
if (kw)
dt_add_property_nstr(node, "vendor", kw, sz);
dt_add_prop_sanitize_val(node, "vendor", kw, sz);

/* CCIN Extension */
kw = vpd_find(fruvpd, fruvpd_sz, "VINI", "CE", &sz);
if (kw)
dt_add_property_nstr(node, "ccin-extension", kw, sz);
dt_add_prop_sanitize_val(node, "ccin-extension", kw, sz);

/* HW Version info */
kw = vpd_find(fruvpd, fruvpd_sz, "VINI", "HW", &sz);
if (kw)
dt_add_property_nstr(node, "hw-version", kw, sz);
dt_add_prop_sanitize_val(node, "hw-version", kw, sz);

/* Card type info */
kw = vpd_find(fruvpd, fruvpd_sz, "VINI", "CT", &sz);
if (kw)
dt_add_property_nstr(node, "card-type", kw, sz);
dt_add_prop_sanitize_val(node, "card-type", kw, sz);

/* HW characteristics info */
kw = vpd_find(fruvpd, fruvpd_sz, "VINI", "B3", &sz);
if (kw)
dt_add_property_nstr(node, "hw-characteristics", kw, sz);
dt_add_prop_sanitize_val(node, "hw-characteristics", kw, sz);

/* Customer Card Identification Number (CCIN) */
kw = vpd_find(fruvpd, fruvpd_sz, "VINI", "CC", &sz);
if (kw) {
dt_add_property_nstr(node, "ccin", kw, sz);
dt_add_prop_sanitize_val(node, "ccin", kw, sz);

cinfo = card_info_lookup((char *)kw);
if (cinfo) {
Expand All @@ -341,7 +368,7 @@ static void vpd_vini_parse(struct dt_node *node,
} else {
kw = vpd_find(fruvpd, fruvpd_sz, "VINI", "DR", &sz);
if (kw) {
dt_add_property_nstr(node,
dt_add_prop_sanitize_val(node,
"description", kw, sz);
} else {
dt_add_property_string(node, "description", "Unknown");
Expand Down Expand Up @@ -548,13 +575,13 @@ static void sysvpd_parse_opp(const void *sysvpd, unsigned int sysvpd_sz)

v = vpd_find(sysvpd, sysvpd_sz, "OSYS", "MM", &sz);
if (v)
dt_add_property_nstr(dt_root, "model", v, sz);
dt_add_prop_sanitize_val(dt_root, "model", v, sz);
else
dt_add_property_string(dt_root, "model", "Unknown");

v = vpd_find(sysvpd, sysvpd_sz, "OSYS", "SS", &sz);
if (v)
dt_add_property_nstr(dt_root, "system-id", v, sz);
dt_add_prop_sanitize_val(dt_root, "system-id", v, sz);
else
dt_add_property_string(dt_root, "system-id", "Unknown");
}
Expand All @@ -569,19 +596,19 @@ static void sysvpd_parse_legacy(const void *sysvpd, unsigned int sysvpd_sz)

model = vpd_find(sysvpd, sysvpd_sz, "VSYS", "TM", &sz);
if (model)
dt_add_property_nstr(dt_root, "model", model, sz);
dt_add_prop_sanitize_val(dt_root, "model", model, sz);
else
dt_add_property_string(dt_root, "model", "Unknown");

system_id = vpd_find(sysvpd, sysvpd_sz, "VSYS", "SE", &sz);
if (system_id)
dt_add_property_nstr(dt_root, "system-id", system_id, sz);
dt_add_prop_sanitize_val(dt_root, "system-id", system_id, sz);
else
dt_add_property_string(dt_root, "system-id", "Unknown");

brand = vpd_find(sysvpd, sysvpd_sz, "VSYS", "BR", &sz);
if (brand)
dt_add_property_nstr(dt_root, "system-brand", brand, sz);
dt_add_prop_sanitize_val(dt_root, "system-brand", brand, sz);
else
dt_add_property_string(dt_root, "brand", "Unknown");
}
Expand Down

0 comments on commit 77f510d

Please sign in to comment.