cbmem: Add custom aligned memcpy() implementation
On some architectures (like AArch64), /dev/mem mappings outside of the area marked as normal RAM use a memory type that does not support unaligned accesses. The libc memcpy() implementation on these architectures may not know or expect that and make an unaligned access for certain source/dest/length alignments. Add a custom memcpy() implementation that takes these restrictions into account and use it anywhere we copy straight out of /dev/mem memory. Change-Id: I03eece380a14a69d4be3805ed72fba640f6f7d9c Signed-off-by: Julius Werner <jwerner@chromium.org> Reviewed-on: https://review.coreboot.org/18300 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
parent
973104ba1f
commit
127a79e0b6
|
@ -60,6 +60,36 @@ static int mem_fd;
|
||||||
static uint64_t lbtable_address;
|
static uint64_t lbtable_address;
|
||||||
static size_t lbtable_size;
|
static size_t lbtable_size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some architectures map /dev/mem memory in a way that doesn't support
|
||||||
|
* unaligned accesses. Most normal libc memcpy()s aren't safe to use in this
|
||||||
|
* case, so build our own which makes sure to never do unaligned accesses on
|
||||||
|
* *src (*dest is fine since we never map /dev/mem for writing).
|
||||||
|
*/
|
||||||
|
static void *aligned_memcpy(void *dest, const void *src, size_t n)
|
||||||
|
{
|
||||||
|
u8 *d = dest;
|
||||||
|
const volatile u8 *s = src; /* volatile to prevent optimization */
|
||||||
|
|
||||||
|
while ((uintptr_t)s & (sizeof(size_t) - 1)) {
|
||||||
|
if (n-- == 0)
|
||||||
|
return dest;
|
||||||
|
*d++ = *s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (n >= sizeof(size_t)) {
|
||||||
|
*(size_t *)d = *(const volatile size_t *)s;
|
||||||
|
d += sizeof(size_t);
|
||||||
|
s += sizeof(size_t);
|
||||||
|
n -= sizeof(size_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (n-- > 0)
|
||||||
|
*d++ = *s++;
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* calculate ip checksum (16 bit quantities) on a passed in buffer. In case
|
* calculate ip checksum (16 bit quantities) on a passed in buffer. In case
|
||||||
* the buffer length is odd last byte is excluded from the calculation
|
* the buffer length is odd last byte is excluded from the calculation
|
||||||
|
@ -608,7 +638,7 @@ static void dump_console(void)
|
||||||
|
|
||||||
console_p = map_memory_size((unsigned long)console.cbmem_addr,
|
console_p = map_memory_size((unsigned long)console.cbmem_addr,
|
||||||
size + sizeof(size) + sizeof(cursor), 1);
|
size + sizeof(size) + sizeof(cursor), 1);
|
||||||
memcpy(console_c, console_p + 8, size);
|
aligned_memcpy(console_c, console_p + 8, size);
|
||||||
|
|
||||||
printf("%s\n", console_c);
|
printf("%s\n", console_c);
|
||||||
if (size < cursor)
|
if (size < cursor)
|
||||||
|
|
Loading…
Reference in New Issue