blob: cb5534fc7314c047979a3ff144e34f2aa8b96fa7 [file] [log] [blame]
Simon Glassd78aa752022-10-20 18:23:10 -06001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Verified Boot for Embedded (VBE) loading firmware phases
4 *
5 * Copyright 2022 Google LLC
6 * Written by Simon Glass <sjg@chromium.org>
7 */
8
9#define LOG_CATEGORY LOGC_BOOT
10
Simon Glass0fcc6c42025-01-15 18:27:23 -070011#include <binman_sym.h>
Simon Glass9d0042e2022-10-20 18:23:18 -060012#include <bloblist.h>
Simon Glassd78aa752022-10-20 18:23:10 -060013#include <bootdev.h>
14#include <bootflow.h>
15#include <bootmeth.h>
16#include <bootstage.h>
17#include <dm.h>
18#include <image.h>
19#include <log.h>
20#include <mapmem.h>
Simon Glassd78aa752022-10-20 18:23:10 -060021#include <mmc.h>
22#include <spl.h>
23#include <vbe.h>
24#include <dm/device-internal.h>
Simon Glass0fcc6c42025-01-15 18:27:23 -070025#include "vbe_common.h"
Simon Glassd78aa752022-10-20 18:23:10 -060026#include "vbe_simple.h"
27
Simon Glass0fcc6c42025-01-15 18:27:23 -070028#ifdef CONFIG_BOOTMETH_VBE_SIMPLE
29binman_sym_extern(ulong, vbe_a, image_pos);
30binman_sym_extern(ulong, vbe_a, size);
31#else
32binman_sym_declare(ulong, vbe_a, image_pos);
33binman_sym_declare(ulong, vbe_a, size);
34#endif
35
36binman_sym_declare(ulong, vpl, image_pos);
37binman_sym_declare(ulong, vpl, size);
38
Simon Glassd78aa752022-10-20 18:23:10 -060039/**
40 * vbe_simple_read_bootflow_fw() - Create a bootflow for firmware
41 *
42 * Locates and loads the firmware image (FIT) needed for the next phase. The FIT
43 * should ideally use external data, to reduce the amount of it that needs to be
44 * read.
45 *
46 * @bdev: bootdev device containing the firmwre
47 * @meth: VBE simple bootmeth
48 * @blow: Place to put the created bootflow, on success
49 * @return 0 if OK, -ve on error
50 */
51int vbe_simple_read_bootflow_fw(struct udevice *dev, struct bootflow *bflow)
52{
Simon Glassd78aa752022-10-20 18:23:10 -060053 struct udevice *media = dev_get_parent(bflow->dev);
54 struct udevice *meth = bflow->method;
55 struct simple_priv *priv = dev_get_priv(meth);
Simon Glass988f16a2025-01-15 18:27:10 -070056 ulong len, load_addr;
Simon Glassd78aa752022-10-20 18:23:10 -060057 struct udevice *blk;
Simon Glass988f16a2025-01-15 18:27:10 -070058 int ret;
Simon Glassd78aa752022-10-20 18:23:10 -060059
60 log_debug("media=%s\n", media->name);
61 ret = blk_get_from_parent(media, &blk);
62 if (ret)
63 return log_msg_ret("med", ret);
64 log_debug("blk=%s\n", blk->name);
Simon Glassd78aa752022-10-20 18:23:10 -060065
Simon Glass988f16a2025-01-15 18:27:10 -070066 ret = vbe_read_fit(blk, priv->area_start + priv->skip_offset,
Simon Glassedd22362025-01-15 18:27:22 -070067 priv->area_size, NULL, &load_addr, &len,
68 &bflow->name);
Simon Glass0fcc6c42025-01-15 18:27:23 -070069 if (ret)
70 return log_msg_ret("vbe", ret);
Simon Glassd78aa752022-10-20 18:23:10 -060071
72 /* set up the bootflow with the info we obtained */
Simon Glassd78aa752022-10-20 18:23:10 -060073 bflow->blk = blk;
74 bflow->buf = map_sysmem(load_addr, len);
75 bflow->size = len;
76
77 return 0;
78}
79
Simon Glass0fcc6c42025-01-15 18:27:23 -070080static int simple_load_from_image(struct spl_image_info *image,
Simon Glassd78aa752022-10-20 18:23:10 -060081 struct spl_boot_device *bootdev)
82{
Simon Glass9d0042e2022-10-20 18:23:18 -060083 struct vbe_handoff *handoff;
Simon Glassd78aa752022-10-20 18:23:10 -060084 int ret;
85
Simon Glass0fcc6c42025-01-15 18:27:23 -070086 if (xpl_phase() != PHASE_VPL && xpl_phase() != PHASE_SPL &&
87 xpl_phase() != PHASE_TPL)
Simon Glassd78aa752022-10-20 18:23:10 -060088 return -ENOENT;
89
Simon Glass9d0042e2022-10-20 18:23:18 -060090 ret = bloblist_ensure_size(BLOBLISTT_VBE, sizeof(struct vbe_handoff),
91 0, (void **)&handoff);
92 if (ret)
93 return log_msg_ret("ro", ret);
94
Simon Glass0fcc6c42025-01-15 18:27:23 -070095 if (USE_BOOTMETH) {
96 struct udevice *meth, *bdev;
97 struct simple_priv *priv;
98 struct bootflow bflow;
Simon Glassd78aa752022-10-20 18:23:10 -060099
Simon Glass0fcc6c42025-01-15 18:27:23 -0700100 vbe_find_first_device(&meth);
101 if (!meth)
102 return log_msg_ret("vd", -ENODEV);
103 log_debug("vbe dev %s\n", meth->name);
104 ret = device_probe(meth);
105 if (ret)
106 return log_msg_ret("probe", ret);
Simon Glassd78aa752022-10-20 18:23:10 -0600107
Simon Glass0fcc6c42025-01-15 18:27:23 -0700108 priv = dev_get_priv(meth);
109 log_debug("simple %s\n", priv->storage);
110 ret = bootdev_find_by_label(priv->storage, &bdev, NULL);
111 if (ret)
112 return log_msg_ret("bd", ret);
113 log_debug("bootdev %s\n", bdev->name);
114
115 bootflow_init(&bflow, bdev, meth);
116 ret = bootmeth_read_bootflow(meth, &bflow);
117 log_debug("\nfw ret=%d\n", ret);
118 if (ret)
119 return log_msg_ret("rd", ret);
Simon Glassd78aa752022-10-20 18:23:10 -0600120
Simon Glass0fcc6c42025-01-15 18:27:23 -0700121 /* jump to the image */
122 image->flags = SPL_SANDBOXF_ARG_IS_BUF;
123 image->arg = bflow.buf;
124 image->size = bflow.size;
125 log_debug("Image: %s at %p size %x\n", bflow.name, bflow.buf,
126 bflow.size);
127
128 /* this is not used from now on, so free it */
129 bootflow_free(&bflow);
130 } else {
131 struct udevice *media, *blk;
132 ulong offset, size;
133
134 ret = uclass_get_device_by_seq(UCLASS_MMC, 1, &media);
135 if (ret)
136 return log_msg_ret("vdv", ret);
137 ret = blk_get_from_parent(media, &blk);
138 if (ret)
139 return log_msg_ret("med", ret);
140 if (xpl_phase() == PHASE_TPL) {
141 offset = binman_sym(ulong, vpl, image_pos);
142 size = binman_sym(ulong, vpl, size);
143 } else {
144 offset = binman_sym(ulong, vbe_a, image_pos);
145 size = binman_sym(ulong, vbe_a, size);
146 printf("offset=%lx\n", offset);
147 }
Simon Glassd78aa752022-10-20 18:23:10 -0600148
Simon Glass0fcc6c42025-01-15 18:27:23 -0700149 ret = vbe_read_fit(blk, offset, size, image, NULL, NULL, NULL);
150 if (ret)
151 return log_msg_ret("vbe", ret);
152 }
Simon Glassd78aa752022-10-20 18:23:10 -0600153
Simon Glass9d0042e2022-10-20 18:23:18 -0600154 /* Record that VBE was used in this phase */
Simon Glassd4dce4a2024-09-29 19:49:36 -0600155 handoff->phases |= 1 << xpl_phase();
Simon Glass9d0042e2022-10-20 18:23:18 -0600156
Simon Glassd78aa752022-10-20 18:23:10 -0600157 return 0;
158}
159SPL_LOAD_IMAGE_METHOD("vbe_simple", 5, BOOT_DEVICE_VBE,
160 simple_load_from_image);