]> Git Repo - J-u-boot.git/blob - arch/arm/lib/save_prev_bl_data.c
Merge patch series "Complete decoupling of zboot logic from commands"
[J-u-boot.git] / arch / arm / lib / save_prev_bl_data.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * save_prev_bl_data - saving previous bootloader data
4  * to environment variables.
5  *
6  * Copyright (c) 2022 Dzmitry Sankouski ([email protected])
7  */
8 #include <init.h>
9 #include <env.h>
10 #include <fdtdec.h>
11 #include <fdt_support.h>
12 #include <fdt.h>
13 #include <common.h>
14 #include <linux/errno.h>
15 #include <asm/system.h>
16 #include <asm/armv8/mmu.h>
17
18 static ulong reg0 __section(".data");
19
20 /**
21  * Save x0 register value, assuming previous bootloader set it to
22  * point on loaded fdt or (for older linux kernels)atags.
23  */
24 void save_boot_params(ulong r0)
25 {
26         reg0 = r0;
27         save_boot_params_ret();
28 }
29
30 bool is_addr_accessible(phys_addr_t addr)
31 {
32         struct mm_region *mem = mem_map;
33         phys_addr_t bank_start;
34         phys_addr_t bank_end;
35
36         while (mem->size) {
37                 bank_start = mem->phys;
38                 bank_end = bank_start + mem->size;
39                 debug("check if block %pap - %pap includes %pap\n", &bank_start, &bank_end, &addr);
40                 if (addr > bank_start && addr < bank_end)
41                         return true;
42                 mem++;
43         }
44
45         return false;
46 }
47
48 phys_addr_t get_prev_bl_fdt_addr(void)
49 {
50         return reg0;
51 }
52
53 int save_prev_bl_data(void)
54 {
55         struct fdt_header *fdt_blob;
56         int node;
57         u64 initrd_start_prop;
58
59         if (!is_addr_accessible((phys_addr_t)reg0))
60                 return -ENODATA;
61
62         fdt_blob = (struct fdt_header *)reg0;
63         if (!fdt_valid(&fdt_blob)) {
64                 pr_warn("%s: address 0x%lx is not a valid fdt\n", __func__, reg0);
65                 return -ENODATA;
66         }
67
68         if (IS_ENABLED(CONFIG_SAVE_PREV_BL_FDT_ADDR))
69                 env_set_addr("prevbl_fdt_addr", (void *)reg0);
70         if (!IS_ENABLED(CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR))
71                 return 0;
72
73         node = fdt_path_offset(fdt_blob, "/chosen");
74         if (!node) {
75                 pr_warn("%s: chosen node not found in device tree at addr: 0x%lx\n",
76                                         __func__, reg0);
77                 return -ENODATA;
78         }
79         /*
80          * linux,initrd-start property might be either 64 or 32 bit,
81          * depending on primary bootloader implementation.
82          */
83         initrd_start_prop = fdtdec_get_uint64(fdt_blob, node, "linux,initrd-start", 0);
84         if (!initrd_start_prop) {
85                 debug("%s: attempt to get uint64 linux,initrd-start property failed, trying uint\n",
86                                 __func__);
87                 initrd_start_prop = fdtdec_get_uint(fdt_blob, node, "linux,initrd-start", 0);
88                 if (!initrd_start_prop) {
89                         debug("%s: attempt to get uint failed, too\n", __func__);
90                         return -ENODATA;
91                 }
92         }
93         env_set_addr("prevbl_initrd_start_addr", (void *)initrd_start_prop);
94
95         return 0;
96 }
This page took 0.037866 seconds and 4 git commands to generate.