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.4 127 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 <asm/efi.h> 21 22#define EFI_MAX_FAKEMEM CONFIG_EFI_MAX_FAKE_MEM 23 24static struct efi_mem_range fake_mems[EFI_MAX_FAKEMEM]; 25static int nr_fake_mem; 26 27static int __init cmp_fake_mem(const void *x1, const void *x2) 28{ 29 const struct efi_mem_range *m1 = x1; 30 const struct efi_mem_range *m2 = x2; 31 32 if (m1->range.start < m2->range.start) 33 return -1; 34 if (m1->range.start > m2->range.start) 35 return 1; 36 return 0; 37} 38 39void __init efi_fake_memmap(void) 40{ 41 int new_nr_map = efi.memmap.nr_map; 42 efi_memory_desc_t *md; 43 phys_addr_t new_memmap_phy; 44 void *new_memmap; 45 int i; 46 47 if (!nr_fake_mem) 48 return; 49 50 /* count up the number of EFI memory descriptor */ 51 for (i = 0; i < nr_fake_mem; i++) { 52 for_each_efi_memory_desc(md) { 53 struct range *r = &fake_mems[i].range; 54 55 new_nr_map += efi_memmap_split_count(md, r); 56 } 57 } 58 59 /* allocate memory for new EFI memmap */ 60 new_memmap_phy = efi_memmap_alloc(new_nr_map); 61 if (!new_memmap_phy) 62 return; 63 64 /* create new EFI memmap */ 65 new_memmap = early_memremap(new_memmap_phy, 66 efi.memmap.desc_size * new_nr_map); 67 if (!new_memmap) { 68 memblock_free(new_memmap_phy, efi.memmap.desc_size * new_nr_map); 69 return; 70 } 71 72 for (i = 0; i < nr_fake_mem; i++) 73 efi_memmap_insert(&efi.memmap, new_memmap, &fake_mems[i]); 74 75 /* swap into new EFI memmap */ 76 early_memunmap(new_memmap, efi.memmap.desc_size * new_nr_map); 77 78 efi_memmap_install(new_memmap_phy, new_nr_map); 79 80 /* print new EFI memmap */ 81 efi_print_memmap(); 82} 83 84static int __init setup_fake_mem(char *p) 85{ 86 u64 start = 0, mem_size = 0, attribute = 0; 87 int i; 88 89 if (!p) 90 return -EINVAL; 91 92 while (*p != '\0') { 93 mem_size = memparse(p, &p); 94 if (*p == '@') 95 start = memparse(p+1, &p); 96 else 97 break; 98 99 if (*p == ':') 100 attribute = simple_strtoull(p+1, &p, 0); 101 else 102 break; 103 104 if (nr_fake_mem >= EFI_MAX_FAKEMEM) 105 break; 106 107 fake_mems[nr_fake_mem].range.start = start; 108 fake_mems[nr_fake_mem].range.end = start + mem_size - 1; 109 fake_mems[nr_fake_mem].attribute = attribute; 110 nr_fake_mem++; 111 112 if (*p == ',') 113 p++; 114 } 115 116 sort(fake_mems, nr_fake_mem, sizeof(struct efi_mem_range), 117 cmp_fake_mem, NULL); 118 119 for (i = 0; i < nr_fake_mem; i++) 120 pr_info("efi_fake_mem: add attr=0x%016llx to [mem 0x%016llx-0x%016llx]", 121 fake_mems[i].attribute, fake_mems[i].range.start, 122 fake_mems[i].range.end); 123 124 return *p == '\0' ? 0 : -EINVAL; 125} 126 127early_param("efi_fake_mem", setup_fake_mem);