Home | History | Annotate | Line # | Download | only in efiboot
efimemory.c revision 1.8.2.1
      1  1.8.2.1  martin /*	$NetBSD: efimemory.c,v 1.8.2.1 2019/09/17 19:32:00 martin Exp $	*/
      2      1.1  nonaka 
      3      1.1  nonaka /*-
      4      1.1  nonaka  * Copyright (c) 2016 Kimihiro Nonaka <nonaka (at) netbsd.org>
      5      1.1  nonaka  * All rights reserved.
      6      1.1  nonaka  *
      7      1.1  nonaka  * Redistribution and use in source and binary forms, with or without
      8      1.1  nonaka  * modification, are permitted provided that the following conditions
      9      1.1  nonaka  * are met:
     10      1.1  nonaka  * 1. Redistributions of source code must retain the above copyright
     11      1.1  nonaka  *    notice, this list of conditions and the following disclaimer.
     12      1.1  nonaka  * 2. Redistributions in binary form must reproduce the above copyright
     13      1.1  nonaka  *    notice, this list of conditions and the following disclaimer in the
     14      1.1  nonaka  *    documentation and/or other materials provided with the distribution.
     15      1.1  nonaka  *
     16      1.1  nonaka  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     17      1.1  nonaka  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18      1.1  nonaka  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19      1.1  nonaka  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     20      1.1  nonaka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21      1.1  nonaka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22      1.1  nonaka  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23      1.1  nonaka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24      1.1  nonaka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25      1.1  nonaka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26      1.1  nonaka  * SUCH DAMAGE.
     27      1.1  nonaka  */
     28      1.1  nonaka 
     29      1.1  nonaka #include "efiboot.h"
     30      1.1  nonaka 
     31      1.1  nonaka #include <bootinfo.h>
     32      1.1  nonaka 
     33      1.8  nonaka static const char *efi_memory_type[] = {
     34      1.8  nonaka 	[EfiReservedMemoryType]		= "Reserved Memory Type",
     35      1.8  nonaka 	[EfiLoaderCode]			= "Loader Code",
     36      1.8  nonaka 	[EfiLoaderData]			= "Loader Data",
     37      1.8  nonaka 	[EfiBootServicesCode]		= "Boot Services Code",
     38      1.8  nonaka 	[EfiBootServicesData]		= "Boot Services Data",
     39      1.8  nonaka 	[EfiRuntimeServicesCode]	= "Runtime Services Code",
     40      1.8  nonaka 	[EfiRuntimeServicesData]	= "Runtime Services Data",
     41      1.8  nonaka 	[EfiConventionalMemory]		= "Conventional Memory",
     42      1.8  nonaka 	[EfiUnusableMemory]		= "Unusable Memory",
     43      1.8  nonaka 	[EfiACPIReclaimMemory]		= "ACPI Reclaim Memory",
     44      1.8  nonaka 	[EfiACPIMemoryNVS]		= "ACPI Memory NVS",
     45      1.8  nonaka 	[EfiMemoryMappedIO]		= "MMIO",
     46      1.8  nonaka 	[EfiMemoryMappedIOPortSpace]	= "MMIO (Port Space)",
     47      1.8  nonaka 	[EfiPalCode]			= "Pal Code",
     48      1.8  nonaka 	[EfiPersistentMemory]		= "Persistent Memory",
     49      1.1  nonaka };
     50      1.1  nonaka 
     51      1.6  nonaka #ifndef KERN_LOADSPACE_SIZE
     52      1.6  nonaka #define KERN_LOADSPACE_SIZE	(128 * 1024 * 1024)	/* 128MiB */
     53      1.6  nonaka #endif
     54      1.6  nonaka 
     55      1.1  nonaka static int
     56      1.1  nonaka getmemtype(EFI_MEMORY_DESCRIPTOR *md)
     57      1.1  nonaka {
     58      1.1  nonaka 
     59      1.1  nonaka 	switch (md->Type) {
     60      1.1  nonaka 	case EfiLoaderCode:
     61      1.1  nonaka 	case EfiLoaderData:
     62      1.1  nonaka 	case EfiBootServicesCode:
     63      1.1  nonaka 	case EfiBootServicesData:
     64      1.1  nonaka 	case EfiConventionalMemory:
     65      1.1  nonaka 		return (md->Attribute & EFI_MEMORY_WB) ?
     66      1.1  nonaka 		    BIM_Memory : BIM_Reserved;
     67      1.1  nonaka 
     68      1.1  nonaka 	case EfiACPIReclaimMemory:
     69      1.1  nonaka 		return BIM_ACPI;
     70      1.1  nonaka 
     71      1.1  nonaka 	case EfiACPIMemoryNVS:
     72      1.1  nonaka 		return BIM_NVS;
     73      1.1  nonaka 
     74      1.4  nonaka 	case EfiPersistentMemory:
     75      1.4  nonaka 		return BIM_PMEM;
     76      1.4  nonaka 
     77      1.1  nonaka 	case EfiReservedMemoryType:
     78      1.1  nonaka 	case EfiRuntimeServicesCode:
     79      1.1  nonaka 	case EfiRuntimeServicesData:
     80      1.1  nonaka 	case EfiUnusableMemory:
     81      1.1  nonaka 	case EfiMemoryMappedIO:
     82      1.1  nonaka 	case EfiMemoryMappedIOPortSpace:
     83      1.1  nonaka 	case EfiPalCode:
     84      1.1  nonaka 	case EfiMaxMemoryType:
     85      1.4  nonaka 	default:
     86      1.1  nonaka 		return BIM_Reserved;
     87      1.1  nonaka 	}
     88      1.1  nonaka }
     89      1.1  nonaka 
     90      1.3  nonaka EFI_MEMORY_DESCRIPTOR *
     91      1.3  nonaka efi_memory_get_map(UINTN *NoEntries, UINTN *MapKey, UINTN *DescriptorSize,
     92      1.3  nonaka     UINT32 *DescriptorVersion, bool sorted)
     93      1.1  nonaka {
     94      1.7  nonaka 	EFI_MEMORY_DESCRIPTOR *desc, *md, *next, *target, *tmp;
     95      1.1  nonaka 	UINTN i, j;
     96      1.1  nonaka 
     97      1.1  nonaka 	*NoEntries = 0;
     98      1.1  nonaka 	desc = LibMemoryMap(NoEntries, MapKey, DescriptorSize,
     99      1.1  nonaka 	    DescriptorVersion);
    100      1.1  nonaka 	if (desc == NULL)
    101      1.5  nonaka 		panic("efi_memory_get_map failed");
    102      1.1  nonaka 
    103      1.1  nonaka 	if (!sorted)
    104      1.1  nonaka 		return desc;
    105      1.1  nonaka 
    106      1.7  nonaka 	tmp = alloc(*DescriptorSize);
    107      1.7  nonaka 	if (tmp == NULL)
    108      1.7  nonaka 		return desc;
    109      1.7  nonaka 
    110      1.1  nonaka 	for (i = 0, md = desc; i < *NoEntries - 1; i++, md = next) {
    111      1.1  nonaka 		target = next = NextMemoryDescriptor(md, *DescriptorSize);
    112      1.1  nonaka 		for (j = i + 1; j < *NoEntries; j++) {
    113      1.1  nonaka 			if (md->PhysicalStart > target->PhysicalStart) {
    114      1.7  nonaka 				CopyMem(tmp, md, *DescriptorSize);
    115      1.7  nonaka 				CopyMem(md, target, *DescriptorSize);
    116      1.7  nonaka 				CopyMem(target, tmp, *DescriptorSize);
    117      1.1  nonaka 			}
    118      1.1  nonaka 			target = NextMemoryDescriptor(target, *DescriptorSize);
    119      1.1  nonaka 		}
    120      1.1  nonaka 	}
    121      1.7  nonaka 	dealloc(tmp, *DescriptorSize);
    122      1.7  nonaka 
    123      1.7  nonaka 	return desc;
    124      1.7  nonaka }
    125      1.7  nonaka 
    126      1.7  nonaka EFI_MEMORY_DESCRIPTOR *
    127      1.7  nonaka efi_memory_compact_map(EFI_MEMORY_DESCRIPTOR *desc, UINTN *NoEntries,
    128      1.7  nonaka     UINTN DescriptorSize)
    129      1.7  nonaka {
    130      1.7  nonaka 	EFI_MEMORY_DESCRIPTOR *md, *next, *target, *tmp;
    131      1.7  nonaka 	UINTN i, j;
    132      1.7  nonaka 	UINT32 type;
    133      1.7  nonaka 	bool first = true, do_compact;
    134      1.7  nonaka 
    135      1.7  nonaka 	for (i = 0, md = target = desc; i < *NoEntries; i++, md = next) {
    136      1.7  nonaka 		type = md->Type;
    137      1.7  nonaka 		switch (type) {
    138      1.7  nonaka 		case EfiLoaderCode:
    139      1.7  nonaka 		case EfiLoaderData:
    140      1.7  nonaka 		case EfiBootServicesCode:
    141      1.7  nonaka 		case EfiBootServicesData:
    142      1.7  nonaka 		case EfiConventionalMemory:
    143      1.7  nonaka 			if ((md->Attribute & EFI_MEMORY_WB) != 0)
    144      1.7  nonaka 				type = EfiConventionalMemory;
    145      1.7  nonaka 			if (md->Attribute == target->Attribute) {
    146      1.7  nonaka 				do_compact = true;
    147      1.7  nonaka 				break;
    148      1.7  nonaka 			}
    149      1.7  nonaka 			/* FALLTHROUGH */
    150      1.7  nonaka 		case EfiACPIReclaimMemory:
    151      1.7  nonaka 		case EfiACPIMemoryNVS:
    152      1.7  nonaka 		case EfiPersistentMemory:
    153      1.7  nonaka 		case EfiReservedMemoryType:
    154      1.7  nonaka 		case EfiRuntimeServicesCode:
    155      1.7  nonaka 		case EfiRuntimeServicesData:
    156      1.7  nonaka 		case EfiUnusableMemory:
    157      1.7  nonaka 		case EfiMemoryMappedIO:
    158      1.7  nonaka 		case EfiMemoryMappedIOPortSpace:
    159      1.7  nonaka 		case EfiPalCode:
    160      1.7  nonaka 		default:
    161      1.7  nonaka 			do_compact = false;
    162      1.7  nonaka 			break;
    163      1.7  nonaka 		}
    164      1.7  nonaka 
    165      1.7  nonaka 		if (first) {
    166      1.7  nonaka 			first = false;
    167      1.7  nonaka 		} else if (do_compact &&
    168      1.7  nonaka 		    type == target->Type &&
    169      1.7  nonaka 		    md->Attribute == target->Attribute &&
    170      1.7  nonaka 		    md->PhysicalStart == target->PhysicalStart + target->NumberOfPages * EFI_PAGE_SIZE) {
    171      1.7  nonaka 			/* continuous region */
    172      1.7  nonaka 			target->NumberOfPages += md->NumberOfPages;
    173      1.7  nonaka 
    174      1.7  nonaka 			tmp = md;
    175      1.7  nonaka 			for (j = i + 1; j < *NoEntries; j++) {
    176      1.7  nonaka 				next = NextMemoryDescriptor(md, DescriptorSize);
    177      1.7  nonaka 				CopyMem(md, next, DescriptorSize);
    178      1.7  nonaka 				md = next;
    179      1.7  nonaka 			}
    180      1.7  nonaka 			next = tmp;
    181      1.7  nonaka 
    182      1.7  nonaka 			i--;
    183      1.7  nonaka 			(*NoEntries)--;
    184      1.7  nonaka 			continue;
    185      1.7  nonaka 		} else {
    186      1.7  nonaka 			target = md;
    187      1.7  nonaka 		}
    188      1.7  nonaka 
    189      1.7  nonaka 		target->Type = type;
    190      1.7  nonaka 		next = NextMemoryDescriptor(md, DescriptorSize);
    191      1.7  nonaka 	}
    192      1.7  nonaka 
    193      1.1  nonaka 	return desc;
    194      1.1  nonaka }
    195      1.1  nonaka 
    196  1.8.2.1  martin int
    197  1.8.2.1  martin efi_memory_get_memmap(struct bi_memmap_entry **memmapp, size_t *num)
    198  1.8.2.1  martin {
    199  1.8.2.1  martin 	EFI_STATUS status;
    200  1.8.2.1  martin 	EFI_MEMORY_DESCRIPTOR *mdtop, *md, *next;
    201  1.8.2.1  martin 	UINTN i, NoEntries, MapKey, DescriptorSize;
    202  1.8.2.1  martin 	UINT32 DescriptorVersion;
    203  1.8.2.1  martin 	UINTN cols, rows;
    204  1.8.2.1  martin 	struct bi_memmap_entry *memmap;
    205  1.8.2.1  martin 
    206  1.8.2.1  martin 	status = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut,
    207  1.8.2.1  martin 	    ST->ConOut->Mode->Mode, &cols, &rows);
    208  1.8.2.1  martin 	if (EFI_ERROR(status) || rows <= 2)
    209  1.8.2.1  martin 		return -1;
    210  1.8.2.1  martin 
    211  1.8.2.1  martin 	mdtop = efi_memory_get_map(&NoEntries, &MapKey, &DescriptorSize,
    212  1.8.2.1  martin 	    &DescriptorVersion, true);
    213  1.8.2.1  martin 	efi_memory_compact_map(mdtop, &NoEntries, DescriptorSize);
    214  1.8.2.1  martin 
    215  1.8.2.1  martin 	memmap = alloc(sizeof(*memmap) * NoEntries);
    216  1.8.2.1  martin 
    217  1.8.2.1  martin 	for (i = 0, md = mdtop; i < NoEntries; i++, md = next) {
    218  1.8.2.1  martin 		memmap[i].addr = md->PhysicalStart;
    219  1.8.2.1  martin 		memmap[i].size = md->NumberOfPages * EFI_PAGE_SIZE;
    220  1.8.2.1  martin 		memmap[i].type = getmemtype(md);
    221  1.8.2.1  martin 
    222  1.8.2.1  martin 		next = NextMemoryDescriptor(md, DescriptorSize);
    223  1.8.2.1  martin 	}
    224  1.8.2.1  martin 
    225  1.8.2.1  martin 	*memmapp = memmap;
    226  1.8.2.1  martin 	*num = NoEntries;
    227  1.8.2.1  martin 	return 0;
    228  1.8.2.1  martin }
    229  1.8.2.1  martin 
    230      1.1  nonaka /*
    231      1.1  nonaka  * get memory size below 1MB
    232      1.1  nonaka  */
    233      1.1  nonaka int
    234      1.1  nonaka getbasemem(void)
    235      1.1  nonaka {
    236      1.1  nonaka 	EFI_MEMORY_DESCRIPTOR *mdtop, *md, *next;
    237      1.1  nonaka 	UINTN i, NoEntries, MapKey, DescriptorSize, MappingSize;
    238      1.1  nonaka 	UINT32 DescriptorVersion;
    239      1.1  nonaka 	EFI_PHYSICAL_ADDRESS basemem = 0, epa;
    240      1.1  nonaka 
    241      1.3  nonaka 	mdtop = efi_memory_get_map(&NoEntries, &MapKey, &DescriptorSize,
    242      1.1  nonaka 	    &DescriptorVersion, true);
    243      1.1  nonaka 
    244      1.1  nonaka 	for (i = 0, md = mdtop; i < NoEntries; i++, md = next) {
    245      1.1  nonaka 		next = NextMemoryDescriptor(md, DescriptorSize);
    246      1.1  nonaka 		if (getmemtype(md) != BIM_Memory)
    247      1.1  nonaka 			continue;
    248      1.1  nonaka 		if (md->PhysicalStart >= 1 * 1024 * 1024)
    249      1.1  nonaka 			continue;
    250      1.1  nonaka 		if (basemem != md->PhysicalStart)
    251      1.1  nonaka 			continue;
    252      1.1  nonaka 
    253      1.1  nonaka 		MappingSize = md->NumberOfPages * EFI_PAGE_SIZE;
    254      1.1  nonaka 		epa = md->PhysicalStart + MappingSize;
    255      1.1  nonaka 		if (epa == 0 || epa > 1 * 1024 * 1024)
    256      1.1  nonaka 			epa = 1 * 1024 * 1024;
    257      1.1  nonaka 		basemem = epa;
    258      1.1  nonaka 	}
    259      1.1  nonaka 
    260      1.1  nonaka 	FreePool(mdtop);
    261      1.1  nonaka 
    262      1.1  nonaka 	return basemem / 1024;	/* KiB */
    263      1.1  nonaka }
    264      1.1  nonaka 
    265      1.1  nonaka /*
    266      1.1  nonaka  * get memory size above 1MB below 4GB
    267      1.1  nonaka  */
    268      1.1  nonaka int
    269      1.1  nonaka getextmemx(void)
    270      1.1  nonaka {
    271      1.1  nonaka 	EFI_MEMORY_DESCRIPTOR *mdtop, *md, *next;
    272      1.1  nonaka 	UINTN i, NoEntries, MapKey, DescriptorSize, MappingSize;
    273      1.1  nonaka 	UINT32 DescriptorVersion;
    274      1.1  nonaka 	EFI_PHYSICAL_ADDRESS extmem16m = 0;	/* 0-16MB */
    275      1.1  nonaka 	EFI_PHYSICAL_ADDRESS extmem4g = 0;	/* 16MB-4GB */
    276      1.1  nonaka 	EFI_PHYSICAL_ADDRESS pa, epa;
    277      1.1  nonaka 	bool first16m = true, first4g = true;
    278      1.1  nonaka 	int extmem;
    279      1.1  nonaka 
    280      1.3  nonaka 	mdtop = efi_memory_get_map(&NoEntries, &MapKey, &DescriptorSize,
    281      1.1  nonaka 	    &DescriptorVersion, true);
    282      1.1  nonaka 
    283      1.1  nonaka 	for (i = 0, md = mdtop; i < NoEntries; i++, md = next) {
    284      1.1  nonaka 		next = NextMemoryDescriptor(md, DescriptorSize);
    285      1.1  nonaka 		if (getmemtype(md) == BIM_Reserved)
    286      1.1  nonaka 			continue;
    287      1.1  nonaka 		if (md->PhysicalStart >= 4 * 1024 * 1024 * 1024ULL)
    288      1.1  nonaka 			continue;
    289      1.1  nonaka 
    290      1.1  nonaka 		MappingSize = md->NumberOfPages * EFI_PAGE_SIZE;
    291      1.1  nonaka 		epa = md->PhysicalStart + MappingSize;
    292      1.1  nonaka 		if (epa == 0 || epa > 4 * 1024 * 1024 * 1024LL)
    293      1.1  nonaka 			epa = 4 * 1024 * 1024 * 1024LL;
    294      1.1  nonaka 
    295      1.1  nonaka 		if (epa <= 1 * 1024 * 1024)
    296      1.1  nonaka 			continue;
    297      1.1  nonaka 
    298      1.1  nonaka 		pa = md->PhysicalStart;
    299      1.1  nonaka 		if (pa < 16 * 1024 * 1024) {
    300      1.1  nonaka 			if (first16m || extmem16m == pa) {
    301      1.1  nonaka 				first16m = false;
    302      1.1  nonaka 				if (epa >= 16 * 1024 * 1024) {
    303      1.1  nonaka 					extmem16m = 16 * 1024 * 1024;
    304      1.1  nonaka 					pa = 16 * 1024 * 1024;
    305      1.1  nonaka 				} else
    306      1.1  nonaka 					extmem16m = epa;
    307      1.1  nonaka 			}
    308      1.1  nonaka 		}
    309      1.1  nonaka 		if (pa >= 16 * 1024 * 1024) {
    310      1.1  nonaka 			if (first4g || extmem4g == pa) {
    311      1.1  nonaka 				first4g = false;
    312      1.1  nonaka 				extmem4g = epa;
    313      1.1  nonaka 			}
    314      1.1  nonaka 		}
    315      1.1  nonaka 	}
    316      1.1  nonaka 
    317      1.1  nonaka 	FreePool(mdtop);
    318      1.1  nonaka 
    319      1.1  nonaka 	if (extmem16m > 1 * 1024 * 1024)
    320      1.1  nonaka 		extmem16m -= 1 * 1024 * 1024;	/* below 1MB */
    321      1.1  nonaka 
    322      1.1  nonaka 	extmem = extmem16m / 1024;
    323      1.1  nonaka 	if (extmem == 15 * 1024)
    324      1.1  nonaka 		extmem += extmem4g / 1024;
    325      1.1  nonaka 	return extmem;
    326      1.1  nonaka }
    327      1.1  nonaka 
    328      1.1  nonaka void
    329      1.1  nonaka efi_memory_probe(void)
    330      1.1  nonaka {
    331      1.1  nonaka 	EFI_MEMORY_DESCRIPTOR *mdtop, *md, *next;
    332      1.6  nonaka 	EFI_STATUS status;
    333      1.6  nonaka 	EFI_PHYSICAL_ADDRESS bouncebuf;
    334      1.1  nonaka 	UINTN i, n, NoEntries, MapKey, DescriptorSize, MappingSize;
    335      1.1  nonaka 	UINT32 DescriptorVersion;
    336      1.1  nonaka 	int memtype;
    337      1.1  nonaka 
    338      1.6  nonaka 	bouncebuf = EFI_ALLOCATE_MAX_ADDRESS;
    339      1.6  nonaka 	status = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress,
    340      1.6  nonaka 	    EfiLoaderData, EFI_SIZE_TO_PAGES(KERN_LOADSPACE_SIZE), &bouncebuf);
    341      1.6  nonaka 	if (EFI_ERROR(status))
    342      1.6  nonaka 		panic("couldn't allocate kernel space.");
    343      1.6  nonaka 	efi_loadaddr = bouncebuf;
    344      1.6  nonaka 
    345      1.3  nonaka 	mdtop = efi_memory_get_map(&NoEntries, &MapKey, &DescriptorSize,
    346      1.1  nonaka 	    &DescriptorVersion, false);
    347      1.5  nonaka 	printf(" mem[");
    348      1.1  nonaka 	for (i = 0, n = 0, md = mdtop; i < NoEntries; i++, md = next) {
    349      1.1  nonaka 		next = NextMemoryDescriptor(md, DescriptorSize);
    350      1.1  nonaka 
    351      1.1  nonaka 		memtype = getmemtype(md);
    352      1.1  nonaka 		if (memtype != BIM_Memory)
    353      1.1  nonaka 			continue;
    354      1.1  nonaka 
    355      1.1  nonaka 		MappingSize = md->NumberOfPages * EFI_PAGE_SIZE;
    356      1.1  nonaka 		if (MappingSize < 12 * 1024)	/* XXX Why? from OpenBSD */
    357      1.1  nonaka 			continue;
    358      1.1  nonaka 
    359      1.1  nonaka 		if (n++ > 0)
    360      1.5  nonaka 			printf(" ");
    361      1.5  nonaka 		printf("0x%" PRIxMAX "-0x%" PRIxMAX, (uintmax_t)md->PhysicalStart,
    362      1.5  nonaka 		    (uintmax_t)(md->PhysicalStart + MappingSize - 1));
    363      1.1  nonaka 	}
    364      1.5  nonaka 	printf("]\n");
    365      1.1  nonaka 
    366      1.1  nonaka 	FreePool(mdtop);
    367      1.1  nonaka }
    368      1.1  nonaka 
    369      1.1  nonaka void
    370      1.7  nonaka efi_memory_show_map(bool sorted, bool compact)
    371      1.1  nonaka {
    372      1.1  nonaka 	EFI_STATUS status;
    373      1.1  nonaka 	EFI_MEMORY_DESCRIPTOR *mdtop, *md, *next;
    374      1.1  nonaka 	UINTN i, NoEntries, MapKey, DescriptorSize;
    375      1.1  nonaka 	UINT32 DescriptorVersion;
    376      1.8  nonaka 	char efimemstr[32];
    377      1.8  nonaka 	UINTN cols, rows, row;
    378      1.1  nonaka 
    379      1.1  nonaka 	status = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut,
    380      1.1  nonaka 	    ST->ConOut->Mode->Mode, &cols, &rows);
    381      1.1  nonaka 	if (EFI_ERROR(status) || rows <= 2)
    382      1.1  nonaka 		rows = 0;
    383      1.1  nonaka 	else
    384      1.1  nonaka 		rows -= 2;
    385      1.1  nonaka 
    386      1.3  nonaka 	mdtop = efi_memory_get_map(&NoEntries, &MapKey, &DescriptorSize,
    387      1.1  nonaka 	    &DescriptorVersion, sorted);
    388      1.7  nonaka 	if (compact)
    389      1.7  nonaka 		efi_memory_compact_map(mdtop, &NoEntries, DescriptorSize);
    390      1.1  nonaka 
    391      1.8  nonaka 	printf("%-22s  %-16s  %-16s  %-16s\n", "Type", "Start", "End", "Attributes");
    392      1.8  nonaka 	printf("----------------------  ----------------  ----------------  ----------------\n");
    393      1.8  nonaka 	row = 2;
    394      1.8  nonaka 
    395      1.1  nonaka 	for (i = 0, md = mdtop; i < NoEntries; i++, md = next) {
    396      1.1  nonaka 		next = NextMemoryDescriptor(md, DescriptorSize);
    397      1.1  nonaka 
    398      1.8  nonaka 		if (md->Type >= __arraycount(efi_memory_type))
    399      1.1  nonaka 			snprintf(efimemstr, sizeof(efimemstr), "unknown (%d)",
    400      1.1  nonaka 			    md->Type);
    401      1.8  nonaka 		printf("%-22s  %016" PRIxMAX "  %016" PRIxMAX "  %016" PRIxMAX "\n",
    402      1.8  nonaka 		    md->Type >= __arraycount(efi_memory_type) ?
    403      1.8  nonaka 		      efimemstr : efi_memory_type[md->Type],
    404      1.1  nonaka 		    (uintmax_t)md->PhysicalStart,
    405      1.1  nonaka 		    (uintmax_t)md->PhysicalStart +
    406      1.1  nonaka 		      md->NumberOfPages * EFI_PAGE_SIZE - 1,
    407      1.8  nonaka 		    (uintmax_t)md->Attribute);
    408      1.1  nonaka 
    409      1.2     roy 		if (++row >= rows) {
    410      1.1  nonaka 			row = 0;
    411      1.5  nonaka 			printf("Press Any Key to continue :");
    412      1.1  nonaka 			(void) awaitkey(-1, 0);
    413      1.5  nonaka 			printf("\n");
    414      1.1  nonaka 		}
    415      1.1  nonaka 	}
    416      1.1  nonaka 
    417      1.1  nonaka 	FreePool(mdtop);
    418      1.1  nonaka }
    419      1.1  nonaka 
    420      1.1  nonaka void
    421      1.1  nonaka vpbcopy(const void *va, void *pa, size_t n)
    422      1.1  nonaka {
    423      1.1  nonaka 	memmove(pa, va, n);
    424      1.1  nonaka }
    425      1.1  nonaka 
    426      1.1  nonaka void
    427      1.1  nonaka pvbcopy(const void *pa, void *va, size_t n)
    428      1.1  nonaka {
    429      1.1  nonaka 	memmove(va, pa, n);
    430      1.1  nonaka }
    431      1.1  nonaka 
    432      1.1  nonaka void
    433      1.1  nonaka pbzero(void *pa, size_t n)
    434      1.1  nonaka {
    435      1.1  nonaka 	memset(pa, 0, n);
    436      1.1  nonaka }
    437      1.1  nonaka 
    438      1.1  nonaka physaddr_t
    439      1.1  nonaka vtophys(void *va)
    440      1.1  nonaka {
    441      1.1  nonaka 	return (physaddr_t)va;
    442      1.1  nonaka }
    443