sound/soc/sof/ipc3-loader.c

Source file repositories/reference/linux-study-clean/sound/soc/sof/ipc3-loader.c

File Facts

System
Linux kernel
Corpus path
sound/soc/sof/ipc3-loader.c
Extension
.c
Size
11850 bytes
Lines
420
Domain
Driver Families
Bucket
sound/soc
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

switch (elem->token) {
		case SOF_EXT_MAN_CONFIG_EMPTY:
			/* unused memory space is zero filled - mapped to EMPTY elements */
			break;
		case SOF_EXT_MAN_CONFIG_IPC_MSG_SIZE:
			/* TODO: use ipc msg size from config data */
			break;
		case SOF_EXT_MAN_CONFIG_MEMORY_USAGE_SCAN:
			if (sdev->first_boot && elem->value)
				ret = snd_sof_dbg_memory_info_init(sdev);
			break;
		default:
			dev_info(sdev->dev,
				 "Unknown firmware configuration token %d value %d",
				 elem->token, elem->value);
			break;
		}
		if (ret < 0) {
			dev_err(sdev->dev,
				"%s: processing failed for token %d value %#x, %d\n",
				__func__, elem->token, elem->value, ret);
			return ret;
		}
	}

	return 0;
}

static ssize_t ipc3_fw_ext_man_size(struct snd_sof_dev *sdev, const struct firmware *fw)
{
	const struct sof_ext_man_header *head;

	head = (struct sof_ext_man_header *)fw->data;

	/*
	 * assert fw size is big enough to contain extended manifest header,
	 * it prevents from reading unallocated memory from `head` in following
	 * step.
	 */
	if (fw->size < sizeof(*head))
		return -EINVAL;

	/*
	 * When fw points to extended manifest,
	 * then first u32 must be equal SOF_EXT_MAN_MAGIC_NUMBER.
	 */
	if (head->magic == SOF_EXT_MAN_MAGIC_NUMBER)
		return head->full_size;

	/* otherwise given fw don't have an extended manifest */
	dev_dbg(sdev->dev, "Unexpected extended manifest magic number: %#x\n",
		head->magic);
	return 0;
}

static size_t sof_ipc3_fw_parse_ext_man(struct snd_sof_dev *sdev)
{
	const struct firmware *fw = sdev->basefw.fw;
	const struct sof_ext_man_elem_header *elem_hdr;
	const struct sof_ext_man_header *head;
	ssize_t ext_man_size;
	ssize_t remaining;
	uintptr_t iptr;
	int ret = 0;

	head = (struct sof_ext_man_header *)fw->data;
	remaining = head->full_size - head->header_size;
	if (remaining < 0 || remaining > sdev->basefw.fw->size)
		return -EINVAL;
	ext_man_size = ipc3_fw_ext_man_size(sdev, fw);

	/* Assert firmware starts with extended manifest */
	if (ext_man_size <= 0)
		return ext_man_size;

	/* incompatible version */
	if (SOF_EXT_MAN_VERSION_INCOMPATIBLE(SOF_EXT_MAN_VERSION,
					     head->header_version)) {
		dev_err(sdev->dev,
			"extended manifest version %#x differ from used %#x\n",
			head->header_version, SOF_EXT_MAN_VERSION);
		return -EINVAL;
	}

	/* get first extended manifest element header */
	iptr = (uintptr_t)fw->data + head->header_size;

	while (remaining > sizeof(*elem_hdr)) {
		elem_hdr = (struct sof_ext_man_elem_header *)iptr;

Annotation

Implementation Notes