1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
|
/** @file
*
* Copyright (c) 2019, Pete Batard <pete@akeo.ie>
* Copyright (c) 2017-2018, Andrey Warkentin <andrey.warkentin@gmail.com>
* Copyright (c) 2014, Linaro Limited. All rights reserved.
* Copyright (c) 2013-2018, ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*
**/
#include <Library/ArmPlatformLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
#include <Library/RPiMem.h>
#include <IndustryStandard/Bcm2711.h>
#include <IndustryStandard/Bcm2836.h>
UINT64 mSystemMemoryBase;
extern UINT64 mSystemMemoryEnd;
UINT64 mVideoCoreBase;
UINT64 mVideoCoreSize;
UINT32 mBoardRevision;
// The total number of descriptors, including the final "end-of-table" descriptor.
#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 11
STATIC BOOLEAN VirtualMemoryInfoInitialized = FALSE;
STATIC RPI_MEMORY_REGION_INFO VirtualMemoryInfo[MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS];
#define VariablesBase (FixedPcdGet32(PcdNvStorageVariableBase))
/**
Return the Virtual Memory Map of your platform
This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU
on your platform.
@param[out] VirtualMemoryMap Array of ARM_MEMORY_REGION_DESCRIPTOR
describing a Physical-to-Virtual Memory
mapping. This array must be ended by a
zero-filled entry
**/
VOID
ArmPlatformGetVirtualMemoryMap (
IN ARM_MEMORY_REGION_DESCRIPTOR** VirtualMemoryMap
)
{
UINTN Index = 0;
INT64 TotalMemorySize;
INT64 MemorySizeBelow3GB;
INT64 MemorySizeBelow4GB;
ARM_MEMORY_REGION_DESCRIPTOR *VirtualMemoryTable;
// Early output of the info we got from VideoCore can prove valuable.
DEBUG ((DEBUG_INFO, "Board Rev: 0x%lX\n", mBoardRevision));
DEBUG ((DEBUG_INFO, "RAM < 1GB: 0x%ll08X (Size 0x%ll08X)\n", mSystemMemoryBase, mSystemMemoryEnd + 1));
DEBUG ((DEBUG_INFO, "VideoCore: 0x%ll08X (Size 0x%ll08X)\n", mVideoCoreBase, mVideoCoreSize));
ASSERT (mSystemMemoryBase == 0);
ASSERT (VirtualMemoryMap != NULL);
// Compute the total RAM size available on this platform
TotalMemorySize = SIZE_256MB;
TotalMemorySize <<= (mBoardRevision >> 20) & 0x07;
DEBUG ((DEBUG_INFO, "Total RAM: 0x%ll08X\n", TotalMemorySize));
//
// Ensure that what we declare as System Memory doesn't overlap with the
// SoC MMIO registers. This can be achieved through a MIN () with the
// base address since SystemMemoryBase is 0 (we assert if it isn't).
//
ASSERT (BCM2836_SOC_REGISTERS < 4UL * SIZE_1GB);
MemorySizeBelow4GB = MIN(TotalMemorySize, 4UL * SIZE_1GB);
MemorySizeBelow4GB = MIN(MemorySizeBelow4GB, BCM2836_SOC_REGISTERS);
if (BCM2711_SOC_REGISTERS > 0) {
ASSERT (BCM2836_SOC_REGISTERS < 4UL * SIZE_1GB);
MemorySizeBelow4GB = MIN(MemorySizeBelow4GB, BCM2711_SOC_REGISTERS);
}
//
// By default we limit the memory to 3 GB to work around OS support for
// DMA bugs in the SoC, for OSes that don't support _DMA range descriptors.
// On boards with more RAM (4GB, 8GB), the extra memory is added by ConfigDxe
// provided the configuration setting for 3GB limit is off.
//
MemorySizeBelow3GB = MIN(MemorySizeBelow4GB, 3UL * SIZE_1GB);
//
// On Pi 3 we've seen SoC registers may overlap the reported VideoCore range,
// so clamp that down as well.
//
if (mVideoCoreBase + mVideoCoreSize > BCM2836_SOC_REGISTERS) {
mVideoCoreSize = BCM2836_SOC_REGISTERS - mVideoCoreBase;
DEBUG ((DEBUG_WARN, "VideoCore range overlapped SoC MMIO, now 0x%ll08X (Size 0x%ll08X)\n",
mVideoCoreBase, mVideoCoreSize));
}
VirtualMemoryTable = (ARM_MEMORY_REGION_DESCRIPTOR*)AllocatePages
(EFI_SIZE_TO_PAGES (sizeof (ARM_MEMORY_REGION_DESCRIPTOR) *
MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS));
if (VirtualMemoryTable == NULL) {
return;
}
// Firmware Volume
VirtualMemoryTable[Index].PhysicalBase = FixedPcdGet64 (PcdFdBaseAddress);
VirtualMemoryTable[Index].VirtualBase = VirtualMemoryTable[Index].PhysicalBase;
VirtualMemoryTable[Index].Length = VariablesBase - VirtualMemoryTable[Index].PhysicalBase;
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK;
VirtualMemoryInfo[Index].Type = RPI_MEM_RESERVED_REGION;
VirtualMemoryInfo[Index++].Name = L"FD";
// Variable Volume
VirtualMemoryTable[Index].PhysicalBase = VariablesBase;
VirtualMemoryTable[Index].VirtualBase = VirtualMemoryTable[Index].PhysicalBase;
VirtualMemoryTable[Index].Length = FixedPcdGet32 (PcdFdtBaseAddress) - VariablesBase;
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK;
VirtualMemoryInfo[Index].Type = RPI_MEM_RUNTIME_REGION;
VirtualMemoryInfo[Index++].Name = L"FD Variables";
//
// Both the the Pi 4 and Pi 3 implementations expect the DTB to directly follow the FD.
//
VirtualMemoryTable[Index].PhysicalBase = FixedPcdGet32 (PcdFdtBaseAddress);
VirtualMemoryTable[Index].VirtualBase = VirtualMemoryTable[Index].PhysicalBase;
VirtualMemoryTable[Index].Length = FixedPcdGet32 (PcdFdtSize);;
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK;
VirtualMemoryInfo[Index].Type = RPI_MEM_RESERVED_REGION;
VirtualMemoryInfo[Index++].Name = L"Flattened Device Tree";
if (BCM2711_SOC_REGISTERS == 0) {
//
// TF-A reserved RAM only exists for the Pi 3 TF-A.
//
// This is 2MB that directly follows the FD.
//
VirtualMemoryTable[Index].PhysicalBase = (FixedPcdGet64(PcdFdBaseAddress) + FixedPcdGet32(PcdFdSize));
VirtualMemoryTable[Index].VirtualBase = VirtualMemoryTable[Index].PhysicalBase;
VirtualMemoryTable[Index].Length = FixedPcdGet64 (PcdSystemMemoryBase) - VirtualMemoryTable[Index].PhysicalBase;
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK;
VirtualMemoryInfo[Index].Type = RPI_MEM_RESERVED_REGION;
VirtualMemoryInfo[Index++].Name = L"TF-A RAM";
}
// Base System RAM
VirtualMemoryTable[Index].PhysicalBase = FixedPcdGet64 (PcdSystemMemoryBase);
VirtualMemoryTable[Index].VirtualBase = VirtualMemoryTable[Index].PhysicalBase;
VirtualMemoryTable[Index].Length = mSystemMemoryEnd + 1 - FixedPcdGet64 (PcdSystemMemoryBase);
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK;
VirtualMemoryInfo[Index].Type = RPI_MEM_BASIC_REGION;
VirtualMemoryInfo[Index++].Name = L"System RAM < 1GB";
// GPU Reserved
VirtualMemoryTable[Index].PhysicalBase = mVideoCoreBase;
VirtualMemoryTable[Index].VirtualBase = VirtualMemoryTable[Index].PhysicalBase;
VirtualMemoryTable[Index].Length = mVideoCoreSize;
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
VirtualMemoryInfo[Index].Type = RPI_MEM_UNMAPPED_REGION;
VirtualMemoryInfo[Index++].Name = L"GPU Reserved";
// Extended SoC registers (PCIe, genet, ...)
if (BCM2711_SOC_REGISTERS > 0) {
VirtualMemoryTable[Index].PhysicalBase = BCM2711_SOC_REGISTERS;
VirtualMemoryTable[Index].VirtualBase = VirtualMemoryTable[Index].PhysicalBase;
VirtualMemoryTable[Index].Length = BCM2711_SOC_REGISTER_LENGTH;
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
VirtualMemoryInfo[Index].Type = RPI_MEM_UNMAPPED_REGION;
VirtualMemoryInfo[Index++].Name = L"SoC Reserved (27xx)";
}
// Base SoC registers
VirtualMemoryTable[Index].PhysicalBase = BCM2836_SOC_REGISTERS;
VirtualMemoryTable[Index].VirtualBase = VirtualMemoryTable[Index].PhysicalBase;
VirtualMemoryTable[Index].Length = BCM2836_SOC_REGISTER_LENGTH;
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
VirtualMemoryInfo[Index].Type = RPI_MEM_UNMAPPED_REGION;
VirtualMemoryInfo[Index++].Name = L"SoC Reserved (283x)";
// Memory in the 1GB - 3GB range is always available.
if (MemorySizeBelow3GB > SIZE_1GB) {
VirtualMemoryTable[Index].PhysicalBase = SIZE_1GB;
VirtualMemoryTable[Index].VirtualBase = VirtualMemoryTable[Index].PhysicalBase;
VirtualMemoryTable[Index].Length = MemorySizeBelow3GB - VirtualMemoryTable[Index].PhysicalBase;
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK;
VirtualMemoryInfo[Index].Type = RPI_MEM_BASIC_REGION;
VirtualMemoryInfo[Index++].Name = L"Extended System RAM < 3GB";
}
//
// If we have RAM in the 3GB - 4GB range, declare it as mapped, but don't
// add it to the memory map. This is done later by ConfigDxe if necessary.
//
if (MemorySizeBelow4GB > 3UL * SIZE_1GB) {
VirtualMemoryTable[Index].PhysicalBase = 3UL * SIZE_1GB;
VirtualMemoryTable[Index].VirtualBase = VirtualMemoryTable[Index].PhysicalBase;
VirtualMemoryTable[Index].Length = MemorySizeBelow4GB - VirtualMemoryTable[Index].PhysicalBase;
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK;
VirtualMemoryInfo[Index].Type = RPI_MEM_UNMAPPED_REGION;
VirtualMemoryInfo[Index++].Name = L"Extended System RAM < 4GB";
}
// Same treatment for the memory above 4GB.
if (TotalMemorySize > 4UL * SIZE_1GB) {
VirtualMemoryTable[Index].PhysicalBase = 4UL * SIZE_1GB;
VirtualMemoryTable[Index].VirtualBase = VirtualMemoryTable[Index].PhysicalBase;
VirtualMemoryTable[Index].Length = TotalMemorySize - VirtualMemoryTable[Index].PhysicalBase;
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK;
VirtualMemoryInfo[Index].Type = RPI_MEM_UNMAPPED_REGION;
VirtualMemoryInfo[Index++].Name = L"Extended System RAM >= 4GB";
}
// End of Table
VirtualMemoryTable[Index].PhysicalBase = 0;
VirtualMemoryTable[Index].VirtualBase = 0;
VirtualMemoryTable[Index].Length = 0;
VirtualMemoryTable[Index++].Attributes = (ARM_MEMORY_REGION_ATTRIBUTES)0;
ASSERT(Index <= MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS);
*VirtualMemoryMap = VirtualMemoryTable;
VirtualMemoryInfoInitialized = TRUE;
}
/**
Return additional memory info not populated by the above call.
This call should follow the one to ArmPlatformGetVirtualMemoryMap ().
**/
VOID
RpiPlatformGetVirtualMemoryInfo (
IN RPI_MEMORY_REGION_INFO** MemoryInfo
)
{
ASSERT (VirtualMemoryInfo != NULL);
if (!VirtualMemoryInfoInitialized) {
DEBUG ((DEBUG_ERROR,
"ArmPlatformGetVirtualMemoryMap must be called before RpiPlatformGetVirtualMemoryInfo.\n"));
return;
}
*MemoryInfo = VirtualMemoryInfo;
}
|