diff --git a/tools/ctl/ctl.c b/tools/ctl/ctl.c index 1d89c2c15fd9..08e201252f8e 100644 --- a/tools/ctl/ctl.c +++ b/tools/ctl/ctl.c @@ -20,6 +20,8 @@ #define BUFFER_SIZE_OFFSET 1 #define BUFFER_ABI_OFFSET 2 +#define BUFFER_TLV_HEADER_BYTES ((BUFFER_ABI_OFFSET) * sizeof(uint32_t)) + /* Definitions for multiple IPCs */ enum sof_ipc_type { SOF_IPC_TYPE_3, @@ -103,6 +105,7 @@ static void header_init(struct ctl_data *ctl_data) hdr->magic = ctl_data->magic; hdr->type = ctl_data->type; hdr->abi = SOF_ABI_VERSION; + ctl_data->buffer[BUFFER_TAG_OFFSET] = SOF_CTRL_CMD_BINARY; } /* Returns the number of bytes written to the control buffer */ @@ -117,7 +120,7 @@ static int read_setup(struct ctl_data *ctl_data) int separator; int n = 0; FILE *fh; - int data_start_int_index = BUFFER_ABI_OFFSET; + int data_start_int_index = 0; int data_int_index; /* open input file */ @@ -131,7 +134,7 @@ static int read_setup(struct ctl_data *ctl_data) if (ctl_data->no_abi) { header_init(ctl_data); abi_size = sizeof(struct sof_abi_hdr); - data_start_int_index += abi_size / sizeof(uint32_t); + data_start_int_index += abi_size / sizeof(uint32_t) + BUFFER_ABI_OFFSET; } if (ctl_data->binary) { @@ -163,6 +166,8 @@ static int read_setup(struct ctl_data *ctl_data) if (ctl_data->no_abi) { hdr->size = n; n += abi_size; + ctl_data->buffer[BUFFER_SIZE_OFFSET] = n; + n += BUFFER_TLV_HEADER_BYTES; } if (n > n_max) { @@ -206,16 +211,16 @@ static void hex_data_dump(struct ctl_data *ctl_data) int i; /* calculate the dumping units */ - n = ctl_data->buffer[BUFFER_SIZE_OFFSET] / sizeof(uint16_t); + n = (ctl_data->buffer[BUFFER_SIZE_OFFSET] + BUFFER_TLV_HEADER_BYTES) / sizeof(uint16_t); /* exclude the type and size header */ - int_offset = 2; + int_offset = 0; /* exclude abi header if '-r' specified */ if (ctl_data->no_abi) { - int_offset += sizeof(struct sof_abi_hdr) / + int_offset += (sizeof(struct sof_abi_hdr) + BUFFER_TLV_HEADER_BYTES) / sizeof(uint32_t); - n -= sizeof(struct sof_abi_hdr) / + n -= (sizeof(struct sof_abi_hdr) + BUFFER_TLV_HEADER_BYTES) / sizeof(uint16_t); } @@ -242,11 +247,11 @@ static void csv_data_dump(struct ctl_data *ctl_data, FILE *fh) int i; int s = 0; - config = &ctl_data->buffer[BUFFER_ABI_OFFSET]; - n = ctl_data->buffer[BUFFER_SIZE_OFFSET] / sizeof(uint32_t); + config = &ctl_data->buffer[0]; + n = (ctl_data->buffer[BUFFER_SIZE_OFFSET] + BUFFER_TLV_HEADER_BYTES) / sizeof(uint32_t); if (ctl_data->no_abi) - s = sizeof(struct sof_abi_hdr) / sizeof(uint32_t); + s = sizeof(struct sof_abi_hdr) / sizeof(uint32_t) + BUFFER_ABI_OFFSET; /* Print out in CSV txt formal */ for (i = s; i < n; i++) { @@ -298,10 +303,7 @@ static int buffer_alloc(struct ctl_data *ctl_data) return -EINVAL; } - ctl_data->buffer[BUFFER_TAG_OFFSET] = SOF_CTRL_CMD_BINARY; - ctl_data->buffer_size = buffer_size; - return 0; } @@ -429,7 +431,7 @@ static int ctl_free(struct ctl_data *ctl_data) return ret; } -static void ctl_dump(struct ctl_data *ctl_data) +static void ctl_dump(struct ctl_data *ctl_data, size_t dump_size) { FILE *fh; int offset = 0; @@ -445,13 +447,16 @@ static void ctl_dump(struct ctl_data *ctl_data) return; } - offset = BUFFER_ABI_OFFSET; - n = ctl_data->buffer[BUFFER_SIZE_OFFSET]; + if (dump_size) + n = dump_size; + else + n = ctl_data->buffer[BUFFER_SIZE_OFFSET] + BUFFER_TLV_HEADER_BYTES; if (ctl_data->no_abi) { - offset += sizeof(struct sof_abi_hdr) / - sizeof(int); + offset = sizeof(struct sof_abi_hdr) / sizeof(int) + + BUFFER_ABI_OFFSET; n -= sizeof(struct sof_abi_hdr); + n -= BUFFER_ABI_OFFSET * sizeof(uint32_t); } n = fwrite(&ctl_data->buffer[offset], 1, n, fh); @@ -476,7 +481,7 @@ static void ctl_dump(struct ctl_data *ctl_data) static int ctl_set_get(struct ctl_data *ctl_data) { int ret; - size_t n; + size_t read_size, ref_size; if (!ctl_data->buffer) { fprintf(stderr, "Error: No buffer for set/get!\n"); @@ -488,14 +493,22 @@ static int ctl_set_get(struct ctl_data *ctl_data) ctl_data->input_file); fprintf(stdout, "into device %s control %s.\n", ctl_data->dev, ctl_data->cname); - n = read_setup(ctl_data); - if (n < 1) { + read_size = read_setup(ctl_data); + if (read_size < 1) { fprintf(stderr, "Error: failed data read from %s.\n", ctl_data->input_file); return -EINVAL; } - ctl_data->buffer[BUFFER_SIZE_OFFSET] = n; + ref_size = ctl_data->buffer[BUFFER_SIZE_OFFSET] + BUFFER_TLV_HEADER_BYTES; + if (read_size != ref_size) { + fprintf(stderr, + "Error: Blob TLV header size %u (plus %lu) does not match with read bytes count %zu.\n", + ctl_data->buffer[BUFFER_SIZE_OFFSET], BUFFER_TLV_HEADER_BYTES, + read_size); + return -EINVAL; + } + ret = snd_ctl_elem_tlv_write(ctl_data->ctl, ctl_data->id, ctl_data->buffer); if (ret < 0) { @@ -518,6 +531,11 @@ static int ctl_set_get(struct ctl_data *ctl_data) fprintf(stderr, "Error: failed TLV read.\n"); return ret; } + /* Replace the numid value (scontrol->comp_id) with SOF_CTRL_CMD_BINARY + * to get similar blob as in set command. Helps to compare the received + * blob to sent blobs. The comp_id is not useful. + */ + ctl_data->buffer[BUFFER_TAG_OFFSET] = SOF_CTRL_CMD_BINARY; fprintf(stdout, "Success.\n"); } @@ -629,8 +647,8 @@ int main(int argc, char *argv[]) hdr = (struct sof_abi_hdr *) &ctl_data->buffer[BUFFER_ABI_OFFSET]; hdr->size = ctl_data->print_abi_size; - ctl_data->buffer[BUFFER_SIZE_OFFSET] = ctl_data->ctrl_size; - ctl_dump(ctl_data); + ctl_data->buffer[BUFFER_SIZE_OFFSET] = ctl_data->ctrl_size + hdr->size; + ctl_dump(ctl_data, sizeof(struct sof_abi_hdr) + BUFFER_TLV_HEADER_BYTES); buffer_free(ctl_data); goto out_fd_close; } @@ -668,7 +686,7 @@ int main(int argc, char *argv[]) } /* dump the tlv buffer to a file or stdout */ - ctl_dump(ctl_data); + ctl_dump(ctl_data, 0); data_free: ret = ctl_free(ctl_data); diff --git a/tools/tune/common/sof_alsactl_write.m b/tools/tune/common/sof_alsactl_write.m index 17a3db23f421..b8676f7a0987 100644 --- a/tools/tune/common/sof_alsactl_write.m +++ b/tools/tune/common/sof_alsactl_write.m @@ -1,5 +1,8 @@ function sof_alsactl_write(fn, blob8) +%% Check that blob header is sane +sof_check_blob_header(blob8); + %% Write blob sof_check_create_dir(fn); fh = fopen(fn, 'w'); diff --git a/tools/tune/common/sof_blob_write.m b/tools/tune/common/sof_blob_write.m index 6a71618fb960..df37669618e1 100644 --- a/tools/tune/common/sof_blob_write.m +++ b/tools/tune/common/sof_blob_write.m @@ -1,5 +1,7 @@ function sof_blob_write(fn, blob8) +%% Check that blob header is sane +sof_check_blob_header(blob8); %% Write blob check_create_dir(fn); diff --git a/tools/tune/common/sof_check_blob_header.m b/tools/tune/common/sof_check_blob_header.m new file mode 100644 index 000000000000..46a3aed45497 --- /dev/null +++ b/tools/tune/common/sof_check_blob_header.m @@ -0,0 +1,37 @@ +% sof_check_blob_header(blob) +% +% Check for correct header in bytes data. The function +% errors if header is not correct. +% +% Input +% blob - int8 type numbers data +% +% Output +% + +function sof_check_blob_header(blob8) + +% Correct size in header? +blob_bytes = length(blob8); +header_bytes = b2w(blob8(5:8)); +if blob_bytes ~= header_bytes + 8 + fprintf(1, "Error: blob header size %d does not math blob size %d\n", header_bytes, blob_bytes); + fprintf(1, "Is installed sof-ctl up-to-date?\n"); + error("Failed."); +end + +% Correct command? +SOF_CTRL_CMD_BINARY = 3; +value = b2w(blob8(1:4)); +if value ~= SOF_CTRL_CMD_BINARY + fprintf(1, "Error: blob control command is not set to SOF_CTRL_CMD_BINARY.\n"); + fprintf(1, "Is installed sof-ctl up-to-date?\n"); + error("Failed."); +end + +end + +function word =b2w(bytes) + tmp = int32(bytes); + word = tmp(1) + bitshift(tmp(2), 8) + bitshift(tmp(3), 16) + bitshift(tmp(4), 24); +end diff --git a/tools/tune/common/sof_tplg2_write.m b/tools/tune/common/sof_tplg2_write.m index 6322fa136cdd..b0b03b86db11 100644 --- a/tools/tune/common/sof_tplg2_write.m +++ b/tools/tune/common/sof_tplg2_write.m @@ -13,6 +13,12 @@ function sof_tplg2_write(fn, blob8, component, comment, howto) howto = []; end +%% Check that blob header is sane +sof_check_blob_header(blob8); + +%% Drop the 8 bytes TLV header from topology embedded blop +blob8 = blob8(9:end); + %% Check that blob length is multiple of 32 bits n_blob = length(blob8); n_test = ceil(n_blob/4)*4; diff --git a/tools/tune/common/sof_tplg_write.m b/tools/tune/common/sof_tplg_write.m index 358782bd30a7..4a766583b726 100644 --- a/tools/tune/common/sof_tplg_write.m +++ b/tools/tune/common/sof_tplg_write.m @@ -7,6 +7,12 @@ function sof_tplg_write(fn, blob8, name, comment, howto) howto = []; end +%% Check that blob header is sane +sof_check_blob_header(blob8); + +%% Drop the 8 bytes TLV header from topology embedded blop +blob8 = blob8(9:end); + %% Pad blob length to multiple of four bytes n_orig = length(blob8); n_new = ceil(n_orig/4)*4; diff --git a/tools/tune/common/sof_ucm_blob_write.m b/tools/tune/common/sof_ucm_blob_write.m index 2633c6571013..22eca5ce5ac5 100644 --- a/tools/tune/common/sof_ucm_blob_write.m +++ b/tools/tune/common/sof_ucm_blob_write.m @@ -13,14 +13,8 @@ function sof_ucm_blob_write(fn, blob8) % % Copyright (c) 2024, Intel Corporation. All rights reserved. -% Export for UCM cset-tlv with additional 8 bytes header -SOF_CTRL_CMD_BINARY = 3; -nh = 8; -nb = length(blob8); -ublob8 = zeros(nb + nh, 1, 'uint8'); -ublob8(1:4) = w32b(SOF_CTRL_CMD_BINARY); -ublob8(5:8) = w32b(nb); -ublob8(9:end) = blob8; +%% Check that blob header is sane +sof_check_blob_header(blob8); %% Write blob sof_check_create_dir(fn); @@ -30,28 +24,19 @@ function sof_ucm_blob_write(fn, blob8) error("Failed."); end -fwrite(fh, ublob8, 'uint8'); +fwrite(fh, blob8, 'uint8'); fclose(fh); %% Print as 8 bit hex -nb = length(ublob8); +nb = length(blob8); nl = ceil(nb/16); for i = 1:nl m = min(16, nb-(i-1)*16); for j = 1:m - fprintf(1, "%02x ", ublob8((i-1)*16 + j)); + fprintf(1, "%02x ", blob8((i-1)*16 + j)); end fprintf(1, "\n"); end fprintf(1, "\n"); end - -function bytes = w32b(word) -sh = [0 -8 -16 -24]; -bytes = uint8(zeros(1,4)); -bytes(1) = bitand(bitshift(word, sh(1)), 255); -bytes(2) = bitand(bitshift(word, sh(2)), 255); -bytes(3) = bitand(bitshift(word, sh(3)), 255); -bytes(4) = bitand(bitshift(word, sh(4)), 255); -end