1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use alloc::vec::Vec;
use core::{slice, str};

use lazy_static::lazy_static;
use log::info;

extern "C" {
    fn _bin_count();
    fn _bin_address();
    fn _bin_name();
}

lazy_static! {
    static ref BIN_NAME_LIST: Vec<&'static str> = {
        let mut bin_name_list = Vec::new();
        let mut bin_name_pointer = _bin_name as usize as *const u8;
        let bin_count = get_bin_count();
        unsafe {
            for _ in 0..bin_count {
                let mut bin_name_length = 0;
                while bin_name_pointer.add(bin_name_length).read_volatile() != b'\0' {
                    bin_name_length += 1;
                }
                let bin_name_slice = slice::from_raw_parts(bin_name_pointer, bin_name_length);
                bin_name_list.push(str::from_utf8(bin_name_slice).unwrap());
                bin_name_pointer = bin_name_pointer.add(bin_name_length).add(1);
            }
        }
        bin_name_list
    };
}

pub fn get_bin_count() -> usize {
    unsafe { (_bin_count as *const usize).read_volatile() }
}

pub fn get_bin(name: &str) -> Option<&'static [u8]> {
    let bin_count = get_bin_count();
    (0..bin_count)
        .find(|&bin_index| BIN_NAME_LIST[bin_index] == name)
        .map(get_bin_data)
}

pub fn get_bin_data(bin_index: usize) -> &'static [u8] {
    let bin_address_pointer = _bin_address as *const usize;

    unsafe {
        let bin_address_start = bin_address_pointer.add(bin_index * 2).read_volatile();
        let bin_address_end = bin_address_pointer.add(bin_index * 2 + 1).read_volatile();
        slice::from_raw_parts(
            bin_address_start as *const u8,
            bin_address_end - bin_address_start,
        )
    }
}

pub fn print_bin_name() {
    let bin_count = get_bin_count();
    let mut bin_name_list = Vec::new();
    for bin_index in 0..bin_count {
        let bin_name = BIN_NAME_LIST[bin_index];
        if bin_name == "init" {
            continue;
        }
        bin_name_list.push(bin_name);
    }
    info!("built-in binaries: {}", bin_name_list.join(", "));
}