Last active
July 29, 2019 08:56
-
-
Save nonakap/3e566c16e8d305f315f9184ca26f82a8 to your computer and use it in GitHub Desktop.
NetBSD/x86 efiboot: Compact BTINFO_EFIMEMMAP before pass it to the kernel.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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