]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
8e366508 SG |
2 | /* |
3 | * Copyright (c) 2015 Google, Inc | |
4 | * Written by Simon Glass <sjg@chromium.org> | |
8e366508 SG |
5 | */ |
6 | ||
d678a59d | 7 | #include <common.h> |
30c7c434 | 8 | #include <cpu_func.h> |
8e366508 | 9 | #include <efi.h> |
40b17231 | 10 | #include <efi_api.h> |
8e366508 | 11 | #include <errno.h> |
91caa3bb | 12 | #include <event.h> |
67c4e9f8 | 13 | #include <init.h> |
f7ae49fc | 14 | #include <log.h> |
1ab2c010 | 15 | #include <usb.h> |
1fdeacd3 | 16 | #include <asm/bootparam.h> |
aac79251 | 17 | #include <asm/e820.h> |
401d1c4f | 18 | #include <asm/global_data.h> |
3773c6a2 | 19 | #include <asm/post.h> |
8e366508 SG |
20 | |
21 | DECLARE_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 | */ | |
d768dd88 | 31 | phys_addr_t board_get_usable_ram_top(phys_size_t total_size) |
8e366508 SG |
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; | |
ce1dc0cc | 55 | for (; desc < end; desc = efi_get_next_mem_desc(desc, map->desc_size)) { |
8e366508 SG |
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; | |
72 | err: | |
73 | panic("No available memory found for relocation"); | |
74 | return 0; | |
75 | } | |
76 | ||
77 | int 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; | |
ce1dc0cc | 93 | for (; desc < end; desc = efi_get_next_mem_desc(desc, map->desc_size)) { |
8e366508 SG |
94 | if (desc->type < EFI_MMAP_IO) |
95 | gd->ram_size += desc->num_pages << EFI_PAGE_SHIFT; | |
96 | } | |
97 | ||
98 | return 0; | |
99 | } | |
100 | ||
76b00aca | 101 | int dram_init_banksize(void) |
8e366508 SG |
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__); | |
76b00aca | 112 | return -ENXIO; |
8e366508 SG |
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; | |
ce1dc0cc | 118 | desc = efi_get_next_mem_desc(desc, map->desc_size)) { |
8e366508 | 119 | /* |
59837472 | 120 | * We only use conventional memory and ignore |
8e366508 SG |
121 | * anything less than 1MB. |
122 | */ | |
123 | if (desc->type != EFI_CONVENTIONAL_MEMORY || | |
8e366508 SG |
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 | } | |
76b00aca SG |
131 | |
132 | return 0; | |
8e366508 SG |
133 | } |
134 | ||
3773c6a2 BM |
135 | int arch_cpu_init(void) |
136 | { | |
137 | post_code(POST_CPU_INIT); | |
138 | ||
139 | return x86_cpu_init_f(); | |
140 | } | |
141 | ||
76d1d02f SG |
142 | int checkcpu(void) |
143 | { | |
144 | return 0; | |
145 | } | |
146 | ||
8e366508 SG |
147 | int print_cpuinfo(void) |
148 | { | |
149 | return default_print_cpuinfo(); | |
150 | } | |
151 | ||
152 | /* Find any available tables and copy them to a safe place */ | |
153 | int 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 | } | |
1ab2c010 | 171 | |
91caa3bb | 172 | static int last_stage_init(void) |
1ab2c010 BM |
173 | { |
174 | /* start usb so that usb keyboard can be used as input device */ | |
91b614ee | 175 | if (IS_ENABLED(CONFIG_USB_KEYBOARD)) |
d3d65318 | 176 | usb_init(); |
1ab2c010 BM |
177 | |
178 | return 0; | |
179 | } | |
91caa3bb | 180 | EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, last_stage_init); |
aac79251 BM |
181 | |
182 | unsigned 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; | |
ce1dc0cc | 202 | desc = efi_get_next_mem_desc(desc, map->desc_size)) { |
aac79251 BM |
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 | } | |
1fdeacd3 BM |
262 | |
263 | void 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; | |
567dfef2 | 286 | efi_info->efi_memmap = (ulong)(map->desc); |
1fdeacd3 BM |
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; | |
567dfef2 | 291 | efi_info->efi_memmap_hi = (u64)(ulong)map->desc >> 32; |
1fdeacd3 BM |
292 | signature = EFI64_LOADER_SIGNATURE; |
293 | #else | |
294 | signature = EFI32_LOADER_SIGNATURE; | |
295 | #endif | |
296 | memcpy(&efi_info->efi_loader_signature, signature, 4); | |
297 | } | |
567dfef2 SG |
298 | |
299 | void efi_show_bdinfo(void) | |
300 | { | |
301 | struct efi_entry_systable *table = NULL; | |
40b17231 | 302 | struct efi_system_table *sys_table; |
567dfef2 SG |
303 | int size, ret; |
304 | ||
305 | ret = efi_info_get(EFIET_SYS_TABLE, (void **)&table, &size); | |
40b17231 SG |
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 | } | |
567dfef2 | 312 | } |