1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2020 Intel Corporation. All rights reserved.
4 //
5 // Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com>
6 
7 #include <kernel/abi.h>
8 #include <kernel/ext_manifest.h>
9 #include <errno.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 
14 #include "ldc.h"
15 #include "smex.h"
16 
fw_version_copy(const struct elf_module * src,struct snd_sof_logs_header * header)17 static int fw_version_copy(const struct elf_module *src,
18 			   struct snd_sof_logs_header *header)
19 {
20 	struct ext_man_elem_header *ext_hdr = NULL;
21 	void *buffer = NULL;
22 	int section_size;
23 
24 	section_size = elf_read_section(src, ".fw_ready", NULL, &buffer);
25 
26 	if (section_size < 0)
27 		return section_size;
28 
29 	memcpy(&header->version,
30 	       &((struct sof_ipc_fw_ready *)buffer)->version,
31 	       sizeof(header->version));
32 	free(buffer);
33 
34 	/* fw_ready structure contains main (primarily kernel)
35 	 * ABI version.
36 	 */
37 	fprintf(stdout, "fw abi main version:\t%d.%d.%d\n",
38 		SOF_ABI_VERSION_MAJOR(header->version.abi_version),
39 		SOF_ABI_VERSION_MINOR(header->version.abi_version),
40 		SOF_ABI_VERSION_PATCH(header->version.abi_version));
41 
42 	/* let's find dbg abi version, which the log client
43 	 * is interested in and override the kernel's one.
44 	 *
45 	 * skip the base fw-ready record and begin from the first extension.
46 	 */
47 	section_size = elf_read_section(src, ".fw_metadata", NULL, &buffer);
48 
49 	if (section_size < 0)
50 		return section_size;
51 
52 	ext_hdr = (struct ext_man_elem_header *)buffer;
53 	while ((uintptr_t)ext_hdr < (uintptr_t)buffer + section_size) {
54 		if (ext_hdr->type == EXT_MAN_ELEM_DBG_ABI) {
55 			header->version.abi_version =
56 				((struct ext_man_dbg_abi *)
57 						ext_hdr)->dbg_abi.abi_dbg_version;
58 			break;
59 		}
60 		//move to the next entry
61 		ext_hdr = (struct ext_man_elem_header *)
62 				((uint8_t *)ext_hdr + ext_hdr->elem_size);
63 	}
64 	free(buffer);
65 
66 	fprintf(stdout, "fw abi dbg version:\t%d.%d.%d\n",
67 		SOF_ABI_VERSION_MAJOR(header->version.abi_version),
68 		SOF_ABI_VERSION_MINOR(header->version.abi_version),
69 		SOF_ABI_VERSION_PATCH(header->version.abi_version));
70 
71 	return 0;
72 }
73 
write_logs_dictionary(struct image * image,const struct elf_module * src)74 static int write_logs_dictionary(struct image *image,
75 				 const struct elf_module *src)
76 {
77 	struct snd_sof_logs_header header;
78 	const Elf32_Shdr *section;
79 	void *buffer = NULL;
80 	int count;
81 	int ret;
82 
83 	memcpy(header.sig, SND_SOF_LOGS_SIG, SND_SOF_LOGS_SIG_SIZE);
84 	header.data_offset = sizeof(struct snd_sof_logs_header);
85 
86 	/* extract fw_version from fw_ready message located
87 	 * in .fw_ready section
88 	 */
89 	ret = fw_version_copy(src, &header);
90 	if (ret < 0)
91 		goto out;
92 
93 	ret = elf_read_section(src, ".static_log_entries", &section, &buffer);
94 	if (ret < 0)
95 		goto out;
96 
97 	ret = 0;
98 	header.base_address = section->vaddr;
99 	header.data_length = section->size;
100 
101 	fwrite(&header, sizeof(struct snd_sof_logs_header), 1,
102 	       image->ldc_out_fd);
103 
104 	count = fwrite(buffer, 1, section->size, image->ldc_out_fd);
105 	if (count != section->size) {
106 		fprintf(stderr,
107 			"error: can't write section %d\n",
108 			-errno);
109 		ret = -errno;
110 		goto out;
111 	}
112 
113 	fprintf(stdout, "logs dictionary size:\t%u\n",
114 		header.data_length + header.data_offset);
115 	fprintf(stdout, "including fw version of size:\t%lu\n",
116 		(unsigned long)sizeof(header.version));
117 out:
118 	if (buffer)
119 		free(buffer);
120 
121 	return ret;
122 }
123 
write_uids_dictionary(struct image * image,const struct elf_module * src)124 static int write_uids_dictionary(struct image *image,
125 				 const struct elf_module *src)
126 {
127 	struct snd_sof_uids_header header;
128 	const Elf32_Shdr *section;
129 	void *buffer = NULL;
130 	int ret;
131 
132 	memcpy(header.sig, SND_SOF_UIDS_SIG, SND_SOF_UIDS_SIG_SIZE);
133 	header.data_offset = sizeof(struct snd_sof_uids_header);
134 
135 	ret = elf_read_section(src, ".static_uuid_entries", &section, &buffer);
136 	if (ret < 0)
137 		goto out;
138 
139 	ret = 0;
140 	header.base_address = section->vaddr;
141 	header.data_length = section->size;
142 
143 	fwrite(&header, sizeof(struct snd_sof_uids_header), 1,
144 	       image->ldc_out_fd);
145 
146 	if (fwrite(buffer, 1, section->size, image->ldc_out_fd) !=
147 			section->size) {
148 		fprintf(stderr, "error: cant't write section %d\n",
149 			-errno);
150 		ret = -errno;
151 		goto out;
152 	}
153 	fprintf(stdout, "uids dictionary size:\t%u\n",
154 		header.data_length + header.data_offset);
155 out:
156 	if (buffer)
157 		free(buffer);
158 	return ret;
159 }
160 
write_dictionaries(struct image * image,const struct elf_module * src)161 int write_dictionaries(struct image *image, const struct elf_module *src)
162 {
163 	int ret = 0;
164 
165 	ret = write_logs_dictionary(image, src);
166 	if (ret)
167 		goto out;
168 
169 	ret = write_uids_dictionary(image, src);
170 
171 out:
172 	return ret;
173 }
174