|  | 
|  | 1 | +#![feature(extern_types)] | 
|  | 2 | + | 
| 1 | 3 | extern crate alloc; | 
| 2 | 4 | 
 | 
|  | 5 | +use alloc::vec::Vec; | 
|  | 6 | +use alloc::vec; | 
|  | 7 | +use alloc::string::String; | 
| 3 | 8 | use core::alloc::{GlobalAlloc, Layout}; | 
| 4 | 9 | use core::ffi::c_char; | 
|  | 10 | +use core::ffi::c_int; | 
|  | 11 | +use core::ffi::c_void; | 
| 5 | 12 | 
 | 
| 6 | 13 | use alloc::ffi::CString; | 
|  | 14 | +use core::ffi::CStr; | 
| 7 | 15 | use core::panic::PanicInfo; | 
| 8 | 16 | 
 | 
| 9 | 17 | extern "C" { | 
| 10 | 18 |     static grub_xputs: extern "C" fn(stri: *const c_char); | 
| 11 | 19 |     pub fn grub_abort(); | 
| 12 | 20 |     pub fn grub_malloc(sz: usize) -> *mut u8; | 
| 13 | 21 |     pub fn grub_free(ptr: *mut u8); | 
|  | 22 | +    pub fn grub_register_command_prio (name: *const c_char, | 
|  | 23 | +				       func: fn (cmd: *const GrubCommand, | 
|  | 24 | +						 argc: c_int, argv: *const *const c_char) ->err_t, | 
|  | 25 | +				       summary: *const c_char, | 
|  | 26 | +				       description: *const c_char, | 
|  | 27 | +				       prio: c_int) -> *mut GrubCommand; | 
|  | 28 | +    pub fn grub_strlen (s: *const c_char) -> usize; | 
|  | 29 | +    pub fn grub_unregister_command (cmd: *const GrubCommand); | 
|  | 30 | +} | 
|  | 31 | + | 
|  | 32 | +#[no_mangle] | 
|  | 33 | +pub extern "C" fn strlen(s: *const c_char) -> usize { | 
|  | 34 | +    return unsafe { grub_strlen(s) };  | 
|  | 35 | +} | 
|  | 36 | + | 
|  | 37 | + | 
|  | 38 | +// TODO: Use code generation? | 
|  | 39 | +#[repr(C)] | 
|  | 40 | +pub struct GrubCommand { | 
|  | 41 | +    next: *mut GrubCommand, | 
|  | 42 | +    prev: *mut *mut GrubCommand, | 
|  | 43 | +    name: *const c_char, | 
|  | 44 | +    prio: c_int, | 
|  | 45 | +    func: *const c_void, | 
|  | 46 | +    flags: u32, | 
|  | 47 | +    summary: *const c_char, | 
|  | 48 | +    description: *const c_char, | 
|  | 49 | +    data: *const c_void, | 
| 14 | 50 | } | 
| 15 | 51 | 
 | 
|  | 52 | +pub type GrubCommandPtr = *const GrubCommand; | 
|  | 53 | +pub type err_t = u32; | 
| 16 | 54 | 
 | 
| 17 | 55 | struct GrubAllocator; | 
| 18 | 56 | 
 | 
| @@ -44,3 +82,30 @@ fn panic(info: &PanicInfo) -> ! { | 
| 44 | 82 |     } | 
| 45 | 83 |     loop{} | 
| 46 | 84 | } | 
|  | 85 | + | 
|  | 86 | +fn cmd_callback (cmd: *const GrubCommand, | 
|  | 87 | +		 argc: c_int, argv: *const *const c_char) -> err_t { | 
|  | 88 | +    let mut argv_vec: Vec<&str> = vec![]; | 
|  | 89 | +    for i in 0..argc { | 
|  | 90 | +	argv_vec.push(unsafe { CStr::from_ptr(*argv.add(i as usize)) }.to_str().unwrap()); | 
|  | 91 | +    } | 
|  | 92 | + | 
|  | 93 | +    return unsafe{(*((*cmd).data as *const fn (argc: usize, argv: &[&str]) -> err_t))} (argc as usize, &argv_vec); | 
|  | 94 | +} | 
|  | 95 | + | 
|  | 96 | +pub fn register_command (name: &str, cb: fn (argc: usize, argv: &[&str]) -> err_t, | 
|  | 97 | +			 summary: &str, description: &str) -> GrubCommandPtr { | 
|  | 98 | +    unsafe { | 
|  | 99 | +	let cmd = grub_register_command_prio (CString::new(name).unwrap().as_ptr(), | 
|  | 100 | +					      cmd_callback, | 
|  | 101 | +					      CString::new(summary).unwrap().as_ptr(), | 
|  | 102 | +					      CString::new(description).unwrap().as_ptr(), | 
|  | 103 | +					      0); | 
|  | 104 | +	(*cmd).data = cb as *mut c_void; | 
|  | 105 | +	return cmd; | 
|  | 106 | +    } | 
|  | 107 | +} | 
|  | 108 | + | 
|  | 109 | +pub fn unregister_command (cmd: GrubCommandPtr) { | 
|  | 110 | +    unsafe { grub_unregister_command(cmd); } | 
|  | 111 | +} | 
0 commit comments