git: c5e433b99ed3 - main - stand: Avoid unaligned access in smbios code
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 01 May 2023 21:28:51 UTC
The branch main has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=c5e433b99ed3ddef0eb4fa937f38c34d4a3c4ae0 commit c5e433b99ed3ddef0eb4fa937f38c34d4a3c4ae0 Author: Warner Losh <imp@FreeBSD.org> AuthorDate: 2023-05-01 21:12:34 +0000 Commit: Warner Losh <imp@FreeBSD.org> CommitDate: 2023-05-01 21:12:34 +0000 stand: Avoid unaligned access in smbios code This code was written on x86 where unaligned accesses were easy. LinuxBoot running on aarch64 uses mmap of /dev/mem to read the smbios table. Linux's mapping of this memory doesn't allow the normal unaligned fixup, so we get a bus error instead. We can't use the more natural le16dec and friends because they optimize into a single, unaligned memory load. We don't see this issue on aarch64 UEFI because memory is mapped such that unaligned accesses are fixed up. Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D39793 --- stand/libsa/smbios.c | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/stand/libsa/smbios.c b/stand/libsa/smbios.c index 657e1635e6e1..a88d3ac4ab69 100644 --- a/stand/libsa/smbios.c +++ b/stand/libsa/smbios.c @@ -96,10 +96,47 @@ __FBSDID("$FreeBSD$"); #define SMBIOS3_SIG "_SM3_" #define SMBIOS_DMI_SIG "_DMI_" -#define SMBIOS_GET8(base, off) (*(uint8_t *)((base) + (off))) -#define SMBIOS_GET16(base, off) (*(uint16_t *)((base) + (off))) -#define SMBIOS_GET32(base, off) (*(uint32_t *)((base) + (off))) -#define SMBIOS_GET64(base, off) (*(uint64_t *)((base) + (off))) +/* + * 5.1 General + *... + * NOTE The Entry Point Structure and all SMBIOS structures assume a + * little-endian ordering convention... + * ... + * + * We use memcpy to avoid unaligned access to memory. To normal memory, this is + * fine, but the memory we are using might be mmap'd /dev/mem which under Linux + * on aarch64 doesn't allow unaligned access. leXdec and friends can't be used + * because those can optimize to an unaligned load (which often is fine, but not + * for mmap'd /dev/mem which has special memory attributes). + */ +static inline uint8_t SMBIOS_GET8(const caddr_t base, int off) { return (base[off]); } + +static inline uint16_t +SMBIOS_GET16(const caddr_t base, int off) +{ + uint16_t v; + + memcpy(&v, base + off, sizeof(v)); + return (le16toh(v)); +} + +static inline uint32_t +SMBIOS_GET32(const caddr_t base, int off) +{ + uint32_t v; + + memcpy(&v, base + off, sizeof(v)); + return (le32toh(v)); +} + +static inline uint64_t +SMBIOS_GET64(const caddr_t base, int off) +{ + uint64_t v; + + memcpy(&v, base + off, sizeof(v)); + return (le64toh(v)); +} #define SMBIOS_GETLEN(base) SMBIOS_GET8(base, 0x01) #define SMBIOS_GETSTR(base) ((base) + SMBIOS_GETLEN(base)) @@ -195,7 +232,7 @@ smbios_setenv(const char *name, caddr_t addr, const int offset) #define UUID_TYPE uint32_t #define UUID_STEP sizeof(UUID_TYPE) #define UUID_ALL_BITS (UUID_SIZE / UUID_STEP) -#define UUID_GET(base, off) (*(UUID_TYPE *)((base) + (off))) +#define UUID_GET(base, off) SMBIOS_GET32(base, off) static void smbios_setuuid(const char *name, const caddr_t addr, const int ver __unused)