]> git.proxmox.com Git - mirror_edk2.git/blob - CorebootModulePkg/SerialDxe/SerialIo.c
MdeModulePkg: Refine the code for DxeHttpLib
[mirror_edk2.git] / CorebootModulePkg / SerialDxe / SerialIo.c
1 /** @file
2 Serial driver that layers on top of a Serial Port Library instance.
3
4 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
5 Copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>
6 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
7
8 This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
12
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15
16 **/
17
18 #include <Library/UefiBootServicesTableLib.h>
19 #include <Library/SerialPortLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/PcdLib.h>
22 #include <Protocol/SerialIo.h>
23 #include <Protocol/DevicePath.h>
24
25 typedef struct {
26 VENDOR_DEVICE_PATH Guid;
27 UART_DEVICE_PATH Uart;
28 EFI_DEVICE_PATH_PROTOCOL End;
29 } SERIAL_DEVICE_PATH;
30
31 /**
32 Reset the serial device.
33
34 @param This Protocol instance pointer.
35
36 @retval EFI_SUCCESS The device was reset.
37 @retval EFI_DEVICE_ERROR The serial device could not be reset.
38
39 **/
40 EFI_STATUS
41 EFIAPI
42 SerialReset (
43 IN EFI_SERIAL_IO_PROTOCOL *This
44 );
45
46 /**
47 Sets the baud rate, receive FIFO depth, transmit/receive time out, parity,
48 data bits, and stop bits on a serial device.
49
50 @param This Protocol instance pointer.
51 @param BaudRate The requested baud rate. A BaudRate value of 0 will use the the
52 device's default interface speed.
53 @param ReceiveFifoDepth The requested depth of the FIFO on the receive side of the
54 serial interface. A ReceiveFifoDepth value of 0 will use
55 the device's default FIFO depth.
56 @param Timeout The requested time out for a single character in microseconds.
57 This timeout applies to both the transmit and receive side of the
58 interface. A Timeout value of 0 will use the device's default time
59 out value.
60 @param Parity The type of parity to use on this serial device. A Parity value of
61 DefaultParity will use the device's default parity value.
62 @param DataBits The number of data bits to use on the serial device. A DataBits
63 value of 0 will use the device's default data bit setting.
64 @param StopBits The number of stop bits to use on this serial device. A StopBits
65 value of DefaultStopBits will use the device's default number of
66 stop bits.
67
68 @retval EFI_SUCCESS The device was reset.
69 @retval EFI_DEVICE_ERROR The serial device could not be reset.
70
71 **/
72 EFI_STATUS
73 EFIAPI
74 SerialSetAttributes (
75 IN EFI_SERIAL_IO_PROTOCOL *This,
76 IN UINT64 BaudRate,
77 IN UINT32 ReceiveFifoDepth,
78 IN UINT32 Timeout,
79 IN EFI_PARITY_TYPE Parity,
80 IN UINT8 DataBits,
81 IN EFI_STOP_BITS_TYPE StopBits
82 );
83
84 /**
85 Set the control bits on a serial device
86
87 @param This Protocol instance pointer.
88 @param Control Set the bits of Control that are settable.
89
90 @retval EFI_SUCCESS The new control bits were set on the serial device.
91 @retval EFI_UNSUPPORTED The serial device does not support this operation.
92 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
93
94 **/
95 EFI_STATUS
96 EFIAPI
97 SerialSetControl (
98 IN EFI_SERIAL_IO_PROTOCOL *This,
99 IN UINT32 Control
100 );
101
102 /**
103 Retrieves the status of the control bits on a serial device
104
105 @param This Protocol instance pointer.
106 @param Control A pointer to return the current Control signals from the serial device.
107
108 @retval EFI_SUCCESS The control bits were read from the serial device.
109 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
110
111 **/
112 EFI_STATUS
113 EFIAPI
114 SerialGetControl (
115 IN EFI_SERIAL_IO_PROTOCOL *This,
116 OUT UINT32 *Control
117 );
118
119 /**
120 Writes data to a serial device.
121
122 @param This Protocol instance pointer.
123 @param BufferSize On input, the size of the Buffer. On output, the amount of
124 data actually written.
125 @param Buffer The buffer of data to write
126
127 @retval EFI_SUCCESS The data was written.
128 @retval EFI_DEVICE_ERROR The device reported an error.
129 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
130
131 **/
132 EFI_STATUS
133 EFIAPI
134 SerialWrite (
135 IN EFI_SERIAL_IO_PROTOCOL *This,
136 IN OUT UINTN *BufferSize,
137 IN VOID *Buffer
138 );
139
140 /**
141 Reads data from a serial device.
142
143 @param This Protocol instance pointer.
144 @param BufferSize On input, the size of the Buffer. On output, the amount of
145 data returned in Buffer.
146 @param Buffer The buffer to return the data into.
147
148 @retval EFI_SUCCESS The data was read.
149 @retval EFI_DEVICE_ERROR The device reported an error.
150 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
151
152 **/
153 EFI_STATUS
154 EFIAPI
155 SerialRead (
156 IN EFI_SERIAL_IO_PROTOCOL *This,
157 IN OUT UINTN *BufferSize,
158 OUT VOID *Buffer
159 );
160
161 EFI_HANDLE mSerialHandle = NULL;
162
163 SERIAL_DEVICE_PATH mSerialDevicePath = {
164 {
165 { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { sizeof (VENDOR_DEVICE_PATH), 0} },
166 EFI_CALLER_ID_GUID // Use the driver's GUID
167 },
168 {
169 { MESSAGING_DEVICE_PATH, MSG_UART_DP, { sizeof (UART_DEVICE_PATH), 0} },
170 0, // Reserved
171 0, // BaudRate
172 0, // DataBits
173 0, // Parity
174 0 // StopBits
175 },
176 { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 } }
177 };
178
179 //
180 // Template used to initialize the Serial IO protocols.
181 //
182 EFI_SERIAL_IO_MODE mSerialIoMode = {
183 //
184 // value field set in SerialDxeInitialize()?
185 //--------- ------------------- -----------------------------
186 0, // ControlMask
187 1000 * 1000, // Timeout
188 0, // BaudRate yes
189 1, // ReceiveFifoDepth
190 0, // DataBits yes
191 0, // Parity yes
192 0 // StopBits yes
193 };
194
195 EFI_SERIAL_IO_PROTOCOL mSerialIoTemplate = {
196 SERIAL_IO_INTERFACE_REVISION,
197 SerialReset,
198 SerialSetAttributes,
199 SerialSetControl,
200 SerialGetControl,
201 SerialWrite,
202 SerialRead,
203 &mSerialIoMode
204 };
205
206 /**
207 Reset the serial device.
208
209 @param This Protocol instance pointer.
210
211 @retval EFI_SUCCESS The device was reset.
212 @retval EFI_DEVICE_ERROR The serial device could not be reset.
213
214 **/
215 EFI_STATUS
216 EFIAPI
217 SerialReset (
218 IN EFI_SERIAL_IO_PROTOCOL *This
219 )
220 {
221 EFI_STATUS Status;
222 EFI_TPL Tpl;
223
224 Status = SerialPortInitialize ();
225 if (EFI_ERROR (Status)) {
226 return Status;
227 }
228
229 //
230 // Set the Serial I/O mode and update the device path
231 //
232
233 Tpl = gBS->RaiseTPL (TPL_NOTIFY);
234
235 //
236 // Set the Serial I/O mode
237 //
238 This->Mode->ReceiveFifoDepth = 1;
239 This->Mode->Timeout = 1000 * 1000;
240 This->Mode->BaudRate = PcdGet64 (PcdUartDefaultBaudRate);
241 This->Mode->DataBits = (UINT32) PcdGet8 (PcdUartDefaultDataBits);
242 This->Mode->Parity = (UINT32) PcdGet8 (PcdUartDefaultParity);
243 This->Mode->StopBits = (UINT32) PcdGet8 (PcdUartDefaultStopBits);
244
245 //
246 // Check if the device path has actually changed
247 //
248 if (mSerialDevicePath.Uart.BaudRate == This->Mode->BaudRate &&
249 mSerialDevicePath.Uart.DataBits == (UINT8) This->Mode->DataBits &&
250 mSerialDevicePath.Uart.Parity == (UINT8) This->Mode->Parity &&
251 mSerialDevicePath.Uart.StopBits == (UINT8) This->Mode->StopBits
252 ) {
253 gBS->RestoreTPL (Tpl);
254 return EFI_SUCCESS;
255 }
256
257 //
258 // Update the device path
259 //
260 mSerialDevicePath.Uart.BaudRate = This->Mode->BaudRate;
261 mSerialDevicePath.Uart.DataBits = (UINT8) This->Mode->DataBits;
262 mSerialDevicePath.Uart.Parity = (UINT8) This->Mode->Parity;
263 mSerialDevicePath.Uart.StopBits = (UINT8) This->Mode->StopBits;
264
265 Status = gBS->ReinstallProtocolInterface (
266 mSerialHandle,
267 &gEfiDevicePathProtocolGuid,
268 &mSerialDevicePath,
269 &mSerialDevicePath
270 );
271
272 gBS->RestoreTPL (Tpl);
273
274 return Status;
275 }
276
277 /**
278 Sets the baud rate, receive FIFO depth, transmit/receive time out, parity,
279 data bits, and stop bits on a serial device.
280
281 @param This Protocol instance pointer.
282 @param BaudRate The requested baud rate. A BaudRate value of 0 will use the the
283 device's default interface speed.
284 @param ReceiveFifoDepth The requested depth of the FIFO on the receive side of the
285 serial interface. A ReceiveFifoDepth value of 0 will use
286 the device's default FIFO depth.
287 @param Timeout The requested time out for a single character in microseconds.
288 This timeout applies to both the transmit and receive side of the
289 interface. A Timeout value of 0 will use the device's default time
290 out value.
291 @param Parity The type of parity to use on this serial device. A Parity value of
292 DefaultParity will use the device's default parity value.
293 @param DataBits The number of data bits to use on the serial device. A DataBits
294 value of 0 will use the device's default data bit setting.
295 @param StopBits The number of stop bits to use on this serial device. A StopBits
296 value of DefaultStopBits will use the device's default number of
297 stop bits.
298
299 @retval EFI_SUCCESS The device was reset.
300 @retval EFI_DEVICE_ERROR The serial device could not be reset.
301
302 **/
303 EFI_STATUS
304 EFIAPI
305 SerialSetAttributes (
306 IN EFI_SERIAL_IO_PROTOCOL *This,
307 IN UINT64 BaudRate,
308 IN UINT32 ReceiveFifoDepth,
309 IN UINT32 Timeout,
310 IN EFI_PARITY_TYPE Parity,
311 IN UINT8 DataBits,
312 IN EFI_STOP_BITS_TYPE StopBits
313 )
314 {
315 EFI_STATUS Status;
316 EFI_TPL Tpl;
317
318 Status = SerialPortSetAttributes (&BaudRate, &ReceiveFifoDepth, &Timeout, &Parity, &DataBits, &StopBits);
319 if (EFI_ERROR (Status)) {
320 return Status;
321 }
322
323 //
324 // Set the Serial I/O mode and update the device path
325 //
326
327 Tpl = gBS->RaiseTPL (TPL_NOTIFY);
328
329 //
330 // Set the Serial I/O mode
331 //
332 This->Mode->ReceiveFifoDepth = ReceiveFifoDepth;
333 This->Mode->Timeout = Timeout;
334 This->Mode->BaudRate = BaudRate;
335 This->Mode->DataBits = (UINT32) DataBits;
336 This->Mode->Parity = (UINT32) Parity;
337 This->Mode->StopBits = (UINT32) StopBits;
338
339 //
340 // Check if the device path has actually changed
341 //
342 if (mSerialDevicePath.Uart.BaudRate == BaudRate &&
343 mSerialDevicePath.Uart.DataBits == DataBits &&
344 mSerialDevicePath.Uart.Parity == (UINT8) Parity &&
345 mSerialDevicePath.Uart.StopBits == (UINT8) StopBits
346 ) {
347 gBS->RestoreTPL (Tpl);
348 return EFI_SUCCESS;
349 }
350
351 //
352 // Update the device path
353 //
354 mSerialDevicePath.Uart.BaudRate = BaudRate;
355 mSerialDevicePath.Uart.DataBits = DataBits;
356 mSerialDevicePath.Uart.Parity = (UINT8) Parity;
357 mSerialDevicePath.Uart.StopBits = (UINT8) StopBits;
358
359 Status = gBS->ReinstallProtocolInterface (
360 mSerialHandle,
361 &gEfiDevicePathProtocolGuid,
362 &mSerialDevicePath,
363 &mSerialDevicePath
364 );
365
366 gBS->RestoreTPL (Tpl);
367
368 return Status;
369 }
370
371 /**
372 Set the control bits on a serial device
373
374 @param This Protocol instance pointer.
375 @param Control Set the bits of Control that are settable.
376
377 @retval EFI_SUCCESS The new control bits were set on the serial device.
378 @retval EFI_UNSUPPORTED The serial device does not support this operation.
379 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
380
381 **/
382 EFI_STATUS
383 EFIAPI
384 SerialSetControl (
385 IN EFI_SERIAL_IO_PROTOCOL *This,
386 IN UINT32 Control
387 )
388 {
389 return SerialPortSetControl (Control);
390 }
391
392 /**
393 Retrieves the status of the control bits on a serial device
394
395 @param This Protocol instance pointer.
396 @param Control A pointer to return the current Control signals from the serial device.
397
398 @retval EFI_SUCCESS The control bits were read from the serial device.
399 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
400
401 **/
402 EFI_STATUS
403 EFIAPI
404 SerialGetControl (
405 IN EFI_SERIAL_IO_PROTOCOL *This,
406 OUT UINT32 *Control
407 )
408 {
409 return SerialPortGetControl (Control);
410 }
411
412 /**
413 Writes data to a serial device.
414
415 @param This Protocol instance pointer.
416 @param BufferSize On input, the size of the Buffer. On output, the amount of
417 data actually written.
418 @param Buffer The buffer of data to write
419
420 @retval EFI_SUCCESS The data was written.
421 @retval EFI_DEVICE_ERROR The device reported an error.
422 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
423
424 **/
425 EFI_STATUS
426 EFIAPI
427 SerialWrite (
428 IN EFI_SERIAL_IO_PROTOCOL *This,
429 IN OUT UINTN *BufferSize,
430 IN VOID *Buffer
431 )
432 {
433 UINTN Count;
434
435 Count = SerialPortWrite (Buffer, *BufferSize);
436
437 if (Count != *BufferSize) {
438 *BufferSize = Count;
439 return EFI_TIMEOUT;
440 }
441
442 return EFI_SUCCESS;
443 }
444
445 /**
446 Reads data from a serial device.
447
448 @param This Protocol instance pointer.
449 @param BufferSize On input, the size of the Buffer. On output, the amount of
450 data returned in Buffer.
451 @param Buffer The buffer to return the data into.
452
453 @retval EFI_SUCCESS The data was read.
454 @retval EFI_DEVICE_ERROR The device reported an error.
455 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
456
457 **/
458 EFI_STATUS
459 EFIAPI
460 SerialRead (
461 IN EFI_SERIAL_IO_PROTOCOL *This,
462 IN OUT UINTN *BufferSize,
463 OUT VOID *Buffer
464 )
465 {
466 UINTN Count;
467
468 Count = 0;
469
470 if (SerialPortPoll ()) {
471 Count = SerialPortRead (Buffer, *BufferSize);
472 }
473
474 if (Count != *BufferSize) {
475 *BufferSize = Count;
476 return EFI_TIMEOUT;
477 }
478
479 return EFI_SUCCESS;
480 }
481
482 /**
483 Initialization for the Serial Io Protocol.
484
485 @param[in] ImageHandle The firmware allocated handle for the EFI image.
486 @param[in] SystemTable A pointer to the EFI System Table.
487
488 @retval EFI_SUCCESS The entry point is executed successfully.
489 @retval other Some error occurs when executing this entry point.
490
491 **/
492 EFI_STATUS
493 EFIAPI
494 SerialDxeInitialize (
495 IN EFI_HANDLE ImageHandle,
496 IN EFI_SYSTEM_TABLE *SystemTable
497 )
498 {
499 EFI_STATUS Status;
500
501 Status = SerialPortInitialize ();
502 if (EFI_ERROR (Status)) {
503 return Status;
504 }
505
506 mSerialIoMode.BaudRate = PcdGet64 (PcdUartDefaultBaudRate);
507 mSerialIoMode.DataBits = (UINT32) PcdGet8 (PcdUartDefaultDataBits);
508 mSerialIoMode.Parity = (UINT32) PcdGet8 (PcdUartDefaultParity);
509 mSerialIoMode.StopBits = (UINT32) PcdGet8 (PcdUartDefaultStopBits);
510 mSerialDevicePath.Uart.BaudRate = PcdGet64 (PcdUartDefaultBaudRate);
511 mSerialDevicePath.Uart.DataBits = PcdGet8 (PcdUartDefaultDataBits);
512 mSerialDevicePath.Uart.Parity = PcdGet8 (PcdUartDefaultParity);
513 mSerialDevicePath.Uart.StopBits = PcdGet8 (PcdUartDefaultStopBits);
514
515 //
516 // Make a new handle with Serial IO protocol and its device path on it.
517 //
518 Status = gBS->InstallMultipleProtocolInterfaces (
519 &mSerialHandle,
520 &gEfiSerialIoProtocolGuid, &mSerialIoTemplate,
521 &gEfiDevicePathProtocolGuid, &mSerialDevicePath,
522 NULL
523 );
524 ASSERT_EFI_ERROR (Status);
525
526 return Status;
527 }
528