Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.5-rc7 125 lines 2.9 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * fake_mem.c 4 * 5 * Copyright (C) 2015 FUJITSU LIMITED 6 * Author: Taku Izumi <izumi.taku@jp.fujitsu.com> 7 * 8 * This code introduces new boot option named "efi_fake_mem" 9 * By specifying this parameter, you can add arbitrary attribute to 10 * specific memory range by updating original (firmware provided) EFI 11 * memmap. 12 */ 13 14#include <linux/kernel.h> 15#include <linux/efi.h> 16#include <linux/init.h> 17#include <linux/memblock.h> 18#include <linux/types.h> 19#include <linux/sort.h> 20#include "fake_mem.h" 21 22struct efi_mem_range efi_fake_mems[EFI_MAX_FAKEMEM]; 23int nr_fake_mem; 24 25static int __init cmp_fake_mem(const void *x1, const void *x2) 26{ 27 const struct efi_mem_range *m1 = x1; 28 const struct efi_mem_range *m2 = x2; 29 30 if (m1->range.start < m2->range.start) 31 return -1; 32 if (m1->range.start > m2->range.start) 33 return 1; 34 return 0; 35} 36 37void __init efi_fake_memmap(void) 38{ 39 int new_nr_map = efi.memmap.nr_map; 40 efi_memory_desc_t *md; 41 phys_addr_t new_memmap_phy; 42 void *new_memmap; 43 int i; 44 45 if (!efi_enabled(EFI_MEMMAP) || !nr_fake_mem) 46 return; 47 48 /* count up the number of EFI memory descriptor */ 49 for (i = 0; i < nr_fake_mem; i++) { 50 for_each_efi_memory_desc(md) { 51 struct range *r = &efi_fake_mems[i].range; 52 53 new_nr_map += efi_memmap_split_count(md, r); 54 } 55 } 56 57 /* allocate memory for new EFI memmap */ 58 new_memmap_phy = efi_memmap_alloc(new_nr_map); 59 if (!new_memmap_phy) 60 return; 61 62 /* create new EFI memmap */ 63 new_memmap = early_memremap(new_memmap_phy, 64 efi.memmap.desc_size * new_nr_map); 65 if (!new_memmap) { 66 memblock_free(new_memmap_phy, efi.memmap.desc_size * new_nr_map); 67 return; 68 } 69 70 for (i = 0; i < nr_fake_mem; i++) 71 efi_memmap_insert(&efi.memmap, new_memmap, &efi_fake_mems[i]); 72 73 /* swap into new EFI memmap */ 74 early_memunmap(new_memmap, efi.memmap.desc_size * new_nr_map); 75 76 efi_memmap_install(new_memmap_phy, new_nr_map); 77 78 /* print new EFI memmap */ 79 efi_print_memmap(); 80} 81 82static int __init setup_fake_mem(char *p) 83{ 84 u64 start = 0, mem_size = 0, attribute = 0; 85 int i; 86 87 if (!p) 88 return -EINVAL; 89 90 while (*p != '\0') { 91 mem_size = memparse(p, &p); 92 if (*p == '@') 93 start = memparse(p+1, &p); 94 else 95 break; 96 97 if (*p == ':') 98 attribute = simple_strtoull(p+1, &p, 0); 99 else 100 break; 101 102 if (nr_fake_mem >= EFI_MAX_FAKEMEM) 103 break; 104 105 efi_fake_mems[nr_fake_mem].range.start = start; 106 efi_fake_mems[nr_fake_mem].range.end = start + mem_size - 1; 107 efi_fake_mems[nr_fake_mem].attribute = attribute; 108 nr_fake_mem++; 109 110 if (*p == ',') 111 p++; 112 } 113 114 sort(efi_fake_mems, nr_fake_mem, sizeof(struct efi_mem_range), 115 cmp_fake_mem, NULL); 116 117 for (i = 0; i < nr_fake_mem; i++) 118 pr_info("efi_fake_mem: add attr=0x%016llx to [mem 0x%016llx-0x%016llx]", 119 efi_fake_mems[i].attribute, efi_fake_mems[i].range.start, 120 efi_fake_mems[i].range.end); 121 122 return *p == '\0' ? 0 : -EINVAL; 123} 124 125early_param("efi_fake_mem", setup_fake_mem);