1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 2015 FUJITSU LIMITED
6 * Author: Taku Izumi <izumi.taku@jp.fujitsu.com>
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
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>
22 struct efi_mem_range efi_fake_mems
[EFI_MAX_FAKEMEM
];
25 static int __init
cmp_fake_mem(const void *x1
, const void *x2
)
27 const struct efi_mem_range
*m1
= x1
;
28 const struct efi_mem_range
*m2
= x2
;
30 if (m1
->range
.start
< m2
->range
.start
)
32 if (m1
->range
.start
> m2
->range
.start
)
37 static void __init
efi_fake_range(struct efi_mem_range
*efi_range
)
39 struct efi_memory_map_data data
= { 0 };
40 int new_nr_map
= efi
.memmap
.nr_map
;
41 efi_memory_desc_t
*md
;
44 /* count up the number of EFI memory descriptor */
45 for_each_efi_memory_desc(md
)
46 new_nr_map
+= efi_memmap_split_count(md
, &efi_range
->range
);
48 /* allocate memory for new EFI memmap */
49 if (efi_memmap_alloc(new_nr_map
, &data
) != 0)
52 /* create new EFI memmap */
53 new_memmap
= early_memremap(data
.phys_map
, data
.size
);
55 __efi_memmap_free(data
.phys_map
, data
.size
, data
.flags
);
59 efi_memmap_insert(&efi
.memmap
, new_memmap
, efi_range
);
61 /* swap into new EFI memmap */
62 early_memunmap(new_memmap
, data
.size
);
64 efi_memmap_install(&data
);
67 void __init
efi_fake_memmap(void)
71 if (!efi_enabled(EFI_MEMMAP
) || !nr_fake_mem
)
74 for (i
= 0; i
< nr_fake_mem
; i
++)
75 efi_fake_range(&efi_fake_mems
[i
]);
77 /* print new EFI memmap */
81 static int __init
setup_fake_mem(char *p
)
83 u64 start
= 0, mem_size
= 0, attribute
= 0;
90 mem_size
= memparse(p
, &p
);
92 start
= memparse(p
+1, &p
);
97 attribute
= simple_strtoull(p
+1, &p
, 0);
101 if (nr_fake_mem
>= EFI_MAX_FAKEMEM
)
104 efi_fake_mems
[nr_fake_mem
].range
.start
= start
;
105 efi_fake_mems
[nr_fake_mem
].range
.end
= start
+ mem_size
- 1;
106 efi_fake_mems
[nr_fake_mem
].attribute
= attribute
;
113 sort(efi_fake_mems
, nr_fake_mem
, sizeof(struct efi_mem_range
),
116 for (i
= 0; i
< nr_fake_mem
; i
++)
117 pr_info("efi_fake_mem: add attr=0x%016llx to [mem 0x%016llx-0x%016llx]",
118 efi_fake_mems
[i
].attribute
, efi_fake_mems
[i
].range
.start
,
119 efi_fake_mems
[i
].range
.end
);
121 return *p
== '\0' ? 0 : -EINVAL
;
124 early_param("efi_fake_mem", setup_fake_mem
);