Linux Audio

Check our new training course

Loading...
v5.9
  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
 37static void __init efi_fake_range(struct efi_mem_range *efi_range)
 38{
 39	struct efi_memory_map_data data = { 0 };
 40	int new_nr_map = efi.memmap.nr_map;
 41	efi_memory_desc_t *md;
 
 42	void *new_memmap;
 
 
 
 
 43
 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);
 
 
 
 
 
 47
 48	/* allocate memory for new EFI memmap */
 49	if (efi_memmap_alloc(new_nr_map, &data) != 0)
 
 50		return;
 51
 52	/* create new EFI memmap */
 53	new_memmap = early_memremap(data.phys_map, data.size);
 
 54	if (!new_memmap) {
 55		__efi_memmap_free(data.phys_map, data.size, data.flags);
 56		return;
 57	}
 58
 59	efi_memmap_insert(&efi.memmap, new_memmap, efi_range);
 
 60
 61	/* swap into new EFI memmap */
 62	early_memunmap(new_memmap, data.size);
 63
 64	efi_memmap_install(&data);
 65}
 66
 67void __init efi_fake_memmap(void)
 68{
 69	int i;
 70
 71	if (!efi_enabled(EFI_MEMMAP) || !nr_fake_mem)
 72		return;
 73
 74	for (i = 0; i < nr_fake_mem; i++)
 75		efi_fake_range(&efi_fake_mems[i]);
 76
 77	/* print new EFI memmap */
 78	efi_print_memmap();
 79}
 80
 81static int __init setup_fake_mem(char *p)
 82{
 83	u64 start = 0, mem_size = 0, attribute = 0;
 84	int i;
 85
 86	if (!p)
 87		return -EINVAL;
 88
 89	while (*p != '\0') {
 90		mem_size = memparse(p, &p);
 91		if (*p == '@')
 92			start = memparse(p+1, &p);
 93		else
 94			break;
 95
 96		if (*p == ':')
 97			attribute = simple_strtoull(p+1, &p, 0);
 98		else
 99			break;
100
101		if (nr_fake_mem >= EFI_MAX_FAKEMEM)
102			break;
103
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;
107		nr_fake_mem++;
108
109		if (*p == ',')
110			p++;
111	}
112
113	sort(efi_fake_mems, nr_fake_mem, sizeof(struct efi_mem_range),
114	     cmp_fake_mem, NULL);
115
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);
120
121	return *p == '\0' ? 0 : -EINVAL;
122}
123
124early_param("efi_fake_mem", setup_fake_mem);
v5.4
  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);