12
12
//! **PLEASE NOTE** that these helpers are meant for the pre exit boot service
13
13
//! epoch.
14
14
15
- #[ cfg( feature = "logger" ) ]
16
- pub mod logger;
17
-
18
- #[ cfg( feature = "panic_handler" ) ]
19
- use cfg_if:: cfg_if;
15
+ use crate :: prelude:: { Boot , SystemTable } ;
16
+ use crate :: Event ;
17
+ use crate :: Result ;
18
+ use crate :: StatusExt ;
20
19
use core:: ffi:: c_void;
21
- use core:: fmt :: Write ;
22
- use core:: ptr:: { self , NonNull } ;
20
+ use core:: ptr ;
21
+ use core:: ptr:: NonNull ;
23
22
use core:: sync:: atomic:: { AtomicPtr , Ordering } ;
24
- use log:: Log ;
25
- use uefi:: allocator:: Allocator ;
26
- use uefi:: table:: boot:: { EventType , Tpl } ;
27
- use uefi:: table:: { Boot , SystemTable } ;
28
- use uefi:: { Event , Result , Status , StatusExt } ;
23
+ #[ doc( hidden) ]
24
+ pub use println:: _print;
25
+ use uefi_raw:: table:: boot:: { EventType , Tpl } ;
26
+ use uefi_raw:: Status ;
29
27
30
- #[ cfg_attr( feature = "global_allocator" , global_allocator) ]
31
- static ALLOCATOR : Allocator = Allocator ;
28
+ #[ cfg( feature = "global_allocator" ) ]
29
+ mod global_allocator;
30
+ #[ cfg( feature = "logger" ) ]
31
+ mod logger;
32
+ #[ cfg( feature = "panic_handler" ) ]
33
+ mod panic_handler;
34
+ mod println;
32
35
33
36
/// Reference to the system table.
34
37
///
35
38
/// This table is only fully safe to use until UEFI boot services have been exited.
36
39
/// After that, some fields and methods are unsafe to use, see the documentation of
37
40
/// UEFI's ExitBootServices entry point for more details.
38
- static SYSTEM_TABLE : AtomicPtr < c_void > = AtomicPtr :: new ( ptr:: null_mut ( ) ) ;
39
-
40
- /// Global logger object
41
- #[ cfg( feature = "logger" ) ]
42
- static LOGGER : logger:: Logger = logger:: Logger :: new ( ) ;
41
+ static SYSTEM_TABLE : AtomicPtr < c_void > = AtomicPtr :: new ( core:: ptr:: null_mut ( ) ) ;
43
42
44
43
#[ must_use]
45
44
fn system_table_opt ( ) -> Option < SystemTable < Boot > > {
@@ -62,7 +61,7 @@ fn system_table_opt() -> Option<SystemTable<Boot>> {
62
61
///
63
62
/// The returned pointer is only valid until boot services are exited.
64
63
#[ must_use]
65
- pub fn system_table ( ) -> SystemTable < Boot > {
64
+ fn system_table ( ) -> SystemTable < Boot > {
66
65
system_table_opt ( ) . expect ( "The system table handle is not available" )
67
66
}
68
67
@@ -87,7 +86,7 @@ pub fn init(st: &mut SystemTable<Boot>) -> Result<Option<Event>> {
87
86
// Setup logging and memory allocation
88
87
89
88
#[ cfg( feature = "logger" ) ]
90
- init_logger ( st) ;
89
+ logger :: init ( st) ;
91
90
92
91
uefi:: allocator:: init ( st) ;
93
92
@@ -104,64 +103,6 @@ pub fn init(st: &mut SystemTable<Boot>) -> Result<Option<Event>> {
104
103
}
105
104
}
106
105
107
- /// INTERNAL API! Helper for print macros.
108
- #[ doc( hidden) ]
109
- pub fn _print ( args : core:: fmt:: Arguments ) {
110
- system_table ( )
111
- . stdout ( )
112
- . write_fmt ( args)
113
- . expect ( "Failed to write to stdout" ) ;
114
- }
115
-
116
- /// Prints to the standard output.
117
- ///
118
- /// # Panics
119
- /// Will panic if `SYSTEM_TABLE` is `None` (Before [init()] and after [uefi::prelude::SystemTable::exit_boot_services()]).
120
- ///
121
- /// # Examples
122
- /// ```
123
- /// print!("");
124
- /// print!("Hello World\n");
125
- /// print!("Hello {}", "World");
126
- /// ```
127
- #[ macro_export]
128
- macro_rules! print {
129
- ( $( $arg: tt) * ) => ( $crate:: helpers:: _print( core:: format_args!( $( $arg) * ) ) ) ;
130
- }
131
-
132
- /// Prints to the standard output, with a newline.
133
- ///
134
- /// # Panics
135
- /// Will panic if `SYSTEM_TABLE` is `None` (Before [init()] and after [uefi::prelude::SystemTable::exit_boot_services()]).
136
- ///
137
- /// # Examples
138
- /// ```
139
- /// println!();
140
- /// println!("Hello World");
141
- /// println!("Hello {}", "World");
142
- /// ```
143
- #[ macro_export]
144
- macro_rules! println {
145
- ( ) => ( $crate:: print!( "\n " ) ) ;
146
- ( $( $arg: tt) * ) => ( $crate:: helpers:: _print( core:: format_args!( "{}{}" , core:: format_args!( $( $arg) * ) , "\n " ) ) ) ;
147
- }
148
-
149
- /// Set up logging
150
- ///
151
- /// This is unsafe because you must arrange for the logger to be reset with
152
- /// disable() on exit from UEFI boot services.
153
- #[ cfg( feature = "logger" ) ]
154
- unsafe fn init_logger ( st : & mut SystemTable < Boot > ) {
155
- // Connect the logger to stdout.
156
- LOGGER . set_output ( st. stdout ( ) ) ;
157
-
158
- // Set the logger.
159
- log:: set_logger ( & LOGGER ) . unwrap ( ) ; // Can only fail if already initialized.
160
-
161
- // Set logger max level to level specified by log features
162
- log:: set_max_level ( log:: STATIC_MAX_LEVEL ) ;
163
- }
164
-
165
106
/// Notify the utility library that boot services are not safe to call anymore
166
107
/// As this is a callback, it must be `extern "efiapi"`.
167
108
unsafe extern "efiapi" fn exit_boot_services ( _e : Event , _ctx : Option < NonNull < c_void > > ) {
@@ -174,68 +115,8 @@ unsafe extern "efiapi" fn exit_boot_services(_e: Event, _ctx: Option<NonNull<c_v
174
115
SYSTEM_TABLE . store ( ptr:: null_mut ( ) , Ordering :: Release ) ;
175
116
176
117
#[ cfg( feature = "logger" ) ]
177
- LOGGER . disable ( ) ;
118
+ logger :: disable ( ) ;
178
119
120
+ #[ cfg( feature = "global_allocator" ) ]
179
121
uefi:: allocator:: exit_boot_services ( ) ;
180
122
}
181
-
182
- #[ cfg( feature = "panic_handler" ) ]
183
- #[ panic_handler]
184
- fn panic_handler ( info : & core:: panic:: PanicInfo ) -> ! {
185
- println ! ( "[PANIC]: {}" , info) ;
186
-
187
- // Give the user some time to read the message
188
- if let Some ( st) = system_table_opt ( ) {
189
- st. boot_services ( ) . stall ( 10_000_000 ) ;
190
- } else {
191
- let mut dummy = 0u64 ;
192
- // FIXME: May need different counter values in debug & release builds
193
- for i in 0 ..300_000_000 {
194
- unsafe {
195
- core:: ptr:: write_volatile ( & mut dummy, i) ;
196
- }
197
- }
198
- }
199
-
200
- cfg_if ! {
201
- if #[ cfg( all( target_arch = "x86_64" , feature = "qemu" ) ) ] {
202
- // If running in QEMU, use the f4 exit port to signal the error and exit
203
- use qemu_exit:: QEMUExit ;
204
- let custom_exit_success = 3 ;
205
- let qemu_exit_handle = qemu_exit:: X86 :: new( 0xF4 , custom_exit_success) ;
206
- qemu_exit_handle. exit_failure( ) ;
207
- } else {
208
- // If the system table is available, use UEFI's standard shutdown mechanism
209
- if let Some ( st) = system_table_opt( ) {
210
- use uefi:: table:: runtime:: ResetType ;
211
- st. runtime_services( )
212
- . reset( ResetType :: SHUTDOWN , uefi:: Status :: ABORTED , None ) ;
213
- }
214
-
215
- // If we don't have any shutdown mechanism handy, the best we can do is loop
216
- log:: error!( "Could not shut down, please power off the system manually..." ) ;
217
-
218
- cfg_if! {
219
- if #[ cfg( target_arch = "x86_64" ) ] {
220
- loop {
221
- unsafe {
222
- // Try to at least keep CPU from running at 100%
223
- core:: arch:: asm!( "hlt" , options( nomem, nostack) ) ;
224
- }
225
- }
226
- } else if #[ cfg( target_arch = "aarch64" ) ] {
227
- loop {
228
- unsafe {
229
- // Try to at least keep CPU from running at 100%
230
- core:: arch:: asm!( "hlt 420" , options( nomem, nostack) ) ;
231
- }
232
- }
233
- } else {
234
- loop {
235
- // just run forever dammit how do you return never anyway
236
- }
237
- }
238
- }
239
- }
240
- }
241
- }
0 commit comments