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 snd_sof_dsp_block_read(sdev, bar, offset + sizeof(*ext_hdr), 54 (void *)((u8 *)ext_data + sizeof(*ext_hdr)), 55 ext_hdr->hdr.size - sizeof(*ext_hdr)); 56 57 dev_dbg(sdev->dev, "found ext header type %d size 0x%x\n", 58 ext_hdr->type, ext_hdr->hdr.size); 59 60 /* process structure data */ 61 switch (ext_hdr->type) { 62 case SOF_IPC_EXT_DMA_BUFFER: 63 ret = 0; 64 break; 65 case SOF_IPC_EXT_WINDOW: 66 ret = get_ext_windows(sdev, ext_hdr); 67 break; 68 default: 69 dev_warn(sdev->dev, "warning: unknown ext header type %d size 0x%x\n", 70 ext_hdr->type, ext_hdr->hdr.size); 71 ret = 0; 72 break; 73 } 74 75 if (ret < 0) { 76 dev_err(sdev->dev, "error: failed to parse ext data type %d\n", 77 ext_hdr->type); 78 break; 79 } 80 81 /* move to next header */ 82 offset += ext_hdr->hdr.size; 83 snd_sof_dsp_block_read(sdev, bar, offset, ext_data, 84 sizeof(*ext_hdr)); 85 ext_hdr = ext_data; 86 } 87 88 kfree(ext_data); 89 return ret; 90 } 91 EXPORT_SYMBOL(snd_sof_fw_parse_ext_data); 92 93 /* 94 * IPC Firmware ready. 95 */ 96 static void sof_get_windows(struct snd_sof_dev *sdev) 97 { 98 struct sof_ipc_window_elem *elem; 99 u32 outbox_offset = 0; 100 u32 stream_offset = 0; 101 u32 inbox_offset = 0; 102 u32 outbox_size = 0; 103 u32 stream_size = 0; 104 u32 inbox_size = 0; 105 int window_offset; 106 int bar; 107 int i; 108 109 if (!sdev->info_window) { 110 dev_err(sdev->dev, "error: have no window info\n"); 111 return; 112 } 113 114 bar = snd_sof_dsp_get_bar_index(sdev, SOF_FW_BLK_TYPE_SRAM); 115 if (bar < 0) { 116 dev_err(sdev->dev, "error: have no bar mapping\n"); 117 return; 118 } 119 120 for (i = 0; i < sdev->info_window->num_windows; i++) { 121 elem = &sdev->info_window->window[i]; 122 123 window_offset = snd_sof_dsp_get_window_offset(sdev, elem->id); 124 if (window_offset < 0) { 125 dev_warn(sdev->dev, "warn: no offset for window %d\n", 126 elem->id); 127 continue; 128 } 129 130 switch (elem->type) { 131 case SOF_IPC_REGION_UPBOX: 132 inbox_offset = window_offset + elem->offset; 133 inbox_size = elem->size; 134 snd_sof_debugfs_io_item(sdev, 135 sdev->bar[bar] + 136 inbox_offset, 137 elem->size, "inbox", 138 SOF_DEBUGFS_ACCESS_D0_ONLY); 139 break; 140 case SOF_IPC_REGION_DOWNBOX: 141 outbox_offset = window_offset + elem->offset; 142 outbox_size = elem->size; 143 snd_sof_debugfs_io_item(sdev, 144 sdev->bar[bar] + 145 outbox_offset, 146 elem->size, "outbox", 147 SOF_DEBUGFS_ACCESS_D0_ONLY); 148 break; 149 case SOF_IPC_REGION_TRACE: 150 snd_sof_debugfs_io_item(sdev, 151 sdev->bar[bar] + 152 window_offset + 153 elem->offset, 154 elem->size, "etrace", 155 SOF_DEBUGFS_ACCESS_D0_ONLY); 156 break; 157 case SOF_IPC_REGION_DEBUG: 158 snd_sof_debugfs_io_item(sdev, 159 sdev->bar[bar] + 160 window_offset + 161 elem->offset, 162 elem->size, "debug", 163 SOF_DEBUGFS_ACCESS_D0_ONLY); 164 break; 165 case SOF_IPC_REGION_STREAM: 166 stream_offset = window_offset + elem->offset; 167 stream_size = elem->size; 168 snd_sof_debugfs_io_item(sdev, 169 sdev->bar[bar] + 170 stream_offset, 171 elem->size, "stream", 172 SOF_DEBUGFS_ACCESS_D0_ONLY); 173 break; 174 case SOF_IPC_REGION_REGS: 175 snd_sof_debugfs_io_item(sdev, 176 sdev->bar[bar] + 177 window_offset + 178 elem->offset, 179 elem->size, "regs", 180 SOF_DEBUGFS_ACCESS_D0_ONLY); 181 break; 182 case SOF_IPC_REGION_EXCEPTION: 183 sdev->dsp_oops_offset = window_offset + elem->offset; 184 snd_sof_debugfs_io_item(sdev, 185 sdev->bar[bar] + 186 window_offset + 187 elem->offset, 188 elem->size, "exception", 189 SOF_DEBUGFS_ACCESS_D0_ONLY); 190 break; 191 default: 192 dev_err(sdev->dev, "error: get illegal window info\n"); 193 return; 194 } 195 } 196 197 if (outbox_size == 0 || inbox_size == 0) { 198 dev_err(sdev->dev, "error: get illegal mailbox window\n"); 199 return; 200 } 201 202 snd_sof_dsp_mailbox_init(sdev, inbox_offset, inbox_size, 203 outbox_offset, outbox_size); 204 sdev->stream_box.offset = stream_offset; 205 sdev->stream_box.size = stream_size; 206 207 dev_dbg(sdev->dev, " mailbox upstream 0x%x - size 0x%x\n", 208 inbox_offset, inbox_size); 209 dev_dbg(sdev->dev, " mailbox downstream 0x%x - size 0x%x\n", 210 outbox_offset, outbox_size); 211 dev_dbg(sdev->dev, " stream region 0x%x - size 0x%x\n", 212 stream_offset, stream_size); 213 } 214 215 /* check for ABI compatibility and create memory windows on first boot */ 216 int sof_fw_ready(struct snd_sof_dev *sdev, u32 msg_id) 217 { 218 struct sof_ipc_fw_ready *fw_ready = &sdev->fw_ready; 219 int offset; 220 int bar; 221 int ret; 222 223 /* mailbox must be on 4k boundary */ 224 offset = snd_sof_dsp_get_mailbox_offset(sdev); 225 if (offset < 0) { 226 dev_err(sdev->dev, "error: have no mailbox offset\n"); 227 return offset; 228 } 229 230 bar = snd_sof_dsp_get_bar_index(sdev, SOF_FW_BLK_TYPE_SRAM); 231 if (bar < 0) { 232 dev_err(sdev->dev, "error: have no bar mapping\n"); 233 return -EINVAL; 234 } 235 236 dev_dbg(sdev->dev, "ipc: DSP is ready 0x%8.8x offset 0x%x\n", 237 msg_id, offset); 238 239 /* no need to re-check version/ABI for subsequent boots */ 240 if (!sdev->first_boot) 241 return 0; 242 243 /* copy data from the DSP FW ready offset */ 244 sof_block_read(sdev, bar, offset, fw_ready, sizeof(*fw_ready)); 245 246 /* make sure ABI version is compatible */ 247 ret = snd_sof_ipc_valid(sdev); 248 if (ret < 0) 249 return ret; 250 251 /* now check for extended data */ 252 snd_sof_fw_parse_ext_data(sdev, bar, offset + 253 sizeof(struct sof_ipc_fw_ready)); 254 255 sof_get_windows(sdev); 256 257 return 0; 258 } 259 EXPORT_SYMBOL(sof_fw_ready); 260 261 /* generic module parser for mmaped DSPs */ 262 int snd_sof_parse_module_memcpy(struct snd_sof_dev *sdev, 263 struct snd_sof_mod_hdr *module) 264 { 265 struct snd_sof_blk_hdr *block; 266 int count, bar; 267 u32 offset; 268 size_t remaining; 269 270 dev_dbg(sdev->dev, "new module size 0x%x blocks 0x%x type 0x%x\n", 271 module->size, module->num_blocks, module->type); 272 273 block = (struct snd_sof_blk_hdr *)((u8 *)module + sizeof(*module)); 274 275 /* module->size doesn't include header size */ 276 remaining = module->size; 277 for (count = 0; count < module->num_blocks; count++) { 278 /* check for wrap */ 279 if (remaining < sizeof(*block)) { 280 dev_err(sdev->dev, "error: not enough data remaining\n"); 281 return -EINVAL; 282 } 283 284 /* minus header size of block */ 285 remaining -= sizeof(*block); 286 287 if (block->size == 0) { 288 dev_warn(sdev->dev, 289 "warning: block %d size zero\n", count); 290 dev_warn(sdev->dev, " type 0x%x offset 0x%x\n", 291 block->type, block->offset); 292 continue; 293 } 294 295 switch (block->type) { 296 case SOF_FW_BLK_TYPE_RSRVD0: 297 case SOF_FW_BLK_TYPE_ROM...SOF_FW_BLK_TYPE_RSRVD14: 298 continue; /* not handled atm */ 299 case SOF_FW_BLK_TYPE_IRAM: 300 case SOF_FW_BLK_TYPE_DRAM: 301 case SOF_FW_BLK_TYPE_SRAM: 302 offset = block->offset; 303 bar = snd_sof_dsp_get_bar_index(sdev, block->type); 304 if (bar < 0) { 305 dev_err(sdev->dev, 306 "error: no BAR mapping for block type 0x%x\n", 307 block->type); 308 return bar; 309 } 310 break; 311 default: 312 dev_err(sdev->dev, "error: bad type 0x%x for block 0x%x\n", 313 block->type, count); 314 return -EINVAL; 315 } 316 317 dev_dbg(sdev->dev, 318 "block %d type 0x%x size 0x%x ==> offset 0x%x\n", 319 count, block->type, block->size, offset); 320 321 /* checking block->size to avoid unaligned access */ 322 if (block->size % sizeof(u32)) { 323 dev_err(sdev->dev, "error: invalid block size 0x%x\n", 324 block->size); 325 return -EINVAL; 326 } 327 snd_sof_dsp_block_write(sdev, bar, offset, 328 block + 1, block->size); 329 330 if (remaining < block->size) { 331 dev_err(sdev->dev, "error: not enough data remaining\n"); 332 return -EINVAL; 333 } 334 335 /* minus body size of block */ 336 remaining -= block->size; 337 /* next block */ 338 block = (struct snd_sof_blk_hdr *)((u8 *)block + sizeof(*block) 339 + block->size); 340 } 341 342 return 0; 343 } 344 EXPORT_SYMBOL(snd_sof_parse_module_memcpy); 345 346 static int check_header(struct snd_sof_dev *sdev, const struct firmware *fw) 347 { 348 struct snd_sof_fw_header *header; 349 350 /* Read the header information from the data pointer */ 351 header = (struct snd_sof_fw_header *)fw->data; 352 353 /* verify FW sig */ 354 if (strncmp(header->sig, SND_SOF_FW_SIG, SND_SOF_FW_SIG_SIZE) != 0) { 355 dev_err(sdev->dev, "error: invalid firmware signature\n"); 356 return -EINVAL; 357 } 358 359 /* check size is valid */ 360 if (fw->size != header->file_size + sizeof(*header)) { 361 dev_err(sdev->dev, "error: invalid filesize mismatch got 0x%zx expected 0x%zx\n", 362 fw->size, header->file_size + sizeof(*header)); 363 return -EINVAL; 364 } 365 366 dev_dbg(sdev->dev, "header size=0x%x modules=0x%x abi=0x%x size=%zu\n", 367 header->file_size, header->num_modules, 368 header->abi, sizeof(*header)); 369 370 return 0; 371 } 372 373 static int load_modules(struct snd_sof_dev *sdev, const struct firmware *fw) 374 { 375 struct snd_sof_fw_header *header; 376 struct snd_sof_mod_hdr *module; 377 int (*load_module)(struct snd_sof_dev *sof_dev, 378 struct snd_sof_mod_hdr *hdr); 379 int ret, count; 380 size_t remaining; 381 382 header = (struct snd_sof_fw_header *)fw->data; 383 load_module = sof_ops(sdev)->load_module; 384 if (!load_module) 385 return -EINVAL; 386 387 /* parse each module */ 388 module = (struct snd_sof_mod_hdr *)((u8 *)(fw->data) + sizeof(*header)); 389 remaining = fw->size - sizeof(*header); 390 /* check for wrap */ 391 if (remaining > fw->size) { 392 dev_err(sdev->dev, "error: fw size smaller than header size\n"); 393 return -EINVAL; 394 } 395 396 for (count = 0; count < header->num_modules; count++) { 397 /* check for wrap */ 398 if (remaining < sizeof(*module)) { 399 dev_err(sdev->dev, "error: not enough data remaining\n"); 400 return -EINVAL; 401 } 402 403 /* minus header size of module */ 404 remaining -= sizeof(*module); 405 406 /* module */ 407 ret = load_module(sdev, module); 408 if (ret < 0) { 409 dev_err(sdev->dev, "error: invalid module %d\n", count); 410 return ret; 411 } 412 413 if (remaining < module->size) { 414 dev_err(sdev->dev, "error: not enough data remaining\n"); 415 return -EINVAL; 416 } 417 418 /* minus body size of module */ 419 remaining -= module->size; 420 module = (struct snd_sof_mod_hdr *)((u8 *)module 421 + sizeof(*module) + module->size); 422 } 423 424 return 0; 425 } 426 427 int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev) 428 { 429 struct snd_sof_pdata *plat_data = sdev->pdata; 430 const char *fw_filename; 431 int ret; 432 433 /* set code loading condition to true */ 434 sdev->code_loading = 1; 435 436 /* Don't request firmware again if firmware is already requested */ 437 if (plat_data->fw) 438 return 0; 439 440 fw_filename = kasprintf(GFP_KERNEL, "%s/%s", 441 plat_data->fw_filename_prefix, 442 plat_data->fw_filename); 443 if (!fw_filename) 444 return -ENOMEM; 445 446 ret = request_firmware(&plat_data->fw, fw_filename, sdev->dev); 447 448 if (ret < 0) { 449 dev_err(sdev->dev, "error: request firmware %s failed err: %d\n", 450 fw_filename, ret); 451 } 452 453 kfree(fw_filename); 454 455 return ret; 456 } 457 EXPORT_SYMBOL(snd_sof_load_firmware_raw); 458 459 int snd_sof_load_firmware_memcpy(struct snd_sof_dev *sdev) 460 { 461 struct snd_sof_pdata *plat_data = sdev->pdata; 462 int ret; 463 464 ret = snd_sof_load_firmware_raw(sdev); 465 if (ret < 0) 466 return ret; 467 468 /* make sure the FW header and file is valid */ 469 ret = check_header(sdev, plat_data->fw); 470 if (ret < 0) { 471 dev_err(sdev->dev, "error: invalid FW header\n"); 472 goto error; 473 } 474 475 /* prepare the DSP for FW loading */ 476 ret = snd_sof_dsp_reset(sdev); 477 if (ret < 0) { 478 dev_err(sdev->dev, "error: failed to reset DSP\n"); 479 goto error; 480 } 481 482 /* parse and load firmware modules to DSP */ 483 ret = load_modules(sdev, plat_data->fw); 484 if (ret < 0) { 485 dev_err(sdev->dev, "error: invalid FW modules\n"); 486 goto error; 487 } 488 489 return 0; 490 491 error: 492 release_firmware(plat_data->fw); 493 plat_data->fw = NULL; 494 return ret; 495 496 } 497 EXPORT_SYMBOL(snd_sof_load_firmware_memcpy); 498 499 int snd_sof_load_firmware(struct snd_sof_dev *sdev) 500 { 501 dev_dbg(sdev->dev, "loading firmware\n"); 502 503 if (sof_ops(sdev)->load_firmware) 504 return sof_ops(sdev)->load_firmware(sdev); 505 return 0; 506 } 507 EXPORT_SYMBOL(snd_sof_load_firmware); 508 509 int snd_sof_run_firmware(struct snd_sof_dev *sdev) 510 { 511 int ret; 512 int init_core_mask; 513 514 init_waitqueue_head(&sdev->boot_wait); 515 sdev->boot_complete = false; 516 517 /* create read-only fw_version debugfs to store boot version info */ 518 if (sdev->first_boot) { 519 ret = snd_sof_debugfs_buf_item(sdev, &sdev->fw_version, 520 sizeof(sdev->fw_version), 521 "fw_version", 0444); 522 /* errors are only due to memory allocation, not debugfs */ 523 if (ret < 0) { 524 dev_err(sdev->dev, "error: snd_sof_debugfs_buf_item failed\n"); 525 return ret; 526 } 527 } 528 529 /* perform pre fw run operations */ 530 ret = snd_sof_dsp_pre_fw_run(sdev); 531 if (ret < 0) { 532 dev_err(sdev->dev, "error: failed pre fw run op\n"); 533 return ret; 534 } 535 536 dev_dbg(sdev->dev, "booting DSP firmware\n"); 537 538 /* boot the firmware on the DSP */ 539 ret = snd_sof_dsp_run(sdev); 540 if (ret < 0) { 541 dev_err(sdev->dev, "error: failed to reset DSP\n"); 542 return ret; 543 } 544 545 init_core_mask = ret; 546 547 /* now wait for the DSP to boot */ 548 ret = wait_event_timeout(sdev->boot_wait, sdev->boot_complete, 549 msecs_to_jiffies(sdev->boot_timeout)); 550 if (ret == 0) { 551 dev_err(sdev->dev, "error: firmware boot failure\n"); 552 snd_sof_dsp_dbg_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX | 553 SOF_DBG_TEXT | SOF_DBG_PCI); 554 /* after this point FW_READY msg should be ignored */ 555 sdev->boot_complete = true; 556 return -EIO; 557 } 558 559 dev_info(sdev->dev, "firmware boot complete\n"); 560 561 /* perform post fw run operations */ 562 ret = snd_sof_dsp_post_fw_run(sdev); 563 if (ret < 0) { 564 dev_err(sdev->dev, "error: failed post fw run op\n"); 565 return ret; 566 } 567 568 /* fw boot is complete. Update the active cores mask */ 569 sdev->enabled_cores_mask = init_core_mask; 570 571 return 0; 572 } 573 EXPORT_SYMBOL(snd_sof_run_firmware); 574 575 void snd_sof_fw_unload(struct snd_sof_dev *sdev) 576 { 577 /* TODO: support module unloading at runtime */ 578 } 579 EXPORT_SYMBOL(snd_sof_fw_unload); 580