xref: /openbmc/linux/sound/soc/sof/loader.c (revision cf9441ad)
1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2 //
3 // This file is provided under a dual BSD/GPLv2 license.  When using or
4 // redistributing this file, you may do so under either license.
5 //
6 // Copyright(c) 2018 Intel Corporation. All rights reserved.
7 //
8 // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
9 //
10 // Generic firmware loader.
11 //
12 
13 #include <linux/firmware.h>
14 #include <sound/sof.h>
15 #include "ops.h"
16 
17 static int get_ext_windows(struct snd_sof_dev *sdev,
18 			   struct sof_ipc_ext_data_hdr *ext_hdr)
19 {
20 	struct sof_ipc_window *w =
21 		container_of(ext_hdr, struct sof_ipc_window, ext_hdr);
22 
23 	if (w->num_windows == 0 || w->num_windows > SOF_IPC_MAX_ELEMS)
24 		return -EINVAL;
25 
26 	/* keep a local copy of the data */
27 	sdev->info_window = kmemdup(w, struct_size(w, window, w->num_windows),
28 				    GFP_KERNEL);
29 	if (!sdev->info_window)
30 		return -ENOMEM;
31 
32 	return 0;
33 }
34 
35 /* parse the extended FW boot data structures from FW boot message */
36 int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset)
37 {
38 	struct sof_ipc_ext_data_hdr *ext_hdr;
39 	void *ext_data;
40 	int ret = 0;
41 
42 	ext_data = kzalloc(PAGE_SIZE, GFP_KERNEL);
43 	if (!ext_data)
44 		return -ENOMEM;
45 
46 	/* get first header */
47 	snd_sof_dsp_block_read(sdev, bar, offset, ext_data,
48 			       sizeof(*ext_hdr));
49 	ext_hdr = ext_data;
50 
51 	while (ext_hdr->hdr.cmd == SOF_IPC_FW_READY) {
52 		/* read in ext structure */
53 		offset += sizeof(*ext_hdr);
54 		snd_sof_dsp_block_read(sdev, bar, offset,
55 				   (void *)((u8 *)ext_data + sizeof(*ext_hdr)),
56 				   ext_hdr->hdr.size - sizeof(*ext_hdr));
57 
58 		dev_dbg(sdev->dev, "found ext header type %d size 0x%x\n",
59 			ext_hdr->type, ext_hdr->hdr.size);
60 
61 		/* process structure data */
62 		switch (ext_hdr->type) {
63 		case SOF_IPC_EXT_DMA_BUFFER:
64 			break;
65 		case SOF_IPC_EXT_WINDOW:
66 			ret = get_ext_windows(sdev, ext_hdr);
67 			break;
68 		default:
69 			break;
70 		}
71 
72 		if (ret < 0) {
73 			dev_err(sdev->dev, "error: failed to parse ext data type %d\n",
74 				ext_hdr->type);
75 			break;
76 		}
77 
78 		/* move to next header */
79 		offset += ext_hdr->hdr.size;
80 		snd_sof_dsp_block_read(sdev, bar, offset, ext_data,
81 				       sizeof(*ext_hdr));
82 		ext_hdr = ext_data;
83 	}
84 
85 	kfree(ext_data);
86 	return ret;
87 }
88 EXPORT_SYMBOL(snd_sof_fw_parse_ext_data);
89 
90 /* generic module parser for mmaped DSPs */
91 int snd_sof_parse_module_memcpy(struct snd_sof_dev *sdev,
92 				struct snd_sof_mod_hdr *module)
93 {
94 	struct snd_sof_blk_hdr *block;
95 	int count, bar;
96 	u32 offset;
97 	size_t remaining;
98 
99 	dev_dbg(sdev->dev, "new module size 0x%x blocks 0x%x type 0x%x\n",
100 		module->size, module->num_blocks, module->type);
101 
102 	block = (struct snd_sof_blk_hdr *)((u8 *)module + sizeof(*module));
103 
104 	/* module->size doesn't include header size */
105 	remaining = module->size;
106 	for (count = 0; count < module->num_blocks; count++) {
107 		/* check for wrap */
108 		if (remaining < sizeof(*block)) {
109 			dev_err(sdev->dev, "error: not enough data remaining\n");
110 			return -EINVAL;
111 		}
112 
113 		/* minus header size of block */
114 		remaining -= sizeof(*block);
115 
116 		if (block->size == 0) {
117 			dev_warn(sdev->dev,
118 				 "warning: block %d size zero\n", count);
119 			dev_warn(sdev->dev, " type 0x%x offset 0x%x\n",
120 				 block->type, block->offset);
121 			continue;
122 		}
123 
124 		switch (block->type) {
125 		case SOF_FW_BLK_TYPE_RSRVD0:
126 		case SOF_FW_BLK_TYPE_ROM...SOF_FW_BLK_TYPE_RSRVD14:
127 			continue;	/* not handled atm */
128 		case SOF_FW_BLK_TYPE_IRAM:
129 		case SOF_FW_BLK_TYPE_DRAM:
130 		case SOF_FW_BLK_TYPE_SRAM:
131 			offset = block->offset;
132 			bar = snd_sof_dsp_get_bar_index(sdev, block->type);
133 			if (bar < 0) {
134 				dev_err(sdev->dev,
135 					"error: no BAR mapping for block type 0x%x\n",
136 					block->type);
137 				return bar;
138 			}
139 			break;
140 		default:
141 			dev_err(sdev->dev, "error: bad type 0x%x for block 0x%x\n",
142 				block->type, count);
143 			return -EINVAL;
144 		}
145 
146 		dev_dbg(sdev->dev,
147 			"block %d type 0x%x size 0x%x ==>  offset 0x%x\n",
148 			count, block->type, block->size, offset);
149 
150 		/* checking block->size to avoid unaligned access */
151 		if (block->size % sizeof(u32)) {
152 			dev_err(sdev->dev, "error: invalid block size 0x%x\n",
153 				block->size);
154 			return -EINVAL;
155 		}
156 		snd_sof_dsp_block_write(sdev, bar, offset,
157 					block + 1, block->size);
158 
159 		if (remaining < block->size) {
160 			dev_err(sdev->dev, "error: not enough data remaining\n");
161 			return -EINVAL;
162 		}
163 
164 		/* minus body size of block */
165 		remaining -= block->size;
166 		/* next block */
167 		block = (struct snd_sof_blk_hdr *)((u8 *)block + sizeof(*block)
168 			+ block->size);
169 	}
170 
171 	return 0;
172 }
173 EXPORT_SYMBOL(snd_sof_parse_module_memcpy);
174 
175 static int check_header(struct snd_sof_dev *sdev, const struct firmware *fw)
176 {
177 	struct snd_sof_fw_header *header;
178 
179 	/* Read the header information from the data pointer */
180 	header = (struct snd_sof_fw_header *)fw->data;
181 
182 	/* verify FW sig */
183 	if (strncmp(header->sig, SND_SOF_FW_SIG, SND_SOF_FW_SIG_SIZE) != 0) {
184 		dev_err(sdev->dev, "error: invalid firmware signature\n");
185 		return -EINVAL;
186 	}
187 
188 	/* check size is valid */
189 	if (fw->size != header->file_size + sizeof(*header)) {
190 		dev_err(sdev->dev, "error: invalid filesize mismatch got 0x%zx expected 0x%zx\n",
191 			fw->size, header->file_size + sizeof(*header));
192 		return -EINVAL;
193 	}
194 
195 	dev_dbg(sdev->dev, "header size=0x%x modules=0x%x abi=0x%x size=%zu\n",
196 		header->file_size, header->num_modules,
197 		header->abi, sizeof(*header));
198 
199 	return 0;
200 }
201 
202 static int load_modules(struct snd_sof_dev *sdev, const struct firmware *fw)
203 {
204 	struct snd_sof_fw_header *header;
205 	struct snd_sof_mod_hdr *module;
206 	int (*load_module)(struct snd_sof_dev *sof_dev,
207 			   struct snd_sof_mod_hdr *hdr);
208 	int ret, count;
209 	size_t remaining;
210 
211 	header = (struct snd_sof_fw_header *)fw->data;
212 	load_module = sof_ops(sdev)->load_module;
213 	if (!load_module)
214 		return -EINVAL;
215 
216 	/* parse each module */
217 	module = (struct snd_sof_mod_hdr *)((u8 *)(fw->data) + sizeof(*header));
218 	remaining = fw->size - sizeof(*header);
219 	/* check for wrap */
220 	if (remaining > fw->size) {
221 		dev_err(sdev->dev, "error: fw size smaller than header size\n");
222 		return -EINVAL;
223 	}
224 
225 	for (count = 0; count < header->num_modules; count++) {
226 		/* check for wrap */
227 		if (remaining < sizeof(*module)) {
228 			dev_err(sdev->dev, "error: not enough data remaining\n");
229 			return -EINVAL;
230 		}
231 
232 		/* minus header size of module */
233 		remaining -= sizeof(*module);
234 
235 		/* module */
236 		ret = load_module(sdev, module);
237 		if (ret < 0) {
238 			dev_err(sdev->dev, "error: invalid module %d\n", count);
239 			return ret;
240 		}
241 
242 		if (remaining < module->size) {
243 			dev_err(sdev->dev, "error: not enough data remaining\n");
244 			return -EINVAL;
245 		}
246 
247 		/* minus body size of module */
248 		remaining -=  module->size;
249 		module = (struct snd_sof_mod_hdr *)((u8 *)module
250 			+ sizeof(*module) + module->size);
251 	}
252 
253 	return 0;
254 }
255 
256 int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev)
257 {
258 	struct snd_sof_pdata *plat_data = sdev->pdata;
259 	const char *fw_filename;
260 	int ret;
261 
262 	/* set code loading condition to true */
263 	sdev->code_loading = 1;
264 
265 	/* Don't request firmware again if firmware is already requested */
266 	if (plat_data->fw)
267 		return 0;
268 
269 	fw_filename = kasprintf(GFP_KERNEL, "%s/%s",
270 				plat_data->fw_filename_prefix,
271 				plat_data->fw_filename);
272 	if (!fw_filename)
273 		return -ENOMEM;
274 
275 	ret = request_firmware(&plat_data->fw, fw_filename, sdev->dev);
276 
277 	if (ret < 0) {
278 		dev_err(sdev->dev, "error: request firmware %s failed err: %d\n",
279 			fw_filename, ret);
280 	}
281 
282 	kfree(fw_filename);
283 
284 	return ret;
285 }
286 EXPORT_SYMBOL(snd_sof_load_firmware_raw);
287 
288 int snd_sof_load_firmware_memcpy(struct snd_sof_dev *sdev)
289 {
290 	struct snd_sof_pdata *plat_data = sdev->pdata;
291 	int ret;
292 
293 	ret = snd_sof_load_firmware_raw(sdev);
294 	if (ret < 0)
295 		return ret;
296 
297 	/* make sure the FW header and file is valid */
298 	ret = check_header(sdev, plat_data->fw);
299 	if (ret < 0) {
300 		dev_err(sdev->dev, "error: invalid FW header\n");
301 		goto error;
302 	}
303 
304 	/* prepare the DSP for FW loading */
305 	ret = snd_sof_dsp_reset(sdev);
306 	if (ret < 0) {
307 		dev_err(sdev->dev, "error: failed to reset DSP\n");
308 		goto error;
309 	}
310 
311 	/* parse and load firmware modules to DSP */
312 	ret = load_modules(sdev, plat_data->fw);
313 	if (ret < 0) {
314 		dev_err(sdev->dev, "error: invalid FW modules\n");
315 		goto error;
316 	}
317 
318 	return 0;
319 
320 error:
321 	release_firmware(plat_data->fw);
322 	plat_data->fw = NULL;
323 	return ret;
324 
325 }
326 EXPORT_SYMBOL(snd_sof_load_firmware_memcpy);
327 
328 int snd_sof_load_firmware(struct snd_sof_dev *sdev)
329 {
330 	dev_dbg(sdev->dev, "loading firmware\n");
331 
332 	if (sof_ops(sdev)->load_firmware)
333 		return sof_ops(sdev)->load_firmware(sdev);
334 	return 0;
335 }
336 EXPORT_SYMBOL(snd_sof_load_firmware);
337 
338 int snd_sof_run_firmware(struct snd_sof_dev *sdev)
339 {
340 	int ret;
341 	int init_core_mask;
342 
343 	init_waitqueue_head(&sdev->boot_wait);
344 	sdev->boot_complete = false;
345 
346 	/* create read-only fw_version debugfs to store boot version info */
347 	if (sdev->first_boot) {
348 		ret = snd_sof_debugfs_buf_item(sdev, &sdev->fw_version,
349 					       sizeof(sdev->fw_version),
350 					       "fw_version", 0444);
351 		/* errors are only due to memory allocation, not debugfs */
352 		if (ret < 0) {
353 			dev_err(sdev->dev, "error: snd_sof_debugfs_buf_item failed\n");
354 			return ret;
355 		}
356 	}
357 
358 	/* perform pre fw run operations */
359 	ret = snd_sof_dsp_pre_fw_run(sdev);
360 	if (ret < 0) {
361 		dev_err(sdev->dev, "error: failed pre fw run op\n");
362 		return ret;
363 	}
364 
365 	dev_dbg(sdev->dev, "booting DSP firmware\n");
366 
367 	/* boot the firmware on the DSP */
368 	ret = snd_sof_dsp_run(sdev);
369 	if (ret < 0) {
370 		dev_err(sdev->dev, "error: failed to reset DSP\n");
371 		return ret;
372 	}
373 
374 	init_core_mask = ret;
375 
376 	/* now wait for the DSP to boot */
377 	ret = wait_event_timeout(sdev->boot_wait, sdev->boot_complete,
378 				 msecs_to_jiffies(sdev->boot_timeout));
379 	if (ret == 0) {
380 		dev_err(sdev->dev, "error: firmware boot failure\n");
381 		/* after this point FW_READY msg should be ignored */
382 		sdev->boot_complete = true;
383 		snd_sof_dsp_dbg_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX |
384 			SOF_DBG_TEXT | SOF_DBG_PCI);
385 		return -EIO;
386 	}
387 
388 	dev_info(sdev->dev, "firmware boot complete\n");
389 
390 	/* perform post fw run operations */
391 	ret = snd_sof_dsp_post_fw_run(sdev);
392 	if (ret < 0) {
393 		dev_err(sdev->dev, "error: failed post fw run op\n");
394 		return ret;
395 	}
396 
397 	/* fw boot is complete. Update the active cores mask */
398 	sdev->enabled_cores_mask = init_core_mask;
399 
400 	return 0;
401 }
402 EXPORT_SYMBOL(snd_sof_run_firmware);
403 
404 void snd_sof_fw_unload(struct snd_sof_dev *sdev)
405 {
406 	/* TODO: support module unloading at runtime */
407 }
408 EXPORT_SYMBOL(snd_sof_fw_unload);
409