jzef

Untitled

Mar 31st, 2026
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 199.60 KB | None | 0 0
  1. // Parser
  2. #[macro_use]
  3. extern crate nom;
  4. pub mod framework_parser;
  5. pub mod uefi_parser;
  6.  
  7. // Main
  8. use std::collections::HashMap;
  9. use std::env;
  10. use std::ffi::OsStr;
  11. use std::ffi::OsString;
  12. use std::fs::File;
  13. use std::fs::OpenOptions;
  14. use std::io::prelude::*;
  15. use std::io::Write;
  16. use std::path::Path;
  17. use std::str;
  18.  
  19. // SHA256
  20. extern crate sha256;
  21. use sha256::digest;
  22.  
  23. struct StringPackage {
  24. offset: usize,
  25. length: usize,
  26. language: String,
  27. string_id_map: HashMap<u16, String>,
  28. }
  29.  
  30. struct FormPackage {
  31. offset: usize,
  32. length: usize,
  33. used_strings: usize,
  34. min_string_id: u16,
  35. max_string_id: u16,
  36. }
  37.  
  38. const VERSION: Option<&'static str> = option_env!("CARGO_PKG_VERSION");
  39.  
  40. //
  41. // UEFI HII parsing
  42. //
  43. fn uefi_find_string_and_form_packages(data: &[u8]) -> (Vec<StringPackage>, Vec<FormPackage>) {
  44. let mut strings = Vec::new(); // String-to-id maps for all found string packages
  45.  
  46. // Search for all string packages in the input file
  47. let mut i = 0;
  48. while i < data.len() {
  49. if let Ok((_, candidate)) = uefi_parser::hii_string_package_candidate(&data[i..]) {
  50. if let Ok((_, package)) = uefi_parser::hii_package(candidate) {
  51. if let Ok((_, string_package)) = uefi_parser::hii_string_package(package.Data.unwrap())
  52. {
  53. let mut string_id_map = HashMap::new(); // Map of StringIds to strings
  54.  
  55. // Parse SIBT blocks
  56. if let Ok((_, sibt_blocks)) = uefi_parser::hii_sibt_blocks(string_package.Data)
  57. {
  58. string_id_map.insert(0_u16, String::new());
  59. let mut current_string_index = 1;
  60. for block in &sibt_blocks {
  61. match block.Type {
  62. // 0x00: End
  63. uefi_parser::HiiSibtType::End => {}
  64. // 0x10: StringScsu
  65. uefi_parser::HiiSibtType::StringScsu => {
  66. if let Ok((_, string)) =
  67. uefi_parser::sibt_string_scsu(block.Data.unwrap())
  68. {
  69. string_id_map.insert(current_string_index, string);
  70. current_string_index += 1;
  71. }
  72. }
  73. // 0x11: StringScsuFont
  74. uefi_parser::HiiSibtType::StringScsuFont => {
  75. if let Ok((_, string)) =
  76. uefi_parser::sibt_string_scsu_font(block.Data.unwrap())
  77. {
  78. string_id_map.insert(current_string_index, string);
  79. current_string_index += 1;
  80. }
  81. }
  82. // 0x12: StringsScsu
  83. uefi_parser::HiiSibtType::StringsScsu => {
  84. if let Ok((_, strings)) =
  85. uefi_parser::sibt_strings_scsu(block.Data.unwrap())
  86. {
  87. for string in strings {
  88. string_id_map.insert(current_string_index, string);
  89. current_string_index += 1;
  90. }
  91. }
  92. }
  93. // 0x13: StringsScsuFont
  94. uefi_parser::HiiSibtType::StringsScsuFont => {
  95. if let Ok((_, strings)) =
  96. uefi_parser::sibt_strings_scsu_font(block.Data.unwrap())
  97. {
  98. for string in strings {
  99. string_id_map.insert(current_string_index, string);
  100. current_string_index += 1;
  101. }
  102. }
  103. }
  104. // 0x14: StringUcs2
  105. uefi_parser::HiiSibtType::StringUcs2 => {
  106. if let Ok((_, string)) =
  107. uefi_parser::sibt_string_ucs2(block.Data.unwrap())
  108. {
  109. string_id_map.insert(current_string_index, string);
  110. current_string_index += 1;
  111. }
  112. }
  113. // 0x15: StringUcs2Font
  114. uefi_parser::HiiSibtType::StringUcs2Font => {
  115. if let Ok((_, string)) =
  116. uefi_parser::sibt_string_ucs2_font(block.Data.unwrap())
  117. {
  118. string_id_map.insert(current_string_index, string);
  119. current_string_index += 1;
  120. }
  121. }
  122. // 0x16: StringsUcs2
  123. uefi_parser::HiiSibtType::StringsUcs2 => {
  124. if let Ok((_, strings)) =
  125. uefi_parser::sibt_strings_ucs2(block.Data.unwrap())
  126. {
  127. for string in strings {
  128. string_id_map.insert(current_string_index, string);
  129. current_string_index += 1;
  130. }
  131. }
  132. }
  133. // 0x17: StringsUcs2Font
  134. uefi_parser::HiiSibtType::StringsUcs2Font => {
  135. if let Ok((_, strings)) =
  136. uefi_parser::sibt_strings_ucs2_font(block.Data.unwrap())
  137. {
  138. for string in strings {
  139. string_id_map.insert(current_string_index, string);
  140. current_string_index += 1;
  141. }
  142. }
  143. }
  144. // 0x20: Duplicate
  145. uefi_parser::HiiSibtType::Duplicate => {
  146. current_string_index += 1;
  147. }
  148. // 0x21: Skip2
  149. uefi_parser::HiiSibtType::Skip2 => {
  150. // Manual parsing of Data as u16
  151. let count = block.Data.unwrap();
  152. current_string_index +=
  153. count[0] as u16 + 0x100 * count[1] as u16;
  154. }
  155. // 0x22: Skip1
  156. uefi_parser::HiiSibtType::Skip1 => {
  157. // Manual parsing of Data as u8
  158. let count = block.Data.unwrap();
  159. current_string_index += count[0] as u16;
  160. }
  161. // Blocks below don't have any strings nor can they influence current_string_index
  162. // No need to parse them here
  163. // 0x30: Ext1
  164. uefi_parser::HiiSibtType::Ext1 => {}
  165. // 0x31: Ext2
  166. uefi_parser::HiiSibtType::Ext2 => {}
  167. // 0x32: Ext4
  168. uefi_parser::HiiSibtType::Ext4 => {}
  169. // Unknown SIBT block is impossible, because parsing will fail on it due to it's unknown length
  170. uefi_parser::HiiSibtType::Unknown(_) => {}
  171. }
  172. }
  173.  
  174. // Add string
  175. let string = (i, candidate.len(), string_package.Language, string_id_map);
  176. strings.push(string);
  177.  
  178. i += candidate.len();
  179. } else {
  180. i += 1;
  181. }
  182. } else {
  183. i += 1;
  184. }
  185. } else {
  186. i += 1;
  187. }
  188. } else {
  189. i += 1;
  190. }
  191. }
  192.  
  193. //
  194. // Search for all form packages in the input file
  195. //
  196. let mut forms = Vec::new();
  197. i = 0;
  198. while i < data.len() {
  199. if let Ok((_, candidate)) = uefi_parser::hii_form_package_candidate(&data[i..]) {
  200. if let Ok((_, package)) = uefi_parser::hii_package(candidate) {
  201. // Parse form package and obtain StringIds
  202. let mut string_ids: Vec<u16> = Vec::new();
  203. if let Ok((_, operations)) = uefi_parser::ifr_operations(package.Data.unwrap()) {
  204. //let mut current_operation: usize = 0;
  205. for operation in &operations {
  206. //current_operation += 1;
  207. //println!("Operation #{}, OpCode: {:?}, Length 0x{:X}, ScopeStart: {}", current_operation, operation.OpCode, operation.Length, operation.ScopeStart);
  208. match operation.OpCode {
  209. // 0x01: Form
  210. uefi_parser::IfrOpcode::Form => {
  211. if let Ok((_, form)) =
  212. uefi_parser::ifr_form(operation.Data.unwrap())
  213. {
  214. string_ids.push(form.TitleStringId);
  215. }
  216. }
  217. // 0x02: Subtitle
  218. uefi_parser::IfrOpcode::Subtitle => {
  219. if let Ok((_, sub)) =
  220. uefi_parser::ifr_subtitle(operation.Data.unwrap())
  221. {
  222. string_ids.push(sub.PromptStringId);
  223. string_ids.push(sub.HelpStringId);
  224. }
  225. }
  226. // 0x03: Text
  227. uefi_parser::IfrOpcode::Text => {
  228. if let Ok((_, txt)) = uefi_parser::ifr_text(operation.Data.unwrap())
  229. {
  230. string_ids.push(txt.PromptStringId);
  231. string_ids.push(txt.HelpStringId);
  232. string_ids.push(txt.TextId);
  233. }
  234. }
  235. // 0x04: Image
  236. uefi_parser::IfrOpcode::Image => {}
  237. // 0x05: OneOf
  238. uefi_parser::IfrOpcode::OneOf => {
  239. if let Ok((_, onf)) =
  240. uefi_parser::ifr_one_of(operation.Data.unwrap())
  241. {
  242. string_ids.push(onf.PromptStringId);
  243. string_ids.push(onf.HelpStringId);
  244. }
  245. }
  246. // 0x06: CheckBox
  247. uefi_parser::IfrOpcode::CheckBox => {
  248. if let Ok((_, cb)) =
  249. uefi_parser::ifr_check_box(operation.Data.unwrap())
  250. {
  251. string_ids.push(cb.PromptStringId);
  252. string_ids.push(cb.HelpStringId);
  253. }
  254. }
  255. // 0x07: Numeric
  256. uefi_parser::IfrOpcode::Numeric => {
  257. if let Ok((_, num)) =
  258. uefi_parser::ifr_numeric(operation.Data.unwrap())
  259. {
  260. string_ids.push(num.PromptStringId);
  261. string_ids.push(num.HelpStringId);
  262. }
  263. }
  264. // 0x08: Password
  265. uefi_parser::IfrOpcode::Password => {
  266. if let Ok((_, pw)) =
  267. uefi_parser::ifr_password(operation.Data.unwrap())
  268. {
  269. string_ids.push(pw.PromptStringId);
  270. string_ids.push(pw.HelpStringId);
  271. }
  272. }
  273. // 0x09: OneOfOption
  274. uefi_parser::IfrOpcode::OneOfOption => {
  275. if let Ok((_, opt)) =
  276. uefi_parser::ifr_one_of_option(operation.Data.unwrap())
  277. {
  278. string_ids.push(opt.OptionStringId);
  279. match opt.Value {
  280. uefi_parser::IfrTypeValue::String(x) => {
  281. string_ids.push(x);
  282. }
  283. uefi_parser::IfrTypeValue::Action(x) => {
  284. string_ids.push(x);
  285. }
  286. _ => {}
  287. }
  288. }
  289. }
  290. // 0x0A: SuppressIf
  291. uefi_parser::IfrOpcode::SuppressIf => {}
  292. // 0x0B: Locked
  293. uefi_parser::IfrOpcode::Locked => {}
  294. // 0x0C: Action
  295. uefi_parser::IfrOpcode::Action => {
  296. if let Ok((_, act)) =
  297. uefi_parser::ifr_action(operation.Data.unwrap())
  298. {
  299. string_ids.push(act.PromptStringId);
  300. string_ids.push(act.HelpStringId);
  301. if let Some(x) = act.ConfigStringId {
  302. string_ids.push(x);
  303. }
  304. }
  305. }
  306. // 0x0D: ResetButton
  307. uefi_parser::IfrOpcode::ResetButton => {
  308. if let Ok((_, rst)) =
  309. uefi_parser::ifr_reset_button(operation.Data.unwrap())
  310. {
  311. string_ids.push(rst.PromptStringId);
  312. string_ids.push(rst.HelpStringId);
  313. }
  314. }
  315. // 0x0E: FormSet
  316. uefi_parser::IfrOpcode::FormSet => {
  317. if let Ok((_, form_set)) =
  318. uefi_parser::ifr_form_set(operation.Data.unwrap())
  319. {
  320. string_ids.push(form_set.TitleStringId);
  321. string_ids.push(form_set.HelpStringId);
  322. }
  323. }
  324. // 0x0F: Ref
  325. uefi_parser::IfrOpcode::Ref => {
  326. if let Ok((_, rf)) = uefi_parser::ifr_ref(operation.Data.unwrap()) {
  327. string_ids.push(rf.PromptStringId);
  328. string_ids.push(rf.HelpStringId);
  329. }
  330. }
  331. // 0x10: NoSubmitIf
  332. uefi_parser::IfrOpcode::NoSubmitIf => {
  333. if let Ok((_, ns)) =
  334. uefi_parser::ifr_no_submit_if(operation.Data.unwrap())
  335. {
  336. string_ids.push(ns.ErrorStringId);
  337. }
  338. }
  339. // 0x11: InconsistentIf
  340. uefi_parser::IfrOpcode::InconsistentIf => {
  341. if let Ok((_, inc)) =
  342. uefi_parser::ifr_inconsistent_if(operation.Data.unwrap())
  343. {
  344. string_ids.push(inc.ErrorStringId);
  345. }
  346. }
  347. // 0x12: EqIdVal
  348. uefi_parser::IfrOpcode::EqIdVal => {}
  349. // 0x13: EqIdId
  350. uefi_parser::IfrOpcode::EqIdId => {}
  351. // 0x14: EqIdValList
  352. uefi_parser::IfrOpcode::EqIdValList => {}
  353. // 0x15: And
  354. uefi_parser::IfrOpcode::And => {}
  355. // 0x16: Or
  356. uefi_parser::IfrOpcode::Or => {}
  357. // 0x17: Not
  358. uefi_parser::IfrOpcode::Not => {}
  359. // 0x18: Rule
  360. uefi_parser::IfrOpcode::Rule => {}
  361. // 0x19: GrayOutIf
  362. uefi_parser::IfrOpcode::GrayOutIf => {}
  363. // 0x1A: Date
  364. uefi_parser::IfrOpcode::Date => {
  365. if let Ok((_, dt)) = uefi_parser::ifr_date(operation.Data.unwrap())
  366. {
  367. string_ids.push(dt.PromptStringId);
  368. string_ids.push(dt.HelpStringId);
  369. }
  370. }
  371. // 0x1B: Time
  372. uefi_parser::IfrOpcode::Time => {
  373. if let Ok((_, time)) =
  374. uefi_parser::ifr_time(operation.Data.unwrap())
  375. {
  376. string_ids.push(time.PromptStringId);
  377. string_ids.push(time.HelpStringId);
  378. }
  379. }
  380. // 0x1C: String
  381. uefi_parser::IfrOpcode::String => {
  382. if let Ok((_, st)) =
  383. uefi_parser::ifr_string(operation.Data.unwrap())
  384. {
  385. string_ids.push(st.PromptStringId);
  386. string_ids.push(st.HelpStringId);
  387. }
  388. }
  389. // 0x1D: Refresh
  390. uefi_parser::IfrOpcode::Refresh => {}
  391. // 0x1E: DisableIf
  392. uefi_parser::IfrOpcode::DisableIf => {}
  393. // 0x1F: Animation
  394. uefi_parser::IfrOpcode::Animation => {}
  395. // 0x20: ToLower
  396. uefi_parser::IfrOpcode::ToLower => {}
  397. // 0x21: ToUpper
  398. uefi_parser::IfrOpcode::ToUpper => {}
  399. // 0x22: Map
  400. uefi_parser::IfrOpcode::Map => {}
  401. // 0x23: OrderedList
  402. uefi_parser::IfrOpcode::OrderedList => {
  403. if let Ok((_, ol)) =
  404. uefi_parser::ifr_ordered_list(operation.Data.unwrap())
  405. {
  406. string_ids.push(ol.PromptStringId);
  407. string_ids.push(ol.HelpStringId);
  408. }
  409. }
  410. // 0x24: VarStore
  411. uefi_parser::IfrOpcode::VarStore => {}
  412. // 0x25: VarStoreNameValue
  413. uefi_parser::IfrOpcode::VarStoreNameValue => {}
  414. // 0x26: VarStoreEfi258
  415. uefi_parser::IfrOpcode::VarStoreEfi => {}
  416. // 0x27: VarStoreDevice
  417. uefi_parser::IfrOpcode::VarStoreDevice => {
  418. if let Ok((_, var_store)) =
  419. uefi_parser::ifr_var_store_device(operation.Data.unwrap())
  420. {
  421. string_ids.push(var_store.DevicePathStringId);
  422. }
  423. }
  424. // 0x28: Version
  425. uefi_parser::IfrOpcode::Version => {}
  426. // 0x29: End
  427. uefi_parser::IfrOpcode::End => {}
  428. // 0x2A: Match
  429. uefi_parser::IfrOpcode::Match => {}
  430. // 0x2B: Get
  431. uefi_parser::IfrOpcode::Get => {}
  432. // 0x2C: Set
  433. uefi_parser::IfrOpcode::Set => {}
  434. // 0x2D: Read
  435. uefi_parser::IfrOpcode::Read => {}
  436. // 0x2E: Write
  437. uefi_parser::IfrOpcode::Write => {}
  438. // 0x2F: Equal
  439. uefi_parser::IfrOpcode::Equal => {}
  440. // 0x30: NotEqual
  441. uefi_parser::IfrOpcode::NotEqual => {}
  442. // 0x31: GreaterThan
  443. uefi_parser::IfrOpcode::GreaterThan => {}
  444. // 0x32: GreaterEqual
  445. uefi_parser::IfrOpcode::GreaterEqual => {}
  446. // 0x33: LessThan
  447. uefi_parser::IfrOpcode::LessThan => {}
  448. // 0x34: LessEqual
  449. uefi_parser::IfrOpcode::LessEqual => {}
  450. // 0x35: BitwiseAnd
  451. uefi_parser::IfrOpcode::BitwiseAnd => {}
  452. // 0x36: BitwiseOr
  453. uefi_parser::IfrOpcode::BitwiseOr => {}
  454. // 0x37: BitwiseNot
  455. uefi_parser::IfrOpcode::BitwiseNot => {}
  456. // 0x38: ShiftLeft
  457. uefi_parser::IfrOpcode::ShiftLeft => {}
  458. // 0x39: ShiftRight
  459. uefi_parser::IfrOpcode::ShiftRight => {}
  460. // 0x3A: Add
  461. uefi_parser::IfrOpcode::Add => {}
  462. // 0x3B: Substract
  463. uefi_parser::IfrOpcode::Substract => {}
  464. // 0x3C: Multiply
  465. uefi_parser::IfrOpcode::Multiply => {}
  466. // 0x3D: Divide
  467. uefi_parser::IfrOpcode::Divide => {}
  468. // 0x3E: Modulo
  469. uefi_parser::IfrOpcode::Modulo => {}
  470. // 0x3F: RuleRef
  471. uefi_parser::IfrOpcode::RuleRef => {}
  472. // 0x40: QuestionRef1
  473. uefi_parser::IfrOpcode::QuestionRef1 => {}
  474. // 0x41: QuestionRef2
  475. uefi_parser::IfrOpcode::QuestionRef2 => {}
  476. // 0x42: Uint8
  477. uefi_parser::IfrOpcode::Uint8 => {}
  478. // 0x43: Uint16
  479. uefi_parser::IfrOpcode::Uint16 => {}
  480. // 0x44: Uint32
  481. uefi_parser::IfrOpcode::Uint32 => {}
  482. // 0x45: Uint64
  483. uefi_parser::IfrOpcode::Uint64 => {}
  484. // 0x46: True
  485. uefi_parser::IfrOpcode::True => {}
  486. // 0x47: False
  487. uefi_parser::IfrOpcode::False => {}
  488. // 0x48: ToUint
  489. uefi_parser::IfrOpcode::ToUint => {}
  490. // 0x49: ToString
  491. uefi_parser::IfrOpcode::ToString => {}
  492. // 0x4A: ToBoolean
  493. uefi_parser::IfrOpcode::ToBoolean => {}
  494. // 0x4B: Mid
  495. uefi_parser::IfrOpcode::Mid => {}
  496. // 0x4C: Find
  497. uefi_parser::IfrOpcode::Find => {}
  498. // 0x4D: Token
  499. uefi_parser::IfrOpcode::Token => {}
  500. // 0x4E: StringRef1
  501. uefi_parser::IfrOpcode::StringRef1 => {
  502. if let Ok((_, st)) =
  503. uefi_parser::ifr_string_ref_1(operation.Data.unwrap())
  504. {
  505. string_ids.push(st.StringId);
  506. }
  507. }
  508. // 0x4F: StringRef2
  509. uefi_parser::IfrOpcode::StringRef2 => {}
  510. // 0x50: Conditional
  511. uefi_parser::IfrOpcode::Conditional => {}
  512. // 0x51: QuestionRef3
  513. uefi_parser::IfrOpcode::QuestionRef3 => {
  514. if operation.Data.is_some() {
  515. if let Ok((_, qr)) =
  516. uefi_parser::ifr_question_ref_3(operation.Data.unwrap())
  517. {
  518. if let Some(x) = qr.DevicePathId {
  519. string_ids.push(x);
  520. }
  521. }
  522. }
  523. }
  524. // 0x52: Zero
  525. uefi_parser::IfrOpcode::Zero => {}
  526. // 0x53: One
  527. uefi_parser::IfrOpcode::One => {}
  528. // 0x54: Ones
  529. uefi_parser::IfrOpcode::Ones => {}
  530. // 0x55: Undefined
  531. uefi_parser::IfrOpcode::Undefined => {}
  532. // 0x56: Length
  533. uefi_parser::IfrOpcode::Length => {}
  534. // 0x57: Dup
  535. uefi_parser::IfrOpcode::Dup => {}
  536. // 0x58: This
  537. uefi_parser::IfrOpcode::This => {}
  538. // 0x59: Span
  539. uefi_parser::IfrOpcode::Span => {}
  540. // 0x5A: Value
  541. uefi_parser::IfrOpcode::Value => {}
  542. // 0x5B: Default
  543. uefi_parser::IfrOpcode::Default => {
  544. if let Ok((_, def)) =
  545. uefi_parser::ifr_default(operation.Data.unwrap())
  546. {
  547. match def.Value {
  548. uefi_parser::IfrTypeValue::String(x) => {
  549. string_ids.push(x);
  550. }
  551. uefi_parser::IfrTypeValue::Action(x) => {
  552. string_ids.push(x);
  553. }
  554. _ => {}
  555. }
  556. }
  557. }
  558. // 0x5C: DefaultStore
  559. uefi_parser::IfrOpcode::DefaultStore => {
  560. if let Ok((_, default_store)) =
  561. uefi_parser::ifr_default_store(operation.Data.unwrap())
  562. {
  563. string_ids.push(default_store.NameStringId);
  564. }
  565. }
  566. // 0x5D: FormMap
  567. uefi_parser::IfrOpcode::FormMap => {
  568. if let Ok((_, form_map)) =
  569. uefi_parser::ifr_form_map(operation.Data.unwrap())
  570. {
  571. for method in form_map.Methods {
  572. string_ids.push(method.MethodTitleId);
  573. }
  574. }
  575. }
  576. // 0x5E: Catenate
  577. uefi_parser::IfrOpcode::Catenate => {}
  578. // 0x5F: GUID
  579. uefi_parser::IfrOpcode::Guid => {
  580. if let Ok((_, guid)) =
  581. uefi_parser::ifr_guid(operation.Data.unwrap())
  582. {
  583. // This manual parsing here is ugly and can ultimately be done using nom,
  584. // but it's done already and not that important anyway
  585. match guid.Guid {
  586. uefi_parser::IFR_TIANO_GUID => {
  587. if let Ok((_, edk2)) =
  588. uefi_parser::ifr_guid_edk2(guid.Data)
  589. {
  590. match edk2.ExtendedOpCode {
  591. uefi_parser::IfrEdk2ExtendOpCode::Banner => {
  592. if let Ok((_, banner)) =
  593. uefi_parser::ifr_guid_edk2_banner(
  594. edk2.Data,
  595. )
  596. {
  597. string_ids.push(banner.TitleId);
  598. }
  599. }
  600. uefi_parser::IfrEdk2ExtendOpCode::Label => {}
  601. uefi_parser::IfrEdk2ExtendOpCode::Timeout => {}
  602. uefi_parser::IfrEdk2ExtendOpCode::Class => {}
  603. uefi_parser::IfrEdk2ExtendOpCode::SubClass => {}
  604. uefi_parser::IfrEdk2ExtendOpCode::Unknown(
  605. _,
  606. ) => {}
  607. }
  608. }
  609. }
  610. uefi_parser::IFR_FRAMEWORK_GUID => {
  611. if let Ok((_, edk)) =
  612. uefi_parser::ifr_guid_edk(guid.Data)
  613. {
  614. match edk.ExtendedOpCode {
  615. uefi_parser::IfrEdkExtendOpCode::OptionKey => {}
  616. uefi_parser::IfrEdkExtendOpCode::VarEqName => {
  617. if edk.Data.len() == 2 {
  618. let name_id = edk.Data[1] as u16 * 100
  619. + edk.Data[0] as u16;
  620. string_ids.push(name_id);
  621. }
  622. }
  623. uefi_parser::IfrEdkExtendOpCode::Unknown(_) => {
  624. }
  625. }
  626. }
  627. }
  628. _ => {}
  629. }
  630. }
  631. }
  632. // 0x60: Security
  633. uefi_parser::IfrOpcode::Security => {}
  634. // 0x61: ModalTag
  635. uefi_parser::IfrOpcode::ModalTag => {}
  636. // 0x62: RefreshId
  637. uefi_parser::IfrOpcode::RefreshId => {}
  638. // 0x63: WarningIf
  639. uefi_parser::IfrOpcode::WarningIf => {
  640. if let Ok((_, warn)) =
  641. uefi_parser::ifr_warning_if(operation.Data.unwrap())
  642. {
  643. string_ids.push(warn.WarningStringId);
  644. }
  645. }
  646. // 0x64: Match2
  647. uefi_parser::IfrOpcode::Match2 => {}
  648. // Unknown operation
  649. uefi_parser::IfrOpcode::Unknown(_) => {}
  650. }
  651. }
  652. }
  653.  
  654. // Find min and max StringId, and the number of unique ones
  655. string_ids.sort();
  656. string_ids.dedup();
  657. if !string_ids.is_empty() {
  658. // Add the required information to forms
  659. let form = (
  660. i,
  661. candidate.len(),
  662. string_ids.len(),
  663. *string_ids.first().unwrap(),
  664. *string_ids.last().unwrap(),
  665. );
  666. forms.push(form);
  667.  
  668. i += candidate.len();
  669. } else {
  670. i += 1;
  671. }
  672. } else {
  673. i += 1;
  674. }
  675. } else {
  676. i += 1;
  677. }
  678. }
  679.  
  680. // Construct return value
  681. let mut result_strings = Vec::new();
  682. let mut result_forms = Vec::new();
  683. for string in &strings {
  684. result_strings.push(StringPackage {
  685. offset: string.0,
  686. length: string.1,
  687. language: string.2.clone(),
  688. string_id_map: string.3.clone(),
  689. });
  690. }
  691. for form in &forms {
  692. result_forms.push(FormPackage {
  693. offset: form.0,
  694. length: form.1,
  695. used_strings: form.2,
  696. min_string_id: form.3,
  697. max_string_id: form.4,
  698. });
  699. }
  700.  
  701. (result_strings, result_forms)
  702. }
  703.  
  704. fn uefi_ifr_extract(
  705. path: &OsStr,
  706. data: &[u8],
  707. form_package: &FormPackage,
  708. form_package_index: usize,
  709. string_package: &StringPackage,
  710. string_package_index: usize,
  711. verbose_mode: bool,
  712. ) {
  713. let mut text = Vec::new();
  714. let strings_map = &string_package.string_id_map;
  715.  
  716. // Add version number and extraction mode
  717. writeln!(&mut text, "Program version: {}, Extraction mode: UEFI, SHA256: {}", VERSION.unwrap_or("0.0.0"), digest(data)).unwrap();
  718.  
  719. if let Ok((_, candidate)) =
  720. uefi_parser::hii_form_package_candidate(&data[form_package.offset..])
  721. {
  722. if let Ok((_, package)) = uefi_parser::hii_package(candidate) {
  723. // Parse form package and output its structure as human-readable strings
  724. match uefi_parser::ifr_operations(package.Data.unwrap()) {
  725. Ok((_, operations)) => {
  726. let mut scope_depth: usize = 0;
  727. let mut current_operation_offset = form_package.offset + 4; // Header size of UEFI HII form package is 4 bytes
  728. for operation in &operations {
  729. if operation.OpCode == uefi_parser::IfrOpcode::End && scope_depth >= 1 {
  730. scope_depth -= 1;
  731. }
  732.  
  733. if verbose_mode {
  734. write!(
  735. &mut text,
  736. "0x{current_operation_offset:X}: "
  737. )
  738. .unwrap();
  739. }
  740.  
  741. write!(
  742. &mut text,
  743. "{:\t<1$}{2:?} ",
  744. "", scope_depth, operation.OpCode
  745. )
  746. .unwrap();
  747.  
  748. if operation.ScopeStart {
  749. scope_depth += 1;
  750. }
  751.  
  752. match operation.OpCode {
  753. // 0x01: Form
  754. uefi_parser::IfrOpcode::Form => {
  755. match uefi_parser::ifr_form(operation.Data.unwrap()) {
  756. Ok((_, form)) => {
  757. write!(
  758. &mut text,
  759. "FormId: 0x{:X}, Title: \"{}\"",
  760. form.FormId,
  761. strings_map
  762. .get(&form.TitleStringId)
  763. .unwrap_or(&String::from("InvalidId"))
  764. )
  765. .unwrap();
  766. }
  767. Err(e) => {
  768. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  769. .unwrap();
  770. println!("Form parse error: {e:?} at offset 0x{current_operation_offset:X}");
  771. }
  772. }
  773. }
  774. // 0x02: Subtitle
  775. uefi_parser::IfrOpcode::Subtitle => {
  776. match uefi_parser::ifr_subtitle(operation.Data.unwrap()) {
  777. Ok((_, sub)) => {
  778. write!(
  779. &mut text,
  780. "Prompt: \"{}\", Help: \"{}\", Flags: 0x{:X}",
  781. strings_map
  782. .get(&sub.PromptStringId)
  783. .unwrap_or(&String::from("InvalidId")),
  784. strings_map
  785. .get(&sub.HelpStringId)
  786. .unwrap_or(&String::from("InvalidId")),
  787. sub.Flags
  788. )
  789. .unwrap();
  790. }
  791. Err(e) => {
  792. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  793. .unwrap();
  794. println!("Subtitle parse error: {e:?} at offset 0x{current_operation_offset:X}");
  795. }
  796. }
  797. }
  798. // 0x03: Text
  799. uefi_parser::IfrOpcode::Text => {
  800. match uefi_parser::ifr_text(operation.Data.unwrap()) {
  801. Ok((_, txt)) => {
  802. write!(
  803. &mut text,
  804. "Prompt: \"{}\", Help: \"{}\", Text: \"{}\"",
  805. strings_map
  806. .get(&txt.PromptStringId)
  807. .unwrap_or(&String::from("InvalidId")),
  808. strings_map
  809. .get(&txt.HelpStringId)
  810. .unwrap_or(&String::from("InvalidId")),
  811. strings_map
  812. .get(&txt.TextId)
  813. .unwrap_or(&String::from("InvalidId"))
  814. )
  815. .unwrap();
  816. }
  817. Err(e) => {
  818. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  819. .unwrap();
  820. println!("Text parse error: {e:?} at offset 0x{current_operation_offset:X}");
  821. }
  822. }
  823. }
  824. // 0x04: Image
  825. uefi_parser::IfrOpcode::Image => {
  826. match uefi_parser::ifr_image(operation.Data.unwrap()) {
  827. Ok((_, image)) => {
  828. write!(&mut text, "ImageId: 0x{:X}", image.ImageId).unwrap();
  829. }
  830. Err(e) => {
  831. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  832. .unwrap();
  833. println!("Image parse error: {e:?} at offset 0x{current_operation_offset:X}");
  834. }
  835. }
  836. }
  837. // 0x05: OneOf
  838. uefi_parser::IfrOpcode::OneOf => {
  839. match uefi_parser::ifr_one_of(operation.Data.unwrap()) {
  840. Ok((_, onf)) => {
  841. write!(&mut text, "Prompt: \"{}\", Help: \"{}\", QuestionFlags: 0x{:X}, QuestionId: 0x{:X}, VarStoreId: 0x{:X}, VarOffset: 0x{:X}, Flags: 0x{:X}, ",
  842. strings_map.get(&onf.PromptStringId).unwrap_or(&String::from("InvalidId")),
  843. strings_map.get(&onf.HelpStringId).unwrap_or(&String::from("InvalidId")),
  844. onf.QuestionFlags,
  845. onf.QuestionId,
  846. onf.VarStoreId,
  847. onf.VarStoreInfo,
  848. onf.Flags).unwrap();
  849. if onf.MinMaxStepData8[0].is_some() {
  850. write!(
  851. &mut text,
  852. "Size: 8, Min: 0x{:X}, Max: 0x{:X}, Step: 0x{:X}",
  853. onf.MinMaxStepData8[0].unwrap(),
  854. onf.MinMaxStepData8[1].unwrap(),
  855. onf.MinMaxStepData8[2].unwrap()
  856. )
  857. .unwrap();
  858. }
  859. if onf.MinMaxStepData16[0].is_some() {
  860. write!(
  861. &mut text,
  862. "Size: 16, Min: 0x{:X}, Max: 0x{:X}, Step: 0x{:X}",
  863. onf.MinMaxStepData16[0].unwrap(),
  864. onf.MinMaxStepData16[1].unwrap(),
  865. onf.MinMaxStepData16[2].unwrap()
  866. )
  867. .unwrap();
  868. }
  869. if onf.MinMaxStepData32[0].is_some() {
  870. write!(
  871. &mut text,
  872. "Size: 32, Min: 0x{:X}, Max: 0x{:X}, Step: 0x{:X}",
  873. onf.MinMaxStepData32[0].unwrap(),
  874. onf.MinMaxStepData32[1].unwrap(),
  875. onf.MinMaxStepData32[2].unwrap()
  876. )
  877. .unwrap();
  878. }
  879. if onf.MinMaxStepData64[0].is_some() {
  880. write!(
  881. &mut text,
  882. "Size: 64, Min: 0x{:X}, Max: 0x{:X}, Step: 0x{:X}",
  883. onf.MinMaxStepData64[0].unwrap(),
  884. onf.MinMaxStepData64[1].unwrap(),
  885. onf.MinMaxStepData64[2].unwrap()
  886. )
  887. .unwrap();
  888. }
  889. }
  890. Err(e) => {
  891. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  892. .unwrap();
  893. println!("OneOf parse error: {e:?} at offset 0x{current_operation_offset:X}");
  894. }
  895. }
  896. }
  897. // 0x06: CheckBox
  898. uefi_parser::IfrOpcode::CheckBox => {
  899. match uefi_parser::ifr_check_box(operation.Data.unwrap()) {
  900. Ok((_, cb)) => {
  901. write!(&mut text, "Prompt: \"{}\", Help: \"{}\", QuestionFlags: 0x{:X}, QuestionId: 0x{:X}, VarStoreId: 0x{:X}, VarOffset: 0x{:X}, Flags: 0x{:X}",
  902. strings_map.get(&cb.PromptStringId).unwrap_or(&String::from("InvalidId")),
  903. strings_map.get(&cb.HelpStringId).unwrap_or(&String::from("InvalidId")),
  904. cb.QuestionFlags,
  905. cb.QuestionId,
  906. cb.VarStoreId,
  907. cb.VarStoreInfo,
  908. cb.Flags).unwrap();
  909.  
  910. if cb.Flags & (uefi_parser::IfrCheckBoxDefaultFlags::Default as u8) > 0 {
  911. write!(&mut text, ", Default: Enabled").unwrap();
  912. }
  913. else {
  914. write!(&mut text, ", Default: Disabled").unwrap();
  915. }
  916. if cb.Flags & (uefi_parser::IfrCheckBoxDefaultFlags::MfgDefault as u8) > 0 {
  917. write!(&mut text, ", MfgDefault: Enabled").unwrap();
  918. }
  919. else {
  920. write!(&mut text, ", MfgDefault: Disabled").unwrap();
  921. }
  922. }
  923. Err(e) => {
  924. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  925. .unwrap();
  926. println!("CheckBox parse error: {e:?} at offset 0x{current_operation_offset:X}");
  927. }
  928. }
  929. }
  930. // 0x07: Numeric
  931. uefi_parser::IfrOpcode::Numeric => {
  932. match uefi_parser::ifr_numeric(operation.Data.unwrap()) {
  933. Ok((_, num)) => {
  934. write!(&mut text, "Prompt: \"{}\", Help: \"{}\", QuestionFlags: 0x{:X}, QuestionId: 0x{:X}, VarStoreId: 0x{:X}, VarOffset: 0x{:X}, Flags: 0x{:X}, ",
  935. strings_map.get(&num.PromptStringId).unwrap_or(&String::from("InvalidId")),
  936. strings_map.get(&num.HelpStringId).unwrap_or(&String::from("InvalidId")),
  937. num.QuestionFlags,
  938. num.QuestionId,
  939. num.VarStoreId,
  940. num.VarStoreInfo,
  941. num.Flags).unwrap();
  942. if num.MinMaxStepData8[0].is_some() {
  943. write!(
  944. &mut text,
  945. "Size: 8, Min: 0x{:X}, Max: 0x{:X}, Step: 0x{:X}",
  946. num.MinMaxStepData8[0].unwrap(),
  947. num.MinMaxStepData8[1].unwrap(),
  948. num.MinMaxStepData8[2].unwrap()
  949. )
  950. .unwrap();
  951. }
  952. if num.MinMaxStepData16[0].is_some() {
  953. write!(
  954. &mut text,
  955. "Size: 16, Min: 0x{:X}, Max: 0x{:X}, Step: 0x{:X}",
  956. num.MinMaxStepData16[0].unwrap(),
  957. num.MinMaxStepData16[1].unwrap(),
  958. num.MinMaxStepData16[2].unwrap()
  959. )
  960. .unwrap();
  961. }
  962. if num.MinMaxStepData32[0].is_some() {
  963. write!(
  964. &mut text,
  965. "Size: 32, Min: 0x{:X}, Max: 0x{:X}, Step: 0x{:X}",
  966. num.MinMaxStepData32[0].unwrap(),
  967. num.MinMaxStepData32[1].unwrap(),
  968. num.MinMaxStepData32[2].unwrap()
  969. )
  970. .unwrap();
  971. }
  972. if num.MinMaxStepData64[0].is_some() {
  973. write!(
  974. &mut text,
  975. "Size: 64, Min: 0x{:X}, Max: 0x{:X}, Step: 0x{:X}",
  976. num.MinMaxStepData64[0].unwrap(),
  977. num.MinMaxStepData64[1].unwrap(),
  978. num.MinMaxStepData64[2].unwrap()
  979. )
  980. .unwrap();
  981. }
  982. }
  983. Err(e) => {
  984. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  985. .unwrap();
  986. println!("Numeric parse error: {e:?} at offset 0x{current_operation_offset:X}");
  987. }
  988. }
  989. }
  990. // 0x08: Password
  991. uefi_parser::IfrOpcode::Password => {
  992. match uefi_parser::ifr_password(operation.Data.unwrap()) {
  993. Ok((_, pw)) => {
  994. write!(&mut text, "Prompt: \"{}\", Help: \"{}\", QuestionFlags: 0x{:X}, QuestionId: 0x{:X}, VarStoreId: 0x{:X}, VarStoreInfo: 0x{:X}, MinSize: 0x{:X}, MaxSize: 0x{:X}",
  995. strings_map.get(&pw.PromptStringId).unwrap_or(&String::from("InvalidId")),
  996. strings_map.get(&pw.HelpStringId).unwrap_or(&String::from("InvalidId")),
  997. pw.QuestionFlags,
  998. pw.QuestionId,
  999. pw.VarStoreId,
  1000. pw.VarStoreInfo,
  1001. pw.MinSize,
  1002. pw.MaxSize).unwrap();
  1003. }
  1004. Err(e) => {
  1005. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1006. .unwrap();
  1007. println!("Password parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1008. }
  1009. }
  1010. }
  1011. // 0x09: OneOfOption
  1012. uefi_parser::IfrOpcode::OneOfOption => {
  1013. match uefi_parser::ifr_one_of_option(operation.Data.unwrap()) {
  1014. Ok((_, opt)) => {
  1015. write!(
  1016. &mut text,
  1017. "Option: \"{}\" ",
  1018. strings_map
  1019. .get(&opt.OptionStringId)
  1020. .unwrap_or(&String::from("InvalidId"))
  1021. )
  1022. .unwrap();
  1023. match opt.Value {
  1024. uefi_parser::IfrTypeValue::String(x) => {
  1025. write!(
  1026. &mut text,
  1027. "String: \"{}\"",
  1028. strings_map
  1029. .get(&x)
  1030. .unwrap_or(&String::from("InvalidId"))
  1031. )
  1032. .unwrap();
  1033. }
  1034. uefi_parser::IfrTypeValue::Action(x) => {
  1035. write!(
  1036. &mut text,
  1037. "Action: \"{}\"",
  1038. strings_map
  1039. .get(&x)
  1040. .unwrap_or(&String::from("InvalidId"))
  1041. )
  1042. .unwrap();
  1043. }
  1044. _ => {
  1045. write!(&mut text, "Value: {}", opt.Value).unwrap();
  1046. }
  1047. }
  1048.  
  1049. if opt.Flags & (uefi_parser::IfrOneOfOptionDefaultFlags::Default as u8) > 0 {
  1050. write!(&mut text, ", Default").unwrap();
  1051. }
  1052. if opt.Flags & (uefi_parser::IfrOneOfOptionDefaultFlags::MfgDefault as u8) > 0 {
  1053. write!(&mut text, ", MfgDefault").unwrap();
  1054. }
  1055. }
  1056. Err(e) => {
  1057. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1058. .unwrap();
  1059. println!("OneOfOption parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1060. }
  1061. }
  1062. }
  1063. // 0x0A: SuppressIf
  1064. uefi_parser::IfrOpcode::SuppressIf => {}
  1065. // 0x0B: Locked
  1066. uefi_parser::IfrOpcode::Locked => {}
  1067. // 0x0C: Action
  1068. uefi_parser::IfrOpcode::Action => {
  1069. match uefi_parser::ifr_action(operation.Data.unwrap()) {
  1070. Ok((_, act)) => {
  1071. write!(&mut text, "Prompt: \"{}\", Help: \"{}\", QuestionFlags: 0x{:X}, QuestionId: 0x{:X}, VarStoreId: 0x{:X}, VarStoreInfo: 0x{:X}",
  1072. strings_map.get(&act.PromptStringId).unwrap_or(&String::from("InvalidId")),
  1073. strings_map.get(&act.HelpStringId).unwrap_or(&String::from("InvalidId")),
  1074. act.QuestionFlags,
  1075. act.QuestionId,
  1076. act.VarStoreId,
  1077. act.VarStoreInfo).unwrap();
  1078. if let Some(x) = act.ConfigStringId {
  1079. write!(
  1080. &mut text,
  1081. ", QuestionConfig: \"{}\"",
  1082. strings_map
  1083. .get(&x)
  1084. .unwrap_or(&String::from("InvalidId"))
  1085. )
  1086. .unwrap();
  1087. }
  1088.  
  1089.  
  1090. }
  1091. Err(e) => {
  1092. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1093. .unwrap();
  1094. println!("Action parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1095. }
  1096. }
  1097. }
  1098. // 0x0D: ResetButton
  1099. uefi_parser::IfrOpcode::ResetButton => {
  1100. match uefi_parser::ifr_reset_button(operation.Data.unwrap()) {
  1101. Ok((_, rst)) => {
  1102. write!(
  1103. &mut text,
  1104. "Prompt: \"{}\", Help: \"{}\", DefaultId: 0x{:X}",
  1105. strings_map
  1106. .get(&rst.PromptStringId)
  1107. .unwrap_or(&String::from("InvalidId")),
  1108. strings_map
  1109. .get(&rst.HelpStringId)
  1110. .unwrap_or(&String::from("InvalidId")),
  1111. rst.DefaultId
  1112. )
  1113. .unwrap();
  1114. }
  1115. Err(e) => {
  1116. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1117. .unwrap();
  1118. println!("ResetButton parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1119. }
  1120. }
  1121. }
  1122. // 0x0E: FormSet
  1123. uefi_parser::IfrOpcode::FormSet => {
  1124. match uefi_parser::ifr_form_set(operation.Data.unwrap()) {
  1125. Ok((_, form_set)) => {
  1126. write!(
  1127. &mut text,
  1128. "Guid: {}, Title: \"{}\", Help: \"{}\"",
  1129. form_set.Guid,
  1130. strings_map
  1131. .get(&form_set.TitleStringId)
  1132. .unwrap_or(&String::from("InvalidId")),
  1133. strings_map
  1134. .get(&form_set.HelpStringId)
  1135. .unwrap_or(&String::from("InvalidId"))
  1136. )
  1137. .unwrap();
  1138. }
  1139. Err(e) => {
  1140. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1141. .unwrap();
  1142. println!("FormSet parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1143. }
  1144. }
  1145. }
  1146. // 0x0F: Ref
  1147. uefi_parser::IfrOpcode::Ref => {
  1148. match uefi_parser::ifr_ref(operation.Data.unwrap()) {
  1149. Ok((_, rf)) => {
  1150. write!(&mut text, "Prompt: \"{}\", Help: \"{}\", QuestionFlags: 0x{:X}, QuestionId: 0x{:X}, VarStoreId: 0x{:X}, VarStoreInfo: 0x{:X}",
  1151. strings_map.get(&rf.PromptStringId).unwrap_or(&String::from("InvalidId")),
  1152. strings_map.get(&rf.HelpStringId).unwrap_or(&String::from("InvalidId")),
  1153. rf.QuestionFlags,
  1154. rf.QuestionId,
  1155. rf.VarStoreId,
  1156. rf.VarStoreInfo).unwrap();
  1157. if let Some(x) = rf.FormId {
  1158. write!(&mut text, ", FormId: 0x{x:X}").unwrap();
  1159. }
  1160. if let Some(x) = rf.RefQuestionId {
  1161. write!(&mut text, ", RefQuestionId: 0x{x:X}").unwrap();
  1162. }
  1163. if let Some(x) = rf.FormSetGuid {
  1164. write!(&mut text, ", FormSetGuid: {x}").unwrap();
  1165. }
  1166. if let Some(x) = rf.DevicePathId {
  1167. write!(&mut text, ", DevicePathId: 0x{x:X}").unwrap();
  1168. }
  1169. }
  1170. Err(e) => {
  1171. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1172. .unwrap();
  1173. println!("Ref parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1174. }
  1175. }
  1176. }
  1177. // 0x10: NoSubmitIf
  1178. uefi_parser::IfrOpcode::NoSubmitIf => {
  1179. match uefi_parser::ifr_no_submit_if(operation.Data.unwrap()) {
  1180. Ok((_, ns)) => {
  1181. write!(
  1182. &mut text,
  1183. "Error: \"{}\"",
  1184. strings_map
  1185. .get(&ns.ErrorStringId)
  1186. .unwrap_or(&String::from("InvalidId"))
  1187. )
  1188. .unwrap();
  1189. }
  1190. Err(e) => {
  1191. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1192. .unwrap();
  1193. println!("NoSubmitIf parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1194. }
  1195. }
  1196. }
  1197. // 0x11: InconsistentIf
  1198. uefi_parser::IfrOpcode::InconsistentIf => {
  1199. match uefi_parser::ifr_inconsistent_if(operation.Data.unwrap()) {
  1200. Ok((_, inc)) => {
  1201. write!(
  1202. &mut text,
  1203. "Error: \"{}\"",
  1204. strings_map
  1205. .get(&inc.ErrorStringId)
  1206. .unwrap_or(&String::from("InvalidId"))
  1207. )
  1208. .unwrap();
  1209. }
  1210. Err(e) => {
  1211. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1212. .unwrap();
  1213. println!("InconsistentIf parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1214. }
  1215. }
  1216. }
  1217. // 0x12: EqIdVal
  1218. uefi_parser::IfrOpcode::EqIdVal => {
  1219. match uefi_parser::ifr_eq_id_val(operation.Data.unwrap()) {
  1220. Ok((_, eq)) => {
  1221. write!(
  1222. &mut text,
  1223. "QuestionId: 0x{:X}, Value: 0x{:X}",
  1224. eq.QuestionId, eq.Value
  1225. )
  1226. .unwrap();
  1227. }
  1228. Err(e) => {
  1229. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1230. .unwrap();
  1231. println!(" EqIdVal parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1232. }
  1233. }
  1234. }
  1235. // 0x13: EqIdId
  1236. uefi_parser::IfrOpcode::EqIdId => {
  1237. match uefi_parser::ifr_eq_id_id(operation.Data.unwrap()) {
  1238. Ok((_, eq)) => {
  1239. write!(
  1240. &mut text,
  1241. "QuestionId: 0x{:X}, OtherQuestionId: 0x{:X}",
  1242. eq.QuestionId, eq.OtherQuestionId
  1243. )
  1244. .unwrap();
  1245. }
  1246. Err(e) => {
  1247. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1248. .unwrap();
  1249. println!("EqIdId parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1250. }
  1251. }
  1252. }
  1253. // 0x14: EqIdValList
  1254. uefi_parser::IfrOpcode::EqIdValList => {
  1255. match uefi_parser::ifr_eq_id_val_list(operation.Data.unwrap()) {
  1256. Ok((_, eql)) => {
  1257. write!(
  1258. &mut text,
  1259. "QuestionId: 0x{:X}, Values: {:?}",
  1260. eql.QuestionId, eql.Values
  1261. )
  1262. .unwrap();
  1263. }
  1264. Err(e) => {
  1265. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1266. .unwrap();
  1267. println!("EqIdValList parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1268. }
  1269. }
  1270. }
  1271. // 0x15: And
  1272. uefi_parser::IfrOpcode::And => {}
  1273. // 0x16: Or
  1274. uefi_parser::IfrOpcode::Or => {}
  1275. // 0x17: Not
  1276. uefi_parser::IfrOpcode::Not => {}
  1277. // 0x18: Rule
  1278. uefi_parser::IfrOpcode::Rule => {
  1279. match uefi_parser::ifr_rule(operation.Data.unwrap()) {
  1280. Ok((_, rule)) => {
  1281. write!(&mut text, "RuleId: 0x{:X}", rule.RuleId).unwrap();
  1282. }
  1283. Err(e) => {
  1284. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1285. .unwrap();
  1286. println!("Rule parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1287. }
  1288. }
  1289. }
  1290. // 0x19: GrayOutIf
  1291. uefi_parser::IfrOpcode::GrayOutIf => {}
  1292. // 0x1A: Date
  1293. uefi_parser::IfrOpcode::Date => {
  1294. match uefi_parser::ifr_date(operation.Data.unwrap()) {
  1295. Ok((_, dt)) => {
  1296. write!(&mut text, "Prompt: \"{}\", Help: \"{}\", QuestionFlags: 0x{:X}, QuestionId: 0x{:X}, VarStoreId: 0x{:X}, VarStoreInfo: 0x{:X}, Flags: 0x{:X}",
  1297. strings_map.get(&dt.PromptStringId).unwrap_or(&String::from("InvalidId")),
  1298. strings_map.get(&dt.HelpStringId).unwrap_or(&String::from("InvalidId")),
  1299. dt.QuestionFlags,
  1300. dt.QuestionId,
  1301. dt.VarStoreId,
  1302. dt.VarStoreInfo,
  1303. dt.Flags).unwrap();
  1304. }
  1305. Err(e) => {
  1306. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1307. .unwrap();
  1308. println!("Date parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1309. }
  1310. }
  1311. }
  1312. // 0x1B: Time
  1313. uefi_parser::IfrOpcode::Time => {
  1314. match uefi_parser::ifr_time(operation.Data.unwrap()) {
  1315. Ok((_, time)) => {
  1316. write!(&mut text, "Prompt: \"{}\", Help: \"{}\", QuestionFlags: 0x{:X}, QuestionId: 0x{:X}, VarStoreId: 0x{:X}, VarStoreInfo: 0x{:X}, Flags: 0x{:X}",
  1317. strings_map.get(&time.PromptStringId).unwrap_or(&String::from("InvalidId")),
  1318. strings_map.get(&time.HelpStringId).unwrap_or(&String::from("InvalidId")),
  1319. time.QuestionFlags,
  1320. time.QuestionId,
  1321. time.VarStoreId,
  1322. time.VarStoreInfo,
  1323. time.Flags).unwrap();
  1324. }
  1325. Err(e) => {
  1326. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1327. .unwrap();
  1328. println!("Time parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1329. }
  1330. }
  1331. }
  1332. // 0x1C: String
  1333. uefi_parser::IfrOpcode::String => {
  1334. match uefi_parser::ifr_string(operation.Data.unwrap()) {
  1335. Ok((_, st)) => {
  1336. write!(&mut text, "Prompt: \"{}\", Help: \"{}\", QuestionFlags: 0x{:X}, QuestionId: 0x{:X}, VarStoreId: 0x{:X}, VarStoreInfo: 0x{:X}, MinSize: 0x{:X}, MaxSize: 0x{:X}, Flags: 0x{:X}",
  1337. strings_map.get(&st.PromptStringId).unwrap_or(&String::from("InvalidId")),
  1338. strings_map.get(&st.HelpStringId).unwrap_or(&String::from("InvalidId")),
  1339. st.QuestionFlags,
  1340. st.QuestionId,
  1341. st.VarStoreId,
  1342. st.VarStoreInfo,
  1343. st.MinSize,
  1344. st.MaxSize,
  1345. st.Flags).unwrap();
  1346. }
  1347. Err(e) => {
  1348. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1349. .unwrap();
  1350. println!("String parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1351. }
  1352. }
  1353. }
  1354. // 0x1D: Refresh
  1355. uefi_parser::IfrOpcode::Refresh => {
  1356. match uefi_parser::ifr_refresh(operation.Data.unwrap()) {
  1357. Ok((_, refr)) => {
  1358. write!(
  1359. &mut text,
  1360. "RefreshInterval: 0x{:X}",
  1361. refr.RefreshInterval
  1362. )
  1363. .unwrap();
  1364. }
  1365. Err(e) => {
  1366. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1367. .unwrap();
  1368. println!("Refresh parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1369. }
  1370. }
  1371. }
  1372. // 0x1E: DisableIf
  1373. uefi_parser::IfrOpcode::DisableIf => {}
  1374. // 0x1F: Animation
  1375. uefi_parser::IfrOpcode::Animation => {
  1376. match uefi_parser::ifr_animation(operation.Data.unwrap()) {
  1377. Ok((_, anim)) => {
  1378. write!(&mut text, "AnimationId: 0x{:X}", anim.AnimationId)
  1379. .unwrap();
  1380. }
  1381. Err(e) => {
  1382. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1383. .unwrap();
  1384. println!("Animation parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1385. }
  1386. }
  1387. }
  1388. // 0x20: ToLower
  1389. uefi_parser::IfrOpcode::ToLower => {}
  1390. // 0x21: ToUpper
  1391. uefi_parser::IfrOpcode::ToUpper => {}
  1392. // 0x22: Map
  1393. uefi_parser::IfrOpcode::Map => {}
  1394. // 0x23: OrderedList
  1395. uefi_parser::IfrOpcode::OrderedList => {
  1396. match uefi_parser::ifr_ordered_list(operation.Data.unwrap()) {
  1397. Ok((_, ol)) => {
  1398. write!(&mut text, "Prompt: \"{}\", Help: \"{}\", QuestionFlags: 0x{:X}, QuestionId: 0x{:X}, VarStoreId: 0x{:X}, VarOffset: 0x{:X}, MaxContainers: 0x{:X}, Flags: 0x{:X}",
  1399. strings_map.get(&ol.PromptStringId).unwrap_or(&String::from("InvalidId")),
  1400. strings_map.get(&ol.HelpStringId).unwrap_or(&String::from("InvalidId")),
  1401. ol.QuestionFlags,
  1402. ol.QuestionId,
  1403. ol.VarStoreId,
  1404. ol.VarStoreInfo,
  1405. ol.MaxContainers,
  1406. ol.Flags).unwrap();
  1407. }
  1408. Err(e) => {
  1409. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1410. .unwrap();
  1411. println!("OrderedList parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1412. }
  1413. }
  1414. }
  1415. // 0x24: VarStore
  1416. uefi_parser::IfrOpcode::VarStore => {
  1417. match uefi_parser::ifr_var_store(operation.Data.unwrap()) {
  1418. Ok((_, var_store)) => {
  1419. write!(
  1420. &mut text,
  1421. "Guid: {}, VarStoreId: 0x{:X}, Size: 0x{:X}, Name: \"{}\"",
  1422. var_store.Guid,
  1423. var_store.VarStoreId,
  1424. var_store.Size,
  1425. var_store.Name
  1426. )
  1427. .unwrap();
  1428. }
  1429. Err(e) => {
  1430. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1431. .unwrap();
  1432. println!("VarStore parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1433. }
  1434. }
  1435. }
  1436. // 0x25: VarStoreNameValue
  1437. uefi_parser::IfrOpcode::VarStoreNameValue => {
  1438. match uefi_parser::ifr_var_store_name_value(operation.Data.unwrap())
  1439. {
  1440. Ok((_, var_store)) => {
  1441. write!(
  1442. &mut text,
  1443. "Guid: {}, VarStoreId: 0x{:X}",
  1444. var_store.Guid, var_store.VarStoreId
  1445. )
  1446. .unwrap();
  1447. }
  1448. Err(e) => {
  1449. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1450. .unwrap();
  1451. println!("VarStoreNameValue parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1452. }
  1453. }
  1454. }
  1455. // 0x26: VarStoreEfi
  1456. uefi_parser::IfrOpcode::VarStoreEfi => {
  1457. match uefi_parser::ifr_var_store_efi(operation.Data.unwrap()) {
  1458. Ok((_, var_store)) => {
  1459. write!(&mut text, "Guid: {}, VarStoreId: 0x{:X}, Attributes: 0x{:X}",
  1460. var_store.Guid,
  1461. var_store.VarStoreId,
  1462. var_store.Attributes
  1463. ).unwrap();
  1464.  
  1465. if let Some(size) = var_store.Size {
  1466. write!(&mut text, ", Size: 0x{size:X}"
  1467. ).unwrap();
  1468. }
  1469.  
  1470. if let Some(name) = var_store.Name {
  1471. write!(&mut text, ", Name: \"{name}\""
  1472. ).unwrap();
  1473. }
  1474. }
  1475. Err(e) => {
  1476. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1477. .unwrap();
  1478. println!("VarStoreEfi parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1479. }
  1480. }
  1481. }
  1482. // 0x27: VarStoreDevice
  1483. uefi_parser::IfrOpcode::VarStoreDevice => {
  1484. match uefi_parser::ifr_var_store_device(operation.Data.unwrap()) {
  1485. Ok((_, var_store)) => {
  1486. write!(
  1487. &mut text,
  1488. "DevicePath: \"{}\"",
  1489. strings_map
  1490. .get(&var_store.DevicePathStringId)
  1491. .unwrap_or(&String::from("InvalidId"))
  1492. )
  1493. .unwrap();
  1494. }
  1495. Err(e) => {
  1496. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1497. .unwrap();
  1498. println!("VarStoreDevice parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1499. }
  1500. }
  1501. }
  1502. // 0x28: Version
  1503. uefi_parser::IfrOpcode::Version => {}
  1504. // 0x29: End
  1505. uefi_parser::IfrOpcode::End => {}
  1506. // 0x2A: Match
  1507. uefi_parser::IfrOpcode::Match => {}
  1508. // 0x2B: Get
  1509. uefi_parser::IfrOpcode::Get => {
  1510. match uefi_parser::ifr_get(operation.Data.unwrap()) {
  1511. Ok((_, get)) => {
  1512. write!(
  1513. &mut text,
  1514. "VarStoreId: 0x{:X}, VarStoreInfo: 0x{:X}, VarStoreType: 0x{:X}",
  1515. get.VarStoreId, get.VarStoreInfo, get.VarStoreType
  1516. )
  1517. .unwrap();
  1518. }
  1519. Err(e) => {
  1520. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1521. .unwrap();
  1522. println!("Get parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1523. }
  1524. }
  1525. }
  1526. // 0x2C: Set
  1527. uefi_parser::IfrOpcode::Set => {
  1528. match uefi_parser::ifr_set(operation.Data.unwrap()) {
  1529. Ok((_, set)) => {
  1530. write!(
  1531. &mut text,
  1532. "VarStoreId: 0x{:X}, VarStoreInfo: 0x{:X}, VarStoreType: 0x{:X}",
  1533. set.VarStoreId, set.VarStoreInfo, set.VarStoreType
  1534. )
  1535. .unwrap();
  1536. }
  1537. Err(e) => {
  1538. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1539. .unwrap();
  1540. println!("Set parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1541. }
  1542. }
  1543. }
  1544. // 0x2D: Read
  1545. uefi_parser::IfrOpcode::Read => {}
  1546. // 0x2E: Write
  1547. uefi_parser::IfrOpcode::Write => {}
  1548. // 0x2F: Equal
  1549. uefi_parser::IfrOpcode::Equal => {}
  1550. // 0x30: NotEqual
  1551. uefi_parser::IfrOpcode::NotEqual => {}
  1552. // 0x31: GreaterThan
  1553. uefi_parser::IfrOpcode::GreaterThan => {}
  1554. // 0x32: GreaterEqual
  1555. uefi_parser::IfrOpcode::GreaterEqual => {}
  1556. // 0x33: LessThan
  1557. uefi_parser::IfrOpcode::LessThan => {}
  1558. // 0x34: LessEqual
  1559. uefi_parser::IfrOpcode::LessEqual => {}
  1560. // 0x35: BitwiseAnd
  1561. uefi_parser::IfrOpcode::BitwiseAnd => {}
  1562. // 0x36: BitwiseOr
  1563. uefi_parser::IfrOpcode::BitwiseOr => {}
  1564. // 0x37: BitwiseNot
  1565. uefi_parser::IfrOpcode::BitwiseNot => {}
  1566. // 0x38: ShiftLeft
  1567. uefi_parser::IfrOpcode::ShiftLeft => {}
  1568. // 0x39: ShiftRight
  1569. uefi_parser::IfrOpcode::ShiftRight => {}
  1570. // 0x3A: Add
  1571. uefi_parser::IfrOpcode::Add => {}
  1572. // 0x3B: Substract
  1573. uefi_parser::IfrOpcode::Substract => {}
  1574. // 0x3C: Multiply
  1575. uefi_parser::IfrOpcode::Multiply => {}
  1576. // 0x3D: Divide
  1577. uefi_parser::IfrOpcode::Divide => {}
  1578. // 0x3E: Modulo
  1579. uefi_parser::IfrOpcode::Modulo => {}
  1580. // 0x3F: RuleRef
  1581. uefi_parser::IfrOpcode::RuleRef => {
  1582. match uefi_parser::ifr_rule_ref(operation.Data.unwrap()) {
  1583. Ok((_, rule)) => {
  1584. write!(&mut text, "RuleId: 0x{:X}", rule.RuleId).unwrap();
  1585. }
  1586. Err(e) => {
  1587. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1588. .unwrap();
  1589. println!("RuleRef parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1590. }
  1591. }
  1592. }
  1593. // 0x40: QuestionRef1
  1594. uefi_parser::IfrOpcode::QuestionRef1 => {
  1595. match uefi_parser::ifr_question_ref_1(operation.Data.unwrap()) {
  1596. Ok((_, qr)) => {
  1597. write!(&mut text, "QuestionId: 0x{:X}", qr.QuestionId).unwrap();
  1598. }
  1599. Err(e) => {
  1600. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1601. .unwrap();
  1602. println!("QuestionRef1 parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1603. }
  1604. }
  1605. }
  1606. // 0x41: QuestionRef2
  1607. uefi_parser::IfrOpcode::QuestionRef2 => {}
  1608. // 0x42: Uint8
  1609. uefi_parser::IfrOpcode::Uint8 => {
  1610. match uefi_parser::ifr_uint8(operation.Data.unwrap()) {
  1611. Ok((_, u)) => {
  1612. write!(&mut text, "Value: 0x{:X}", u.Value).unwrap();
  1613. }
  1614. Err(e) => {
  1615. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1616. .unwrap();
  1617. println!("Uint8 parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1618. }
  1619. }
  1620. }
  1621. // 0x43: Uint16
  1622. uefi_parser::IfrOpcode::Uint16 => {
  1623. match uefi_parser::ifr_uint16(operation.Data.unwrap()) {
  1624. Ok((_, u)) => {
  1625. write!(&mut text, "Value: 0x{:X}", u.Value).unwrap();
  1626. }
  1627. Err(e) => {
  1628. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1629. .unwrap();
  1630. println!("Uint16 parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1631. }
  1632. }
  1633. }
  1634. // 0x44: Uint32
  1635. uefi_parser::IfrOpcode::Uint32 => {
  1636. match uefi_parser::ifr_uint32(operation.Data.unwrap()) {
  1637. Ok((_, u)) => {
  1638. write!(&mut text, "Value: 0x{:X}", u.Value).unwrap();
  1639. }
  1640. Err(e) => {
  1641. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1642. .unwrap();
  1643. println!("Uint32 parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1644. }
  1645. }
  1646. }
  1647. // 0x45: Uint64
  1648. uefi_parser::IfrOpcode::Uint64 => {
  1649. match uefi_parser::ifr_uint64(operation.Data.unwrap()) {
  1650. Ok((_, u)) => {
  1651. write!(&mut text, "Value: 0x{:X}", u.Value).unwrap();
  1652. }
  1653. Err(e) => {
  1654. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1655. .unwrap();
  1656. println!("Uint64 parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1657. }
  1658. }
  1659. }
  1660. // 0x46: True
  1661. uefi_parser::IfrOpcode::True => {}
  1662. // 0x47: False
  1663. uefi_parser::IfrOpcode::False => {}
  1664. // 0x48: ToUint
  1665. uefi_parser::IfrOpcode::ToUint => {}
  1666. // 0x49: ToString
  1667. uefi_parser::IfrOpcode::ToString => {
  1668. match uefi_parser::ifr_to_string(operation.Data.unwrap()) {
  1669. Ok((_, ts)) => {
  1670. write!(&mut text, "Format: 0x{:X}", ts.Format).unwrap();
  1671. }
  1672. Err(e) => {
  1673. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1674. .unwrap();
  1675. println!("ToString parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1676. }
  1677. }
  1678. }
  1679. // 0x4A: ToBoolean
  1680. uefi_parser::IfrOpcode::ToBoolean => {}
  1681. // 0x4B: Mid
  1682. uefi_parser::IfrOpcode::Mid => {}
  1683. // 0x4C: Find
  1684. uefi_parser::IfrOpcode::Find => {
  1685. match uefi_parser::ifr_find(operation.Data.unwrap()) {
  1686. Ok((_, fnd)) => {
  1687. write!(&mut text, "Format: 0x{:X}", fnd.Format).unwrap();
  1688. }
  1689. Err(e) => {
  1690. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1691. .unwrap();
  1692. println!("Find parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1693. }
  1694. }
  1695. }
  1696. // 0x4D: Token
  1697. uefi_parser::IfrOpcode::Token => {}
  1698. // 0x4E: StringRef1
  1699. uefi_parser::IfrOpcode::StringRef1 => {
  1700. match uefi_parser::ifr_string_ref_1(operation.Data.unwrap()) {
  1701. Ok((_, st)) => {
  1702. write!(
  1703. &mut text,
  1704. "String: \"{}\"",
  1705. strings_map
  1706. .get(&st.StringId)
  1707. .unwrap_or(&String::from("InvalidId"))
  1708. )
  1709. .unwrap();
  1710. }
  1711. Err(e) => {
  1712. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1713. .unwrap();
  1714. println!("StringRef1 parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1715. }
  1716. }
  1717. }
  1718. // 0x4F: StringRef2
  1719. uefi_parser::IfrOpcode::StringRef2 => {}
  1720. // 0x50: Conditional
  1721. uefi_parser::IfrOpcode::Conditional => {}
  1722. // 0x51: QuestionRef3
  1723. uefi_parser::IfrOpcode::QuestionRef3 => {
  1724. if operation.Data.is_some() {
  1725. match uefi_parser::ifr_question_ref_3(operation.Data.unwrap()) {
  1726. Ok((_, qr)) => {
  1727. if let Some(x) = qr.DevicePathId {
  1728. write!(
  1729. &mut text,
  1730. "DevicePath: \"{}\"",
  1731. strings_map
  1732. .get(&x)
  1733. .unwrap_or(&String::from("InvalidId"))
  1734. )
  1735. .unwrap();
  1736. }
  1737. if let Some(x) = qr.QuestionGuid {
  1738. write!(&mut text, "Guid: {x}").unwrap();
  1739. }
  1740. }
  1741. Err(e) => {
  1742. write!(
  1743. &mut text,
  1744. "RawData: {:02X?}",
  1745. operation.Data.unwrap()
  1746. )
  1747. .unwrap();
  1748. println!("QuestionRef3 parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1749. }
  1750. }
  1751. }
  1752. }
  1753. // 0x52: Zero
  1754. uefi_parser::IfrOpcode::Zero => {}
  1755. // 0x53: One
  1756. uefi_parser::IfrOpcode::One => {}
  1757. // 0x54: Ones
  1758. uefi_parser::IfrOpcode::Ones => {}
  1759. // 0x55: Undefined
  1760. uefi_parser::IfrOpcode::Undefined => {}
  1761. // 0x56: Length
  1762. uefi_parser::IfrOpcode::Length => {}
  1763. // 0x57: Dup
  1764. uefi_parser::IfrOpcode::Dup => {}
  1765. // 0x58: This
  1766. uefi_parser::IfrOpcode::This => {}
  1767. // 0x59: Span
  1768. uefi_parser::IfrOpcode::Span => {
  1769. match uefi_parser::ifr_span(operation.Data.unwrap()) {
  1770. Ok((_, span)) => {
  1771. write!(&mut text, "Flags: 0x{:X}", span.Flags).unwrap();
  1772. }
  1773. Err(e) => {
  1774. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1775. .unwrap();
  1776. println!("Span parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1777. }
  1778. }
  1779. }
  1780. // 0x5A: Value
  1781. uefi_parser::IfrOpcode::Value => {}
  1782. // 0x5B: Default
  1783. uefi_parser::IfrOpcode::Default => {
  1784. match uefi_parser::ifr_default(operation.Data.unwrap()) {
  1785. Ok((_, def)) => {
  1786. write!(&mut text, "DefaultId: 0x{:X} ", def.DefaultId).unwrap();
  1787. match def.Value {
  1788. uefi_parser::IfrTypeValue::String(x) => {
  1789. write!(
  1790. &mut text,
  1791. "String: \"{}\"",
  1792. strings_map
  1793. .get(&x)
  1794. .unwrap_or(&String::from("InvalidId"))
  1795. )
  1796. .unwrap();
  1797. }
  1798. uefi_parser::IfrTypeValue::Action(x) => {
  1799. write!(
  1800. &mut text,
  1801. "Action: \"{}\"",
  1802. strings_map
  1803. .get(&x)
  1804. .unwrap_or(&String::from("InvalidId"))
  1805. )
  1806. .unwrap();
  1807. }
  1808. _ => {
  1809. write!(&mut text, "Value: {}", def.Value).unwrap();
  1810. }
  1811. }
  1812. }
  1813. Err(e) => {
  1814. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1815. .unwrap();
  1816. println!("Default parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1817. }
  1818. }
  1819. }
  1820. // 0x5C: DefaultStore
  1821. uefi_parser::IfrOpcode::DefaultStore => {
  1822. match uefi_parser::ifr_default_store(operation.Data.unwrap()) {
  1823. Ok((_, default_store)) => {
  1824. write!(
  1825. &mut text,
  1826. "DefaultId: 0x{:X}, Name: \"{}\"",
  1827. default_store.DefaultId,
  1828. strings_map
  1829. .get(&default_store.NameStringId)
  1830. .unwrap_or(&String::from("InvalidId"))
  1831. )
  1832. .unwrap();
  1833. }
  1834. Err(e) => {
  1835. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1836. .unwrap();
  1837. println!("DefaultStore parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1838. }
  1839. }
  1840. }
  1841. // 0x5D: FormMap
  1842. uefi_parser::IfrOpcode::FormMap => {
  1843. match uefi_parser::ifr_form_map(operation.Data.unwrap()) {
  1844. Ok((_, form_map)) => {
  1845. write!(&mut text, "FormId: 0x{:X}", form_map.FormId).unwrap();
  1846. for method in form_map.Methods {
  1847. write!(
  1848. &mut text,
  1849. "| Guid: {}, Method: \"{}\"",
  1850. method.MethodIdentifier,
  1851. strings_map
  1852. .get(&method.MethodTitleId)
  1853. .unwrap_or(&String::from("InvalidId"))
  1854. )
  1855. .unwrap();
  1856. }
  1857. }
  1858. Err(e) => {
  1859. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1860. .unwrap();
  1861. println!("FormMap parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1862. }
  1863. }
  1864. }
  1865. // 0x5E: Catenate
  1866. uefi_parser::IfrOpcode::Catenate => {}
  1867. // 0x5F: GUID
  1868. uefi_parser::IfrOpcode::Guid => {
  1869. match uefi_parser::ifr_guid(operation.Data.unwrap()) {
  1870. Ok((_, guid)) => {
  1871. // This manual parsing here is ugly and can ultimately be done using nom,
  1872. // but it's done already and not that important anyway
  1873. // TODO: refactor later
  1874. let mut done = false;
  1875. match guid.Guid {
  1876. uefi_parser::IFR_TIANO_GUID => {
  1877. if let Ok((_, edk2)) =
  1878. uefi_parser::ifr_guid_edk2(guid.Data)
  1879. {
  1880. match edk2.ExtendedOpCode {
  1881. uefi_parser::IfrEdk2ExtendOpCode::Banner => {
  1882. if let Ok((_, banner)) =
  1883. uefi_parser::ifr_guid_edk2_banner(
  1884. edk2.Data,
  1885. )
  1886. {
  1887. write!(&mut text, "Guid: {}, ExtendedOpCode: {:?}, Title: \"{}\", LineNumber: 0x{:X}, Alignment: 0x{:X} ",
  1888. guid.Guid,
  1889. edk2.ExtendedOpCode,
  1890. strings_map.get(&banner.TitleId).unwrap_or(&String::from("InvalidId")),
  1891. banner.LineNumber,
  1892. banner.Alignment).unwrap();
  1893. done = true;
  1894. }
  1895. }
  1896. uefi_parser::IfrEdk2ExtendOpCode::Label => {
  1897. if edk2.Data.len() == 2 {
  1898. write!(&mut text, "Guid: {}, ExtendedOpCode: {:?}, LabelNumber: 0x{:X}",
  1899. guid.Guid,
  1900. edk2.ExtendedOpCode,
  1901. edk2.Data[1] as u16 * 100 + edk2.Data[0] as u16).unwrap();
  1902. done = true;
  1903. }
  1904. }
  1905. uefi_parser::IfrEdk2ExtendOpCode::Timeout => {
  1906. if edk2.Data.len() == 2 {
  1907. write!(&mut text, "Guid: {}, ExtendedOpCode: {:?}, Timeout: 0x{:X}",
  1908. guid.Guid,
  1909. edk2.ExtendedOpCode,
  1910. edk2.Data[1] as u16 * 100 + edk2.Data[0] as u16).unwrap();
  1911. done = true;
  1912. }
  1913. }
  1914. uefi_parser::IfrEdk2ExtendOpCode::Class => {
  1915. if edk2.Data.len() == 2 {
  1916. write!(&mut text, "Guid: {}, ExtendedOpCode: {:?}, Class: 0x{:X}",
  1917. guid.Guid,
  1918. edk2.ExtendedOpCode,
  1919. edk2.Data[1] as u16 * 100 + edk2.Data[0] as u16).unwrap();
  1920. done = true;
  1921. }
  1922. }
  1923. uefi_parser::IfrEdk2ExtendOpCode::SubClass => {
  1924. if edk2.Data.len() == 2 {
  1925. write!(&mut text, "Guid: {}, ExtendedOpCode: {:?}, SubClass: 0x{:X}",
  1926. guid.Guid,
  1927. edk2.ExtendedOpCode,
  1928. edk2.Data[1] as u16 * 100 + edk2.Data[0] as u16).unwrap();
  1929. done = true;
  1930. }
  1931. }
  1932. uefi_parser::IfrEdk2ExtendOpCode::Unknown(_) => {
  1933. }
  1934. }
  1935. }
  1936. }
  1937. uefi_parser::IFR_FRAMEWORK_GUID => {
  1938. if let Ok((_, edk)) =
  1939. uefi_parser::ifr_guid_edk(guid.Data)
  1940. {
  1941. match edk.ExtendedOpCode {
  1942. uefi_parser::IfrEdkExtendOpCode::OptionKey => {
  1943. write!(&mut text, "Guid: {}, ExtendedOpCode: {:?}, QuestionId: 0x{:X}, Data: {:?}",
  1944. guid.Guid,
  1945. edk.ExtendedOpCode,
  1946. edk.QuestionId,
  1947. edk.Data).unwrap();
  1948. done = true;
  1949. }
  1950. uefi_parser::IfrEdkExtendOpCode::VarEqName => {
  1951. if edk.Data.len() == 2 {
  1952. let name_id = edk.Data[1] as u16
  1953. * 100
  1954. + edk.Data[0] as u16;
  1955. write!(&mut text, "Guid: {}, ExtendedOpCode: {:?}, QuestionId: 0x{:X}, Name: \"{}\"",
  1956. guid.Guid,
  1957. edk.ExtendedOpCode,
  1958. edk.QuestionId,
  1959. strings_map.get(&name_id).unwrap_or(&String::from("InvalidId"))).unwrap();
  1960. done = true;
  1961. }
  1962. }
  1963. uefi_parser::IfrEdkExtendOpCode::Unknown(_) => {}
  1964. }
  1965. }
  1966. }
  1967. _ => {}
  1968. }
  1969. if !done {
  1970. write!(
  1971. &mut text,
  1972. "Guid: {}, Optional data: {:?}",
  1973. guid.Guid, guid.Data
  1974. )
  1975. .unwrap();
  1976. }
  1977. }
  1978. Err(e) => {
  1979. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1980. .unwrap();
  1981. println!("Guid parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1982. }
  1983. }
  1984. }
  1985. // 0x60: Security
  1986. uefi_parser::IfrOpcode::Security => {
  1987. match uefi_parser::ifr_security(operation.Data.unwrap()) {
  1988. Ok((_, sec)) => {
  1989. write!(&mut text, "Guid: {}", sec.Guid).unwrap();
  1990. }
  1991. Err(e) => {
  1992. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  1993. .unwrap();
  1994. println!("Security parse error: {e:?} at offset 0x{current_operation_offset:X}");
  1995. }
  1996. }
  1997. }
  1998. // 0x61: ModalTag
  1999. uefi_parser::IfrOpcode::ModalTag => {}
  2000. // 0x62: RefreshId
  2001. uefi_parser::IfrOpcode::RefreshId => {
  2002. match uefi_parser::ifr_refresh_id(operation.Data.unwrap()) {
  2003. Ok((_, rid)) => {
  2004. write!(&mut text, "Guid: {}", rid.Guid).unwrap();
  2005. }
  2006. Err(e) => {
  2007. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2008. .unwrap();
  2009. println!("RefreshId parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2010. }
  2011. }
  2012. }
  2013. // 0x63: WarningIf
  2014. uefi_parser::IfrOpcode::WarningIf => {
  2015. match uefi_parser::ifr_warning_if(operation.Data.unwrap()) {
  2016. Ok((_, warn)) => {
  2017. write!(
  2018. &mut text,
  2019. "Timeout: 0x{:X}, Warning: \"{}\"",
  2020. warn.Timeout,
  2021. strings_map
  2022. .get(&warn.WarningStringId)
  2023. .unwrap_or(&String::from("InvalidId"))
  2024. )
  2025. .unwrap();
  2026. }
  2027. Err(e) => {
  2028. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2029. .unwrap();
  2030. println!("WarningIf parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2031. }
  2032. }
  2033. }
  2034. // 0x64: Match2
  2035. uefi_parser::IfrOpcode::Match2 => {
  2036. match uefi_parser::ifr_match_2(operation.Data.unwrap()) {
  2037. Ok((_, m2)) => {
  2038. write!(&mut text, "Guid: {}", m2.Guid).unwrap();
  2039. }
  2040. Err(e) => {
  2041. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2042. .unwrap();
  2043. println!("Match2 parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2044. }
  2045. }
  2046. }
  2047. // Unknown operation
  2048. uefi_parser::IfrOpcode::Unknown(x) => {
  2049. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2050. .unwrap();
  2051. println!("IFR operation of unknown type 0x{x:X}");
  2052. }
  2053. }
  2054. current_operation_offset += operation.Length as usize;
  2055.  
  2056. if verbose_mode {
  2057. write!(&mut text, " {operation}").unwrap();
  2058. }
  2059.  
  2060. writeln!(&mut text).unwrap();
  2061. }
  2062. }
  2063. Err(e) => {
  2064. println!("IFR operations parse error: {e:?}");
  2065. }
  2066. }
  2067. }
  2068. }
  2069.  
  2070. // Write the result
  2071. let mut file_path = OsString::new();
  2072. file_path.push(path);
  2073. file_path.push(".");
  2074. file_path.push(form_package_index.to_string());
  2075. file_path.push(".");
  2076. file_path.push(string_package_index.to_string());
  2077. file_path.push(".");
  2078. file_path.push(string_package.language.clone());
  2079. file_path.push(".uefi.ifr.txt");
  2080. let mut output_file = OpenOptions::new()
  2081. .write(true)
  2082. .truncate(true)
  2083. .create(true)
  2084. .open(&file_path)
  2085. .unwrap_or_else(|_| panic!("Can't create output file {:?}", &file_path));
  2086. output_file
  2087. .write_all(&text)
  2088. .unwrap_or_else(|_| panic!("{}", "Can't write to output file {file_path:?}"));
  2089. }
  2090.  
  2091. //
  2092. // Framework HII parsing
  2093. //
  2094. fn framework_find_string_and_form_packages(data: &[u8]) -> (Vec<StringPackage>, Vec<FormPackage>) {
  2095. let mut strings = Vec::new(); // String-to-id maps for all found string packages
  2096.  
  2097. // Search for all string packages in the input file
  2098. let mut i = 0;
  2099. while i < data.len() {
  2100. if let Ok((_, candidate)) = framework_parser::hii_string_package_candidate(&data[i..]) {
  2101. if let Ok((_, package)) = framework_parser::hii_package(candidate) {
  2102. if let Ok((_, string_package)) =
  2103. framework_parser::hii_string_package(package.Data.unwrap())
  2104. {
  2105. let mut string_id_map = HashMap::new(); // Map of StringIds to strings
  2106. let mut language = String::from("Invalid");
  2107. for (current_string_index, string) in string_package.Strings.iter().enumerate() {
  2108. // This will always work in a properly formatted string package
  2109. if string_package.StringPointers[current_string_index]
  2110. == string_package.LanguageNameStringOffset
  2111. {
  2112. language = string_package.Strings[current_string_index].clone();
  2113. }
  2114.  
  2115. string_id_map.insert(current_string_index as u16, string.clone());
  2116. }
  2117.  
  2118. // Add string
  2119. let string = (i, candidate.len(), language, string_id_map);
  2120. strings.push(string);
  2121.  
  2122. i += candidate.len();
  2123. } else {
  2124. i += 1;
  2125. }
  2126. } else {
  2127. i += 1;
  2128. }
  2129. } else {
  2130. i += 1;
  2131. }
  2132. }
  2133.  
  2134. // No need to continue if there are no string packages found
  2135. if strings.is_empty() {
  2136. return (Vec::new(), Vec::new());
  2137. }
  2138.  
  2139. //
  2140. // Search for all form packages in the input file
  2141. //
  2142. let mut forms = Vec::new();
  2143. i = 0;
  2144. while i < data.len() {
  2145. if let Ok((_, candidate)) = framework_parser::hii_form_package_candidate(&data[i..]) {
  2146. if let Ok((_, package)) = framework_parser::hii_package(candidate) {
  2147. // Parse form package and obtain StringIds
  2148. let mut string_ids: Vec<u16> = Vec::new();
  2149. if let Ok((_, operations)) = framework_parser::ifr_operations(package.Data.unwrap()) {
  2150. //let mut current_operation: usize = 0;
  2151. for operation in &operations {
  2152. //current_operation += 1;
  2153. //println!("Operation #{}, OpCode: {:?}, Length 0x{:X}", current_operation, operation.OpCode, operation.Length);
  2154. match operation.OpCode {
  2155. framework_parser::IfrOpcode::Form => {
  2156. if let Ok((_, form)) =
  2157. framework_parser::ifr_form(operation.Data.unwrap())
  2158. {
  2159. string_ids.push(form.TitleStringId);
  2160. }
  2161. }
  2162. framework_parser::IfrOpcode::Subtitle => {
  2163. if let Ok((_, subtitile)) =
  2164. framework_parser::ifr_subtitle(operation.Data.unwrap())
  2165. {
  2166. string_ids.push(subtitile.SubtitleStringId);
  2167. }
  2168. }
  2169. framework_parser::IfrOpcode::Text => {
  2170. if let Ok((_, text)) =
  2171. framework_parser::ifr_text(operation.Data.unwrap())
  2172. {
  2173. string_ids.push(text.HelpStringId);
  2174. string_ids.push(text.TextStringId);
  2175. string_ids.push(text.TextTwoStringId);
  2176. }
  2177. }
  2178. framework_parser::IfrOpcode::Graphic => {}
  2179. framework_parser::IfrOpcode::OneOf => {
  2180. if let Ok((_, oneof)) =
  2181. framework_parser::ifr_one_of(operation.Data.unwrap())
  2182. {
  2183. string_ids.push(oneof.PromptStringId);
  2184. string_ids.push(oneof.HelpStringId);
  2185. }
  2186. }
  2187. framework_parser::IfrOpcode::CheckBox => {
  2188. if let Ok((_, checkbox)) =
  2189. framework_parser::ifr_check_box(operation.Data.unwrap())
  2190. {
  2191. string_ids.push(checkbox.PromptStringId);
  2192. string_ids.push(checkbox.HelpStringId);
  2193. }
  2194. }
  2195. framework_parser::IfrOpcode::Numeric => {
  2196. if let Ok((_, numeric)) =
  2197. framework_parser::ifr_numeric(operation.Data.unwrap())
  2198. {
  2199. string_ids.push(numeric.PromptStringId);
  2200. string_ids.push(numeric.HelpStringId);
  2201. }
  2202. }
  2203. framework_parser::IfrOpcode::Password => {
  2204. if let Ok((_, password)) =
  2205. framework_parser::ifr_password(operation.Data.unwrap())
  2206. {
  2207. string_ids.push(password.PromptStringId);
  2208. string_ids.push(password.HelpStringId);
  2209. }
  2210. }
  2211. framework_parser::IfrOpcode::OneOfOption => {
  2212. if let Ok((_, oneofoption)) =
  2213. framework_parser::ifr_one_of_option(operation.Data.unwrap())
  2214. {
  2215. string_ids.push(oneofoption.OptionStringId);
  2216. }
  2217. }
  2218. framework_parser::IfrOpcode::SuppressIf => {}
  2219. framework_parser::IfrOpcode::EndForm => {}
  2220. framework_parser::IfrOpcode::Hidden => {}
  2221. framework_parser::IfrOpcode::EndFormSet => {}
  2222. framework_parser::IfrOpcode::FormSet => {
  2223. if let Ok((_, formset)) =
  2224. framework_parser::ifr_form_set(operation.Data.unwrap())
  2225. {
  2226. string_ids.push(formset.TitleStringId);
  2227. string_ids.push(formset.HelpStringId);
  2228. }
  2229. }
  2230. framework_parser::IfrOpcode::Ref => {
  2231. if let Ok((_, rf)) =
  2232. framework_parser::ifr_ref(operation.Data.unwrap())
  2233. {
  2234. string_ids.push(rf.PromptStringId);
  2235. string_ids.push(rf.HelpStringId);
  2236. }
  2237. }
  2238. framework_parser::IfrOpcode::End => {}
  2239. framework_parser::IfrOpcode::InconsistentIf => {
  2240. if let Ok((_, incif)) =
  2241. framework_parser::ifr_inconsistent_if(operation.Data.unwrap())
  2242. {
  2243. string_ids.push(incif.PopupStringId);
  2244. }
  2245. }
  2246. framework_parser::IfrOpcode::EqIdVal => {}
  2247. framework_parser::IfrOpcode::EqIdId => {}
  2248. framework_parser::IfrOpcode::EqIdList => {}
  2249. framework_parser::IfrOpcode::And => {}
  2250. framework_parser::IfrOpcode::Or => {}
  2251. framework_parser::IfrOpcode::Not => {}
  2252. framework_parser::IfrOpcode::EndIf => {}
  2253. framework_parser::IfrOpcode::GrayOutIf => {}
  2254. framework_parser::IfrOpcode::Date => {
  2255. if let Ok((_, date)) =
  2256. framework_parser::ifr_date(operation.Data.unwrap())
  2257. {
  2258. string_ids.push(date.PromptStringId);
  2259. string_ids.push(date.HelpStringId);
  2260. }
  2261. }
  2262. framework_parser::IfrOpcode::Time => {
  2263. if let Ok((_, time)) =
  2264. framework_parser::ifr_time(operation.Data.unwrap())
  2265. {
  2266. string_ids.push(time.PromptStringId);
  2267. string_ids.push(time.HelpStringId);
  2268. }
  2269. }
  2270. framework_parser::IfrOpcode::String => {
  2271. if let Ok((_, str)) =
  2272. framework_parser::ifr_string(operation.Data.unwrap())
  2273. {
  2274. string_ids.push(str.PromptStringId);
  2275. string_ids.push(str.HelpStringId);
  2276. }
  2277. }
  2278. framework_parser::IfrOpcode::Label => {}
  2279. framework_parser::IfrOpcode::SaveDefaults => {
  2280. if let Ok((_, sd)) =
  2281. framework_parser::ifr_save_defaults(operation.Data.unwrap())
  2282. {
  2283. string_ids.push(sd.PromptStringId);
  2284. string_ids.push(sd.HelpStringId);
  2285. }
  2286. }
  2287. framework_parser::IfrOpcode::RestoreDefaults => {
  2288. if let Ok((_, rd)) =
  2289. framework_parser::ifr_restore_defaults(operation.Data.unwrap())
  2290. {
  2291. string_ids.push(rd.PromptStringId);
  2292. string_ids.push(rd.HelpStringId);
  2293. }
  2294. }
  2295. framework_parser::IfrOpcode::Banner => {
  2296. if let Ok((_, banner)) =
  2297. framework_parser::ifr_banner(operation.Data.unwrap())
  2298. {
  2299. string_ids.push(banner.TitleStringId);
  2300. }
  2301. }
  2302. framework_parser::IfrOpcode::Inventory => {
  2303. if let Ok((_, inv)) =
  2304. framework_parser::ifr_inventory(operation.Data.unwrap())
  2305. {
  2306. string_ids.push(inv.HelpStringId);
  2307. string_ids.push(inv.TextStringId);
  2308. string_ids.push(inv.TextTwoStringId);
  2309. }
  2310. }
  2311. framework_parser::IfrOpcode::EqVarVal => {}
  2312. framework_parser::IfrOpcode::OrderedList => {
  2313. if let Ok((_, ol)) =
  2314. framework_parser::ifr_ordered_list(operation.Data.unwrap())
  2315. {
  2316. string_ids.push(ol.PromptStringId);
  2317. string_ids.push(ol.HelpStringId);
  2318. }
  2319. }
  2320. framework_parser::IfrOpcode::VarStore => {}
  2321. framework_parser::IfrOpcode::VarStoreSelect => {}
  2322. framework_parser::IfrOpcode::VarStoreSelectPair => {}
  2323. framework_parser::IfrOpcode::True => {}
  2324. framework_parser::IfrOpcode::False => {}
  2325. framework_parser::IfrOpcode::Greater => {}
  2326. framework_parser::IfrOpcode::GreaterEqual => {}
  2327. framework_parser::IfrOpcode::OemDefined => {}
  2328. framework_parser::IfrOpcode::Oem => {}
  2329. framework_parser::IfrOpcode::NvAccessCommand => {}
  2330. framework_parser::IfrOpcode::Unknown(_) => {}
  2331. }
  2332. }
  2333. }
  2334.  
  2335. // Find min and max StringId, and the number of unique ones
  2336. string_ids.sort();
  2337. string_ids.dedup();
  2338. if !string_ids.is_empty() {
  2339. // Add the required information to forms
  2340. let form = (
  2341. i,
  2342. candidate.len(),
  2343. string_ids.len(),
  2344. *string_ids.first().unwrap(),
  2345. *string_ids.last().unwrap(),
  2346. );
  2347. forms.push(form);
  2348.  
  2349. i += candidate.len();
  2350. } else {
  2351. i += 1;
  2352. }
  2353. } else {
  2354. i += 1;
  2355. }
  2356. } else {
  2357. i += 1;
  2358. }
  2359. }
  2360.  
  2361. // No need to continue if no forms are found
  2362. if forms.is_empty() {
  2363. return (Vec::new(), Vec::new());
  2364. }
  2365.  
  2366. // Construct return value
  2367. let mut result_strings = Vec::new();
  2368. let mut result_forms = Vec::new();
  2369. for string in &strings {
  2370. result_strings.push(StringPackage {
  2371. offset: string.0,
  2372. length: string.1,
  2373. language: string.2.clone(),
  2374. string_id_map: string.3.clone(),
  2375. });
  2376. }
  2377. for form in &forms {
  2378. result_forms.push(FormPackage {
  2379. offset: form.0,
  2380. length: form.1,
  2381. used_strings: form.2,
  2382. min_string_id: form.3,
  2383. max_string_id: form.4,
  2384. });
  2385. }
  2386.  
  2387. (result_strings, result_forms)
  2388. }
  2389.  
  2390. fn framework_ifr_extract(
  2391. path: &OsStr,
  2392. data: &[u8],
  2393. form_package: &FormPackage,
  2394. form_package_index: usize,
  2395. string_package: &StringPackage,
  2396. string_package_index: usize,
  2397. verbose_mode: bool,
  2398. ) {
  2399. let mut text = Vec::new();
  2400. let strings_map = &string_package.string_id_map;
  2401.  
  2402. // Add version number and extraction mode
  2403. writeln!(&mut text, "Program version: {}, Extraction mode: Framework, SHA256: {}", VERSION.unwrap_or("0.0.0"), digest(data)).unwrap();
  2404.  
  2405. if let Ok((_, candidate)) =
  2406. framework_parser::hii_form_package_candidate(&data[form_package.offset..])
  2407. {
  2408. if let Ok((_, package)) = framework_parser::hii_package(candidate) {
  2409. // Parse form package and output its structure as human-readable strings
  2410. match framework_parser::ifr_operations(package.Data.unwrap()) {
  2411. Ok((_, operations)) => {
  2412. let mut scope_depth:usize = 0;
  2413. let mut current_operation_offset = form_package.offset + 6; // Header size of Framework HII form package is 6 bytes
  2414. for operation in &operations {
  2415. // Special case of operations that decrease scope_depth
  2416. if operation.OpCode == framework_parser::IfrOpcode::EndFormSet
  2417. || operation.OpCode == framework_parser::IfrOpcode::EndForm
  2418. {
  2419. scope_depth = scope_depth.saturating_sub(1);
  2420. }
  2421.  
  2422. if verbose_mode {
  2423. write!(
  2424. &mut text,
  2425. "0x{current_operation_offset:X}: "
  2426. )
  2427. .unwrap();
  2428. }
  2429.  
  2430. write!(
  2431. &mut text,
  2432. "{:\t<1$}{2:?} ",
  2433. "", scope_depth, operation.OpCode
  2434. )
  2435. .unwrap();
  2436.  
  2437. match operation.OpCode {
  2438. //0x01: Form
  2439. framework_parser::IfrOpcode::Form => {
  2440. match framework_parser::ifr_form(operation.Data.unwrap()) {
  2441. Ok((_, form)) => {
  2442. write!(
  2443. &mut text,
  2444. "Title: \"{}\", FormId: 0x{:X}",
  2445. strings_map
  2446. .get(&form.TitleStringId)
  2447. .unwrap_or(&String::from("InvalidId")),
  2448. form.FormId
  2449. )
  2450. .unwrap();
  2451. }
  2452. Err(e) => {
  2453. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2454. .unwrap();
  2455. println!("Form parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2456. }
  2457. }
  2458.  
  2459. scope_depth += 1;
  2460. }
  2461. //0x02: Subtitle
  2462. framework_parser::IfrOpcode::Subtitle => {
  2463. match framework_parser::ifr_subtitle(operation.Data.unwrap()) {
  2464. Ok((_, subtitle)) => {
  2465. write!(
  2466. &mut text,
  2467. "Subtitle: \"{}\"",
  2468. strings_map
  2469. .get(&subtitle.SubtitleStringId)
  2470. .unwrap_or(&String::from("InvalidId"))
  2471. )
  2472. .unwrap();
  2473. }
  2474. Err(e) => {
  2475. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2476. .unwrap();
  2477. println!("Subtitle parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2478. }
  2479. }
  2480. }
  2481. //0x03: Text
  2482. framework_parser::IfrOpcode::Text => {
  2483. match framework_parser::ifr_text(operation.Data.unwrap()) {
  2484. Ok((_, txt)) => {
  2485. write!(&mut text,
  2486. "Text: \"{}\", TextTwo: \"{}\", Help: \"{}\", Flags: 0x{:X}, Key: 0x{:X}",
  2487. strings_map.get(&txt.TextStringId).unwrap_or(&String::from("InvalidId")),
  2488. strings_map.get(&txt.TextTwoStringId).unwrap_or(&String::from("InvalidId")),
  2489. strings_map.get(&txt.HelpStringId).unwrap_or(&String::from("InvalidId")),
  2490. txt.Flags,
  2491. txt.Key
  2492. ).unwrap();
  2493. }
  2494. Err(e) => {
  2495. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2496. .unwrap();
  2497. println!("Text parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2498. }
  2499. }
  2500. }
  2501. //0x04: Graphic, should be unused
  2502. framework_parser::IfrOpcode::Graphic => {}
  2503. //0x05: OneOf
  2504. framework_parser::IfrOpcode::OneOf => {
  2505. match framework_parser::ifr_one_of(operation.Data.unwrap()) {
  2506. Ok((_, oneof)) => {
  2507. write!(
  2508. &mut text,
  2509. "Prompt: \"{}\", Help: \"{}\", QuestionId: 0x{:X}, Width: 0x{:X}",
  2510. strings_map
  2511. .get(&oneof.PromptStringId)
  2512. .unwrap_or(&String::from("InvalidId")),
  2513. strings_map
  2514. .get(&oneof.HelpStringId)
  2515. .unwrap_or(&String::from("InvalidId")),
  2516. oneof.QuestionId,
  2517. oneof.Width
  2518. )
  2519. .unwrap();
  2520. }
  2521. Err(e) => {
  2522. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2523. .unwrap();
  2524. println!("OneOf parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2525. }
  2526. }
  2527. }
  2528. //0x06: CheckBox
  2529. framework_parser::IfrOpcode::CheckBox => {
  2530. match framework_parser::ifr_check_box(operation.Data.unwrap()) {
  2531. Ok((_, checkbox)) => {
  2532. write!(&mut text,
  2533. "Prompt: \"{}\", Help: \"{}\", QuestionId: 0x{:X}, Width: 0x{:X}, Flags: 0x{:X}, Key: 0x{:X}",
  2534. strings_map.get(&checkbox.PromptStringId).unwrap_or(&String::from("InvalidId")),
  2535. strings_map.get(&checkbox.HelpStringId).unwrap_or(&String::from("InvalidId")),
  2536. checkbox.QuestionId,
  2537. checkbox.Width,
  2538. checkbox.Flags,
  2539. checkbox.Key
  2540. ).unwrap();
  2541. }
  2542. Err(e) => {
  2543. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2544. .unwrap();
  2545. println!("CheckBox parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2546. }
  2547. }
  2548. }
  2549. //0x07: Numeric
  2550. framework_parser::IfrOpcode::Numeric => {
  2551. match framework_parser::ifr_numeric(operation.Data.unwrap()) {
  2552. Ok((_, numeric)) => {
  2553. write!(&mut text,
  2554. "Prompt: \"{}\", Help: \"{}\", QuestionId: 0x{:X}, Width: 0x{:X}, Flags: 0x{:X}, Key: 0x{:X}, Min: 0x{:X}, Max: 0x{:X}, Step: 0x{:X}, Default: 0x{:X}",
  2555. strings_map.get(&numeric.PromptStringId).unwrap_or(&String::from("InvalidId")),
  2556. strings_map.get(&numeric.HelpStringId).unwrap_or(&String::from("InvalidId")),
  2557. numeric.QuestionId,
  2558. numeric.Width,
  2559. numeric.Flags,
  2560. numeric.Key,
  2561. numeric.Min,
  2562. numeric.Max,
  2563. numeric.Step,
  2564. numeric.Default
  2565. ).unwrap();
  2566. }
  2567. Err(e) => {
  2568. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2569. .unwrap();
  2570. println!("Numeric parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2571. }
  2572. }
  2573. }
  2574. //0x08: Password
  2575. framework_parser::IfrOpcode::Password => {
  2576. match framework_parser::ifr_password(operation.Data.unwrap()) {
  2577. Ok((_, password)) => {
  2578. write!(&mut text,
  2579. "Prompt: \"{}\", Help: \"{}\", QuestionId: 0x{:X}, Width: 0x{:X}, Flags: 0x{:X}, Key: 0x{:X}, MinSize: 0x{:X}, MaxSize: 0x{:X}, Encoding 0x{:X}",
  2580. strings_map.get(&password.PromptStringId).unwrap_or(&String::from("InvalidId")),
  2581. strings_map.get(&password.HelpStringId).unwrap_or(&String::from("InvalidId")),
  2582. password.QuestionId,
  2583. password.Width,
  2584. password.Flags,
  2585. password.Key,
  2586. password.MinSize,
  2587. password.MaxSize,
  2588. password.Encoding
  2589. ).unwrap();
  2590. }
  2591. Err(e) => {
  2592. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2593. .unwrap();
  2594. println!("Password parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2595. }
  2596. }
  2597. }
  2598. //0x09: OneOfOption
  2599. framework_parser::IfrOpcode::OneOfOption => {
  2600. match framework_parser::ifr_one_of_option(operation.Data.unwrap()) {
  2601. Ok((_, oneofopt)) => {
  2602. write!(
  2603. &mut text,
  2604. "Option: \"{}\", Value: 0x{:X}, Flags: 0x{:X}, Key: 0x{:X}",
  2605. strings_map
  2606. .get(&oneofopt.OptionStringId)
  2607. .unwrap_or(&String::from("InvalidId")),
  2608. oneofopt.Value,
  2609. oneofopt.Flags,
  2610. oneofopt.Key
  2611. )
  2612. .unwrap();
  2613. }
  2614. Err(e) => {
  2615. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2616. .unwrap();
  2617. println!("OneOfOption parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2618. }
  2619. }
  2620. }
  2621. //0x0A: SuppressIf
  2622. framework_parser::IfrOpcode::SuppressIf => {
  2623. match framework_parser::ifr_supress_if(operation.Data.unwrap()) {
  2624. Ok((_, supressif)) => {
  2625. write!(&mut text, "Flags: 0x{:X}", supressif.Flags)
  2626. .unwrap();
  2627. }
  2628. Err(e) => {
  2629. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2630. .unwrap();
  2631. println!("SupressIf parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2632. }
  2633. }
  2634. }
  2635. //0x0B: EndForm
  2636. framework_parser::IfrOpcode::EndForm => {}
  2637. //0x0C: Hidden
  2638. framework_parser::IfrOpcode::Hidden => {
  2639. match framework_parser::ifr_hidden(operation.Data.unwrap()) {
  2640. Ok((_, hidden)) => {
  2641. write!(
  2642. &mut text,
  2643. "Value: 0x{:X}, Key: 0x{:X}",
  2644. hidden.Value, hidden.Key
  2645. )
  2646. .unwrap();
  2647. }
  2648. Err(e) => {
  2649. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2650. .unwrap();
  2651. println!("Hidden parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2652. }
  2653. }
  2654. }
  2655. //0x0D: EndFormSet
  2656. framework_parser::IfrOpcode::EndFormSet => {}
  2657. //0x0E: FormSet
  2658. framework_parser::IfrOpcode::FormSet => {
  2659. match framework_parser::ifr_form_set(operation.Data.unwrap()) {
  2660. Ok((_, formset)) => {
  2661. write!(&mut text,
  2662. "Title: \"{}\", Help: \"{}\", Guid: {}, CallbackHandle: 0x{:X}, Class: 0x{:X}, SubClass: 0x{:X}, NvDataSize: 0x{:X}",
  2663. strings_map.get(&formset.TitleStringId).unwrap_or(&String::from("InvalidId")),
  2664. strings_map.get(&formset.HelpStringId).unwrap_or(&String::from("InvalidId")),
  2665. formset.Guid,
  2666. formset.CallbackHandle,
  2667. formset.Class,
  2668. formset.SubClass,
  2669. formset.NvDataSize
  2670. ).unwrap();
  2671. }
  2672. Err(e) => {
  2673. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2674. .unwrap();
  2675. println!("FromSet parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2676. }
  2677. }
  2678.  
  2679. scope_depth += 1;
  2680. }
  2681. //0x0F: Ref
  2682. framework_parser::IfrOpcode::Ref => {
  2683. match framework_parser::ifr_ref(operation.Data.unwrap()) {
  2684. Ok((_, rf)) => {
  2685. write!(&mut text,
  2686. "Prompt: \"{}\", Help: \"{}\", FormId: 0x{:X}, Flags: 0x{:X}, Key: 0x{:X}",
  2687. strings_map.get(&rf.PromptStringId).unwrap_or(&String::from("InvalidId")),
  2688. strings_map.get(&rf.HelpStringId).unwrap_or(&String::from("InvalidId")),
  2689. rf.FormId,
  2690. rf.Flags,
  2691. rf.Key
  2692. ).unwrap();
  2693. }
  2694. Err(e) => {
  2695. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2696. .unwrap();
  2697. println!("Ref parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2698. }
  2699. }
  2700. }
  2701. //0x10: End
  2702. framework_parser::IfrOpcode::End => {}
  2703. //0x11: InconsistentIf
  2704. framework_parser::IfrOpcode::InconsistentIf => {
  2705. match framework_parser::ifr_inconsistent_if(operation.Data.unwrap())
  2706. {
  2707. Ok((_, incif)) => {
  2708. write!(
  2709. &mut text,
  2710. "Popup: \"{}\", Flags: 0x{:X}",
  2711. strings_map
  2712. .get(&incif.PopupStringId)
  2713. .unwrap_or(&String::from("InvalidId")),
  2714. incif.Flags
  2715. )
  2716. .unwrap();
  2717. }
  2718. Err(e) => {
  2719. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2720. .unwrap();
  2721. println!("InconsistentIf parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2722. }
  2723. }
  2724. }
  2725. //0x12: EqIdVal
  2726. framework_parser::IfrOpcode::EqIdVal => {
  2727. match framework_parser::ifr_eq_id_val(operation.Data.unwrap()) {
  2728. Ok((_, eqidval)) => {
  2729. write!(
  2730. &mut text,
  2731. "QuestionId: 0x{:X}, Value: 0x{:X}",
  2732. eqidval.QuestionId, eqidval.Value
  2733. )
  2734. .unwrap();
  2735. }
  2736. Err(e) => {
  2737. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2738. .unwrap();
  2739. println!("EqIdVal parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2740. }
  2741. }
  2742. }
  2743. //0x13: EqIdId
  2744. framework_parser::IfrOpcode::EqIdId => {
  2745. match framework_parser::ifr_eq_id_id(operation.Data.unwrap()) {
  2746. Ok((_, eqidid)) => {
  2747. write!(
  2748. &mut text,
  2749. "QuestionId1: 0x{:X}, QuestionId2: 0x{:X}",
  2750. eqidid.QuestionId1, eqidid.QuestionId2
  2751. )
  2752. .unwrap();
  2753. }
  2754. Err(e) => {
  2755. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2756. .unwrap();
  2757. println!("EqIdId parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2758. }
  2759. }
  2760. }
  2761. //0x14: EqIdList
  2762. framework_parser::IfrOpcode::EqIdList => {
  2763. match framework_parser::ifr_eq_id_list(operation.Data.unwrap()) {
  2764. Ok((_, eqidlist)) => {
  2765. write!(
  2766. &mut text,
  2767. "QuestionId: 0x{:X}, Width: 0x{:X}, List: {{",
  2768. eqidlist.QuestionId, eqidlist.Width
  2769. )
  2770. .unwrap();
  2771. for item in &eqidlist.List {
  2772. write!(&mut text, " 0x{:X},", *item).unwrap();
  2773. }
  2774. write!(&mut text, " }}").unwrap();
  2775. }
  2776. Err(e) => {
  2777. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2778. .unwrap();
  2779. println!("EqIdList parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2780. }
  2781. }
  2782. }
  2783. //0x15: And
  2784. framework_parser::IfrOpcode::And => {}
  2785. //0x16: Or
  2786. framework_parser::IfrOpcode::Or => {}
  2787. //0x17: Not
  2788. framework_parser::IfrOpcode::Not => {}
  2789. //0x18: EndIf
  2790. framework_parser::IfrOpcode::EndIf => {}
  2791. //0x19: GrayOutIf
  2792. framework_parser::IfrOpcode::GrayOutIf => {
  2793. match framework_parser::ifr_grayout_if(operation.Data.unwrap()) {
  2794. Ok((_, grif)) => {
  2795. write!(&mut text, "Flags: 0x{:X}", grif.Flags).unwrap();
  2796. }
  2797. Err(e) => {
  2798. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2799. .unwrap();
  2800. println!("GrayoutIf parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2801. }
  2802. }
  2803. }
  2804. //0x1A: Date
  2805. framework_parser::IfrOpcode::Date => {
  2806. match framework_parser::ifr_date(operation.Data.unwrap()) {
  2807. Ok((_, date)) => {
  2808. write!(&mut text,
  2809. "Prompt: \"{}\", Help: \"{}\", QuestionId: 0x{:X}, Width: 0x{:X}, Flags: 0x{:X}, Key: 0x{:X}, Min: 0x{:X}, Max: 0x{:X}, Step: 0x{:X}, Default: 0x{:X}",
  2810. strings_map.get(&date.PromptStringId).unwrap_or(&String::from("InvalidId")),
  2811. strings_map.get(&date.HelpStringId).unwrap_or(&String::from("InvalidId")),
  2812. date.QuestionId,
  2813. date.Width,
  2814. date.Flags,
  2815. date.Key,
  2816. date.Min,
  2817. date.Max,
  2818. date.Step,
  2819. date.Default
  2820. ).unwrap();
  2821. }
  2822. Err(e) => {
  2823. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2824. .unwrap();
  2825. println!("Date parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2826. }
  2827. }
  2828. }
  2829. //0x1B: Time
  2830. framework_parser::IfrOpcode::Time => {
  2831. match framework_parser::ifr_time(operation.Data.unwrap()) {
  2832. Ok((_, time)) => {
  2833. write!(&mut text,
  2834. "Prompt: \"{}\", Help: \"{}\", QuestionId: 0x{:X}, Width: 0x{:X}, Flags: 0x{:X}, Key: 0x{:X}, Min: 0x{:X}, Max: 0x{:X}, Step: 0x{:X}, Default: 0x{:X}",
  2835. strings_map.get(&time.PromptStringId).unwrap_or(&String::from("InvalidId")),
  2836. strings_map.get(&time.HelpStringId).unwrap_or(&String::from("InvalidId")),
  2837. time.QuestionId,
  2838. time.Width,
  2839. time.Flags,
  2840. time.Key,
  2841. time.Min,
  2842. time.Max,
  2843. time.Step,
  2844. time.Default
  2845. ).unwrap();
  2846. }
  2847. Err(e) => {
  2848. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2849. .unwrap();
  2850. println!("Time parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2851. }
  2852. }
  2853. }
  2854. //0x1C: String
  2855. framework_parser::IfrOpcode::String => {
  2856. match framework_parser::ifr_string(operation.Data.unwrap()) {
  2857. Ok((_, str)) => {
  2858. write!(&mut text,
  2859. "Prompt: \"{}\", Help: \"{}\", QuestionId: 0x{:X}, Width: 0x{:X}, Flags: 0x{:X}, Key: 0x{:X}, MinSize: 0x{:X}, MaxSize: 0x{:X}",
  2860. strings_map.get(&str.PromptStringId).unwrap_or(&String::from("InvalidId")),
  2861. strings_map.get(&str.HelpStringId).unwrap_or(&String::from("InvalidId")),
  2862. str.QuestionId,
  2863. str.Width,
  2864. str.Flags,
  2865. str.Key,
  2866. str.MinSize,
  2867. str.MaxSize
  2868. ).unwrap();
  2869. }
  2870. Err(e) => {
  2871. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2872. .unwrap();
  2873. println!("String parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2874. }
  2875. }
  2876. }
  2877. //0x1D: Label
  2878. framework_parser::IfrOpcode::Label => {
  2879. match framework_parser::ifr_label(operation.Data.unwrap()) {
  2880. Ok((_, label)) => {
  2881. write!(&mut text, "LabelId: 0x{:X}", label.LabelId)
  2882. .unwrap();
  2883. }
  2884. Err(e) => {
  2885. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2886. .unwrap();
  2887. println!("Label parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2888. }
  2889. }
  2890. }
  2891. //0x1E: SaveDefaults
  2892. framework_parser::IfrOpcode::SaveDefaults => {
  2893. match framework_parser::ifr_save_defaults(operation.Data.unwrap()) {
  2894. Ok((_, sd)) => {
  2895. write!(&mut text,
  2896. "Prompt: \"{}\", Help: \"{}\", FormId: 0x{:X}, Flags: 0x{:X}, Key: 0x{:X}",
  2897. strings_map.get(&sd.PromptStringId).unwrap_or(&String::from("InvalidId")),
  2898. strings_map.get(&sd.HelpStringId).unwrap_or(&String::from("InvalidId")),
  2899. sd.FormId,
  2900. sd.Flags,
  2901. sd.Key
  2902. ).unwrap();
  2903. }
  2904. Err(e) => {
  2905. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2906. .unwrap();
  2907. println!("SaveDefaults parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2908. }
  2909. }
  2910. }
  2911. //0x1F: RestoreDefaults
  2912. framework_parser::IfrOpcode::RestoreDefaults => {
  2913. match framework_parser::ifr_restore_defaults(
  2914. operation.Data.unwrap(),
  2915. ) {
  2916. Ok((_, rd)) => {
  2917. write!(&mut text,
  2918. "Prompt: \"{}\", Help: \"{}\", FormId: 0x{:X}, Flags: 0x{:X}, Key: 0x{:X}",
  2919. strings_map.get(&rd.PromptStringId).unwrap_or(&String::from("InvalidId")),
  2920. strings_map.get(&rd.HelpStringId).unwrap_or(&String::from("InvalidId")),
  2921. rd.FormId,
  2922. rd.Flags,
  2923. rd.Key
  2924. ).unwrap();
  2925. }
  2926. Err(e) => {
  2927. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2928. .unwrap();
  2929. println!("RestoreDefaults parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2930. }
  2931. }
  2932. }
  2933. //0x20: Banner
  2934. framework_parser::IfrOpcode::Banner => {
  2935. match framework_parser::ifr_banner(operation.Data.unwrap()) {
  2936. Ok((_, banner)) => {
  2937. write!(
  2938. &mut text,
  2939. "Title: \"{}\", LineNumber: 0x{:X}, Alignment: 0x{:X}",
  2940. strings_map
  2941. .get(&banner.TitleStringId)
  2942. .unwrap_or(&String::from("InvalidId")),
  2943. banner.LineNumber,
  2944. banner.Alignment
  2945. )
  2946. .unwrap();
  2947. }
  2948. Err(e) => {
  2949. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2950. .unwrap();
  2951. println!("Banner parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2952. }
  2953. }
  2954. }
  2955. //0x21: Inventory
  2956. framework_parser::IfrOpcode::Inventory => {
  2957. match framework_parser::ifr_inventory(operation.Data.unwrap()) {
  2958. Ok((_, inventory)) => {
  2959. write!(
  2960. &mut text,
  2961. "Text: \"{}\", TextTwo: \"{}\", Help: \"{}\"",
  2962. strings_map
  2963. .get(&inventory.TextStringId)
  2964. .unwrap_or(&String::from("InvalidId")),
  2965. strings_map
  2966. .get(&inventory.TextTwoStringId)
  2967. .unwrap_or(&String::from("InvalidId")),
  2968. strings_map
  2969. .get(&inventory.HelpStringId)
  2970. .unwrap_or(&String::from("InvalidId"))
  2971. )
  2972. .unwrap();
  2973. }
  2974. Err(e) => {
  2975. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2976. .unwrap();
  2977. println!("Inventory parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2978. }
  2979. }
  2980. }
  2981. //0x22: EqVarVal
  2982. framework_parser::IfrOpcode::EqVarVal => {
  2983. match framework_parser::ifr_eq_var_val(operation.Data.unwrap()) {
  2984. Ok((_, eqvarval)) => {
  2985. write!(
  2986. &mut text,
  2987. "VariableId: 0x{:X}, Value: 0x{:X}",
  2988. eqvarval.VariableId, eqvarval.Value
  2989. )
  2990. .unwrap();
  2991. }
  2992. Err(e) => {
  2993. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  2994. .unwrap();
  2995. println!("EqVarVal parse error: {e:?} at offset 0x{current_operation_offset:X}");
  2996. }
  2997. }
  2998. }
  2999. //0x23: OrderedList
  3000. framework_parser::IfrOpcode::OrderedList => {
  3001. match framework_parser::ifr_ordered_list(operation.Data.unwrap()) {
  3002. Ok((_, ol)) => {
  3003. write!(&mut text,
  3004. "Prompt: \"{}\", Help: \"{}\", QuestionId: 0x{:X}, MaxEntries: 0x{:X}",
  3005. strings_map.get(&ol.PromptStringId).unwrap_or(&String::from("InvalidId")),
  3006. strings_map.get(&ol.HelpStringId).unwrap_or(&String::from("InvalidId")),
  3007. ol.QuestionId,
  3008. ol.MaxEntries
  3009. ).unwrap();
  3010. }
  3011. Err(e) => {
  3012. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  3013. .unwrap();
  3014. println!("OrderedList parse error: {e:?} at offset 0x{current_operation_offset:X}");
  3015. }
  3016. }
  3017. }
  3018. //0x24: VarStore
  3019. framework_parser::IfrOpcode::VarStore => {
  3020. match framework_parser::ifr_var_store(operation.Data.unwrap()) {
  3021. Ok((_, vs)) => {
  3022. write!(
  3023. &mut text,
  3024. "VarstoreId: 0x{:X}, Guid: {}, Name: \"{}\", Size: 0x{:X}",
  3025. vs.VarStoreId, vs.Guid, vs.Name, vs.Size
  3026. )
  3027. .unwrap();
  3028. }
  3029. Err(e) => {
  3030. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  3031. .unwrap();
  3032. println!("VarStore parse error: {e:?} at offset 0x{current_operation_offset:X}");
  3033. }
  3034. }
  3035. }
  3036. //0x25: VarStoreSelect
  3037. framework_parser::IfrOpcode::VarStoreSelect => {
  3038. match framework_parser::ifr_var_store_select(
  3039. operation.Data.unwrap(),
  3040. ) {
  3041. Ok((_, vss)) => {
  3042. write!(&mut text, "VarstoreId: 0x{:X}", vss.VarStoreId)
  3043. .unwrap();
  3044. }
  3045. Err(e) => {
  3046. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  3047. .unwrap();
  3048. println!("VarStoreSelect parse error: {e:?} at offset 0x{current_operation_offset:X}");
  3049. }
  3050. }
  3051. }
  3052. //0x26: VarStoreSelectPair
  3053. framework_parser::IfrOpcode::VarStoreSelectPair => {
  3054. match framework_parser::ifr_var_store_select_pair(
  3055. operation.Data.unwrap(),
  3056. ) {
  3057. Ok((_, vssp)) => {
  3058. write!(
  3059. &mut text,
  3060. "VarstoreId: 0x{:X}, SecondaryVarStoreId: 0x{:X}",
  3061. vssp.VarStoreId, vssp.SecondaryVarStoreId
  3062. )
  3063. .unwrap();
  3064. }
  3065. Err(e) => {
  3066. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  3067. .unwrap();
  3068. println!("VarStoreSelectPair parse error: {e:?} at offset 0x{current_operation_offset:X}");
  3069. }
  3070. }
  3071. }
  3072. //0x27: True
  3073. framework_parser::IfrOpcode::True => {}
  3074. //0x28: False
  3075. framework_parser::IfrOpcode::False => {}
  3076. //0x29: Greater
  3077. framework_parser::IfrOpcode::Greater => {}
  3078. //0x2A: GreaterEqual
  3079. framework_parser::IfrOpcode::GreaterEqual => {}
  3080. //0x2B: OemDefined
  3081. framework_parser::IfrOpcode::OemDefined => {}
  3082. //0xFE: Oem
  3083. framework_parser::IfrOpcode::Oem => {}
  3084. //0xFF: NvAccessCommand
  3085. framework_parser::IfrOpcode::NvAccessCommand => {}
  3086. //Unknown operation
  3087. framework_parser::IfrOpcode::Unknown(x) => {
  3088. write!(&mut text, "RawData: {:02X?}", operation.Data.unwrap())
  3089. .unwrap();
  3090. println!("IFR operation of unknown type 0x{x:X}");
  3091. }
  3092. }
  3093. current_operation_offset += operation.Length as usize;
  3094.  
  3095. if verbose_mode {
  3096. write!(&mut text, " {operation}").unwrap();
  3097. }
  3098.  
  3099. writeln!(&mut text).unwrap();
  3100. }
  3101. }
  3102. Err(e) => {
  3103. println!("IFR operations parse error: {e:?}");
  3104. }
  3105. }
  3106. }
  3107. }
  3108.  
  3109. // Write the result
  3110. let mut file_path = OsString::new();
  3111. file_path.push(path);
  3112. file_path.push(".");
  3113. file_path.push(form_package_index.to_string());
  3114. file_path.push(".");
  3115. file_path.push(string_package_index.to_string());
  3116. file_path.push(".");
  3117. file_path.push(string_package.language.clone());
  3118. file_path.push(".framework.ifr.txt");
  3119. let mut output_file = OpenOptions::new()
  3120. .write(true)
  3121. .truncate(true)
  3122. .create(true)
  3123. .open(&file_path)
  3124. .unwrap_or_else(|_| panic!("Can't create output file {:?}", &file_path));
  3125. output_file
  3126. .write_all(&text)
  3127. .unwrap_or_else(|_| panic!("{}", "Can't write to output file {file_path:?}"));
  3128. }
  3129.  
  3130. fn main() {
  3131. // Obtain program arguments
  3132. let mut args = std::env::args_os();
  3133.  
  3134. // Check if we have none
  3135. if args.len() <= 1 {
  3136. println!("
  3137. IFRExtractor RS v{} - extracts HII string and form packages in UEFI Internal Form Representation (IFR) from a binary file into human-readable text
  3138. Usage: ifrextractor file.bin list - list all string and form packages in the input file
  3139. ifrextractor file.bin single <form_package_number> <string_package_number> - extract a given form package using a given string package (use list command to obtain the package numbers)
  3140. ifrextractor file.bin lang <language> - extract all form packages using all string packages in a given language
  3141. ifrextractor file.bin all - extract all form package using all string packages
  3142. ifrextractor file.bin verbose - extract all form packages using string packages in English, add raw bytes to all opcodes
  3143. ifrextractor file.bin - default extraction mode (only try string packages in English)",
  3144. VERSION.unwrap_or("0.0.0"));
  3145. std::process::exit(1);
  3146. }
  3147.  
  3148. // The only mandatory argument is a path to input file
  3149. let arg = args.nth(1).expect("Failed to obtain file path");
  3150. let path = Path::new(&arg);
  3151.  
  3152. // Open input file
  3153. let mut file = File::open(path).expect("Can't open input file");
  3154.  
  3155. // Read the whole file as binary data
  3156. let mut data = Vec::new();
  3157. file.read_to_end(&mut data).expect("Can't read input file");
  3158.  
  3159. // Find all string and form packages in UEFI HII format
  3160. let (uefi_strings, uefi_forms) = uefi_find_string_and_form_packages(&data);
  3161.  
  3162. // Find all string and form packages in Framework HII format
  3163. let (framework_strings, framework_forms) = framework_find_string_and_form_packages(&data);
  3164.  
  3165. // Exit early if nothing is found
  3166. if uefi_strings.is_empty() && uefi_forms.is_empty() && framework_strings.is_empty() && framework_forms.is_empty() {
  3167. println!("No IFR data found");
  3168. std::process::exit(2);
  3169. }
  3170.  
  3171. // Parse the other arguments
  3172. let collected_args: Vec<String> = env::args().collect();
  3173. let mut found = false;
  3174. if collected_args.len() == 2 {
  3175. // Extract all form packages using all string packages with english language
  3176. if !uefi_strings.is_empty() && !uefi_forms.is_empty() {
  3177. println!("Extracting all UEFI HII form packages using en-US UEFI HII string packages");
  3178. for (form_num, form) in uefi_forms.iter().enumerate() {
  3179. for (string_num, string) in uefi_strings.iter().enumerate() {
  3180. if string.language == "en-US" {
  3181. found = true;
  3182. uefi_ifr_extract(
  3183. path.as_os_str(),
  3184. &data,
  3185. form,
  3186. form_num,
  3187. string,
  3188. string_num,
  3189. false
  3190. );
  3191. }
  3192. }
  3193. }
  3194. if !found {
  3195. println!("No en-US UEFI HII string packages found");
  3196. }
  3197. }
  3198. if !framework_strings.is_empty() && !framework_forms.is_empty() {
  3199. println!("Extracting all Framework HII form packages using eng Framework HII string packages");
  3200. for (form_num, form) in framework_forms.iter().enumerate() {
  3201. for (string_num, string) in framework_strings.iter().enumerate() {
  3202. if string.language == "eng" {
  3203. found = true;
  3204. framework_ifr_extract(
  3205. path.as_os_str(),
  3206. &data,
  3207. form,
  3208. form_num,
  3209. string,
  3210. string_num,
  3211. false
  3212. );
  3213. }
  3214. }
  3215. }
  3216. if !found {
  3217. println!("No eng Framework HII string packages found");
  3218. }
  3219. }
  3220. if !found {
  3221. println!("Not enough IFR data found to complete extraction");
  3222. std::process::exit(3);
  3223. }
  3224. } else if collected_args.len() == 3 && collected_args[2] == "verbose" {
  3225. // Extract all form packages using all string packages with english language in verbose mode
  3226. if !uefi_strings.is_empty() && !uefi_forms.is_empty() {
  3227. println!("Extracting all UEFI HII form packages using en-US UEFI HII string packages in verbose mode");
  3228. for (form_num, form) in uefi_forms.iter().enumerate() {
  3229. for (string_num, string) in uefi_strings.iter().enumerate() {
  3230. if string.language == "en-US" {
  3231. found = true;
  3232. uefi_ifr_extract(
  3233. path.as_os_str(),
  3234. &data,
  3235. form,
  3236. form_num,
  3237. string,
  3238. string_num,
  3239. true
  3240. );
  3241. }
  3242. }
  3243. }
  3244. if !found {
  3245. println!("No en-US UEFI HII string packages found");
  3246. }
  3247. }
  3248. if !framework_strings.is_empty() && !framework_forms.is_empty() {
  3249. println!("Extracting all Framework HII form packages using eng Framework HII string packages in vebose mode");
  3250. for (form_num, form) in framework_forms.iter().enumerate() {
  3251. for (string_num, string) in framework_strings.iter().enumerate() {
  3252. if string.language == "eng" {
  3253. found = true;
  3254. framework_ifr_extract(
  3255. path.as_os_str(),
  3256. &data,
  3257. form,
  3258. form_num,
  3259. string,
  3260. string_num,
  3261. true
  3262. );
  3263. }
  3264. }
  3265. }
  3266. if !found {
  3267. println!("No eng Framework HII string packages found");
  3268. }
  3269. }
  3270. if !found {
  3271. println!("Not enough IFR data found to complete extraction");
  3272. std::process::exit(3);
  3273. }
  3274. } else if collected_args.len() == 3 && collected_args[2] == "list" {
  3275. if !uefi_forms.is_empty() {
  3276. println!("UEFI HII form packages:");
  3277. for (form_num, form) in uefi_forms.iter().enumerate() {
  3278. println!("Index: {}, Offset: 0x{:X}, Length: 0x{:X}, Used strings: {}, Min StringId: 0x{:X}, Max StringId: 0x{:X}",
  3279. form_num, form.offset, form.length, form.used_strings, form.min_string_id, form.max_string_id);
  3280. }
  3281. } else {
  3282. println!("UEFI HII form packages: none");
  3283. }
  3284.  
  3285. if !uefi_strings.is_empty() {
  3286. println!("UEFI HII string packages:");
  3287. for (string_num, string) in uefi_strings.iter().enumerate() {
  3288. println!(
  3289. "Index: {}, Offset: 0x{:X}, Length: 0x{:X}, Language: {}, Total strings: {}",
  3290. string_num,
  3291. string.offset,
  3292. string.length,
  3293. string.language,
  3294. string.string_id_map.len()
  3295. );
  3296. }
  3297. } else {
  3298. println!("UEFI HII string packages: none");
  3299. }
  3300.  
  3301. if !framework_forms.is_empty() {
  3302. println!("Framework HII form packages:");
  3303. for (form_num, form) in framework_forms.iter().enumerate() {
  3304. println!("Index: {}, Offset: 0x{:X}, Length: 0x{:X}, Used strings: {}, Min StringId: 0x{:X}, Max StringId: 0x{:X}",
  3305. form_num, form.offset, form.length, form.used_strings, form.min_string_id, form.max_string_id);
  3306. }
  3307. } else {
  3308. println!("Framework HII form packages: none");
  3309. }
  3310.  
  3311. if !framework_strings.is_empty() {
  3312. println!("Framework HII string packages:");
  3313. for (string_num, string) in framework_strings.iter().enumerate() {
  3314. println!(
  3315. "Index: {}, Offset: 0x{:X}, Length: 0x{:X}, Language: {}, Total strings: {}",
  3316. string_num,
  3317. string.offset,
  3318. string.length,
  3319. string.language,
  3320. string.string_id_map.len()
  3321. );
  3322. }
  3323. } else {
  3324. println!("Framework HII string packages: none");
  3325. }
  3326. } else if collected_args.len() == 3 && collected_args[2] == "all" {
  3327. if !uefi_strings.is_empty() && !uefi_forms.is_empty() {
  3328. println!("Extracting all UEFI HII form packages using all UEFI HII string packages");
  3329. for (form_num, form) in uefi_forms.iter().enumerate() {
  3330. for (string_num, string) in uefi_strings.iter().enumerate() {
  3331. found = true;
  3332. uefi_ifr_extract(path.as_os_str(), &data, form, form_num, string, string_num, false);
  3333. }
  3334. }
  3335. }
  3336. if !framework_strings.is_empty() && !framework_forms.is_empty() {
  3337. println!("Extracting all Framework HII form packages using all Framework HII string packages");
  3338. for (form_num, form) in framework_forms.iter().enumerate() {
  3339. for (string_num, string) in framework_strings.iter().enumerate() {
  3340. found = true;
  3341. framework_ifr_extract(
  3342. path.as_os_str(),
  3343. &data,
  3344. form,
  3345. form_num,
  3346. string,
  3347. string_num,
  3348. false
  3349. );
  3350. }
  3351. }
  3352. }
  3353. if !found {
  3354. println!("Not enough IFR data found to complete extraction");
  3355. std::process::exit(3);
  3356. }
  3357. } else if collected_args.len() == 4 && collected_args[2] == "lang" {
  3358. // Extract all form packages using all string packages in a given language
  3359. if !uefi_strings.is_empty() && !uefi_forms.is_empty() {
  3360. println!("Extracting all UEFI HII form packages using {} string packages", collected_args[3]);
  3361. for (form_num, form) in uefi_forms.iter().enumerate() {
  3362. for (string_num, string) in uefi_strings.iter().enumerate() {
  3363. if string.language == collected_args[3] {
  3364. found = true;
  3365. uefi_ifr_extract(
  3366. path.as_os_str(),
  3367. &data,
  3368. form,
  3369. form_num,
  3370. string,
  3371. string_num,
  3372. false
  3373. );
  3374. }
  3375. }
  3376. }
  3377. if !found {
  3378. println!("No {} UEFI HII string packages found", collected_args[3]);
  3379. }
  3380. }
  3381. if !framework_strings.is_empty() && !framework_forms.is_empty() {
  3382. println!("Extracting all Framework HII form packages using {} Framework HII string packages", collected_args[3]);
  3383. for (form_num, form) in framework_forms.iter().enumerate() {
  3384. for (string_num, string) in framework_strings.iter().enumerate() {
  3385. if string.language == collected_args[3] {
  3386. found = true;
  3387. framework_ifr_extract(
  3388. path.as_os_str(),
  3389. &data,
  3390. form,
  3391. form_num,
  3392. string,
  3393. string_num,
  3394. false
  3395. );
  3396. }
  3397. }
  3398. }
  3399. if !found {
  3400. println!("No {} Framework HII string packages found", collected_args[3]);
  3401. }
  3402. }
  3403. if !found {
  3404. println!("Not enough IFR data found to complete extraction");
  3405. std::process::exit(3);
  3406. }
  3407. } else if collected_args.len() == 5 && collected_args[2] == "single" {
  3408. if !uefi_strings.is_empty() && !uefi_forms.is_empty() {
  3409. // Extract the exact single combination
  3410. let form_package_num: usize = collected_args[3]
  3411. .parse()
  3412. .expect("Can't parse form_package_number argument as a number");
  3413. if form_package_num > uefi_forms.len() - 1 {
  3414. println!("Provided form_package_number argument {} is out of range [0..{}]", form_package_num, uefi_forms.len() - 1);
  3415. std::process::exit(4);
  3416. }
  3417. let string_package_num: usize = collected_args[4]
  3418. .parse()
  3419. .expect("Can't parse string_package_number argument as a number");
  3420. if string_package_num > uefi_strings.len() - 1 {
  3421. println!("Provided string_package_number argument {} is out of range [0..{}]", string_package_num, uefi_strings.len() - 1);
  3422. std::process::exit(4);
  3423. }
  3424. println!("Extracting UEFI HII form package #{form_package_num} using UEFI HII string package #{string_package_num}");
  3425. uefi_ifr_extract(
  3426. path.as_os_str(),
  3427. &data,
  3428. &uefi_forms[form_package_num],
  3429. form_package_num,
  3430. &uefi_strings[string_package_num],
  3431. string_package_num,
  3432. false
  3433. );
  3434. found = true;
  3435. }
  3436. if !framework_strings.is_empty() && !framework_forms.is_empty() {
  3437. let form_package_num: usize = collected_args[3]
  3438. .parse()
  3439. .expect("Can't parse form_package_number argument as a number");
  3440. if form_package_num > framework_forms.len() - 1 {
  3441. println!("Provided form_package_number argument {} is out of range [0..{}]", form_package_num, uefi_forms.len() - 1);
  3442. std::process::exit(4);
  3443. }
  3444. let string_package_num: usize = collected_args[4]
  3445. .parse()
  3446. .expect("Can't parse string_package_number argument as a number");
  3447. if string_package_num > framework_strings.len() - 1 {
  3448. println!("Provided string_package_number argument {} is out of range [0..{}]", string_package_num, uefi_strings.len() - 1);
  3449. std::process::exit(4);
  3450. }
  3451. println!("Extracting Framework HII form package #{form_package_num} using Framework HII string package #{string_package_num}");
  3452. framework_ifr_extract(
  3453. path.as_os_str(),
  3454. &data,
  3455. &framework_forms[form_package_num],
  3456. form_package_num,
  3457. &framework_strings[string_package_num],
  3458. string_package_num,
  3459. false
  3460. );
  3461. found = true;
  3462. }
  3463. if !found {
  3464. println!("Not enough IFR data found to complete extraction");
  3465. std::process::exit(3);
  3466. }
  3467. } else {
  3468. println!("Invalid arguments");
  3469. std::process::exit(4);
  3470. }
  3471. }
  3472.  
Advertisement
Add Comment
Please, Sign In to add comment