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
12void
13build_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
78void
79build_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
104const char*
105memory_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