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