efi_selftest_unaligned.c 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * efi_selftest_unaligned
  4. *
  5. * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
  6. *
  7. * Test unaligned memory access on ARMv7.
  8. */
  9. #include <efi_selftest.h>
  10. struct aligned_buffer {
  11. char a[8] __aligned(8);
  12. };
  13. /*
  14. * Return an u32 at a give address.
  15. * If the address is not four byte aligned, an unaligned memory access
  16. * occurs.
  17. *
  18. * @addr: address to read
  19. * @return: value at the address
  20. */
  21. static inline u32 deref(u32 *addr)
  22. {
  23. int ret;
  24. asm(
  25. "ldr %[out], [%[in]]\n\t"
  26. : [out] "=r" (ret)
  27. : [in] "r" (addr)
  28. );
  29. return ret;
  30. }
  31. /*
  32. * Execute unit test.
  33. * An unaligned memory access is executed. The result is checked.
  34. *
  35. * @return: EFI_ST_SUCCESS for success
  36. */
  37. static int execute(void)
  38. {
  39. struct aligned_buffer buf = {
  40. {0, 1, 2, 3, 4, 5, 6, 7},
  41. };
  42. void *v = &buf;
  43. u32 r = 0;
  44. /* Read an unaligned address */
  45. r = deref(v + 1);
  46. /* UEFI only supports low endian systems */
  47. if (r != 0x04030201) {
  48. efi_st_error("Unaligned access failed");
  49. return EFI_ST_FAILURE;
  50. }
  51. return EFI_ST_SUCCESS;
  52. }
  53. EFI_UNIT_TEST(unaligned) = {
  54. .name = "unaligned memory access",
  55. .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
  56. .execute = execute,
  57. };