blob: 554723046f6d87f86a120e643e1687320bfe66d1 [file] [log] [blame]
Masami Hiramatsu1f52b642023-05-31 00:29:14 -05001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) 2023, Linaro Limited
4 */
5
6#include <dm.h>
7#include <dfu.h>
8#include <fwu.h>
9#include <fwu_mdata.h>
10#include <log.h>
11#include <malloc.h>
12#include <mtd.h>
Caleb Connolly29cab7c2024-08-30 13:34:37 +010013#include <u-boot/uuid.h>
Raymond Mao24da8312024-05-16 14:11:52 -070014#include <stdio.h>
Masami Hiramatsu1f52b642023-05-31 00:29:14 -050015
16#include <dm/ofnode.h>
17
Masami Hiramatsu1f52b642023-05-31 00:29:14 -050018static struct fwu_mtd_image_info *mtd_img_by_uuid(const char *uuidbuf)
19{
Sughosh Ganu3d7ffcf2024-03-22 16:27:25 +053020 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;
Masami Hiramatsu1f52b642023-05-31 00:29:14 -050029
30 for (int i = 0; i < num_images; i++)
Sughosh Ganu3d7ffcf2024-03-22 16:27:25 +053031 if (!strcmp(uuidbuf, image_info[i].uuidbuf))
32 return &image_info[i];
Masami Hiramatsu1f52b642023-05-31 00:29:14 -050033
34 return NULL;
35}
36
37int fwu_mtd_get_alt_num(efi_guid_t *image_id, u8 *alt_num,
38 const char *mtd_dev)
39{
40 struct fwu_mtd_image_info *mtd_img_info;
41 char uuidbuf[UUID_STR_LEN + 1];
42 fdt_addr_t offset, size = 0;
43 struct dfu_entity *dfu;
44 int i, nalt, ret;
45
46 mtd_probe_devices();
47
48 uuid_bin_to_str(image_id->b, uuidbuf, UUID_STR_FORMAT_STD);
49
50 mtd_img_info = mtd_img_by_uuid(uuidbuf);
51 if (!mtd_img_info) {
52 log_err("%s: Not found partition for image %s\n", __func__, uuidbuf);
53 return -ENOENT;
54 }
55
56 offset = mtd_img_info->start;
57 size = mtd_img_info->size;
58
59 ret = dfu_init_env_entities(NULL, NULL);
60 if (ret)
61 return -ENOENT;
62
Sughosh Ganuebb1c202024-08-28 22:24:22 +053063 nalt = list_count_nodes(&dfu_list);
Masami Hiramatsu1f52b642023-05-31 00:29:14 -050064 if (!nalt) {
65 log_warning("No entities in dfu_alt_info\n");
66 dfu_free_entities();
67 return -ENOENT;
68 }
69
70 ret = -ENOENT;
71 for (i = 0; i < nalt; i++) {
72 dfu = dfu_get_entity(i);
73
74 /* Only MTD RAW access */
75 if (!dfu || dfu->dev_type != DFU_DEV_MTD ||
76 dfu->layout != DFU_RAW_ADDR ||
77 dfu->data.mtd.start != offset ||
78 dfu->data.mtd.size != size)
79 continue;
80
81 *alt_num = dfu->alt;
82 ret = 0;
83 break;
84 }
85
86 dfu_free_entities();
87
88 log_debug("%s: %s -> %d\n", __func__, uuidbuf, *alt_num);
89 return ret;
90}
91
92/**
93 * fwu_plat_get_alt_num() - Get the DFU Alt Num for the image from the platform
94 * @dev: FWU device
95 * @image_id: Image GUID for which DFU alt number needs to be retrieved
96 * @alt_num: Pointer to the alt_num
97 *
98 * Get the DFU alt number from the platform for the image specified by the
99 * image GUID.
100 *
101 * Note: This is a weak function and platforms can override this with
102 * their own implementation for obtaining the alt number value.
103 *
104 * Return: 0 if OK, -ve on error
105 */
106__weak int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_id,
107 u8 *alt_num)
108{
109 return fwu_mtd_get_alt_num(image_id, alt_num, "nor1");
110}
111
Sughosh Ganu5db141c2024-03-22 16:27:24 +0530112static int gen_image_alt_info(char *buf, size_t len,
Masami Hiramatsu1f52b642023-05-31 00:29:14 -0500113 struct fwu_image_entry *img, struct mtd_info *mtd)
114{
115 char *p = buf, *end = buf + len;
116 int i;
117
118 p += snprintf(p, end - p, "mtd %s", mtd->name);
119 if (end < p) {
120 log_err("%s:%d Run out of buffer\n", __func__, __LINE__);
121 return -E2BIG;
122 }
123
124 /*
125 * List the image banks in the FWU mdata and search the corresponding
126 * partition based on partition's uuid.
127 */
128 for (i = 0; i < CONFIG_FWU_NUM_BANKS; i++) {
129 struct fwu_mtd_image_info *mtd_img_info;
130 struct fwu_image_bank_info *bank;
131 char uuidbuf[UUID_STR_LEN + 1];
132 u32 offset, size;
133
134 /* Query a partition by image UUID */
135 bank = &img->img_bank_info[i];
Sughosh Ganua7188b42024-03-22 16:27:26 +0530136 uuid_bin_to_str(bank->image_guid.b, uuidbuf, UUID_STR_FORMAT_STD);
Masami Hiramatsu1f52b642023-05-31 00:29:14 -0500137
138 mtd_img_info = mtd_img_by_uuid(uuidbuf);
139 if (!mtd_img_info) {
140 log_err("%s: Not found partition for image %s\n", __func__, uuidbuf);
141 break;
142 }
143
144 offset = mtd_img_info->start;
145 size = mtd_img_info->size;
146
147 p += snprintf(p, end - p, "%sbank%d raw %x %x",
148 i == 0 ? "=" : ";", i, offset, size);
149 if (end < p) {
150 log_err("%s:%d Run out of buffer\n", __func__, __LINE__);
151 return -E2BIG;
152 }
153 }
154
155 if (i == CONFIG_FWU_NUM_BANKS)
156 return 0;
157
158 return -ENOENT;
159}
160
161int fwu_gen_alt_info_from_mtd(char *buf, size_t len, struct mtd_info *mtd)
162{
Masami Hiramatsu1f52b642023-05-31 00:29:14 -0500163 int i, l, ret;
Sughosh Ganua7188b42024-03-22 16:27:26 +0530164 struct fwu_data *data = fwu_get_data();
165 struct fwu_image_entry *img_entry;
Masami Hiramatsu1f52b642023-05-31 00:29:14 -0500166
167 for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) {
Sughosh Ganua7188b42024-03-22 16:27:26 +0530168 img_entry = &data->fwu_images[i];
169 ret = gen_image_alt_info(buf, len, img_entry, mtd);
Masami Hiramatsu1f52b642023-05-31 00:29:14 -0500170 if (ret)
171 break;
172
173 l = strlen(buf);
174 /* Replace the last ';' with '&' if there is another image. */
Michal Simek4b5ab712023-07-13 16:36:27 +0200175 if (i != CONFIG_FWU_NUM_IMAGES_PER_BANK - 1 && l) {
176 buf[l] = '&';
177 buf++;
178 }
Masami Hiramatsu1f52b642023-05-31 00:29:14 -0500179 len -= l;
180 buf += l;
181 }
182
183 return ret;
184}