bootdev.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * 'bootdev' command
  4. *
  5. * Copyright 2021 Google LLC
  6. * Written by Simon Glass <sjg@chromium.org>
  7. */
  8. #include <common.h>
  9. #include <bootdev.h>
  10. #include <bootflow.h>
  11. #include <bootstd.h>
  12. #include <command.h>
  13. #include <dm.h>
  14. #include <dm/device-internal.h>
  15. #include <dm/uclass-internal.h>
  16. static int bootdev_check_state(struct bootstd_priv **stdp)
  17. {
  18. struct bootstd_priv *std;
  19. int ret;
  20. ret = bootstd_get_priv(&std);
  21. if (ret)
  22. return ret;
  23. if (!std->cur_bootdev) {
  24. printf("Please use 'bootdev select' first\n");
  25. return -ENOENT;
  26. }
  27. *stdp = std;
  28. return 0;
  29. }
  30. static int do_bootdev_list(struct cmd_tbl *cmdtp, int flag, int argc,
  31. char *const argv[])
  32. {
  33. bool probe;
  34. probe = argc >= 2 && !strcmp(argv[1], "-p");
  35. bootdev_list(probe);
  36. return 0;
  37. }
  38. static int do_bootdev_select(struct cmd_tbl *cmdtp, int flag, int argc,
  39. char *const argv[])
  40. {
  41. struct bootstd_priv *std;
  42. struct udevice *dev;
  43. int ret;
  44. ret = bootstd_get_priv(&std);
  45. if (ret)
  46. return CMD_RET_FAILURE;
  47. if (argc < 2) {
  48. std->cur_bootdev = NULL;
  49. return 0;
  50. }
  51. if (bootdev_find_by_any(argv[1], &dev, NULL))
  52. return CMD_RET_FAILURE;
  53. std->cur_bootdev = dev;
  54. return 0;
  55. }
  56. static int do_bootdev_info(struct cmd_tbl *cmdtp, int flag, int argc,
  57. char *const argv[])
  58. {
  59. struct bootstd_priv *priv;
  60. struct bootflow *bflow;
  61. int ret, i, num_valid;
  62. struct udevice *dev;
  63. bool probe;
  64. probe = argc >= 2 && !strcmp(argv[1], "-p");
  65. ret = bootdev_check_state(&priv);
  66. if (ret)
  67. return CMD_RET_FAILURE;
  68. dev = priv->cur_bootdev;
  69. /* Count the number of bootflows, including how many are valid*/
  70. num_valid = 0;
  71. for (ret = bootdev_first_bootflow(dev, &bflow), i = 0;
  72. !ret;
  73. ret = bootdev_next_bootflow(&bflow), i++)
  74. num_valid += bflow->state == BOOTFLOWST_READY;
  75. /*
  76. * Prove the device, if requested, otherwise assume that there is no
  77. * error
  78. */
  79. ret = 0;
  80. if (probe)
  81. ret = device_probe(dev);
  82. printf("Name: %s\n", dev->name);
  83. printf("Sequence: %d\n", dev_seq(dev));
  84. printf("Status: %s\n", ret ? simple_itoa(-ret) : device_active(dev) ?
  85. "Probed" : "OK");
  86. printf("Uclass: %s\n", dev_get_uclass_name(dev_get_parent(dev)));
  87. printf("Bootflows: %d (%d valid)\n", i, num_valid);
  88. return 0;
  89. }
  90. static int do_bootdev_hunt(struct cmd_tbl *cmdtp, int flag, int argc,
  91. char *const argv[])
  92. {
  93. struct bootstd_priv *priv;
  94. const char *spec = NULL;
  95. bool list = false;
  96. int ret = 0;
  97. if (argc >= 2) {
  98. if (!strcmp(argv[1], "-l"))
  99. list = true;
  100. else
  101. spec = argv[1];
  102. }
  103. ret = bootstd_get_priv(&priv);
  104. if (ret)
  105. return ret;
  106. if (list) {
  107. bootdev_list_hunters(priv);
  108. } else {
  109. ret = bootdev_hunt(spec, true);
  110. if (ret) {
  111. printf("Failed (err=%dE)\n", ret);
  112. return CMD_RET_FAILURE;
  113. }
  114. }
  115. return 0;
  116. }
  117. #ifdef CONFIG_SYS_LONGHELP
  118. static char bootdev_help_text[] =
  119. "list [-p] - list all available bootdevs (-p to probe)\n"
  120. "bootdev hunt [-l|<spec>] - use hunt drivers to find bootdevs\n"
  121. "bootdev select <bd> - select a bootdev by name | label | seq\n"
  122. "bootdev info [-p] - show information about a bootdev (-p to probe)";
  123. #endif
  124. U_BOOT_CMD_WITH_SUBCMDS(bootdev, "Boot devices", bootdev_help_text,
  125. U_BOOT_SUBCMD_MKENT(list, 2, 1, do_bootdev_list),
  126. U_BOOT_SUBCMD_MKENT(hunt, 2, 1, do_bootdev_hunt),
  127. U_BOOT_SUBCMD_MKENT(select, 2, 1, do_bootdev_select),
  128. U_BOOT_SUBCMD_MKENT(info, 2, 1, do_bootdev_info));