@@ -91,9 +91,11 @@ impl Command {
91
91
}
92
92
93
93
pub fn output ( & mut self ) -> io:: Result < ( ExitStatus , Vec < u8 > , Vec < u8 > ) > {
94
- let cmd = uefi_command_internal:: Command :: load_image ( & self . prog ) ?;
94
+ let mut cmd = uefi_command_internal:: Command :: load_image ( & self . prog ) ?;
95
+ cmd. stdout_init ( ) ?;
95
96
let stat = cmd. start_image ( ) ?;
96
- Ok ( ( ExitStatus ( stat) , Vec :: new ( ) , Vec :: new ( ) ) )
97
+ let stdout = cmd. stdout ( ) ?;
98
+ Ok ( ( ExitStatus ( stat) , stdout, Vec :: new ( ) ) )
97
99
}
98
100
}
99
101
@@ -246,20 +248,30 @@ impl<'a> fmt::Debug for CommandArgs<'a> {
246
248
}
247
249
248
250
mod uefi_command_internal {
251
+ use r_efi:: protocols:: { loaded_image, simple_text_output} ;
252
+
249
253
use super :: super :: helpers;
250
- use crate :: ffi:: OsStr ;
254
+ use crate :: ffi:: { OsStr , OsString } ;
251
255
use crate :: io:: { self , const_io_error} ;
252
256
use crate :: mem:: MaybeUninit ;
253
257
use crate :: os:: uefi:: env:: { boot_services, image_handle} ;
258
+ use crate :: os:: uefi:: ffi:: OsStringExt ;
254
259
use crate :: ptr:: NonNull ;
260
+ use crate :: slice;
261
+ use crate :: sys_common:: wstr:: WStrUnits ;
255
262
256
263
pub struct Command {
257
264
handle : NonNull < crate :: ffi:: c_void > ,
265
+ stdout : Option < helpers:: Protocol < PipeProtocol > > ,
266
+ st : Box < r_efi:: efi:: SystemTable > ,
258
267
}
259
268
260
269
impl Command {
261
- const fn new ( handle : NonNull < crate :: ffi:: c_void > ) -> Self {
262
- Self { handle }
270
+ const fn new (
271
+ handle : NonNull < crate :: ffi:: c_void > ,
272
+ st : Box < r_efi:: efi:: SystemTable > ,
273
+ ) -> Self {
274
+ Self { handle, stdout : None , st }
263
275
}
264
276
265
277
pub fn load_image ( p : & OsStr ) -> io:: Result < Self > {
@@ -286,7 +298,17 @@ mod uefi_command_internal {
286
298
} else {
287
299
let child_handle = unsafe { child_handle. assume_init ( ) } ;
288
300
let child_handle = NonNull :: new ( child_handle) . unwrap ( ) ;
289
- Ok ( Self :: new ( child_handle) )
301
+
302
+ let loaded_image: NonNull < loaded_image:: Protocol > =
303
+ helpers:: open_protocol ( child_handle, loaded_image:: PROTOCOL_GUID ) . unwrap ( ) ;
304
+ let mut st: Box < r_efi:: efi:: SystemTable > =
305
+ Box :: new ( unsafe { crate :: ptr:: read ( ( * loaded_image. as_ptr ( ) ) . system_table ) } ) ;
306
+
307
+ unsafe {
308
+ ( * loaded_image. as_ptr ( ) ) . system_table = st. as_mut ( ) ;
309
+ }
310
+
311
+ Ok ( Self :: new ( child_handle, st) )
290
312
}
291
313
}
292
314
@@ -313,6 +335,32 @@ mod uefi_command_internal {
313
335
314
336
Ok ( r)
315
337
}
338
+
339
+ pub fn stdout_init ( & mut self ) -> io:: Result < ( ) > {
340
+ let mut protocol =
341
+ helpers:: Protocol :: create ( PipeProtocol :: new ( ) , simple_text_output:: PROTOCOL_GUID ) ?;
342
+
343
+ self . st . console_out_handle = protocol. handle ( ) . as_ptr ( ) ;
344
+ self . st . con_out =
345
+ protocol. as_mut ( ) as * mut PipeProtocol as * mut simple_text_output:: Protocol ;
346
+
347
+ self . stdout = Some ( protocol) ;
348
+
349
+ Ok ( ( ) )
350
+ }
351
+
352
+ pub fn stdout ( & self ) -> io:: Result < Vec < u8 > > {
353
+ if let Some ( stdout) = & self . stdout {
354
+ stdout
355
+ . as_ref ( )
356
+ . utf8 ( )
357
+ . into_string ( )
358
+ . map_err ( |_| const_io_error ! ( io:: ErrorKind :: Other , "utf8 conversion failed" ) )
359
+ . map ( Into :: into)
360
+ } else {
361
+ Err ( const_io_error ! ( io:: ErrorKind :: NotFound , "stdout not found" ) )
362
+ }
363
+ }
316
364
}
317
365
318
366
impl Drop for Command {
@@ -325,4 +373,134 @@ mod uefi_command_internal {
325
373
}
326
374
}
327
375
}
376
+
377
+ #[ repr( C ) ]
378
+ struct PipeProtocol {
379
+ reset : simple_text_output:: ProtocolReset ,
380
+ output_string : simple_text_output:: ProtocolOutputString ,
381
+ test_string : simple_text_output:: ProtocolTestString ,
382
+ query_mode : simple_text_output:: ProtocolQueryMode ,
383
+ set_mode : simple_text_output:: ProtocolSetMode ,
384
+ set_attribute : simple_text_output:: ProtocolSetAttribute ,
385
+ clear_screen : simple_text_output:: ProtocolClearScreen ,
386
+ set_cursor_position : simple_text_output:: ProtocolSetCursorPosition ,
387
+ enable_cursor : simple_text_output:: ProtocolEnableCursor ,
388
+ mode : * mut simple_text_output:: Mode ,
389
+ _mode : Box < simple_text_output:: Mode > ,
390
+ _buffer : Vec < u16 > ,
391
+ }
392
+
393
+ impl PipeProtocol {
394
+ fn new ( ) -> Self {
395
+ let mut mode = Box :: new ( simple_text_output:: Mode {
396
+ max_mode : 0 ,
397
+ mode : 0 ,
398
+ attribute : 0 ,
399
+ cursor_column : 0 ,
400
+ cursor_row : 0 ,
401
+ cursor_visible : r_efi:: efi:: Boolean :: FALSE ,
402
+ } ) ;
403
+ Self {
404
+ reset : Self :: reset,
405
+ output_string : Self :: output_string,
406
+ test_string : Self :: test_string,
407
+ query_mode : Self :: query_mode,
408
+ set_mode : Self :: set_mode,
409
+ set_attribute : Self :: set_attribute,
410
+ clear_screen : Self :: clear_screen,
411
+ set_cursor_position : Self :: set_cursor_position,
412
+ enable_cursor : Self :: enable_cursor,
413
+ mode : mode. as_mut ( ) ,
414
+ _mode : mode,
415
+ _buffer : Vec :: new ( ) ,
416
+ }
417
+ }
418
+
419
+ fn utf8 ( & self ) -> OsString {
420
+ OsString :: from_wide ( & self . _buffer )
421
+ }
422
+
423
+ extern "efiapi" fn reset (
424
+ proto : * mut simple_text_output:: Protocol ,
425
+ _: r_efi:: efi:: Boolean ,
426
+ ) -> r_efi:: efi:: Status {
427
+ let proto: * mut PipeProtocol = proto. cast ( ) ;
428
+ unsafe {
429
+ ( * proto) . _buffer . clear ( ) ;
430
+ }
431
+ r_efi:: efi:: Status :: SUCCESS
432
+ }
433
+
434
+ extern "efiapi" fn output_string (
435
+ proto : * mut simple_text_output:: Protocol ,
436
+ buf : * mut r_efi:: efi:: Char16 ,
437
+ ) -> r_efi:: efi:: Status {
438
+ let proto: * mut PipeProtocol = proto. cast ( ) ;
439
+ let buf_len = unsafe {
440
+ if let Some ( x) = WStrUnits :: new ( buf) {
441
+ x. count ( )
442
+ } else {
443
+ return r_efi:: efi:: Status :: INVALID_PARAMETER ;
444
+ }
445
+ } ;
446
+ let buf_slice = unsafe { slice:: from_raw_parts ( buf, buf_len) } ;
447
+
448
+ unsafe {
449
+ ( * proto) . _buffer . extend_from_slice ( buf_slice) ;
450
+ } ;
451
+
452
+ r_efi:: efi:: Status :: SUCCESS
453
+ }
454
+
455
+ extern "efiapi" fn test_string (
456
+ _: * mut simple_text_output:: Protocol ,
457
+ _: * mut r_efi:: efi:: Char16 ,
458
+ ) -> r_efi:: efi:: Status {
459
+ r_efi:: efi:: Status :: SUCCESS
460
+ }
461
+
462
+ extern "efiapi" fn query_mode (
463
+ _: * mut simple_text_output:: Protocol ,
464
+ _: usize ,
465
+ _: * mut usize ,
466
+ _: * mut usize ,
467
+ ) -> r_efi:: efi:: Status {
468
+ r_efi:: efi:: Status :: UNSUPPORTED
469
+ }
470
+
471
+ extern "efiapi" fn set_mode (
472
+ _: * mut simple_text_output:: Protocol ,
473
+ _: usize ,
474
+ ) -> r_efi:: efi:: Status {
475
+ r_efi:: efi:: Status :: UNSUPPORTED
476
+ }
477
+
478
+ extern "efiapi" fn set_attribute (
479
+ _: * mut simple_text_output:: Protocol ,
480
+ _: usize ,
481
+ ) -> r_efi:: efi:: Status {
482
+ r_efi:: efi:: Status :: UNSUPPORTED
483
+ }
484
+
485
+ extern "efiapi" fn clear_screen (
486
+ _: * mut simple_text_output:: Protocol ,
487
+ ) -> r_efi:: efi:: Status {
488
+ r_efi:: efi:: Status :: UNSUPPORTED
489
+ }
490
+
491
+ extern "efiapi" fn set_cursor_position (
492
+ _: * mut simple_text_output:: Protocol ,
493
+ _: usize ,
494
+ _: usize ,
495
+ ) -> r_efi:: efi:: Status {
496
+ r_efi:: efi:: Status :: UNSUPPORTED
497
+ }
498
+
499
+ extern "efiapi" fn enable_cursor (
500
+ _: * mut simple_text_output:: Protocol ,
501
+ _: r_efi:: efi:: Boolean ,
502
+ ) -> r_efi:: efi:: Status {
503
+ r_efi:: efi:: Status :: UNSUPPORTED
504
+ }
505
+ }
328
506
}
0 commit comments