efi.c 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /*
  2. * Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 as
  6. * published by the Free Software Foundation.
  7. */
  8. #include <linux/efi.h>
  9. #include <asm/efi.h>
  10. #include <asm/mach/map.h>
  11. #include <asm/mmu_context.h>
  12. static int __init set_permissions(pte_t *ptep, pgtable_t token,
  13. unsigned long addr, void *data)
  14. {
  15. efi_memory_desc_t *md = data;
  16. pte_t pte = *ptep;
  17. if (md->attribute & EFI_MEMORY_RO)
  18. pte = set_pte_bit(pte, __pgprot(L_PTE_RDONLY));
  19. if (md->attribute & EFI_MEMORY_XP)
  20. pte = set_pte_bit(pte, __pgprot(L_PTE_XN));
  21. set_pte_ext(ptep, pte, PTE_EXT_NG);
  22. return 0;
  23. }
  24. int __init efi_set_mapping_permissions(struct mm_struct *mm,
  25. efi_memory_desc_t *md)
  26. {
  27. unsigned long base, size;
  28. base = md->virt_addr;
  29. size = md->num_pages << EFI_PAGE_SHIFT;
  30. /*
  31. * We can only use apply_to_page_range() if we can guarantee that the
  32. * entire region was mapped using pages. This should be the case if the
  33. * region does not cover any naturally aligned SECTION_SIZE sized
  34. * blocks.
  35. */
  36. if (round_down(base + size, SECTION_SIZE) <
  37. round_up(base, SECTION_SIZE) + SECTION_SIZE)
  38. return apply_to_page_range(mm, base, size, set_permissions, md);
  39. return 0;
  40. }
  41. int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
  42. {
  43. struct map_desc desc = {
  44. .virtual = md->virt_addr,
  45. .pfn = __phys_to_pfn(md->phys_addr),
  46. .length = md->num_pages * EFI_PAGE_SIZE,
  47. };
  48. /*
  49. * Order is important here: memory regions may have all of the
  50. * bits below set (and usually do), so we check them in order of
  51. * preference.
  52. */
  53. if (md->attribute & EFI_MEMORY_WB)
  54. desc.type = MT_MEMORY_RWX;
  55. else if (md->attribute & EFI_MEMORY_WT)
  56. desc.type = MT_MEMORY_RWX_NONCACHED;
  57. else if (md->attribute & EFI_MEMORY_WC)
  58. desc.type = MT_DEVICE_WC;
  59. else
  60. desc.type = MT_DEVICE;
  61. create_mapping_late(mm, &desc, true);
  62. /*
  63. * If stricter permissions were specified, apply them now.
  64. */
  65. if (md->attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP))
  66. return efi_set_mapping_permissions(mm, md);
  67. return 0;
  68. }