zfi_macros/
lib.rs

1use self::entry::parse_entry;
2use self::string::parse_str;
3use crate::entry::{EntryDebug, EntryOptions};
4use proc_macro::TokenStream;
5use syn::{parse_macro_input, Error, ItemFn, LitStr};
6
7mod entry;
8mod string;
9
10/// Define the entry of EFI program, automatically import `alloc` crate, generate `global_allocator`
11/// and `panic_handler`.
12///
13/// This macro will not enable the debug writer by default. To enable the debug writer, specify one
14/// of the following options:
15///
16/// - `debug_extension`: A string literal that specify the extension of the log file that will be
17///   created next to the application image. If you specify `#[zfi::main(debug_extension = "log")]`,
18///   ZFI will create a file `PATH\TO\YOUR\APP.EFI.log`.
19/// - `debug_writer`: A function identifier with zero parameter that return
20///   `alloc::boxed::Box<dyn core::fmt::Write>`.
21///
22/// Other available options:
23///
24/// - `no_ph`: Do not generate `panic_handler`.
25#[proc_macro_attribute]
26pub fn main(arg: TokenStream, item: TokenStream) -> TokenStream {
27    let item = parse_macro_input!(item as ItemFn);
28    let mut options = EntryOptions::default();
29    let parser = syn::meta::parser(|m| {
30        if m.path.is_ident("debug_extension") {
31            options.debug = Some(EntryDebug::Extension(m.value()?.parse()?));
32        } else if m.path.is_ident("debug_writer") {
33            options.debug = Some(EntryDebug::Writer(m.value()?.parse()?));
34        } else if m.path.is_ident("no_ph") {
35            options.no_ph = true;
36        } else {
37            return Err(m.error("unknown option"));
38        }
39
40        Ok(())
41    });
42
43    parse_macro_input!(arg with parser);
44
45    parse_entry(item, options)
46        .unwrap_or_else(Error::into_compile_error)
47        .into()
48}
49
50/// Construct an EFI string from a Rust string literal.
51#[proc_macro]
52pub fn str(arg: TokenStream) -> TokenStream {
53    let arg = parse_macro_input!(arg as LitStr);
54
55    parse_str(arg)
56        .unwrap_or_else(Error::into_compile_error)
57        .into()
58}