]> git.proxmox.com Git - mirror_edk2.git/blob - EdkUnixPkg/Dxe/UnixThunk/Bus/SerialIo/UnixSerialIo.c
Remove unused variable and function
[mirror_edk2.git] / EdkUnixPkg / Dxe / UnixThunk / Bus / SerialIo / UnixSerialIo.c
1 /*++
2
3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 UnixSerialIo.c
15
16 Abstract:
17
18 Our DriverBinding member functions operate on the handles
19 created by the NT Bus driver.
20
21 Handle(1) - UnixIo - DevicePath(1)
22
23 If a serial port is added to the system this driver creates a new handle.
24 The new handle is required, since the serial device must add an UART device
25 pathnode.
26
27 Handle(2) - SerialIo - DevicePath(1)\UART
28
29 The driver then adds a gEfiUnixSerialPortGuid as a protocol to Handle(1).
30 The instance data for this protocol is the private data used to create
31 Handle(2).
32
33 Handle(1) - UnixIo - DevicePath(1) - UnixSerialPort
34
35 If the driver is unloaded Handle(2) is removed from the system and
36 gEfiUnixSerialPortGuid is removed from Handle(1).
37
38 Note: Handle(1) is any handle created by the Win NT Bus driver that is passed
39 into the DriverBinding member functions of this driver. This driver requires
40 a Handle(1) to contain a UnixIo protocol, a DevicePath protocol, and
41 the TypeGuid in the UnixIo must be gEfiUnixSerialPortGuid.
42
43 If Handle(1) contains a gEfiUnixSerialPortGuid protocol then the driver is
44 loaded on the device.
45
46 --*/
47
48 #include "UnixSerialIo.h"
49 #include <termio.h>
50
51 EFI_DRIVER_BINDING_PROTOCOL gUnixSerialIoDriverBinding = {
52 UnixSerialIoDriverBindingSupported,
53 UnixSerialIoDriverBindingStart,
54 UnixSerialIoDriverBindingStop,
55 0xa,
56 NULL,
57 NULL
58 };
59
60 STATIC
61 UINTN
62 ConvertBaud2Unix (
63 UINT64 BaudRate
64 )
65 {
66 switch (BaudRate) {
67 case 0:
68 return B0;
69 case 50:
70 return B50;
71 case 75:
72 return B75;
73 case 110:
74 return B110;
75 case 134:
76 return B134;
77 case 150:
78 return B150;
79 case 200:
80 return B200;
81 case 300:
82 return B300;
83 case 600:
84 return B600;
85 case 1200:
86 return B1200;
87 case 1800:
88 return B1800;
89 case 2400:
90 return B2400;
91 case 4800:
92 return B4800;
93 case 9600:
94 return B9600;
95 case 19200:
96 return B19200;
97 case 38400:
98 return B38400;
99 case 57600:
100 return B57600;
101 case 115200:
102 return B115200;
103 case 230400:
104 return B230400;
105 case 460800:
106 return B460800;
107 case 500000:
108 return B500000;
109 case 576000:
110 return B576000;
111 case 921600:
112 return B921600;
113 case 1000000:
114 return B1000000;
115 case 1152000:
116 return B1152000;
117 case 1500000:
118 return B1500000;
119 case 2000000:
120 return B2000000;
121 case 2500000:
122 return B2500000;
123 case 3000000:
124 return B3000000;
125 case 3500000:
126 return B3500000;
127 case 4000000:
128 return B4000000;
129 case __MAX_BAUD:
130 default:
131 DEBUG ((EFI_D_ERROR, "Invalid Baud Rate Parameter!\r\n"));
132 }
133 return -1;
134 }
135
136 STATIC
137 UINTN
138 ConvertByteSize2Unix (
139 UINT8 DataBit
140 )
141 {
142 switch (DataBit) {
143 case 5:
144 return CS5;
145 case 6:
146 return CS6;
147 case 7:
148 return CS7;
149 case 8:
150 return CS8;
151 default:
152 DEBUG ((EFI_D_ERROR, "Invalid Data Size Parameter!\r\n"));
153 }
154 return -1;
155 }
156
157 STATIC
158 VOID
159 ConvertParity2Unix (
160 struct termios *Options,
161 EFI_PARITY_TYPE Parity
162 )
163 {
164 switch (Parity) {
165 case NoParity:
166 Options->c_cflag &= ~PARENB;
167 break;
168 case EvenParity:
169 Options->c_cflag |= PARENB;
170 break;
171 case OddParity:
172 Options->c_cflag |= PARENB;
173 Options->c_cflag |= PARODD;
174 break;
175 case MarkParity:
176 Options->c_cflag = PARENB | CMSPAR | PARODD;
177 break;
178 case SpaceParity:
179 Options->c_cflag |= PARENB | CMSPAR;
180 Options->c_cflag &= ~PARODD;
181 break;
182 default:
183 DEBUG ((EFI_D_ERROR, "Invalid Parity Parameter!\r\n"));
184 }
185 }
186
187 STATIC
188 VOID
189 ConvertStopBit2Unix (
190 struct termios *Options,
191 EFI_STOP_BITS_TYPE StopBits
192 )
193 {
194 switch (StopBits) {
195 case TwoStopBits:
196 Options->c_cflag |= CSTOPB;
197 break;
198 case OneStopBit:
199 case OneFiveStopBits:
200 case DefaultStopBits:
201 Options->c_cflag &= ~CSTOPB;
202 }
203 }
204
205 EFI_STATUS
206 EFIAPI
207 UnixSerialIoDriverBindingSupported (
208 IN EFI_DRIVER_BINDING_PROTOCOL *This,
209 IN EFI_HANDLE Handle,
210 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
211 )
212 /*++
213
214 Routine Description:
215 The implementation of EFI_DRIVER_BINDING_PROTOCOL.EFI_DRIVER_BINDING_SUPPORTED.
216
217 Arguments:
218
219 Returns:
220
221 None
222
223 --*/
224 {
225 EFI_STATUS Status;
226 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
227 EFI_UNIX_IO_PROTOCOL *UnixIo;
228 UART_DEVICE_PATH *UartNode;
229
230 //
231 // Open the IO Abstraction(s) needed to perform the supported test
232 //
233 Status = gBS->OpenProtocol (
234 Handle,
235 &gEfiDevicePathProtocolGuid,
236 (VOID**)&ParentDevicePath,
237 This->DriverBindingHandle,
238 Handle,
239 EFI_OPEN_PROTOCOL_BY_DRIVER
240 );
241 if (Status == EFI_ALREADY_STARTED) {
242 return EFI_SUCCESS;
243 }
244
245 if (EFI_ERROR (Status)) {
246 return Status;
247 }
248
249 gBS->CloseProtocol (
250 Handle,
251 &gEfiDevicePathProtocolGuid,
252 This->DriverBindingHandle,
253 Handle
254 );
255
256 Status = gBS->OpenProtocol (
257 Handle,
258 &gEfiUnixIoProtocolGuid,
259 (VOID**)&UnixIo,
260 This->DriverBindingHandle,
261 Handle,
262 EFI_OPEN_PROTOCOL_BY_DRIVER
263 );
264 if (Status == EFI_ALREADY_STARTED) {
265 return EFI_SUCCESS;
266 }
267
268 if (EFI_ERROR (Status)) {
269 return Status;
270 }
271
272 //
273 // Make sure that the Unix Thunk Protocol is valid
274 //
275 if (UnixIo->UnixThunk->Signature != EFI_UNIX_THUNK_PROTOCOL_SIGNATURE) {
276 Status = EFI_UNSUPPORTED;
277 goto Error;
278 }
279
280 //
281 // Check the GUID to see if this is a handle type the driver supports
282 //
283 if (!CompareGuid (UnixIo->TypeGuid, &gEfiUnixSerialPortGuid)) {
284 Status = EFI_UNSUPPORTED;
285 goto Error;
286 }
287
288 if (RemainingDevicePath != NULL) {
289 Status = EFI_UNSUPPORTED;
290 UartNode = (UART_DEVICE_PATH *) RemainingDevicePath;
291 if (UartNode->Header.Type != MESSAGING_DEVICE_PATH ||
292 UartNode->Header.SubType != MSG_UART_DP ||
293 DevicePathNodeLength((EFI_DEVICE_PATH_PROTOCOL *)UartNode) != sizeof(UART_DEVICE_PATH)) {
294 goto Error;
295 }
296 if (UartNode->BaudRate < 0 || UartNode->BaudRate > SERIAL_PORT_MAX_BAUD_RATE) {
297 goto Error;
298 }
299 if (UartNode->Parity < NoParity || UartNode->Parity > SpaceParity) {
300 goto Error;
301 }
302 if (UartNode->DataBits < 5 || UartNode->DataBits > 8) {
303 goto Error;
304 }
305 if (UartNode->StopBits < OneStopBit || UartNode->StopBits > TwoStopBits) {
306 goto Error;
307 }
308 if ((UartNode->DataBits == 5) && (UartNode->StopBits == TwoStopBits)) {
309 goto Error;
310 }
311 if ((UartNode->DataBits >= 6) && (UartNode->DataBits <= 8) && (UartNode->StopBits == OneFiveStopBits)) {
312 goto Error;
313 }
314 Status = EFI_SUCCESS;
315 }
316
317 Error:
318 //
319 // Close the I/O Abstraction(s) used to perform the supported test
320 //
321 gBS->CloseProtocol (
322 Handle,
323 &gEfiUnixIoProtocolGuid,
324 This->DriverBindingHandle,
325 Handle
326 );
327
328 return Status;
329 }
330
331 EFI_STATUS
332 EFIAPI
333 UnixSerialIoDriverBindingStart (
334 IN EFI_DRIVER_BINDING_PROTOCOL *This,
335 IN EFI_HANDLE Handle,
336 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
337 )
338 /*++
339
340 Routine Description:
341
342 Arguments:
343
344 Returns:
345
346 None
347
348 --*/
349 {
350 EFI_STATUS Status;
351 EFI_UNIX_IO_PROTOCOL *UnixIo;
352 UNIX_SERIAL_IO_PRIVATE_DATA *Private;
353 UINTN UnixHandle;
354 UART_DEVICE_PATH Node;
355 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
356 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
357 UINTN EntryCount;
358 UINTN Index;
359 EFI_SERIAL_IO_PROTOCOL *SerialIo;
360 CHAR8 AsciiDevName[1024];
361
362 DEBUG ((EFI_D_INFO, "SerialIo drive binding start!\r\n"));
363 Private = NULL;
364 UnixHandle = -1;
365
366 //
367 // Grab the protocols we need
368 //
369 Status = gBS->OpenProtocol (
370 Handle,
371 &gEfiDevicePathProtocolGuid,
372 (VOID**)&ParentDevicePath,
373 This->DriverBindingHandle,
374 Handle,
375 EFI_OPEN_PROTOCOL_BY_DRIVER
376 );
377 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
378 return Status;
379 }
380
381 //
382 // Grab the IO abstraction we need to get any work done
383 //
384 Status = gBS->OpenProtocol (
385 Handle,
386 &gEfiUnixIoProtocolGuid,
387 (VOID**)&UnixIo,
388 This->DriverBindingHandle,
389 Handle,
390 EFI_OPEN_PROTOCOL_BY_DRIVER
391 );
392 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
393 gBS->CloseProtocol (
394 Handle,
395 &gEfiDevicePathProtocolGuid,
396 This->DriverBindingHandle,
397 Handle
398 );
399 return Status;
400 }
401
402 if (Status == EFI_ALREADY_STARTED) {
403
404 if (RemainingDevicePath == NULL) {
405 return EFI_SUCCESS;
406 }
407
408 //
409 // Make sure a child handle does not already exist. This driver can only
410 // produce one child per serial port.
411 //
412 Status = gBS->OpenProtocolInformation (
413 Handle,
414 &gEfiUnixIoProtocolGuid,
415 &OpenInfoBuffer,
416 &EntryCount
417 );
418 if (EFI_ERROR (Status)) {
419 return Status;
420 }
421
422 Status = EFI_ALREADY_STARTED;
423 for (Index = 0; Index < EntryCount; Index++) {
424 if (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
425 Status = gBS->OpenProtocol (
426 OpenInfoBuffer[Index].ControllerHandle,
427 &gEfiSerialIoProtocolGuid,
428 (VOID**)&SerialIo,
429 This->DriverBindingHandle,
430 Handle,
431 EFI_OPEN_PROTOCOL_GET_PROTOCOL
432 );
433 if (!EFI_ERROR (Status)) {
434 CopyMem (&Node, RemainingDevicePath, sizeof (UART_DEVICE_PATH));
435 Status = SerialIo->SetAttributes (
436 SerialIo,
437 Node.BaudRate,
438 SerialIo->Mode->ReceiveFifoDepth,
439 SerialIo->Mode->Timeout,
440 Node.Parity,
441 Node.DataBits,
442 Node.StopBits
443 );
444 }
445 break;
446 }
447 }
448
449 FreePool (OpenInfoBuffer);
450 return Status;
451 }
452
453 //
454 // Check to see if we can access the hardware device. If it's Open in Unix we
455 // will not get access.
456 //
457 UnicodeStrToAsciiStr(UnixIo->EnvString, AsciiDevName);
458 UnixHandle = UnixIo->UnixThunk->Open (AsciiDevName, O_RDWR | O_NOCTTY, 0);
459
460 if (UnixHandle == -1) {
461 DEBUG ((EFI_D_INFO, "Faile to open serial device, %s!\r\n", UnixIo->EnvString ));
462 UnixIo->UnixThunk->Perror (AsciiDevName);
463 Status = EFI_DEVICE_ERROR;
464 goto Error;
465 }
466 DEBUG ((EFI_D_INFO, "Success to open serial device %s, Hanle = 0x%x \r\n", UnixIo->EnvString, UnixHandle));
467
468 //
469 // Construct Private data
470 //
471 Private = AllocatePool (sizeof (UNIX_SERIAL_IO_PRIVATE_DATA));
472 if (Private == NULL) {
473 goto Error;
474 }
475
476 //
477 // This signature must be valid before any member function is called
478 //
479 Private->Signature = UNIX_SERIAL_IO_PRIVATE_DATA_SIGNATURE;
480 Private->UnixHandle = UnixHandle;
481 Private->ControllerHandle = Handle;
482 Private->Handle = NULL;
483 Private->UnixThunk = UnixIo->UnixThunk;
484 Private->ParentDevicePath = ParentDevicePath;
485 Private->ControllerNameTable = NULL;
486
487 Private->SoftwareLoopbackEnable = FALSE;
488 Private->HardwareLoopbackEnable = FALSE;
489 Private->HardwareFlowControl = FALSE;
490 Private->Fifo.First = 0;
491 Private->Fifo.Last = 0;
492 Private->Fifo.Surplus = SERIAL_MAX_BUFFER_SIZE;
493
494 AddUnicodeString (
495 "eng",
496 gUnixSerialIoComponentName.SupportedLanguages,
497 &Private->ControllerNameTable,
498 UnixIo->EnvString
499 );
500
501 Private->SerialIo.Revision = SERIAL_IO_INTERFACE_REVISION;
502 Private->SerialIo.Reset = UnixSerialIoReset;
503 Private->SerialIo.SetAttributes = UnixSerialIoSetAttributes;
504 Private->SerialIo.SetControl = UnixSerialIoSetControl;
505 Private->SerialIo.GetControl = UnixSerialIoGetControl;
506 Private->SerialIo.Write = UnixSerialIoWrite;
507 Private->SerialIo.Read = UnixSerialIoRead;
508 Private->SerialIo.Mode = &Private->SerialIoMode;
509
510 if (RemainingDevicePath != NULL) {
511 //
512 // Match the configuration of the RemainingDevicePath. IsHandleSupported()
513 // already checked to make sure the RemainingDevicePath contains settings
514 // that we can support.
515 //
516 CopyMem (&Private->UartDevicePath, RemainingDevicePath, sizeof (UART_DEVICE_PATH));
517 } else {
518 //
519 // Build the device path by appending the UART node to the ParentDevicePath
520 // from the UnixIo handle. The Uart setings are zero here, since
521 // SetAttribute() will update them to match the default setings.
522 //
523 ZeroMem (&Private->UartDevicePath, sizeof (UART_DEVICE_PATH));
524 Private->UartDevicePath.Header.Type = MESSAGING_DEVICE_PATH;
525 Private->UartDevicePath.Header.SubType = MSG_UART_DP;
526 SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath, sizeof (UART_DEVICE_PATH));
527 }
528
529 //
530 // Build the device path by appending the UART node to the ParentDevicePath
531 // from the UnixIo handle. The Uart setings are zero here, since
532 // SetAttribute() will update them to match the current setings.
533 //
534 Private->DevicePath = AppendDevicePathNode (
535 ParentDevicePath,
536 (EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath
537 );
538 if (Private->DevicePath == NULL) {
539 Status = EFI_OUT_OF_RESOURCES;
540 goto Error;
541 }
542
543 //
544 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
545 //
546 Private->SerialIoMode.ControlMask = SERIAL_CONTROL_MASK;
547 Private->SerialIoMode.Timeout = SERIAL_TIMEOUT_DEFAULT;
548 Private->SerialIoMode.BaudRate = Private->UartDevicePath.BaudRate;
549 Private->SerialIoMode.ReceiveFifoDepth = SERIAL_FIFO_DEFAULT;
550 Private->SerialIoMode.DataBits = Private->UartDevicePath.DataBits;
551 Private->SerialIoMode.Parity = Private->UartDevicePath.Parity;
552 Private->SerialIoMode.StopBits = Private->UartDevicePath.StopBits;
553
554 //
555 // Issue a reset to initialize the COM port
556 //
557 Status = Private->SerialIo.Reset (&Private->SerialIo);
558 if (EFI_ERROR (Status)) {
559 goto Error;
560 }
561
562 //
563 // Create new child handle
564 //
565 Status = gBS->InstallMultipleProtocolInterfaces (
566 &Private->Handle,
567 &gEfiSerialIoProtocolGuid,
568 &Private->SerialIo,
569 &gEfiDevicePathProtocolGuid,
570 Private->DevicePath,
571 NULL
572 );
573 if (EFI_ERROR (Status)) {
574 goto Error;
575 }
576
577 //
578 // Open For Child Device
579 //
580 Status = gBS->OpenProtocol (
581 Handle,
582 &gEfiUnixIoProtocolGuid,
583 (VOID**)&UnixIo,
584 This->DriverBindingHandle,
585 Private->Handle,
586 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
587 );
588 if (EFI_ERROR (Status)) {
589 goto Error;
590 }
591
592 return EFI_SUCCESS;
593
594 Error:
595 //
596 // Use the Stop() function to free all resources allocated in Start()
597 //
598 if (Private != NULL) {
599 if (Private->Handle != NULL) {
600 This->Stop (This, Handle, 1, &Private->Handle);
601 } else {
602 if (UnixHandle != -1) {
603 Private->UnixThunk->Close (UnixHandle);
604 }
605
606 if (Private->DevicePath != NULL) {
607 FreePool (Private->DevicePath);
608 }
609
610 FreeUnicodeStringTable (Private->ControllerNameTable);
611
612 FreePool (Private);
613 }
614 }
615
616 This->Stop (This, Handle, 0, NULL);
617
618 return Status;
619 }
620
621 EFI_STATUS
622 EFIAPI
623 UnixSerialIoDriverBindingStop (
624 IN EFI_DRIVER_BINDING_PROTOCOL *This,
625 IN EFI_HANDLE Handle,
626 IN UINTN NumberOfChildren,
627 IN EFI_HANDLE *ChildHandleBuffer
628 )
629 /*++
630
631 Routine Description:
632
633 TODO: Add function description
634
635 Arguments:
636
637 This - TODO: add argument description
638 Handle - TODO: add argument description
639 NumberOfChildren - TODO: add argument description
640 ChildHandleBuffer - TODO: add argument description
641
642 Returns:
643
644 EFI_DEVICE_ERROR - TODO: Add description for return value
645 EFI_SUCCESS - TODO: Add description for return value
646
647 --*/
648 {
649 EFI_STATUS Status;
650 UINTN Index;
651 BOOLEAN AllChildrenStopped;
652 EFI_SERIAL_IO_PROTOCOL *SerialIo;
653 UNIX_SERIAL_IO_PRIVATE_DATA *Private;
654 EFI_UNIX_IO_PROTOCOL *UnixIo;
655
656 //
657 // Complete all outstanding transactions to Controller.
658 // Don't allow any new transaction to Controller to be started.
659 //
660
661 if (NumberOfChildren == 0) {
662 //
663 // Close the bus driver
664 //
665 Status = gBS->CloseProtocol (
666 Handle,
667 &gEfiUnixIoProtocolGuid,
668 This->DriverBindingHandle,
669 Handle
670 );
671 Status = gBS->CloseProtocol (
672 Handle,
673 &gEfiDevicePathProtocolGuid,
674 This->DriverBindingHandle,
675 Handle
676 );
677 return Status;
678 }
679
680 AllChildrenStopped = TRUE;
681
682 for (Index = 0; Index < NumberOfChildren; Index++) {
683 Status = gBS->OpenProtocol (
684 ChildHandleBuffer[Index],
685 &gEfiSerialIoProtocolGuid,
686 (VOID**)&SerialIo,
687 This->DriverBindingHandle,
688 Handle,
689 EFI_OPEN_PROTOCOL_GET_PROTOCOL
690 );
691 if (!EFI_ERROR (Status)) {
692 Private = UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo);
693
694 ASSERT (Private->Handle == ChildHandleBuffer[Index]);
695
696 Status = gBS->CloseProtocol (
697 Handle,
698 &gEfiUnixIoProtocolGuid,
699 This->DriverBindingHandle,
700 ChildHandleBuffer[Index]
701 );
702
703 Status = gBS->UninstallMultipleProtocolInterfaces (
704 ChildHandleBuffer[Index],
705 &gEfiSerialIoProtocolGuid,
706 &Private->SerialIo,
707 &gEfiDevicePathProtocolGuid,
708 Private->DevicePath,
709 NULL
710 );
711
712 if (EFI_ERROR (Status)) {
713 gBS->OpenProtocol (
714 Handle,
715 &gEfiUnixIoProtocolGuid,
716 (VOID **) &UnixIo,
717 This->DriverBindingHandle,
718 ChildHandleBuffer[Index],
719 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
720 );
721 } else {
722 Private->UnixThunk->Close (Private->UnixHandle);
723
724 FreePool (Private->DevicePath);
725
726 FreeUnicodeStringTable (Private->ControllerNameTable);
727
728 FreePool (Private);
729 }
730 }
731
732 if (EFI_ERROR (Status)) {
733 AllChildrenStopped = FALSE;
734 }
735 }
736
737 if (!AllChildrenStopped) {
738 return EFI_DEVICE_ERROR;
739 }
740
741 return EFI_SUCCESS;
742 }
743
744 //
745 // Serial IO Protocol member functions
746 //
747
748 EFI_STATUS
749 EFIAPI
750 UnixSerialIoReset (
751 IN EFI_SERIAL_IO_PROTOCOL *This
752 )
753 /*++
754
755 Routine Description:
756
757 TODO: Add function description
758
759 Arguments:
760
761 This - TODO: add argument description
762
763 Returns:
764
765 TODO: add return values
766
767 --*/
768 {
769 UNIX_SERIAL_IO_PRIVATE_DATA *Private;
770 EFI_TPL Tpl;
771 UINTN UnixStatus;
772
773 Tpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
774
775 Private = UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
776
777 UnixStatus = Private->UnixThunk->Tcflush (
778 Private->UnixHandle,
779 TCIOFLUSH
780 );
781 switch (UnixStatus) {
782 case EBADF:
783 DEBUG ((EFI_D_ERROR, "Invalid handle of serial device!\r\n"));
784 return EFI_DEVICE_ERROR;
785 case EINVAL:
786 DEBUG ((EFI_D_ERROR, "Invalid queue selector!\r\n"));
787 return EFI_DEVICE_ERROR;
788 case ENOTTY:
789 DEBUG ((EFI_D_ERROR, "The file associated with serial's handle is not a terminal!\r\n"));
790 return EFI_DEVICE_ERROR;
791 default:
792 DEBUG ((EFI_D_ERROR, "The serial IO device is reset successfully!\r\n"));
793 }
794
795 gBS->RestoreTPL (Tpl);
796
797 return This->SetAttributes (
798 This,
799 This->Mode->BaudRate,
800 This->Mode->ReceiveFifoDepth,
801 This->Mode->Timeout,
802 This->Mode->Parity,
803 (UINT8) This->Mode->DataBits,
804 This->Mode->StopBits
805 );
806 }
807
808 EFI_STATUS
809 EFIAPI
810 UnixSerialIoSetAttributes (
811 IN EFI_SERIAL_IO_PROTOCOL *This,
812 IN UINT64 BaudRate,
813 IN UINT32 ReceiveFifoDepth,
814 IN UINT32 Timeout,
815 IN EFI_PARITY_TYPE Parity,
816 IN UINT8 DataBits,
817 IN EFI_STOP_BITS_TYPE StopBits
818 )
819 /*++
820
821 Routine Description:
822
823 This function is used to set the attributes.
824
825 Arguments:
826
827 This - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue.
828 BaudRate - The Baud rate of the serial device.
829 ReceiveFifoDepth - The request depth of fifo on receive side.
830 Timeout - the request timeout for a single charact.
831 Parity - The type of parity used in serial device.
832 DataBits - Number of deata bits used in serial device.
833 StopBits - Number of stop bits used in serial device.
834
835 Returns:
836 Status code
837
838 None
839
840 --*/
841 {
842 EFI_STATUS Status;
843 UNIX_SERIAL_IO_PRIVATE_DATA *Private;
844 EFI_TPL Tpl;
845 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
846
847 Tpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
848 Private = UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
849
850 //
851 // Some of our arguments have defaults if a null value is passed in, and
852 // we must set the default values if a null argument is passed in.
853 //
854 if (BaudRate == 0) {
855 BaudRate = SERIAL_BAUD_DEFAULT;
856 }
857
858 if (ReceiveFifoDepth == 0) {
859 ReceiveFifoDepth = SERIAL_FIFO_DEFAULT;
860 }
861
862 if (Timeout == 0) {
863 Timeout = SERIAL_TIMEOUT_DEFAULT;
864 }
865
866 if (Parity == DefaultParity) {
867 Parity = NoParity;
868 }
869
870 if (DataBits == 0) {
871 DataBits = SERIAL_DATABITS_DEFAULT;
872 }
873
874 if (StopBits == DefaultStopBits) {
875 StopBits = OneStopBit;
876 }
877
878 //
879 // See if the new attributes already match the current attributes
880 //
881 if (Private->UartDevicePath.BaudRate == BaudRate &&
882 Private->UartDevicePath.DataBits == DataBits &&
883 Private->UartDevicePath.Parity == Parity &&
884 Private->UartDevicePath.StopBits == StopBits &&
885 Private->SerialIoMode.ReceiveFifoDepth == ReceiveFifoDepth &&
886 Private->SerialIoMode.Timeout == Timeout ) {
887 gBS->RestoreTPL(Tpl);
888 return EFI_SUCCESS;
889 }
890
891 //
892 // Try to get options from serial device.
893 //
894 if (Private->UnixThunk->Tcgetattr (Private->UnixHandle, &Private->UnixTermios) == -1) {
895 Private->UnixThunk->Perror ("IoSetAttributes");
896 gBS->RestoreTPL (Tpl);
897 return EFI_DEVICE_ERROR;
898 }
899
900 //
901 // Setting Baud Rate
902 //
903 Private->UnixThunk->Cfsetispeed (&Private->UnixTermios, ConvertBaud2Unix(BaudRate));
904 Private->UnixThunk->Cfsetospeed (&Private->UnixTermios, ConvertBaud2Unix(BaudRate));
905 //
906 // Setting DataBits
907 //
908 Private->UnixTermios.c_cflag &= ~CSIZE;
909 Private->UnixTermios.c_cflag |= ConvertByteSize2Unix (DataBits);
910 //
911 // Setting Parity
912 //
913 ConvertParity2Unix (&Private->UnixTermios, Parity);
914 //
915 // Setting StopBits
916 //
917 ConvertStopBit2Unix (&Private->UnixTermios, StopBits);
918 //
919 // Raw input
920 //
921 Private->UnixTermios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
922 //
923 // Raw output
924 //
925 Private->UnixTermios.c_oflag &= ~OPOST;
926 //
927 // Support hardware flow control
928 //
929 Private->UnixTermios.c_cflag &= ~CRTSCTS;;
930 //
931 // Time out
932 //
933 Private->UnixTermios.c_cc[VMIN] = 0;
934 Private->UnixTermios.c_cc[VTIME] = (Timeout/1000000) * 10;
935
936 //
937 // Set the options
938 //
939 if (-1 == Private->UnixThunk->Tcsetattr (
940 Private->UnixHandle,
941 TCSANOW,
942 &Private->UnixTermios
943 )) {
944 DEBUG ((EFI_D_INFO, "Fail to set options for serial device!\r\n"));
945 return EFI_DEVICE_ERROR;
946 }
947
948 //
949 // Update mode
950 //
951 Private->SerialIoMode.BaudRate = BaudRate;
952 Private->SerialIoMode.ReceiveFifoDepth = ReceiveFifoDepth;
953 Private->SerialIoMode.Timeout = Timeout;
954 Private->SerialIoMode.Parity = Parity;
955 Private->SerialIoMode.DataBits = DataBits;
956 Private->SerialIoMode.StopBits = StopBits;
957 //
958 // See if Device Path Node has actually changed
959 //
960 if (Private->UartDevicePath.BaudRate == BaudRate &&
961 Private->UartDevicePath.DataBits == DataBits &&
962 Private->UartDevicePath.Parity == Parity &&
963 Private->UartDevicePath.StopBits == StopBits ) {
964 gBS->RestoreTPL(Tpl);
965 return EFI_SUCCESS;
966 }
967
968 //
969 // Update the device path
970 //
971 Private->UartDevicePath.BaudRate = BaudRate;
972 Private->UartDevicePath.DataBits = DataBits;
973 Private->UartDevicePath.Parity = (UINT8) Parity;
974 Private->UartDevicePath.StopBits = (UINT8) StopBits;
975
976 NewDevicePath = AppendDevicePathNode (
977 Private->ParentDevicePath,
978 (EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath
979 );
980 if (NewDevicePath == NULL) {
981 gBS->RestoreTPL (Tpl);
982 return EFI_DEVICE_ERROR;
983 }
984
985 if (Private->Handle != NULL) {
986 Status = gBS->ReinstallProtocolInterface (
987 Private->Handle,
988 &gEfiDevicePathProtocolGuid,
989 Private->DevicePath,
990 NewDevicePath
991 );
992 if (EFI_ERROR (Status)) {
993 gBS->RestoreTPL (Tpl);
994 return Status;
995 }
996 }
997
998 if (Private->DevicePath != NULL) {
999 FreePool (Private->DevicePath);
1000 }
1001
1002 Private->DevicePath = NewDevicePath;
1003
1004 gBS->RestoreTPL (Tpl);
1005
1006 return EFI_SUCCESS;
1007 }
1008
1009 EFI_STATUS
1010 EFIAPI
1011 UnixSerialIoSetControl (
1012 IN EFI_SERIAL_IO_PROTOCOL *This,
1013 IN UINT32 Control
1014 )
1015 /*++
1016
1017 Routine Description:
1018
1019 TODO: Add function description
1020
1021 Arguments:
1022
1023 This - TODO: add argument description
1024 Control - TODO: add argument description
1025
1026 Returns:
1027
1028 EFI_DEVICE_ERROR - TODO: Add description for return value
1029 EFI_DEVICE_ERROR - TODO: Add description for return value
1030 EFI_SUCCESS - TODO: Add description for return value
1031
1032 --*/
1033 {
1034 UNIX_SERIAL_IO_PRIVATE_DATA *Private;
1035 UINTN Result;
1036 UINTN Status;
1037 struct termios Options;
1038 EFI_TPL Tpl;
1039
1040 Tpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
1041
1042 Private = UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
1043
1044 Result = Private->UnixThunk->IoCtl (Private->UnixHandle, TIOCMGET, &Status);
1045
1046 if (Result == -1) {
1047 Private->UnixThunk->Perror ("SerialSetControl");
1048 gBS->RestoreTPL (Tpl);
1049 return EFI_DEVICE_ERROR;
1050 }
1051
1052 Private->HardwareFlowControl = FALSE;
1053 Private->SoftwareLoopbackEnable = FALSE;
1054 Private->HardwareLoopbackEnable = FALSE;
1055
1056 if (Control & EFI_SERIAL_REQUEST_TO_SEND) {
1057 Options.c_cflag |= TIOCM_RTS;
1058 }
1059
1060 if (Control & EFI_SERIAL_DATA_TERMINAL_READY) {
1061 Options.c_cflag |= TIOCM_DTR;
1062 }
1063
1064 if (Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {
1065 Private->HardwareFlowControl = TRUE;
1066 }
1067
1068 if (Control & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) {
1069 Private->SoftwareLoopbackEnable = TRUE;
1070 }
1071
1072 if (Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {
1073 Private->HardwareLoopbackEnable = TRUE;
1074 }
1075
1076 Result = Private->UnixThunk->IoCtl (Private->UnixHandle, TIOCMSET, &Status);
1077
1078 if (Result == -1) {
1079 Private->UnixThunk->Perror ("SerialSetControl");
1080 gBS->RestoreTPL (Tpl);
1081 return EFI_DEVICE_ERROR;
1082 }
1083
1084 gBS->RestoreTPL (Tpl);
1085
1086 return EFI_SUCCESS;
1087 }
1088
1089 EFI_STATUS
1090 EFIAPI
1091 UnixSerialIoGetControl (
1092 IN EFI_SERIAL_IO_PROTOCOL *This,
1093 OUT UINT32 *Control
1094 )
1095 /*++
1096
1097 Routine Description:
1098
1099 TODO: Add function description
1100
1101 Arguments:
1102
1103 This - TODO: add argument description
1104 Control - TODO: add argument description
1105
1106 Returns:
1107
1108 EFI_DEVICE_ERROR - TODO: Add description for return value
1109 EFI_DEVICE_ERROR - TODO: Add description for return value
1110 EFI_DEVICE_ERROR - TODO: Add description for return value
1111 EFI_SUCCESS - TODO: Add description for return value
1112
1113 --*/
1114 {
1115 UNIX_SERIAL_IO_PRIVATE_DATA *Private;
1116 UINTN Result;
1117 UINTN Status;
1118 UINT32 Bits;
1119 EFI_TPL Tpl;
1120 UINTN Bytes;
1121
1122 Tpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
1123
1124 Private = UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
1125 Result = Private->UnixThunk->IoCtl (Private->UnixHandle, TIOCMGET, &Status);
1126 if (Result == -1) {
1127 Private->UnixThunk->Perror ("SerialGetControl");
1128 gBS->RestoreTPL (Tpl);
1129 return EFI_DEVICE_ERROR;
1130 }
1131
1132 if ((Status & TIOCM_CTS) == TIOCM_CTS) {
1133 Bits |= EFI_SERIAL_CLEAR_TO_SEND;
1134 }
1135
1136 if ((Status & TIOCM_DSR) == TIOCM_DSR) {
1137 Bits |= EFI_SERIAL_DATA_SET_READY;
1138 }
1139
1140 if ((Status & TIOCM_DTR) == TIOCM_DTR) {
1141 Bits |= EFI_SERIAL_DATA_TERMINAL_READY;
1142 }
1143
1144 if ((Status & TIOCM_RTS) == TIOCM_RTS) {
1145 Bits |= EFI_SERIAL_REQUEST_TO_SEND;
1146 }
1147
1148 if ((Status & TIOCM_RNG) == TIOCM_RNG) {
1149 Bits |= EFI_SERIAL_RING_INDICATE;
1150 }
1151
1152 if ((Status & TIOCM_CAR) == TIOCM_CAR) {
1153 Bits |= EFI_SERIAL_CARRIER_DETECT;
1154 }
1155
1156 if (Private->HardwareFlowControl) {
1157 Bits |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
1158 }
1159
1160 if (Private->SoftwareLoopbackEnable) {
1161 Bits |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;
1162 }
1163
1164 if (Private->HardwareLoopbackEnable) {
1165 Bits |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;
1166 }
1167
1168 Result = Private->UnixThunk->IoCtl (Private->UnixHandle, FIONREAD, &Bytes);
1169 if (Result == -1) {
1170 Private->UnixThunk->Perror ("SerialGetControl");
1171 gBS->RestoreTPL (Tpl);
1172 return EFI_DEVICE_ERROR;
1173 }
1174
1175 if (Bytes == 0) {
1176 Bits |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
1177 }
1178
1179 *Control = Bits;
1180
1181 gBS->RestoreTPL (Tpl);
1182
1183 return EFI_SUCCESS;
1184 }
1185
1186 EFI_STATUS
1187 EFIAPI
1188 UnixSerialIoWrite (
1189 IN EFI_SERIAL_IO_PROTOCOL *This,
1190 IN OUT UINTN *BufferSize,
1191 IN VOID *Buffer
1192 )
1193 /*++
1194
1195 Routine Description:
1196
1197 TODO: Add function description
1198
1199 Arguments:
1200
1201 This - TODO: add argument description
1202 BufferSize - TODO: add argument description
1203 Buffer - TODO: add argument description
1204
1205 Returns:
1206
1207 EFI_DEVICE_ERROR - TODO: Add description for return value
1208 EFI_SUCCESS - TODO: Add description for return value
1209
1210 --*/
1211 {
1212 UNIX_SERIAL_IO_PRIVATE_DATA *Private;
1213 UINT8 *ByteBuffer;
1214 UINT32 TotalBytesWritten;
1215 UINT32 BytesToGo;
1216 UINT32 BytesWritten;
1217 UINT32 Index;
1218 UINT32 Control;
1219 EFI_TPL Tpl;
1220
1221 Tpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
1222
1223 Private = UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
1224
1225 ByteBuffer = (UINT8 *) Buffer;
1226 TotalBytesWritten = 0;
1227
1228 if (Private->SoftwareLoopbackEnable || Private->HardwareLoopbackEnable) {
1229 for (Index = 0; Index < *BufferSize; Index++) {
1230 if (IsaSerialFifoAdd (&Private->Fifo, ByteBuffer[Index]) == EFI_SUCCESS) {
1231 TotalBytesWritten++;
1232 } else {
1233 break;
1234 }
1235 }
1236 } else {
1237 BytesToGo = (*BufferSize);
1238
1239 do {
1240 if (Private->HardwareFlowControl) {
1241 //
1242 // Send RTS
1243 //
1244 UnixSerialIoGetControl (&Private->SerialIo, &Control);
1245 Control |= EFI_SERIAL_REQUEST_TO_SEND;
1246 UnixSerialIoSetControl (&Private->SerialIo, Control);
1247 }
1248
1249 //
1250 // Do the write
1251 //
1252 BytesWritten = Private->UnixThunk->Write (
1253 Private->UnixHandle,
1254 &ByteBuffer[TotalBytesWritten],
1255 BytesToGo
1256 );
1257
1258 if (Private->HardwareFlowControl) {
1259 //
1260 // Assert RTS
1261 //
1262 UnixSerialIoGetControl (&Private->SerialIo, &Control);
1263 Control &= ~ (UINT32) EFI_SERIAL_REQUEST_TO_SEND;
1264 UnixSerialIoSetControl (&Private->SerialIo, Control);
1265 }
1266
1267 TotalBytesWritten += BytesWritten;
1268 BytesToGo -= BytesWritten;
1269 } while (BytesToGo > 0);
1270 }
1271
1272 *BufferSize = TotalBytesWritten;
1273
1274 gBS->RestoreTPL (Tpl);
1275
1276 return EFI_SUCCESS;
1277 }
1278
1279 EFI_STATUS
1280 EFIAPI
1281 UnixSerialIoRead (
1282 IN EFI_SERIAL_IO_PROTOCOL *This,
1283 IN OUT UINTN *BufferSize,
1284 OUT VOID *Buffer
1285 )
1286 /*++
1287
1288 Routine Description:
1289
1290 TODO: Add function description
1291
1292 Arguments:
1293
1294 This - TODO: add argument description
1295 BufferSize - TODO: add argument description
1296 Buffer - TODO: add argument description
1297
1298 Returns:
1299
1300 EFI_DEVICE_ERROR - TODO: Add description for return value
1301
1302 --*/
1303 {
1304 UNIX_SERIAL_IO_PRIVATE_DATA *Private;
1305 UINT32 BytesRead;
1306 EFI_STATUS Status;
1307 UINT32 Index;
1308 UINT8 Data;
1309 UINT32 Control;
1310 EFI_TPL Tpl;
1311
1312 Tpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
1313
1314 Private = UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
1315
1316 //
1317 // Do the read
1318 //
1319 if (Private->SoftwareLoopbackEnable || Private->HardwareLoopbackEnable) {
1320 for (Index = 0, BytesRead = 0; Index < *BufferSize; Index++) {
1321 if (IsaSerialFifoRemove (&Private->Fifo, &Data) == EFI_SUCCESS) {
1322 ((UINT8 *) Buffer)[Index] = Data;
1323 BytesRead++;
1324 } else {
1325 break;
1326 }
1327 }
1328 } else {
1329 if (Private->HardwareFlowControl) {
1330 UnixSerialIoGetControl (&Private->SerialIo, &Control);
1331 Control |= EFI_SERIAL_DATA_TERMINAL_READY;
1332 UnixSerialIoSetControl (&Private->SerialIo, Control);
1333 }
1334
1335 BytesRead = Private->UnixThunk->Read (Private->UnixHandle, Buffer, *BufferSize);
1336 if (Private->HardwareFlowControl) {
1337 UnixSerialIoGetControl (&Private->SerialIo, &Control);
1338 Control &= ~ (UINT32) EFI_SERIAL_DATA_TERMINAL_READY;
1339 UnixSerialIoSetControl (&Private->SerialIo, Control);
1340 }
1341
1342 }
1343
1344 if (BytesRead != *BufferSize) {
1345 Status = EFI_TIMEOUT;
1346 } else {
1347 Status = EFI_SUCCESS;
1348 }
1349
1350 *BufferSize = (UINTN) BytesRead;
1351
1352 gBS->RestoreTPL (Tpl);
1353
1354 return Status;
1355 }
1356
1357 BOOLEAN
1358 IsaSerialFifoFull (
1359 IN SERIAL_DEV_FIFO *Fifo
1360 )
1361 /*++
1362
1363 Routine Description:
1364 Detect whether specific FIFO is full or not
1365
1366 Arguments:
1367 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1368
1369 Returns:
1370 TRUE: the FIFO is full
1371 FALSE: the FIFO is not full
1372
1373 --*/
1374 {
1375 if (Fifo->Surplus == 0) {
1376 return TRUE;
1377 }
1378
1379 return FALSE;
1380 }
1381
1382 BOOLEAN
1383 IsaSerialFifoEmpty (
1384 IN SERIAL_DEV_FIFO *Fifo
1385 )
1386 /*++
1387
1388 Routine Description:
1389 Detect whether specific FIFO is empty or not
1390
1391 Arguments:
1392 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1393
1394 Returns:
1395 TRUE: the FIFO is empty
1396 FALSE: the FIFO is not empty
1397
1398 --*/
1399 {
1400 if (Fifo->Surplus == SERIAL_MAX_BUFFER_SIZE) {
1401 return TRUE;
1402 }
1403
1404 return FALSE;
1405 }
1406
1407 EFI_STATUS
1408 IsaSerialFifoAdd (
1409 IN SERIAL_DEV_FIFO *Fifo,
1410 IN UINT8 Data
1411 )
1412 /*++
1413
1414 Routine Description:
1415 Add data to specific FIFO
1416
1417 Arguments:
1418 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1419 Data UINT8: the data added to FIFO
1420
1421 Returns:
1422 EFI_SUCCESS: Add data to specific FIFO successfully
1423 EFI_OUT_RESOURCE: Failed to add data because FIFO is already full
1424
1425 --*/
1426 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1427 {
1428 //
1429 // if FIFO full can not add data
1430 //
1431 if (IsaSerialFifoFull (Fifo)) {
1432 return EFI_OUT_OF_RESOURCES;
1433 }
1434
1435 //
1436 // FIFO is not full can add data
1437 //
1438 Fifo->Data[Fifo->Last] = Data;
1439 Fifo->Surplus--;
1440 Fifo->Last++;
1441 if (Fifo->Last >= SERIAL_MAX_BUFFER_SIZE) {
1442 Fifo->Last = 0;
1443 }
1444
1445 return EFI_SUCCESS;
1446 }
1447
1448 EFI_STATUS
1449 IsaSerialFifoRemove (
1450 IN SERIAL_DEV_FIFO *Fifo,
1451 OUT UINT8 *Data
1452 )
1453 /*++
1454
1455 Routine Description:
1456 Remove data from specific FIFO
1457
1458 Arguments:
1459 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1460 Data UINT8*: the data removed from FIFO
1461
1462 Returns:
1463 EFI_SUCCESS: Remove data from specific FIFO successfully
1464 EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty
1465
1466 --*/
1467 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1468 {
1469 //
1470 // if FIFO is empty, no data can remove
1471 //
1472 if (IsaSerialFifoEmpty (Fifo)) {
1473 return EFI_OUT_OF_RESOURCES;
1474 }
1475
1476 //
1477 // FIFO is not empty, can remove data
1478 //
1479 *Data = Fifo->Data[Fifo->First];
1480 Fifo->Surplus++;
1481 Fifo->First++;
1482 if (Fifo->First >= SERIAL_MAX_BUFFER_SIZE) {
1483 Fifo->First = 0;
1484 }
1485
1486 return EFI_SUCCESS;
1487 }