reboot-mode.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-02-25 GuEe-GUI the first version
  9. */
  10. #include "reboot-mode.h"
  11. #define MODE_SUFFIXE "mode-"
  12. struct mode_info
  13. {
  14. rt_slist_t list;
  15. const char *mode;
  16. rt_uint32_t magic;
  17. };
  18. static rt_err_t reboot_mode_work(struct rt_device *dev, char *cmd)
  19. {
  20. struct mode_info *info;
  21. struct reboot_mode *reboot = (void *)dev;
  22. cmd = cmd ? : "normal";
  23. rt_slist_for_each_entry(info, &reboot->mode_nodes, list)
  24. {
  25. if (!rt_strcmp(info->mode, cmd))
  26. {
  27. reboot->write(reboot, info->magic);
  28. break;
  29. }
  30. }
  31. return RT_EOK;
  32. }
  33. rt_err_t reboot_mode_register(struct reboot_mode *reboot)
  34. {
  35. rt_err_t err;
  36. struct mode_info *info;
  37. struct rt_ofw_prop *prop;
  38. struct rt_ofw_node *np = reboot->dev->ofw_node;
  39. const int mode_suffixe_len = sizeof(MODE_SUFFIXE) - 1;
  40. if (!reboot || !reboot->dev)
  41. {
  42. return -RT_EINVAL;
  43. }
  44. rt_slist_init(&reboot->mode_nodes);
  45. rt_ofw_foreach_prop(np, prop)
  46. {
  47. if (rt_strncmp(prop->name, MODE_SUFFIXE, mode_suffixe_len))
  48. {
  49. continue;
  50. }
  51. info = rt_malloc(sizeof(*info));
  52. if (!info)
  53. {
  54. err = -RT_ENOMEM;
  55. goto _end;
  56. }
  57. info->mode = prop->name + mode_suffixe_len;
  58. info->magic = fdt32_to_cpu(*(const fdt32_t *)prop->value);
  59. rt_slist_init(&info->list);
  60. rt_slist_insert(&reboot->mode_nodes, &info->list);
  61. }
  62. err = rt_dm_reboot_mode_register((void *)reboot, &reboot_mode_work);
  63. _end:
  64. if (err)
  65. {
  66. struct mode_info *prev_info = RT_NULL;
  67. rt_slist_for_each_entry(info, &reboot->mode_nodes, list)
  68. {
  69. if (prev_info)
  70. {
  71. rt_free(prev_info);
  72. }
  73. prev_info = info;
  74. }
  75. if (prev_info)
  76. {
  77. rt_free(prev_info);
  78. }
  79. }
  80. return err;
  81. }