// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Copyright (c) 2019 Amlogic, Inc. All rights reserved. */ #include #include #include #include #include #include #include #include #define TEE_ERROR_RPMB_AUTH_KEY_PROGRAMMED 0x7FFFFFFD #define CMD_RPMB_AUTH_KEY_INIT 0 #define CMD_RPMB_AUTH_KEY_STATE 1 #define TA_RPMB_UUID { 0x0ab5a718, 0xee63, 0x4115, \ { 0xa0, 0xad, 0xef, 0x6e, 0xe9, 0x8f, 0xcb, 0xc7 } } static int do_rpmb_init(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { int ret = 0; struct udevice *dev; struct tee_open_session_arg open_arg; struct tee_invoke_arg invoke_arg; const struct tee_optee_ta_uuid uuid = TA_RPMB_UUID; dev = tee_find_device(NULL, NULL, NULL, NULL); if (!dev) { printf("tee_find_device() failed"); return -ENODEV; } memset(&open_arg, 0, sizeof(open_arg)); tee_optee_ta_uuid_to_octets(open_arg.uuid, &uuid); ret = tee_open_session(dev, &open_arg, 0, NULL); if (ret) { printf("tee_open_session() failed, ret = 0x%x\n", ret); return ret; } if (open_arg.ret) { printf("tee_open_session() failed, ret = 0x%x, ret_origin=0x%x \n", open_arg.ret, open_arg.ret_origin); return open_arg.ret; } memset(&invoke_arg, 0, sizeof(invoke_arg)); invoke_arg.session = open_arg.session; invoke_arg.func = CMD_RPMB_AUTH_KEY_INIT; ret = tee_invoke_func(dev, &invoke_arg, 0, NULL); if (ret) { printf("tee_invoke_func() failed, ret = 0x%x\n", ret); goto exit; } if (invoke_arg.ret == TEE_SUCCESS) { printf("program RPMB auth key success\n"); } else if (invoke_arg.ret == TEE_ERROR_RPMB_AUTH_KEY_PROGRAMMED) { printf("RPMB auth key is programmed already\n"); } else { printf("tee_invoke_func() failed, ret = 0x%x, origin = %d\n", invoke_arg.ret, invoke_arg.ret_origin); ret = invoke_arg.ret; goto exit; } exit: tee_close_session(dev, open_arg.session); return ret; } U_BOOT_CMD(rpmb_init, CONFIG_SYS_MAXARGS, 0, do_rpmb_init, "RPMB sub-system", "RPMB auth key init\n"); static int do_rpmb_state(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { int ret = 0; struct udevice *dev; struct tee_open_session_arg open_arg; struct tee_invoke_arg invoke_arg; const struct tee_optee_ta_uuid uuid = TA_RPMB_UUID; struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT }; char *parg = NULL; struct mmc *mmc = NULL; if (store_get_type() == BOOT_EMMC) mmc = find_mmc_device(1); if (!mmc) return -ENODEV; dev = tee_find_device(NULL, NULL, NULL, NULL); if (!dev) { printf("tee_find_device() failed"); return -ENODEV; } memset(&open_arg, 0, sizeof(open_arg)); tee_optee_ta_uuid_to_octets(open_arg.uuid, &uuid); ret = tee_open_session(dev, &open_arg, 0, NULL); if (ret) { printf("tee_open_session() failed, ret = 0x%x\n", ret); return ret; } if (open_arg.ret) { printf("tee_open_session() failed, ret = 0x%x, ret_origin=0x%x\n", open_arg.ret, open_arg.ret_origin); return open_arg.ret; } memset(&invoke_arg, 0, sizeof(invoke_arg)); invoke_arg.session = open_arg.session; invoke_arg.func = CMD_RPMB_AUTH_KEY_STATE; ret = tee_invoke_func(dev, &invoke_arg, 1, ¶m); if (ret) { printf("tee_invoke_func() failed, ret = 0x%x\n", ret); goto exit; } if (invoke_arg.ret) { printf("tee_invoke_func() failed, ret = 0x%x, origin = %d\n", invoke_arg.ret, invoke_arg.ret_origin); ret = invoke_arg.ret; goto exit; } env_set("rpmb_state", param.u.value.a ? "1" : "0"); //need this? parg = env_get("bootconfig"); if (!parg) parg = env_get("bootargs"); else env_set("use_bootconfig", "true"); if (parg) { char *buff =malloc(strlen(parg) + 64); if (!buff) { ret = -ENOMEM; goto exit; } memset(buff + strlen(parg), 0, 64); strcpy(buff, parg); char *find = strstr(buff, "androidboot.rpmb_state"); if (!find) sprintf(buff,"%s androidboot.rpmb_state=0x%llx", parg, param.u.value.a); else find[23] = param.u.value.a ? '1':'0'; //printf("2 bootargs=%s\n",buff); env_set("rpmb_state", param.u.value.a?"1":"0"); //need this? char *use_bootconfig = env_get("use_bootconfig"); if (use_bootconfig && (strcmp(use_bootconfig, "true") == 0)) env_set("bootconfig", buff); else env_set("bootargs", buff); free(buff); buff = NULL; } exit: tee_close_session(dev, open_arg.session); return ret; } U_BOOT_CMD(rpmb_state, CONFIG_SYS_MAXARGS, 0, do_rpmb_state, "RPMB sub-system", "RPMB state\n"); /****************************************************/