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
build_physical_memory_list(size_t memoryMapSize,efi_memory_descriptor * memoryMap,size_t descriptorSize,uint32_t descriptorVersion,uint64_t physicalMemoryLow,uint64_t physicalMemoryHigh)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
build_physical_allocated_list(size_t memoryMapSize,efi_memory_descriptor * memoryMap,size_t descriptorSize,uint32_t descriptorVersion)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*
memory_region_type_str(int type)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