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