aboutsummaryrefslogtreecommitdiff
path: root/src/sbi.zig
blob: fc8afde41ff45d33530186e140c4a7bb5f9c1748 (plain) (blame)
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// SPDX-FileCopyrightText: 2024 Himbeer <himbeer@disroot.org>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

const riscv = @import("riscv.zig");

pub const Error = error{
    Success,
    Failed,
    NotSupported,
    InvalidParam,
    Denied,
    InvalidAddr,
    AlreadyAvail,
    AlreadyStarted,
    AlreadyStopped,
    NoSharedMem,
    InvalidState,
    BadRange,
    SbiUnknown,
};

pub fn errorFromCode(code: isize) Error {
    return switch (code) {
        0 => Error.Success,
        -1 => Error.Failed,
        -2 => Error.NotSupported,
        -3 => Error.InvalidParam,
        -4 => Error.Denied,
        -5 => Error.InvalidAddr,
        -6 => Error.AlreadyAvail,
        -7 => Error.AlreadyStarted,
        -8 => Error.AlreadyStopped,
        -9 => Error.NoSharedMem,
        -10 => Error.InvalidState,
        -11 => Error.BadRange,
        else => Error.SbiUnknown,
    };
}

const BaseExtId: usize = 0x10;

const BaseFnId = enum(usize) {
    GetSpecVer,
    GetImpId,
    GetImpVer,
    ProbeExt,
    GetMVendorId,
    GetMArchId,
    GetMImpId,
};

pub const ImpId = enum(isize) {
    Bbl,
    OpenSbi,
    Xvisor,
    Kvm,
    RustSbi,
    Diosix,
    Coffer,
    Xen,
    PolarFire,
    _,
};

pub fn specVer() !isize {
    const ret = riscv.ecall(BaseExtId, @intFromEnum(BaseFnId.GetSpecVer), 0, 0, 0);
    if (ret.err != 0) {
        return errorFromCode(ret.err);
    }

    return ret.val;
}

pub fn impId() !ImpId {
    const ret = riscv.ecall(BaseExtId, @intFromEnum(BaseFnId.GetImpId), 0, 0, 0);
    if (ret.err != 0) {
        return errorFromCode(ret.err);
    }

    return @enumFromInt(ret.val);
}

pub fn impVer() !isize {
    const ret = riscv.ecall(BaseExtId, @intFromEnum(BaseFnId.GetImpVer), 0, 0, 0);
    if (ret.err != 0) {
        return errorFromCode(ret.err);
    }

    return ret.val;
}

pub fn probeExt(ext_id: usize) !bool {
    const ret = riscv.ecall(BaseExtId, @intFromEnum(BaseFnId.ProbeExt), ext_id, 0, 0);
    if (ret.err != 0) {
        return errorFromCode(ret.err);
    }

    return ret.val != 0;
}

pub fn mVendorId() !isize {
    const ret = riscv.ecall(BaseExtId, @intFromEnum(BaseFnId.GetMVendorId), 0, 0, 0);
    if (ret.err != 0) {
        return errorFromCode(ret.err);
    }

    return ret.val;
}

pub fn mArchId() !isize {
    const ret = riscv.ecall(BaseExtId, @intFromEnum(BaseFnId.GetMarchId), 0, 0, 0);
    if (ret.err != 0) {
        return errorFromCode(ret.err);
    }

    return ret.val;
}

pub fn mImpId() !isize {
    const ret = riscv.ecall(BaseExtId, @intFromEnum(BaseFnId.GetMImpId), 0, 0, 0);
    if (ret.err != 0) {
        return errorFromCode(ret.err);
    }

    return ret.val;
}