/* * Copyright (C) 2012-2018 Samsung Electronics, Inc. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include #include #include #include #include #include #include #include "tz_common.h" #include "tz_deploy_tzar.h" #include "tz_iwsock.h" #include "tz_mem.h" #include "tzlog.h" #include "teec/iw_messages.h" #define MAX_CONNECTION_ATTEMPTS 20 #define CONNECTION_ATTEMPT_TIMEOUT 100 __asm__ ( ".section .init.data,\"aw\"\n" "tzdev_tzar_begin:\n" ".incbin \"" KBUILD_SRC "/drivers/misc/tzdev/startup.tzar\"\n" "tzdev_tzar_end:\n" ".previous\n" ); extern char tzdev_tzar_begin[], tzdev_tzar_end[]; enum iw_startup_loader_cmd_type { CMD_STARTUP_LOADER_INVALID_ID, CMD_STARTUP_LOADER_UPLOAD_CONTAINER, CMD_STARTUP_LOADER_REPLY, CMD_STARTUP_LOADER_REPLY_UPLOAD_CONTAINER, CMD_STARTUP_LOADER_MAX }; struct cmd_startup_loader_upload_container { struct cmd_request base; struct shared_buffer_description buf_desc; } IW_STRUCTURE; struct cmd_startup_loader_reply_upload_container { struct cmd_reply base; } IW_STRUCTURE; static __ref int tz_deploy_handler(void *arg) { int ret; size_t size; struct sock_desc *sd; struct cmd_startup_loader_upload_container command; struct cmd_startup_loader_reply_upload_container reply; void *tzar; unsigned int attempt; (void)arg; size = tzdev_tzar_end - tzdev_tzar_begin; tzdev_print(0, "[debug] tzar size = %zu\n", size); tzar = vmalloc(size); if (!tzar) { tzdev_print(0, "vmalloc fail\n"); return -ENOMEM; } memcpy(tzar, tzdev_tzar_begin, size); size = DIV_ROUND_UP(size, PAGE_SIZE) * PAGE_SIZE; ret = tzdev_mem_register(tzar, size, 0, NULL, NULL); if (ret < 0) { tzdev_print(0, "tzdev_mem_register fail, ret=%d\n", ret); goto out_tzar; } command.base.cmd = CMD_STARTUP_LOADER_UPLOAD_CONTAINER; command.buf_desc.id = ret; command.buf_desc.size = (unsigned int)size; sd = tz_iwsock_socket(1); if (IS_ERR(sd)) { ret = PTR_ERR(sd); tzdev_print(0, "tz_iwsock_socket fail, ret=%d\n", ret); goto out_mem; } for (attempt = 0; attempt < MAX_CONNECTION_ATTEMPTS; attempt++) { ret = tz_iwsock_connect(sd, STARTUP_LOADER_SOCK, 0); if (!ret) break; tzdev_print(0, "Failed to connect to startup loader socket, " "error = %d, retrying...\n", ret); msleep(CONNECTION_ATTEMPT_TIMEOUT); } if (ret < 0) { tzdev_print(0, "tz_iwsock_connect fail, ret=%d\n", ret); goto out_sock; } ret = tz_iwsock_write(sd, &command, sizeof(command), 0); if (ret != sizeof(command)) { tzdev_print(0, "tz_iwsock_write fail, ret=%d\n", ret); goto out_sock; } ret = tz_iwsock_read(sd, &reply, sizeof(reply), 0); if (ret < 0) { tzdev_print(0, "tz_iwsock_read fail, ret=%d\n", ret); goto out_sock; } if (reply.base.result) panic("tzdev: iwsock error. result=%d\n", reply.base.result); if (reply.base.base.cmd != CMD_STARTUP_LOADER_REPLY_UPLOAD_CONTAINER) panic("tzdev: iwsock wrong cmd. cmd=%u\n", reply.base.base.cmd); ret = 0; tzdev_print(0, "[debug] Startuploader complete\n"); out_sock: tz_iwsock_release(sd); out_mem: tzdev_mem_release(command.buf_desc.id); out_tzar: vfree(tzar); return ret; } int tzdev_deploy_tzar(void) { struct task_struct *t; t = kthread_run(tz_deploy_handler, NULL, "tzdev_deploy_tzar"); if (IS_ERR(t)) { printk("Can't start startup.tzar deployment thread\n"); return PTR_ERR(t); } return 0; }