aboutsummaryrefslogtreecommitdiffstats
path: root/src/arch/riscv/include/ipxe/sbi.h
blob: 44685cc87a6d6dd4cc3530e712dfc3936d078ac9 (plain)
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#ifndef _IPXE_SBI_H
#define _IPXE_SBI_H

/** @file
 *
 * Supervisor Binary Interface (SBI)
 *
 */

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );

#include <stdint.h>

/** An SBI function return value */
struct sbi_return {
	/** Error status (returned in a0) */
	long error;
	/** Data value (returned in a1) */
	long value;
};

/**
 * @defgroup sbierrors SBI errors
 *
 * *{
 */
#define SBI_SUCCESS 0			/**< Completed successfully */
#define SBI_ERR_FAILED -1		/**< Failed */
#define SBI_ERR_NOT_SUPPORTED -2	/**< Not supported */
#define SBI_ERR_INVALID_PARAM -3	/**< Invalid parameter(s) */
#define SBI_ERR_DENIED -4		/**< Denied or not allowed */
#define SBI_ERR_INVALID_ADDRESS -5	/**< Invalid address(es) */
#define SBI_ERR_ALREADY_AVAILABLE -6	/**< Already available */
#define SBI_ERR_ALREADY_STARTED -7	/**< Already started */
#define SBI_ERR_ALREADY_STOPPED -8	/**< Already stopped */
#define SBI_ERR_NO_SHMEM -9		/**< Shared memory not available */
#define SBI_ERR_INVALID_STATE -10	/**< Invalid state */
#define SBI_ERR_BAD_RANGE -11		/**< Bad (or invalid) range */
#define SBI_ERR_TIMEOUT -12		/**< Failed due to timeout */
#define SBI_ERR_IO -13			/**< Input/output error */
/** @} */

/** Construct SBI extension ID */
#define SBI_EID( c1, c2, c3, c4 ) \
	( (int) ( ( (c1) << 24 ) | ( (c2) << 16 ) | ( (c3) << 8 ) | (c4) ) )

/**
 * Call supervisor with no parameters
 *
 * @v eid		Extension ID
 * @v fid		Function ID
 * @ret ret		Return value
 */
static inline __attribute__ (( always_inline )) struct sbi_return
sbi_ecall_0 ( int eid, int fid ) {
	register unsigned long a7 asm ( "a7" ) = ( ( long ) eid );
	register unsigned long a6 asm ( "a6" ) = ( ( long ) fid );
	register unsigned long a0 asm ( "a0" );
	register unsigned long a1 asm ( "a1" );
	struct sbi_return ret;

	__asm__ __volatile__ ( "ecall"
			       : "=r" ( a0 ), "=r" ( a1 )
			       : "r" ( a6 ), "r" ( a7 )
			       : "memory" );
	ret.error = a0;
	ret.value = a1;
	return ret;
}

/**
 * Call supervisor with one parameter
 *
 * @v eid		Extension ID
 * @v fid		Function ID
 * @v param0		Parameter 0
 * @ret ret		Return value
 */
static inline __attribute__ (( always_inline )) struct sbi_return
sbi_ecall_1 ( int eid, int fid, unsigned long p0 ) {
	register unsigned long a7 asm ( "a7" ) = ( ( long ) eid );
	register unsigned long a6 asm ( "a6" ) = ( ( long ) fid );
	register unsigned long a0 asm ( "a0" ) = p0;
	register unsigned long a1 asm ( "a1" );
	struct sbi_return ret;

	__asm__ __volatile__ ( "ecall"
			       : "+r" ( a0 ), "=r" ( a1 )
			       : "r" ( a6 ), "r" ( a7 )
			       : "memory" );
	ret.error = a0;
	ret.value = a1;
	return ret;
}

/**
 * Call supervisor with two parameters
 *
 * @v eid		Extension ID
 * @v fid		Function ID
 * @v param0		Parameter 0
 * @v param1		Parameter 1
 * @ret ret		Return value
 */
static inline __attribute__ (( always_inline )) struct sbi_return
sbi_ecall_2 ( int eid, int fid, unsigned long p0, unsigned long p1 ) {
	register unsigned long a7 asm ( "a7" ) = ( ( long ) eid );
	register unsigned long a6 asm ( "a6" ) = ( ( long ) fid );
	register unsigned long a0 asm ( "a0" ) = p0;
	register unsigned long a1 asm ( "a1" ) = p1;
	struct sbi_return ret;

	__asm__ __volatile__ ( "ecall"
			       : "+r" ( a0 ), "+r" ( a1 )
			       : "r" ( a6 ), "r" ( a7 )
			       : "memory" );
	ret.error = a0;
	ret.value = a1;
	return ret;
}

/**
 * Call supervisor with three parameters
 *
 * @v eid		Extension ID
 * @v fid		Function ID
 * @v param0		Parameter 0
 * @v param1		Parameter 1
 * @v param2		Parameter 2
 * @ret ret		Return value
 */
static inline __attribute__ (( always_inline )) struct sbi_return
sbi_ecall_3 ( int eid, int fid, unsigned long p0, unsigned long p1,
	      unsigned long p2 ) {
	register unsigned long a7 asm ( "a7" ) = ( ( long ) eid );
	register unsigned long a6 asm ( "a6" ) = ( ( long ) fid );
	register unsigned long a0 asm ( "a0" ) = p0;
	register unsigned long a1 asm ( "a1" ) = p1;
	register unsigned long a2 asm ( "a2" ) = p2;
	struct sbi_return ret;

	__asm__ __volatile__ ( "ecall"
			       : "+r" ( a0 ), "+r" ( a1 )
			       : "r" ( a2 ), "r" ( a6 ), "r" ( a7 )
			       : "memory" );
	ret.error = a0;
	ret.value = a1;
	return ret;
}

/** Convert an SBI error code to an iPXE status code */
#define ESBI( error ) EPLATFORM ( EINFO_EPLATFORM, error )

/** System reset extension */
#define SBI_SRST SBI_EID ( 'S', 'R', 'S', 'T' )
#define SBI_SRST_SYSTEM_RESET 0x00	/**< Reset system */
#define SBI_RESET_SHUTDOWN 0x00000000	/**< Shutdown */
#define SBI_RESET_COLD 0x00000001	/**< Cold reboot */
#define SBI_RESET_WARM 0x00000002	/**< Warm reboot */

/** Debug console extension */
#define SBI_DBCN SBI_EID ( 'D', 'B', 'C', 'N' )
#define SBI_DBCN_WRITE 0x00		/**< Console Write */
#define SBI_DBCN_READ 0x01		/**< Console Read */
#define SBI_DBCN_WRITE_BYTE 0x02	/**< Console Write Byte */

#endif /* _IPXE_SBI_H */