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