// SPDX-License-Identifier: GPL-2.0+ /* Copyright (C) 2023 AVM GmbH */ #define pr_fmt(fmt) "mrpc dtbo server: " fmt #include #include #include #include #include #include #include #include "avm_dtbo_mrpc.h" static struct mrpc_server *server; #define MAX_DT_OVERLAYS CONFIG_AVM_OF_OVERLAY_CMDLINE_MAX static const struct dt_overlay_mem *dtbo_array[MAX_DT_OVERLAYS]; static size_t num_dtbo; static void mprc_avm_dtbo_fill_array(void) { for (num_dtbo = 0; num_dtbo < MAX_DT_OVERLAYS; num_dtbo++) { dtbo_array[num_dtbo] = avm_of_overlay_get_dtbo_mem(num_dtbo); if (dtbo_array[num_dtbo] == NULL) break; } } static int mrpc_avm_dtbo_server_read(void *arg, ssize_t arglen, void *rep, ssize_t replen) { struct avm_dtbo_read_request *request = arg; struct avm_dtbo_read_reply *reply = rep; const struct dt_overlay_mem *dtbo; u32 offset, len, dtbo_index; offset = be32_to_cpu(request->offset); len = be32_to_cpu(request->len); dtbo_index = be32_to_cpu(request->dtbo_index); if (dtbo_index >= num_dtbo) { reply->data_len = 0; return 0; } dtbo = dtbo_array[dtbo_index]; if ((offset + len) > dtbo->size) len = dtbo->size - offset; memcpy(reply->data, dtbo->dtbo + offset, len); reply->data_len = cpu_to_be32(len); reply->dtbo_size = cpu_to_be32(dtbo->size); return 0; } static struct mrpc_procinfo avm_dtbo_server_procs[] = { /* Request enum, Handle function, Argument length, Reply length */ MRPC_PROCINFO_ENTRY(MRPC_AVM_DTBO_READ, mrpc_avm_dtbo_server_read, sizeof(struct avm_dtbo_read_request), sizeof(struct avm_dtbo_read_reply)), }; static int avm_dtbo_server_init(void) { mprc_avm_dtbo_fill_array(); server = mrpc_server_register( MRPC_RESERVED_ID_AVM_DTBO, "AVM dtbo server", avm_dtbo_server_procs, ARRAY_SIZE(avm_dtbo_server_procs)); if (!server) return -ENODEV; return 0; } static_notifier_module_init(mrpc_ready, avm_dtbo_server_init);