VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/SerialDxe/SerialIo.c@ 101297

Last change on this file since 101297 was 99404, checked in by vboxsync, 22 months ago

Devices/EFI/FirmwareNew: Update to edk2-stable202302 and make it build, bugref:4643

  • Property svn:eol-style set to native
File size: 17.3 KB
Line 
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 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10**/
11
12#include <Library/UefiBootServicesTableLib.h>
13#include <Library/SerialPortLib.h>
14#include <Library/DebugLib.h>
15#include <Library/PcdLib.h>
16
17#include <Protocol/SerialIo.h>
18#include <Protocol/DevicePath.h>
19#include <Guid/SerialPortLibVendor.h>
20
21typedef struct {
22 VENDOR_DEVICE_PATH Guid;
23 UART_DEVICE_PATH Uart;
24 EFI_DEVICE_PATH_PROTOCOL End;
25} SERIAL_DEVICE_PATH;
26
27/**
28 Reset the serial device.
29
30 @param This Protocol instance pointer.
31
32 @retval EFI_SUCCESS The device was reset.
33 @retval EFI_DEVICE_ERROR The serial device could not be reset.
34
35**/
36EFI_STATUS
37EFIAPI
38SerialReset (
39 IN EFI_SERIAL_IO_PROTOCOL *This
40 );
41
42/**
43 Sets the baud rate, receive FIFO depth, transmit/receive time out, parity,
44 data bits, and stop bits on a serial device.
45
46 @param This Protocol instance pointer.
47 @param BaudRate The requested baud rate. A BaudRate value of 0 will use the the
48 device's default interface speed.
49 @param ReceiveFifoDepth The requested depth of the FIFO on the receive side of the
50 serial interface. A ReceiveFifoDepth value of 0 will use
51 the device's default FIFO depth.
52 @param Timeout The requested time out for a single character in microseconds.
53 This timeout applies to both the transmit and receive side of the
54 interface. A Timeout value of 0 will use the device's default time
55 out value.
56 @param Parity The type of parity to use on this serial device. A Parity value of
57 DefaultParity will use the device's default parity value.
58 @param DataBits The number of data bits to use on the serial device. A DataBits
59 value of 0 will use the device's default data bit setting.
60 @param StopBits The number of stop bits to use on this serial device. A StopBits
61 value of DefaultStopBits will use the device's default number of
62 stop bits.
63
64 @retval EFI_SUCCESS The device was reset.
65 @retval EFI_INVALID_PARAMETER One or more attributes has an unsupported value.
66 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
67
68**/
69EFI_STATUS
70EFIAPI
71SerialSetAttributes (
72 IN EFI_SERIAL_IO_PROTOCOL *This,
73 IN UINT64 BaudRate,
74 IN UINT32 ReceiveFifoDepth,
75 IN UINT32 Timeout,
76 IN EFI_PARITY_TYPE Parity,
77 IN UINT8 DataBits,
78 IN EFI_STOP_BITS_TYPE StopBits
79 );
80
81/**
82 Set the control bits on a serial device
83
84 @param This Protocol instance pointer.
85 @param Control Set the bits of Control that are settable.
86
87 @retval EFI_SUCCESS The new control bits were set on the serial device.
88 @retval EFI_UNSUPPORTED The serial device does not support this operation.
89 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
90
91**/
92EFI_STATUS
93EFIAPI
94SerialSetControl (
95 IN EFI_SERIAL_IO_PROTOCOL *This,
96 IN UINT32 Control
97 );
98
99/**
100 Retrieves the status of the control bits on a serial device
101
102 @param This Protocol instance pointer.
103 @param Control A pointer to return the current Control signals from the serial device.
104
105 @retval EFI_SUCCESS The control bits were read from the serial device.
106 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
107
108**/
109EFI_STATUS
110EFIAPI
111SerialGetControl (
112 IN EFI_SERIAL_IO_PROTOCOL *This,
113 OUT UINT32 *Control
114 );
115
116/**
117 Writes data to a serial device.
118
119 @param This Protocol instance pointer.
120 @param BufferSize On input, the size of the Buffer. On output, the amount of
121 data actually written.
122 @param Buffer The buffer of data to write
123
124 @retval EFI_SUCCESS The data was written.
125 @retval EFI_DEVICE_ERROR The device reported an error.
126 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
127
128**/
129EFI_STATUS
130EFIAPI
131SerialWrite (
132 IN EFI_SERIAL_IO_PROTOCOL *This,
133 IN OUT UINTN *BufferSize,
134 IN VOID *Buffer
135 );
136
137/**
138 Reads data from a serial device.
139
140 @param This Protocol instance pointer.
141 @param BufferSize On input, the size of the Buffer. On output, the amount of
142 data returned in Buffer.
143 @param Buffer The buffer to return the data into.
144
145 @retval EFI_SUCCESS The data was read.
146 @retval EFI_DEVICE_ERROR The device reported an error.
147 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
148
149**/
150EFI_STATUS
151EFIAPI
152SerialRead (
153 IN EFI_SERIAL_IO_PROTOCOL *This,
154 IN OUT UINTN *BufferSize,
155 OUT VOID *Buffer
156 );
157
158EFI_HANDLE mSerialHandle = NULL;
159
160SERIAL_DEVICE_PATH mSerialDevicePath = {
161 {
162 { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { sizeof (VENDOR_DEVICE_PATH), 0 }
163 },
164 EDKII_SERIAL_PORT_LIB_VENDOR_GUID
165 },
166 {
167 { MESSAGING_DEVICE_PATH, MSG_UART_DP, { sizeof (UART_DEVICE_PATH), 0 }
168 },
169 0, // Reserved
170 0, // BaudRate
171 0, // DataBits
172 0, // Parity
173 0 // StopBits
174 },
175 { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
176 }
177};
178
179//
180// Template used to initialize the Serial IO protocols.
181//
182EFI_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
195EFI_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**/
215EFI_STATUS
216EFIAPI
217SerialReset (
218 IN EFI_SERIAL_IO_PROTOCOL *This
219 )
220{
221 EFI_STATUS Status;
222
223 Status = SerialPortInitialize ();
224 if (EFI_ERROR (Status)) {
225 return Status;
226 }
227
228 //
229 // Go set the current attributes
230 //
231 Status = This->SetAttributes (
232 This,
233 This->Mode->BaudRate,
234 This->Mode->ReceiveFifoDepth,
235 This->Mode->Timeout,
236 (EFI_PARITY_TYPE)This->Mode->Parity,
237 (UINT8)This->Mode->DataBits,
238 (EFI_STOP_BITS_TYPE)This->Mode->StopBits
239 );
240
241 //
242 // The serial device may not support some of the attributes. To prevent
243 // later failure, always return EFI_SUCCESS when SetAttributes is returning
244 // EFI_INVALID_PARAMETER.
245 //
246 if (Status == EFI_INVALID_PARAMETER) {
247 return EFI_SUCCESS;
248 }
249
250 return Status;
251}
252
253/**
254 Sets the baud rate, receive FIFO depth, transmit/receive time out, parity,
255 data bits, and stop bits on a serial device.
256
257 @param This Protocol instance pointer.
258 @param BaudRate The requested baud rate. A BaudRate value of 0 will use the the
259 device's default interface speed.
260 @param ReceiveFifoDepth The requested depth of the FIFO on the receive side of the
261 serial interface. A ReceiveFifoDepth value of 0 will use
262 the device's default FIFO depth.
263 @param Timeout The requested time out for a single character in microseconds.
264 This timeout applies to both the transmit and receive side of the
265 interface. A Timeout value of 0 will use the device's default time
266 out value.
267 @param Parity The type of parity to use on this serial device. A Parity value of
268 DefaultParity will use the device's default parity value.
269 @param DataBits The number of data bits to use on the serial device. A DataBits
270 value of 0 will use the device's default data bit setting.
271 @param StopBits The number of stop bits to use on this serial device. A StopBits
272 value of DefaultStopBits will use the device's default number of
273 stop bits.
274
275 @retval EFI_SUCCESS The device was reset.
276 @retval EFI_INVALID_PARAMETER One or more attributes has an unsupported value.
277 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
278
279**/
280EFI_STATUS
281EFIAPI
282SerialSetAttributes (
283 IN EFI_SERIAL_IO_PROTOCOL *This,
284 IN UINT64 BaudRate,
285 IN UINT32 ReceiveFifoDepth,
286 IN UINT32 Timeout,
287 IN EFI_PARITY_TYPE Parity,
288 IN UINT8 DataBits,
289 IN EFI_STOP_BITS_TYPE StopBits
290 )
291{
292 EFI_STATUS Status;
293 EFI_TPL Tpl;
294 UINT64 OriginalBaudRate;
295 UINT32 OriginalReceiveFifoDepth;
296 UINT32 OriginalTimeout;
297 EFI_PARITY_TYPE OriginalParity;
298 UINT8 OriginalDataBits;
299 EFI_STOP_BITS_TYPE OriginalStopBits;
300
301 //
302 // Preserve the original input values in case
303 // SerialPortSetAttributes() updates the input/output
304 // parameters even on error.
305 //
306 OriginalBaudRate = BaudRate;
307 OriginalReceiveFifoDepth = ReceiveFifoDepth;
308 OriginalTimeout = Timeout;
309 OriginalParity = Parity;
310 OriginalDataBits = DataBits;
311 OriginalStopBits = StopBits;
312 Status = SerialPortSetAttributes (&BaudRate, &ReceiveFifoDepth, &Timeout, &Parity, &DataBits, &StopBits);
313 if (EFI_ERROR (Status)) {
314 //
315 // If it is just to set Timeout value and unsupported is returned,
316 // do not return error.
317 //
318 if ((Status == EFI_UNSUPPORTED) &&
319 (This->Mode->Timeout != OriginalTimeout) &&
320 (This->Mode->ReceiveFifoDepth == OriginalReceiveFifoDepth) &&
321 (This->Mode->BaudRate == OriginalBaudRate) &&
322 (This->Mode->DataBits == (UINT32)OriginalDataBits) &&
323 (This->Mode->Parity == (UINT32)OriginalParity) &&
324 (This->Mode->StopBits == (UINT32)OriginalStopBits))
325 {
326 //
327 // Restore to the original input values.
328 //
329 BaudRate = OriginalBaudRate;
330 ReceiveFifoDepth = OriginalReceiveFifoDepth;
331 Timeout = OriginalTimeout;
332 Parity = OriginalParity;
333 DataBits = OriginalDataBits;
334 StopBits = OriginalStopBits;
335 Status = EFI_SUCCESS;
336 } else if ((Status == EFI_INVALID_PARAMETER) || (Status == EFI_UNSUPPORTED)) {
337 return EFI_INVALID_PARAMETER;
338 } else {
339 return EFI_DEVICE_ERROR;
340 }
341 }
342
343 //
344 // Set the Serial I/O mode and update the device path
345 //
346
347 Tpl = gBS->RaiseTPL (TPL_NOTIFY);
348
349 //
350 // Set the Serial I/O mode
351 //
352 This->Mode->ReceiveFifoDepth = ReceiveFifoDepth;
353 This->Mode->Timeout = Timeout;
354 This->Mode->BaudRate = BaudRate;
355 This->Mode->DataBits = (UINT32)DataBits;
356 This->Mode->Parity = (UINT32)Parity;
357 This->Mode->StopBits = (UINT32)StopBits;
358
359 //
360 // Check if the device path has actually changed
361 //
362 if ((mSerialDevicePath.Uart.BaudRate == BaudRate) &&
363 (mSerialDevicePath.Uart.DataBits == DataBits) &&
364 (mSerialDevicePath.Uart.Parity == (UINT8)Parity) &&
365 (mSerialDevicePath.Uart.StopBits == (UINT8)StopBits)
366 )
367 {
368 gBS->RestoreTPL (Tpl);
369 return EFI_SUCCESS;
370 }
371
372 //
373 // Update the device path
374 //
375 mSerialDevicePath.Uart.BaudRate = BaudRate;
376 mSerialDevicePath.Uart.DataBits = DataBits;
377 mSerialDevicePath.Uart.Parity = (UINT8)Parity;
378 mSerialDevicePath.Uart.StopBits = (UINT8)StopBits;
379
380 Status = gBS->ReinstallProtocolInterface (
381 mSerialHandle,
382 &gEfiDevicePathProtocolGuid,
383 &mSerialDevicePath,
384 &mSerialDevicePath
385 );
386
387 gBS->RestoreTPL (Tpl);
388
389 return Status;
390}
391
392/**
393 Set the control bits on a serial device
394
395 @param This Protocol instance pointer.
396 @param Control Set the bits of Control that are settable.
397
398 @retval EFI_SUCCESS The new control bits were set on the serial device.
399 @retval EFI_UNSUPPORTED The serial device does not support this operation.
400 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
401
402**/
403EFI_STATUS
404EFIAPI
405SerialSetControl (
406 IN EFI_SERIAL_IO_PROTOCOL *This,
407 IN UINT32 Control
408 )
409{
410 return SerialPortSetControl (Control);
411}
412
413/**
414 Retrieves the status of the control bits on a serial device
415
416 @param This Protocol instance pointer.
417 @param Control A pointer to return the current Control signals from the serial device.
418
419 @retval EFI_SUCCESS The control bits were read from the serial device.
420 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
421
422**/
423EFI_STATUS
424EFIAPI
425SerialGetControl (
426 IN EFI_SERIAL_IO_PROTOCOL *This,
427 OUT UINT32 *Control
428 )
429{
430 return SerialPortGetControl (Control);
431}
432
433/**
434 Writes data to a serial device.
435
436 @param This Protocol instance pointer.
437 @param BufferSize On input, the size of the Buffer. On output, the amount of
438 data actually written.
439 @param Buffer The buffer of data to write
440
441 @retval EFI_SUCCESS The data was written.
442 @retval EFI_DEVICE_ERROR The device reported an error.
443 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
444
445**/
446EFI_STATUS
447EFIAPI
448SerialWrite (
449 IN EFI_SERIAL_IO_PROTOCOL *This,
450 IN OUT UINTN *BufferSize,
451 IN VOID *Buffer
452 )
453{
454 UINTN Count;
455
456 Count = SerialPortWrite (Buffer, *BufferSize);
457
458 if (Count != *BufferSize) {
459 *BufferSize = Count;
460 return EFI_TIMEOUT;
461 }
462
463 return EFI_SUCCESS;
464}
465
466/**
467 Reads data from a serial device.
468
469 @param This Protocol instance pointer.
470 @param BufferSize On input, the size of the Buffer. On output, the amount of
471 data returned in Buffer.
472 @param Buffer The buffer to return the data into.
473
474 @retval EFI_SUCCESS The data was read.
475 @retval EFI_DEVICE_ERROR The device reported an error.
476 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
477
478**/
479EFI_STATUS
480EFIAPI
481SerialRead (
482 IN EFI_SERIAL_IO_PROTOCOL *This,
483 IN OUT UINTN *BufferSize,
484 OUT VOID *Buffer
485 )
486{
487 UINTN Count;
488 UINTN TimeOut;
489
490 Count = 0;
491
492 while (Count < *BufferSize) {
493 TimeOut = 0;
494 while (TimeOut < mSerialIoMode.Timeout) {
495 if (SerialPortPoll ()) {
496 break;
497 }
498
499 gBS->Stall (10);
500 TimeOut += 10;
501 }
502
503 if (TimeOut >= mSerialIoMode.Timeout) {
504 break;
505 }
506
507 SerialPortRead (Buffer, 1);
508 Count++;
509 Buffer = (VOID *)((UINT8 *)Buffer + 1);
510 }
511
512 if (Count != *BufferSize) {
513 *BufferSize = Count;
514 return EFI_TIMEOUT;
515 }
516
517 return EFI_SUCCESS;
518}
519
520/**
521 Initialization for the Serial Io Protocol.
522
523 @param[in] ImageHandle The firmware allocated handle for the EFI image.
524 @param[in] SystemTable A pointer to the EFI System Table.
525
526 @retval EFI_SUCCESS The entry point is executed successfully.
527 @retval other Some error occurs when executing this entry point.
528
529**/
530EFI_STATUS
531EFIAPI
532SerialDxeInitialize (
533 IN EFI_HANDLE ImageHandle,
534 IN EFI_SYSTEM_TABLE *SystemTable
535 )
536{
537 EFI_STATUS Status;
538
539 mSerialIoMode.BaudRate = PcdGet64 (PcdUartDefaultBaudRate);
540 mSerialIoMode.DataBits = (UINT32)PcdGet8 (PcdUartDefaultDataBits);
541 mSerialIoMode.Parity = (UINT32)PcdGet8 (PcdUartDefaultParity);
542 mSerialIoMode.StopBits = (UINT32)PcdGet8 (PcdUartDefaultStopBits);
543 mSerialIoMode.ReceiveFifoDepth = PcdGet16 (PcdUartDefaultReceiveFifoDepth);
544 mSerialDevicePath.Uart.BaudRate = PcdGet64 (PcdUartDefaultBaudRate);
545 mSerialDevicePath.Uart.DataBits = PcdGet8 (PcdUartDefaultDataBits);
546 mSerialDevicePath.Uart.Parity = PcdGet8 (PcdUartDefaultParity);
547 mSerialDevicePath.Uart.StopBits = PcdGet8 (PcdUartDefaultStopBits);
548
549 //
550 // Issue a reset to initialize the Serial Port
551 //
552 Status = mSerialIoTemplate.Reset (&mSerialIoTemplate);
553 if (EFI_ERROR (Status)) {
554 return Status;
555 }
556
557 //
558 // Make a new handle with Serial IO protocol and its device path on it.
559 //
560 Status = gBS->InstallMultipleProtocolInterfaces (
561 &mSerialHandle,
562 &gEfiSerialIoProtocolGuid,
563 &mSerialIoTemplate,
564 &gEfiDevicePathProtocolGuid,
565 &mSerialDevicePath,
566 NULL
567 );
568 ASSERT_EFI_ERROR (Status);
569
570 return Status;
571}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette