1 // SPDX-License-Identifier: GPL-2.0
3 * Verified Boot for Embedded (VBE) loading firmware phases
5 * Copyright 2022 Google LLC
6 * Written by Simon Glass <sjg@chromium.org>
9 #define LOG_CATEGORY LOGC_BOOT
16 #include <bootstage.h>
25 #include <dm/device-internal.h>
26 #include "vbe_simple.h"
29 * vbe_simple_read_bootflow_fw() - Create a bootflow for firmware
31 * Locates and loads the firmware image (FIT) needed for the next phase. The FIT
32 * should ideally use external data, to reduce the amount of it that needs to be
35 * @bdev: bootdev device containing the firmwre
36 * @meth: VBE simple bootmeth
37 * @blow: Place to put the created bootflow, on success
38 * @return 0 if OK, -ve on error
40 int vbe_simple_read_bootflow_fw(struct udevice
*dev
, struct bootflow
*bflow
)
42 ALLOC_CACHE_ALIGN_BUFFER(u8
, sbuf
, MMC_MAX_BLOCK_LEN
);
43 struct udevice
*media
= dev_get_parent(bflow
->dev
);
44 struct udevice
*meth
= bflow
->method
;
45 struct simple_priv
*priv
= dev_get_priv(meth
);
46 const char *fit_uname
, *fit_uname_config
;
47 struct bootm_headers images
= {};
48 ulong offset
, size
, blknum
, addr
, len
, load_addr
, num_blks
;
49 enum image_phase_t phase
;
50 struct blk_desc
*desc
;
55 log_debug("media=%s\n", media
->name
);
56 ret
= blk_get_from_parent(media
, &blk
);
58 return log_msg_ret("med", ret
);
59 log_debug("blk=%s\n", blk
->name
);
60 desc
= dev_get_uclass_plat(blk
);
62 offset
= priv
->area_start
+ priv
->skip_offset
;
64 /* read in one block to find the FIT size */
65 blknum
= offset
/ desc
->blksz
;
66 log_debug("read at %lx, blknum %lx\n", offset
, blknum
);
67 ret
= blk_read(blk
, blknum
, 1, sbuf
);
69 return log_msg_ret("rd", ret
);
71 ret
= fdt_check_header(sbuf
);
73 return log_msg_ret("fdt", -EINVAL
);
74 size
= fdt_totalsize(sbuf
);
75 if (size
> priv
->area_size
)
76 return log_msg_ret("fdt", -E2BIG
);
77 log_debug("FIT size %lx\n", size
);
80 * Load the FIT into the SPL memory. This is typically a FIT with
81 * external data, so this is quite small, perhaps a few KB.
83 addr
= CONFIG_VAL(TEXT_BASE
);
84 buf
= map_sysmem(addr
, size
);
85 num_blks
= DIV_ROUND_UP(size
, desc
->blksz
);
86 log_debug("read %lx, %lx blocks to %lx / %p\n", size
, num_blks
, addr
,
88 ret
= blk_read(blk
, blknum
, num_blks
, buf
);
90 return log_msg_ret("rd", ret
);
92 /* figure out the phase to load */
93 phase
= IS_ENABLED(CONFIG_VPL_BUILD
) ? IH_PHASE_SPL
: IH_PHASE_U_BOOT
;
96 * Load the image from the FIT. We ignore any load-address information
97 * so in practice this simply locates the image in the external-data
98 * region and returns its address and size. Since we only loaded the FIT
99 * itself, only a part of the image will be present, at best.
102 fit_uname_config
= NULL
;
103 log_debug("loading FIT\n");
104 ret
= fit_image_load(&images
, addr
, &fit_uname
, &fit_uname_config
,
105 IH_ARCH_SANDBOX
, image_ph(phase
, IH_TYPE_FIRMWARE
),
106 BOOTSTAGE_ID_FIT_SPL_START
, FIT_LOAD_IGNORED
,
109 return log_msg_ret("ld", ret
);
111 log_debug("loaded to %lx\n", load_addr
);
113 /* For FIT external data, read in the external data */
114 if (load_addr
+ len
> addr
+ size
) {
115 ulong base
, full_size
;
118 /* Find the start address to load from */
119 base
= ALIGN_DOWN(load_addr
, desc
->blksz
);
122 * Get the total number of bytes to load, taking care of
125 full_size
= load_addr
+ len
- base
;
128 * Get the start block number, number of blocks and the address
129 * to load to, then load the blocks
131 blknum
= (offset
+ base
- addr
) / desc
->blksz
;
132 num_blks
= DIV_ROUND_UP(full_size
, desc
->blksz
);
133 base_buf
= map_sysmem(base
, full_size
);
134 ret
= blk_read(blk
, blknum
, num_blks
, base_buf
);
135 log_debug("read %lx %lx, %lx blocks to %lx / %p: ret=%d\n",
136 blknum
, full_size
, num_blks
, base
, base_buf
, ret
);
138 return log_msg_ret("rd", ret
);
141 /* set up the bootflow with the info we obtained */
142 bflow
->name
= strdup(fdt_get_name(buf
, node
, NULL
));
144 return log_msg_ret("name", -ENOMEM
);
146 bflow
->buf
= map_sysmem(load_addr
, len
);
152 static int simple_load_from_image(struct spl_image_info
*spl_image
,
153 struct spl_boot_device
*bootdev
)
155 struct udevice
*meth
, *bdev
;
156 struct simple_priv
*priv
;
157 struct bootflow bflow
;
158 struct vbe_handoff
*handoff
;
161 if (spl_phase() != PHASE_VPL
&& spl_phase() != PHASE_SPL
)
164 ret
= bloblist_ensure_size(BLOBLISTT_VBE
, sizeof(struct vbe_handoff
),
165 0, (void **)&handoff
);
167 return log_msg_ret("ro", ret
);
169 vbe_find_first_device(&meth
);
171 return log_msg_ret("vd", -ENODEV
);
172 log_debug("vbe dev %s\n", meth
->name
);
173 ret
= device_probe(meth
);
175 return log_msg_ret("probe", ret
);
177 priv
= dev_get_priv(meth
);
178 log_debug("simple %s\n", priv
->storage
);
179 ret
= bootdev_find_by_label(priv
->storage
, &bdev
, NULL
);
181 return log_msg_ret("bd", ret
);
182 log_debug("bootdev %s\n", bdev
->name
);
184 bootflow_init(&bflow
, bdev
, meth
);
185 ret
= bootmeth_read_bootflow(meth
, &bflow
);
186 log_debug("\nfw ret=%d\n", ret
);
188 return log_msg_ret("rd", ret
);
190 /* jump to the image */
191 spl_image
->flags
= SPL_SANDBOXF_ARG_IS_BUF
;
192 spl_image
->arg
= bflow
.buf
;
193 spl_image
->size
= bflow
.size
;
194 log_debug("Image: %s at %p size %x\n", bflow
.name
, bflow
.buf
,
197 /* this is not used from now on, so free it */
198 bootflow_free(&bflow
);
200 /* Record that VBE was used in this phase */
201 handoff
->phases
|= 1 << spl_phase();
205 SPL_LOAD_IMAGE_METHOD("vbe_simple", 5, BOOT_DEVICE_VBE
,
206 simple_load_from_image
);