TianoCore EDK2 master
Loading...
Searching...
No Matches
BhyveFwCtlLib.c
Go to the documentation of this file.
1
12#include "Uefi.h"
13#include <Library/BaseLib.h>
16#include <Library/DebugLib.h>
17#include <Library/IoLib.h>
20
21#define FW_PORT 0x510
22#define FW_IPORT 0x511
23
24/* Transport protocol basic operations */
25#define OP_NULL 1
26#define OP_ECHO 2
27#define OP_GET 3
28#define OP_GET_LEN 4
29#define OP_SET 5
30
31/* Transport protocol error returns */
32#define T_ESUCCESS 0
33#define T_ENOENT 2
34#define T_E2BIG 7
35#define T_EMSGSIZE 40
36
37#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
38
39STATIC CONST CHAR8 mBhyveSig[4] = { 'B', 'H', 'Y', 'V' };
40
41STATIC BOOLEAN mBhyveFwCtlSupported = FALSE;
42
43STATIC INT32 mBhyveFwCtlTxid = 0xa5;
44
45/* XXX Maybe a better inbuilt version of this ? */
46typedef struct {
47 VOID *Base;
48 UINT32 Len;
49} BIO_VEC;
50
51typedef struct {
52 UINT32 Sz;
53 UINT32 Op;
54 UINT32 TxId;
55 UINT32 Err;
57
59RETURN_STATUS
60EFIAPI
61BhyveFwCtl_CvtErr (
62 IN UINT32 errno
63 )
64{
65 RETURN_STATUS Status;
66
67 switch (errno) {
68 case T_ESUCCESS:
69 Status = RETURN_SUCCESS;
70 break;
71 case T_ENOENT:
72 Status = RETURN_NOT_FOUND;
73 break;
74 case T_E2BIG:
76 break;
77 case T_EMSGSIZE:
79 break;
80 default:
81 Status = RETURN_PROTOCOL_ERROR;
82 break;
83 }
84
85 return Status;
86}
87
89UINT32
90EFIAPI
91BIov_WLen (
92 IN BIO_VEC b[]
93 )
94{
95 UINT32 i;
96 UINT32 tLen;
97
98 tLen = 0;
99
100 if (b != NULL) {
101 for (i = 0; b[i].Base != NULL; i++) {
102 tLen += ROUNDUP (b[i].Len, sizeof (UINT32));
103 }
104 }
105
106 return tLen;
107}
108
113STATIC
114UINT32
116 IN UINT32 *Data,
117 IN UINT32 Len
118 )
119{
120 union {
121 UINT8 c[4];
122 UINT32 w;
123 } u;
124 UINT8 *cdata;
125 UINT32 i;
126
127 cdata = (UINT8 *)Data;
128 u.w = 0;
129
130 for (i = 0; i < Len; i++) {
131 u.c[i] = *cdata++;
132 }
133
134 return u.w;
135}
136
141STATIC
142VOID
144 IN char *Data,
145 IN UINT32 Len
146 )
147{
148 UINT32 *LData;
149
150 LData = (UINT32 *)Data;
151
152 while (Len > sizeof (UINT32)) {
153 IoWrite32 (FW_PORT, *LData++);
154 Len -= sizeof (UINT32);
155 }
156
157 if (Len > 0) {
158 IoWrite32 (FW_PORT, BIov_Send_Rem (LData, Len));
159 }
160}
161
165STATIC
166VOID
168 IN BIO_VEC b[]
169 )
170{
171 INT32 i;
172
173 if (b != NULL) {
174 for (i = 0; b[i].Base; i++) {
175 BIov_Send (b[i].Base, b[i].Len);
176 }
177 }
178}
179
183STATIC
184VOID
185EFIAPI
187 IN UINT32 OpCode,
188 IN BIO_VEC Data[]
189 )
190{
191 BIO_VEC hIov[4];
192 UINT32 Hdr[3];
193 UINT32 i;
194
195 /* Set up header as an iovec */
196 for (i = 0; i < 3; i++) {
197 hIov[i].Base = &Hdr[i];
198 hIov[i].Len = sizeof (Hdr[0]);
199 }
200
201 hIov[i].Base = NULL;
202 hIov[i].Len = 0;
203
204 /* Initialize header */
205 Hdr[0] = BIov_WLen (hIov) + BIov_WLen (Data);
206 Hdr[1] = (UINT32)OpCode;
207 Hdr[2] = mBhyveFwCtlTxid;
208
209 /* Send header and data */
210 BIov_SendAll (hIov);
211 BIov_SendAll (Data);
212}
213
217STATIC
218RETURN_STATUS
219EFIAPI
221 OUT MSG_RX_HDR *Rhdr,
222 OUT BIO_VEC Data[]
223 )
224{
225 RETURN_STATUS Status;
226 UINT32 *Dp;
227 UINT32 Rd;
228 UINT32 remLen;
229 INT32 oLen;
230 INT32 xLen;
231
232 Rd = IoRead32 (FW_PORT);
233 if (Rd < sizeof (MSG_RX_HDR)) {
234 }
235
236 /* Read in header and setup initial error */
237 Rhdr->Sz = Rd;
238 Rhdr->Op = IoRead32 (FW_PORT);
239 Rhdr->TxId = IoRead32 (FW_PORT);
240 Rhdr->Err = IoRead32 (FW_PORT);
241
242 /* Convert transport errno into UEFI error status */
243 Status = BhyveFwCtl_CvtErr (Rhdr->Err);
244
245 remLen = Rd - sizeof (MSG_RX_HDR);
246 xLen = 0;
247
248 /*
249 * A few cases to handle:
250 * - the user didn't supply a read buffer
251 * - the buffer is too small for the response
252 * - the response is zero-length
253 */
254 if (Data != NULL) {
255 Dp = (UINT32 *)Data[0].Base;
256 oLen = remLen;
257 if (remLen > Data[0].Len) {
259 xLen = remLen - Data[0].Len;
260 oLen = remLen = Data[0].Len;
261 }
262
263 while (remLen > 0) {
264 *Dp++ = IoRead32 (FW_PORT);
265 remLen -= sizeof (UINT32);
266 }
267
268 Data[0].Len = oLen;
269 } else {
270 /* No user data, but data returned - drop */
271 if (remLen > 0) {
273 xLen = remLen;
274 }
275 }
276
277 /* Drop additional data */
278 while (xLen > 0) {
279 (void)IoRead32 (FW_PORT);
280 xLen -= sizeof (UINT32);
281 }
282
283 return Status;
284}
285
286STATIC
287RETURN_STATUS
288EFIAPI
289BhyveFwCtl_Msg (
290 IN UINT32 OpCode,
291 IN BIO_VEC Sdata[],
292 OUT BIO_VEC Rdata[]
293 )
294{
295 MSG_RX_HDR Rh;
296 RETURN_STATUS Status;
297
298 Status = RETURN_SUCCESS;
299
300 BhyveFwCtl_MsgSend (OpCode, Sdata);
301 Status = BhyveFwCtl_MsgRecv (&Rh, Rdata);
302
303 mBhyveFwCtlTxid++;
304
305 return Status;
306}
307
308STATIC
309RETURN_STATUS
310EFIAPI
311BhyveFwCtlGetLen (
312 IN CONST CHAR8 *Name,
313 IN OUT UINT32 *Size
314 )
315{
316 BIO_VEC Req[2], Resp[2];
317 RETURN_STATUS Status;
318
319 Req[0].Base = (VOID *)Name;
320 Req[0].Len = (UINT32)AsciiStrLen (Name) + 1;
321 Req[1].Base = NULL;
322
323 Resp[0].Base = Size;
324 Resp[0].Len = sizeof (UINT32);
325 Resp[1].Base = NULL;
326
327 Status = BhyveFwCtl_Msg (OP_GET_LEN, Req, Resp);
328
329 return Status;
330}
331
332#define FMAXSZ 1024
333STATIC struct {
334 UINT64 fSize;
335 UINT32 fData[FMAXSZ];
336} FwGetvalBuf;
337
338STATIC
339RETURN_STATUS
340EFIAPI
341BhyveFwCtlGetVal (
342 IN CONST CHAR8 *Name,
343 OUT VOID *Item,
344 IN OUT UINT32 *Size
345 )
346{
347 BIO_VEC Req[2];
348 BIO_VEC Resp[2];
349 RETURN_STATUS Status;
350
351 /* Make sure temp buffer is larger than passed-in size */
352 if (*Size > sizeof (FwGetvalBuf.fData)) {
354 }
355
356 Req[0].Base = (VOID *)Name;
357 Req[0].Len = (UINT32)AsciiStrLen (Name) + 1;
358 Req[1].Base = NULL;
359
360 Resp[0].Base = &FwGetvalBuf;
361 Resp[0].Len = sizeof (UINT64) + *Size;
362 Resp[1].Base = NULL;
363
364 Status = BhyveFwCtl_Msg (OP_GET, Req, Resp);
365
366 /*
367 * Copy out data on success (or on a truncated message).
368 * XXX This step can be eliminted with Msg() supporting
369 * multiple iovecs.
370 */
371 if ((Status == RETURN_SUCCESS) || (Status == RETURN_BUFFER_TOO_SMALL)) {
372 *Size = (UINT32)FwGetvalBuf.fSize;
373 CopyMem (Item, FwGetvalBuf.fData, *Size);
374 }
375
376 return Status;
377}
378
382RETURN_STATUS
383EFIAPI
385 IN CONST CHAR8 *Name,
386 OUT VOID *Item,
387 IN OUT UINTN *Size
388 )
389{
390 RETURN_STATUS Status;
391
392 if (mBhyveFwCtlSupported == FALSE) {
393 return RETURN_UNSUPPORTED;
394 }
395
396 if (Item == NULL) {
397 Status = BhyveFwCtlGetLen (Name, (UINT32 *)Size);
398 } else {
399 Status = BhyveFwCtlGetVal (Name, Item, (UINT32 *)Size);
400 }
401
402 return Status;
403}
404
409RETURN_STATUS
410EFIAPI
412 VOID
413 )
414{
415 UINT32 i;
416 UINT8 ch;
417
418 DEBUG ((DEBUG_INFO, "FwCtlInitialize\n"));
419
420 IoWrite16 (FW_PORT, 0x0000);
421 for (i = 0; i < 4; i++) {
422 ch = IoRead8 (FW_IPORT);
423 if (ch != mBhyveSig[i]) {
424 DEBUG ((DEBUG_INFO, "Host f/w sig mismatch %c/%c\n", ch, mBhyveSig[i]));
425 return RETURN_SUCCESS;
426 }
427 }
428
429 mBhyveFwCtlSupported = TRUE;
430
431 return RETURN_SUCCESS;
432}
UINT64 UINTN
UINTN EFIAPI AsciiStrLen(IN CONST CHAR8 *String)
Definition: String.c:641
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
RETURN_STATUS EFIAPI BhyveFwCtlInitialize(VOID)
STATIC VOID EFIAPI BhyveFwCtl_MsgSend(IN UINT32 OpCode, IN BIO_VEC Data[])
STATIC VOID BIov_SendAll(IN BIO_VEC b[])
STATIC RETURN_STATUS EFIAPI BhyveFwCtl_MsgRecv(OUT MSG_RX_HDR *Rhdr, OUT BIO_VEC Data[])
STATIC UINT32 BIov_Send_Rem(IN UINT32 *Data, IN UINT32 Len)
STATIC VOID BIov_Send(IN char *Data, IN UINT32 Len)
RETURN_STATUS EFIAPI BhyveFwCtlGet(IN CONST CHAR8 *Name, OUT VOID *Item, IN OUT UINTN *Size)
UINT8 EFIAPI IoRead8(IN UINTN Port)
Definition: IoLibArmVirt.c:175
UINT32 EFIAPI IoRead32(IN UINTN Port)
Definition: IoLibArmVirt.c:275
UINT32 EFIAPI IoWrite32(IN UINTN Port, IN UINT32 Value)
Definition: IoLibArmVirt.c:300
UINT16 EFIAPI IoWrite16(IN UINTN Port, IN UINT16 Value)
Definition: IoLibArmVirt.c:250
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define RETURN_BUFFER_TOO_SMALL
Definition: Base.h:1093
#define STATIC
Definition: Base.h:264
#define RETURN_PROTOCOL_ERROR
Definition: Base.h:1192
#define RETURN_NOT_FOUND
Definition: Base.h:1142
#define RETURN_UNSUPPORTED
Definition: Base.h:1081
#define RETURN_SUCCESS
Definition: Base.h:1066
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define RETURN_INVALID_PARAMETER
Definition: Base.h:1076
#define DEBUG(Expression)
Definition: DebugLib.h:434