Commit c8c1a4c5 authored by Matt Fleming's avatar Matt Fleming

efi/fake_mem: Refactor main two code chunks into functions

There is a whole load of generic EFI memory map code inside of the
fake_mem driver which is better suited to being grouped with the rest
of the generic EFI code for manipulating EFI memory maps.

In preparation for that, this patch refactors the core code, so that
it's possible to move entire functions later.

Tested-by: Dave Young <dyoung@redhat.com> [kexec/kdump]
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> [arm]
Acked-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Peter Jones <pjones@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Taku Izumi <izumi.taku@jp.fujitsu.com>
Signed-off-by: default avatarMatt Fleming <matt@codeblueprint.co.uk>
parent dca0f971
...@@ -54,43 +54,151 @@ static int __init cmp_fake_mem(const void *x1, const void *x2) ...@@ -54,43 +54,151 @@ static int __init cmp_fake_mem(const void *x1, const void *x2)
return 0; return 0;
} }
/**
* efi_fake_memmap_split_count - Count number of additional EFI memmap entries
* @md: EFI memory descriptor to split
* @range: Address range (start, end) to split around
*
* Returns the number of additional EFI memmap entries required to
* accomodate @range.
*/
static int efi_fake_memmap_split_count(efi_memory_desc_t *md, struct range *range)
{
u64 m_start, m_end;
u64 start, end;
int count = 0;
start = md->phys_addr;
end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1;
/* modifying range */
m_start = range->start;
m_end = range->end;
if (m_start <= start) {
/* split into 2 parts */
if (start < m_end && m_end < end)
count++;
}
if (start < m_start && m_start < end) {
/* split into 3 parts */
if (m_end < end)
count += 2;
/* split into 2 parts */
if (end <= m_end)
count++;
}
return count;
}
/**
* efi_fake_memmap_insert - Insert a fake memory region in an EFI memmap
* @old_memmap: The existing EFI memory map structure
* @buf: Address of buffer to store new map
* @mem: Fake memory map entry to insert
*
* It is suggested that you call efi_fake_memmap_split_count() first
* to see how large @buf needs to be.
*/
static void efi_fake_memmap_insert(struct efi_memory_map *old_memmap,
void *buf, struct fake_mem *mem)
{
u64 m_start, m_end, m_attr;
efi_memory_desc_t *md;
u64 start, end;
void *old, *new;
/* modifying range */
m_start = mem->range.start;
m_end = mem->range.end;
m_attr = mem->attribute;
for (old = old_memmap->map, new = buf;
old < old_memmap->map_end;
old += old_memmap->desc_size, new += old_memmap->desc_size) {
/* copy original EFI memory descriptor */
memcpy(new, old, old_memmap->desc_size);
md = new;
start = md->phys_addr;
end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
if (m_start <= start && end <= m_end)
md->attribute |= m_attr;
if (m_start <= start &&
(start < m_end && m_end < end)) {
/* first part */
md->attribute |= m_attr;
md->num_pages = (m_end - md->phys_addr + 1) >>
EFI_PAGE_SHIFT;
/* latter part */
new += old_memmap->desc_size;
memcpy(new, old, old_memmap->desc_size);
md = new;
md->phys_addr = m_end + 1;
md->num_pages = (end - md->phys_addr + 1) >>
EFI_PAGE_SHIFT;
}
if ((start < m_start && m_start < end) && m_end < end) {
/* first part */
md->num_pages = (m_start - md->phys_addr) >>
EFI_PAGE_SHIFT;
/* middle part */
new += old_memmap->desc_size;
memcpy(new, old, old_memmap->desc_size);
md = new;
md->attribute |= m_attr;
md->phys_addr = m_start;
md->num_pages = (m_end - m_start + 1) >>
EFI_PAGE_SHIFT;
/* last part */
new += old_memmap->desc_size;
memcpy(new, old, old_memmap->desc_size);
md = new;
md->phys_addr = m_end + 1;
md->num_pages = (end - m_end) >>
EFI_PAGE_SHIFT;
}
if ((start < m_start && m_start < end) &&
(end <= m_end)) {
/* first part */
md->num_pages = (m_start - md->phys_addr) >>
EFI_PAGE_SHIFT;
/* latter part */
new += old_memmap->desc_size;
memcpy(new, old, old_memmap->desc_size);
md = new;
md->phys_addr = m_start;
md->num_pages = (end - md->phys_addr + 1) >>
EFI_PAGE_SHIFT;
md->attribute |= m_attr;
}
}
}
void __init efi_fake_memmap(void) void __init efi_fake_memmap(void)
{ {
u64 start, end, m_start, m_end, m_attr;
struct efi_memory_map_data data; struct efi_memory_map_data data;
int new_nr_map = efi.memmap.nr_map; int new_nr_map = efi.memmap.nr_map;
efi_memory_desc_t *md; efi_memory_desc_t *md;
phys_addr_t new_memmap_phy; phys_addr_t new_memmap_phy;
void *new_memmap; void *new_memmap;
void *old, *new;
int i; int i;
if (!nr_fake_mem) if (!nr_fake_mem)
return; return;
/* count up the number of EFI memory descriptor */ /* count up the number of EFI memory descriptor */
for_each_efi_memory_desc(md) { for (i = 0; i < nr_fake_mem; i++) {
start = md->phys_addr; for_each_efi_memory_desc(md) {
end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1; struct range *r = &fake_mems[i].range;
for (i = 0; i < nr_fake_mem; i++) { new_nr_map += efi_fake_memmap_split_count(md, r);
/* modifying range */
m_start = fake_mems[i].range.start;
m_end = fake_mems[i].range.end;
if (m_start <= start) {
/* split into 2 parts */
if (start < m_end && m_end < end)
new_nr_map++;
}
if (start < m_start && m_start < end) {
/* split into 3 parts */
if (m_end < end)
new_nr_map += 2;
/* split into 2 parts */
if (end <= m_end)
new_nr_map++;
}
} }
} }
...@@ -108,77 +216,8 @@ void __init efi_fake_memmap(void) ...@@ -108,77 +216,8 @@ void __init efi_fake_memmap(void)
return; return;
} }
for (old = efi.memmap.map, new = new_memmap; for (i = 0; i < nr_fake_mem; i++)
old < efi.memmap.map_end; efi_fake_memmap_insert(&efi.memmap, new_memmap, &fake_mems[i]);
old += efi.memmap.desc_size, new += efi.memmap.desc_size) {
/* copy original EFI memory descriptor */
memcpy(new, old, efi.memmap.desc_size);
md = new;
start = md->phys_addr;
end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
for (i = 0; i < nr_fake_mem; i++) {
/* modifying range */
m_start = fake_mems[i].range.start;
m_end = fake_mems[i].range.end;
m_attr = fake_mems[i].attribute;
if (m_start <= start && end <= m_end)
md->attribute |= m_attr;
if (m_start <= start &&
(start < m_end && m_end < end)) {
/* first part */
md->attribute |= m_attr;
md->num_pages = (m_end - md->phys_addr + 1) >>
EFI_PAGE_SHIFT;
/* latter part */
new += efi.memmap.desc_size;
memcpy(new, old, efi.memmap.desc_size);
md = new;
md->phys_addr = m_end + 1;
md->num_pages = (end - md->phys_addr + 1) >>
EFI_PAGE_SHIFT;
}
if ((start < m_start && m_start < end) && m_end < end) {
/* first part */
md->num_pages = (m_start - md->phys_addr) >>
EFI_PAGE_SHIFT;
/* middle part */
new += efi.memmap.desc_size;
memcpy(new, old, efi.memmap.desc_size);
md = new;
md->attribute |= m_attr;
md->phys_addr = m_start;
md->num_pages = (m_end - m_start + 1) >>
EFI_PAGE_SHIFT;
/* last part */
new += efi.memmap.desc_size;
memcpy(new, old, efi.memmap.desc_size);
md = new;
md->phys_addr = m_end + 1;
md->num_pages = (end - m_end) >>
EFI_PAGE_SHIFT;
}
if ((start < m_start && m_start < end) &&
(end <= m_end)) {
/* first part */
md->num_pages = (m_start - md->phys_addr) >>
EFI_PAGE_SHIFT;
/* latter part */
new += efi.memmap.desc_size;
memcpy(new, old, efi.memmap.desc_size);
md = new;
md->phys_addr = m_start;
md->num_pages = (end - md->phys_addr + 1) >>
EFI_PAGE_SHIFT;
md->attribute |= m_attr;
}
}
}
/* swap into new EFI memmap */ /* swap into new EFI memmap */
early_memunmap(new_memmap, efi.memmap.desc_size * new_nr_map); early_memunmap(new_memmap, efi.memmap.desc_size * new_nr_map);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment