blob: bcc5f6f30441546a71bc8d3fa3132b9081f5d928 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Bin Menga4899632015-10-07 20:19:10 -07002/*
3 * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
Bin Menga4899632015-10-07 20:19:10 -07004 */
5
Simon Glassf92c54e2025-03-15 14:25:53 +00006#define LOG_CATEGORY LOGC_ARCH
7
Bin Meng1a4e82d2018-06-27 20:38:01 -07008#include <efi_loader.h>
Sughosh Ganu526eebd2024-10-15 21:07:13 +05309#include <lmb.h>
Simon Glassf92c54e2025-03-15 14:25:53 +000010#include <log.h>
Bin Menga4899632015-10-07 20:19:10 -070011#include <asm/e820.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060012#include <asm/global_data.h>
Bin Menga4899632015-10-07 20:19:10 -070013
14DECLARE_GLOBAL_DATA_PTR;
15
Simon Glassb106f072025-03-15 14:25:52 +000016static const char *const e820_type_name[E820_COUNT] = {
17 [E820_RAM] = "RAM",
18 [E820_RESERVED] = "Reserved",
19 [E820_ACPI] = "ACPI",
20 [E820_NVS] = "ACPI NVS",
21 [E820_UNUSABLE] = "Unusable",
22};
23
24void e820_dump(struct e820_entry *entries, uint count)
25{
26 int i;
27
28 printf("%12s %10s %s\n", "Addr", "Size", "Type");
29 for (i = 0; i < count; i++) {
30 struct e820_entry *entry = &entries[i];
31
32 printf("%12llx %10llx %s\n", entry->addr, entry->size,
33 entry->type < E820_COUNT ?
34 e820_type_name[entry->type] :
35 simple_itoa(entry->type));
36 }
37}
38
Bin Menga4899632015-10-07 20:19:10 -070039/*
40 * Install a default e820 table with 4 entries as follows:
41 *
42 * 0x000000-0x0a0000 Useable RAM
43 * 0x0a0000-0x100000 Reserved for ISA
44 * 0x100000-gd->ram_size Useable RAM
45 * CONFIG_PCIE_ECAM_BASE PCIe ECAM
46 */
Bin Meng3838d712018-04-11 22:02:10 -070047__weak unsigned int install_e820_map(unsigned int max_entries,
Bin Meng4b8fc742018-04-11 22:02:11 -070048 struct e820_entry *entries)
Bin Menga4899632015-10-07 20:19:10 -070049{
50 entries[0].addr = 0;
51 entries[0].size = ISA_START_ADDRESS;
52 entries[0].type = E820_RAM;
53 entries[1].addr = ISA_START_ADDRESS;
54 entries[1].size = ISA_END_ADDRESS - ISA_START_ADDRESS;
55 entries[1].type = E820_RESERVED;
56 entries[2].addr = ISA_END_ADDRESS;
57 entries[2].size = gd->ram_size - ISA_END_ADDRESS;
58 entries[2].type = E820_RAM;
59 entries[3].addr = CONFIG_PCIE_ECAM_BASE;
60 entries[3].size = CONFIG_PCIE_ECAM_SIZE;
61 entries[3].type = E820_RESERVED;
62
63 return 4;
64}
Bin Meng1a4e82d2018-06-27 20:38:01 -070065
Simon Glassf92c54e2025-03-15 14:25:53 +000066void e820_init(struct e820_ctx *ctx, struct e820_entry *entries,
67 int max_entries)
68{
69 memset(ctx, '\0', sizeof(*ctx));
70 ctx->entries = entries;
71 ctx->max_entries = max_entries;
72}
73
74void e820_add(struct e820_ctx *ctx, enum e820_type type, u64 addr, u64 size)
75{
76 struct e820_entry *entry = &ctx->entries[ctx->count++];
77
78 if (ctx->count <= ctx->max_entries) {
79 entry->addr = addr;
80 entry->size = size;
81 entry->type = type;
82 }
83 ctx->addr = addr + size;
84}
85
86void e820_next(struct e820_ctx *ctx, enum e820_type type, u64 size)
87{
88 e820_add(ctx, type, ctx->addr, size);
89}
90
91void e820_to_addr(struct e820_ctx *ctx, enum e820_type type, u64 addr)
92{
93 e820_next(ctx, type, addr - ctx->addr);
94}
95
96int e820_finish(struct e820_ctx *ctx)
97{
98 if (ctx->count > ctx->max_entries) {
99 printf("e820 has %d entries but room for only %d\n", ctx->count,
100 ctx->max_entries);
101 panic("e820 table too large");
102 }
103 log_debug("e820 map installed, n=%d\n", ctx->count);
104 if (_DEBUG)
105 e820_dump(ctx->entries, ctx->count);
106
107 return ctx->count;
108}
109
Stephen Warrend0de8062018-08-30 15:43:43 -0600110#if CONFIG_IS_ENABLED(EFI_LOADER)
Bin Meng1a4e82d2018-06-27 20:38:01 -0700111void efi_add_known_memory(void)
112{
113 struct e820_entry e820[E820MAX];
114 unsigned int i, num;
Sughosh Ganu526eebd2024-10-15 21:07:13 +0530115 u64 start;
Bin Meng1a4e82d2018-06-27 20:38:01 -0700116 int type;
117
118 num = install_e820_map(ARRAY_SIZE(e820), e820);
119
120 for (i = 0; i < num; ++i) {
121 start = e820[i].addr;
Bin Meng1a4e82d2018-06-27 20:38:01 -0700122
123 switch (e820[i].type) {
124 case E820_RAM:
125 type = EFI_CONVENTIONAL_MEMORY;
126 break;
127 case E820_RESERVED:
128 type = EFI_RESERVED_MEMORY_TYPE;
129 break;
130 case E820_ACPI:
131 type = EFI_ACPI_RECLAIM_MEMORY;
132 break;
133 case E820_NVS:
134 type = EFI_ACPI_MEMORY_NVS;
135 break;
136 case E820_UNUSABLE:
137 default:
138 type = EFI_UNUSABLE_MEMORY;
139 break;
140 }
141
Sughosh Ganu526eebd2024-10-15 21:07:13 +0530142 if (type != EFI_CONVENTIONAL_MEMORY)
Michael Walle282d3862020-05-17 12:29:19 +0200143 efi_add_memory_map(start, e820[i].size, type);
Bin Meng1a4e82d2018-06-27 20:38:01 -0700144 }
145}
Stephen Warrend0de8062018-08-30 15:43:43 -0600146#endif /* CONFIG_IS_ENABLED(EFI_LOADER) */
Sughosh Ganu526eebd2024-10-15 21:07:13 +0530147
148#if CONFIG_IS_ENABLED(LMB_ARCH_MEM_MAP)
149void lmb_arch_add_memory(void)
150{
151 struct e820_entry e820[E820MAX];
152 unsigned int i, num;
153 u64 ram_top;
154
155 num = install_e820_map(ARRAY_SIZE(e820), e820);
156
157 ram_top = (u64)gd->ram_top & ~EFI_PAGE_MASK;
158 if (!ram_top)
159 ram_top = 0x100000000ULL;
160
161 for (i = 0; i < num; ++i) {
162 if (e820[i].type == E820_RAM) {
163 u64 start, size, rgn_top;
164
165 start = e820[i].addr;
166 size = e820[i].size;
167 rgn_top = start + size;
168
169 if (start > ram_top)
170 continue;
171
172 if (rgn_top > ram_top)
173 size -= rgn_top - ram_top;
174
175 lmb_add(start, size);
176 }
177 }
178}
179#endif /* CONFIG_IS_ENABLED(LMB_ARCH_MEM_MAP) */