fail.rs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. use serde_device_tree::Dtb;
  2. use crate::dt;
  3. #[cfg(not(feature = "payload"))]
  4. use crate::firmware::dynamic;
  5. #[cfg(not(feature = "payload"))]
  6. use crate::sbi::reset;
  7. #[cfg(not(feature = "payload"))]
  8. use riscv::register::mstatus;
  9. // TODO: Need a better way to handle device tree parsing errors
  10. /// Handles device tree format parsing errors by logging and resetting.
  11. #[cold]
  12. pub fn device_tree_format(_err: dt::ParseDeviceTreeError) -> Dtb {
  13. loop {
  14. core::hint::spin_loop()
  15. }
  16. }
  17. #[cold]
  18. pub fn device_tree_deserialize_root<'a>(
  19. _err: serde_device_tree::error::Error,
  20. ) -> serde_device_tree::buildin::Node<'a> {
  21. loop {
  22. core::hint::spin_loop()
  23. }
  24. }
  25. /// Handles invalid dynamic information data by logging details and resetting.
  26. #[cold]
  27. #[cfg(not(feature = "payload"))]
  28. pub fn invalid_dynamic_data(err: dynamic::DynamicError) -> (mstatus::MPP, usize) {
  29. error!("Invalid data in dynamic information:");
  30. if err.invalid_mpp {
  31. error!("* dynamic information contains invalid privilege mode");
  32. }
  33. if err.invalid_next_addr {
  34. error!("* dynamic information contains invalid next jump address");
  35. }
  36. let explain_next_mode = match err.bad_info.next_mode {
  37. 3 => "Machine",
  38. 1 => "Supervisor",
  39. 0 => "User",
  40. _ => "Invalid",
  41. };
  42. error!(
  43. "@ help: dynamic information contains magic value 0x{:x}, version {}, next jump address 0x{:x}, next privilege mode {} ({}), options {:x}, boot hart ID {}",
  44. err.bad_info.magic, err.bad_info.version, err.bad_info.next_addr, err.bad_info.next_mode, explain_next_mode, err.bad_info.options, err.bad_info.boot_hart
  45. );
  46. reset::fail()
  47. }
  48. /// Handles case where dynamic information is not available by logging details and resetting.
  49. #[cold]
  50. #[cfg(not(feature = "payload"))]
  51. pub fn no_dynamic_info_available(err: dynamic::DynamicReadError) -> dynamic::DynamicInfo {
  52. if let Some(bad_paddr) = err.bad_paddr {
  53. error!(
  54. "No dynamic information available at address 0x{:x}",
  55. bad_paddr
  56. );
  57. } else {
  58. error!("No valid dynamic information available:");
  59. if let Some(bad_magic) = err.bad_magic {
  60. error!(
  61. "* tried to identify dynamic information, but found invalid magic number 0x{:x}",
  62. bad_magic
  63. );
  64. }
  65. if let Some(bad_version) = err.bad_version {
  66. error!("* tries to identify version of dynamic information, but the version number {} is not supported", bad_version);
  67. }
  68. if err.bad_magic.is_none() {
  69. error!("@ help: magic number is valid")
  70. }
  71. if err.bad_version.is_none() {
  72. error!("@ help: dynamic information version is valid")
  73. }
  74. }
  75. reset::fail()
  76. }
  77. /// Fallback function that returns default dynamic info with boot_hart set to MAX.
  78. ///
  79. /// Used when dynamic info read fails but execution should continue.
  80. #[cold]
  81. #[cfg(not(feature = "payload"))]
  82. pub fn use_lottery(_err: dynamic::DynamicReadError) -> dynamic::DynamicInfo {
  83. dynamic::DynamicInfo {
  84. magic: 0,
  85. version: 0,
  86. next_addr: 0,
  87. next_mode: 0,
  88. options: 0,
  89. boot_hart: usize::MAX,
  90. }
  91. }