1/*
2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7#include <autoconf.h>
8#include <elfloader/gen_config.h>
9
10#include <printf.h>
11#include <types.h>
12#include <abort.h>
13#include <strops.h>
14#include <binaries/elf/elf.h>
15#include <cpio/cpio.h>
16
17#include <elfloader.h>
18#include <fdt.h>
19
20#ifdef CONFIG_HASH_SHA
21#include "crypt_sha256.h"
22#elif CONFIG_HASH_MD5
23#include "crypt_md5.h"
24#endif
25
26#include "hash.h"
27
28#ifdef CONFIG_ELFLOADER_ROOTSERVERS_LAST
29#include <platform_info.h> // this provides memory_region
30#endif
31
32extern char _bss[];
33extern char _bss_end[];
34void clear_bss(void)
35{
36    char *start = _bss;
37    char *end = _bss_end;
38    while (start < end) {
39        *start = 0;
40        start++;
41    }
42}
43
44#define KEEP_HEADERS_SIZE BIT(PAGE_BITS)
45
46/* Determine if two intervals overlap. */
47static int regions_overlap(uintptr_t startA, uintptr_t endA,
48                           uintptr_t startB, uintptr_t endB)
49{
50    if (endA < startB) {
51        return 0;
52    }
53    if (endB < startA) {
54        return 0;
55    }
56    return 1;
57}
58
59/*
60 * Ensure that we are able to use the given physical memory range.
61 *
62 * We abort if the destination physical range overlaps us, or if it
63 * goes outside the bounds of memory.
64 */
65static void ensure_phys_range_valid(char const *const name, paddr_t paddr_min,
66                                    paddr_t paddr_max)
67{
68    /*
69     * Ensure that the physical load address of the object we're loading (called
70     * `name`) doesn't overwrite us.
71     */
72    if (regions_overlap(paddr_min, paddr_max - 1, (word_t)_text, (word_t)_end - 1)) {
73        printf("%s load address would overlap ELF-loader!\n", name);
74        abort();
75    }
76}
77
78/*
79 * Unpack an ELF file to the given physical address.
80 */
81static void unpack_elf_to_paddr(void *elf, paddr_t dest_paddr)
82{
83    uint16_t i;
84    uint64_t min_vaddr, max_vaddr;
85    size_t image_size;
86
87    word_t phys_virt_offset;
88
89    /* Get size of the image. */
90    elf_getMemoryBounds(elf, 0, &min_vaddr, &max_vaddr);
91    image_size = (size_t)(max_vaddr - min_vaddr);
92    phys_virt_offset = dest_paddr - (paddr_t)min_vaddr;
93
94    /* Zero out all memory in the region, as the ELF file may be sparse. */
95    memset((char *)dest_paddr, 0, image_size);
96
97    /* Load each segment in the ELF file. */
98    for (i = 0; i < elf_getNumProgramHeaders(elf); i++) {
99        vaddr_t dest_vaddr;
100        size_t data_size, data_offset;
101
102        /* Skip segments that are not marked as being loadable. */
103        if (elf_getProgramHeaderType(elf, i) != PT_LOAD) {
104            continue;
105        }
106
107        /* Parse size/length headers. */
108        dest_vaddr = elf_getProgramHeaderVaddr(elf, i);
109        data_size = elf_getProgramHeaderFileSize(elf, i);
110        data_offset = elf_getProgramHeaderOffset(elf, i);
111
112        /* Load data into memory. */
113        memcpy((char *)dest_vaddr + phys_virt_offset,
114               (char *)elf + data_offset, data_size);
115    }
116}
117
118static size_t rounded_image_size(void *elf, uint64_t *min_vaddr, uint64_t *max_vaddr)
119{
120    elf_getMemoryBounds(elf, 0, min_vaddr, max_vaddr);
121    *max_vaddr = ROUND_UP(*max_vaddr, PAGE_BITS);
122    return (size_t)(*max_vaddr - *min_vaddr);
123}
124
125/*
126 * Load an ELF file into physical memory at the given physical address.
127 *
128 * Return the byte past the last byte of the physical address used.
129 */
130static paddr_t load_elf(const char *name, void *elf, paddr_t dest_paddr,
131                        struct image_info *info, int keep_headers,
132                        __attribute__((unused)) unsigned long size,
133                        __attribute__((unused)) const char *hash)
134{
135    uint64_t min_vaddr, max_vaddr;
136    /* Fetch image info. */
137    size_t image_size = rounded_image_size(elf, &min_vaddr, &max_vaddr);
138
139    /* Ensure our starting physical address is aligned. */
140    if (!IS_ALIGNED(dest_paddr, PAGE_BITS)) {
141        printf("Attempting to load ELF at unaligned physical address!\n");
142        abort();
143    }
144
145    /* Ensure that the ELF file itself is 4-byte aligned in memory, so that
146     * libelf can perform word accesses on it. */
147    if (!IS_ALIGNED(dest_paddr, 2)) {
148        printf("Input ELF file not 4-byte aligned in memory!\n");
149        abort();
150    }
151
152#ifndef CONFIG_HASH_NONE
153
154    /* Get the binary file that contains the SHA256 Hash */
155    unsigned long unused;
156    unsigned long cpio_len = _archive_start_end - _archive_start;
157    void *file_hash = cpio_get_file(_archive_start, cpio_len, (const char *)hash, &unused);
158    uint8_t *print_hash_pointer = (uint8_t *)file_hash;
159
160    /* If the file hash doesn't have a pointer, the file doesn't exist, so we cannot confirm the file is what we expect. Abort */
161    if (file_hash == NULL) {
162        printf("Cannot compare hashes for %s, expected hash, %s, doesn't exist\n", name, hash);
163        abort();
164    } else {
165
166        hashes_t hashes;
167
168#ifdef CONFIG_HASH_SHA
169        int hash_len = 32;
170        hashes.hash_type = SHA_256;
171#else
172        int hash_len = 16;
173        hashes.hash_type = MD5;
174#endif
175
176        uint8_t calculated_hash[hash_len];
177
178        /* Print the Hash for the user to see */
179        printf("Hash from ELF File: ");
180        print_hash(print_hash_pointer, hash_len);
181
182        get_hash(hashes, elf, size, calculated_hash);
183
184        /* Print the hash so the user can see they're the same or different */
185        printf("Hash for ELF Input: ");
186        print_hash(calculated_hash, hash_len);
187
188        /* Check to make sure the hashes are the same */
189        if (strncmp((char *)file_hash, (char *)calculated_hash, hash_len) != 0) {
190            printf("Hashes are different. Load failure\n");
191            abort();
192        }
193    }
194
195#endif  /* CONFIG_HASH_NONE */
196
197    /* Print diagnostics. */
198    printf("ELF-loading image '%s'\n", name);
199    printf("  paddr=[%lx..%lx]\n", dest_paddr, dest_paddr + image_size - 1);
200    printf("  vaddr=[%lx..%lx]\n", (vaddr_t)min_vaddr, (vaddr_t)max_vaddr - 1);
201    printf("  virt_entry=%lx\n", (vaddr_t)elf_getEntryPoint(elf));
202
203    /* Ensure the ELF file is valid. */
204    if (elf_checkFile(elf) != 0) {
205        printf("Attempting to load invalid ELF file '%s'.\n", name);
206        abort();
207    }
208
209    /* Ensure sane alignment of the image. */
210    if (!IS_ALIGNED(min_vaddr, PAGE_BITS)) {
211        printf("Start of image '%s' is not 4K-aligned!\n", name);
212        abort();
213    }
214
215    /* Ensure that we region we want to write to is sane. */
216    ensure_phys_range_valid(name, dest_paddr, dest_paddr + image_size);
217
218    /* Copy the data. */
219    unpack_elf_to_paddr(elf, dest_paddr);
220
221    /* Record information about the placement of the image. */
222    info->phys_region_start = dest_paddr;
223    info->phys_region_end = dest_paddr + image_size;
224    info->virt_region_start = (vaddr_t)min_vaddr;
225    info->virt_region_end = (vaddr_t)max_vaddr;
226    info->virt_entry = (vaddr_t)elf_getEntryPoint(elf);
227    info->phys_virt_offset = dest_paddr - (vaddr_t)min_vaddr;
228
229    /* Round up the destination address to the next page */
230    dest_paddr = ROUND_UP(dest_paddr + image_size, PAGE_BITS);
231
232    if (keep_headers) {
233        /* Put the ELF headers in this page */
234        uint32_t phnum = elf_getNumProgramHeaders(elf);
235        uint32_t phsize;
236        paddr_t source_paddr;
237        if (ISELF32(elf)) {
238            phsize = ((struct Elf32_Header *)elf)->e_phentsize;
239            source_paddr = (paddr_t)elf32_getProgramHeaderTable(elf);
240        } else {
241            phsize = ((struct Elf64_Header *)elf)->e_phentsize;
242            source_paddr = (paddr_t)elf64_getProgramHeaderTable(elf);
243        }
244        /* We have no way of sharing definitions with the kernel so we just
245         * memcpy to a bunch of magic offsets. Explicit numbers for sizes
246         * and offsets are used so that it is clear exactly what the layout
247         * is */
248        memcpy((void *)dest_paddr, &phnum, 4);
249        memcpy((void *)(dest_paddr + 4), &phsize, 4);
250        memcpy((void *)(dest_paddr + 8), (void *)source_paddr, phsize * phnum);
251        /* return the frame after our headers */
252        dest_paddr += KEEP_HEADERS_SIZE;
253    }
254    return dest_paddr;
255}
256
257/*
258 * ELF-loader for ARM systems.
259 *
260 * We are currently running out of physical memory, with an ELF file for the
261 * kernel and one or more ELF files for the userspace image. (Typically there
262 * will only be one userspace ELF file, though if we are running a multi-core
263 * CPU, we may have multiple userspace images; one per CPU.) These ELF files
264 * are packed into an 'ar' archive.
265 *
266 * The kernel ELF file indicates what physical address it wants to be loaded
267 * at, while userspace images run out of virtual memory, so don't have any
268 * requirements about where they are located. We place the kernel at its
269 * desired location, and then load userspace images straight after it in
270 * physical memory.
271 *
272 * Several things could possibly go wrong:
273 *
274 *  1. The physical load address of the kernel might want to overwrite this
275 *  ELF-loader;
276 *
277 *  2. The physical load addresses of the kernel might not actually be in
278 *  physical memory;
279 *
280 *  3. Userspace images may not fit in physical memory, or may try to overlap
281 *  the ELF-loader.
282 *
283 *  We attempt to check for some of these, but some may go unnoticed.
284 */
285void load_images(struct image_info *kernel_info, struct image_info *user_info,
286                 int max_user_images, int *num_images, void *bootloader_dtb, void **chosen_dtb,
287                 uint32_t *chosen_dtb_size)
288{
289    int i;
290    uint64_t kernel_phys_start, kernel_phys_end;
291    uintptr_t dtb_phys_start, dtb_phys_end;
292    paddr_t next_phys_addr;
293    const char *elf_filename;
294    unsigned long unused;
295    unsigned long kernel_filesize;
296    int has_dtb_cpio = 0;
297
298    /* Load kernel. */
299    unsigned long cpio_len = _archive_start_end - _archive_start;
300    void *kernel_elf = cpio_get_file(_archive_start, cpio_len, "kernel.elf", &kernel_filesize);
301    if (kernel_elf == NULL) {
302        printf("No kernel image present in archive!\n");
303        abort();
304    }
305    if (elf_checkFile(kernel_elf)) {
306        printf("Kernel image not a valid ELF file!\n");
307        abort();
308    }
309
310    elf_getMemoryBounds(kernel_elf, 1, &kernel_phys_start, &kernel_phys_end);
311
312    void *dtb = NULL;
313#ifdef CONFIG_ELFLOADER_INCLUDE_DTB
314    if (chosen_dtb) {
315        printf("Looking for DTB in CPIO archive...");
316        /*
317         * Note the lack of newline in the above printf().  Normally one would
318         * have an fflush(stdout) here to ensure that the message shows up on a
319         * line-buffered stream (which is the POSIX default on terminal
320         * devices).  But we are freestanding (on the "bare metal"), and using
321         * our own unbuffered printf() implementation.
322         */
323        dtb = cpio_get_file(_archive_start, cpio_len, "kernel.dtb", &unused);
324        if (dtb == NULL) {
325            printf("not found.\n");
326        } else {
327            has_dtb_cpio = 1;
328            printf("found at %p.\n", dtb);
329        }
330    }
331#endif
332
333    if (chosen_dtb && !dtb && bootloader_dtb) {
334        /* Use the bootloader's DTB if we are not using the DTB in the CPIO archive. */
335        dtb = bootloader_dtb;
336    }
337
338    /*
339     * Move the DTB out of the way, if it's present.
340     */
341    if (dtb) {
342        /* keep it page aligned */
343        next_phys_addr = dtb_phys_start = ROUND_UP(kernel_phys_end, PAGE_BITS);
344
345        *chosen_dtb_size = fdt_size(dtb);
346        if (!*chosen_dtb_size) {
347            printf("Invalid device tree blob supplied!\n");
348            abort();
349        }
350
351        /* Make sure this is a sane thing to do */
352        ensure_phys_range_valid("DTB", next_phys_addr,
353                                next_phys_addr + *chosen_dtb_size);
354
355        memmove((void *)next_phys_addr, dtb, *chosen_dtb_size);
356        next_phys_addr += *chosen_dtb_size;
357        next_phys_addr = ROUND_UP(next_phys_addr, PAGE_BITS);
358        dtb_phys_end = next_phys_addr;
359
360        printf("Loaded DTB from %p.\n", dtb);
361        printf("   paddr=[%lx..%lx]\n", dtb_phys_start, dtb_phys_end - 1);
362        *chosen_dtb = (void *)dtb_phys_start;
363    } else {
364        next_phys_addr = ROUND_UP(kernel_phys_end, PAGE_BITS);
365    }
366    load_elf("kernel", kernel_elf,
367             (paddr_t)kernel_phys_start, kernel_info, 0, kernel_filesize, "kernel.bin");
368
369    /*
370     * Load userspace images.
371     *
372     * We assume (and check) that the kernel is the first file in the archive,
373     * that the DTB is the second if present,
374     * and then load the (n+user_elf_offset)'th file in the archive onto the (n)'th CPU.
375     */
376    int user_elf_offset = 2;
377    cpio_get_entry(_archive_start, cpio_len, 0, &elf_filename, &unused);
378    if (strcmp(elf_filename, "kernel.elf") != 0) {
379        printf("Kernel image not first image in archive.\n");
380        abort();
381    }
382    cpio_get_entry(_archive_start, cpio_len, 1, &elf_filename, &unused);
383    if (strcmp(elf_filename, "kernel.dtb") != 0) {
384        if (has_dtb_cpio) {
385            printf("Kernel DTB not second image in archive.\n");
386            abort();
387        }
388        user_elf_offset = 1;
389    }
390
391#ifdef CONFIG_ELFLOADER_ROOTSERVERS_LAST
392    /* work out the size of the user images - this corresponds to how much memory
393     * load_elf uses */
394    int total_user_image_size = 0;
395    for (i = 0; i < max_user_images; i++) {
396        void *user_elf = cpio_get_entry(_archive_start, cpio_len, i + user_elf_offset,
397                                        &elf_filename, &unused);
398        uint64_t min_vaddr, max_vaddr;
399        total_user_image_size += rounded_image_size(user_elf, &min_vaddr, &max_vaddr);
400
401        total_user_image_size += KEEP_HEADERS_SIZE;
402    }
403
404    /* work out where to place the user image */
405
406    next_phys_addr = ROUND_DOWN(memory_region[0].end, PAGE_BITS) - ROUND_UP(total_user_image_size, PAGE_BITS);
407#endif /* CONFIG_ELFLOADER_ROOTSERVERS_LAST */
408
409    *num_images = 0;
410    for (i = 0; i < max_user_images; i++) {
411        /* Fetch info about the next ELF file in the archive. */
412        void *user_elf = cpio_get_entry(_archive_start, cpio_len, i + user_elf_offset,
413                                        &elf_filename, &unused);
414        if (user_elf == NULL) {
415            break;
416        }
417
418        /* Load the file into memory. */
419        next_phys_addr = load_elf(elf_filename, user_elf,
420                                  next_phys_addr, &user_info[*num_images], 1, unused, "app.bin");
421        *num_images = i + 1;
422    }
423}
424
425void __attribute__((weak)) platform_init(void) {}
426