Merge branches 'device-properties' and 'acpi-misc'
[cascardo/linux.git] / drivers / firmware / efi / libstub / fdt.c
1 /*
2  * FDT related Helper functions used by the EFI stub on multiple
3  * architectures. This should be #included by the EFI stub
4  * implementation files.
5  *
6  * Copyright 2013 Linaro Limited; author Roy Franz
7  *
8  * This file is part of the Linux kernel, and is made available
9  * under the terms of the GNU General Public License version 2.
10  *
11  */
12
13 #include <linux/efi.h>
14 #include <linux/libfdt.h>
15 #include <asm/efi.h>
16
17 #include "efistub.h"
18
19 efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
20                         unsigned long orig_fdt_size,
21                         void *fdt, int new_fdt_size, char *cmdline_ptr,
22                         u64 initrd_addr, u64 initrd_size,
23                         efi_memory_desc_t *memory_map,
24                         unsigned long map_size, unsigned long desc_size,
25                         u32 desc_ver)
26 {
27         int node, num_rsv;
28         int status;
29         u32 fdt_val32;
30         u64 fdt_val64;
31
32         /* Do some checks on provided FDT, if it exists*/
33         if (orig_fdt) {
34                 if (fdt_check_header(orig_fdt)) {
35                         pr_efi_err(sys_table, "Device Tree header not valid!\n");
36                         return EFI_LOAD_ERROR;
37                 }
38                 /*
39                  * We don't get the size of the FDT if we get if from a
40                  * configuration table.
41                  */
42                 if (orig_fdt_size && fdt_totalsize(orig_fdt) > orig_fdt_size) {
43                         pr_efi_err(sys_table, "Truncated device tree! foo!\n");
44                         return EFI_LOAD_ERROR;
45                 }
46         }
47
48         if (orig_fdt)
49                 status = fdt_open_into(orig_fdt, fdt, new_fdt_size);
50         else
51                 status = fdt_create_empty_tree(fdt, new_fdt_size);
52
53         if (status != 0)
54                 goto fdt_set_fail;
55
56         /*
57          * Delete all memory reserve map entries. When booting via UEFI,
58          * kernel will use the UEFI memory map to find reserved regions.
59          */
60         num_rsv = fdt_num_mem_rsv(fdt);
61         while (num_rsv-- > 0)
62                 fdt_del_mem_rsv(fdt, num_rsv);
63
64         node = fdt_subnode_offset(fdt, 0, "chosen");
65         if (node < 0) {
66                 node = fdt_add_subnode(fdt, 0, "chosen");
67                 if (node < 0) {
68                         status = node; /* node is error code when negative */
69                         goto fdt_set_fail;
70                 }
71         }
72
73         if ((cmdline_ptr != NULL) && (strlen(cmdline_ptr) > 0)) {
74                 status = fdt_setprop(fdt, node, "bootargs", cmdline_ptr,
75                                      strlen(cmdline_ptr) + 1);
76                 if (status)
77                         goto fdt_set_fail;
78         }
79
80         /* Set initrd address/end in device tree, if present */
81         if (initrd_size != 0) {
82                 u64 initrd_image_end;
83                 u64 initrd_image_start = cpu_to_fdt64(initrd_addr);
84
85                 status = fdt_setprop(fdt, node, "linux,initrd-start",
86                                      &initrd_image_start, sizeof(u64));
87                 if (status)
88                         goto fdt_set_fail;
89                 initrd_image_end = cpu_to_fdt64(initrd_addr + initrd_size);
90                 status = fdt_setprop(fdt, node, "linux,initrd-end",
91                                      &initrd_image_end, sizeof(u64));
92                 if (status)
93                         goto fdt_set_fail;
94         }
95
96         /* Add FDT entries for EFI runtime services in chosen node. */
97         node = fdt_subnode_offset(fdt, 0, "chosen");
98         fdt_val64 = cpu_to_fdt64((u64)(unsigned long)sys_table);
99         status = fdt_setprop(fdt, node, "linux,uefi-system-table",
100                              &fdt_val64, sizeof(fdt_val64));
101         if (status)
102                 goto fdt_set_fail;
103
104         fdt_val64 = cpu_to_fdt64((u64)(unsigned long)memory_map);
105         status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
106                              &fdt_val64,  sizeof(fdt_val64));
107         if (status)
108                 goto fdt_set_fail;
109
110         fdt_val32 = cpu_to_fdt32(map_size);
111         status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
112                              &fdt_val32,  sizeof(fdt_val32));
113         if (status)
114                 goto fdt_set_fail;
115
116         fdt_val32 = cpu_to_fdt32(desc_size);
117         status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
118                              &fdt_val32, sizeof(fdt_val32));
119         if (status)
120                 goto fdt_set_fail;
121
122         fdt_val32 = cpu_to_fdt32(desc_ver);
123         status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
124                              &fdt_val32, sizeof(fdt_val32));
125         if (status)
126                 goto fdt_set_fail;
127
128         if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
129                 efi_status_t efi_status;
130
131                 efi_status = efi_get_random_bytes(sys_table, sizeof(fdt_val64),
132                                                   (u8 *)&fdt_val64);
133                 if (efi_status == EFI_SUCCESS) {
134                         status = fdt_setprop(fdt, node, "kaslr-seed",
135                                              &fdt_val64, sizeof(fdt_val64));
136                         if (status)
137                                 goto fdt_set_fail;
138                 } else if (efi_status != EFI_NOT_FOUND) {
139                         return efi_status;
140                 }
141         }
142         return EFI_SUCCESS;
143
144 fdt_set_fail:
145         if (status == -FDT_ERR_NOSPACE)
146                 return EFI_BUFFER_TOO_SMALL;
147
148         return EFI_LOAD_ERROR;
149 }
150
151 #ifndef EFI_FDT_ALIGN
152 #define EFI_FDT_ALIGN EFI_PAGE_SIZE
153 #endif
154
155 struct exit_boot_struct {
156         efi_memory_desc_t *runtime_map;
157         int *runtime_entry_count;
158 };
159
160 static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
161                                    struct efi_boot_memmap *map,
162                                    void *priv)
163 {
164         struct exit_boot_struct *p = priv;
165         /*
166          * Update the memory map with virtual addresses. The function will also
167          * populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME
168          * entries so that we can pass it straight to SetVirtualAddressMap()
169          */
170         efi_get_virtmap(*map->map, *map->map_size, *map->desc_size,
171                         p->runtime_map, p->runtime_entry_count);
172
173         return EFI_SUCCESS;
174 }
175
176 /*
177  * Allocate memory for a new FDT, then add EFI, commandline, and
178  * initrd related fields to the FDT.  This routine increases the
179  * FDT allocation size until the allocated memory is large
180  * enough.  EFI allocations are in EFI_PAGE_SIZE granules,
181  * which are fixed at 4K bytes, so in most cases the first
182  * allocation should succeed.
183  * EFI boot services are exited at the end of this function.
184  * There must be no allocations between the get_memory_map()
185  * call and the exit_boot_services() call, so the exiting of
186  * boot services is very tightly tied to the creation of the FDT
187  * with the final memory map in it.
188  */
189
190 efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
191                                             void *handle,
192                                             unsigned long *new_fdt_addr,
193                                             unsigned long max_addr,
194                                             u64 initrd_addr, u64 initrd_size,
195                                             char *cmdline_ptr,
196                                             unsigned long fdt_addr,
197                                             unsigned long fdt_size)
198 {
199         unsigned long map_size, desc_size, buff_size;
200         u32 desc_ver;
201         unsigned long mmap_key;
202         efi_memory_desc_t *memory_map, *runtime_map;
203         unsigned long new_fdt_size;
204         efi_status_t status;
205         int runtime_entry_count = 0;
206         struct efi_boot_memmap map;
207         struct exit_boot_struct priv;
208
209         map.map =       &runtime_map;
210         map.map_size =  &map_size;
211         map.desc_size = &desc_size;
212         map.desc_ver =  &desc_ver;
213         map.key_ptr =   &mmap_key;
214         map.buff_size = &buff_size;
215
216         /*
217          * Get a copy of the current memory map that we will use to prepare
218          * the input for SetVirtualAddressMap(). We don't have to worry about
219          * subsequent allocations adding entries, since they could not affect
220          * the number of EFI_MEMORY_RUNTIME regions.
221          */
222         status = efi_get_memory_map(sys_table, &map);
223         if (status != EFI_SUCCESS) {
224                 pr_efi_err(sys_table, "Unable to retrieve UEFI memory map.\n");
225                 return status;
226         }
227
228         pr_efi(sys_table,
229                "Exiting boot services and installing virtual address map...\n");
230
231         map.map = &memory_map;
232         /*
233          * Estimate size of new FDT, and allocate memory for it. We
234          * will allocate a bigger buffer if this ends up being too
235          * small, so a rough guess is OK here.
236          */
237         new_fdt_size = fdt_size + EFI_PAGE_SIZE;
238         while (1) {
239                 status = efi_high_alloc(sys_table, new_fdt_size, EFI_FDT_ALIGN,
240                                         new_fdt_addr, max_addr);
241                 if (status != EFI_SUCCESS) {
242                         pr_efi_err(sys_table, "Unable to allocate memory for new device tree.\n");
243                         goto fail;
244                 }
245
246                 /*
247                  * Now that we have done our final memory allocation (and free)
248                  * we can get the memory map key  needed for
249                  * exit_boot_services().
250                  */
251                 status = efi_get_memory_map(sys_table, &map);
252                 if (status != EFI_SUCCESS)
253                         goto fail_free_new_fdt;
254
255                 status = update_fdt(sys_table,
256                                     (void *)fdt_addr, fdt_size,
257                                     (void *)*new_fdt_addr, new_fdt_size,
258                                     cmdline_ptr, initrd_addr, initrd_size,
259                                     memory_map, map_size, desc_size, desc_ver);
260
261                 /* Succeeding the first time is the expected case. */
262                 if (status == EFI_SUCCESS)
263                         break;
264
265                 if (status == EFI_BUFFER_TOO_SMALL) {
266                         /*
267                          * We need to allocate more space for the new
268                          * device tree, so free existing buffer that is
269                          * too small.  Also free memory map, as we will need
270                          * to get new one that reflects the free/alloc we do
271                          * on the device tree buffer.
272                          */
273                         efi_free(sys_table, new_fdt_size, *new_fdt_addr);
274                         sys_table->boottime->free_pool(memory_map);
275                         new_fdt_size += EFI_PAGE_SIZE;
276                 } else {
277                         pr_efi_err(sys_table, "Unable to construct new device tree.\n");
278                         goto fail_free_mmap;
279                 }
280         }
281
282         sys_table->boottime->free_pool(memory_map);
283         priv.runtime_map = runtime_map;
284         priv.runtime_entry_count = &runtime_entry_count;
285         status = efi_exit_boot_services(sys_table, handle, &map, &priv,
286                                         exit_boot_func);
287
288         if (status == EFI_SUCCESS) {
289                 efi_set_virtual_address_map_t *svam;
290
291                 /* Install the new virtual address map */
292                 svam = sys_table->runtime->set_virtual_address_map;
293                 status = svam(runtime_entry_count * desc_size, desc_size,
294                               desc_ver, runtime_map);
295
296                 /*
297                  * We are beyond the point of no return here, so if the call to
298                  * SetVirtualAddressMap() failed, we need to signal that to the
299                  * incoming kernel but proceed normally otherwise.
300                  */
301                 if (status != EFI_SUCCESS) {
302                         int l;
303
304                         /*
305                          * Set the virtual address field of all
306                          * EFI_MEMORY_RUNTIME entries to 0. This will signal
307                          * the incoming kernel that no virtual translation has
308                          * been installed.
309                          */
310                         for (l = 0; l < map_size; l += desc_size) {
311                                 efi_memory_desc_t *p = (void *)memory_map + l;
312
313                                 if (p->attribute & EFI_MEMORY_RUNTIME)
314                                         p->virt_addr = 0;
315                         }
316                 }
317                 return EFI_SUCCESS;
318         }
319
320         pr_efi_err(sys_table, "Exit boot services failed.\n");
321
322 fail_free_mmap:
323         sys_table->boottime->free_pool(memory_map);
324
325 fail_free_new_fdt:
326         efi_free(sys_table, new_fdt_size, *new_fdt_addr);
327
328 fail:
329         sys_table->boottime->free_pool(runtime_map);
330         return EFI_LOAD_ERROR;
331 }
332
333 void *get_fdt(efi_system_table_t *sys_table, unsigned long *fdt_size)
334 {
335         efi_guid_t fdt_guid = DEVICE_TREE_GUID;
336         efi_config_table_t *tables;
337         void *fdt;
338         int i;
339
340         tables = (efi_config_table_t *) sys_table->tables;
341         fdt = NULL;
342
343         for (i = 0; i < sys_table->nr_tables; i++)
344                 if (efi_guidcmp(tables[i].guid, fdt_guid) == 0) {
345                         fdt = (void *) tables[i].table;
346                         if (fdt_check_header(fdt) != 0) {
347                                 pr_efi_err(sys_table, "Invalid header detected on UEFI supplied FDT, ignoring ...\n");
348                                 return NULL;
349                         }
350                         *fdt_size = fdt_totalsize(fdt);
351                         break;
352          }
353
354         return fdt;
355 }