armffa.c 4.8 KB

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