14f1dacd4SBin Meng // SPDX-License-Identifier: GPL-2.0+
24f1dacd4SBin Meng /*
34f1dacd4SBin Meng * Copyright (c) 2015 Google, Inc
44f1dacd4SBin Meng * Written by Simon Glass <sjg@chromium.org>
54f1dacd4SBin Meng */
64f1dacd4SBin Meng
74f1dacd4SBin Meng #include <common.h>
84f1dacd4SBin Meng #include <efi.h>
94f1dacd4SBin Meng #include <errno.h>
101ab2c010SBin Meng #include <usb.h>
111fdeacd3SBin Meng #include <asm/bootparam.h>
12aac79251SBin Meng #include <asm/e820.h>
133773c6a2SBin Meng #include <asm/post.h>
144f1dacd4SBin Meng
154f1dacd4SBin Meng DECLARE_GLOBAL_DATA_PTR;
164f1dacd4SBin Meng
174f1dacd4SBin Meng /*
184f1dacd4SBin Meng * This function looks for the highest region of memory lower than 4GB which
194f1dacd4SBin Meng * has enough space for U-Boot where U-Boot is aligned on a page boundary.
204f1dacd4SBin Meng * It overrides the default implementation found elsewhere which simply
214f1dacd4SBin Meng * picks the end of ram, wherever that may be. The location of the stack,
224f1dacd4SBin Meng * the relocation address, and how far U-Boot is moved by relocation are
234f1dacd4SBin Meng * set in the global data structure.
244f1dacd4SBin Meng */
board_get_usable_ram_top(ulong total_size)254f1dacd4SBin Meng ulong board_get_usable_ram_top(ulong total_size)
264f1dacd4SBin Meng {
274f1dacd4SBin Meng struct efi_mem_desc *desc, *end;
284f1dacd4SBin Meng struct efi_entry_memmap *map;
294f1dacd4SBin Meng int ret, size;
304f1dacd4SBin Meng uintptr_t dest_addr = 0;
314f1dacd4SBin Meng struct efi_mem_desc *largest = NULL;
324f1dacd4SBin Meng
334f1dacd4SBin Meng /*
344f1dacd4SBin Meng * Find largest area of memory below 4GB. We could
354f1dacd4SBin Meng * call efi_build_mem_table() for a more accurate picture since it
364f1dacd4SBin Meng * merges areas together where possible. But that function uses more
374f1dacd4SBin Meng * pre-relocation memory, and it's not critical that we find the
384f1dacd4SBin Meng * absolute largest region.
394f1dacd4SBin Meng */
404f1dacd4SBin Meng ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
414f1dacd4SBin Meng if (ret) {
424f1dacd4SBin Meng /* We should have stopped in dram_init(), something is wrong */
434f1dacd4SBin Meng debug("%s: Missing memory map\n", __func__);
444f1dacd4SBin Meng goto err;
454f1dacd4SBin Meng }
464f1dacd4SBin Meng
474f1dacd4SBin Meng end = (struct efi_mem_desc *)((ulong)map + size);
484f1dacd4SBin Meng desc = map->desc;
494f1dacd4SBin Meng for (; desc < end; desc = efi_get_next_mem_desc(map, desc)) {
504f1dacd4SBin Meng if (desc->type != EFI_CONVENTIONAL_MEMORY ||
514f1dacd4SBin Meng desc->physical_start >= 1ULL << 32)
524f1dacd4SBin Meng continue;
534f1dacd4SBin Meng if (!largest || desc->num_pages > largest->num_pages)
544f1dacd4SBin Meng largest = desc;
554f1dacd4SBin Meng }
564f1dacd4SBin Meng
574f1dacd4SBin Meng /* If no suitable area was found, return an error. */
584f1dacd4SBin Meng assert(largest);
594f1dacd4SBin Meng if (!largest || (largest->num_pages << EFI_PAGE_SHIFT) < (2 << 20))
604f1dacd4SBin Meng goto err;
614f1dacd4SBin Meng
624f1dacd4SBin Meng dest_addr = largest->physical_start + (largest->num_pages <<
634f1dacd4SBin Meng EFI_PAGE_SHIFT);
644f1dacd4SBin Meng
654f1dacd4SBin Meng return (ulong)dest_addr;
664f1dacd4SBin Meng err:
674f1dacd4SBin Meng panic("No available memory found for relocation");
684f1dacd4SBin Meng return 0;
694f1dacd4SBin Meng }
704f1dacd4SBin Meng
dram_init(void)714f1dacd4SBin Meng int dram_init(void)
724f1dacd4SBin Meng {
734f1dacd4SBin Meng struct efi_mem_desc *desc, *end;
744f1dacd4SBin Meng struct efi_entry_memmap *map;
754f1dacd4SBin Meng int size, ret;
764f1dacd4SBin Meng
774f1dacd4SBin Meng ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
784f1dacd4SBin Meng if (ret) {
794f1dacd4SBin Meng printf("Cannot find EFI memory map tables, ret=%d\n", ret);
804f1dacd4SBin Meng
814f1dacd4SBin Meng return -ENODEV;
824f1dacd4SBin Meng }
834f1dacd4SBin Meng
844f1dacd4SBin Meng end = (struct efi_mem_desc *)((ulong)map + size);
854f1dacd4SBin Meng gd->ram_size = 0;
864f1dacd4SBin Meng desc = map->desc;
874f1dacd4SBin Meng for (; desc < end; desc = efi_get_next_mem_desc(map, desc)) {
884f1dacd4SBin Meng if (desc->type < EFI_MMAP_IO)
894f1dacd4SBin Meng gd->ram_size += desc->num_pages << EFI_PAGE_SHIFT;
904f1dacd4SBin Meng }
914f1dacd4SBin Meng
924f1dacd4SBin Meng return 0;
934f1dacd4SBin Meng }
944f1dacd4SBin Meng
dram_init_banksize(void)954f1dacd4SBin Meng int dram_init_banksize(void)
964f1dacd4SBin Meng {
974f1dacd4SBin Meng struct efi_mem_desc *desc, *end;
984f1dacd4SBin Meng struct efi_entry_memmap *map;
994f1dacd4SBin Meng int ret, size;
1004f1dacd4SBin Meng int num_banks;
1014f1dacd4SBin Meng
1024f1dacd4SBin Meng ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
1034f1dacd4SBin Meng if (ret) {
1044f1dacd4SBin Meng /* We should have stopped in dram_init(), something is wrong */
1054f1dacd4SBin Meng debug("%s: Missing memory map\n", __func__);
1064f1dacd4SBin Meng return -ENXIO;
1074f1dacd4SBin Meng }
1084f1dacd4SBin Meng end = (struct efi_mem_desc *)((ulong)map + size);
1094f1dacd4SBin Meng desc = map->desc;
1104f1dacd4SBin Meng for (num_banks = 0;
1114f1dacd4SBin Meng desc < end && num_banks < CONFIG_NR_DRAM_BANKS;
1124f1dacd4SBin Meng desc = efi_get_next_mem_desc(map, desc)) {
1134f1dacd4SBin Meng /*
11459837472SBin Meng * We only use conventional memory and ignore
1154f1dacd4SBin Meng * anything less than 1MB.
1164f1dacd4SBin Meng */
1174f1dacd4SBin Meng if (desc->type != EFI_CONVENTIONAL_MEMORY ||
1184f1dacd4SBin Meng (desc->num_pages << EFI_PAGE_SHIFT) < 1 << 20)
1194f1dacd4SBin Meng continue;
1204f1dacd4SBin Meng gd->bd->bi_dram[num_banks].start = desc->physical_start;
1214f1dacd4SBin Meng gd->bd->bi_dram[num_banks].size = desc->num_pages <<
1224f1dacd4SBin Meng EFI_PAGE_SHIFT;
1234f1dacd4SBin Meng num_banks++;
1244f1dacd4SBin Meng }
1254f1dacd4SBin Meng
1264f1dacd4SBin Meng return 0;
1274f1dacd4SBin Meng }
1284f1dacd4SBin Meng
arch_cpu_init(void)1293773c6a2SBin Meng int arch_cpu_init(void)
1303773c6a2SBin Meng {
1313773c6a2SBin Meng post_code(POST_CPU_INIT);
1323773c6a2SBin Meng
1333773c6a2SBin Meng return x86_cpu_init_f();
1343773c6a2SBin Meng }
1353773c6a2SBin Meng
checkcpu(void)1364f1dacd4SBin Meng int checkcpu(void)
1374f1dacd4SBin Meng {
1384f1dacd4SBin Meng return 0;
1394f1dacd4SBin Meng }
1404f1dacd4SBin Meng
print_cpuinfo(void)1414f1dacd4SBin Meng int print_cpuinfo(void)
1424f1dacd4SBin Meng {
1434f1dacd4SBin Meng return default_print_cpuinfo();
1444f1dacd4SBin Meng }
1454f1dacd4SBin Meng
1464f1dacd4SBin Meng /* Find any available tables and copy them to a safe place */
reserve_arch(void)1474f1dacd4SBin Meng int reserve_arch(void)
1484f1dacd4SBin Meng {
1494f1dacd4SBin Meng struct efi_info_hdr *hdr;
1504f1dacd4SBin Meng
1514f1dacd4SBin Meng debug("table=%lx\n", gd->arch.table);
1524f1dacd4SBin Meng if (!gd->arch.table)
1534f1dacd4SBin Meng return 0;
1544f1dacd4SBin Meng
1554f1dacd4SBin Meng hdr = (struct efi_info_hdr *)gd->arch.table;
1564f1dacd4SBin Meng
1574f1dacd4SBin Meng gd->start_addr_sp -= hdr->total_size;
1584f1dacd4SBin Meng memcpy((void *)gd->start_addr_sp, hdr, hdr->total_size);
1594f1dacd4SBin Meng debug("Stashing EFI table at %lx to %lx, size %x\n",
1604f1dacd4SBin Meng gd->arch.table, gd->start_addr_sp, hdr->total_size);
1614f1dacd4SBin Meng gd->arch.table = gd->start_addr_sp;
1624f1dacd4SBin Meng
1634f1dacd4SBin Meng return 0;
1644f1dacd4SBin Meng }
1651ab2c010SBin Meng
last_stage_init(void)1661ab2c010SBin Meng int last_stage_init(void)
1671ab2c010SBin Meng {
1681ab2c010SBin Meng /* start usb so that usb keyboard can be used as input device */
169*d3d65318SBin Meng if (CONFIG_IS_ENABLED(USB_KEYBOARD))
1701ab2c010SBin Meng usb_init();
1711ab2c010SBin Meng
1721ab2c010SBin Meng return 0;
1731ab2c010SBin Meng }
174aac79251SBin Meng
install_e820_map(unsigned int max_entries,struct e820_entry * entries)175aac79251SBin Meng unsigned int install_e820_map(unsigned int max_entries,
176aac79251SBin Meng struct e820_entry *entries)
177aac79251SBin Meng {
178aac79251SBin Meng struct efi_mem_desc *desc, *end;
179aac79251SBin Meng struct efi_entry_memmap *map;
180aac79251SBin Meng int size, ret;
181aac79251SBin Meng efi_physical_addr_t last_end_addr = 0;
182aac79251SBin Meng struct e820_entry *last_entry = NULL;
183aac79251SBin Meng __u32 e820_type;
184aac79251SBin Meng unsigned int num_entries = 0;
185aac79251SBin Meng
186aac79251SBin Meng ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
187aac79251SBin Meng if (ret) {
188aac79251SBin Meng printf("Cannot find EFI memory map tables, ret=%d\n", ret);
189aac79251SBin Meng
190aac79251SBin Meng return -ENODEV;
191aac79251SBin Meng }
192aac79251SBin Meng
193aac79251SBin Meng end = (struct efi_mem_desc *)((ulong)map + size);
194aac79251SBin Meng for (desc = map->desc; desc < end;
195aac79251SBin Meng desc = efi_get_next_mem_desc(map, desc)) {
196aac79251SBin Meng if (desc->num_pages == 0)
197aac79251SBin Meng continue;
198aac79251SBin Meng
199aac79251SBin Meng switch (desc->type) {
200aac79251SBin Meng case EFI_LOADER_CODE:
201aac79251SBin Meng case EFI_LOADER_DATA:
202aac79251SBin Meng case EFI_BOOT_SERVICES_CODE:
203aac79251SBin Meng case EFI_BOOT_SERVICES_DATA:
204aac79251SBin Meng case EFI_CONVENTIONAL_MEMORY:
205aac79251SBin Meng e820_type = E820_RAM;
206aac79251SBin Meng break;
207aac79251SBin Meng
208aac79251SBin Meng case EFI_RESERVED_MEMORY_TYPE:
209aac79251SBin Meng case EFI_RUNTIME_SERVICES_CODE:
210aac79251SBin Meng case EFI_RUNTIME_SERVICES_DATA:
211aac79251SBin Meng case EFI_MMAP_IO:
212aac79251SBin Meng case EFI_MMAP_IO_PORT:
213aac79251SBin Meng case EFI_PAL_CODE:
214aac79251SBin Meng e820_type = E820_RESERVED;
215aac79251SBin Meng break;
216aac79251SBin Meng
217aac79251SBin Meng case EFI_ACPI_RECLAIM_MEMORY:
218aac79251SBin Meng e820_type = E820_ACPI;
219aac79251SBin Meng break;
220aac79251SBin Meng
221aac79251SBin Meng case EFI_ACPI_MEMORY_NVS:
222aac79251SBin Meng e820_type = E820_NVS;
223aac79251SBin Meng break;
224aac79251SBin Meng
225aac79251SBin Meng case EFI_UNUSABLE_MEMORY:
226aac79251SBin Meng e820_type = E820_UNUSABLE;
227aac79251SBin Meng break;
228aac79251SBin Meng
229aac79251SBin Meng default:
230aac79251SBin Meng printf("Invalid EFI memory descriptor type (0x%x)!\n",
231aac79251SBin Meng desc->type);
232aac79251SBin Meng continue;
233aac79251SBin Meng }
234aac79251SBin Meng
235aac79251SBin Meng if (last_entry != NULL && last_entry->type == e820_type &&
236aac79251SBin Meng desc->physical_start == last_end_addr) {
237aac79251SBin Meng last_entry->size += (desc->num_pages << EFI_PAGE_SHIFT);
238aac79251SBin Meng last_end_addr += (desc->num_pages << EFI_PAGE_SHIFT);
239aac79251SBin Meng } else {
240aac79251SBin Meng if (num_entries >= E820MAX)
241aac79251SBin Meng break;
242aac79251SBin Meng
243aac79251SBin Meng entries[num_entries].addr = desc->physical_start;
244aac79251SBin Meng entries[num_entries].size = desc->num_pages;
245aac79251SBin Meng entries[num_entries].size <<= EFI_PAGE_SHIFT;
246aac79251SBin Meng entries[num_entries].type = e820_type;
247aac79251SBin Meng last_entry = &entries[num_entries];
248aac79251SBin Meng last_end_addr = last_entry->addr + last_entry->size;
249aac79251SBin Meng num_entries++;
250aac79251SBin Meng }
251aac79251SBin Meng }
252aac79251SBin Meng
253aac79251SBin Meng return num_entries;
254aac79251SBin Meng }
2551fdeacd3SBin Meng
setup_efi_info(struct efi_info * efi_info)2561fdeacd3SBin Meng void setup_efi_info(struct efi_info *efi_info)
2571fdeacd3SBin Meng {
2581fdeacd3SBin Meng struct efi_entry_systable *table;
2591fdeacd3SBin Meng struct efi_entry_memmap *map;
2601fdeacd3SBin Meng char *signature;
2611fdeacd3SBin Meng int size, ret;
2621fdeacd3SBin Meng
2631fdeacd3SBin Meng memset(efi_info, 0, sizeof(struct efi_info));
2641fdeacd3SBin Meng
2651fdeacd3SBin Meng ret = efi_info_get(EFIET_SYS_TABLE, (void **)&table, &size);
2661fdeacd3SBin Meng if (ret) {
2671fdeacd3SBin Meng printf("Cannot find EFI system table, ret=%d\n", ret);
2681fdeacd3SBin Meng return;
2691fdeacd3SBin Meng }
2701fdeacd3SBin Meng efi_info->efi_systab = (u32)(table->sys_table);
2711fdeacd3SBin Meng
2721fdeacd3SBin Meng ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
2731fdeacd3SBin Meng if (ret) {
2741fdeacd3SBin Meng printf("Cannot find EFI memory map tables, ret=%d\n", ret);
2751fdeacd3SBin Meng return;
2761fdeacd3SBin Meng }
2771fdeacd3SBin Meng efi_info->efi_memdesc_size = map->desc_size;
2781fdeacd3SBin Meng efi_info->efi_memdesc_version = map->version;
2791fdeacd3SBin Meng efi_info->efi_memmap = (u32)(map->desc);
2801fdeacd3SBin Meng efi_info->efi_memmap_size = size - sizeof(struct efi_entry_memmap);
2811fdeacd3SBin Meng
2821fdeacd3SBin Meng #ifdef CONFIG_EFI_STUB_64BIT
2831fdeacd3SBin Meng efi_info->efi_systab_hi = table->sys_table >> 32;
2841fdeacd3SBin Meng efi_info->efi_memmap_hi = (u64)(u32)(map->desc) >> 32;
2851fdeacd3SBin Meng signature = EFI64_LOADER_SIGNATURE;
2861fdeacd3SBin Meng #else
2871fdeacd3SBin Meng signature = EFI32_LOADER_SIGNATURE;
2881fdeacd3SBin Meng #endif
2891fdeacd3SBin Meng memcpy(&efi_info->efi_loader_signature, signature, 4);
2901fdeacd3SBin Meng }
291