2 Debug Port Library implementation based on serial port.
4 Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Library/DebugCommunicationLib.h>
18 #include <Library/SerialPortLib.h>
19 #include <Library/TimerLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/BaseLib.h>
22 #include <Library/BaseMemoryLib.h>
26 // The internal data structure of DEBUG_PORT_HANDLE, which stores some
27 // important datum which are used across various phases.
29 typedef struct _SERIAL_DEBUG_PORT_HANDLE
{
33 UINT64 TimerFrequency
;
35 BOOLEAN TimerCountDown
;
36 } SERIAL_DEBUG_PORT_HANDLE
;
40 // The global variable which can be used after memory is ready.
42 SERIAL_DEBUG_PORT_HANDLE mSerialDebugPortHandle
;
45 Check if the timer is timeout.
47 @param[in] SerialDebugPortHandle Pointer to Serial Debug port handle
48 @param[in] Timer The start timer from the begin.
49 @param[in] TimeoutTicker Ticker number need time out.
51 @return TRUE Timer time out occurs.
52 @retval FALSE Timer does not time out.
57 IN SERIAL_DEBUG_PORT_HANDLE
*SerialDebugPortHandle
,
59 IN UINT64 TimeoutTicker
65 CurrentTimer
= GetPerformanceCounter ();
67 if (SerialDebugPortHandle
->TimerCountDown
) {
69 // The timer counter counts down. Check for roll over condition.
71 if (CurrentTimer
< Timer
) {
72 Delta
= Timer
- CurrentTimer
;
75 // Handle one roll-over.
77 Delta
= SerialDebugPortHandle
->TimerCycle
- (CurrentTimer
- Timer
);
81 // The timer counter counts up. Check for roll over condition.
83 if (CurrentTimer
> Timer
) {
84 Delta
= CurrentTimer
- Timer
;
87 // Handle one roll-over.
89 Delta
= SerialDebugPortHandle
->TimerCycle
- (Timer
- CurrentTimer
);
93 return (BOOLEAN
) (Delta
>= TimeoutTicker
);
97 Initialize the debug port.
99 This function will initialize debug port to get it ready for data transmition. If
100 certain Debug Communication Library instance has to save some private data in the
101 stack, this function must work on the mode that doesn't return to the caller, then
102 the caller needs to wrap up all rest of logic after DebugPortInitialize() into one
103 function and pass it into DebugPortInitialize(). DebugPortInitialize() is
104 responsible to invoke the passing-in funciton at the end of DebugPortInitialize().
106 If the paramter Function is not NULL, Debug Communication Libary instance will
107 invoke it by passing in the Context to be the first parameter. Debug Communication
108 Library instance could create one debug port handle to be the second parameter
109 passing into the Function. Debug Communication Library instance also could pass
110 NULL to be the second parameter if it doesn't create the debug port handle.
112 If the parameter Function is NULL, and Context is not NULL. At this time, Context
113 is the debug port handle created by the previous Debug Communication Library
115 a) If the instance can understand and continue use the private data of the previous
116 instance, it could return the same handle as passed in (as Context parameter).
117 b) If the instance does not understand, or does not want to continue use the
118 private data of the previous instance, it could ignore the input Context parameter
119 and create the new hanlde to be returned.
121 If Function() is NULL and Context is NULL, Debug Communication Library could create a
122 new handle and return it. NULL is also a valid handle to be returned.
124 @param[in] Context Context needed by callback function; it was optional.
125 @param[in] Function Continue function called by Debug Communication library;
128 @return The debug port handle created by Debug Communication Library if Function
134 DebugPortInitialize (
136 IN DEBUG_PORT_CONTINUE Function
139 RETURN_STATUS Status
;
140 SERIAL_DEBUG_PORT_HANDLE Handle
;
141 SERIAL_DEBUG_PORT_HANDLE
*SerialDebugPortHandle
;
142 UINT64 TimerStartValue
;
143 UINT64 TimerEndValue
;
146 // Validate the PCD PcdDebugPortHandleBufferSize value
148 ASSERT (PcdGet16 (PcdDebugPortHandleBufferSize
) == sizeof (SERIAL_DEBUG_PORT_HANDLE
));
150 if (Context
!= NULL
&& Function
== NULL
) {
151 SerialDebugPortHandle
= (SERIAL_DEBUG_PORT_HANDLE
*)Context
;
153 ZeroMem (&Handle
, sizeof (SERIAL_DEBUG_PORT_HANDLE
));
154 SerialDebugPortHandle
= &Handle
;
156 SerialDebugPortHandle
->TimerFrequency
= GetPerformanceCounterProperties (
160 DEBUG ((EFI_D_INFO
, "Serial Debug Port: TimerFrequency = 0x%lx\n", SerialDebugPortHandle
->TimerFrequency
));
161 DEBUG ((EFI_D_INFO
, "Serial Debug Port: TimerStartValue = 0x%lx\n", TimerStartValue
));
162 DEBUG ((EFI_D_INFO
, "Serial Debug Port: TimerEndValue = 0x%lx\n", TimerEndValue
));
164 if (TimerEndValue
< TimerStartValue
) {
165 SerialDebugPortHandle
->TimerCountDown
= TRUE
;
166 SerialDebugPortHandle
->TimerCycle
= TimerStartValue
- TimerEndValue
;
168 SerialDebugPortHandle
->TimerCountDown
= FALSE
;
169 SerialDebugPortHandle
->TimerCycle
= TimerEndValue
- TimerStartValue
;
172 if (Function
== NULL
&& Context
!= NULL
) {
173 return (DEBUG_PORT_HANDLE
*) Context
;
176 Status
= SerialPortInitialize ();
177 if (RETURN_ERROR(Status
)) {
178 DEBUG ((EFI_D_ERROR
, "Debug Serial Port: Initialization failed!\n"));
181 if (Function
!= NULL
) {
182 Function (Context
, SerialDebugPortHandle
);
184 CopyMem(&mSerialDebugPortHandle
, SerialDebugPortHandle
, sizeof (SERIAL_DEBUG_PORT_HANDLE
));
187 return (DEBUG_PORT_HANDLE
)(UINTN
)&mSerialDebugPortHandle
;
191 Read data from debug device and save the datas in buffer.
193 Reads NumberOfBytes data bytes from a debug device into the buffer
194 specified by Buffer. The number of bytes actually read is returned.
195 If the return value is less than NumberOfBytes, then the rest operation failed.
196 If NumberOfBytes is zero, then return 0.
198 @param Handle Debug port handle.
199 @param Buffer Pointer to the data buffer to store the data read from the debug device.
200 @param NumberOfBytes Number of bytes which will be read.
201 @param Timeout Timeout value for reading from debug device. It unit is Microsecond.
203 @retval 0 Read data failed, no data is to be read.
204 @retval >0 Actual number of bytes read from debug device.
209 DebugPortReadBuffer (
210 IN DEBUG_PORT_HANDLE Handle
,
212 IN UINTN NumberOfBytes
,
216 SERIAL_DEBUG_PORT_HANDLE
*SerialDebugPortHandle
;
219 UINT64 TimeoutTicker
;
223 // If Handle is NULL, it means memory is ready for use.
224 // Use global variable to store handle value.
226 if (Handle
== NULL
) {
227 SerialDebugPortHandle
= &mSerialDebugPortHandle
;
229 SerialDebugPortHandle
= (SERIAL_DEBUG_PORT_HANDLE
*)Handle
;
236 Begin
= GetPerformanceCounter ();
237 TimeoutTicker
= DivU64x32 (
239 SerialDebugPortHandle
->TimerFrequency
,
244 TimerRound
= DivU64x64Remainder (
246 DivU64x32 (SerialDebugPortHandle
->TimerCycle
, 2),
251 while (Index
< NumberOfBytes
) {
252 if (SerialPortPoll () || Timeout
== 0) {
253 SerialPortRead (Buffer
+ Index
, 1);
257 if (TimerRound
== 0) {
258 if (IsTimerTimeout (SerialDebugPortHandle
, Begin
, TimeoutTicker
)) {
260 // If time out occurs.
265 if (IsTimerTimeout (SerialDebugPortHandle
, Begin
, DivU64x32 (SerialDebugPortHandle
->TimerCycle
, 2))) {
275 Write data from buffer to debug device.
277 Writes NumberOfBytes data bytes from Buffer to the debug device.
278 The number of bytes actually written to the debug device is returned.
279 If the return value is less than NumberOfBytes, then the write operation failed.
280 If NumberOfBytes is zero, then return 0.
282 @param Handle Debug port handle.
283 @param Buffer Pointer to the data buffer to be written.
284 @param NumberOfBytes Number of bytes to written to the debug device.
286 @retval 0 NumberOfBytes is 0.
287 @retval >0 The number of bytes written to the debug device.
288 If this value is less than NumberOfBytes, then the read operation failed.
293 DebugPortWriteBuffer (
294 IN DEBUG_PORT_HANDLE Handle
,
296 IN UINTN NumberOfBytes
299 return SerialPortWrite (Buffer
, NumberOfBytes
);
303 Polls a debug device to see if there is any data waiting to be read.
305 Polls a debug device to see if there is any data waiting to be read.
306 If there is data waiting to be read from the debug device, then TRUE is returned.
307 If there is no data waiting to be read from the debug device, then FALSE is returned.
309 @param Handle Debug port handle.
311 @retval TRUE Data is waiting to be read from the debug device.
312 @retval FALSE There is no data waiting to be read from the serial device.
317 DebugPortPollBuffer (
318 IN DEBUG_PORT_HANDLE Handle
321 return SerialPortPoll ();