prototyper.rs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. use std::{
  2. env, fs,
  3. process::{Command, ExitStatus},
  4. };
  5. use clap::Args;
  6. use crate::utils::CmdOptional;
  7. use crate::utils::cargo;
  8. #[derive(Debug, Args, Clone)]
  9. pub struct PrototyperArg {
  10. #[clap(long, short = 'f')]
  11. pub features: Vec<String>,
  12. #[clap(long, env = "PROTOTYPER_FDT_PATH")]
  13. pub fdt: Option<String>,
  14. #[clap(long, env = "PROTOTYPER_PAYLOAD_PATH")]
  15. pub payload: Option<String>,
  16. #[clap(long)]
  17. pub jump: bool,
  18. #[clap(long, default_value = "INFO")]
  19. pub log_level: String,
  20. }
  21. #[must_use]
  22. #[rustfmt::skip] // "export_env!("PROTOTYPER_FDT_PATH" ?= fdt.unwrap());" is a macro, rustfmt will not format it correctly
  23. pub fn run(arg: &PrototyperArg) -> Option<ExitStatus> {
  24. let arch = "riscv64imac-unknown-none-elf";
  25. let fdt = arg.fdt.clone();
  26. let payload = arg.payload.clone();
  27. let jump = arg.jump;
  28. let current_dir = env::current_dir();
  29. let target_dir = current_dir
  30. .as_ref()
  31. .unwrap()
  32. .join("target")
  33. .join(arch)
  34. .join("release");
  35. info!("Building Protoyper");
  36. cargo::Cargo::new("build")
  37. .package("rustsbi-prototyper")
  38. .target(arch)
  39. .unstable("build-std", ["core","alloc"])
  40. .env("RUSTFLAGS", "-C relocation-model=pie -C link-arg=-pie")
  41. .features(&arg.features)
  42. .optional(arg.fdt.is_some(), |cargo| {
  43. cargo.env("PROTOTYPER_FDT_PATH", fdt.as_ref().unwrap());
  44. cargo.features(["fdt".to_string()])
  45. })
  46. .optional(payload.is_some(), |cargo| {
  47. cargo.env("PROTOTYPER_PAYLOAD_PATH", payload.as_ref().unwrap());
  48. cargo.features(["payload".to_string()])
  49. })
  50. .optional(jump, |cargo| {
  51. cargo.features(["jump".to_string()])
  52. })
  53. .env("RUST_LOG", &arg.log_level)
  54. .release()
  55. .status()
  56. .ok()?;
  57. info!("Copy to binary");
  58. let exit_status = Command::new("rust-objcopy")
  59. .args(["-O", "binary"])
  60. .arg("--binary-architecture=riscv64")
  61. .arg(target_dir.join("rustsbi-prototyper"))
  62. .arg(target_dir.join("rustsbi-prototyper.bin"))
  63. .status()
  64. .ok()?;
  65. if !exit_status.success() {
  66. error!("Failed to exec rust-objcopy, please check if cargo-binutils has been installed?");
  67. return Some(exit_status);
  68. }
  69. if arg.payload.is_some() {
  70. info!("Copy for payload mode");
  71. fs::copy(
  72. target_dir.join("rustsbi-prototyper"),
  73. target_dir.join("rustsbi-prototyper-payload.elf"),
  74. )
  75. .ok()?;
  76. fs::copy(
  77. target_dir.join("rustsbi-prototyper.bin"),
  78. target_dir.join("rustsbi-prototyper-payload.bin"),
  79. )
  80. .ok()?;
  81. } else if arg.jump {
  82. info!("Copy for jump mode");
  83. fs::copy(
  84. target_dir.join("rustsbi-prototyper"),
  85. target_dir.join("rustsbi-prototyper-jump.elf"),
  86. )
  87. .ok()?;
  88. fs::copy(
  89. target_dir.join("rustsbi-prototyper.bin"),
  90. target_dir.join("rustsbi-prototyper-jump.bin"),
  91. )
  92. .ok()?;
  93. } else {
  94. info!("Copy for dynamic mode");
  95. fs::copy(
  96. target_dir.join("rustsbi-prototyper"),
  97. target_dir.join("rustsbi-prototyper-dynamic.elf"),
  98. )
  99. .ok()?;
  100. fs::copy(
  101. target_dir.join("rustsbi-prototyper.bin"),
  102. target_dir.join("rustsbi-prototyper-dynamic.bin"),
  103. )
  104. .ok()?;
  105. }
  106. Some(exit_status)
  107. }