1/*
2 * Copyright 2011, François Revol, revol@free.fr.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <string.h>
8#include <stdarg.h>
9
10#include <OS.h>
11
12#include <boot/platform.h>
13#include <boot/stage2.h>
14#include <boot/heap.h>
15#include <boot/platform/cfe/cfe.h>
16#include <platform_arch.h>
17
18typedef uint64	ptr64; // for clarity
19
20status_t cfe_error(int32 err)
21{
22	// not an error
23	if (err > 0)
24		return err;
25
26	switch (err) {
27		case CFE_OK:
28			return B_OK;
29		case CFE_ERR:
30			return B_ERROR;
31		//TODO:add cases
32		default:
33			return B_ERROR;
34	}
35}
36
37#define CFE_CMD_FW_GETINFO		0
38#define CFE_CMD_FW_RESTART		1
39#define CFE_CMD_FW_BOOT			2
40#define CFE_CMD_FW_CPUCTL		3
41#define CFE_CMD_FW_GETTIME		4
42#define CFE_CMD_FW_MEMENUM		5
43#define CFE_CMD_FW_FLUSHCACHE	6
44
45#define CFE_CMD_DEV_GETHANDLE	9
46#define CFE_CMD_DEV_ENUM		10
47#define CFE_CMD_DEV_OPEN		11
48#define CFE_CMD_DEV_READ		13
49#define CFE_CMD_DEV_WRITE		14
50#define CFE_CMD_DEV_CLOSE		16
51
52
53struct cfe_xiocb_s {
54	cfe_xiocb_s(uint64 fcode, int64 handle = 0, uint64 flags = 0);
55
56	uint64	xiocb_fcode;
57	int64	xiocb_status;
58	int64	xiocb_handle;
59	uint64	xiocb_flags;
60	uint64	xiocb_psize;
61	union {
62		struct {
63			uint64	buf_offset;
64			ptr64	buf_ptr;
65			uint64	buf_length;
66			uint64	buf_retlen;
67			uint64	buf_ioctlcmd;
68		} xiocb_buffer;
69/*
70		struct {
71		} xiocb_inpstat;
72*/
73		struct {
74			int64	enum_idx;
75			ptr64	name_ptr;
76			int64	name_length;
77			ptr64	val_ptr;
78			int64	val_length;
79		} xiocb_envbuf;
80/*
81		struct {
82		} xiocb_cpuctl;
83*/
84		struct {
85			int64	ticks;
86		} xiocb_time;
87/*
88		struct {
89		} xiocb_meminfo;
90		struct {
91		} xiocb_fwinfo;
92*/
93		struct {
94			int64	status;
95		} xiocb_exitstat;
96	} plist;
97};
98
99typedef struct cfe_xiocb_s cfe_xiocb_t;
100
101cfe_xiocb_s::cfe_xiocb_s(uint64 fcode, int64 handle, uint64 flags)
102	: xiocb_fcode(fcode),
103	xiocb_status(0),
104	xiocb_handle(handle),
105	xiocb_flags(flags),
106	xiocb_psize(0)
107{
108	switch (fcode) {
109		case CFE_CMD_FW_GETINFO:
110		case CFE_CMD_DEV_READ:
111		case CFE_CMD_DEV_WRITE:
112		case CFE_CMD_DEV_OPEN:
113			xiocb_psize = sizeof(plist.xiocb_buffer);
114			break;
115		case CFE_CMD_FW_RESTART:
116			xiocb_psize = sizeof(plist.xiocb_exitstat);
117			break;
118		case CFE_CMD_FW_GETTIME:
119			xiocb_psize = sizeof(plist.xiocb_time);
120			break;
121		case CFE_CMD_DEV_ENUM:
122			xiocb_psize = sizeof(plist.xiocb_envbuf);
123			break;
124		//XXX: some more...
125		default:
126			break;
127	}
128	memset(&plist, 0, sizeof(plist));
129};
130
131
132// CFE handle
133static uint64 sCFEHandle;
134// CFE entry point
135static uint64 sCFEEntry;
136
137static int cfe_iocb_dispatch(cfe_xiocb_t *xiocb)
138{
139	static int (*dispfunc)(intptr_t handle, intptr_t xiocb);
140	dispfunc = (int(*)(intptr_t, intptr_t))(void *)sCFEEntry;
141	if (dispfunc == NULL)
142		return CFE_ERR;
143	return (*dispfunc)((intptr_t)sCFEHandle, (intptr_t)xiocb);
144}
145
146int
147cfe_init(uint64 handle, uint64 entry)
148{
149	sCFEHandle = handle;
150	sCFEEntry = entry;
151
152	return CFE_OK;
153}
154
155int
156cfe_exit(int32 warm, int32 status)
157{
158	cfe_xiocb_t xiocb(CFE_CMD_FW_RESTART, 0,
159		warm ? CFE_FLG_WARMSTART : CFE_FLG_COLDSTART);
160	xiocb.plist.xiocb_exitstat.status = status;
161
162	cfe_iocb_dispatch(&xiocb);
163
164	return xiocb.xiocb_status;
165}
166
167
168int cfe_enumdev(int idx, char *name, int namelen)
169{
170	cfe_xiocb_t xiocb(CFE_CMD_DEV_ENUM);
171	xiocb.plist.xiocb_envbuf.enum_idx = idx;
172	xiocb.plist.xiocb_envbuf.name_ptr = (uint64)name;
173	xiocb.plist.xiocb_envbuf.name_length = namelen;
174
175	cfe_iocb_dispatch(&xiocb);
176
177	return xiocb.xiocb_status;
178}
179
180
181int
182cfe_getstdhandle(int flag)
183{
184	cfe_xiocb_t xiocb(CFE_CMD_DEV_GETHANDLE, 0, flag);
185
186	cfe_iocb_dispatch(&xiocb);
187
188	if (xiocb.xiocb_status < 0);
189		return xiocb.xiocb_status;
190	return xiocb.xiocb_handle;
191}
192
193
194int
195cfe_open(const char *name)
196{
197	cfe_xiocb_t xiocb(CFE_CMD_DEV_OPEN);
198	xiocb.plist.xiocb_buffer.buf_offset = 0;
199	xiocb.plist.xiocb_buffer.buf_ptr = (uint64)name;
200	xiocb.plist.xiocb_buffer.buf_length = strlen(name);
201
202	cfe_iocb_dispatch(&xiocb);
203
204	if (xiocb.xiocb_status < 0);
205		return xiocb.xiocb_status;
206	return xiocb.xiocb_handle;
207}
208
209
210int
211cfe_close(int handle)
212{
213	cfe_xiocb_t xiocb(CFE_CMD_DEV_CLOSE, handle);
214
215	cfe_iocb_dispatch(&xiocb);
216
217	return xiocb.xiocb_status;
218}
219
220
221uint64
222cfe_getticks(void)
223{
224	cfe_xiocb_t xiocb(CFE_CMD_FW_GETTIME);
225
226	cfe_iocb_dispatch(&xiocb);
227
228	return xiocb.plist.xiocb_time.ticks;
229}
230
231
232int
233cfe_readblk(int handle, int64 offset, void *buffer, int length)
234{
235	cfe_xiocb_t xiocb(CFE_CMD_DEV_READ, handle);
236	xiocb.plist.xiocb_buffer.buf_offset = offset;
237	xiocb.plist.xiocb_buffer.buf_ptr = (uint64)buffer;
238	xiocb.plist.xiocb_buffer.buf_length = length;
239
240	cfe_iocb_dispatch(&xiocb);
241
242	if (xiocb.xiocb_status < 0);
243		return xiocb.xiocb_status;
244	return xiocb.plist.xiocb_buffer.buf_retlen;
245}
246
247
248
249int
250cfe_writeblk(int handle, int64 offset, const void *buffer, int length)
251{
252	cfe_xiocb_t xiocb(CFE_CMD_DEV_WRITE, handle);
253	xiocb.plist.xiocb_buffer.buf_offset = offset;
254	xiocb.plist.xiocb_buffer.buf_ptr = (uint64)buffer;
255	xiocb.plist.xiocb_buffer.buf_length = length;
256
257	cfe_iocb_dispatch(&xiocb);
258
259	if (xiocb.xiocb_status < 0);
260		return xiocb.xiocb_status;
261	return xiocb.plist.xiocb_buffer.buf_retlen;
262}
263
264
265