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