1 /*
2  * Copyright 2019 The Hafnium Authors.
3  *
4  * Use of this source code is governed by a BSD-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/BSD-3-Clause.
7  */
8 
9 #include "hf/cpio.h"
10 #include "hf/dlog.h"
11 #include "hf/fdt_handler.h"
12 #include "hf/fdt_patch.h"
13 #include "hf/plat/boot_flow.h"
14 #include "hf/std.h"
15 
16 /* Set by arch-specific boot-time hook. */
17 uintreg_t plat_boot_flow_fdt_addr;
18 
19 /**
20  * Returns the physical address of board FDT. This was passed to Hafnium in the
21  * first kernel arg by the boot loader.
22  */
plat_boot_flow_get_fdt_addr(void)23 paddr_t plat_boot_flow_get_fdt_addr(void)
24 {
25 	return pa_init((uintpaddr_t)plat_boot_flow_fdt_addr);
26 }
27 
28 /**
29  * When handing over to the primary, give it the same FDT address that was given
30  * to Hafnium. The FDT may have been modified during Hafnium init.
31  */
plat_boot_flow_get_kernel_arg(void)32 uintreg_t plat_boot_flow_get_kernel_arg(void)
33 {
34 	return plat_boot_flow_fdt_addr;
35 }
36 
37 /**
38  * Load initrd range from the board FDT.
39  */
plat_boot_flow_get_initrd_range(const struct fdt * fdt,paddr_t * begin,paddr_t * end)40 bool plat_boot_flow_get_initrd_range(const struct fdt *fdt, paddr_t *begin,
41 				     paddr_t *end)
42 {
43 	return fdt_find_initrd(fdt, begin, end);
44 }
45 
plat_boot_flow_update(struct mm_stage1_locked stage1_locked,const struct manifest * manifest,struct boot_params_update * update,struct memiter * cpio,struct mpool * ppool)46 bool plat_boot_flow_update(struct mm_stage1_locked stage1_locked,
47 			   const struct manifest *manifest,
48 			   struct boot_params_update *update,
49 			   struct memiter *cpio, struct mpool *ppool)
50 {
51 	struct memiter primary_initrd;
52 	const struct string *filename =
53 		&manifest->vm[HF_PRIMARY_VM_INDEX].primary.ramdisk_filename;
54 
55 	if (string_is_empty(filename)) {
56 		memiter_init(&primary_initrd, NULL, 0);
57 	} else if (!cpio_get_file(cpio, filename, &primary_initrd)) {
58 		dlog_error("Unable to find primary initrd \"%s\".\n",
59 			   string_data(filename));
60 		return false;
61 	}
62 
63 	update->initrd_begin = pa_from_va(va_from_ptr(primary_initrd.next));
64 	update->initrd_end = pa_from_va(va_from_ptr(primary_initrd.limit));
65 
66 	return fdt_patch(stage1_locked, plat_boot_flow_get_fdt_addr(), update,
67 			 ppool);
68 }
69