1 // SPDX-License-Identifier: (GPL-2.0-only 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 <sound/sof/ext_manifest.h> 16 #include "ops.h" 17 18 static int get_ext_windows(struct snd_sof_dev *sdev, 19 const struct sof_ipc_ext_data_hdr *ext_hdr) 20 { 21 const struct sof_ipc_window *w = 22 container_of(ext_hdr, struct sof_ipc_window, ext_hdr); 23 24 if (w->num_windows == 0 || w->num_windows > SOF_IPC_MAX_ELEMS) 25 return -EINVAL; 26 27 if (sdev->info_window) { 28 if (memcmp(sdev->info_window, w, ext_hdr->hdr.size)) { 29 dev_err(sdev->dev, "error: mismatch between window descriptor from extended manifest and mailbox"); 30 return -EINVAL; 31 } 32 return 0; 33 } 34 35 /* keep a local copy of the data */ 36 sdev->info_window = devm_kmemdup(sdev->dev, w, ext_hdr->hdr.size, 37 GFP_KERNEL); 38 if (!sdev->info_window) 39 return -ENOMEM; 40 41 return 0; 42 } 43 44 static int get_cc_info(struct snd_sof_dev *sdev, 45 const struct sof_ipc_ext_data_hdr *ext_hdr) 46 { 47 int ret; 48 49 const struct sof_ipc_cc_version *cc = 50 container_of(ext_hdr, struct sof_ipc_cc_version, ext_hdr); 51 52 if (sdev->cc_version) { 53 if (memcmp(sdev->cc_version, cc, cc->ext_hdr.hdr.size)) { 54 dev_err(sdev->dev, "error: receive diverged cc_version descriptions"); 55 return -EINVAL; 56 } 57 return 0; 58 } 59 60 dev_dbg(sdev->dev, "Firmware info: used compiler %s %d:%d:%d%s used optimization flags %s\n", 61 cc->name, cc->major, cc->minor, cc->micro, cc->desc, 62 cc->optim); 63 64 /* create read-only cc_version debugfs to store compiler version info */ 65 /* use local copy of the cc_version to prevent data corruption */ 66 if (sdev->first_boot) { 67 sdev->cc_version = devm_kmalloc(sdev->dev, cc->ext_hdr.hdr.size, 68 GFP_KERNEL); 69 70 if (!sdev->cc_version) 71 return -ENOMEM; 72 73 memcpy(sdev->cc_version, cc, cc->ext_hdr.hdr.size); 74 ret = snd_sof_debugfs_buf_item(sdev, sdev->cc_version, 75 cc->ext_hdr.hdr.size, 76 "cc_version", 0444); 77 78 /* errors are only due to memory allocation, not debugfs */ 79 if (ret < 0) { 80 dev_err(sdev->dev, "error: snd_sof_debugfs_buf_item failed\n"); 81 return ret; 82 } 83 } 84 85 return 0; 86 } 87 88 /* parse the extended FW boot data structures from FW boot message */ 89 int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset) 90 { 91 struct sof_ipc_ext_data_hdr *ext_hdr; 92 void *ext_data; 93 int ret = 0; 94 95 ext_data = kzalloc(PAGE_SIZE, GFP_KERNEL); 96 if (!ext_data) 97 return -ENOMEM; 98 99 /* get first header */ 100 snd_sof_dsp_block_read(sdev, bar, offset, ext_data, 101 sizeof(*ext_hdr)); 102 ext_hdr = ext_data; 103 104 while (ext_hdr->hdr.cmd == SOF_IPC_FW_READY) { 105 /* read in ext structure */ 106 snd_sof_dsp_block_read(sdev, bar, offset + sizeof(*ext_hdr), 107 (void *)((u8 *)ext_data + sizeof(*ext_hdr)), 108 ext_hdr->hdr.size - sizeof(*ext_hdr)); 109 110 dev_dbg(sdev->dev, "found ext header type %d size 0x%x\n", 111 ext_hdr->type, ext_hdr->hdr.size); 112 113 /* process structure data */ 114 switch (ext_hdr->type) { 115 case SOF_IPC_EXT_WINDOW: 116 ret = get_ext_windows(sdev, ext_hdr); 117 break; 118 case SOF_IPC_EXT_CC_INFO: 119 ret = get_cc_info(sdev, ext_hdr); 120 break; 121 case SOF_IPC_EXT_UNUSED: 122 case SOF_IPC_EXT_PROBE_INFO: 123 case SOF_IPC_EXT_USER_ABI_INFO: 124 /* They are supported but we don't do anything here */ 125 break; 126 default: 127 dev_warn(sdev->dev, "warning: unknown ext header type %d size 0x%x\n", 128 ext_hdr->type, ext_hdr->hdr.size); 129 ret = 0; 130 break; 131 } 132 133 if (ret < 0) { 134 dev_err(sdev->dev, "error: failed to parse ext data type %d\n", 135 ext_hdr->type); 136 break; 137 } 138 139 /* move to next header */ 140 offset += ext_hdr->hdr.size; 141 snd_sof_dsp_block_read(sdev, bar, offset, ext_data, 142 sizeof(*ext_hdr)); 143 ext_hdr = ext_data; 144 } 145 146 kfree(ext_data); 147 return ret; 148 } 149 EXPORT_SYMBOL(snd_sof_fw_parse_ext_data); 150 151 static int ext_man_get_fw_version(struct snd_sof_dev *sdev, 152 const struct sof_ext_man_elem_header *hdr) 153 { 154 const struct sof_ext_man_fw_version *v = 155 container_of(hdr, struct sof_ext_man_fw_version, hdr); 156 157 memcpy(&sdev->fw_ready.version, &v->version, sizeof(v->version)); 158 sdev->fw_ready.flags = v->flags; 159 160 /* log ABI versions and check FW compatibility */ 161 return snd_sof_ipc_valid(sdev); 162 } 163 164 static int ext_man_get_windows(struct snd_sof_dev *sdev, 165 const struct sof_ext_man_elem_header *hdr) 166 { 167 const struct sof_ext_man_window *w; 168 169 w = container_of(hdr, struct sof_ext_man_window, hdr); 170 171 return get_ext_windows(sdev, &w->ipc_window.ext_hdr); 172 } 173 174 static int ext_man_get_cc_info(struct snd_sof_dev *sdev, 175 const struct sof_ext_man_elem_header *hdr) 176 { 177 const struct sof_ext_man_cc_version *cc; 178 179 cc = container_of(hdr, struct sof_ext_man_cc_version, hdr); 180 181 return get_cc_info(sdev, &cc->cc_version.ext_hdr); 182 } 183 184 static int ext_man_get_dbg_abi_info(struct snd_sof_dev *sdev, 185 const struct sof_ext_man_elem_header *hdr) 186 { 187 const struct ext_man_dbg_abi *dbg_abi = 188 container_of(hdr, struct ext_man_dbg_abi, hdr); 189 190 if (sdev->first_boot) 191 dev_dbg(sdev->dev, 192 "Firmware: DBG_ABI %d:%d:%d\n", 193 SOF_ABI_VERSION_MAJOR(dbg_abi->dbg_abi.abi_dbg_version), 194 SOF_ABI_VERSION_MINOR(dbg_abi->dbg_abi.abi_dbg_version), 195 SOF_ABI_VERSION_PATCH(dbg_abi->dbg_abi.abi_dbg_version)); 196 197 return 0; 198 } 199 200 static ssize_t snd_sof_ext_man_size(const struct firmware *fw) 201 { 202 const struct sof_ext_man_header *head; 203 204 head = (struct sof_ext_man_header *)fw->data; 205 206 /* 207 * assert fw size is big enough to contain extended manifest header, 208 * it prevents from reading unallocated memory from `head` in following 209 * step. 210 */ 211 if (fw->size < sizeof(*head)) 212 return -EINVAL; 213 214 /* 215 * When fw points to extended manifest, 216 * then first u32 must be equal SOF_EXT_MAN_MAGIC_NUMBER. 217 */ 218 if (head->magic == SOF_EXT_MAN_MAGIC_NUMBER) 219 return head->full_size; 220 221 /* otherwise given fw don't have an extended manifest */ 222 return 0; 223 } 224 225 /* parse extended FW manifest data structures */ 226 static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev, 227 const struct firmware *fw) 228 { 229 const struct sof_ext_man_elem_header *elem_hdr; 230 const struct sof_ext_man_header *head; 231 ssize_t ext_man_size; 232 ssize_t remaining; 233 uintptr_t iptr; 234 int ret = 0; 235 236 head = (struct sof_ext_man_header *)fw->data; 237 remaining = head->full_size - head->header_size; 238 ext_man_size = snd_sof_ext_man_size(fw); 239 240 /* Assert firmware starts with extended manifest */ 241 if (ext_man_size <= 0) 242 return ext_man_size; 243 244 /* incompatible version */ 245 if (SOF_EXT_MAN_VERSION_INCOMPATIBLE(SOF_EXT_MAN_VERSION, 246 head->header_version)) { 247 dev_err(sdev->dev, "error: extended manifest version 0x%X differ from used 0x%X\n", 248 head->header_version, SOF_EXT_MAN_VERSION); 249 return -EINVAL; 250 } 251 252 /* get first extended manifest element header */ 253 iptr = (uintptr_t)fw->data + head->header_size; 254 255 while (remaining > sizeof(*elem_hdr)) { 256 elem_hdr = (struct sof_ext_man_elem_header *)iptr; 257 258 dev_dbg(sdev->dev, "found sof_ext_man header type %d size 0x%X\n", 259 elem_hdr->type, elem_hdr->size); 260 261 if (elem_hdr->size < sizeof(*elem_hdr) || 262 elem_hdr->size > remaining) { 263 dev_err(sdev->dev, "error: invalid sof_ext_man header size, type %d size 0x%X\n", 264 elem_hdr->type, elem_hdr->size); 265 return -EINVAL; 266 } 267 268 /* process structure data */ 269 switch (elem_hdr->type) { 270 case SOF_EXT_MAN_ELEM_FW_VERSION: 271 ret = ext_man_get_fw_version(sdev, elem_hdr); 272 break; 273 case SOF_EXT_MAN_ELEM_WINDOW: 274 ret = ext_man_get_windows(sdev, elem_hdr); 275 break; 276 case SOF_EXT_MAN_ELEM_CC_VERSION: 277 ret = ext_man_get_cc_info(sdev, elem_hdr); 278 break; 279 case SOF_EXT_MAN_ELEM_DBG_ABI: 280 ret = ext_man_get_dbg_abi_info(sdev, elem_hdr); 281 break; 282 default: 283 dev_warn(sdev->dev, "warning: unknown sof_ext_man header type %d size 0x%X\n", 284 elem_hdr->type, elem_hdr->size); 285 break; 286 } 287 288 if (ret < 0) { 289 dev_err(sdev->dev, "error: failed to parse sof_ext_man header type %d size 0x%X\n", 290 elem_hdr->type, elem_hdr->size); 291 return ret; 292 } 293 294 remaining -= elem_hdr->size; 295 iptr += elem_hdr->size; 296 } 297 298 if (remaining) { 299 dev_err(sdev->dev, "error: sof_ext_man header is inconsistent\n"); 300 return -EINVAL; 301 } 302 303 return ext_man_size; 304 } 305 306 /* 307 * IPC Firmware ready. 308 */ 309 static void sof_get_windows(struct snd_sof_dev *sdev) 310 { 311 struct sof_ipc_window_elem *elem; 312 u32 outbox_offset = 0; 313 u32 stream_offset = 0; 314 u32 inbox_offset = 0; 315 u32 outbox_size = 0; 316 u32 stream_size = 0; 317 u32 inbox_size = 0; 318 u32 debug_size = 0; 319 u32 debug_offset = 0; 320 int window_offset; 321 int bar; 322 int i; 323 324 if (!sdev->info_window) { 325 dev_err(sdev->dev, "error: have no window info\n"); 326 return; 327 } 328 329 bar = snd_sof_dsp_get_bar_index(sdev, SOF_FW_BLK_TYPE_SRAM); 330 if (bar < 0) { 331 dev_err(sdev->dev, "error: have no bar mapping\n"); 332 return; 333 } 334 335 for (i = 0; i < sdev->info_window->num_windows; i++) { 336 elem = &sdev->info_window->window[i]; 337 338 window_offset = snd_sof_dsp_get_window_offset(sdev, elem->id); 339 if (window_offset < 0) { 340 dev_warn(sdev->dev, "warn: no offset for window %d\n", 341 elem->id); 342 continue; 343 } 344 345 switch (elem->type) { 346 case SOF_IPC_REGION_UPBOX: 347 inbox_offset = window_offset + elem->offset; 348 inbox_size = elem->size; 349 snd_sof_debugfs_io_item(sdev, 350 sdev->bar[bar] + 351 inbox_offset, 352 elem->size, "inbox", 353 SOF_DEBUGFS_ACCESS_D0_ONLY); 354 break; 355 case SOF_IPC_REGION_DOWNBOX: 356 outbox_offset = window_offset + elem->offset; 357 outbox_size = elem->size; 358 snd_sof_debugfs_io_item(sdev, 359 sdev->bar[bar] + 360 outbox_offset, 361 elem->size, "outbox", 362 SOF_DEBUGFS_ACCESS_D0_ONLY); 363 break; 364 case SOF_IPC_REGION_TRACE: 365 snd_sof_debugfs_io_item(sdev, 366 sdev->bar[bar] + 367 window_offset + 368 elem->offset, 369 elem->size, "etrace", 370 SOF_DEBUGFS_ACCESS_D0_ONLY); 371 break; 372 case SOF_IPC_REGION_DEBUG: 373 debug_offset = window_offset + elem->offset; 374 debug_size = elem->size; 375 snd_sof_debugfs_io_item(sdev, 376 sdev->bar[bar] + 377 window_offset + 378 elem->offset, 379 elem->size, "debug", 380 SOF_DEBUGFS_ACCESS_D0_ONLY); 381 break; 382 case SOF_IPC_REGION_STREAM: 383 stream_offset = window_offset + elem->offset; 384 stream_size = elem->size; 385 snd_sof_debugfs_io_item(sdev, 386 sdev->bar[bar] + 387 stream_offset, 388 elem->size, "stream", 389 SOF_DEBUGFS_ACCESS_D0_ONLY); 390 break; 391 case SOF_IPC_REGION_REGS: 392 snd_sof_debugfs_io_item(sdev, 393 sdev->bar[bar] + 394 window_offset + 395 elem->offset, 396 elem->size, "regs", 397 SOF_DEBUGFS_ACCESS_D0_ONLY); 398 break; 399 case SOF_IPC_REGION_EXCEPTION: 400 sdev->dsp_oops_offset = window_offset + elem->offset; 401 snd_sof_debugfs_io_item(sdev, 402 sdev->bar[bar] + 403 window_offset + 404 elem->offset, 405 elem->size, "exception", 406 SOF_DEBUGFS_ACCESS_D0_ONLY); 407 break; 408 default: 409 dev_err(sdev->dev, "error: get illegal window info\n"); 410 return; 411 } 412 } 413 414 if (outbox_size == 0 || inbox_size == 0) { 415 dev_err(sdev->dev, "error: get illegal mailbox window\n"); 416 return; 417 } 418 419 snd_sof_dsp_mailbox_init(sdev, inbox_offset, inbox_size, 420 outbox_offset, outbox_size); 421 sdev->stream_box.offset = stream_offset; 422 sdev->stream_box.size = stream_size; 423 424 sdev->debug_box.offset = debug_offset; 425 sdev->debug_box.size = debug_size; 426 427 dev_dbg(sdev->dev, " mailbox upstream 0x%x - size 0x%x\n", 428 inbox_offset, inbox_size); 429 dev_dbg(sdev->dev, " mailbox downstream 0x%x - size 0x%x\n", 430 outbox_offset, outbox_size); 431 dev_dbg(sdev->dev, " stream region 0x%x - size 0x%x\n", 432 stream_offset, stream_size); 433 dev_dbg(sdev->dev, " debug region 0x%x - size 0x%x\n", 434 debug_offset, debug_size); 435 } 436 437 /* check for ABI compatibility and create memory windows on first boot */ 438 int sof_fw_ready(struct snd_sof_dev *sdev, u32 msg_id) 439 { 440 struct sof_ipc_fw_ready *fw_ready = &sdev->fw_ready; 441 int offset; 442 int bar; 443 int ret; 444 445 /* mailbox must be on 4k boundary */ 446 offset = snd_sof_dsp_get_mailbox_offset(sdev); 447 if (offset < 0) { 448 dev_err(sdev->dev, "error: have no mailbox offset\n"); 449 return offset; 450 } 451 452 bar = snd_sof_dsp_get_bar_index(sdev, SOF_FW_BLK_TYPE_SRAM); 453 if (bar < 0) { 454 dev_err(sdev->dev, "error: have no bar mapping\n"); 455 return -EINVAL; 456 } 457 458 dev_dbg(sdev->dev, "ipc: DSP is ready 0x%8.8x offset 0x%x\n", 459 msg_id, offset); 460 461 /* no need to re-check version/ABI for subsequent boots */ 462 if (!sdev->first_boot) 463 return 0; 464 465 /* copy data from the DSP FW ready offset */ 466 sof_block_read(sdev, bar, offset, fw_ready, sizeof(*fw_ready)); 467 468 /* make sure ABI version is compatible */ 469 ret = snd_sof_ipc_valid(sdev); 470 if (ret < 0) 471 return ret; 472 473 /* now check for extended data */ 474 snd_sof_fw_parse_ext_data(sdev, bar, offset + 475 sizeof(struct sof_ipc_fw_ready)); 476 477 sof_get_windows(sdev); 478 479 return 0; 480 } 481 EXPORT_SYMBOL(sof_fw_ready); 482 483 /* generic module parser for mmaped DSPs */ 484 int snd_sof_parse_module_memcpy(struct snd_sof_dev *sdev, 485 struct snd_sof_mod_hdr *module) 486 { 487 struct snd_sof_blk_hdr *block; 488 int count, bar; 489 u32 offset; 490 size_t remaining; 491 492 dev_dbg(sdev->dev, "new module size 0x%x blocks 0x%x type 0x%x\n", 493 module->size, module->num_blocks, module->type); 494 495 block = (struct snd_sof_blk_hdr *)((u8 *)module + sizeof(*module)); 496 497 /* module->size doesn't include header size */ 498 remaining = module->size; 499 for (count = 0; count < module->num_blocks; count++) { 500 /* check for wrap */ 501 if (remaining < sizeof(*block)) { 502 dev_err(sdev->dev, "error: not enough data remaining\n"); 503 return -EINVAL; 504 } 505 506 /* minus header size of block */ 507 remaining -= sizeof(*block); 508 509 if (block->size == 0) { 510 dev_warn(sdev->dev, 511 "warning: block %d size zero\n", count); 512 dev_warn(sdev->dev, " type 0x%x offset 0x%x\n", 513 block->type, block->offset); 514 continue; 515 } 516 517 switch (block->type) { 518 case SOF_FW_BLK_TYPE_RSRVD0: 519 case SOF_FW_BLK_TYPE_ROM...SOF_FW_BLK_TYPE_RSRVD14: 520 continue; /* not handled atm */ 521 case SOF_FW_BLK_TYPE_IRAM: 522 case SOF_FW_BLK_TYPE_DRAM: 523 case SOF_FW_BLK_TYPE_SRAM: 524 offset = block->offset; 525 bar = snd_sof_dsp_get_bar_index(sdev, block->type); 526 if (bar < 0) { 527 dev_err(sdev->dev, 528 "error: no BAR mapping for block type 0x%x\n", 529 block->type); 530 return bar; 531 } 532 break; 533 default: 534 dev_err(sdev->dev, "error: bad type 0x%x for block 0x%x\n", 535 block->type, count); 536 return -EINVAL; 537 } 538 539 dev_dbg(sdev->dev, 540 "block %d type 0x%x size 0x%x ==> offset 0x%x\n", 541 count, block->type, block->size, offset); 542 543 /* checking block->size to avoid unaligned access */ 544 if (block->size % sizeof(u32)) { 545 dev_err(sdev->dev, "error: invalid block size 0x%x\n", 546 block->size); 547 return -EINVAL; 548 } 549 snd_sof_dsp_block_write(sdev, bar, offset, 550 block + 1, block->size); 551 552 if (remaining < block->size) { 553 dev_err(sdev->dev, "error: not enough data remaining\n"); 554 return -EINVAL; 555 } 556 557 /* minus body size of block */ 558 remaining -= block->size; 559 /* next block */ 560 block = (struct snd_sof_blk_hdr *)((u8 *)block + sizeof(*block) 561 + block->size); 562 } 563 564 return 0; 565 } 566 EXPORT_SYMBOL(snd_sof_parse_module_memcpy); 567 568 static int check_header(struct snd_sof_dev *sdev, const struct firmware *fw, 569 size_t fw_offset) 570 { 571 struct snd_sof_fw_header *header; 572 size_t fw_size = fw->size - fw_offset; 573 574 if (fw->size <= fw_offset) { 575 dev_err(sdev->dev, "error: firmware size must be greater than firmware offset\n"); 576 return -EINVAL; 577 } 578 579 /* Read the header information from the data pointer */ 580 header = (struct snd_sof_fw_header *)(fw->data + fw_offset); 581 582 /* verify FW sig */ 583 if (strncmp(header->sig, SND_SOF_FW_SIG, SND_SOF_FW_SIG_SIZE) != 0) { 584 dev_err(sdev->dev, "error: invalid firmware signature\n"); 585 return -EINVAL; 586 } 587 588 /* check size is valid */ 589 if (fw_size != header->file_size + sizeof(*header)) { 590 dev_err(sdev->dev, "error: invalid filesize mismatch got 0x%zx expected 0x%zx\n", 591 fw_size, header->file_size + sizeof(*header)); 592 return -EINVAL; 593 } 594 595 dev_dbg(sdev->dev, "header size=0x%x modules=0x%x abi=0x%x size=%zu\n", 596 header->file_size, header->num_modules, 597 header->abi, sizeof(*header)); 598 599 return 0; 600 } 601 602 static int load_modules(struct snd_sof_dev *sdev, const struct firmware *fw, 603 size_t fw_offset) 604 { 605 struct snd_sof_fw_header *header; 606 struct snd_sof_mod_hdr *module; 607 int (*load_module)(struct snd_sof_dev *sof_dev, 608 struct snd_sof_mod_hdr *hdr); 609 int ret, count; 610 size_t remaining; 611 612 header = (struct snd_sof_fw_header *)(fw->data + fw_offset); 613 load_module = sof_ops(sdev)->load_module; 614 if (!load_module) 615 return -EINVAL; 616 617 /* parse each module */ 618 module = (struct snd_sof_mod_hdr *)(fw->data + fw_offset + 619 sizeof(*header)); 620 remaining = fw->size - sizeof(*header) - fw_offset; 621 /* check for wrap */ 622 if (remaining > fw->size) { 623 dev_err(sdev->dev, "error: fw size smaller than header size\n"); 624 return -EINVAL; 625 } 626 627 for (count = 0; count < header->num_modules; count++) { 628 /* check for wrap */ 629 if (remaining < sizeof(*module)) { 630 dev_err(sdev->dev, "error: not enough data remaining\n"); 631 return -EINVAL; 632 } 633 634 /* minus header size of module */ 635 remaining -= sizeof(*module); 636 637 /* module */ 638 ret = load_module(sdev, module); 639 if (ret < 0) { 640 dev_err(sdev->dev, "error: invalid module %d\n", count); 641 return ret; 642 } 643 644 if (remaining < module->size) { 645 dev_err(sdev->dev, "error: not enough data remaining\n"); 646 return -EINVAL; 647 } 648 649 /* minus body size of module */ 650 remaining -= module->size; 651 module = (struct snd_sof_mod_hdr *)((u8 *)module 652 + sizeof(*module) + module->size); 653 } 654 655 return 0; 656 } 657 658 int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev) 659 { 660 struct snd_sof_pdata *plat_data = sdev->pdata; 661 const char *fw_filename; 662 ssize_t ext_man_size; 663 int ret; 664 665 /* Don't request firmware again if firmware is already requested */ 666 if (plat_data->fw) 667 return 0; 668 669 fw_filename = kasprintf(GFP_KERNEL, "%s/%s", 670 plat_data->fw_filename_prefix, 671 plat_data->fw_filename); 672 if (!fw_filename) 673 return -ENOMEM; 674 675 ret = request_firmware(&plat_data->fw, fw_filename, sdev->dev); 676 677 if (ret < 0) { 678 dev_err(sdev->dev, "error: request firmware %s failed err: %d\n", 679 fw_filename, ret); 680 goto err; 681 } else { 682 dev_dbg(sdev->dev, "request_firmware %s successful\n", 683 fw_filename); 684 } 685 686 /* check for extended manifest */ 687 ext_man_size = snd_sof_fw_ext_man_parse(sdev, plat_data->fw); 688 if (ext_man_size > 0) { 689 /* when no error occurred, drop extended manifest */ 690 plat_data->fw_offset = ext_man_size; 691 } else if (!ext_man_size) { 692 /* No extended manifest, so nothing to skip during FW load */ 693 dev_dbg(sdev->dev, "firmware doesn't contain extended manifest\n"); 694 } else { 695 ret = ext_man_size; 696 dev_err(sdev->dev, "error: firmware %s contains unsupported or invalid extended manifest: %d\n", 697 fw_filename, ret); 698 } 699 700 err: 701 kfree(fw_filename); 702 703 return ret; 704 } 705 EXPORT_SYMBOL(snd_sof_load_firmware_raw); 706 707 int snd_sof_load_firmware_memcpy(struct snd_sof_dev *sdev) 708 { 709 struct snd_sof_pdata *plat_data = sdev->pdata; 710 int ret; 711 712 ret = snd_sof_load_firmware_raw(sdev); 713 if (ret < 0) 714 return ret; 715 716 /* make sure the FW header and file is valid */ 717 ret = check_header(sdev, plat_data->fw, plat_data->fw_offset); 718 if (ret < 0) { 719 dev_err(sdev->dev, "error: invalid FW header\n"); 720 goto error; 721 } 722 723 /* prepare the DSP for FW loading */ 724 ret = snd_sof_dsp_reset(sdev); 725 if (ret < 0) { 726 dev_err(sdev->dev, "error: failed to reset DSP\n"); 727 goto error; 728 } 729 730 /* parse and load firmware modules to DSP */ 731 ret = load_modules(sdev, plat_data->fw, plat_data->fw_offset); 732 if (ret < 0) { 733 dev_err(sdev->dev, "error: invalid FW modules\n"); 734 goto error; 735 } 736 737 return 0; 738 739 error: 740 release_firmware(plat_data->fw); 741 plat_data->fw = NULL; 742 return ret; 743 744 } 745 EXPORT_SYMBOL(snd_sof_load_firmware_memcpy); 746 747 int snd_sof_load_firmware(struct snd_sof_dev *sdev) 748 { 749 dev_dbg(sdev->dev, "loading firmware\n"); 750 751 if (sof_ops(sdev)->load_firmware) 752 return sof_ops(sdev)->load_firmware(sdev); 753 return 0; 754 } 755 EXPORT_SYMBOL(snd_sof_load_firmware); 756 757 int snd_sof_run_firmware(struct snd_sof_dev *sdev) 758 { 759 int ret; 760 int init_core_mask; 761 762 init_waitqueue_head(&sdev->boot_wait); 763 764 /* create read-only fw_version debugfs to store boot version info */ 765 if (sdev->first_boot) { 766 ret = snd_sof_debugfs_buf_item(sdev, &sdev->fw_version, 767 sizeof(sdev->fw_version), 768 "fw_version", 0444); 769 /* errors are only due to memory allocation, not debugfs */ 770 if (ret < 0) { 771 dev_err(sdev->dev, "error: snd_sof_debugfs_buf_item failed\n"); 772 return ret; 773 } 774 } 775 776 /* perform pre fw run operations */ 777 ret = snd_sof_dsp_pre_fw_run(sdev); 778 if (ret < 0) { 779 dev_err(sdev->dev, "error: failed pre fw run op\n"); 780 return ret; 781 } 782 783 dev_dbg(sdev->dev, "booting DSP firmware\n"); 784 785 /* boot the firmware on the DSP */ 786 ret = snd_sof_dsp_run(sdev); 787 if (ret < 0) { 788 dev_err(sdev->dev, "error: failed to reset DSP\n"); 789 return ret; 790 } 791 792 init_core_mask = ret; 793 794 /* 795 * now wait for the DSP to boot. There are 3 possible outcomes: 796 * 1. Boot wait times out indicating FW boot failure. 797 * 2. FW boots successfully and fw_ready op succeeds. 798 * 3. FW boots but fw_ready op fails. 799 */ 800 ret = wait_event_timeout(sdev->boot_wait, 801 sdev->fw_state > SOF_FW_BOOT_IN_PROGRESS, 802 msecs_to_jiffies(sdev->boot_timeout)); 803 if (ret == 0) { 804 dev_err(sdev->dev, "error: firmware boot failure\n"); 805 snd_sof_dsp_dbg_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX | 806 SOF_DBG_TEXT | SOF_DBG_PCI); 807 sdev->fw_state = SOF_FW_BOOT_FAILED; 808 return -EIO; 809 } 810 811 if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) 812 dev_dbg(sdev->dev, "firmware boot complete\n"); 813 else 814 return -EIO; /* FW boots but fw_ready op failed */ 815 816 /* perform post fw run operations */ 817 ret = snd_sof_dsp_post_fw_run(sdev); 818 if (ret < 0) { 819 dev_err(sdev->dev, "error: failed post fw run op\n"); 820 return ret; 821 } 822 823 /* fw boot is complete. Update the active cores mask */ 824 sdev->enabled_cores_mask = init_core_mask; 825 826 return 0; 827 } 828 EXPORT_SYMBOL(snd_sof_run_firmware); 829 830 void snd_sof_fw_unload(struct snd_sof_dev *sdev) 831 { 832 /* TODO: support module unloading at runtime */ 833 } 834 EXPORT_SYMBOL(snd_sof_fw_unload); 835