]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.c
98022354cf31003d259ff63ede1961fa73e7bb7b
[mirror_edk2.git] / OvmfPkg / Library / XenConsoleSerialPortLib / XenConsoleSerialPortLib.c
1 /** @file
2 Xen console SerialPortLib instance
3
4 Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
5
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include <Base.h>
17 #include <Uefi/UefiBaseType.h>
18
19 #include <Library/BaseLib.h>
20 #include <Library/SerialPortLib.h>
21 #include <Library/XenHypercallLib.h>
22
23 #include <IndustryStandard/Xen/io/console.h>
24 #include <IndustryStandard/Xen/hvm/params.h>
25 #include <IndustryStandard/Xen/event_channel.h>
26
27 //
28 // The code below expects these global variables to be mutable, even in the case
29 // that we have been incorporated into SEC or PEIM phase modules (which is
30 // allowed by our INF description). While this is a dangerous assumption to make
31 // in general, it is actually fine for the Xen domU (guest) environment that
32 // this module is intended for, as UEFI always executes from DRAM in that case.
33 //
34 STATIC evtchn_send_t mXenConsoleEventChain;
35 STATIC struct xencons_interface *mXenConsoleInterface;
36
37 RETURN_STATUS
38 EFIAPI
39 SerialPortInitialize (
40 VOID
41 )
42 {
43 if (!mXenConsoleInterface) {
44 mXenConsoleEventChain.port = (UINT32)XenHypercallHvmGetParam (HVM_PARAM_CONSOLE_EVTCHN);
45 mXenConsoleInterface = (struct xencons_interface *)(UINTN)
46 (XenHypercallHvmGetParam (HVM_PARAM_CONSOLE_PFN) << EFI_PAGE_SHIFT);
47
48 //
49 // No point in ASSERT'ing here as we won't be seeing the output
50 //
51 }
52 return RETURN_SUCCESS;
53 }
54
55 /**
56 Write data to serial device.
57
58 @param Buffer Point of data buffer which need to be written.
59 @param NumberOfBytes Number of output bytes which are cached in Buffer.
60
61 @retval 0 Write data failed.
62 @retval !0 Actual number of bytes written to serial device.
63
64 **/
65 UINTN
66 EFIAPI
67 SerialPortWrite (
68 IN UINT8 *Buffer,
69 IN UINTN NumberOfBytes
70 )
71 {
72 XENCONS_RING_IDX Consumer, Producer;
73 UINTN Sent;
74
75 if (!mXenConsoleInterface) {
76 return 0;
77 }
78
79 Consumer = mXenConsoleInterface->out_cons;
80 Producer = mXenConsoleInterface->out_prod;
81
82 MemoryFence ();
83
84 Sent = 0;
85 while (Sent < NumberOfBytes && ((Producer - Consumer) < sizeof (mXenConsoleInterface->out)))
86 mXenConsoleInterface->out[MASK_XENCONS_IDX(Producer++, mXenConsoleInterface->out)] = Buffer[Sent++];
87
88 MemoryFence ();
89
90 mXenConsoleInterface->out_prod = Producer;
91
92 if (Sent > 0) {
93 XenHypercallEventChannelOp (EVTCHNOP_send, &mXenConsoleEventChain);
94 }
95
96 return Sent;
97 }
98
99 /**
100 Read data from serial device and save the data in buffer.
101
102 @param Buffer Point of data buffer which need to be written.
103 @param NumberOfBytes Size of Buffer[].
104
105 @retval 0 Read data failed.
106 @retval !0 Actual number of bytes read from serial device.
107
108 **/
109 UINTN
110 EFIAPI
111 SerialPortRead (
112 OUT UINT8 *Buffer,
113 IN UINTN NumberOfBytes
114 )
115 {
116 XENCONS_RING_IDX Consumer, Producer;
117 UINTN Received;
118
119 if (!mXenConsoleInterface) {
120 return 0;
121 }
122
123 Consumer = mXenConsoleInterface->in_cons;
124 Producer = mXenConsoleInterface->in_prod;
125
126 MemoryFence ();
127
128 Received = 0;
129 while (Received < NumberOfBytes && Consumer < Producer)
130 Buffer[Received++] = mXenConsoleInterface->in[MASK_XENCONS_IDX(Consumer++, mXenConsoleInterface->in)];
131
132 MemoryFence ();
133
134 mXenConsoleInterface->in_cons = Consumer;
135
136 XenHypercallEventChannelOp (EVTCHNOP_send, &mXenConsoleEventChain);
137
138 return Received;
139 }
140
141 /**
142 Check to see if any data is available to be read from the debug device.
143
144 @retval TRUE At least one byte of data is available to be read
145 @retval FALSE No data is available to be read
146
147 **/
148 BOOLEAN
149 EFIAPI
150 SerialPortPoll (
151 VOID
152 )
153 {
154 return mXenConsoleInterface &&
155 mXenConsoleInterface->in_cons != mXenConsoleInterface->in_prod;
156 }