1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com> 4 * 5 * Authors: 6 * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> 7 */ 8#include <common.h> 9#include <arm_ffa.h> 10#include <command.h> 11#include <dm.h> 12#include <mapmem.h> 13#include <stdlib.h> 14#include <asm/io.h> 15 16/* Select the right physical address formatting according to the platform */ 17#ifdef CONFIG_PHYS_64BIT 18#define PhysAddrLength "ll" 19#else 20#define PhysAddrLength "" 21#endif 22#define PHYS_ADDR_LN "%" PhysAddrLength "x" 23 24/** 25 * ffa_get_dev() - Return the FF-A device 26 * @devp: pointer to the FF-A device 27 * 28 * Search for the FF-A device. 29 * 30 * Return: 31 * 0 on success. Otherwise, failure 32 */ 33static int ffa_get_dev(struct udevice **devp) 34{ 35 int ret; 36 37 ret = uclass_first_device_err(UCLASS_FFA, devp); 38 if (ret) { 39 log_err("Cannot find FF-A bus device\n"); 40 return ret; 41 } 42 43 return 0; 44} 45 46/** 47 * do_ffa_getpart() - implementation of the getpart subcommand 48 * @cmdtp: Command Table 49 * @flag: flags 50 * @argc: number of arguments 51 * @argv: arguments 52 * 53 * Query a secure partition information. The secure partition UUID is provided 54 * as an argument. The function uses the arm_ffa driver 55 * partition_info_get operation which implements FFA_PARTITION_INFO_GET 56 * ABI to retrieve the data. The input UUID string is expected to be in big 57 * endian format. 58 * 59 * Return: 60 * 61 * CMD_RET_SUCCESS: on success, otherwise failure 62 */ 63static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc, 64 char *const argv[]) 65{ 66 u32 count = 0; 67 int ret; 68 struct ffa_partition_desc *descs; 69 u32 i; 70 struct udevice *dev; 71 72 if (argc != 2) { 73 log_err("Missing argument\n"); 74 return CMD_RET_USAGE; 75 } 76 77 ret = ffa_get_dev(&dev); 78 if (ret) 79 return CMD_RET_FAILURE; 80 81 /* Ask the driver to fill the buffer with the SPs info */ 82 83 ret = ffa_partition_info_get(dev, argv[1], &count, &descs); 84 if (ret) { 85 log_err("Failure in querying partition(s) info (error code: %d)\n", ret); 86 return CMD_RET_FAILURE; 87 } 88 89 /* SPs found , show the partition information */ 90 for (i = 0; i < count ; i++) { 91 log_info("Partition: id = %x , exec_ctxt %x , properties %x\n", 92 descs[i].info.id, 93 descs[i].info.exec_ctxt, 94 descs[i].info.properties); 95 } 96 97 return CMD_RET_SUCCESS; 98} 99 100/** 101 * do_ffa_ping() - implementation of the ping subcommand 102 * @cmdtp: Command Table 103 * @flag: flags 104 * @argc: number of arguments 105 * @argv: arguments 106 * 107 * Send data to a secure partition. The secure partition UUID is provided 108 * as an argument. Use the arm_ffa driver sync_send_receive operation 109 * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive data. 110 * 111 * Return: 112 * 113 * CMD_RET_SUCCESS: on success, otherwise failure 114 */ 115static int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 116{ 117 struct ffa_send_direct_data msg = { 118 .data0 = 0xaaaaaaaa, 119 .data1 = 0xbbbbbbbb, 120 .data2 = 0xcccccccc, 121 .data3 = 0xdddddddd, 122 .data4 = 0xeeeeeeee, 123 }; 124 u16 part_id; 125 int ret; 126 struct udevice *dev; 127 128 if (argc != 2) { 129 log_err("Missing argument\n"); 130 return CMD_RET_USAGE; 131 } 132 133 part_id = strtoul(argv[1], NULL, 16); 134 if (!part_id) { 135 log_err("Partition ID can not be 0\n"); 136 return CMD_RET_USAGE; 137 } 138 139 ret = ffa_get_dev(&dev); 140 if (ret) 141 return CMD_RET_FAILURE; 142 143 ret = ffa_sync_send_receive(dev, part_id, &msg, 1); 144 if (!ret) { 145 u8 cnt; 146 147 log_info("SP response:\n[LSB]\n"); 148 for (cnt = 0; 149 cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); 150 cnt++) 151 log_info("%llx\n", ((u64 *)&msg)[cnt]); 152 return CMD_RET_SUCCESS; 153 } 154 155 log_err("Sending direct request error (%d)\n", ret); 156 return CMD_RET_FAILURE; 157} 158 159/** 160 *do_ffa_devlist() - implementation of the devlist subcommand 161 * @cmdtp: [in] Command Table 162 * @flag: flags 163 * @argc: number of arguments 164 * @argv: arguments 165 * 166 * Query the device belonging to the UCLASS_FFA 167 * class. 168 * 169 * Return: 170 * 171 * CMD_RET_SUCCESS: on success, otherwise failure 172 */ 173static int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 174{ 175 struct udevice *dev; 176 int ret; 177 178 ret = ffa_get_dev(&dev); 179 if (ret) 180 return CMD_RET_FAILURE; 181 182 log_info("device %s, addr " PHYS_ADDR_LN ", driver %s, ops " PHYS_ADDR_LN "\n", 183 dev->name, 184 map_to_sysmem(dev), 185 dev->driver->name, 186 map_to_sysmem(dev->driver->ops)); 187 188 return CMD_RET_SUCCESS; 189} 190 191U_BOOT_LONGHELP(armffa, 192 "getpart <partition UUID>\n" 193 " - lists the partition(s) info\n" 194 "ping <partition ID>\n" 195 " - sends a data pattern to the specified partition\n" 196 "devlist\n" 197 " - displays information about the FF-A device/driver\n"); 198 199U_BOOT_CMD_WITH_SUBCMDS(armffa, "Arm FF-A test command", armffa_help_text, 200 U_BOOT_SUBCMD_MKENT(getpart, 2, 1, do_ffa_getpart), 201 U_BOOT_SUBCMD_MKENT(ping, 2, 1, do_ffa_ping), 202 U_BOOT_SUBCMD_MKENT(devlist, 1, 1, do_ffa_devlist)); 203