diff options
author | Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 2018-05-15 20:32:02 +0300 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2018-05-17 12:47:21 +0200 |
commit | 63dcc7090137a893322432e156d66be3ce104615 (patch) | |
tree | 600312eeea6325c486b706b846ffa62b0c0e3a7f /drivers/firmware | |
parent | 67b8d5c7081221efa252e111cd52532ec6d4266f (diff) | |
download | linux-63dcc7090137a893322432e156d66be3ce104615.tar.gz linux-63dcc7090137a893322432e156d66be3ce104615.tar.bz2 linux-63dcc7090137a893322432e156d66be3ce104615.zip |
device property: Get rid of union aliasing
Commit 318a19718261 (device property: refactor built-in properties
support) went way too far and brought a union aliasing. Partially
revert it here to get rid of union aliasing.
Note, all Apple properties are considered as u8 arrays. To get a value
of any of them the caller must use device_property_read_u8_array().
What's union aliasing?
~~~~~~~~~~~~~~~~~~~~~~
The C99 standard in section 6.2.5 paragraph 20 defines union type as
"an overlapping nonempty set of member objects". It also states in
section 6.7.2.1 paragraph 14 that "the value of at most one of the
members can be stored in a union object at any time'.
Union aliasing is a type punning mechanism using union members to store
as one type and read back as another.
Why it's not good?
~~~~~~~~~~~~~~~~~~
Section 6.2.6.1 paragraph 6 says that a union object may not be a trap
representation, although its member objects may be.
Meanwhile annex J.1 says that "the value of a union member other than
the last one stored into" is unspecified [removed in C11].
In TC3, a footnote is added which specifies that accessing a member of a
union other than the last one stored causes "the object representation"
to be re-interpreted in the new type and specifically refers to this as
"type punning". This conflicts to some degree with Annex J.1.
While it's working in Linux with GCC, the use of union members to do
type punning is not clear area in the C standard and might lead to
unspecified behaviour.
More information is available in this [1] blog post.
[1]: https://davmac.wordpress.com/2010/02/26/c99-revisited/
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/efi/apple-properties.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/drivers/firmware/efi/apple-properties.c b/drivers/firmware/efi/apple-properties.c index adaa9a3714b9..60a95719ecb8 100644 --- a/drivers/firmware/efi/apple-properties.c +++ b/drivers/firmware/efi/apple-properties.c @@ -13,6 +13,9 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, see <http://www.gnu.org/licenses/>. + * + * Note, all properties are considered as u8 arrays. + * To get a value of any of them the caller must use device_property_read_u8_array(). */ #define pr_fmt(fmt) "apple-properties: " fmt @@ -96,12 +99,13 @@ static void __init unmarshal_key_value_pairs(struct dev_header *dev_header, entry[i].name = key; entry[i].length = val_len - sizeof(val_len); entry[i].is_array = !!entry[i].length; - entry[i].pointer.raw_data = ptr + key_len + sizeof(val_len); + entry[i].type = DEV_PROP_U8; + entry[i].pointer.u8_data = ptr + key_len + sizeof(val_len); if (dump_properties) { dev_info(dev, "property: %s\n", entry[i].name); print_hex_dump(KERN_INFO, pr_fmt(), DUMP_PREFIX_OFFSET, - 16, 1, entry[i].pointer.raw_data, + 16, 1, entry[i].pointer.u8_data, entry[i].length, true); } |