blob: 6845ce72ff940685a65b338bc2139338c1de678f [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glassd2269f22015-08-04 12:34:01 -06002/*
3 * Copyright (c) 2015 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
Simon Glassd2269f22015-08-04 12:34:01 -06005 */
6
Simon Glass1fa70f82019-11-14 12:57:34 -07007#include <cpu_func.h>
Simon Glassd2269f22015-08-04 12:34:01 -06008#include <efi.h>
Simon Glassc3dcef12021-12-29 11:57:53 -07009#include <efi_api.h>
Simon Glassd2269f22015-08-04 12:34:01 -060010#include <errno.h>
Simon Glass1cedca12023-08-21 21:17:01 -060011#include <event.h>
Simon Glass6980b6b2019-11-14 12:57:45 -070012#include <init.h>
Simon Glass0f2af882020-05-10 11:40:05 -060013#include <log.h>
Bin Mengdb59dd32018-06-17 05:57:53 -070014#include <usb.h>
Bin Meng106dcfc2018-08-23 08:24:10 -070015#include <asm/bootparam.h>
Bin Meng2f65c072018-08-23 08:24:08 -070016#include <asm/e820.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060017#include <asm/global_data.h>
Bin Meng6bd41092018-06-12 08:36:17 -070018#include <asm/post.h>
Tom Rinidec7ea02024-05-20 13:35:03 -060019#include <asm/u-boot-x86.h>
Simon Glassd2269f22015-08-04 12:34:01 -060020
21DECLARE_GLOBAL_DATA_PTR;
22
23/*
24 * This function looks for the highest region of memory lower than 4GB which
25 * has enough space for U-Boot where U-Boot is aligned on a page boundary.
26 * It overrides the default implementation found elsewhere which simply
27 * picks the end of ram, wherever that may be. The location of the stack,
28 * the relocation address, and how far U-Boot is moved by relocation are
29 * set in the global data structure.
30 */
Heinrich Schuchardt51a9aac2023-08-12 20:16:58 +020031phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
Simon Glassd2269f22015-08-04 12:34:01 -060032{
33 struct efi_mem_desc *desc, *end;
34 struct efi_entry_memmap *map;
35 int ret, size;
36 uintptr_t dest_addr = 0;
37 struct efi_mem_desc *largest = NULL;
38
39 /*
40 * Find largest area of memory below 4GB. We could
41 * call efi_build_mem_table() for a more accurate picture since it
42 * merges areas together where possible. But that function uses more
43 * pre-relocation memory, and it's not critical that we find the
44 * absolute largest region.
45 */
46 ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
47 if (ret) {
48 /* We should have stopped in dram_init(), something is wrong */
49 debug("%s: Missing memory map\n", __func__);
50 goto err;
51 }
52
53 end = (struct efi_mem_desc *)((ulong)map + size);
54 desc = map->desc;
Simon Glass6f4d7aa2022-01-04 03:51:11 -070055 for (; desc < end; desc = efi_get_next_mem_desc(desc, map->desc_size)) {
Simon Glassd2269f22015-08-04 12:34:01 -060056 if (desc->type != EFI_CONVENTIONAL_MEMORY ||
57 desc->physical_start >= 1ULL << 32)
58 continue;
59 if (!largest || desc->num_pages > largest->num_pages)
60 largest = desc;
61 }
62
63 /* If no suitable area was found, return an error. */
64 assert(largest);
65 if (!largest || (largest->num_pages << EFI_PAGE_SHIFT) < (2 << 20))
66 goto err;
67
68 dest_addr = largest->physical_start + (largest->num_pages <<
69 EFI_PAGE_SHIFT);
70
71 return (ulong)dest_addr;
72err:
73 panic("No available memory found for relocation");
74 return 0;
75}
76
77int dram_init(void)
78{
79 struct efi_mem_desc *desc, *end;
80 struct efi_entry_memmap *map;
81 int size, ret;
82
83 ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
84 if (ret) {
85 printf("Cannot find EFI memory map tables, ret=%d\n", ret);
86
87 return -ENODEV;
88 }
89
90 end = (struct efi_mem_desc *)((ulong)map + size);
91 gd->ram_size = 0;
92 desc = map->desc;
Simon Glass6f4d7aa2022-01-04 03:51:11 -070093 for (; desc < end; desc = efi_get_next_mem_desc(desc, map->desc_size)) {
Simon Glassd2269f22015-08-04 12:34:01 -060094 if (desc->type < EFI_MMAP_IO)
95 gd->ram_size += desc->num_pages << EFI_PAGE_SHIFT;
96 }
97
98 return 0;
99}
100
Simon Glass2f949c32017-03-31 08:40:32 -0600101int dram_init_banksize(void)
Simon Glassd2269f22015-08-04 12:34:01 -0600102{
103 struct efi_mem_desc *desc, *end;
104 struct efi_entry_memmap *map;
105 int ret, size;
106 int num_banks;
107
108 ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
109 if (ret) {
110 /* We should have stopped in dram_init(), something is wrong */
111 debug("%s: Missing memory map\n", __func__);
Simon Glass2f949c32017-03-31 08:40:32 -0600112 return -ENXIO;
Simon Glassd2269f22015-08-04 12:34:01 -0600113 }
114 end = (struct efi_mem_desc *)((ulong)map + size);
115 desc = map->desc;
116 for (num_banks = 0;
117 desc < end && num_banks < CONFIG_NR_DRAM_BANKS;
Simon Glass6f4d7aa2022-01-04 03:51:11 -0700118 desc = efi_get_next_mem_desc(desc, map->desc_size)) {
Simon Glassd2269f22015-08-04 12:34:01 -0600119 /*
Bin Meng7eb28a52018-06-22 01:38:30 -0700120 * We only use conventional memory and ignore
Simon Glassd2269f22015-08-04 12:34:01 -0600121 * anything less than 1MB.
122 */
123 if (desc->type != EFI_CONVENTIONAL_MEMORY ||
Simon Glassd2269f22015-08-04 12:34:01 -0600124 (desc->num_pages << EFI_PAGE_SHIFT) < 1 << 20)
125 continue;
126 gd->bd->bi_dram[num_banks].start = desc->physical_start;
127 gd->bd->bi_dram[num_banks].size = desc->num_pages <<
128 EFI_PAGE_SHIFT;
129 num_banks++;
130 }
Simon Glass2f949c32017-03-31 08:40:32 -0600131
132 return 0;
Simon Glassd2269f22015-08-04 12:34:01 -0600133}
134
Bin Meng6bd41092018-06-12 08:36:17 -0700135int arch_cpu_init(void)
136{
137 post_code(POST_CPU_INIT);
138
139 return x86_cpu_init_f();
140}
141
Simon Glassee7c36f2017-03-28 10:27:30 -0600142int checkcpu(void)
143{
144 return 0;
145}
146
Simon Glassd2269f22015-08-04 12:34:01 -0600147/* Find any available tables and copy them to a safe place */
148int reserve_arch(void)
149{
150 struct efi_info_hdr *hdr;
151
152 debug("table=%lx\n", gd->arch.table);
153 if (!gd->arch.table)
154 return 0;
155
156 hdr = (struct efi_info_hdr *)gd->arch.table;
157
158 gd->start_addr_sp -= hdr->total_size;
159 memcpy((void *)gd->start_addr_sp, hdr, hdr->total_size);
160 debug("Stashing EFI table at %lx to %lx, size %x\n",
161 gd->arch.table, gd->start_addr_sp, hdr->total_size);
162 gd->arch.table = gd->start_addr_sp;
163
164 return 0;
165}
Bin Mengdb59dd32018-06-17 05:57:53 -0700166
Simon Glass1cedca12023-08-21 21:17:01 -0600167static int last_stage_init(void)
Bin Mengdb59dd32018-06-17 05:57:53 -0700168{
169 /* start usb so that usb keyboard can be used as input device */
Simon Glass04443802023-02-05 17:55:28 -0700170 if (IS_ENABLED(CONFIG_USB_KEYBOARD))
Bin Menga7bb8ef2018-11-29 20:07:13 -0800171 usb_init();
Bin Mengdb59dd32018-06-17 05:57:53 -0700172
173 return 0;
174}
Simon Glass1cedca12023-08-21 21:17:01 -0600175EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, last_stage_init);
Bin Meng2f65c072018-08-23 08:24:08 -0700176
177unsigned int install_e820_map(unsigned int max_entries,
178 struct e820_entry *entries)
179{
180 struct efi_mem_desc *desc, *end;
181 struct efi_entry_memmap *map;
182 int size, ret;
183 efi_physical_addr_t last_end_addr = 0;
184 struct e820_entry *last_entry = NULL;
185 __u32 e820_type;
186 unsigned int num_entries = 0;
187
188 ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
189 if (ret) {
190 printf("Cannot find EFI memory map tables, ret=%d\n", ret);
191
192 return -ENODEV;
193 }
194
195 end = (struct efi_mem_desc *)((ulong)map + size);
196 for (desc = map->desc; desc < end;
Simon Glass6f4d7aa2022-01-04 03:51:11 -0700197 desc = efi_get_next_mem_desc(desc, map->desc_size)) {
Bin Meng2f65c072018-08-23 08:24:08 -0700198 if (desc->num_pages == 0)
199 continue;
200
201 switch (desc->type) {
202 case EFI_LOADER_CODE:
203 case EFI_LOADER_DATA:
204 case EFI_BOOT_SERVICES_CODE:
205 case EFI_BOOT_SERVICES_DATA:
206 case EFI_CONVENTIONAL_MEMORY:
207 e820_type = E820_RAM;
208 break;
209
210 case EFI_RESERVED_MEMORY_TYPE:
211 case EFI_RUNTIME_SERVICES_CODE:
212 case EFI_RUNTIME_SERVICES_DATA:
213 case EFI_MMAP_IO:
214 case EFI_MMAP_IO_PORT:
215 case EFI_PAL_CODE:
216 e820_type = E820_RESERVED;
217 break;
218
219 case EFI_ACPI_RECLAIM_MEMORY:
220 e820_type = E820_ACPI;
221 break;
222
223 case EFI_ACPI_MEMORY_NVS:
224 e820_type = E820_NVS;
225 break;
226
227 case EFI_UNUSABLE_MEMORY:
228 e820_type = E820_UNUSABLE;
229 break;
230
231 default:
232 printf("Invalid EFI memory descriptor type (0x%x)!\n",
233 desc->type);
234 continue;
235 }
236
237 if (last_entry != NULL && last_entry->type == e820_type &&
238 desc->physical_start == last_end_addr) {
239 last_entry->size += (desc->num_pages << EFI_PAGE_SHIFT);
240 last_end_addr += (desc->num_pages << EFI_PAGE_SHIFT);
241 } else {
242 if (num_entries >= E820MAX)
243 break;
244
245 entries[num_entries].addr = desc->physical_start;
246 entries[num_entries].size = desc->num_pages;
247 entries[num_entries].size <<= EFI_PAGE_SHIFT;
248 entries[num_entries].type = e820_type;
249 last_entry = &entries[num_entries];
250 last_end_addr = last_entry->addr + last_entry->size;
251 num_entries++;
252 }
253 }
254
255 return num_entries;
256}
Bin Meng106dcfc2018-08-23 08:24:10 -0700257
258void setup_efi_info(struct efi_info *efi_info)
259{
260 struct efi_entry_systable *table;
261 struct efi_entry_memmap *map;
262 char *signature;
263 int size, ret;
264
265 memset(efi_info, 0, sizeof(struct efi_info));
266
267 ret = efi_info_get(EFIET_SYS_TABLE, (void **)&table, &size);
268 if (ret) {
269 printf("Cannot find EFI system table, ret=%d\n", ret);
270 return;
271 }
272 efi_info->efi_systab = (u32)(table->sys_table);
273
274 ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
275 if (ret) {
276 printf("Cannot find EFI memory map tables, ret=%d\n", ret);
277 return;
278 }
279 efi_info->efi_memdesc_size = map->desc_size;
280 efi_info->efi_memdesc_version = map->version;
Simon Glass912e06f2021-09-24 18:30:21 -0600281 efi_info->efi_memmap = (ulong)(map->desc);
Bin Meng106dcfc2018-08-23 08:24:10 -0700282 efi_info->efi_memmap_size = size - sizeof(struct efi_entry_memmap);
283
284#ifdef CONFIG_EFI_STUB_64BIT
285 efi_info->efi_systab_hi = table->sys_table >> 32;
Simon Glass912e06f2021-09-24 18:30:21 -0600286 efi_info->efi_memmap_hi = (u64)(ulong)map->desc >> 32;
Bin Meng106dcfc2018-08-23 08:24:10 -0700287 signature = EFI64_LOADER_SIGNATURE;
288#else
289 signature = EFI32_LOADER_SIGNATURE;
290#endif
291 memcpy(&efi_info->efi_loader_signature, signature, 4);
292}
Simon Glass912e06f2021-09-24 18:30:21 -0600293
294void efi_show_bdinfo(void)
295{
296 struct efi_entry_systable *table = NULL;
Simon Glassc3dcef12021-12-29 11:57:53 -0700297 struct efi_system_table *sys_table;
Simon Glass912e06f2021-09-24 18:30:21 -0600298 int size, ret;
299
300 ret = efi_info_get(EFIET_SYS_TABLE, (void **)&table, &size);
Simon Glassc3dcef12021-12-29 11:57:53 -0700301 if (!ret) {
302 bdinfo_print_num_l("efi_table", table->sys_table);
303 sys_table = (struct efi_system_table *)(uintptr_t)
304 table->sys_table;
305 bdinfo_print_num_l(" revision", sys_table->fw_revision);
306 }
Simon Glass912e06f2021-09-24 18:30:21 -0600307}