extension_board.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2021
  4. * Köry Maincent, Bootlin, <kory.maincent@bootlin.com>
  5. */
  6. #include <common.h>
  7. #include <command.h>
  8. #include <malloc.h>
  9. #include <extension_board.h>
  10. #include <mapmem.h>
  11. #include <linux/libfdt.h>
  12. #include <fdt_support.h>
  13. static LIST_HEAD(extension_list);
  14. static int extension_apply(struct extension *extension)
  15. {
  16. char *overlay_cmd;
  17. ulong extrasize, overlay_addr;
  18. struct fdt_header *blob;
  19. if (!working_fdt) {
  20. printf("No FDT memory address configured. Please configure\n"
  21. "the FDT address via \"fdt addr <address>\" command.\n");
  22. return CMD_RET_FAILURE;
  23. }
  24. overlay_cmd = env_get("extension_overlay_cmd");
  25. if (!overlay_cmd) {
  26. printf("Environment extension_overlay_cmd is missing\n");
  27. return CMD_RET_FAILURE;
  28. }
  29. overlay_addr = env_get_hex("extension_overlay_addr", 0);
  30. if (!overlay_addr) {
  31. printf("Environment extension_overlay_addr is missing\n");
  32. return CMD_RET_FAILURE;
  33. }
  34. env_set("extension_overlay_name", extension->overlay);
  35. if (run_command(overlay_cmd, 0) != 0)
  36. return CMD_RET_FAILURE;
  37. extrasize = env_get_hex("filesize", 0);
  38. if (!extrasize)
  39. return CMD_RET_FAILURE;
  40. fdt_shrink_to_minimum(working_fdt, extrasize);
  41. blob = map_sysmem(overlay_addr, 0);
  42. if (!fdt_valid(&blob))
  43. return CMD_RET_FAILURE;
  44. /* apply method prints messages on error */
  45. if (fdt_overlay_apply_verbose(working_fdt, blob))
  46. return CMD_RET_FAILURE;
  47. return CMD_RET_SUCCESS;
  48. }
  49. static int do_extension_list(struct cmd_tbl *cmdtp, int flag,
  50. int argc, char *const argv[])
  51. {
  52. int i = 0;
  53. struct extension *extension;
  54. if (list_empty(&extension_list)) {
  55. printf("No extension registered - Please run \"extension scan\"\n");
  56. return CMD_RET_SUCCESS;
  57. }
  58. list_for_each_entry(extension, &extension_list, list) {
  59. printf("Extension %d: %s\n", i++, extension->name);
  60. printf("\tManufacturer: \t\t%s\n", extension->owner);
  61. printf("\tVersion: \t\t%s\n", extension->version);
  62. printf("\tDevicetree overlay: \t%s\n", extension->overlay);
  63. printf("\tOther information: \t%s\n", extension->other);
  64. }
  65. return CMD_RET_SUCCESS;
  66. }
  67. static int do_extension_scan(struct cmd_tbl *cmdtp, int flag,
  68. int argc, char *const argv[])
  69. {
  70. struct extension *extension, *next;
  71. int extension_num;
  72. list_for_each_entry_safe(extension, next, &extension_list, list) {
  73. list_del(&extension->list);
  74. free(extension);
  75. }
  76. extension_num = extension_board_scan(&extension_list);
  77. if (extension_num < 0)
  78. return CMD_RET_FAILURE;
  79. printf("Found %d extension board(s).\n", extension_num);
  80. return CMD_RET_SUCCESS;
  81. }
  82. static int do_extension_apply(struct cmd_tbl *cmdtp, int flag,
  83. int argc, char *const argv[])
  84. {
  85. struct extension *extension = NULL;
  86. struct list_head *entry;
  87. int i = 0, extension_id, ret;
  88. if (argc < 2)
  89. return CMD_RET_USAGE;
  90. if (strcmp(argv[1], "all") == 0) {
  91. list_for_each_entry(extension, &extension_list, list) {
  92. ret = extension_apply(extension);
  93. if (ret != CMD_RET_SUCCESS)
  94. break;
  95. }
  96. } else {
  97. extension_id = simple_strtol(argv[1], NULL, 10);
  98. list_for_each(entry, &extension_list) {
  99. if (i == extension_id) {
  100. extension = list_entry(entry, struct extension, list);
  101. break;
  102. }
  103. i++;
  104. }
  105. if (!extension) {
  106. printf("Wrong extension number\n");
  107. return CMD_RET_FAILURE;
  108. }
  109. ret = extension_apply(extension);
  110. }
  111. return ret;
  112. }
  113. static struct cmd_tbl cmd_extension[] = {
  114. U_BOOT_CMD_MKENT(scan, 1, 1, do_extension_scan, "", ""),
  115. U_BOOT_CMD_MKENT(list, 1, 0, do_extension_list, "", ""),
  116. U_BOOT_CMD_MKENT(apply, 2, 0, do_extension_apply, "", ""),
  117. };
  118. static int do_extensionops(struct cmd_tbl *cmdtp, int flag, int argc,
  119. char *const argv[])
  120. {
  121. struct cmd_tbl *cp;
  122. /* Drop the extension command */
  123. argc--;
  124. argv++;
  125. cp = find_cmd_tbl(argv[0], cmd_extension, ARRAY_SIZE(cmd_extension));
  126. if (cp)
  127. return cp->cmd(cmdtp, flag, argc, argv);
  128. return CMD_RET_USAGE;
  129. }
  130. U_BOOT_CMD(extension, 3, 1, do_extensionops,
  131. "Extension board management sub system",
  132. "scan - scan plugged extension(s) board(s)\n"
  133. "extension list - lists available extension(s) board(s)\n"
  134. "extension apply <extension number|all> - applies DT overlays corresponding to extension boards\n"
  135. );