"Das U-Boot" Source Tree
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

vbe: Add an implementation of VBE-ABrec

So far only VBE-simple is implemented in U-Boot. This supports a single
image which can be updated in situ.

It is often necessary to support two images (A and B) so that the board
is not bricked if the update is interrupted or is bad.

In some cases, a non-updatable recovery image is desirable, so that the
board can be returned to a known-good state in the event of a serious
failure.

Introduce ABrec which provides these features. It supports three
independent images and the logic to select the desired one on boot.

While we are here, fix a debug message to indicate the function it
called. Provide a maintainers entry for VBE.

Note that fwupdated only supports VBE-simple so far, but supports for
ABrec will appear in time.

Signed-off-by: Simon Glass <sjg@chromium.org>

authored by

Simon Glass and committed by
Tom Rini
f1eb367d f4415f2a

+627
+7
MAINTAINERS
··· 1806 1806 S: Maintained 1807 1807 F: test/lib/uuid.c 1808 1808 1809 + VBE 1810 + M: Simon Glass <sjg@chromium.org> 1811 + S: Maintained 1812 + F: boot/vbe* 1813 + F: common/spl_reloc.c 1814 + F: include/vbe.h 1815 + 1809 1816 VIDEO 1810 1817 M: Anatolij Gustschin <agust@denx.de> 1811 1818 S: Maintained
+73
boot/Kconfig
··· 711 711 firmware image in boot media such as MMC. It does not support any sort 712 712 of rollback, recovery or A/B boot. 713 713 714 + config BOOTMETH_VBE_ABREC 715 + bool "Bootdev support for VBE 'a/b/recovery' method" 716 + imply SPL_CRC8 717 + imply VPL_CRC8 718 + help 719 + Enables support for VBE 'abrec' boot. This allows updating one of an 720 + A or B firmware image in boot media such as MMC. The new firmware is 721 + tried and if it boots, it is copied to the other image, so that both 722 + A and B have the same version. If neither firmware image passes the 723 + verification step, a recovery image is booted. This method will 724 + eventually provide rollback protection as well. 725 + 726 + if BOOTMETH_VBE_SIMPLE 727 + 714 728 config BOOTMETH_VBE_SIMPLE_OS 715 729 bool "Bootdev support for VBE 'simple' method OS phase" 716 730 default y ··· 768 782 TPL loads a FIT containing the VPL binary and a suitable devicetree. 769 783 770 784 endif # BOOTMETH_VBE_SIMPLE 785 + 786 + if BOOTMETH_VBE_ABREC 787 + 788 + config SPL_BOOTMETH_VBE_ABREC 789 + bool "Bootdev support for VBE 'abrec' method (SPL)" 790 + depends on SPL 791 + default y if VPL 792 + help 793 + Enables support for VBE 'abrec' boot. The SPL part of this 794 + implementation simply loads U-Boot from the image selected by the 795 + VPL phase. 796 + 797 + config TPL_BOOTMETH_VBE_ABREC 798 + bool "Bootdev support for VBE 'abrec' method (TPL)" 799 + depends on TPL 800 + select TPL_FIT 801 + default y 802 + help 803 + Enables support for VBE 'abrec' boot. The TPL part of this 804 + implementation simply jumps to VPL after device init is completed. 805 + 806 + config VPL_BOOTMETH_VBE_ABREC 807 + bool "Bootdev support for VBE 'abrec' method (VPL)" 808 + depends on VPL 809 + default y 810 + help 811 + Enables support for VBE 'abrec' boot. The VPL part of this 812 + implementation selects which SPL to use (A, B or recovery) and then 813 + boots into SPL. 814 + 815 + config SPL_BOOTMETH_VBE_ABREC_FW 816 + bool "Bootdev support for VBE 'abrec' method firmware phase (SPL)" 817 + depends on SPL 818 + default y if VPL 819 + help 820 + Enables support for VBE 'abrec' boot. The SPL part of this 821 + implementation simply loads U-Boot from the image selected by the 822 + VPL phase. 823 + 824 + config TPL_BOOTMETH_VBE_ABREC_FW 825 + bool "Bootdev support for VBE 'abrec' method firmware phase (TPL)" 826 + depends on TPL 827 + default y if VPL 828 + help 829 + Enables support for VBE 'abrec' boot. The TPL part of this 830 + implementation simply jumps to VPL after device init is completed. 831 + 832 + config VPL_BOOTMETH_VBE_ABREC_FW 833 + bool "Bootdev support for VBE 'abrec' method firmware phase (VPL)" 834 + depends on VPL 835 + default y 836 + help 837 + Enables support for VBE 'abrec' boot. The VPL part of this 838 + implementation selects which SPL to use (A, B or recovery) and then 839 + boots into SPL. 840 + 841 + endif # BOOTMETH_VBE_ABREC 842 + 843 + endif # BOOTMETH_VBE 771 844 772 845 config EXPO 773 846 bool "Support for expos - groups of scenes displaying a UI"
+4
boot/Makefile
··· 70 70 obj-$(CONFIG_$(PHASE_)BOOTMETH_VBE_SIMPLE_OS) += vbe_simple_os.o 71 71 72 72 obj-$(CONFIG_$(PHASE_)BOOTMETH_ANDROID) += bootmeth_android.o 73 + 74 + obj-$(CONFIG_$(PHASE_)BOOTMETH_VBE_ABREC) += vbe_abrec.o vbe_common.o 75 + obj-$(CONFIG_$(PHASE_)BOOTMETH_VBE_ABREC_FW) += vbe_abrec_fw.o 76 + obj-$(CONFIG_$(PHASE_)BOOTMETH_VBE_ABREC_OS) += vbe_abrec_os.o
+83
boot/vbe_abrec.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Verified Boot for Embedded (VBE) 'simple' method 4 + * 5 + * Copyright 2024 Google LLC 6 + * Written by Simon Glass <sjg@chromium.org> 7 + */ 8 + 9 + #define LOG_CATEGORY LOGC_BOOT 10 + 11 + #include <dm.h> 12 + #include <memalign.h> 13 + #include <mmc.h> 14 + #include <dm/ofnode.h> 15 + #include "vbe_abrec.h" 16 + 17 + int abrec_read_priv(ofnode node, struct abrec_priv *priv) 18 + { 19 + memset(priv, '\0', sizeof(*priv)); 20 + if (ofnode_read_u32(node, "area-start", &priv->area_start) || 21 + ofnode_read_u32(node, "area-size", &priv->area_size) || 22 + ofnode_read_u32(node, "version-offset", &priv->version_offset) || 23 + ofnode_read_u32(node, "version-size", &priv->version_size) || 24 + ofnode_read_u32(node, "state-offset", &priv->state_offset) || 25 + ofnode_read_u32(node, "state-size", &priv->state_size)) 26 + return log_msg_ret("read", -EINVAL); 27 + ofnode_read_u32(node, "skip-offset", &priv->skip_offset); 28 + priv->storage = strdup(ofnode_read_string(node, "storage")); 29 + if (!priv->storage) 30 + return log_msg_ret("str", -EINVAL); 31 + 32 + return 0; 33 + } 34 + 35 + int abrec_read_nvdata(struct abrec_priv *priv, struct udevice *blk, 36 + struct abrec_state *state) 37 + { 38 + ALLOC_CACHE_ALIGN_BUFFER(u8, buf, MMC_MAX_BLOCK_LEN); 39 + const struct vbe_nvdata *nvd = (struct vbe_nvdata *)buf; 40 + uint flags; 41 + int ret; 42 + 43 + ret = vbe_read_nvdata(blk, priv->area_start + priv->state_offset, 44 + priv->state_size, buf); 45 + if (ret == -EPERM) { 46 + memset(buf, '\0', MMC_MAX_BLOCK_LEN); 47 + log_warning("Starting with empty state\n"); 48 + } else if (ret) { 49 + return log_msg_ret("nv", ret); 50 + } 51 + 52 + state->fw_vernum = nvd->fw_vernum; 53 + flags = nvd->flags; 54 + state->try_count = flags & VBEF_TRY_COUNT_MASK; 55 + state->try_b = flags & VBEF_TRY_B; 56 + state->recovery = flags & VBEF_RECOVERY; 57 + state->pick = (flags & VBEF_PICK_MASK) >> VBEF_PICK_SHIFT; 58 + 59 + return 0; 60 + } 61 + 62 + int abrec_read_state(struct udevice *dev, struct abrec_state *state) 63 + { 64 + struct abrec_priv *priv = dev_get_priv(dev); 65 + struct udevice *blk; 66 + int ret; 67 + 68 + ret = vbe_get_blk(priv->storage, &blk); 69 + if (ret) 70 + return log_msg_ret("blk", ret); 71 + 72 + ret = vbe_read_version(blk, priv->area_start + priv->version_offset, 73 + state->fw_version, MAX_VERSION_LEN); 74 + if (ret) 75 + return log_msg_ret("ver", ret); 76 + log_debug("version=%s\n", state->fw_version); 77 + 78 + ret = abrec_read_nvdata(priv, blk, state); 79 + if (ret) 80 + return log_msg_ret("nvd", ret); 81 + 82 + return 0; 83 + }
+115
boot/vbe_abrec.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Verified Boot for Embedded (VBE) vbe-abrec common file 4 + * 5 + * Copyright 2024 Google LLC 6 + * Written by Simon Glass <sjg@chromium.org> 7 + */ 8 + 9 + #ifndef __VBE_ABREC_H 10 + #define __VBE_ABREC_H 11 + 12 + #include <vbe.h> 13 + #include <dm/ofnode_decl.h> 14 + 15 + #include "vbe_common.h" 16 + 17 + struct bootflow; 18 + struct udevice; 19 + 20 + /** 21 + * struct abrec_priv - information read from the device tree 22 + * 23 + * @area_start: Start offset of the VBE area in the device, in bytes 24 + * @area_size: Total size of the VBE area 25 + * @skip_offset: Size of an initial part of the device to skip, when using 26 + * area_start. This is effectively added to area_start to calculate the 27 + * actual start position on the device 28 + * @state_offset: Offset from area_start of the VBE state, in bytes 29 + * @state_size: Size of the state information 30 + * @version_offset: Offset from from area_start of the VBE version info 31 + * @version_size: Size of the version info 32 + * @storage: Storage device to use, in the form <uclass><devnum>, e.g. "mmc1" 33 + */ 34 + struct abrec_priv { 35 + u32 area_start; 36 + u32 area_size; 37 + u32 skip_offset; 38 + u32 state_offset; 39 + u32 state_size; 40 + u32 version_offset; 41 + u32 version_size; 42 + const char *storage; 43 + }; 44 + 45 + /** struct abrec_state - state information read from media 46 + * 47 + * The state on the media is converted into this more code-friendly structure. 48 + * 49 + * @fw_version: Firmware version string 50 + * @fw_vernum: Firmware version number 51 + * @try_count: Number of times the B firmware has been tried 52 + * @try_b: true to try B firmware on the next boot 53 + * @recovery: true to enter recovery firmware on the next boot 54 + * @try_result: Result of trying to boot with the last firmware 55 + * @pick: Firmware which was chosen in this boot 56 + */ 57 + struct abrec_state { 58 + char fw_version[MAX_VERSION_LEN]; 59 + u32 fw_vernum; 60 + u8 try_count; 61 + bool try_b; 62 + bool recovery; 63 + enum vbe_try_result try_result; 64 + enum vbe_pick_t pick; 65 + }; 66 + 67 + /** 68 + * abrec_read_fw_bootflow() - Read a bootflow for firmware 69 + * 70 + * Locates and loads the firmware image (FIT) needed for the next phase. The FIT 71 + * should ideally use external data, to reduce the amount of it that needs to be 72 + * read. 73 + * 74 + * @bdev: bootdev device containing the firmwre 75 + * @bflow: Place to put the created bootflow, on success 76 + * @return 0 if OK, -ve on error 77 + */ 78 + int abrec_read_bootflow_fw(struct udevice *dev, struct bootflow *bflow); 79 + 80 + /** 81 + * vbe_simple_read_state() - Read the VBE simple state information 82 + * 83 + * @dev: VBE bootmeth 84 + * @state: Place to put the state 85 + * @return 0 if OK, -ve on error 86 + */ 87 + int abrec_read_state(struct udevice *dev, struct abrec_state *state); 88 + 89 + /** 90 + * abrec_read_nvdata() - Read non-volatile data from a block device 91 + * 92 + * Reads the ABrec VBE nvdata from a device. This function reads a single block 93 + * from the device, so the nvdata cannot be larger than that. 94 + * 95 + * @blk: Device to read from 96 + * @offset: Offset to read, in bytes 97 + * @size: Number of bytes to read 98 + * @buf: Buffer to hold the data 99 + * Return: 0 if OK, -E2BIG if @size > block size, -EBADF if the offset is not 100 + * block-aligned, -EIO if an I/O error occurred, -EPERM if the header version is 101 + * incorrect, the header size is invalid or the data fails its CRC check 102 + */ 103 + int abrec_read_nvdata(struct abrec_priv *priv, struct udevice *blk, 104 + struct abrec_state *state); 105 + 106 + /** 107 + * abrec_read_priv() - Read info from the devicetree 108 + * 109 + * @node: Node to read from 110 + * @priv: Information to fill in 111 + * Return 0 if OK, -EINVAL if something is wrong with the devicetree node 112 + */ 113 + int abrec_read_priv(ofnode node, struct abrec_priv *priv); 114 + 115 + #endif /* __VBE_ABREC_H */
+276
boot/vbe_abrec_fw.c
··· 1 + // 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 + 11 + #include <binman_sym.h> 12 + #include <bloblist.h> 13 + #include <bootdev.h> 14 + #include <bootflow.h> 15 + #include <bootmeth.h> 16 + #include <bootstage.h> 17 + #include <display_options.h> 18 + #include <dm.h> 19 + #include <image.h> 20 + #include <log.h> 21 + #include <mapmem.h> 22 + #include <memalign.h> 23 + #include <mmc.h> 24 + #include <spl.h> 25 + #include <vbe.h> 26 + #include <dm/device-internal.h> 27 + #include "vbe_abrec.h" 28 + #include "vbe_common.h" 29 + 30 + binman_sym_declare(ulong, spl_a, image_pos); 31 + binman_sym_declare(ulong, spl_b, image_pos); 32 + binman_sym_declare(ulong, spl_recovery, image_pos); 33 + 34 + binman_sym_declare(ulong, spl_a, size); 35 + binman_sym_declare(ulong, spl_b, size); 36 + binman_sym_declare(ulong, spl_recovery, size); 37 + 38 + binman_sym_declare(ulong, u_boot_a, image_pos); 39 + binman_sym_declare(ulong, u_boot_b, image_pos); 40 + binman_sym_declare(ulong, u_boot_recovery, image_pos); 41 + 42 + binman_sym_declare(ulong, u_boot_a, size); 43 + binman_sym_declare(ulong, u_boot_b, size); 44 + binman_sym_declare(ulong, u_boot_recovery, size); 45 + 46 + binman_sym_declare(ulong, vpl, image_pos); 47 + binman_sym_declare(ulong, vpl, size); 48 + 49 + static const char *const pick_names[] = {"A", "B", "Recovery"}; 50 + 51 + /** 52 + * abrec_read_bootflow_fw() - Create a bootflow for firmware 53 + * 54 + * Locates and loads the firmware image (FIT) needed for the next phase. The FIT 55 + * should ideally use external data, to reduce the amount of it that needs to be 56 + * read. 57 + * 58 + * @bdev: bootdev device containing the firmwre 59 + * @meth: VBE abrec bootmeth 60 + * @blow: Place to put the created bootflow, on success 61 + * @return 0 if OK, -ve on error 62 + */ 63 + int abrec_read_bootflow_fw(struct udevice *dev, struct bootflow *bflow) 64 + { 65 + struct udevice *media = dev_get_parent(bflow->dev); 66 + struct udevice *meth = bflow->method; 67 + struct abrec_priv *priv = dev_get_priv(meth); 68 + ulong len, load_addr; 69 + struct udevice *blk; 70 + int ret; 71 + 72 + log_debug("media=%s\n", media->name); 73 + ret = blk_get_from_parent(media, &blk); 74 + if (ret) 75 + return log_msg_ret("med", ret); 76 + 77 + ret = vbe_read_fit(blk, priv->area_start + priv->skip_offset, 78 + priv->area_size, NULL, &load_addr, &len, &bflow->name); 79 + if (ret) 80 + return log_msg_ret("vbe", ret); 81 + 82 + /* set up the bootflow with the info we obtained */ 83 + bflow->blk = blk; 84 + bflow->buf = map_sysmem(load_addr, len); 85 + bflow->size = len; 86 + 87 + return 0; 88 + } 89 + 90 + static int abrec_run_vpl(struct udevice *blk, struct spl_image_info *image, 91 + struct vbe_handoff *handoff) 92 + { 93 + uint flags, tries, prev_result; 94 + struct abrec_priv priv; 95 + struct abrec_state state; 96 + enum vbe_pick_t pick; 97 + uint try_count; 98 + ulong offset, size; 99 + ulong ub_offset, ub_size; 100 + ofnode node; 101 + int ret; 102 + 103 + node = vbe_get_node(); 104 + if (!ofnode_valid(node)) 105 + return log_msg_ret("nod", -EINVAL); 106 + 107 + ret = abrec_read_priv(node, &priv); 108 + if (ret) 109 + return log_msg_ret("pri", ret); 110 + 111 + ret = abrec_read_nvdata(&priv, blk, &state); 112 + if (ret) 113 + return log_msg_ret("sta", ret); 114 + 115 + prev_result = state.try_result; 116 + try_count = state.try_count; 117 + 118 + if (state.recovery) { 119 + pick = VBEP_RECOVERY; 120 + 121 + /* if we are trying B but ran out of tries, use A */ 122 + } else if ((prev_result == VBETR_TRYING) && !tries) { 123 + pick = VBEP_A; 124 + state.try_result = VBETR_BAD; 125 + 126 + /* if requested, try B */ 127 + } else if (flags & VBEF_TRY_B) { 128 + pick = VBEP_B; 129 + 130 + /* decrement the try count if not already zero */ 131 + if (try_count) 132 + try_count--; 133 + state.try_result = VBETR_TRYING; 134 + } else { 135 + pick = VBEP_A; 136 + } 137 + state.try_count = try_count; 138 + 139 + switch (pick) { 140 + case VBEP_A: 141 + offset = binman_sym(ulong, spl_a, image_pos); 142 + size = binman_sym(ulong, spl_a, size); 143 + ub_offset = binman_sym(ulong, u_boot_a, image_pos); 144 + ub_size = binman_sym(ulong, u_boot_a, size); 145 + break; 146 + case VBEP_B: 147 + offset = binman_sym(ulong, spl_b, image_pos); 148 + size = binman_sym(ulong, spl_b, size); 149 + ub_offset = binman_sym(ulong, u_boot_b, image_pos); 150 + ub_size = binman_sym(ulong, u_boot_b, size); 151 + break; 152 + case VBEP_RECOVERY: 153 + offset = binman_sym(ulong, spl_recovery, image_pos); 154 + size = binman_sym(ulong, spl_recovery, size); 155 + ub_offset = binman_sym(ulong, u_boot_recovery, image_pos); 156 + ub_size = binman_sym(ulong, u_boot_recovery, size); 157 + break; 158 + } 159 + log_debug("pick=%d, offset=%lx size=%lx\n", pick, offset, size); 160 + log_info("VBE: Firmware pick %s at %lx\n", pick_names[pick], offset); 161 + 162 + ret = vbe_read_fit(blk, offset, size, image, NULL, NULL, NULL); 163 + if (ret) 164 + return log_msg_ret("vbe", ret); 165 + handoff->offset = ub_offset; 166 + handoff->size = ub_size; 167 + handoff->pick = pick; 168 + image->load_addr = spl_get_image_text_base(); 169 + image->entry_point = image->load_addr; 170 + 171 + return 0; 172 + } 173 + 174 + static int abrec_run_spl(struct udevice *blk, struct spl_image_info *image, 175 + struct vbe_handoff *handoff) 176 + { 177 + int ret; 178 + 179 + log_info("VBE: Firmware pick %s at %lx\n", pick_names[handoff->pick], 180 + handoff->offset); 181 + ret = vbe_read_fit(blk, handoff->offset, handoff->size, image, NULL, 182 + NULL, NULL); 183 + if (ret) 184 + return log_msg_ret("vbe", ret); 185 + image->load_addr = spl_get_image_text_base(); 186 + image->entry_point = image->load_addr; 187 + 188 + return 0; 189 + } 190 + 191 + static int abrec_load_from_image(struct spl_image_info *image, 192 + struct spl_boot_device *bootdev) 193 + { 194 + struct vbe_handoff *handoff; 195 + int ret; 196 + 197 + printf("load: %s\n", ofnode_read_string(ofnode_root(), "model")); 198 + if (xpl_phase() != PHASE_VPL && xpl_phase() != PHASE_SPL && 199 + xpl_phase() != PHASE_TPL) 200 + return -ENOENT; 201 + 202 + ret = bloblist_ensure_size(BLOBLISTT_VBE, sizeof(struct vbe_handoff), 203 + 0, (void **)&handoff); 204 + if (ret) 205 + return log_msg_ret("ro", ret); 206 + 207 + if (USE_BOOTMETH) { 208 + struct udevice *meth, *bdev; 209 + struct abrec_priv *priv; 210 + struct bootflow bflow; 211 + 212 + vbe_find_first_device(&meth); 213 + if (!meth) 214 + return log_msg_ret("vd", -ENODEV); 215 + log_debug("vbe dev %s\n", meth->name); 216 + ret = device_probe(meth); 217 + if (ret) 218 + return log_msg_ret("probe", ret); 219 + 220 + priv = dev_get_priv(meth); 221 + log_debug("abrec %s\n", priv->storage); 222 + ret = bootdev_find_by_label(priv->storage, &bdev, NULL); 223 + if (ret) 224 + return log_msg_ret("bd", ret); 225 + log_debug("bootdev %s\n", bdev->name); 226 + 227 + bootflow_init(&bflow, bdev, meth); 228 + ret = bootmeth_read_bootflow(meth, &bflow); 229 + log_debug("\nfw ret=%d\n", ret); 230 + if (ret) 231 + return log_msg_ret("rd", ret); 232 + 233 + /* jump to the image */ 234 + image->flags = SPL_SANDBOXF_ARG_IS_BUF; 235 + image->arg = bflow.buf; 236 + image->size = bflow.size; 237 + log_debug("Image: %s at %p size %x\n", bflow.name, bflow.buf, 238 + bflow.size); 239 + 240 + /* this is not used from now on, so free it */ 241 + bootflow_free(&bflow); 242 + } else { 243 + struct udevice *media; 244 + struct udevice *blk; 245 + 246 + ret = uclass_get_device_by_seq(UCLASS_MMC, 1, &media); 247 + if (ret) 248 + return log_msg_ret("vdv", ret); 249 + ret = blk_get_from_parent(media, &blk); 250 + if (ret) 251 + return log_msg_ret("med", ret); 252 + 253 + if (xpl_phase() == PHASE_TPL) { 254 + ulong offset, size; 255 + 256 + offset = binman_sym(ulong, vpl, image_pos); 257 + size = binman_sym(ulong, vpl, size); 258 + log_debug("VPL at offset %lx size %lx\n", offset, size); 259 + ret = vbe_read_fit(blk, offset, size, image, NULL, 260 + NULL, NULL); 261 + if (ret) 262 + return log_msg_ret("vbe", ret); 263 + } else if (xpl_phase() == PHASE_VPL) { 264 + ret = abrec_run_vpl(blk, image, handoff); 265 + } else { 266 + ret = abrec_run_spl(blk, image, handoff); 267 + } 268 + } 269 + 270 + /* Record that VBE was used in this phase */ 271 + handoff->phases |= 1 << xpl_phase(); 272 + 273 + return 0; 274 + } 275 + SPL_LOAD_IMAGE_METHOD("vbe_abrec", 5, BOOT_DEVICE_VBE, 276 + abrec_load_from_image);
+5
boot/vbe_common.c
··· 374 374 375 375 return 0; 376 376 } 377 + 378 + ofnode vbe_get_node(void) 379 + { 380 + return ofnode_path("/bootstd/firmware0"); 381 + }
+43
boot/vbe_common.h
··· 9 9 #ifndef __VBE_COMMON_H 10 10 #define __VBE_COMMON_H 11 11 12 + #include <dm/ofnode_decl.h> 13 + #include <linux/bitops.h> 12 14 #include <linux/types.h> 13 15 14 16 struct spl_image_info; ··· 36 38 FWVER_FW_MASK = 0xffff, 37 39 38 40 NVD_HDR_VER_CUR = 1, /* current version */ 41 + }; 42 + 43 + /** 44 + * enum vbe_try_result - result of trying a firmware pick 45 + * 46 + * @VBETR_UNKNOWN: Unknown / invalid result 47 + * @VBETR_TRYING: Firmware pick is being tried 48 + * @VBETR_OK: Firmware pick is OK and can be used from now on 49 + * @VBETR_BAD: Firmware pick is bad and should be removed 50 + */ 51 + enum vbe_try_result { 52 + VBETR_UNKNOWN, 53 + VBETR_TRYING, 54 + VBETR_OK, 55 + VBETR_BAD, 56 + }; 57 + 58 + /** 59 + * enum vbe_flags - flags controlling operation 60 + * 61 + * @VBEF_TRY_COUNT_MASK: mask for the 'try count' value 62 + * @VBEF_TRY_B: Try the B slot 63 + * @VBEF_RECOVERY: Use recovery slot 64 + */ 65 + enum vbe_flags { 66 + VBEF_TRY_COUNT_MASK = 0x3, 67 + VBEF_TRY_B = BIT(2), 68 + VBEF_RECOVERY = BIT(3), 69 + 70 + VBEF_RESULT_SHIFT = 4, 71 + VBEF_RESULT_MASK = 3 << VBEF_RESULT_SHIFT, 72 + 73 + VBEF_PICK_SHIFT = 6, 74 + VBEF_PICK_MASK = 3 << VBEF_PICK_SHIFT, 39 75 }; 40 76 41 77 /** ··· 133 169 int vbe_read_fit(struct udevice *blk, ulong area_offset, ulong area_size, 134 170 struct spl_image_info *image, ulong *load_addrp, ulong *lenp, 135 171 char **namep); 172 + 173 + /** 174 + * vbe_get_node() - Get the node containing the VBE settings 175 + * 176 + * Return: VBE node (typically "/bootstd/firmware0") 177 + */ 178 + ofnode vbe_get_node(void); 136 179 137 180 #endif /* __VBE_ABREC_H */
+21
include/vbe.h
··· 10 10 #ifndef __VBE_H 11 11 #define __VBE_H 12 12 13 + #include <linux/types.h> 14 + 13 15 /** 14 16 * enum vbe_phase_t - current phase of VBE 15 17 * ··· 26 28 }; 27 29 28 30 /** 31 + * enum vbe_pick_t - indicates which firmware is picked 32 + * 33 + * @VBEFT_A: Firmware A 34 + * @VBEFT_B: Firmware B 35 + * @VBEFT_RECOVERY: Recovery firmware 36 + */ 37 + enum vbe_pick_t { 38 + VBEP_A, 39 + VBEP_B, 40 + VBEP_RECOVERY, 41 + }; 42 + 43 + /** 29 44 * struct vbe_handoff - information about VBE progress 30 45 * 46 + * @offset: Offset of the FIT to use for SPL onwards 47 + * @size: Size of the area containing the FIT 31 48 * @phases: Indicates which phases used the VBE bootmeth (1 << PHASE_...) 49 + * @pick: Indicates which firmware pick was used (enum vbe_pick_t) 32 50 */ 33 51 struct vbe_handoff { 52 + ulong offset; 53 + ulong size; 34 54 u8 phases; 55 + u8 pick; 35 56 }; 36 57 37 58 /**