"Das U-Boot" Source Tree

Merge patch series "FWU: Add support for FWU metadata version 2"

Sughosh Ganu <sughosh.ganu@linaro.org> says:

The following patch series adds support for version 2 of the FWU
metadata. The version 2 metadata structure is defined in the latest
revision of the FWU specification [1].

The earlier versions of these patches were migrating to a version 2
only support in U-Boot, similar to TF-A. However, based on feedback
from ST [2], this series has been updated to support both versions. A
platform would still be needed to enable one of the two versions of
metadata through a config symbol.

TF-A has code which reads the FWU metadata and boots the platform from
the active partition. TF-A has decided to migrate the FWU code to a
version 2 only support. These changes have been merged in upstream
TF-A.

These changes have been tested on the ST DK2 board, which uses the GPT
based partitioning scheme. Both V1 and V2 metadata versions have been
tested on the DK2 board.

These changes need to be tested on platforms with MTD partitioned
storage devices.

Tom Rini 7e52d6cc 6b9ae578

+1152 -216
+8
MAINTAINERS
··· 1168 1168 F: drivers/watchdog/sp805_wdt.c 1169 1169 F: drivers/watchdog/sbsa_gwdt.c 1170 1170 1171 + FWU Multi Bank Update 1172 + M: Sughosh Ganu <sughosh.ganu@linaro.org> 1173 + S: Maintained 1174 + T: git https://source.denx.de/u-boot/custodians/u-boot-efi.git 1175 + F: lib/fwu_updates/* 1176 + F: drivers/fwu-mdata/* 1177 + F: tools/mkfwumdata.c 1178 + 1171 1179 GATEWORKS_SC 1172 1180 M: Tim Harvey <tharvey@gateworks.com> 1173 1181 S: Maintained
+18 -21
cmd/fwu_mdata.c
··· 13 13 14 14 #include <linux/types.h> 15 15 16 - static void print_mdata(struct fwu_mdata *mdata) 16 + static void print_mdata(struct fwu_data *data) 17 17 { 18 18 int i, j; 19 19 struct fwu_image_entry *img_entry; 20 20 struct fwu_image_bank_info *img_info; 21 21 22 22 printf("\tFWU Metadata\n"); 23 - printf("crc32: %#x\n", mdata->crc32); 24 - printf("version: %#x\n", mdata->version); 25 - printf("active_index: %#x\n", mdata->active_index); 26 - printf("previous_active_index: %#x\n", mdata->previous_active_index); 23 + printf("crc32: %#x\n", data->crc32); 24 + printf("version: %#x\n", data->version); 25 + printf("active_index: %#x\n", data->active_index); 26 + printf("previous_active_index: %#x\n", data->previous_active_index); 27 + 28 + if (data->version == 2) { 29 + for (i = 0; i < 4; i++) 30 + printf("bank_state[%d]: %#x\n", 31 + i, data->bank_state[i]); 32 + } 27 33 28 34 printf("\tImage Info\n"); 29 35 for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { 30 - img_entry = &mdata->img_entry[i]; 36 + img_entry = &data->fwu_images[i]; 31 37 printf("\nImage Type Guid: %pUL\n", 32 - &img_entry->image_type_uuid); 33 - printf("Location Guid: %pUL\n", &img_entry->location_uuid); 38 + &img_entry->image_type_guid); 39 + printf("Location Guid: %pUL\n", &img_entry->location_guid); 34 40 for (j = 0; j < CONFIG_FWU_NUM_BANKS; j++) { 35 41 img_info = &img_entry->img_bank_info[j]; 36 - printf("Image Guid: %pUL\n", &img_info->image_uuid); 42 + printf("Image Guid: %pUL\n", &img_info->image_guid); 37 43 printf("Image Acceptance: %s\n", 38 44 img_info->accepted == 0x1 ? "yes" : "no"); 39 45 } ··· 43 49 int do_fwu_mdata_read(struct cmd_tbl *cmdtp, int flag, 44 50 int argc, char * const argv[]) 45 51 { 46 - int ret = CMD_RET_SUCCESS, res; 47 - struct fwu_mdata mdata; 52 + struct fwu_data *data = fwu_get_data(); 48 53 49 - res = fwu_get_mdata(&mdata); 50 - if (res < 0) { 51 - log_err("Unable to get valid FWU metadata\n"); 52 - ret = CMD_RET_FAILURE; 53 - goto out; 54 - } 54 + print_mdata(data); 55 55 56 - print_mdata(&mdata); 57 - 58 - out: 59 - return ret; 56 + return CMD_RET_SUCCESS; 60 57 } 61 58 62 59 U_BOOT_CMD(
+1
configs/corstone1000_defconfig
··· 68 68 CONFIG_EFI_CAPSULE_ON_DISK=y 69 69 CONFIG_EFI_IGNORE_OSINDICATIONS=y 70 70 CONFIG_FWU_MULTI_BANK_UPDATE=y 71 + CONFIG_FWU_MDATA_V1=y
+1 -1
configs/synquacer_developerbox_defconfig
··· 11 11 CONFIG_DEFAULT_DEVICE_TREE="synquacer-sc2a11-developerbox" 12 12 CONFIG_SYS_LOAD_ADDR=0x80000000 13 13 CONFIG_TARGET_DEVELOPERBOX=y 14 - CONFIG_FWU_NUM_IMAGES_PER_BANK=1 15 14 CONFIG_AHCI=y 16 15 CONFIG_FIT=y 17 16 CONFIG_SYS_BOOTM_LEN=0x800000 ··· 97 96 CONFIG_EFI_IGNORE_OSINDICATIONS=y 98 97 CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y 99 98 CONFIG_FWU_MULTI_BANK_UPDATE=y 99 + CONFIG_FWU_MDATA_V2=y
+5 -2
doc/board/socionext/developerbox.rst
··· 116 116 CONFIG_FWU_NUM_BANKS=2 117 117 CONFIG_FWU_NUM_IMAGES_PER_BANK=1 118 118 CONFIG_CMD_FWU_METADATA=y 119 + CONFIG_FWU_MDATA_V2=y 119 120 120 121 And build it:: 121 122 ··· 129 130 By default, the CONFIG_FWU_NUM_BANKS and CONFIG_FWU_NUM_IMAGES_PER_BANKS are 130 131 set to 2 and 1 respectively. This uses FIP (Firmware Image Package) type image 131 132 which contains TF-A, U-Boot and OP-TEE (the OP-TEE is optional). 132 - You can use fiptool to compose the FIP image from those firmware images. 133 + You can use fiptool to compose the FIP image from those firmware 134 + images. There are two versions of the FWU metadata, of which the 135 + platform enables version 2 by default. 133 136 134 137 Rebuild SCP firmware 135 138 -------------------- ··· 194 197 195 198 These UUIDs are used for making a FWU metadata image. 196 199 197 - u-boot$ ./tools/mkfwumdata -i 1 -b 2 \ 200 + u-boot$ ./tools/mkfwumdata -v 2 -i 1 -b 2 \ 198 201 17e86d77-41f9-4fd7-87ec-a55df9842de5,10c36d7d-ca52-b843-b7b9-f9d6c501d108,5a66a702-99fd-4fef-a392-c26e261a2828,a8f868a1-6e5c-4757-878d-ce63375ef2c0 \ 199 202 ../devbox-fwu-mdata.img 200 203
+15 -5
doc/develop/uefi/fwu_updates.rst
··· 46 46 CONFIG_FWU_NUM_BANKS=<val> 47 47 CONFIG_FWU_NUM_IMAGES_PER_BANK=<val> 48 48 49 + CONFIG_FWU_MDATA_V1=y or CONFIG_FWU_MDATA_V2=y 50 + 49 51 in the .config file 50 52 51 53 By enabling the CONFIG_CMD_FWU_METADATA config option, the ··· 57 59 enable the FWU Multi Bank Update functionality. Please refer to the 58 60 section :ref:`uefi_capsule_update_ref` for more details on generation 59 61 of the UEFI capsule. 62 + 63 + FWU Metadata 64 + ------------ 65 + 66 + U-Boot supports both versions(1 and 2) of the FWU metadata defined in 67 + the two revisions of the specification. Support can be enabled for 68 + either of the two versions through a config flag. The mkfwumdata tool 69 + can generate metadata for both the supported versions. 60 70 61 71 Setting up the device for GPT partitioned storage 62 72 ------------------------------------------------- ··· 94 104 * UniquePartitionGUID 95 105 96 106 The PartitionTypeGUID value should correspond to the 97 - ``image_type_uuid`` field of the FWU metadata. This field is used to 107 + ``image_type_guid`` field of the FWU metadata. This field is used to 98 108 identify a given type of updatable firmware image, e.g. U-Boot, 99 109 OP-TEE, FIP etc. This GUID should also be used for specifying the 100 110 `--guid` parameter when generating the capsule. 101 111 102 - The UniquePartitionGUID value should correspond to the ``image_uuid`` 112 + The UniquePartitionGUID value should correspond to the ``image_guid`` 103 113 field in the FWU metadata. This GUID is used to identify images of a 104 114 given image type in different banks. 105 115 ··· 108 118 metadata partitions. Similarly, the UEFI specification defines the ESP 109 119 GUID to be be used. 110 120 111 - When generating the metadata, the ``image_type_uuid`` and the 112 - ``image_uuid`` values should match the *PartitionTypeGUID* and the 121 + When generating the metadata, the ``image_type_guid`` and the 122 + ``image_guid`` values should match the *PartitionTypeGUID* and the 113 123 *UniquePartitionGUID* values respectively. 114 124 115 125 Performing the Update ··· 181 191 Links 182 192 ----- 183 193 184 - * [1] https://developer.arm.com/documentation/den0118/a/ - FWU Specification 194 + * [1] https://developer.arm.com/documentation/den0118/ - FWU Specification 185 195 * [2] https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf - Dependable Boot Specification
+15 -1
doc/mkfwumdata.1
··· 6 6 . 7 7 .SH SYNOPSIS 8 8 .SY mkfwumdata 9 + .OP \-v version 9 10 .OP \-a activeidx 10 11 .OP \-p previousidx 11 12 .OP \-g 13 + .OP \-V vendor-file 12 14 .BI \-i\~ imagecount 13 15 .BI \-b\~ bankcount 14 16 .I UUIDs ··· 26 28 .TP 27 29 .B \-h 28 30 Print usage information and exit. 31 + . 32 + .TP 33 + .B \-v 34 + Set 35 + .IR version 36 + as the metadata version to generate. Valid values 1 or 2. 29 37 . 30 38 .TP 31 39 .B \-a ··· 50 58 as GUIDs before use. 51 59 . 52 60 .TP 61 + .B \-V 62 + Pass 63 + .IR vendor-file 64 + for appending vendor data to the metadata. Supported only with version 2. 65 + . 66 + .TP 53 67 .B \-i 54 68 Specify there are 55 69 .IR imagecount ··· 81 95 .EX 82 96 .in +4 83 97 $ \c 84 - .B mkfwumdata \-a 0 \-p 1 \-b 2 \-i 1 \\\\\& 98 + .B mkfwumdata \-v 2 \-a 0 \-p 1 \-b 2 \-i 1 \\\\\& 85 99 .in +6 86 100 .B 17e86d77-41f9-4fd7-87ec-a55df9842de5,\\\\\& 87 101 .B 10c36d7d-ca52-b843-b7b9-f9d6c501d108,\\\\\&
+6 -4
drivers/fwu-mdata/fwu-mdata-uclass.c
··· 19 19 * 20 20 * Return: 0 if OK, -ve on error 21 21 */ 22 - int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary) 22 + int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary, 23 + uint32_t size) 23 24 { 24 25 const struct fwu_mdata_ops *ops = device_get_ops(dev); 25 26 ··· 28 29 return -ENOSYS; 29 30 } 30 31 31 - return ops->read_mdata(dev, mdata, primary); 32 + return ops->read_mdata(dev, mdata, primary, size); 32 33 } 33 34 34 35 /** ··· 36 37 * 37 38 * Return: 0 if OK, -ve on error 38 39 */ 39 - int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary) 40 + int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary, 41 + uint32_t size) 40 42 { 41 43 const struct fwu_mdata_ops *ops = device_get_ops(dev); 42 44 ··· 45 47 return -ENOSYS; 46 48 } 47 49 48 - return ops->write_mdata(dev, mdata, primary); 50 + return ops->write_mdata(dev, mdata, primary, size); 49 51 } 50 52 51 53 UCLASS_DRIVER(fwu_mdata) = {
+13 -10
drivers/fwu-mdata/gpt_blk.c
··· 81 81 return -ENOENT; 82 82 } 83 83 84 - static int gpt_read_write_mdata(struct blk_desc *desc, 85 - struct fwu_mdata *mdata, 86 - u8 access, u32 part_num) 84 + static int gpt_read_write_mdata(struct blk_desc *desc, struct fwu_mdata *mdata, 85 + u8 access, u32 part_num, u32 size) 87 86 { 88 87 int ret; 89 88 u32 len, blk_start, blkcnt; 90 89 struct disk_partition info; 91 90 92 - ALLOC_CACHE_ALIGN_BUFFER_PAD(struct fwu_mdata, mdata_aligned, 1, 91 + ALLOC_CACHE_ALIGN_BUFFER_PAD(u8, mdata_aligned, size, 93 92 desc->blksz); 94 93 95 94 if (!mdata) ··· 101 100 return -ENOENT; 102 101 } 103 102 104 - len = sizeof(*mdata); 103 + len = size; 105 104 blkcnt = BLOCK_CNT(len, desc); 106 105 if (blkcnt > info.size) { 107 106 log_debug("Block count exceeds FWU metadata partition size\n"); ··· 114 113 log_debug("Error reading FWU metadata from the device\n"); 115 114 return -EIO; 116 115 } 117 - memcpy(mdata, mdata_aligned, sizeof(struct fwu_mdata)); 116 + memcpy(mdata, mdata_aligned, size); 118 117 } else { 119 118 if (blk_dwrite(desc, blk_start, blkcnt, mdata) != blkcnt) { 120 119 log_debug("Error writing FWU metadata to the device\n"); ··· 164 163 } 165 164 166 165 static int fwu_gpt_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, 167 - bool primary) 166 + bool primary, u32 size) 168 167 { 169 168 struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev); 170 169 struct blk_desc *desc = dev_get_uclass_plat(priv->blk_dev); ··· 177 176 } 178 177 179 178 return gpt_read_write_mdata(desc, mdata, MDATA_READ, 180 - primary ? g_mdata_part[0] : g_mdata_part[1]); 179 + primary ? 180 + g_mdata_part[0] : g_mdata_part[1], 181 + size); 181 182 } 182 183 183 184 static int fwu_gpt_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, 184 - bool primary) 185 + bool primary, u32 size) 185 186 { 186 187 struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev); 187 188 struct blk_desc *desc = dev_get_uclass_plat(priv->blk_dev); ··· 194 195 } 195 196 196 197 return gpt_read_write_mdata(desc, mdata, MDATA_WRITE, 197 - primary ? g_mdata_part[0] : g_mdata_part[1]); 198 + primary ? 199 + g_mdata_part[0] : g_mdata_part[1], 200 + size); 198 201 } 199 202 200 203 static const struct fwu_mdata_ops fwu_gpt_blk_ops = {
+49 -29
drivers/fwu-mdata/raw_mtd.c
··· 12 12 #include <linux/errno.h> 13 13 #include <linux/types.h> 14 14 15 - /* Internal helper structure to move data around */ 16 - struct fwu_mdata_mtd_priv { 17 - struct mtd_info *mtd; 18 - char pri_label[50]; 19 - char sec_label[50]; 20 - u32 pri_offset; 21 - u32 sec_offset; 22 - }; 23 - 24 15 enum fwu_mtd_op { 25 16 FWU_MTD_READ, 26 17 FWU_MTD_WRITE, 27 18 }; 28 - 29 - extern struct fwu_mtd_image_info fwu_mtd_images[]; 30 19 31 20 static bool mtd_is_aligned_with_block_size(struct mtd_info *mtd, u64 size) 32 21 { ··· 97 86 return ret; 98 87 } 99 88 100 - static int fwu_mtd_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary) 89 + static int fwu_mtd_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, 90 + bool primary, u32 size) 101 91 { 102 92 struct fwu_mdata_mtd_priv *mtd_priv = dev_get_priv(dev); 103 93 struct mtd_info *mtd = mtd_priv->mtd; 104 94 u32 offs = primary ? mtd_priv->pri_offset : mtd_priv->sec_offset; 105 95 106 - return mtd_io_data(mtd, offs, sizeof(struct fwu_mdata), mdata, FWU_MTD_READ); 96 + return mtd_io_data(mtd, offs, size, mdata, FWU_MTD_READ); 107 97 } 108 98 109 - static int fwu_mtd_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary) 99 + static int fwu_mtd_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, 100 + bool primary, u32 size) 110 101 { 111 102 struct fwu_mdata_mtd_priv *mtd_priv = dev_get_priv(dev); 112 103 struct mtd_info *mtd = mtd_priv->mtd; 113 104 u32 offs = primary ? mtd_priv->pri_offset : mtd_priv->sec_offset; 114 105 115 - return mtd_io_data(mtd, offs, sizeof(struct fwu_mdata), mdata, FWU_MTD_WRITE); 106 + return mtd_io_data(mtd, offs, size, mdata, FWU_MTD_WRITE); 116 107 } 117 108 118 109 static int flash_partition_offset(struct udevice *dev, const char *part_name, fdt_addr_t *offset) ··· 132 123 return (int)size; 133 124 } 134 125 135 - static int fwu_mdata_mtd_of_to_plat(struct udevice *dev) 126 + static int get_fwu_mdata_dev(struct udevice *dev) 136 127 { 137 128 struct fwu_mdata_mtd_priv *mtd_priv = dev_get_priv(dev); 138 129 const fdt32_t *phandle_p = NULL; ··· 142 133 fdt_addr_t offset; 143 134 int ret, size; 144 135 u32 phandle; 145 - ofnode bank; 146 - int off_img; 147 136 148 137 /* Find the FWU mdata storage device */ 149 138 phandle_p = ofnode_get_property(dev_ofnode(dev), ··· 197 186 return ret; 198 187 mtd_priv->sec_offset = offset; 199 188 200 - off_img = 0; 189 + return 0; 190 + } 191 + 192 + static int fwu_mtd_image_info_populate(struct udevice *dev, u8 nbanks, 193 + u16 nimages) 194 + { 195 + struct fwu_mtd_image_info *mtd_images; 196 + struct fwu_mdata_mtd_priv *mtd_priv = dev_get_priv(dev); 197 + struct udevice *mtd_dev = mtd_priv->mtd->dev; 198 + fdt_addr_t offset; 199 + ofnode bank; 200 + int off_img; 201 + u32 total_images; 201 202 203 + total_images = nbanks * nimages; 204 + mtd_priv->fwu_mtd_images = malloc(sizeof(struct fwu_mtd_image_info) * 205 + total_images); 206 + if (!mtd_priv->fwu_mtd_images) 207 + return -ENOMEM; 208 + 209 + off_img = 0; 210 + mtd_images = mtd_priv->fwu_mtd_images; 202 211 ofnode_for_each_subnode(bank, dev_ofnode(dev)) { 203 212 int bank_num, bank_offset, bank_size; 204 213 const char *bank_name; ··· 217 226 int image_num, image_offset, image_size; 218 227 const char *uuid; 219 228 220 - if (off_img == CONFIG_FWU_NUM_BANKS * 221 - CONFIG_FWU_NUM_IMAGES_PER_BANK) { 229 + if (off_img == total_images) { 222 230 log_err("DT provides more images than configured!\n"); 223 231 break; 224 232 } ··· 228 236 ofnode_read_u32(image, "offset", &image_offset); 229 237 ofnode_read_u32(image, "size", &image_size); 230 238 231 - fwu_mtd_images[off_img].start = bank_offset + image_offset; 232 - fwu_mtd_images[off_img].size = image_size; 233 - fwu_mtd_images[off_img].bank_num = bank_num; 234 - fwu_mtd_images[off_img].image_num = image_num; 235 - strcpy(fwu_mtd_images[off_img].uuidbuf, uuid); 239 + mtd_images[off_img].start = bank_offset + image_offset; 240 + mtd_images[off_img].size = image_size; 241 + mtd_images[off_img].bank_num = bank_num; 242 + mtd_images[off_img].image_num = image_num; 243 + strcpy(mtd_images[off_img].uuidbuf, uuid); 236 244 log_debug("\tImage%d: %s @0x%x\n\n", 237 245 image_num, uuid, bank_offset + image_offset); 238 246 off_img++; ··· 244 252 245 253 static int fwu_mdata_mtd_probe(struct udevice *dev) 246 254 { 247 - /* Ensure the metadata can be read. */ 248 - return fwu_get_mdata(NULL); 255 + u8 nbanks; 256 + u16 nimages; 257 + int ret; 258 + 259 + ret = get_fwu_mdata_dev(dev); 260 + if (ret) 261 + return ret; 262 + 263 + nbanks = CONFIG_FWU_NUM_BANKS; 264 + nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK; 265 + ret = fwu_mtd_image_info_populate(dev, nbanks, nimages); 266 + if (ret) 267 + return ret; 268 + 269 + return 0; 249 270 } 250 271 251 272 static struct fwu_mdata_ops fwu_mtd_ops = { ··· 264 285 .of_match = fwu_mdata_ids, 265 286 .ops = &fwu_mtd_ops, 266 287 .probe = fwu_mdata_mtd_probe, 267 - .of_to_plat = fwu_mdata_mtd_of_to_plat, 268 288 .priv_auto = sizeof(struct fwu_mdata_mtd_priv), 269 289 };
+142 -5
include/fwu.h
··· 8 8 9 9 #include <blk.h> 10 10 #include <efi.h> 11 + #include <fwu_mdata.h> 11 12 #include <mtd.h> 12 13 #include <uuid.h> 13 14 ··· 26 27 char uuidbuf[UUID_STR_LEN + 1]; 27 28 }; 28 29 30 + struct fwu_mdata_mtd_priv { 31 + struct mtd_info *mtd; 32 + char pri_label[50]; 33 + char sec_label[50]; 34 + u32 pri_offset; 35 + u32 sec_offset; 36 + struct fwu_mtd_image_info *fwu_mtd_images; 37 + }; 38 + 39 + struct fwu_data { 40 + uint32_t crc32; 41 + uint32_t version; 42 + uint32_t active_index; 43 + uint32_t previous_active_index; 44 + uint32_t metadata_size; 45 + uint32_t boot_index; 46 + uint32_t num_banks; 47 + uint32_t num_images; 48 + uint8_t bank_state[4]; 49 + bool trial_state; 50 + 51 + struct fwu_mdata *fwu_mdata; 52 + 53 + struct fwu_image_entry fwu_images[CONFIG_FWU_NUM_IMAGES_PER_BANK]; 54 + }; 55 + 29 56 struct fwu_mdata_ops { 30 57 /** 31 58 * read_mdata() - Populate the asked FWU metadata copy 32 59 * @dev: FWU metadata device 33 60 * @mdata: Output FWU mdata read 34 61 * @primary: If primary or secondary copy of metadata is to be read 62 + * @size: Size in bytes of the metadata to be read 35 63 * 36 64 * Return: 0 if OK, -ve on error 37 65 */ 38 - int (*read_mdata)(struct udevice *dev, struct fwu_mdata *mdata, bool primary); 66 + int (*read_mdata)(struct udevice *dev, struct fwu_mdata *mdata, 67 + bool primary, uint32_t size); 39 68 40 69 /** 41 70 * write_mdata() - Write the given FWU metadata copy 42 71 * @dev: FWU metadata device 43 72 * @mdata: Copy of the FWU metadata to write 44 73 * @primary: If primary or secondary copy of metadata is to be written 74 + * @size: Size in bytes of the metadata to be written 45 75 * 46 76 * Return: 0 if OK, -ve on error 47 77 */ 48 - int (*write_mdata)(struct udevice *dev, struct fwu_mdata *mdata, bool primary); 78 + int (*write_mdata)(struct udevice *dev, struct fwu_mdata *mdata, 79 + bool primary, uint32_t size); 49 80 }; 50 81 51 - #define FWU_MDATA_VERSION 0x1 52 82 #define FWU_IMAGE_ACCEPTED 0x1 53 83 84 + #define FWU_BANK_INVALID (uint8_t)0xFF 85 + #define FWU_BANK_VALID (uint8_t)0xFE 86 + #define FWU_BANK_ACCEPTED (uint8_t)0xFC 87 + 88 + enum { 89 + PRIMARY_PART = 1, 90 + SECONDARY_PART, 91 + BOTH_PARTS, 92 + }; 93 + 54 94 /* 55 95 * GUID value defined in the FWU specification for identification 56 96 * of the FWU metadata partition. ··· 80 120 /** 81 121 * fwu_read_mdata() - Wrapper around fwu_mdata_ops.read_mdata() 82 122 */ 83 - int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary); 123 + int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, 124 + bool primary, uint32_t size); 84 125 85 126 /** 86 127 * fwu_write_mdata() - Wrapper around fwu_mdata_ops.write_mdata() 87 128 */ 88 - int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary); 129 + int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, 130 + bool primary, uint32_t size); 89 131 90 132 /** 91 133 * fwu_get_mdata() - Read, verify and return the FWU metadata ··· 279 321 * Return: 0 if OK, -ve on error 280 322 */ 281 323 int fwu_mtd_get_alt_num(efi_guid_t *image_guid, u8 *alt_num, const char *mtd_dev); 324 + 325 + /** 326 + * fwu_mdata_copies_allocate() - Allocate memory for metadata 327 + * @mdata_size: Size of the metadata structure 328 + * 329 + * Allocate memory for storing both the copies of the FWU metadata. The 330 + * copies are then used as a cache for storing FWU metadata contents. 331 + * 332 + * Return: 0 if OK, -ve on error 333 + */ 334 + int fwu_mdata_copies_allocate(u32 mdata_size); 335 + 336 + /** 337 + * fwu_get_dev() - Return the FWU metadata device 338 + * 339 + * Return the pointer to the FWU metadata device. 340 + * 341 + * Return: Pointer to the FWU metadata dev 342 + */ 343 + struct udevice *fwu_get_dev(void); 344 + 345 + /** 346 + * fwu_get_data() - Return the version agnostic FWU structure 347 + * 348 + * Return the pointer to the version agnostic FWU structure. 349 + * 350 + * Return: Pointer to the FWU data structure 351 + */ 352 + struct fwu_data *fwu_get_data(void); 353 + 354 + /** 355 + * fwu_sync_mdata() - Update given meta-data partition(s) with the copy provided 356 + * @data: FWU Data structure 357 + * @part: Bitmask of FWU metadata partitions to be written to 358 + * 359 + * Return: 0 if OK, -ve on error 360 + */ 361 + int fwu_sync_mdata(struct fwu_mdata *mdata, int part); 362 + 363 + /** 364 + * fwu_populate_mdata_image_info() - Populate the image information 365 + * of the metadata 366 + * @data: Version agnostic FWU metadata information 367 + * 368 + * Populate the image information in the FWU metadata by copying it 369 + * from the version agnostic structure. This is done before the 370 + * metadata gets written to the storage media. 371 + * 372 + * Return: None 373 + */ 374 + void fwu_populate_mdata_image_info(struct fwu_data *data); 375 + 376 + /** 377 + * fwu_get_mdata_size() - Get the FWU metadata size 378 + * @mdata_size: Size of the metadata structure 379 + * 380 + * Get the size of the FWU metadata from the structure. This is later used 381 + * to allocate memory for the structure. 382 + * 383 + * Return: 0 if OK, -ve on error 384 + */ 385 + int fwu_get_mdata_size(uint32_t *mdata_size); 386 + 387 + /** 388 + * fwu_state_machine_updates() - Update FWU state of the platform 389 + * @trial_state: Is platform transitioning into Trial State 390 + * @update_index: Bank number to which images have been updated 391 + * 392 + * On successful completion of updates, transition the platform to 393 + * either Trial State or Regular State. 394 + * 395 + * To transition the platform to Trial State, start the 396 + * TrialStateCtr counter, followed by setting the value of bank_state 397 + * field of the metadata to Valid state(applicable only in version 2 398 + * of metadata). 399 + * 400 + * In case, the platform is to transition directly to Regular State, 401 + * update the bank_state field of the metadata to Accepted 402 + * state(applicable only in version 2 of metadata). 403 + * 404 + * Return: 0 if OK, -ve on error 405 + */ 406 + int fwu_state_machine_updates(bool trial_state, uint32_t update_index); 407 + 408 + /** 409 + * fwu_init() - FWU specific initialisations 410 + * 411 + * Carry out some FWU specific initialisations including allocation 412 + * of memory for the metadata copies, and reading the FWU metadata 413 + * copies into the allocated memory. The metadata fields are then 414 + * copied into a version agnostic structure. 415 + * 416 + * Return: 0 if OK, -ve on error 417 + */ 418 + int fwu_init(void); 282 419 283 420 #endif /* _FWU_H_ */
+65 -6
include/fwu_mdata.h
··· 11 11 12 12 /** 13 13 * struct fwu_image_bank_info - firmware image information 14 - * @image_uuid: Guid value of the image in this bank 14 + * @image_guid: Guid value of the image in this bank 15 15 * @accepted: Acceptance status of the image 16 16 * @reserved: Reserved 17 17 * ··· 20 20 * acceptance status 21 21 */ 22 22 struct fwu_image_bank_info { 23 - efi_guid_t image_uuid; 23 + efi_guid_t image_guid; 24 24 uint32_t accepted; 25 25 uint32_t reserved; 26 26 } __packed; 27 27 28 28 /** 29 29 * struct fwu_image_entry - information for a particular type of image 30 - * @image_type_uuid: Guid value for identifying the image type 31 - * @location_uuid: Guid of the storage volume where the image is located 30 + * @image_type_guid: Guid value for identifying the image type 31 + * @location_guid: Guid of the storage volume where the image is located 32 32 * @img_bank_info: Array containing properties of images 33 33 * 34 34 * This structure contains information on various types of updatable ··· 36 36 * information per bank. 37 37 */ 38 38 struct fwu_image_entry { 39 - efi_guid_t image_type_uuid; 40 - efi_guid_t location_uuid; 39 + efi_guid_t image_type_guid; 40 + efi_guid_t location_guid; 41 41 struct fwu_image_bank_info img_bank_info[CONFIG_FWU_NUM_BANKS]; 42 42 } __packed; 43 43 44 + /** 45 + * struct fwu_fw_store_desc - FWU updatable image information 46 + * @num_banks: Number of firmware banks 47 + * @num_images: Number of images per bank 48 + * @img_entry_size: The size of the img_entry array 49 + * @bank_info_entry_size: The size of the img_bank_info array 50 + * @img_entry: Array of image entries each giving information on a image 51 + * 52 + * This image descriptor structure contains information on the number of 53 + * updatable banks and images per bank. It also gives the total sizes of 54 + * the fwu_image_entry and fwu_image_bank_info arrays. This structure is 55 + * only present in version 2 of the metadata structure. 56 + */ 57 + struct fwu_fw_store_desc { 58 + uint8_t num_banks; 59 + uint8_t reserved; 60 + uint16_t num_images; 61 + uint16_t img_entry_size; 62 + uint16_t bank_info_entry_size; 63 + 64 + struct fwu_image_entry img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK]; 65 + } __packed; 66 + 67 + #if defined(CONFIG_FWU_MDATA_V1) 44 68 /** 45 69 * struct fwu_mdata - FWU metadata structure for multi-bank updates 46 70 * @crc32: crc32 value for the FWU metadata ··· 64 88 65 89 struct fwu_image_entry img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK]; 66 90 } __packed; 91 + 92 + #else /* CONFIG_FWU_MDATA_V1 */ 93 + /** 94 + * struct fwu_mdata - FWU metadata structure for multi-bank updates 95 + * @crc32: crc32 value for the FWU metadata 96 + * @version: FWU metadata version 97 + * @active_index: Index of the bank currently used for booting images 98 + * @previous_active_inde: Index of the bank used before the current bank 99 + * being used for booting 100 + * @metadata_size: Size of the entire metadata structure, including the 101 + * image descriptors 102 + * @desc_offset: The offset from the start of this structure where the 103 + * image descriptor structure starts. 0 if absent 104 + * @bank_state: State of each bank, valid, invalid or accepted 105 + * @fw_desc: The structure describing the FWU updatable images 106 + * 107 + * This is the top level structure used to store all information for performing 108 + * multi bank updates on the platform. This contains info on the bank being 109 + * used to boot along with the information on state of individual banks. 110 + */ 111 + struct fwu_mdata { 112 + uint32_t crc32; 113 + uint32_t version; 114 + uint32_t active_index; 115 + uint32_t previous_active_index; 116 + uint32_t metadata_size; 117 + uint16_t desc_offset; 118 + uint16_t reserved1; 119 + uint8_t bank_state[4]; 120 + uint32_t reserved2; 121 + 122 + // struct fwu_fw_store_desc fw_desc; 123 + } __packed; 124 + 125 + #endif /* CONFIG_FWU_MDATA_V1 */ 67 126 68 127 #endif /* _FWU_MDATA_H_ */
+9 -5
lib/efi_loader/efi_capsule.c
··· 480 480 if (ret != EFI_SUCCESS) 481 481 log_err("Unable to set the Accept bit for the image %pUs\n", 482 482 image_guid); 483 + 484 + status = fwu_state_machine_updates(0, active_idx); 485 + if (status < 0) 486 + ret = EFI_DEVICE_ERROR; 487 + 483 488 } 484 489 485 490 return ret; ··· 521 526 log_err("Failed to update FWU metadata index values\n"); 522 527 } else { 523 528 log_debug("Successfully updated the active_index\n"); 524 - if (fw_accept_os) { 525 - status = fwu_trial_state_ctr_start(); 526 - if (status < 0) 527 - ret = EFI_DEVICE_ERROR; 528 - } 529 + status = fwu_state_machine_updates(fw_accept_os ? 1 : 0, 530 + update_index); 531 + if (status < 0) 532 + ret = EFI_DEVICE_ERROR; 529 533 } 530 534 531 535 return ret;
+14
lib/fwu_updates/Kconfig
··· 31 31 the platform is allowed to boot in Trial State after an 32 32 update. 33 33 34 + config FWU_MDATA_V1 35 + bool "Enable support FWU Metadata version 1" 36 + help 37 + The FWU specification supports two versions of the 38 + metadata structure. This option enables support for FWU 39 + Metadata version 1 access. 40 + 41 + config FWU_MDATA_V2 42 + bool "Enable support FWU Metadata version 2" 43 + help 44 + The FWU specification supports two versions of the 45 + metadata structure. This option enables support for FWU 46 + Metadata version 2 access. 47 + 34 48 endif
+2
lib/fwu_updates/Makefile
··· 6 6 obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu.o 7 7 obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_gpt.o 8 8 obj-$(CONFIG_FWU_MDATA_MTD) += fwu_mtd.o 9 + obj-$(CONFIG_FWU_MDATA_V1) += fwu_v1.o 10 + obj-$(CONFIG_FWU_MDATA_V2) += fwu_v2.o
+138 -66
lib/fwu_updates/fwu.c
··· 10 10 #include <event.h> 11 11 #include <fwu.h> 12 12 #include <fwu_mdata.h> 13 + #include <log.h> 13 14 #include <malloc.h> 14 15 15 16 #include <linux/errno.h> ··· 17 18 18 19 #include <u-boot/crc.h> 19 20 20 - static struct fwu_mdata g_mdata; /* = {0} makes uninit crc32 always invalid */ 21 + struct fwu_data g_fwu_data; 21 22 static struct udevice *g_dev; 22 23 static u8 in_trial; 23 24 static u8 boottime_check; ··· 25 26 enum { 26 27 IMAGE_ACCEPT_SET = 1, 27 28 IMAGE_ACCEPT_CLEAR, 28 - }; 29 - 30 - enum { 31 - PRIMARY_PART = 1, 32 - SECONDARY_PART, 33 - BOTH_PARTS, 34 29 }; 35 30 36 31 static int trial_counter_update(u16 *trial_state_ctr) ··· 106 101 return ret; 107 102 } 108 103 109 - static int in_trial_state(struct fwu_mdata *mdata) 104 + static u32 in_trial_state(void) 110 105 { 111 - u32 i, active_bank; 112 - struct fwu_image_entry *img_entry; 113 - struct fwu_image_bank_info *img_bank_info; 114 - 115 - active_bank = mdata->active_index; 116 - img_entry = &mdata->img_entry[0]; 117 - for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { 118 - img_bank_info = &img_entry[i].img_bank_info[active_bank]; 119 - if (!img_bank_info->accepted) { 120 - log_info("System booting in Trial State\n"); 121 - return 1; 122 - } 123 - } 124 - 125 - return 0; 106 + return g_fwu_data.trial_state; 126 107 } 127 108 128 109 static int fwu_get_image_type_id(u8 image_index, efi_guid_t *image_type_id) ··· 141 122 return -ENOENT; 142 123 } 143 124 125 + static int mdata_crc_check(struct fwu_mdata *mdata) 126 + { 127 + int ret; 128 + u32 calc_crc32; 129 + uint32_t mdata_size; 130 + void *buf = &mdata->version; 131 + 132 + ret = fwu_get_mdata_size(&mdata_size); 133 + if (ret) 134 + return ret; 135 + 136 + calc_crc32 = crc32(0, buf, mdata_size - sizeof(u32)); 137 + return calc_crc32 == mdata->crc32 ? 0 : -EINVAL; 138 + } 139 + 140 + static void fwu_data_crc_update(uint32_t crc32) 141 + { 142 + g_fwu_data.crc32 = crc32; 143 + } 144 + 145 + /** 146 + * fwu_get_data() - Return the version agnostic FWU structure 147 + * 148 + * Return the pointer to the version agnostic FWU structure. 149 + * 150 + * Return: Pointer to the FWU data structure 151 + */ 152 + struct fwu_data *fwu_get_data(void) 153 + { 154 + return &g_fwu_data; 155 + } 156 + 157 + static void fwu_populate_mdata_bank_index(struct fwu_data *fwu_data) 158 + { 159 + struct fwu_mdata *mdata = fwu_data->fwu_mdata; 160 + 161 + mdata->active_index = fwu_data->active_index; 162 + mdata->previous_active_index = fwu_data->previous_active_index; 163 + } 164 + 165 + /** 166 + * fwu_get_dev() - Return the FWU metadata device 167 + * 168 + * Return the pointer to the FWU metadata device. 169 + * 170 + * Return: Pointer to the FWU metadata dev 171 + */ 172 + struct udevice *fwu_get_dev(void) 173 + { 174 + return g_dev; 175 + } 176 + 144 177 /** 145 178 * fwu_sync_mdata() - Update given meta-data partition(s) with the copy provided 146 - * @mdata: FWU metadata structure 179 + * @data: FWU Data structure 147 180 * @part: Bitmask of FWU metadata partitions to be written to 148 181 * 149 182 * Return: 0 if OK, -ve on error 150 183 */ 151 - static int fwu_sync_mdata(struct fwu_mdata *mdata, int part) 184 + int fwu_sync_mdata(struct fwu_mdata *mdata, int part) 152 185 { 186 + int err; 187 + uint mdata_size; 153 188 void *buf = &mdata->version; 154 - int err; 155 189 156 190 if (part == BOTH_PARTS) { 157 191 err = fwu_sync_mdata(mdata, SECONDARY_PART); ··· 159 193 return err; 160 194 part = PRIMARY_PART; 161 195 } 196 + 197 + err = fwu_get_mdata_size(&mdata_size); 198 + if (err) 199 + return err; 162 200 163 201 /* 164 202 * Calculate the crc32 for the updated FWU metadata 165 203 * and put the updated value in the FWU metadata crc32 166 204 * field 167 205 */ 168 - mdata->crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32)); 206 + mdata->crc32 = crc32(0, buf, mdata_size - sizeof(u32)); 207 + fwu_data_crc_update(mdata->crc32); 169 208 170 - err = fwu_write_mdata(g_dev, mdata, part == PRIMARY_PART); 209 + err = fwu_write_mdata(g_dev, mdata, part == PRIMARY_PART, mdata_size); 171 210 if (err) { 172 211 log_err("Unable to write %s mdata\n", 173 212 part == PRIMARY_PART ? "primary" : "secondary"); 174 213 return err; 175 214 } 176 215 177 - /* update the cached copy of meta-data */ 178 - memcpy(&g_mdata, mdata, sizeof(struct fwu_mdata)); 179 - 180 216 return 0; 181 217 } 182 218 183 - static inline int mdata_crc_check(struct fwu_mdata *mdata) 219 + /** 220 + * fwu_mdata_copies_allocate() - Allocate memory for metadata 221 + * @mdata_size: Size of the metadata structure 222 + * 223 + * Allocate memory for storing both the copies of the FWU metadata. The 224 + * copies are then used as a cache for storing FWU metadata contents. 225 + * 226 + * Return: 0 if OK, -ve on error 227 + */ 228 + int fwu_mdata_copies_allocate(u32 mdata_size) 184 229 { 185 - void *buf = &mdata->version; 186 - u32 calc_crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32)); 230 + if (g_fwu_data.fwu_mdata) 231 + return 0; 187 232 188 - return calc_crc32 == mdata->crc32 ? 0 : -EINVAL; 233 + /* 234 + * Allocate the total memory that would be needed for both 235 + * the copies. 236 + */ 237 + g_fwu_data.fwu_mdata = calloc(2, mdata_size); 238 + if (!g_fwu_data.fwu_mdata) { 239 + log_err("Unable to allocate space for FWU metadata\n"); 240 + return -ENOMEM; 241 + } 242 + 243 + return 0; 189 244 } 190 245 191 246 /** ··· 201 256 int fwu_get_mdata(struct fwu_mdata *mdata) 202 257 { 203 258 int err; 259 + uint32_t mdata_size; 204 260 bool parts_ok[2] = { false }; 205 - struct fwu_mdata s, *parts_mdata[2]; 261 + struct fwu_mdata *parts_mdata[2]; 262 + 263 + err = fwu_get_mdata_size(&mdata_size); 264 + if (err) 265 + return err; 266 + 267 + parts_mdata[0] = g_fwu_data.fwu_mdata; 268 + if (!parts_mdata[0]) { 269 + log_err("Memory not allocated for the FWU Metadata copies\n"); 270 + return -ENOMEM; 271 + } 206 272 207 - parts_mdata[0] = &g_mdata; 208 - parts_mdata[1] = &s; 273 + parts_mdata[1] = (struct fwu_mdata *)((char *)parts_mdata[0] + 274 + mdata_size); 209 275 210 276 /* if mdata already read and ready */ 211 277 err = mdata_crc_check(parts_mdata[0]); 212 278 if (!err) 213 279 goto ret_mdata; 214 - /* else read, verify and, if needed, fix mdata */ 280 + 215 281 282 + /* else read, verify and, if needed, fix mdata */ 216 283 for (int i = 0; i < 2; i++) { 217 284 parts_ok[i] = false; 218 - err = fwu_read_mdata(g_dev, parts_mdata[i], !i); 285 + err = fwu_read_mdata(g_dev, parts_mdata[i], !i, mdata_size); 219 286 if (!err) { 220 287 err = mdata_crc_check(parts_mdata[i]); 221 288 if (!err) ··· 230 297 * Before returning, check that both the 231 298 * FWU metadata copies are the same. 232 299 */ 233 - err = memcmp(parts_mdata[0], parts_mdata[1], sizeof(struct fwu_mdata)); 300 + err = memcmp(parts_mdata[0], parts_mdata[1], mdata_size); 234 301 if (!err) 235 302 goto ret_mdata; 236 303 ··· 247 314 if (parts_ok[i]) 248 315 continue; 249 316 250 - memcpy(parts_mdata[i], parts_mdata[1 - i], sizeof(struct fwu_mdata)); 317 + memcpy(parts_mdata[i], parts_mdata[1 - i], mdata_size); 251 318 err = fwu_sync_mdata(parts_mdata[i], i ? SECONDARY_PART : PRIMARY_PART); 252 319 if (err) { 253 320 log_debug("mdata : %s write failed\n", i ? "secondary" : "primary"); ··· 257 324 258 325 ret_mdata: 259 326 if (!err && mdata) 260 - memcpy(mdata, parts_mdata[0], sizeof(struct fwu_mdata)); 327 + memcpy(mdata, parts_mdata[0], mdata_size); 261 328 262 329 return err; 263 330 } ··· 275 342 int fwu_get_active_index(uint *active_idx) 276 343 { 277 344 int ret = 0; 278 - struct fwu_mdata *mdata = &g_mdata; 345 + struct fwu_data *data = &g_fwu_data; 279 346 280 347 /* 281 348 * Found the FWU metadata partition, now read the active_index 282 349 * value 283 350 */ 284 - *active_idx = mdata->active_index; 351 + *active_idx = data->active_index; 285 352 if (*active_idx >= CONFIG_FWU_NUM_BANKS) { 286 353 log_debug("Active index value read is incorrect\n"); 287 354 ret = -EINVAL; ··· 302 369 int fwu_set_active_index(uint active_idx) 303 370 { 304 371 int ret; 305 - struct fwu_mdata *mdata = &g_mdata; 372 + struct fwu_data *data = &g_fwu_data; 306 373 307 374 if (active_idx >= CONFIG_FWU_NUM_BANKS) { 308 375 log_debug("Invalid active index value\n"); ··· 313 380 * Update the active index and previous_active_index fields 314 381 * in the FWU metadata 315 382 */ 316 - mdata->previous_active_index = mdata->active_index; 317 - mdata->active_index = active_idx; 383 + data->previous_active_index = data->active_index; 384 + data->active_index = active_idx; 385 + 386 + fwu_populate_mdata_bank_index(data); 318 387 319 388 /* 320 389 * Now write this updated FWU metadata to both the 321 390 * FWU metadata partitions 322 391 */ 323 - ret = fwu_sync_mdata(mdata, BOTH_PARTS); 392 + ret = fwu_sync_mdata(data->fwu_mdata, BOTH_PARTS); 324 393 if (ret) { 325 394 log_debug("Failed to update FWU metadata partitions\n"); 326 395 ret = -EIO; ··· 346 415 int ret, i; 347 416 uint update_bank; 348 417 efi_guid_t *image_guid, image_type_id; 349 - struct fwu_mdata *mdata = &g_mdata; 418 + struct fwu_data *data = &g_fwu_data; 350 419 struct fwu_image_entry *img_entry; 351 420 struct fwu_image_bank_info *img_bank_info; 352 421 ··· 365 434 366 435 ret = -EINVAL; 367 436 /* 368 - * The FWU metadata has been read. Now get the image_uuid for the 437 + * The FWU metadata has been read. Now get the image_guid for the 369 438 * image with the update_bank. 370 439 */ 371 440 for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { 372 441 if (!guidcmp(&image_type_id, 373 - &mdata->img_entry[i].image_type_uuid)) { 374 - img_entry = &mdata->img_entry[i]; 442 + &data->fwu_images[i].image_type_guid)) { 443 + img_entry = &data->fwu_images[i]; 375 444 img_bank_info = &img_entry->img_bank_info[update_bank]; 376 - image_guid = &img_bank_info->image_uuid; 445 + image_guid = &img_bank_info->image_guid; 377 446 ret = fwu_plat_get_alt_num(g_dev, image_guid, alt_num); 378 447 if (ret) 379 448 log_debug("alt_num not found for partition with GUID %pUs\n", ··· 407 476 { 408 477 int ret; 409 478 u32 cur_active_index; 410 - struct fwu_mdata *mdata = &g_mdata; 479 + struct fwu_data *data = &g_fwu_data; 411 480 412 481 /* 413 482 * Swap the active index and previous_active_index fields 414 483 * in the FWU metadata 415 484 */ 416 - cur_active_index = mdata->active_index; 417 - mdata->active_index = mdata->previous_active_index; 418 - mdata->previous_active_index = cur_active_index; 485 + cur_active_index = data->active_index; 486 + data->active_index = data->previous_active_index; 487 + data->previous_active_index = cur_active_index; 488 + 489 + fwu_populate_mdata_bank_index(data); 419 490 420 491 /* 421 492 * Now write this updated FWU metadata to both the 422 493 * FWU metadata partitions 423 494 */ 424 - ret = fwu_sync_mdata(mdata, BOTH_PARTS); 495 + ret = fwu_sync_mdata(data->fwu_mdata, BOTH_PARTS); 425 496 if (ret) { 426 497 log_debug("Failed to update FWU metadata partitions\n"); 427 498 ret = -EIO; ··· 448 519 static int fwu_clrset_image_accept(efi_guid_t *img_type_id, u32 bank, u8 action) 449 520 { 450 521 int ret, i; 451 - struct fwu_mdata *mdata = &g_mdata; 522 + struct fwu_data *data = &g_fwu_data; 452 523 struct fwu_image_entry *img_entry; 453 524 struct fwu_image_bank_info *img_bank_info; 454 525 455 - img_entry = &mdata->img_entry[0]; 526 + img_entry = &data->fwu_images[0]; 456 527 for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { 457 - if (!guidcmp(&img_entry[i].image_type_uuid, img_type_id)) { 528 + if (!guidcmp(&img_entry[i].image_type_guid, img_type_id)) { 458 529 img_bank_info = &img_entry[i].img_bank_info[bank]; 459 530 if (action == IMAGE_ACCEPT_SET) 460 531 img_bank_info->accepted |= FWU_IMAGE_ACCEPTED; 461 532 else 462 533 img_bank_info->accepted = 0; 463 534 464 - ret = fwu_sync_mdata(mdata, BOTH_PARTS); 535 + fwu_populate_mdata_image_info(data); 536 + ret = fwu_sync_mdata(data->fwu_mdata, BOTH_PARTS); 465 537 goto out; 466 538 } 467 539 } ··· 627 699 return 0; 628 700 } 629 701 630 - ret = fwu_get_mdata(NULL); 702 + ret = fwu_init(); 631 703 if (ret) { 632 - log_debug("Unable to read meta-data\n"); 704 + log_debug("fwu_init() failed\n"); 633 705 return ret; 634 706 } 635 707 ··· 665 737 if (efi_init_obj_list() != EFI_SUCCESS) 666 738 return 0; 667 739 668 - in_trial = in_trial_state(&g_mdata); 740 + in_trial = in_trial_state(); 669 741 if (!in_trial || (ret = fwu_trial_count_update()) > 0) 670 742 ret = trial_counter_update(NULL); 671 743
+17 -17
lib/fwu_updates/fwu_mtd.c
··· 15 15 16 16 #include <dm/ofnode.h> 17 17 18 - struct fwu_mtd_image_info 19 - fwu_mtd_images[CONFIG_FWU_NUM_BANKS * CONFIG_FWU_NUM_IMAGES_PER_BANK]; 20 - 21 18 static struct fwu_mtd_image_info *mtd_img_by_uuid(const char *uuidbuf) 22 19 { 23 - int num_images = ARRAY_SIZE(fwu_mtd_images); 20 + int num_images; 21 + struct fwu_mdata_mtd_priv *mtd_priv = dev_get_priv(fwu_get_dev()); 22 + struct fwu_mtd_image_info *image_info = mtd_priv->fwu_mtd_images; 23 + 24 + if (!image_info) 25 + return NULL; 26 + 27 + num_images = CONFIG_FWU_NUM_BANKS * 28 + CONFIG_FWU_NUM_IMAGES_PER_BANK; 24 29 25 30 for (int i = 0; i < num_images; i++) 26 - if (!strcmp(uuidbuf, fwu_mtd_images[i].uuidbuf)) 27 - return &fwu_mtd_images[i]; 31 + if (!strcmp(uuidbuf, image_info[i].uuidbuf)) 32 + return &image_info[i]; 28 33 29 34 return NULL; 30 35 } ··· 107 112 return fwu_mtd_get_alt_num(image_id, alt_num, "nor1"); 108 113 } 109 114 110 - static int gen_image_alt_info(char *buf, size_t len, int sidx, 115 + static int gen_image_alt_info(char *buf, size_t len, 111 116 struct fwu_image_entry *img, struct mtd_info *mtd) 112 117 { 113 118 char *p = buf, *end = buf + len; ··· 131 136 132 137 /* Query a partition by image UUID */ 133 138 bank = &img->img_bank_info[i]; 134 - uuid_bin_to_str(bank->image_uuid.b, uuidbuf, UUID_STR_FORMAT_STD); 139 + uuid_bin_to_str(bank->image_guid.b, uuidbuf, UUID_STR_FORMAT_STD); 135 140 136 141 mtd_img_info = mtd_img_by_uuid(uuidbuf); 137 142 if (!mtd_img_info) { ··· 158 163 159 164 int fwu_gen_alt_info_from_mtd(char *buf, size_t len, struct mtd_info *mtd) 160 165 { 161 - struct fwu_mdata mdata; 162 166 int i, l, ret; 163 - 164 - ret = fwu_get_mdata(&mdata); 165 - if (ret < 0) { 166 - log_err("Failed to get the FWU mdata.\n"); 167 - return ret; 168 - } 167 + struct fwu_data *data = fwu_get_data(); 168 + struct fwu_image_entry *img_entry; 169 169 170 170 for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { 171 - ret = gen_image_alt_info(buf, len, i * CONFIG_FWU_NUM_BANKS, 172 - &mdata.img_entry[i], mtd); 171 + img_entry = &data->fwu_images[i]; 172 + ret = gen_image_alt_info(buf, len, img_entry, mtd); 173 173 if (ret) 174 174 break; 175 175
+167
lib/fwu_updates/fwu_v1.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Copyright (c) 2024, Linaro Limited 4 + */ 5 + 6 + #include <fwu.h> 7 + #include <fwu_mdata.h> 8 + 9 + #include <linux/types.h> 10 + 11 + #define FWU_MDATA_VERSION 0x1U 12 + 13 + static uint32_t fwu_check_trial_state(struct fwu_mdata *mdata, uint32_t bank) 14 + { 15 + u32 i; 16 + struct fwu_image_entry *img_entry; 17 + struct fwu_image_bank_info *img_bank_info; 18 + 19 + img_entry = &mdata->img_entry[0]; 20 + for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { 21 + img_bank_info = &img_entry[i].img_bank_info[bank]; 22 + if (!img_bank_info->accepted) { 23 + return 1; 24 + } 25 + } 26 + 27 + return 0; 28 + } 29 + 30 + static void fwu_data_init(void) 31 + { 32 + size_t image_info_size; 33 + void *dst_img_info, *src_img_info; 34 + struct fwu_data *data = fwu_get_data(); 35 + struct fwu_mdata *mdata = data->fwu_mdata; 36 + 37 + data->crc32 = mdata->crc32; 38 + data->version = mdata->version; 39 + data->active_index = mdata->active_index; 40 + data->previous_active_index = mdata->previous_active_index; 41 + 42 + data->metadata_size = sizeof(struct fwu_mdata); 43 + data->num_banks = CONFIG_FWU_NUM_BANKS; 44 + data->num_images = CONFIG_FWU_NUM_IMAGES_PER_BANK; 45 + fwu_plat_get_bootidx(&data->boot_index); 46 + data->trial_state = fwu_check_trial_state(mdata, data->boot_index); 47 + 48 + src_img_info = &mdata->img_entry[0]; 49 + dst_img_info = &data->fwu_images[0]; 50 + image_info_size = sizeof(data->fwu_images); 51 + 52 + memcpy(dst_img_info, src_img_info, image_info_size); 53 + } 54 + 55 + static int fwu_trial_state_update(bool trial_state) 56 + { 57 + int ret; 58 + struct fwu_data *data = fwu_get_data(); 59 + 60 + if (trial_state) { 61 + ret = fwu_trial_state_ctr_start(); 62 + if (ret) 63 + return ret; 64 + } 65 + 66 + data->trial_state = trial_state; 67 + 68 + return 0; 69 + } 70 + 71 + /** 72 + * fwu_populate_mdata_image_info() - Populate the image information 73 + * of the metadata 74 + * @data: Version agnostic FWU metadata information 75 + * 76 + * Populate the image information in the FWU metadata by copying it 77 + * from the version agnostic structure. This is done before the 78 + * metadata gets written to the storage media. 79 + * 80 + * Return: None 81 + */ 82 + void fwu_populate_mdata_image_info(struct fwu_data *data) 83 + { 84 + size_t image_info_size; 85 + void *dst_img_info, *src_img_info; 86 + struct fwu_mdata *mdata = data->fwu_mdata; 87 + 88 + image_info_size = sizeof(data->fwu_images); 89 + dst_img_info = &mdata->img_entry[0]; 90 + src_img_info = &data->fwu_images[0]; 91 + 92 + memcpy(dst_img_info, src_img_info, image_info_size); 93 + } 94 + 95 + /** 96 + * fwu_state_machine_updates() - Update FWU state of the platform 97 + * @trial_state: Is platform transitioning into Trial State 98 + * @update_index: Bank number to which images have been updated 99 + * 100 + * On successful completion of updates, transition the platform to 101 + * either Trial State or Regular State. 102 + * 103 + * To transition the platform to Trial State, start the 104 + * TrialStateCtr counter, followed by setting the value of bank_state 105 + * field of the metadata to Valid state(applicable only in version 2 106 + * of metadata). 107 + * 108 + * In case, the platform is to transition directly to Regular State, 109 + * update the bank_state field of the metadata to Accepted 110 + * state(applicable only in version 2 of metadata). 111 + * 112 + * Return: 0 if OK, -ve on error 113 + */ 114 + int fwu_state_machine_updates(bool trial_state, 115 + __maybe_unused uint32_t update_index) 116 + { 117 + return fwu_trial_state_update(trial_state); 118 + } 119 + 120 + /** 121 + * fwu_get_mdata_size() - Get the FWU metadata size 122 + * @mdata_size: Size of the metadata structure 123 + * 124 + * Get the size of the FWU metadata. 125 + * 126 + * Return: 0 if OK, -ve on error 127 + */ 128 + int fwu_get_mdata_size(uint32_t *mdata_size) 129 + { 130 + *mdata_size = sizeof(struct fwu_mdata); 131 + 132 + return 0; 133 + } 134 + 135 + /** 136 + * fwu_init() - FWU specific initialisations 137 + * 138 + * Carry out some FWU specific initialisations including allocation 139 + * of memory for the metadata copies, and reading the FWU metadata 140 + * copies into the allocated memory. The metadata fields are then 141 + * copied into a version agnostic structure. 142 + * 143 + * Return: 0 if OK, -ve on error 144 + */ 145 + int fwu_init(void) 146 + { 147 + int ret; 148 + uint32_t mdata_size; 149 + 150 + fwu_get_mdata_size(&mdata_size); 151 + 152 + ret = fwu_mdata_copies_allocate(mdata_size); 153 + if (ret) 154 + return ret; 155 + 156 + /* 157 + * Now read the entire structure, both copies, and 158 + * validate that the copies. 159 + */ 160 + ret = fwu_get_mdata(NULL); 161 + if (ret) 162 + return ret; 163 + 164 + fwu_data_init(); 165 + 166 + return 0; 167 + }
+260
lib/fwu_updates/fwu_v2.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Copyright (c) 2024, Linaro Limited 4 + */ 5 + 6 + #include <fwu.h> 7 + #include <fwu_mdata.h> 8 + #include <log.h> 9 + 10 + #include <linux/types.h> 11 + 12 + #define FWU_MDATA_VERSION 0x2U 13 + 14 + static inline struct fwu_fw_store_desc *fwu_get_fw_desc(struct fwu_mdata *mdata) 15 + { 16 + return (struct fwu_fw_store_desc *)((u8 *)mdata + sizeof(*mdata)); 17 + } 18 + 19 + static uint32_t fwu_check_trial_state(struct fwu_mdata *mdata, uint32_t bank) 20 + { 21 + return mdata->bank_state[bank] == FWU_BANK_VALID ? 1 : 0; 22 + } 23 + 24 + static void fwu_data_init(void) 25 + { 26 + int i; 27 + size_t image_info_size; 28 + void *dst_img_info, *src_img_info; 29 + struct fwu_data *data = fwu_get_data(); 30 + struct fwu_mdata *mdata = data->fwu_mdata; 31 + 32 + data->crc32 = mdata->crc32; 33 + data->version = mdata->version; 34 + data->active_index = mdata->active_index; 35 + data->previous_active_index = mdata->previous_active_index; 36 + data->metadata_size = mdata->metadata_size; 37 + fwu_plat_get_bootidx(&data->boot_index); 38 + data->trial_state = fwu_check_trial_state(mdata, data->boot_index); 39 + 40 + data->num_banks = fwu_get_fw_desc(mdata)->num_banks; 41 + data->num_images = fwu_get_fw_desc(mdata)->num_images; 42 + 43 + for (i = 0; i < 4; i++) { 44 + data->bank_state[i] = mdata->bank_state[i]; 45 + } 46 + 47 + image_info_size = sizeof(data->fwu_images); 48 + src_img_info = &fwu_get_fw_desc(mdata)->img_entry[0]; 49 + dst_img_info = &data->fwu_images[0]; 50 + 51 + memcpy(dst_img_info, src_img_info, image_info_size); 52 + } 53 + 54 + static int fwu_mdata_sanity_checks(void) 55 + { 56 + uint8_t num_banks; 57 + uint16_t num_images; 58 + struct fwu_data *data = fwu_get_data(); 59 + struct fwu_mdata *mdata = data->fwu_mdata; 60 + 61 + if (mdata->version != FWU_MDATA_VERSION) { 62 + log_err("FWU metadata version %u. Expected value of %u\n", 63 + mdata->version, FWU_MDATA_VERSION); 64 + return -EINVAL; 65 + } 66 + 67 + if (!mdata->desc_offset) { 68 + log_err("No image information provided with the Metadata. "); 69 + log_err("Image information expected in the metadata\n"); 70 + return -EINVAL; 71 + } 72 + 73 + if (mdata->desc_offset != 0x20) { 74 + log_err("Descriptor Offset(0x%x) in the FWU Metadata not equal to 0x20\n", 75 + mdata->desc_offset); 76 + return -EINVAL; 77 + } 78 + 79 + num_banks = fwu_get_fw_desc(mdata)->num_banks; 80 + num_images = fwu_get_fw_desc(mdata)->num_images; 81 + 82 + if (num_banks != CONFIG_FWU_NUM_BANKS) { 83 + log_err("Number of Banks(%u) in FWU Metadata different from the configured value(%d)", 84 + num_banks, CONFIG_FWU_NUM_BANKS); 85 + return -EINVAL; 86 + } 87 + 88 + if (num_images != CONFIG_FWU_NUM_IMAGES_PER_BANK) { 89 + log_err("Number of Images(%u) in FWU Metadata different from the configured value(%d)", 90 + num_images, CONFIG_FWU_NUM_IMAGES_PER_BANK); 91 + return -EINVAL; 92 + } 93 + 94 + return 0; 95 + } 96 + 97 + static int fwu_bank_state_update(bool trial_state, uint32_t bank) 98 + { 99 + int ret; 100 + struct fwu_data *data = fwu_get_data(); 101 + struct fwu_mdata *mdata = data->fwu_mdata; 102 + 103 + mdata->bank_state[bank] = data->bank_state[bank] = trial_state ? 104 + FWU_BANK_VALID : FWU_BANK_ACCEPTED; 105 + 106 + ret = fwu_sync_mdata(mdata, BOTH_PARTS); 107 + if (ret) 108 + log_err("Unable to set bank_state for bank %u\n", bank); 109 + else 110 + data->trial_state = trial_state; 111 + 112 + return ret; 113 + } 114 + 115 + static int fwu_trial_state_start(uint update_index) 116 + { 117 + int ret; 118 + 119 + ret = fwu_trial_state_ctr_start(); 120 + if (ret) 121 + return ret; 122 + 123 + ret = fwu_bank_state_update(1, update_index); 124 + if (ret) 125 + return ret; 126 + 127 + return 0; 128 + } 129 + 130 + /** 131 + * fwu_populate_mdata_image_info() - Populate the image information 132 + * of the metadata 133 + * @data: Version agnostic FWU metadata information 134 + * 135 + * Populate the image information in the FWU metadata by copying it 136 + * from the version agnostic structure. This is done before the 137 + * metadata gets written to the storage media. 138 + * 139 + * Return: None 140 + */ 141 + void fwu_populate_mdata_image_info(struct fwu_data *data) 142 + { 143 + size_t image_info_size; 144 + struct fwu_mdata *mdata = data->fwu_mdata; 145 + void *dst_img_info, *src_img_info; 146 + 147 + image_info_size = sizeof(data->fwu_images); 148 + dst_img_info = &fwu_get_fw_desc(mdata)->img_entry[0]; 149 + src_img_info = &data->fwu_images[0]; 150 + 151 + memcpy(dst_img_info, src_img_info, image_info_size); 152 + } 153 + 154 + /** 155 + * fwu_state_machine_updates() - Update FWU state of the platform 156 + * @trial_state: Is platform transitioning into Trial State 157 + * @update_index: Bank number to which images have been updated 158 + * 159 + * On successful completion of updates, transition the platform to 160 + * either Trial State or Regular State. 161 + * 162 + * To transition the platform to Trial State, start the 163 + * TrialStateCtr counter, followed by setting the value of bank_state 164 + * field of the metadata to Valid state(applicable only in version 2 165 + * of metadata). 166 + * 167 + * In case, the platform is to transition directly to Regular State, 168 + * update the bank_state field of the metadata to Accepted 169 + * state(applicable only in version 2 of metadata). 170 + * 171 + * Return: 0 if OK, -ve on error 172 + */ 173 + int fwu_state_machine_updates(bool trial_state, uint32_t update_index) 174 + { 175 + return trial_state ? fwu_trial_state_start(update_index) : 176 + fwu_bank_state_update(0, update_index); 177 + } 178 + 179 + /** 180 + * fwu_get_mdata_size() - Get the FWU metadata size 181 + * @mdata_size: Size of the metadata structure 182 + * 183 + * Get the size of the FWU metadata from the structure. This is later used 184 + * to allocate memory for the structure. 185 + * 186 + * Return: 0 if OK, -ve on error 187 + */ 188 + int fwu_get_mdata_size(uint32_t *mdata_size) 189 + { 190 + int ret = 0; 191 + struct fwu_mdata mdata = { 0 }; 192 + struct fwu_data *data = fwu_get_data(); 193 + struct udevice *fwu_dev = fwu_get_dev(); 194 + 195 + if (data->metadata_size) { 196 + *mdata_size = data->metadata_size; 197 + return 0; 198 + } 199 + 200 + ret = fwu_read_mdata(fwu_dev, &mdata, 1, 201 + sizeof(struct fwu_mdata)); 202 + if (ret) { 203 + log_err("FWU metadata read failed\n"); 204 + return ret; 205 + } 206 + 207 + *mdata_size = mdata.metadata_size; 208 + if (!*mdata_size) 209 + return -EINVAL; 210 + 211 + return 0; 212 + } 213 + 214 + /** 215 + * fwu_init() - FWU specific initialisations 216 + * 217 + * Carry out some FWU specific initialisations including allocation 218 + * of memory for the metadata copies, and reading the FWU metadata 219 + * copies into the allocated memory. The metadata fields are then 220 + * copied into a version agnostic structure. 221 + * 222 + * Return: 0 if OK, -ve on error 223 + */ 224 + int fwu_init(void) 225 + { 226 + int ret; 227 + struct fwu_mdata mdata = { 0 }; 228 + struct udevice *fwu_dev = fwu_get_dev(); 229 + 230 + /* 231 + * First we read only the top level structure 232 + * and get the size of the complete structure. 233 + */ 234 + ret = fwu_read_mdata(fwu_dev, &mdata, 1, 235 + sizeof(struct fwu_mdata)); 236 + if (ret) { 237 + log_err("FWU metadata read failed\n"); 238 + return ret; 239 + } 240 + 241 + ret = fwu_mdata_copies_allocate(mdata.metadata_size); 242 + if (ret) 243 + return ret; 244 + 245 + /* 246 + * Now read the entire structure, both copies, and 247 + * validate that the copies. 248 + */ 249 + ret = fwu_get_mdata(NULL); 250 + if (ret) 251 + return ret; 252 + 253 + ret = fwu_mdata_sanity_checks(); 254 + if (ret) 255 + return ret; 256 + 257 + fwu_data_init(); 258 + 259 + return 0; 260 + }
+10 -6
test/dm/fwu_mdata.c
··· 92 92 struct udevice *dev; 93 93 struct fwu_mdata mdata = { 0 }; 94 94 95 + ut_assertok(setup_blk_device(uts)); 96 + ut_assertok(populate_mmc_disk_image(uts)); 97 + ut_assertok(write_mmc_blk_device(uts)); 98 + 95 99 /* 96 100 * Trigger lib/fwu_updates/fwu.c fwu_boottime_checks() 97 101 * to populate g_dev global pointer in that library. ··· 99 103 event_notify_null(EVT_MAIN_LOOP); 100 104 101 105 ut_assertok(uclass_first_device_err(UCLASS_FWU_MDATA, &dev)); 102 - ut_assertok(setup_blk_device(uts)); 103 - ut_assertok(populate_mmc_disk_image(uts)); 104 - ut_assertok(write_mmc_blk_device(uts)); 106 + ut_assertok(fwu_init()); 105 107 106 108 ut_assertok(fwu_get_mdata(&mdata)); 107 109 ··· 117 119 struct udevice *dev; 118 120 struct fwu_mdata mdata = { 0 }; 119 121 122 + ut_assertok(setup_blk_device(uts)); 123 + ut_assertok(populate_mmc_disk_image(uts)); 124 + ut_assertok(write_mmc_blk_device(uts)); 125 + 120 126 /* 121 127 * Trigger lib/fwu_updates/fwu.c fwu_boottime_checks() 122 128 * to populate g_dev global pointer in that library. 123 129 */ 124 130 event_notify_null(EVT_MAIN_LOOP); 125 131 126 - ut_assertok(setup_blk_device(uts)); 127 - ut_assertok(populate_mmc_disk_image(uts)); 128 - ut_assertok(write_mmc_blk_device(uts)); 129 132 130 133 ut_assertok(uclass_first_device_err(UCLASS_FWU_MDATA, &dev)); 131 134 135 + ut_assertok(fwu_init()); 132 136 ut_assertok(fwu_get_mdata(&mdata)); 133 137 134 138 active_idx = (mdata.active_index + 1) % CONFIG_FWU_NUM_BANKS;
+197 -38
tools/mkfwumdata.c
··· 10 10 #include <stdint.h> 11 11 #include <stdlib.h> 12 12 #include <string.h> 13 - #include <u-boot/crc.h> 14 13 #include <unistd.h> 14 + #include <generated/autoconf.h> 15 + #include <sys/types.h> 16 + #include <sys/stat.h> 17 + #include <u-boot/crc.h> 15 18 #include <uuid/uuid.h> 16 19 17 - /* This will dynamically allocate the fwu_mdata */ 18 - #define CONFIG_FWU_NUM_BANKS 0 19 - #define CONFIG_FWU_NUM_IMAGES_PER_BANK 0 20 - 21 - /* Since we can not include fwu.h, redefine version here. */ 22 - #define FWU_MDATA_VERSION 1 23 - 24 20 typedef uint8_t u8; 25 21 typedef int16_t s16; 26 22 typedef uint16_t u16; 27 23 typedef uint32_t u32; 28 24 typedef uint64_t u64; 29 25 30 - #include <fwu_mdata.h> 26 + #undef CONFIG_FWU_NUM_BANKS 27 + #undef CONFIG_FWU_NUM_IMAGES_PER_BANK 31 28 32 - /* TODO: Endianness conversion may be required for some arch. */ 29 + /* This will dynamically allocate the fwu_mdata */ 30 + #define CONFIG_FWU_NUM_BANKS 0 31 + #define CONFIG_FWU_NUM_IMAGES_PER_BANK 0 32 + 33 + /* version 2 supports maximum of 4 banks */ 34 + #define MAX_BANKS_V2 4 35 + 36 + #define BANK_INVALID (u8)0xFF 37 + #define BANK_ACCEPTED (u8)0xFC 33 38 34 - static const char *opts_short = "b:i:a:p:gh"; 39 + #include <fwu_mdata.h> 40 + 41 + static const char *opts_short = "b:i:a:p:v:V:gh"; 35 42 36 43 static struct option options[] = { 37 44 {"banks", required_argument, NULL, 'b'}, ··· 39 46 {"guid", required_argument, NULL, 'g'}, 40 47 {"active-bank", required_argument, NULL, 'a'}, 41 48 {"previous-bank", required_argument, NULL, 'p'}, 49 + {"version", required_argument, NULL, 'v'}, 50 + {"vendor-file", required_argument, NULL, 'V'}, 42 51 {"help", no_argument, NULL, 'h'}, 43 52 {NULL, 0, NULL, 0}, 44 53 }; ··· 49 58 fprintf(stderr, "Options:\n" 50 59 "\t-i, --images <num> Number of images (mandatory)\n" 51 60 "\t-b, --banks <num> Number of banks (mandatory)\n" 61 + "\t-v, --version Metadata version (mandatory)\n" 52 62 "\t-a, --active-bank <num> Active bank (default=0)\n" 53 63 "\t-p, --previous-bank <num> Previous active bank (default=active_bank - 1)\n" 54 64 "\t-g, --guid Use GUID instead of UUID\n" 65 + "\t-V, --vendor-file Vendor data file to append to the metadata\n" 55 66 "\t-h, --help print a help message\n" 56 67 ); 57 68 fprintf(stderr, " UUIDs list syntax:\n" ··· 70 81 size_t images; 71 82 size_t banks; 72 83 size_t size; 84 + u8 version; 85 + size_t vsize; 86 + void *vbuf; 73 87 struct fwu_mdata *mdata; 74 88 }; 75 89 76 90 static int previous_bank, active_bank; 77 91 static bool __use_guid; 78 92 79 - static struct fwu_mdata_object *fwu_alloc_mdata(size_t images, size_t banks) 93 + static bool supported_mdata_version(unsigned long version) 94 + { 95 + switch (version) { 96 + case 1: 97 + case 2: 98 + return true; 99 + default: 100 + return false; 101 + } 102 + } 103 + 104 + static struct fwu_mdata_object *fwu_alloc_mdata(size_t images, size_t banks, 105 + u8 version, size_t vendor_size) 80 106 { 81 107 struct fwu_mdata_object *mobj; 82 108 ··· 84 110 if (!mobj) 85 111 return NULL; 86 112 87 - mobj->size = sizeof(struct fwu_mdata) + 88 - (sizeof(struct fwu_image_entry) + 89 - sizeof(struct fwu_image_bank_info) * banks) * images; 113 + if (version == 1) { 114 + mobj->size = sizeof(struct fwu_mdata) + 115 + (sizeof(struct fwu_image_entry) + 116 + sizeof(struct fwu_image_bank_info) * banks) * images; 117 + } else { 118 + mobj->size = sizeof(struct fwu_mdata) + 119 + sizeof(struct fwu_fw_store_desc) + 120 + (sizeof(struct fwu_image_entry) + 121 + sizeof(struct fwu_image_bank_info) * banks) * images; 122 + 123 + mobj->size += vendor_size; 124 + mobj->vsize = vendor_size; 125 + } 126 + 90 127 mobj->images = images; 91 128 mobj->banks = banks; 129 + mobj->version = version; 92 130 93 131 mobj->mdata = calloc(1, mobj->size); 94 - if (!mobj->mdata) { 95 - free(mobj); 96 - return NULL; 132 + if (!mobj->mdata) 133 + goto alloc_err; 134 + 135 + if (vendor_size) { 136 + mobj->vbuf = calloc(1, mobj->vsize); 137 + if (!mobj->vbuf) 138 + goto alloc_err; 97 139 } 98 140 99 141 return mobj; 142 + 143 + alloc_err: 144 + free(mobj->mdata); 145 + free(mobj); 146 + return NULL; 100 147 } 101 148 102 149 static struct fwu_image_entry * ··· 104 151 { 105 152 size_t offset; 106 153 107 - offset = sizeof(struct fwu_mdata) + 108 - (sizeof(struct fwu_image_entry) + 109 - sizeof(struct fwu_image_bank_info) * mobj->banks) * idx; 154 + if (mobj->version == 1) { 155 + offset = sizeof(struct fwu_mdata) + 156 + (sizeof(struct fwu_image_entry) + 157 + sizeof(struct fwu_image_bank_info) * mobj->banks) * 158 + idx; 159 + } else { 160 + offset = sizeof(struct fwu_mdata) + 161 + sizeof(struct fwu_fw_store_desc) + 162 + (sizeof(struct fwu_image_entry) + 163 + sizeof(struct fwu_image_bank_info) * mobj->banks) * 164 + idx; 165 + } 110 166 111 167 return (struct fwu_image_entry *)((char *)mobj->mdata + offset); 112 168 } ··· 116 172 { 117 173 size_t offset; 118 174 119 - offset = sizeof(struct fwu_mdata) + 120 - (sizeof(struct fwu_image_entry) + 121 - sizeof(struct fwu_image_bank_info) * mobj->banks) * img_idx + 122 - sizeof(struct fwu_image_entry) + 123 - sizeof(struct fwu_image_bank_info) * bnk_idx; 175 + if (mobj->version == 1) { 176 + offset = sizeof(struct fwu_mdata) + 177 + (sizeof(struct fwu_image_entry) + 178 + sizeof(struct fwu_image_bank_info) * mobj->banks) * 179 + img_idx + sizeof(struct fwu_image_entry) + 180 + sizeof(struct fwu_image_bank_info) * bnk_idx; 181 + } else { 182 + offset = sizeof(struct fwu_mdata) + 183 + sizeof(struct fwu_fw_store_desc) + 184 + (sizeof(struct fwu_image_entry) + 185 + sizeof(struct fwu_image_bank_info) * mobj->banks) * 186 + img_idx + sizeof(struct fwu_image_entry) + 187 + sizeof(struct fwu_image_bank_info) * bnk_idx; 188 + } 124 189 125 190 return (struct fwu_image_bank_info *)((char *)mobj->mdata + offset); 126 191 } ··· 188 253 return -EINVAL; 189 254 190 255 if (strcmp(uuid, "0") && 191 - uuid_guid_parse(uuid, (unsigned char *)&image->location_uuid) < 0) 256 + uuid_guid_parse(uuid, (unsigned char *)&image->location_guid) < 0) 192 257 return -EINVAL; 193 258 194 259 /* Image type UUID */ ··· 196 261 if (!uuid) 197 262 return -EINVAL; 198 263 199 - if (uuid_guid_parse(uuid, (unsigned char *)&image->image_type_uuid) < 0) 264 + if (uuid_guid_parse(uuid, (unsigned char *)&image->image_type_guid) < 0) 200 265 return -EINVAL; 201 266 202 267 /* Fill bank image-UUID */ ··· 210 275 return -EINVAL; 211 276 212 277 if (strcmp(uuid, "0") && 213 - uuid_guid_parse(uuid, (unsigned char *)&bank->image_uuid) < 0) 278 + uuid_guid_parse(uuid, (unsigned char *)&bank->image_guid) < 0) 214 279 return -EINVAL; 215 280 } 216 281 return 0; 217 282 } 218 283 284 + #if defined(CONFIG_FWU_MDATA_V1) 285 + static void fwu_fill_version_specific_mdata(struct fwu_mdata_object *mobj) 286 + { 287 + } 288 + #else 289 + static void fwu_fill_version_specific_mdata(struct fwu_mdata_object *mobj) 290 + { 291 + int i; 292 + struct fwu_fw_store_desc *fw_desc; 293 + struct fwu_mdata *mdata = mobj->mdata; 294 + 295 + mdata->metadata_size = mobj->size; 296 + mdata->desc_offset = sizeof(struct fwu_mdata); 297 + 298 + for (i = 0; i < MAX_BANKS_V2; i++) 299 + mdata->bank_state[i] = i < mobj->banks ? 300 + BANK_ACCEPTED : BANK_INVALID; 301 + 302 + fw_desc = (struct fwu_fw_store_desc *)((u8 *)mdata + sizeof(*mdata)); 303 + fw_desc->num_banks = mobj->banks; 304 + fw_desc->num_images = mobj->images; 305 + fw_desc->img_entry_size = sizeof(struct fwu_image_entry) + 306 + (sizeof(struct fwu_image_bank_info) * mobj->banks); 307 + fw_desc->bank_info_entry_size = 308 + sizeof(struct fwu_image_bank_info); 309 + } 310 + #endif /* CONFIG_FWU_MDATA_V1 */ 311 + 219 312 /* Caller must ensure that @uuids[] has @mobj->images entries. */ 220 313 static int fwu_parse_fill_uuids(struct fwu_mdata_object *mobj, char *uuids[]) 221 314 { 222 315 struct fwu_mdata *mdata = mobj->mdata; 316 + char *vdata; 223 317 int i, ret; 224 318 225 - mdata->version = FWU_MDATA_VERSION; 319 + mdata->version = mobj->version; 226 320 mdata->active_index = active_bank; 227 321 mdata->previous_active_index = previous_bank; 322 + 323 + fwu_fill_version_specific_mdata(mobj); 228 324 229 325 for (i = 0; i < mobj->images; i++) { 230 326 ret = fwu_parse_fill_image_uuid(mobj, i, uuids[i]); ··· 232 328 return ret; 233 329 } 234 330 331 + if (mobj->vsize) { 332 + vdata = (char *)mobj->mdata + (mobj->size - mobj->vsize); 333 + memcpy(vdata, mobj->vbuf, mobj->vsize); 334 + } 335 + 235 336 mdata->crc32 = crc32(0, (const unsigned char *)&mdata->version, 236 337 mobj->size - sizeof(uint32_t)); 237 338 238 339 return 0; 239 340 } 240 341 241 - static int 242 - fwu_make_mdata(size_t images, size_t banks, char *uuids[], char *output) 342 + static int fwu_read_vendor_data(struct fwu_mdata_object *mobj, 343 + const char *vendor_file) 344 + { 345 + int ret = 0; 346 + FILE *vfile = NULL; 347 + 348 + vfile = fopen(vendor_file, "r"); 349 + if (!vfile) { 350 + ret = -1; 351 + goto out; 352 + } 353 + 354 + if (fread(mobj->vbuf, 1, mobj->vsize, vfile) != mobj->vsize) 355 + ret = -1; 356 + 357 + out: 358 + fclose(vfile); 359 + return ret; 360 + } 361 + 362 + static int fwu_make_mdata(size_t images, size_t banks, u8 version, 363 + const char *vendor_file, char *uuids[], 364 + char *output) 243 365 { 366 + int ret; 367 + FILE *file; 368 + struct stat sbuf; 369 + size_t vendor_size = 0; 244 370 struct fwu_mdata_object *mobj; 245 - FILE *file; 246 - int ret; 371 + 372 + if (vendor_file) { 373 + ret = stat(vendor_file, &sbuf); 374 + if (ret) 375 + return -errno; 247 376 248 - mobj = fwu_alloc_mdata(images, banks); 377 + vendor_size = sbuf.st_size; 378 + } 379 + 380 + mobj = fwu_alloc_mdata(images, banks, version, vendor_size); 249 381 if (!mobj) 250 382 return -ENOMEM; 251 383 384 + if (vendor_file) { 385 + ret = fwu_read_vendor_data(mobj, vendor_file); 386 + if (ret) 387 + goto done_make; 388 + } 389 + 252 390 ret = fwu_parse_fill_uuids(mobj, uuids); 253 391 if (ret < 0) 254 392 goto done_make; ··· 259 397 goto done_make; 260 398 } 261 399 262 - ret = fwrite(mobj->mdata, mobj->size, 1, file); 400 + ret = fwrite(mobj->mdata, 1, mobj->size, file); 263 401 if (ret != mobj->size) 264 402 ret = -errno; 265 403 else ··· 269 407 270 408 done_make: 271 409 free(mobj->mdata); 410 + free(mobj->vbuf); 272 411 free(mobj); 273 412 274 413 return ret; ··· 276 415 277 416 int main(int argc, char *argv[]) 278 417 { 279 - unsigned long banks = 0, images = 0; 418 + unsigned long banks = 0, images = 0, version = 0; 280 419 int c, ret; 420 + const char *vendor_file; 281 421 282 422 /* Explicitly initialize defaults */ 283 423 active_bank = 0; 284 424 __use_guid = false; 285 425 previous_bank = INT_MAX; 426 + vendor_file = NULL; 286 427 287 428 do { 288 429 c = getopt_long(argc, argv, opts_short, options, NULL); ··· 304 445 break; 305 446 case 'a': 306 447 active_bank = strtoul(optarg, NULL, 0); 448 + break; 449 + case 'v': 450 + version = strtoul(optarg, NULL, 0); 451 + break; 452 + case 'V': 453 + vendor_file = optarg; 307 454 break; 308 455 } 309 456 } while (c != -1); ··· 313 460 return -EINVAL; 314 461 } 315 462 463 + if (!version || !supported_mdata_version(version)) { 464 + fprintf(stderr, "Error: Version value can only be either 1 or 2, not %ld.\n", 465 + version); 466 + return -EINVAL; 467 + } 468 + 469 + if (version == 1 && vendor_file) { 470 + fprintf(stderr, "Error: Vendor Data can only be appended in version 2 of FWU Metadata.\n"); 471 + return -EINVAL; 472 + } 473 + 316 474 /* This command takes UUIDs * images and output file. */ 317 475 if (optind + images + 1 != argc) { 318 476 fprintf(stderr, "Error: UUID list or output file is not specified or too much.\n"); ··· 325 483 previous_bank = active_bank > 0 ? active_bank - 1 : banks - 1; 326 484 } 327 485 328 - ret = fwu_make_mdata(images, banks, argv + optind, argv[argc - 1]); 486 + ret = fwu_make_mdata(images, banks, (u8)version, vendor_file, 487 + argv + optind, argv[argc - 1]); 329 488 if (ret < 0) 330 489 fprintf(stderr, "Error: Failed to parse and write image: %s\n", 331 490 strerror(-ret));