Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2019 Intel Corporation. All rights reserved. */
0003 #include <linux/efi.h>
0004 #include <asm/e820/api.h>
0005 #include "fake_mem.h"
0006 
0007 void __init efi_fake_memmap_early(void)
0008 {
0009     int i;
0010 
0011     /*
0012      * The late efi_fake_mem() call can handle all requests if
0013      * EFI_MEMORY_SP support is disabled.
0014      */
0015     if (!efi_soft_reserve_enabled())
0016         return;
0017 
0018     if (!efi_enabled(EFI_MEMMAP) || !nr_fake_mem)
0019         return;
0020 
0021     /*
0022      * Given that efi_fake_memmap() needs to perform memblock
0023      * allocations it needs to run after e820__memblock_setup().
0024      * However, if efi_fake_mem specifies EFI_MEMORY_SP for a given
0025      * address range that potentially needs to mark the memory as
0026      * reserved prior to e820__memblock_setup(). Update e820
0027      * directly if EFI_MEMORY_SP is specified for an
0028      * EFI_CONVENTIONAL_MEMORY descriptor.
0029      */
0030     for (i = 0; i < nr_fake_mem; i++) {
0031         struct efi_mem_range *mem = &efi_fake_mems[i];
0032         efi_memory_desc_t *md;
0033         u64 m_start, m_end;
0034 
0035         if ((mem->attribute & EFI_MEMORY_SP) == 0)
0036             continue;
0037 
0038         m_start = mem->range.start;
0039         m_end = mem->range.end;
0040         for_each_efi_memory_desc(md) {
0041             u64 start, end, size;
0042 
0043             if (md->type != EFI_CONVENTIONAL_MEMORY)
0044                 continue;
0045 
0046             start = md->phys_addr;
0047             end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
0048 
0049             if (m_start <= end && m_end >= start)
0050                 /* fake range overlaps descriptor */;
0051             else
0052                 continue;
0053 
0054             /*
0055              * Trim the boundary of the e820 update to the
0056              * descriptor in case the fake range overlaps
0057              * !EFI_CONVENTIONAL_MEMORY
0058              */
0059             start = max(start, m_start);
0060             end = min(end, m_end);
0061             size = end - start + 1;
0062 
0063             if (end <= start)
0064                 continue;
0065 
0066             /*
0067              * Ensure each efi_fake_mem instance results in
0068              * a unique e820 resource
0069              */
0070             e820__range_remove(start, size, E820_TYPE_RAM, 1);
0071             e820__range_add(start, size, E820_TYPE_SOFT_RESERVED);
0072             e820__update_table(e820_table);
0073         }
0074     }
0075 }