Home | History | Annotate | Line # | Download | only in efiboot
      1  1.10  riastrad /*	$NetBSD: efimemory.c,v 1.10 2023/05/14 09:07:54 riastradh 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.9      manu int
    197   1.9      manu efi_memory_get_memmap(struct bi_memmap_entry **memmapp, size_t *num)
    198   1.9      manu {
    199   1.9      manu 	EFI_STATUS status;
    200   1.9      manu 	EFI_MEMORY_DESCRIPTOR *mdtop, *md, *next;
    201   1.9      manu 	UINTN i, NoEntries, MapKey, DescriptorSize;
    202   1.9      manu 	UINT32 DescriptorVersion;
    203   1.9      manu 	UINTN cols, rows;
    204   1.9      manu 	struct bi_memmap_entry *memmap;
    205   1.9      manu 
    206   1.9      manu 	status = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut,
    207   1.9      manu 	    ST->ConOut->Mode->Mode, &cols, &rows);
    208   1.9      manu 	if (EFI_ERROR(status) || rows <= 2)
    209   1.9      manu 		return -1;
    210   1.9      manu 
    211   1.9      manu 	mdtop = efi_memory_get_map(&NoEntries, &MapKey, &DescriptorSize,
    212   1.9      manu 	    &DescriptorVersion, true);
    213   1.9      manu 	efi_memory_compact_map(mdtop, &NoEntries, DescriptorSize);
    214   1.9      manu 
    215   1.9      manu 	memmap = alloc(sizeof(*memmap) * NoEntries);
    216   1.9      manu 
    217   1.9      manu 	for (i = 0, md = mdtop; i < NoEntries; i++, md = next) {
    218   1.9      manu 		memmap[i].addr = md->PhysicalStart;
    219   1.9      manu 		memmap[i].size = md->NumberOfPages * EFI_PAGE_SIZE;
    220   1.9      manu 		memmap[i].type = getmemtype(md);
    221   1.9      manu 
    222   1.9      manu 		next = NextMemoryDescriptor(md, DescriptorSize);
    223   1.9      manu 	}
    224  1.10  riastrad 
    225   1.9      manu 	*memmapp = memmap;
    226   1.9      manu 	*num = NoEntries;
    227   1.9      manu 	return 0;
    228   1.9      manu }
    229   1.9      manu 
    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