1 /* 2 * Copyright 2022 Haiku, Inc. All rights reserved. 3 * Released under the terms of the MIT License. 4 */ 5 6 #include "generic_mmu.h" 7 8 #include <algorithm> 9 #include <boot/stage2.h> 10 11 12 void 13 build_physical_memory_list(size_t memoryMapSize, efi_memory_descriptor* memoryMap, 14 size_t descriptorSize, uint32_t descriptorVersion, 15 uint64_t physicalMemoryLow, uint64_t physicalMemoryHigh) 16 { 17 addr_t addr = (addr_t)memoryMap; 18 19 gKernelArgs.num_physical_memory_ranges = 0; 20 21 // First scan: Add all usable ranges 22 for (size_t i = 0; i < memoryMapSize / descriptorSize; ++i) { 23 efi_memory_descriptor* entry = (efi_memory_descriptor *)(addr + i * descriptorSize); 24 switch (entry->Type) { 25 case EfiLoaderCode: 26 case EfiLoaderData: 27 case EfiBootServicesCode: 28 case EfiBootServicesData: 29 case EfiConventionalMemory: { 30 uint64_t base = entry->PhysicalStart; 31 uint64_t end = entry->PhysicalStart + entry->NumberOfPages * B_PAGE_SIZE; 32 uint64_t originalSize = end - base; 33 base = std::max(base, physicalMemoryLow); 34 end = std::min(end, physicalMemoryHigh); 35 36 gKernelArgs.ignored_physical_memory 37 += originalSize - (max_c(end, base) - base); 38 39 if (base >= end) 40 break; 41 uint64_t size = end - base; 42 43 insert_physical_memory_range(base, size); 44 break; 45 } 46 default: 47 break; 48 } 49 } 50 51 uint64_t initialPhysicalMemory = total_physical_memory(); 52 53 // Second scan: Remove everything reserved that may overlap 54 for (size_t i = 0; i < memoryMapSize / descriptorSize; ++i) { 55 efi_memory_descriptor* entry = (efi_memory_descriptor *)(addr + i * descriptorSize); 56 switch (entry->Type) { 57 case EfiLoaderCode: 58 case EfiLoaderData: 59 case EfiBootServicesCode: 60 case EfiBootServicesData: 61 case EfiConventionalMemory: 62 break; 63 default: 64 uint64_t base = entry->PhysicalStart; 65 uint64_t size = entry->NumberOfPages * B_PAGE_SIZE; 66 remove_physical_memory_range(base, size); 67 } 68 } 69 70 gKernelArgs.ignored_physical_memory 71 += initialPhysicalMemory - total_physical_memory(); 72 73 sort_address_ranges(gKernelArgs.physical_memory_range, 74 gKernelArgs.num_physical_memory_ranges); 75 } 76 77 78 void 79 build_physical_allocated_list(size_t memoryMapSize, efi_memory_descriptor* memoryMap, 80 size_t descriptorSize, uint32_t descriptorVersion) 81 { 82 gKernelArgs.num_physical_allocated_ranges = 0; 83 84 addr_t addr = (addr_t)memoryMap; 85 for (size_t i = 0; i < memoryMapSize / descriptorSize; ++i) { 86 efi_memory_descriptor* entry = (efi_memory_descriptor *)(addr + i * descriptorSize); 87 switch (entry->Type) { 88 case EfiLoaderData: { 89 uint64_t base = entry->PhysicalStart; 90 uint64_t size = entry->NumberOfPages * B_PAGE_SIZE; 91 insert_physical_allocated_range(base, size); 92 break; 93 } 94 default: 95 ; 96 } 97 } 98 99 sort_address_ranges(gKernelArgs.physical_allocated_range, 100 gKernelArgs.num_physical_allocated_ranges); 101 } 102 103 104 const char* 105 memory_region_type_str(int type) 106 { 107 switch (type) { 108 case EfiReservedMemoryType: 109 return "EfiReservedMemoryType"; 110 case EfiLoaderCode: 111 return "EfiLoaderCode"; 112 case EfiLoaderData: 113 return "EfiLoaderData"; 114 case EfiBootServicesCode: 115 return "EfiBootServicesCode"; 116 case EfiBootServicesData: 117 return "EfiBootServicesData"; 118 case EfiRuntimeServicesCode: 119 return "EfiRuntimeServicesCode"; 120 case EfiRuntimeServicesData: 121 return "EfiRuntimeServicesData"; 122 case EfiConventionalMemory: 123 return "EfiConventionalMemory"; 124 case EfiUnusableMemory: 125 return "EfiUnusableMemory"; 126 case EfiACPIReclaimMemory: 127 return "EfiACPIReclaimMemory"; 128 case EfiACPIMemoryNVS: 129 return "EfiACPIMemoryNVS"; 130 case EfiMemoryMappedIO: 131 return "EfiMemoryMappedIO"; 132 case EfiMemoryMappedIOPortSpace: 133 return "EfiMemoryMappedIOPortSpace"; 134 case EfiPalCode: 135 return "EfiPalCode"; 136 case EfiPersistentMemory: 137 return "EfiPersistentMemory"; 138 default: 139 return "unknown"; 140 } 141 } 142