adtimg.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2018 Linaro Ltd.
  4. * Sam Protsenko <semen.protsenko@linaro.org>
  5. * Eugeniu Rosca <rosca.eugeniu@gmail.com>
  6. */
  7. #include <env.h>
  8. #include <image-android-dt.h>
  9. #include <common.h>
  10. #define OPT_INDEX "--index"
  11. /*
  12. * Current/working DTB/DTBO Android image address.
  13. * Similar to 'working_fdt' variable in 'fdt' command.
  14. */
  15. static ulong working_img;
  16. static int do_adtimg_addr(cmd_tbl_t *cmdtp, int flag, int argc,
  17. char * const argv[])
  18. {
  19. char *endp;
  20. ulong hdr_addr;
  21. if (argc != 2)
  22. return CMD_RET_USAGE;
  23. hdr_addr = simple_strtoul(argv[1], &endp, 16);
  24. if (*endp != '\0') {
  25. printf("Error: Wrong image address '%s'\n", argv[1]);
  26. return CMD_RET_FAILURE;
  27. }
  28. /*
  29. * Allow users to set an address prior to copying the DTB/DTBO
  30. * image to that same address, i.e. skip header verification.
  31. */
  32. working_img = hdr_addr;
  33. return CMD_RET_SUCCESS;
  34. }
  35. static int adtimg_check_working_img(void)
  36. {
  37. if (!working_img) {
  38. printf("Error: Please, call 'adtimg addr <addr>'. Aborting!\n");
  39. return CMD_RET_FAILURE;
  40. }
  41. if (!android_dt_check_header(working_img)) {
  42. printf("Error: Invalid image header at 0x%lx\n", working_img);
  43. return CMD_RET_FAILURE;
  44. }
  45. return CMD_RET_SUCCESS;
  46. }
  47. static int do_adtimg_dump(cmd_tbl_t *cmdtp, int flag, int argc,
  48. char * const argv[])
  49. {
  50. if (argc != 1)
  51. return CMD_RET_USAGE;
  52. if (adtimg_check_working_img() != CMD_RET_SUCCESS)
  53. return CMD_RET_FAILURE;
  54. android_dt_print_contents(working_img);
  55. return CMD_RET_SUCCESS;
  56. }
  57. static int adtimg_getopt_u32(char * const opt, char * const name, u32 *optval)
  58. {
  59. char *endp, *str;
  60. u32 val;
  61. if (!opt || !name || !optval)
  62. return CMD_RET_FAILURE;
  63. str = strchr(opt, '=');
  64. if (!str) {
  65. printf("Error: Option '%s' not followed by '='\n", name);
  66. return CMD_RET_FAILURE;
  67. }
  68. if (*++str == '\0') {
  69. printf("Error: Option '%s=' not followed by value\n", name);
  70. return CMD_RET_FAILURE;
  71. }
  72. val = simple_strtoul(str, &endp, 0);
  73. if (*endp != '\0') {
  74. printf("Error: Wrong integer value '%s=%s'\n", name, str);
  75. return CMD_RET_FAILURE;
  76. }
  77. *optval = val;
  78. return CMD_RET_SUCCESS;
  79. }
  80. static int adtimg_getopt_index(int argc, char * const argv[], u32 *index,
  81. char **avar, char **svar)
  82. {
  83. int ret;
  84. if (!argv || !avar || !svar)
  85. return CMD_RET_FAILURE;
  86. if (argc > 3) {
  87. printf("Error: Unexpected argument '%s'\n", argv[3]);
  88. return CMD_RET_FAILURE;
  89. }
  90. ret = adtimg_getopt_u32(argv[0], OPT_INDEX, index);
  91. if (ret != CMD_RET_SUCCESS)
  92. return ret;
  93. if (argc > 1)
  94. *avar = argv[1];
  95. if (argc > 2)
  96. *svar = argv[2];
  97. return CMD_RET_SUCCESS;
  98. }
  99. static int adtimg_get_dt_by_index(int argc, char * const argv[])
  100. {
  101. ulong addr;
  102. u32 index, size;
  103. int ret;
  104. char *avar = NULL, *svar = NULL;
  105. ret = adtimg_getopt_index(argc, argv, &index, &avar, &svar);
  106. if (ret != CMD_RET_SUCCESS)
  107. return ret;
  108. if (!android_dt_get_fdt_by_index(working_img, index, &addr, &size))
  109. return CMD_RET_FAILURE;
  110. if (avar && svar) {
  111. ret = env_set_hex(avar, addr);
  112. if (ret) {
  113. printf("Error: Can't set '%s' to 0x%lx\n", avar, addr);
  114. return CMD_RET_FAILURE;
  115. }
  116. ret = env_set_hex(svar, size);
  117. if (ret) {
  118. printf("Error: Can't set '%s' to 0x%x\n", svar, size);
  119. return CMD_RET_FAILURE;
  120. }
  121. } else if (avar) {
  122. ret = env_set_hex(avar, addr);
  123. if (ret) {
  124. printf("Error: Can't set '%s' to 0x%lx\n", avar, addr);
  125. return CMD_RET_FAILURE;
  126. }
  127. printf("0x%x (%d)\n", size, size);
  128. } else {
  129. printf("0x%lx, 0x%x (%d)\n", addr, size, size);
  130. }
  131. return CMD_RET_SUCCESS;
  132. }
  133. static int adtimg_get_dt(int argc, char * const argv[])
  134. {
  135. if (argc < 2) {
  136. printf("Error: No options passed to '%s'\n", argv[0]);
  137. return CMD_RET_FAILURE;
  138. }
  139. /* Strip off leading 'dt' command argument */
  140. argc--;
  141. argv++;
  142. if (!strncmp(argv[0], OPT_INDEX, sizeof(OPT_INDEX) - 1))
  143. return adtimg_get_dt_by_index(argc, argv);
  144. printf("Error: Option '%s' not supported\n", argv[0]);
  145. return CMD_RET_FAILURE;
  146. }
  147. static int do_adtimg_get(cmd_tbl_t *cmdtp, int flag, int argc,
  148. char * const argv[])
  149. {
  150. if (argc < 2) {
  151. printf("Error: No arguments passed to '%s'\n", argv[0]);
  152. return CMD_RET_FAILURE;
  153. }
  154. if (adtimg_check_working_img() != CMD_RET_SUCCESS)
  155. return CMD_RET_FAILURE;
  156. /* Strip off leading 'get' command argument */
  157. argc--;
  158. argv++;
  159. if (!strcmp(argv[0], "dt"))
  160. return adtimg_get_dt(argc, argv);
  161. printf("Error: Wrong argument '%s'\n", argv[0]);
  162. return CMD_RET_FAILURE;
  163. }
  164. static cmd_tbl_t cmd_adtimg_sub[] = {
  165. U_BOOT_CMD_MKENT(addr, CONFIG_SYS_MAXARGS, 1, do_adtimg_addr, "", ""),
  166. U_BOOT_CMD_MKENT(dump, CONFIG_SYS_MAXARGS, 1, do_adtimg_dump, "", ""),
  167. U_BOOT_CMD_MKENT(get, CONFIG_SYS_MAXARGS, 1, do_adtimg_get, "", ""),
  168. };
  169. static int do_adtimg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  170. {
  171. cmd_tbl_t *cp;
  172. cp = find_cmd_tbl(argv[1], cmd_adtimg_sub, ARRAY_SIZE(cmd_adtimg_sub));
  173. /* Strip off leading 'adtimg' command argument */
  174. argc--;
  175. argv++;
  176. if (!cp || argc > cp->maxargs)
  177. return CMD_RET_USAGE;
  178. if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
  179. return CMD_RET_SUCCESS;
  180. return cp->cmd(cmdtp, flag, argc, argv);
  181. }
  182. U_BOOT_CMD(
  183. adtimg, CONFIG_SYS_MAXARGS, 0, do_adtimg,
  184. "manipulate dtb/dtbo Android image",
  185. "addr <addr> - Set image location to <addr>\n"
  186. "adtimg dump - Print out image contents\n"
  187. "adtimg get dt --index=<index> [avar [svar]] - Get DT address/size by index\n"
  188. "\n"
  189. "Legend:\n"
  190. " - <addr>: DTB/DTBO image address (hex) in RAM\n"
  191. " - <index>: index (hex/dec) of desired DT in the image\n"
  192. " - <avar>: variable name to contain DT address (hex)\n"
  193. " - <svar>: variable name to contain DT size (hex)"
  194. );