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