summaryrefslogtreecommitdiff
path: root/Core/EM/StatusCode/SerialStatusCode.c
blob: 1aefcdee938feaba84c7242cf0ceb9517db33c7b (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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
//**********************************************************************
//**********************************************************************
//**                                                                  **
//**        (C)Copyright 1985-2009, American Megatrends, Inc.         **
//**                                                                  **
//**                       All Rights Reserved.                       **
//**                                                                  **
//**      5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093        **
//**                                                                  **
//**                       Phone: (770)-246-8600                      **
//**                                                                  **
//**********************************************************************
//**********************************************************************

//**********************************************************************
// $Header: /Alaska/BIN/Modules/StatusCode/SerialStatusCode.c 13    1/22/13 4:56p Oleksiyy $
//
// $Revision: 13 $
//
// $Date: 1/22/13 4:56p $
//*****************************************************************************
// Revision History
// ----------------
// $Log: /Alaska/BIN/Modules/StatusCode/SerialStatusCode.c $
// 
// 13    1/22/13 4:56p Oleksiyy
// [TAG]	EIP112774
// [Category]	Bug Fix
// [Severity:]	Normal
// [Symptom:]	CPU Exception occurs when TRACE is used in SMM Handler
// [Root Cause]	pBS, used in Delay function, do not exist during  runtime.
// [Solution]	Delay replaced with dummy "for" cycle in SerialOutput
// function.
// [Files]	StatusCodeCommon.c
// 
// 
// 12    3/18/11 12:33p Oleksiyy
// [TAG]  		EIP54959 
// [Category]  	Bug Fix
// [Severity]  	Normal
// [Symptom]  	No debug output in projects with no SIO.
// [RootCause]  	Dependency from SIO added to sdl.
// [Solution]  	Dependency from SIO removed from SerialOutput eLink and
// moved directly to  SerialOutput function body.
// 
// [Files]  		SeriaStatusCode.c and StatusCode.sdl
// 
// 11    10/01/10 6:08p Oleksiyy
// Issue Number:  43888
// 
// Category:  Bug Fix
// 
// Symptom:  System hang endlesly if com port not working and Debug is ON
// 
// Severity:  Normal
// 
// Root Cause:  Infinite loop in SerialOutput.
// 
// Solution:  SEND_BYTE_DELEY and SEND_BYTE_ATEMPTS values is added. In
// SendByte SEND_BYTE_DELEY atempts will be made in loop until the serial
// port is ready for the next byte. 
// 
// Files:  SeriaStatusCode.c, StausCode.sdl
// 
// 10    5/03/10 1:17a Rameshr
// Issue:Need to handle different Base Hz values for SerialStatusCode,
// Terminal, and Legacy Serial Redirection.
// Solution: Moved Uart input clock into Core.sdl token and used in all
// the above modules.
// EIP: 37332
// 
// 9     11/13/09 4:30p Felixp
// Buffer overflow protection is added (calls to Sprintf replaced with
// Sprintf_s).
// 
// 8     7/09/09 5:18p Oleksiyy
// Files clean-up some headers added
//
// 7     3/05/09 1:41p Felixp
// Major update of the StatusCode module.
// See Label Comments and Release Notes in StatusCode.chm for more
// details.
//
// 5     8/24/06 3:33p Felixp
// Preliminary x64 support (work in progress)
//
// 4     5/04/06 12:01p Robert
// Updated to support core release 4.4.10
//
// 15    6/07/05 7:23p Felixp
// Moving toward generic Status Code module
//
// 13    1/20/05 11:31a Felixp
// StatusCodes.h renamed to AmiStatusCode.h
//
// 12    1/18/05 3:21p Felixp
// PrintDebugMessage renamed to Trace
//
// 11    11/15/04 10:35 Dougm
// Change the initialization of SIO
//
// 9     11/10/04 5:21p Felixp
// Serial output implementation changed to send '\r' before every '\n'
//
//*****************************************************************************
//<AMI_FHDR_START>
//
// Name: SerialStatusCode.c
//
// Description: Implementation of the serial port status code handler.
//
//<AMI_FHDR_END>
//*****************************************************************************
#include <PEI.h>
#include <StatusCodes.h>
#include <AMILIB.h>
#include <token.h>

//----------------------------------------------------------------------------
// Local constant definitions
#define CONFIG_PORT0        0x2E
#define INDEX_PORT0         0x2E
#define DATA_PORT0          0x2F
#define SEND_BYTE_DELEY     0x200
#define SEND_BYTE_ATEMPTS   0x10

#ifdef DEBUG_COM_PORT_ADDR
#define COM_BASE_ADDR DEBUG_COM_PORT_ADDR
#else
#define COM_BASE_ADDR       0x03f8
#endif
#define LSR_OFFSET          0x05
#define LCR_OFFSET          0x03
#define DIV_MSB             0x01
#define DIV_LSB             0

#define TRANSMIT_READY_BIT  0x020
#ifdef UART_INPUT_CLOCK
UINTN   UartInputClock=UART_INPUT_CLOCK;
#else
//
// Set the default value((24000000/13)MHz input clock) if the UART_INPUT_CLOCK SDL token is not present.
//
UINTN   UartInputClock=1843200;
#endif

#define BAUD_RATE_DIVISOR   115200

#define DATA_BITS           3   // 0 - 5 bits / 1 - 6 bits
// 2 - 7 bits / 3 - 8 bits
// RSP BUGBUG #define STOP_BIT          0   // 0 - 1 stop bit
#define STOP_BIT            1   // 0 - 1 stop bit
// 1 - mutiple bits depending on the databits
#define PARITY_BITS         0   // 0 - None / 1 enables parity
#define BREAK_BIT           0   // 0 - No break
#define DLAB_BIT            1   // 0 - Divisor Latch Disabled
// 1 - Divisor Latch Enabled

//----------------------------------------------------------------------------
// Module specific type definitions


//----------------------------------------------------------------------------
// Function Prototypes
EFI_STATUS SerialData(
    IN  EFI_STATUS_CODE_TYPE    Type,
    IN  EFI_STATUS_CODE_VALUE   Value,
    IN  EFI_STATUS_CODE_DATA    *Data,
    OUT UINT8                   *String
);
VOID Delay(EFI_PEI_SERVICES **PeiServices, UINT32 Microseconds);
//<AMI_PHDR_START>
//----------------------------------------------------------------------------
// Procedure: SendByte
//
// Description: Writes the given byte to the serial port
//
// Input:
//      UINT8 Byte - a byte to write to the serial port
//
// Output: TRUE - Byte was sent, FALSE - serial port was not ready
//
//----------------------------------------------------------------------------
//<AMI_PHDR_END>
BOOLEAN SendByte(UINT8 Byte)
{
    UINT8 Buffer8;
    UINT32 Cntr = 0;
    
    do
    {
        // Read the ready signal to see if the serial port is
        // ready for the next byte.
        Buffer8 = IoRead8(COM_BASE_ADDR + LSR_OFFSET);
        // Increment timeout counter.
        Cntr++;
        // Loop until the serial port is ready for the next byte.
    }
    while ( (Cntr < SEND_BYTE_DELEY) && 
            ((Buffer8 & TRANSMIT_READY_BIT) == FALSE) );
    if (Cntr < SEND_BYTE_DELEY){
       
        IoWrite8(COM_BASE_ADDR, Byte);
        return TRUE;
    } else return FALSE;

}

//<AMI_PHDR_START>
//----------------------------------------------------------------------------
// Procedure:   SerialOutput
//
// Description: Writes the given string to the serial port byte by byte
//              using the function SendByte.
//
// Input:
//      IN EFI_PEI_SERVICES **PeiServices - pointer to the PEI Boot Services table
//      CHAR8 *String - String to be sent over the serial port
//
// Output: EFI_SUCCESS
//
//----------------------------------------------------------------------------
//<AMI_PHDR_END>
EFI_STATUS SerialOutput(
    IN EFI_PEI_SERVICES **PeiServices,
    IN CHAR8 *String
)
{
#if SERIAL_STATUS_SUPPORT
    UINT8       *Buffer, i;
    UINT32       Delay;
    BOOLEAN     ByteSent;
    
    if (String == NULL) return EFI_SUCCESS;
    // first make data useable
    Buffer = String;
    
    // now send data one byte at a time until the string hits the end of string
    // or we hit the max number of characters
    while (*Buffer)
    {
        // replace "\n" with "\r\n"
        for (i = 0; i <= SEND_BYTE_ATEMPTS; i++){
            ByteSent = TRUE;

            if (*Buffer=='\n') ByteSent = SendByte('\r');
            
            if (ByteSent)  ByteSent = SendByte(*Buffer);
            
            if (ByteSent) break;
            else
                for (Delay = 0; Delay <= 100000; Delay++);
        }
        
        // move Data pointer to the next byte if previous was sent
        if (ByteSent) Buffer++;
        else return EFI_SUCCESS;
    }
#endif    
    return EFI_SUCCESS;
}

//<AMI_PHDR_START>
//----------------------------------------------------------------------------
// Procedure:   SerialStatusInit
//
// Description:
//   The function programs the stop bits, data bits, and baud rate
//   of the com port and outputs the debug message "Status Code Available."
//   NOTE: This function does not assumes Super I/O has already been initialized.
//
// Input:
//      IN EFI_FFS_FILE_HEADER *FfsHeader
//      IN EFI_PEI_SERVICES **PeiServices - pointer to the PEI Boot Services table
// Output:
//      EFI_SUCCESS
//
//----------------------------------------------------------------------------
//<AMI_PHDR_END>
EFI_STATUS SerialStatusInit(
    IN EFI_FFS_FILE_HEADER *FfsHeader,
    IN EFI_PEI_SERVICES **PeiServices
)
{
    UINT8   Data8;
    UINT16  Divisor;
    UINTN   Remainder;

    //
    // Compute the baud rate divisor.
    //
    Divisor = (UINT32) Div64 (UartInputClock,
                                ((UINT32)BAUD_RATE_DIVISOR * 16), 
                                &Remainder);
    if ( Remainder ) {
        Divisor += 1;
    }
    
    if ((Divisor == 0) || (Divisor & 0xffff0000)) {
        return EFI_INVALID_PARAMETER;
    }
    
    // Programm Serial port
    // Set Line Control Register (LCR)
    Data8 = DLAB_BIT << 7 | STOP_BIT << 2 | DATA_BITS;
    IoWrite8(COM_BASE_ADDR + LCR_OFFSET, Data8 );
    
    IoWrite8(COM_BASE_ADDR + DIV_LSB, Divisor & 0xFF);
    IoWrite8(COM_BASE_ADDR + DIV_MSB, Divisor >> 8);
    
    // Clear DLAB bit in LCR
    Data8 &= ~((UINT8)DLAB_BIT << 7);
    IoWrite8(COM_BASE_ADDR + LCR_OFFSET, Data8 );
#ifdef EFI_DEBUG
#ifndef PEI_STATUS_CODE
    SerialOutput(PeiServices, "DXE Status Code Available\n");
#else
    SerialOutput(PeiServices, "Status Code Available\n");
#endif
#endif
    return EFI_SUCCESS;
}

//<AMI_PHDR_START>
//----------------------------------------------------------------------------
// Procedure:   SerialStatusInit
//
// Description:
//   The function sends "Checkpoint #" string to serial port
//
// Input:
//      IN EFI_PEI_SERVICES **PeiServices - pointer to the PEI Boot Services table
//      UINT8 Checkpoint - Checkpoint to send
// Output:
//      VOID
//
//----------------------------------------------------------------------------
//<AMI_PHDR_END>
VOID SerialCheckpoint(EFI_PEI_SERVICES **PeiServices, UINT8 Checkpoint)
{
    char s[20];
    Sprintf_s(s, sizeof(s), "Checkpoint %X\n",Checkpoint);
    SerialOutput(PeiServices, s);
}

//**********************************************************************
//**********************************************************************
//**                                                                  **
//**        (C)Copyright 1985-2009, American Megatrends, Inc.         **
//**                                                                  **
//**                       All Rights Reserved.                       **
//**                                                                  **
//**      5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093        **
//**                                                                  **
//**                       Phone: (770)-246-8600                      **
//**                                                                  **
//**********************************************************************
//**********************************************************************