Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org>
0004  */
0005 
0006 #include <linux/efi.h>
0007 #include <asm/efi.h>
0008 #include <asm/mach/map.h>
0009 #include <asm/mmu_context.h>
0010 
0011 static int __init set_permissions(pte_t *ptep, unsigned long addr, void *data)
0012 {
0013     efi_memory_desc_t *md = data;
0014     pte_t pte = *ptep;
0015 
0016     if (md->attribute & EFI_MEMORY_RO)
0017         pte = set_pte_bit(pte, __pgprot(L_PTE_RDONLY));
0018     if (md->attribute & EFI_MEMORY_XP)
0019         pte = set_pte_bit(pte, __pgprot(L_PTE_XN));
0020     set_pte_ext(ptep, pte, PTE_EXT_NG);
0021     return 0;
0022 }
0023 
0024 int __init efi_set_mapping_permissions(struct mm_struct *mm,
0025                        efi_memory_desc_t *md)
0026 {
0027     unsigned long base, size;
0028 
0029     base = md->virt_addr;
0030     size = md->num_pages << EFI_PAGE_SHIFT;
0031 
0032     /*
0033      * We can only use apply_to_page_range() if we can guarantee that the
0034      * entire region was mapped using pages. This should be the case if the
0035      * region does not cover any naturally aligned SECTION_SIZE sized
0036      * blocks.
0037      */
0038     if (round_down(base + size, SECTION_SIZE) <
0039         round_up(base, SECTION_SIZE) + SECTION_SIZE)
0040         return apply_to_page_range(mm, base, size, set_permissions, md);
0041 
0042     return 0;
0043 }
0044 
0045 int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
0046 {
0047     struct map_desc desc = {
0048         .virtual    = md->virt_addr,
0049         .pfn        = __phys_to_pfn(md->phys_addr),
0050         .length     = md->num_pages * EFI_PAGE_SIZE,
0051     };
0052 
0053     /*
0054      * Order is important here: memory regions may have all of the
0055      * bits below set (and usually do), so we check them in order of
0056      * preference.
0057      */
0058     if (md->attribute & EFI_MEMORY_WB)
0059         desc.type = MT_MEMORY_RWX;
0060     else if (md->attribute & EFI_MEMORY_WT)
0061         desc.type = MT_MEMORY_RWX_NONCACHED;
0062     else if (md->attribute & EFI_MEMORY_WC)
0063         desc.type = MT_DEVICE_WC;
0064     else
0065         desc.type = MT_DEVICE;
0066 
0067     create_mapping_late(mm, &desc, true);
0068 
0069     /*
0070      * If stricter permissions were specified, apply them now.
0071      */
0072     if (md->attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP))
0073         return efi_set_mapping_permissions(mm, md);
0074     return 0;
0075 }