1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2024, Linaro Limited
4 */
5
6 #include <errno.h>
7 #include <fwu.h>
8 #include <fwu_mdata.h>
9
10 #include <linux/types.h>
11
12 #define FWU_MDATA_VERSION 0x1U
13
fwu_check_trial_state(struct fwu_mdata * mdata,uint32_t bank)14 static uint32_t fwu_check_trial_state(struct fwu_mdata *mdata, uint32_t bank)
15 {
16 u32 i;
17 struct fwu_image_entry *img_entry;
18 struct fwu_image_bank_info *img_bank_info;
19
20 img_entry = &mdata->img_entry[0];
21 for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) {
22 img_bank_info = &img_entry[i].img_bank_info[bank];
23 if (!img_bank_info->accepted) {
24 return 1;
25 }
26 }
27
28 return 0;
29 }
30
fwu_data_init(void)31 static void fwu_data_init(void)
32 {
33 size_t image_info_size;
34 void *dst_img_info, *src_img_info;
35 struct fwu_data *data = fwu_get_data();
36 struct fwu_mdata *mdata = data->fwu_mdata;
37
38 data->crc32 = mdata->crc32;
39 data->version = mdata->version;
40 data->active_index = mdata->active_index;
41 data->previous_active_index = mdata->previous_active_index;
42
43 data->metadata_size = sizeof(struct fwu_mdata);
44 data->num_banks = CONFIG_FWU_NUM_BANKS;
45 data->num_images = CONFIG_FWU_NUM_IMAGES_PER_BANK;
46 fwu_plat_get_bootidx(&data->boot_index);
47 data->trial_state = fwu_check_trial_state(mdata, data->boot_index);
48
49 src_img_info = &mdata->img_entry[0];
50 dst_img_info = &data->fwu_images[0];
51 image_info_size = sizeof(data->fwu_images);
52
53 memcpy(dst_img_info, src_img_info, image_info_size);
54 }
55
fwu_trial_state_update(bool trial_state,uint32_t bank)56 static int fwu_trial_state_update(bool trial_state, uint32_t bank)
57 {
58 int ret;
59 struct fwu_data *data = fwu_get_data();
60
61 if (!trial_state && !fwu_bank_accepted(data, bank))
62 return 0;
63
64 if (trial_state) {
65 ret = fwu_trial_state_ctr_start();
66 if (ret)
67 return ret;
68 }
69
70 data->trial_state = trial_state;
71
72 return 0;
73 }
74
75 /**
76 * fwu_populate_mdata_image_info() - Populate the image information
77 * of the metadata
78 * @data: Version agnostic FWU metadata information
79 *
80 * Populate the image information in the FWU metadata by copying it
81 * from the version agnostic structure. This is done before the
82 * metadata gets written to the storage media.
83 *
84 * Return: None
85 */
fwu_populate_mdata_image_info(struct fwu_data * data)86 void fwu_populate_mdata_image_info(struct fwu_data *data)
87 {
88 size_t image_info_size;
89 void *dst_img_info, *src_img_info;
90 struct fwu_mdata *mdata = data->fwu_mdata;
91
92 image_info_size = sizeof(data->fwu_images);
93 dst_img_info = &mdata->img_entry[0];
94 src_img_info = &data->fwu_images[0];
95
96 memcpy(dst_img_info, src_img_info, image_info_size);
97 }
98
99 /**
100 * fwu_state_machine_updates() - Update FWU state of the platform
101 * @trial_state: Is platform transitioning into Trial State
102 * @update_index: Bank number to which images have been updated
103 *
104 * On successful completion of updates, transition the platform to
105 * either Trial State or Regular State.
106 *
107 * To transition the platform to Trial State, start the
108 * TrialStateCtr counter, followed by setting the value of bank_state
109 * field of the metadata to Valid state(applicable only in version 2
110 * of metadata).
111 *
112 * In case, the platform is to transition directly to Regular State,
113 * update the bank_state field of the metadata to Accepted
114 * state(applicable only in version 2 of metadata).
115 *
116 * Return: 0 if OK, -ve on error
117 */
fwu_state_machine_updates(bool trial_state,uint32_t update_index)118 int fwu_state_machine_updates(bool trial_state,
119 uint32_t update_index)
120 {
121 return fwu_trial_state_update(trial_state, update_index);
122 }
123
124 /**
125 * fwu_get_mdata_size() - Get the FWU metadata size
126 * @mdata_size: Size of the metadata structure
127 *
128 * Get the size of the FWU metadata.
129 *
130 * Return: 0 if OK, -ve on error
131 */
fwu_get_mdata_size(uint32_t * mdata_size)132 int fwu_get_mdata_size(uint32_t *mdata_size)
133 {
134 *mdata_size = sizeof(struct fwu_mdata);
135
136 return 0;
137 }
138
139 /**
140 * fwu_init() - FWU specific initialisations
141 *
142 * Carry out some FWU specific initialisations including allocation
143 * of memory for the metadata copies, and reading the FWU metadata
144 * copies into the allocated memory. The metadata fields are then
145 * copied into a version agnostic structure.
146 *
147 * Return: 0 if OK, -ve on error
148 */
fwu_init(void)149 int fwu_init(void)
150 {
151 int ret;
152 uint32_t mdata_size;
153 struct fwu_mdata mdata = {0};
154
155 fwu_get_mdata_size(&mdata_size);
156
157 ret = fwu_mdata_copies_allocate(mdata_size);
158 if (ret)
159 return ret;
160
161 /*
162 * Now read the entire structure, both copies, and
163 * validate that the copies.
164 */
165 ret = fwu_get_mdata(&mdata);
166 if (ret)
167 return ret;
168
169 if (mdata.version != 0x1) {
170 log_err("FWU metadata version %u. Expected value of %u\n",
171 mdata.version, FWU_MDATA_VERSION);
172 return -EINVAL;
173 }
174
175 fwu_data_init();
176
177 return 0;
178 }
179