1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2015 Google, Inc 4 * Written by Simon Glass <sjg@chromium.org> 5 */ 6 7 #include <common.h> 8 #include <efi.h> 9 #include <errno.h> 10 #include <asm/post.h> 11 12 DECLARE_GLOBAL_DATA_PTR; 13 14 /* 15 * This function looks for the highest region of memory lower than 4GB which 16 * has enough space for U-Boot where U-Boot is aligned on a page boundary. 17 * It overrides the default implementation found elsewhere which simply 18 * picks the end of ram, wherever that may be. The location of the stack, 19 * the relocation address, and how far U-Boot is moved by relocation are 20 * set in the global data structure. 21 */ 22 ulong board_get_usable_ram_top(ulong total_size) 23 { 24 struct efi_mem_desc *desc, *end; 25 struct efi_entry_memmap *map; 26 int ret, size; 27 uintptr_t dest_addr = 0; 28 struct efi_mem_desc *largest = NULL; 29 30 /* 31 * Find largest area of memory below 4GB. We could 32 * call efi_build_mem_table() for a more accurate picture since it 33 * merges areas together where possible. But that function uses more 34 * pre-relocation memory, and it's not critical that we find the 35 * absolute largest region. 36 */ 37 ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size); 38 if (ret) { 39 /* We should have stopped in dram_init(), something is wrong */ 40 debug("%s: Missing memory map\n", __func__); 41 goto err; 42 } 43 44 end = (struct efi_mem_desc *)((ulong)map + size); 45 desc = map->desc; 46 for (; desc < end; desc = efi_get_next_mem_desc(map, desc)) { 47 if (desc->type != EFI_CONVENTIONAL_MEMORY || 48 desc->physical_start >= 1ULL << 32) 49 continue; 50 if (!largest || desc->num_pages > largest->num_pages) 51 largest = desc; 52 } 53 54 /* If no suitable area was found, return an error. */ 55 assert(largest); 56 if (!largest || (largest->num_pages << EFI_PAGE_SHIFT) < (2 << 20)) 57 goto err; 58 59 dest_addr = largest->physical_start + (largest->num_pages << 60 EFI_PAGE_SHIFT); 61 62 return (ulong)dest_addr; 63 err: 64 panic("No available memory found for relocation"); 65 return 0; 66 } 67 68 int dram_init(void) 69 { 70 struct efi_mem_desc *desc, *end; 71 struct efi_entry_memmap *map; 72 int size, ret; 73 74 ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size); 75 if (ret) { 76 printf("Cannot find EFI memory map tables, ret=%d\n", ret); 77 78 return -ENODEV; 79 } 80 81 end = (struct efi_mem_desc *)((ulong)map + size); 82 gd->ram_size = 0; 83 desc = map->desc; 84 for (; desc < end; desc = efi_get_next_mem_desc(map, desc)) { 85 if (desc->type < EFI_MMAP_IO) 86 gd->ram_size += desc->num_pages << EFI_PAGE_SHIFT; 87 } 88 89 return 0; 90 } 91 92 int dram_init_banksize(void) 93 { 94 struct efi_mem_desc *desc, *end; 95 struct efi_entry_memmap *map; 96 int ret, size; 97 int num_banks; 98 99 ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size); 100 if (ret) { 101 /* We should have stopped in dram_init(), something is wrong */ 102 debug("%s: Missing memory map\n", __func__); 103 return -ENXIO; 104 } 105 end = (struct efi_mem_desc *)((ulong)map + size); 106 desc = map->desc; 107 for (num_banks = 0; 108 desc < end && num_banks < CONFIG_NR_DRAM_BANKS; 109 desc = efi_get_next_mem_desc(map, desc)) { 110 /* 111 * We only use conventional memory below 4GB, and ignore 112 * anything less than 1MB. 113 */ 114 if (desc->type != EFI_CONVENTIONAL_MEMORY || 115 desc->physical_start >= 1ULL << 32 || 116 (desc->num_pages << EFI_PAGE_SHIFT) < 1 << 20) 117 continue; 118 gd->bd->bi_dram[num_banks].start = desc->physical_start; 119 gd->bd->bi_dram[num_banks].size = desc->num_pages << 120 EFI_PAGE_SHIFT; 121 num_banks++; 122 } 123 124 return 0; 125 } 126 127 int arch_cpu_init(void) 128 { 129 post_code(POST_CPU_INIT); 130 131 return x86_cpu_init_f(); 132 } 133 134 int checkcpu(void) 135 { 136 return 0; 137 } 138 139 int print_cpuinfo(void) 140 { 141 return default_print_cpuinfo(); 142 } 143 144 /* Find any available tables and copy them to a safe place */ 145 int reserve_arch(void) 146 { 147 struct efi_info_hdr *hdr; 148 149 debug("table=%lx\n", gd->arch.table); 150 if (!gd->arch.table) 151 return 0; 152 153 hdr = (struct efi_info_hdr *)gd->arch.table; 154 155 gd->start_addr_sp -= hdr->total_size; 156 memcpy((void *)gd->start_addr_sp, hdr, hdr->total_size); 157 debug("Stashing EFI table at %lx to %lx, size %x\n", 158 gd->arch.table, gd->start_addr_sp, hdr->total_size); 159 gd->arch.table = gd->start_addr_sp; 160 161 return 0; 162 } 163