Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save nonakap/3e566c16e8d305f315f9184ca26f82a8 to your computer and use it in GitHub Desktop.

Select an option

Save nonakap/3e566c16e8d305f315f9184ca26f82a8 to your computer and use it in GitHub Desktop.
NetBSD/x86 efiboot: Compact BTINFO_EFIMEMMAP before pass it to the kernel.
diff --git a/sys/arch/i386/stand/efiboot/boot.c b/sys/arch/i386/stand/efiboot/boot.c
index 3ae137e961a..d5a6a1f642f 100644
--- a/sys/arch/i386/stand/efiboot/boot.c
+++ b/sys/arch/i386/stand/efiboot/boot.c
@@ -351,7 +351,7 @@ command_help(char *arg)
#if LIBSA_ENABLE_LS_OP
"ls [path]\n"
#endif
- "memmap [{sorted|unsorted}]\n"
+ "memmap [{sorted|unsorted|compact}]\n"
#ifndef SMALL
"menu (reenters boot menu, if defined in boot.cfg)\n"
#endif
@@ -613,18 +613,21 @@ void
command_memmap(char *arg)
{
bool sorted = true;
+ bool compact = false;
if (*arg == '\0' || strcmp(arg, "sorted") == 0)
/* Already sorted is true. */;
else if (strcmp(arg, "unsorted") == 0)
sorted = false;
+ else if (strcmp(arg, "compact") == 0)
+ compact = true;
else {
printf("invalid flag, "
"must be 'sorted' or 'unsorted'.\n");
return;
}
- efi_memory_show_map(sorted);
+ efi_memory_show_map(sorted, compact);
}
void
diff --git a/sys/arch/i386/stand/efiboot/efiboot.c b/sys/arch/i386/stand/efiboot/efiboot.c
index 79bd5611ec8..015f18868a4 100644
--- a/sys/arch/i386/stand/efiboot/efiboot.c
+++ b/sys/arch/i386/stand/efiboot/efiboot.c
@@ -134,6 +134,7 @@ efi_cleanup(void)
}
efi_cleanuped = true;
+ efi_memory_compact_map(desc, &NoEntries, DescriptorSize);
allocsz = sizeof(struct btinfo_efimemmap) - 1
+ NoEntries * DescriptorSize;
bim = alloc(allocsz);
diff --git a/sys/arch/i386/stand/efiboot/efiboot.h b/sys/arch/i386/stand/efiboot/efiboot.h
index d34007d7919..c3b82d7576d 100644
--- a/sys/arch/i386/stand/efiboot/efiboot.h
+++ b/sys/arch/i386/stand/efiboot/efiboot.h
@@ -80,9 +80,11 @@ void efi_disk_show(void);
/* efimemory.c */
void efi_memory_probe(void);
-void efi_memory_show_map(bool);
+void efi_memory_show_map(bool, bool);
EFI_MEMORY_DESCRIPTOR *efi_memory_get_map(UINTN *, UINTN *, UINTN *, UINT32 *,
bool);
+EFI_MEMORY_DESCRIPTOR *efi_memory_compact_map(EFI_MEMORY_DESCRIPTOR *, UINTN *,
+ UINTN);
/* efinet.c */
void efi_net_probe(void);
diff --git a/sys/arch/i386/stand/efiboot/efimemory.c b/sys/arch/i386/stand/efiboot/efimemory.c
index 33767cff92c..ee39cdbc45d 100644
--- a/sys/arch/i386/stand/efiboot/efimemory.c
+++ b/sys/arch/i386/stand/efiboot/efimemory.c
@@ -107,7 +107,7 @@ EFI_MEMORY_DESCRIPTOR *
efi_memory_get_map(UINTN *NoEntries, UINTN *MapKey, UINTN *DescriptorSize,
UINT32 *DescriptorVersion, bool sorted)
{
- EFI_MEMORY_DESCRIPTOR *desc, *md, *next, *target, tmp;
+ EFI_MEMORY_DESCRIPTOR *desc, *md, *next, *target, *tmp;
UINTN i, j;
*NoEntries = 0;
@@ -119,17 +119,87 @@ efi_memory_get_map(UINTN *NoEntries, UINTN *MapKey, UINTN *DescriptorSize,
if (!sorted)
return desc;
+ tmp = alloc(*DescriptorSize);
+ if (tmp == NULL)
+ return desc;
+
for (i = 0, md = desc; i < *NoEntries - 1; i++, md = next) {
target = next = NextMemoryDescriptor(md, *DescriptorSize);
for (j = i + 1; j < *NoEntries; j++) {
if (md->PhysicalStart > target->PhysicalStart) {
- CopyMem(&tmp, md, sizeof(*md));
- CopyMem(md, target, sizeof(*md));
- CopyMem(target, &tmp, sizeof(*md));
+ CopyMem(tmp, md, *DescriptorSize);
+ CopyMem(md, target, *DescriptorSize);
+ CopyMem(target, tmp, *DescriptorSize);
}
target = NextMemoryDescriptor(target, *DescriptorSize);
}
}
+ dealloc(tmp, *DescriptorSize);
+
+ return desc;
+}
+
+EFI_MEMORY_DESCRIPTOR *
+efi_memory_compact_map(EFI_MEMORY_DESCRIPTOR *desc, UINTN *NoEntries,
+ UINTN DescriptorSize)
+{
+ EFI_MEMORY_DESCRIPTOR *md, *next, *target, *tmp;
+ UINTN i, j;
+ UINT32 type;
+ bool first = true;
+
+ for (i = 0, md = target = desc; i < *NoEntries; i++, md = next) {
+ next = NextMemoryDescriptor(md, DescriptorSize);
+
+ switch (md->Type) {
+ case EfiLoaderCode:
+ case EfiLoaderData:
+ case EfiBootServicesCode:
+ case EfiBootServicesData:
+ if (md->Attribute == target->Attribute &&
+ (md->Attribute & EFI_MEMORY_WB) != 0) {
+ type = EfiConventionalMemory;
+ break;
+ }
+ /* FALLTHROUGH */
+ case EfiConventionalMemory:
+ case EfiACPIReclaimMemory:
+ case EfiACPIMemoryNVS:
+ case EfiPersistentMemory:
+ case EfiReservedMemoryType:
+ case EfiRuntimeServicesCode:
+ case EfiRuntimeServicesData:
+ case EfiUnusableMemory:
+ case EfiMemoryMappedIO:
+ case EfiMemoryMappedIOPortSpace:
+ case EfiPalCode:
+ default:
+ type = md->Type;
+ break;
+ }
+
+ if (!first &&
+ type == target->Type &&
+ md->PhysicalStart == target->PhysicalStart + target->NumberOfPages * EFI_PAGE_SIZE) {
+ /* continuous region */
+ target->NumberOfPages += md->NumberOfPages;
+
+ tmp = md;
+ for (j = i + 1; j < *NoEntries; j++) {
+ CopyMem(tmp, next, DescriptorSize);
+ tmp = next;
+ next = NextMemoryDescriptor(next,
+ DescriptorSize);
+ }
+ (*NoEntries)--;
+
+ next = md;
+ } else {
+ first = false;
+ target->Type = type;
+ }
+ }
+
return desc;
}
@@ -273,7 +343,7 @@ efi_memory_probe(void)
}
void
-efi_memory_show_map(bool sorted)
+efi_memory_show_map(bool sorted, bool compact)
{
EFI_STATUS status;
EFI_MEMORY_DESCRIPTOR *mdtop, *md, *next;
@@ -292,6 +362,8 @@ efi_memory_show_map(bool sorted)
mdtop = efi_memory_get_map(&NoEntries, &MapKey, &DescriptorSize,
&DescriptorVersion, sorted);
+ if (compact)
+ efi_memory_compact_map(mdtop, &NoEntries, DescriptorSize);
for (i = 0, md = mdtop; i < NoEntries; i++, md = next) {
next = NextMemoryDescriptor(md, DescriptorSize);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment