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 <cpu_func.h> 9#include <efi.h> 10#include <efi_api.h> 11#include <errno.h> 12#include <event.h> 13#include <init.h> 14#include <log.h> 15#include <usb.h> 16#include <asm/bootparam.h> 17#include <asm/e820.h> 18#include <asm/global_data.h> 19#include <asm/post.h> 20 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 */ 31phys_addr_t board_get_usable_ram_top(phys_size_t total_size) 32{ 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; 55 for (; desc < end; desc = efi_get_next_mem_desc(desc, map->desc_size)) { 56 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; 93 for (; desc < end; desc = efi_get_next_mem_desc(desc, map->desc_size)) { 94 if (desc->type < EFI_MMAP_IO) 95 gd->ram_size += desc->num_pages << EFI_PAGE_SHIFT; 96 } 97 98 return 0; 99} 100 101int dram_init_banksize(void) 102{ 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__); 112 return -ENXIO; 113 } 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; 118 desc = efi_get_next_mem_desc(desc, map->desc_size)) { 119 /* 120 * We only use conventional memory and ignore 121 * anything less than 1MB. 122 */ 123 if (desc->type != EFI_CONVENTIONAL_MEMORY || 124 (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 } 131 132 return 0; 133} 134 135int arch_cpu_init(void) 136{ 137 post_code(POST_CPU_INIT); 138 139 return x86_cpu_init_f(); 140} 141 142int checkcpu(void) 143{ 144 return 0; 145} 146 147int print_cpuinfo(void) 148{ 149 return default_print_cpuinfo(); 150} 151 152/* Find any available tables and copy them to a safe place */ 153int reserve_arch(void) 154{ 155 struct efi_info_hdr *hdr; 156 157 debug("table=%lx\n", gd->arch.table); 158 if (!gd->arch.table) 159 return 0; 160 161 hdr = (struct efi_info_hdr *)gd->arch.table; 162 163 gd->start_addr_sp -= hdr->total_size; 164 memcpy((void *)gd->start_addr_sp, hdr, hdr->total_size); 165 debug("Stashing EFI table at %lx to %lx, size %x\n", 166 gd->arch.table, gd->start_addr_sp, hdr->total_size); 167 gd->arch.table = gd->start_addr_sp; 168 169 return 0; 170} 171 172static int last_stage_init(void) 173{ 174 /* start usb so that usb keyboard can be used as input device */ 175 if (IS_ENABLED(CONFIG_USB_KEYBOARD)) 176 usb_init(); 177 178 return 0; 179} 180EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, last_stage_init); 181 182unsigned int install_e820_map(unsigned int max_entries, 183 struct e820_entry *entries) 184{ 185 struct efi_mem_desc *desc, *end; 186 struct efi_entry_memmap *map; 187 int size, ret; 188 efi_physical_addr_t last_end_addr = 0; 189 struct e820_entry *last_entry = NULL; 190 __u32 e820_type; 191 unsigned int num_entries = 0; 192 193 ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size); 194 if (ret) { 195 printf("Cannot find EFI memory map tables, ret=%d\n", ret); 196 197 return -ENODEV; 198 } 199 200 end = (struct efi_mem_desc *)((ulong)map + size); 201 for (desc = map->desc; desc < end; 202 desc = efi_get_next_mem_desc(desc, map->desc_size)) { 203 if (desc->num_pages == 0) 204 continue; 205 206 switch (desc->type) { 207 case EFI_LOADER_CODE: 208 case EFI_LOADER_DATA: 209 case EFI_BOOT_SERVICES_CODE: 210 case EFI_BOOT_SERVICES_DATA: 211 case EFI_CONVENTIONAL_MEMORY: 212 e820_type = E820_RAM; 213 break; 214 215 case EFI_RESERVED_MEMORY_TYPE: 216 case EFI_RUNTIME_SERVICES_CODE: 217 case EFI_RUNTIME_SERVICES_DATA: 218 case EFI_MMAP_IO: 219 case EFI_MMAP_IO_PORT: 220 case EFI_PAL_CODE: 221 e820_type = E820_RESERVED; 222 break; 223 224 case EFI_ACPI_RECLAIM_MEMORY: 225 e820_type = E820_ACPI; 226 break; 227 228 case EFI_ACPI_MEMORY_NVS: 229 e820_type = E820_NVS; 230 break; 231 232 case EFI_UNUSABLE_MEMORY: 233 e820_type = E820_UNUSABLE; 234 break; 235 236 default: 237 printf("Invalid EFI memory descriptor type (0x%x)!\n", 238 desc->type); 239 continue; 240 } 241 242 if (last_entry != NULL && last_entry->type == e820_type && 243 desc->physical_start == last_end_addr) { 244 last_entry->size += (desc->num_pages << EFI_PAGE_SHIFT); 245 last_end_addr += (desc->num_pages << EFI_PAGE_SHIFT); 246 } else { 247 if (num_entries >= E820MAX) 248 break; 249 250 entries[num_entries].addr = desc->physical_start; 251 entries[num_entries].size = desc->num_pages; 252 entries[num_entries].size <<= EFI_PAGE_SHIFT; 253 entries[num_entries].type = e820_type; 254 last_entry = &entries[num_entries]; 255 last_end_addr = last_entry->addr + last_entry->size; 256 num_entries++; 257 } 258 } 259 260 return num_entries; 261} 262 263void setup_efi_info(struct efi_info *efi_info) 264{ 265 struct efi_entry_systable *table; 266 struct efi_entry_memmap *map; 267 char *signature; 268 int size, ret; 269 270 memset(efi_info, 0, sizeof(struct efi_info)); 271 272 ret = efi_info_get(EFIET_SYS_TABLE, (void **)&table, &size); 273 if (ret) { 274 printf("Cannot find EFI system table, ret=%d\n", ret); 275 return; 276 } 277 efi_info->efi_systab = (u32)(table->sys_table); 278 279 ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size); 280 if (ret) { 281 printf("Cannot find EFI memory map tables, ret=%d\n", ret); 282 return; 283 } 284 efi_info->efi_memdesc_size = map->desc_size; 285 efi_info->efi_memdesc_version = map->version; 286 efi_info->efi_memmap = (ulong)(map->desc); 287 efi_info->efi_memmap_size = size - sizeof(struct efi_entry_memmap); 288 289#ifdef CONFIG_EFI_STUB_64BIT 290 efi_info->efi_systab_hi = table->sys_table >> 32; 291 efi_info->efi_memmap_hi = (u64)(ulong)map->desc >> 32; 292 signature = EFI64_LOADER_SIGNATURE; 293#else 294 signature = EFI32_LOADER_SIGNATURE; 295#endif 296 memcpy(&efi_info->efi_loader_signature, signature, 4); 297} 298 299void efi_show_bdinfo(void) 300{ 301 struct efi_entry_systable *table = NULL; 302 struct efi_system_table *sys_table; 303 int size, ret; 304 305 ret = efi_info_get(EFIET_SYS_TABLE, (void **)&table, &size); 306 if (!ret) { 307 bdinfo_print_num_l("efi_table", table->sys_table); 308 sys_table = (struct efi_system_table *)(uintptr_t) 309 table->sys_table; 310 bdinfo_print_num_l(" revision", sys_table->fw_revision); 311 } 312} 313