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