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
|
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*/
#define LOG_CATEGORY LOGC_ARCH
#include <efi_loader.h>
#include <lmb.h>
#include <log.h>
#include <asm/e820.h>
#include <asm/global_data.h>
DECLARE_GLOBAL_DATA_PTR;
static const char *const e820_type_name[E820_COUNT] = {
[E820_RAM] = "RAM",
[E820_RESERVED] = "Reserved",
[E820_ACPI] = "ACPI",
[E820_NVS] = "ACPI NVS",
[E820_UNUSABLE] = "Unusable",
};
void e820_dump(struct e820_entry *entries, uint count)
{
int i;
printf("%12s %10s %s\n", "Addr", "Size", "Type");
for (i = 0; i < count; i++) {
struct e820_entry *entry = &entries[i];
printf("%12llx %10llx %s\n", entry->addr, entry->size,
entry->type < E820_COUNT ?
e820_type_name[entry->type] :
simple_itoa(entry->type));
}
}
/*
* Install a default e820 table with 4 entries as follows:
*
* 0x000000-0x0a0000 Useable RAM
* 0x0a0000-0x100000 Reserved for ISA
* 0x100000-gd->ram_size Useable RAM
* CONFIG_PCIE_ECAM_BASE PCIe ECAM
*/
__weak unsigned int install_e820_map(unsigned int max_entries,
struct e820_entry *entries)
{
entries[0].addr = 0;
entries[0].size = ISA_START_ADDRESS;
entries[0].type = E820_RAM;
entries[1].addr = ISA_START_ADDRESS;
entries[1].size = ISA_END_ADDRESS - ISA_START_ADDRESS;
entries[1].type = E820_RESERVED;
entries[2].addr = ISA_END_ADDRESS;
entries[2].size = gd->ram_size - ISA_END_ADDRESS;
entries[2].type = E820_RAM;
entries[3].addr = CONFIG_PCIE_ECAM_BASE;
entries[3].size = CONFIG_PCIE_ECAM_SIZE;
entries[3].type = E820_RESERVED;
return 4;
}
void e820_init(struct e820_ctx *ctx, struct e820_entry *entries,
int max_entries)
{
memset(ctx, '\0', sizeof(*ctx));
ctx->entries = entries;
ctx->max_entries = max_entries;
}
void e820_add(struct e820_ctx *ctx, enum e820_type type, u64 addr, u64 size)
{
struct e820_entry *entry = &ctx->entries[ctx->count++];
if (ctx->count <= ctx->max_entries) {
entry->addr = addr;
entry->size = size;
entry->type = type;
}
ctx->addr = addr + size;
}
void e820_next(struct e820_ctx *ctx, enum e820_type type, u64 size)
{
e820_add(ctx, type, ctx->addr, size);
}
void e820_to_addr(struct e820_ctx *ctx, enum e820_type type, u64 addr)
{
e820_next(ctx, type, addr - ctx->addr);
}
int e820_finish(struct e820_ctx *ctx)
{
if (ctx->count > ctx->max_entries) {
printf("e820 has %d entries but room for only %d\n", ctx->count,
ctx->max_entries);
panic("e820 table too large");
}
log_debug("e820 map installed, n=%d\n", ctx->count);
if (_DEBUG)
e820_dump(ctx->entries, ctx->count);
return ctx->count;
}
#if CONFIG_IS_ENABLED(EFI_LOADER)
void efi_add_known_memory(void)
{
struct e820_entry e820[E820MAX];
unsigned int i, num;
u64 start;
int type;
num = install_e820_map(ARRAY_SIZE(e820), e820);
for (i = 0; i < num; ++i) {
start = e820[i].addr;
switch (e820[i].type) {
case E820_RAM:
type = EFI_CONVENTIONAL_MEMORY;
break;
case E820_RESERVED:
type = EFI_RESERVED_MEMORY_TYPE;
break;
case E820_ACPI:
type = EFI_ACPI_RECLAIM_MEMORY;
break;
case E820_NVS:
type = EFI_ACPI_MEMORY_NVS;
break;
case E820_UNUSABLE:
default:
type = EFI_UNUSABLE_MEMORY;
break;
}
if (type != EFI_CONVENTIONAL_MEMORY)
efi_add_memory_map(start, e820[i].size, type);
}
}
#endif /* CONFIG_IS_ENABLED(EFI_LOADER) */
#if CONFIG_IS_ENABLED(LMB_ARCH_MEM_MAP)
void lmb_arch_add_memory(void)
{
struct e820_entry e820[E820MAX];
unsigned int i, num;
u64 ram_top;
num = install_e820_map(ARRAY_SIZE(e820), e820);
ram_top = (u64)gd->ram_top & ~EFI_PAGE_MASK;
if (!ram_top)
ram_top = 0x100000000ULL;
for (i = 0; i < num; ++i) {
if (e820[i].type == E820_RAM) {
u64 start, size, rgn_top;
start = e820[i].addr;
size = e820[i].size;
rgn_top = start + size;
if (start > ram_top)
continue;
if (rgn_top > ram_top)
size -= rgn_top - ram_top;
lmb_add(start, size);
}
}
}
#endif /* CONFIG_IS_ENABLED(LMB_ARCH_MEM_MAP) */
|