• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Top level C file for debugport driver.  Contains initialization function.
3   This driver layers on top of SerialIo.
4   ALL CODE IN THE SERIALIO STACK MUST BE RE-ENTRANT AND CALLABLE FROM
5   INTERRUPT CONTEXT
6 
7 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
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 "DebugPort.h"
19 
20 //
21 // Globals
22 //
23 EFI_DRIVER_BINDING_PROTOCOL gDebugPortDriverBinding = {
24   DebugPortSupported,
25   DebugPortStart,
26   DebugPortStop,
27   DEBUGPORT_DRIVER_VERSION,
28   NULL,
29   NULL
30 };
31 
32 DEBUGPORT_DEVICE mDebugPortDevice = {
33   DEBUGPORT_DEVICE_SIGNATURE,
34   (EFI_HANDLE) 0,
35   (EFI_HANDLE) 0,
36   (EFI_DEVICE_PATH_PROTOCOL *) NULL,
37   {
38     DebugPortReset,
39     DebugPortWrite,
40     DebugPortRead,
41     DebugPortPoll
42   },
43   (EFI_HANDLE) 0,
44   (EFI_SERIAL_IO_PROTOCOL *) NULL,
45   DEBUGPORT_UART_DEFAULT_BAUDRATE,
46   DEBUGPORT_UART_DEFAULT_FIFO_DEPTH,
47   DEBUGPORT_UART_DEFAULT_TIMEOUT,
48   (EFI_PARITY_TYPE) DEBUGPORT_UART_DEFAULT_PARITY,
49   DEBUGPORT_UART_DEFAULT_DATA_BITS,
50   (EFI_STOP_BITS_TYPE) DEBUGPORT_UART_DEFAULT_STOP_BITS
51 };
52 
53 /**
54   Local worker function to obtain device path information from DebugPort variable.
55 
56   Records requested settings in DebugPort device structure.
57 
58 **/
59 EFI_DEVICE_PATH_PROTOCOL *
GetDebugPortVariable(VOID)60 GetDebugPortVariable (
61   VOID
62   )
63 {
64   UINTN                     DataSize;
65   EFI_DEVICE_PATH_PROTOCOL  *DebugPortVariable;
66   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
67 
68   GetVariable2 (EFI_DEBUGPORT_VARIABLE_NAME, &gEfiDebugPortVariableGuid, (VOID **) &DebugPortVariable, &DataSize);
69   if (DebugPortVariable == NULL) {
70     return NULL;
71   }
72 
73   DevicePath = DebugPortVariable;
74   while (!IsDevicePathEnd (DevicePath) && !IS_UART_DEVICEPATH (DevicePath)) {
75     DevicePath = NextDevicePathNode (DevicePath);
76   }
77 
78   if (IsDevicePathEnd (DevicePath)) {
79     FreePool (DebugPortVariable);
80     return NULL;
81   } else {
82     CopyMem (
83       &mDebugPortDevice.BaudRate,
84       &((UART_DEVICE_PATH *) DevicePath)->BaudRate,
85       sizeof (((UART_DEVICE_PATH *) DevicePath)->BaudRate)
86       );
87     mDebugPortDevice.ReceiveFifoDepth = DEBUGPORT_UART_DEFAULT_FIFO_DEPTH;
88     mDebugPortDevice.Timeout          = DEBUGPORT_UART_DEFAULT_TIMEOUT;
89     CopyMem (
90       &mDebugPortDevice.Parity,
91       &((UART_DEVICE_PATH *) DevicePath)->Parity,
92       sizeof (((UART_DEVICE_PATH *) DevicePath)->Parity)
93       );
94     CopyMem (
95       &mDebugPortDevice.DataBits,
96       &((UART_DEVICE_PATH *) DevicePath)->DataBits,
97       sizeof (((UART_DEVICE_PATH *) DevicePath)->DataBits)
98       );
99     CopyMem (
100       &mDebugPortDevice.StopBits,
101       &((UART_DEVICE_PATH *) DevicePath)->StopBits,
102       sizeof (((UART_DEVICE_PATH *) DevicePath)->StopBits)
103       );
104     return DebugPortVariable;
105   }
106 }
107 
108 /**
109   Debug Port Driver entry point.
110 
111   Reads DebugPort variable to determine what device and settings to use as the
112   debug port.  Binds exclusively to SerialIo. Reverts to defaults if no variable
113   is found.
114 
115   @param[in] ImageHandle       The firmware allocated handle for the EFI image.
116   @param[in] SystemTable       A pointer to the EFI System Table.
117 
118   @retval EFI_SUCCESS          The entry point is executed successfully.
119   @retval EFI_OUT_OF_RESOURCES Fails to allocate memory for device.
120   @retval other                Some error occurs when executing this entry point.
121 
122 **/
123 EFI_STATUS
124 EFIAPI
InitializeDebugPortDriver(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)125 InitializeDebugPortDriver (
126   IN EFI_HANDLE             ImageHandle,
127   IN EFI_SYSTEM_TABLE       *SystemTable
128   )
129 {
130   EFI_STATUS    Status;
131 
132   //
133   // Install driver model protocol(s).
134   //
135   Status = EfiLibInstallDriverBindingComponentName2 (
136              ImageHandle,
137              SystemTable,
138              &gDebugPortDriverBinding,
139              ImageHandle,
140              &gDebugPortComponentName,
141              &gDebugPortComponentName2
142              );
143   ASSERT_EFI_ERROR (Status);
144 
145   return Status;
146 }
147 
148 /**
149   Checks to see if there's not already a DebugPort interface somewhere.
150 
151   If there's a DEBUGPORT variable, the device path must match exactly.  If there's
152   no DEBUGPORT variable, then device path is not checked and does not matter.
153   Checks to see that there's a serial io interface on the controller handle
154   that can be bound BY_DRIVER | EXCLUSIVE.
155   If all these tests succeed, then we return EFI_SUCCESS, else, EFI_UNSUPPORTED
156   or other error returned by OpenProtocol.
157 
158   @param  This                 Protocol instance pointer.
159   @param  ControllerHandle     Handle of device to test.
160   @param  RemainingDevicePath  Optional parameter use to pick a specific child
161                                device to start.
162 
163   @retval EFI_SUCCESS          This driver supports this device.
164   @retval EFI_UNSUPPORTED      Debug Port device is not supported.
165   @retval EFI_OUT_OF_RESOURCES Fails to allocate memory for device.
166   @retval others               Some error occurs.
167 
168 **/
169 EFI_STATUS
170 EFIAPI
DebugPortSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)171 DebugPortSupported (
172   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
173   IN EFI_HANDLE                     ControllerHandle,
174   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
175   )
176 {
177   EFI_STATUS                Status;
178   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
179   EFI_DEVICE_PATH_PROTOCOL  *DebugPortVariable;
180   EFI_SERIAL_IO_PROTOCOL    *SerialIo;
181   EFI_DEBUGPORT_PROTOCOL    *DebugPortInterface;
182   EFI_HANDLE                TempHandle;
183 
184   //
185   // Check to see that there's not a debugport protocol already published,
186   // since only one standard UART serial port could be supported by this driver.
187   //
188   if (gBS->LocateProtocol (&gEfiDebugPortProtocolGuid, NULL, (VOID **) &DebugPortInterface) != EFI_NOT_FOUND) {
189     return EFI_UNSUPPORTED;
190   }
191   //
192   // Read DebugPort variable to determine debug port selection and parameters
193   //
194   DebugPortVariable = GetDebugPortVariable ();
195 
196   if (DebugPortVariable != NULL) {
197     //
198     // There's a DEBUGPORT variable, so do LocateDevicePath and check to see if
199     // the closest matching handle matches the controller handle, and if it does,
200     // check to see that the remaining device path has the DebugPort GUIDed messaging
201     // device path only.  Otherwise, it's a mismatch and EFI_UNSUPPORTED is returned.
202     //
203     DevicePath = DebugPortVariable;
204     Status = gBS->LocateDevicePath (
205                     &gEfiSerialIoProtocolGuid,
206                     &DevicePath,
207                     &TempHandle
208                     );
209 
210     if (Status == EFI_SUCCESS && TempHandle != ControllerHandle) {
211       Status = EFI_UNSUPPORTED;
212     }
213 
214     if (Status == EFI_SUCCESS &&
215         (DevicePath->Type != MESSAGING_DEVICE_PATH ||
216          DevicePath->SubType != MSG_VENDOR_DP ||
217          *((UINT16 *) DevicePath->Length) != sizeof (DEBUGPORT_DEVICE_PATH))) {
218 
219       Status = EFI_UNSUPPORTED;
220     }
221 
222     if (Status == EFI_SUCCESS && !CompareGuid (&gEfiDebugPortDevicePathGuid, (GUID *) (DevicePath + 1))) {
223       Status = EFI_UNSUPPORTED;
224     }
225 
226     FreePool (DebugPortVariable);
227     if (EFI_ERROR (Status)) {
228       return Status;
229     }
230   }
231 
232   Status = gBS->OpenProtocol (
233                   ControllerHandle,
234                   &gEfiSerialIoProtocolGuid,
235                   (VOID **) &SerialIo,
236                   This->DriverBindingHandle,
237                   ControllerHandle,
238                   EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE
239                   );
240   if (EFI_ERROR (Status)) {
241     return Status;
242   }
243 
244   Status = gBS->CloseProtocol (
245                   ControllerHandle,
246                   &gEfiSerialIoProtocolGuid,
247                   This->DriverBindingHandle,
248                   ControllerHandle
249                   );
250 
251   return Status;
252 }
253 
254 /**
255   Binds exclusively to serial io on the controller handle, Produces DebugPort
256   protocol and DevicePath on new handle.
257 
258   @param  This                 Protocol instance pointer.
259   @param  ControllerHandle     Handle of device to bind driver to.
260   @param  RemainingDevicePath  Optional parameter use to pick a specific child
261                                device to start.
262 
263   @retval EFI_SUCCESS          This driver is added to ControllerHandle.
264   @retval EFI_OUT_OF_RESOURCES Fails to allocate memory for device.
265   @retval others               Some error occurs.
266 
267 **/
268 EFI_STATUS
269 EFIAPI
DebugPortStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)270 DebugPortStart (
271   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
272   IN EFI_HANDLE                     ControllerHandle,
273   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
274   )
275 {
276   EFI_STATUS                Status;
277   DEBUGPORT_DEVICE_PATH     DebugPortDP;
278   EFI_DEVICE_PATH_PROTOCOL  EndDP;
279   EFI_DEVICE_PATH_PROTOCOL  *Dp1;
280 
281   Status = gBS->OpenProtocol (
282                   ControllerHandle,
283                   &gEfiSerialIoProtocolGuid,
284                   (VOID **) &mDebugPortDevice.SerialIoBinding,
285                   This->DriverBindingHandle,
286                   ControllerHandle,
287                   EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE
288                   );
289   if (EFI_ERROR (Status)) {
290     return Status;
291   }
292 
293   mDebugPortDevice.SerialIoDeviceHandle = ControllerHandle;
294 
295   //
296   // Initialize the Serial Io interface...
297   //
298   Status = mDebugPortDevice.SerialIoBinding->SetAttributes (
299                                                 mDebugPortDevice.SerialIoBinding,
300                                                 mDebugPortDevice.BaudRate,
301                                                 mDebugPortDevice.ReceiveFifoDepth,
302                                                 mDebugPortDevice.Timeout,
303                                                 mDebugPortDevice.Parity,
304                                                 mDebugPortDevice.DataBits,
305                                                 mDebugPortDevice.StopBits
306                                                 );
307   if (EFI_ERROR (Status)) {
308     mDebugPortDevice.BaudRate          = 0;
309     mDebugPortDevice.Parity            = DefaultParity;
310     mDebugPortDevice.DataBits          = 0;
311     mDebugPortDevice.StopBits          = DefaultStopBits;
312     mDebugPortDevice.ReceiveFifoDepth  = 0;
313     Status = mDebugPortDevice.SerialIoBinding->SetAttributes (
314                                                   mDebugPortDevice.SerialIoBinding,
315                                                   mDebugPortDevice.BaudRate,
316                                                   mDebugPortDevice.ReceiveFifoDepth,
317                                                   mDebugPortDevice.Timeout,
318                                                   mDebugPortDevice.Parity,
319                                                   mDebugPortDevice.DataBits,
320                                                   mDebugPortDevice.StopBits
321                                                   );
322     if (EFI_ERROR (Status)) {
323       gBS->CloseProtocol (
324             ControllerHandle,
325             &gEfiSerialIoProtocolGuid,
326             This->DriverBindingHandle,
327             ControllerHandle
328             );
329       return Status;
330     }
331   }
332 
333   mDebugPortDevice.SerialIoBinding->Reset (mDebugPortDevice.SerialIoBinding);
334 
335   //
336   // Create device path instance for DebugPort
337   //
338   DebugPortDP.Header.Type     = MESSAGING_DEVICE_PATH;
339   DebugPortDP.Header.SubType  = MSG_VENDOR_DP;
340   SetDevicePathNodeLength (&(DebugPortDP.Header), sizeof (DebugPortDP));
341   CopyGuid (&DebugPortDP.Guid, &gEfiDebugPortDevicePathGuid);
342 
343   Dp1 = DevicePathFromHandle (ControllerHandle);
344   if (Dp1 == NULL) {
345     Dp1 = &EndDP;
346     SetDevicePathEndNode (Dp1);
347   }
348 
349   mDebugPortDevice.DebugPortDevicePath = AppendDevicePathNode (Dp1, (EFI_DEVICE_PATH_PROTOCOL *) &DebugPortDP);
350   if (mDebugPortDevice.DebugPortDevicePath == NULL) {
351     return EFI_OUT_OF_RESOURCES;
352   }
353   //
354   // Publish DebugPort and Device Path protocols
355   //
356   Status = gBS->InstallMultipleProtocolInterfaces (
357                   &mDebugPortDevice.DebugPortDeviceHandle,
358                   &gEfiDevicePathProtocolGuid,
359                   mDebugPortDevice.DebugPortDevicePath,
360                   &gEfiDebugPortProtocolGuid,
361                   &mDebugPortDevice.DebugPortInterface,
362                   NULL
363                   );
364 
365   if (EFI_ERROR (Status)) {
366     gBS->CloseProtocol (
367           ControllerHandle,
368           &gEfiSerialIoProtocolGuid,
369           This->DriverBindingHandle,
370           ControllerHandle
371           );
372     return Status;
373   }
374   //
375   // Connect debugport child to serial io
376   //
377   Status = gBS->OpenProtocol (
378                   ControllerHandle,
379                   &gEfiSerialIoProtocolGuid,
380                   (VOID **) &mDebugPortDevice.SerialIoBinding,
381                   This->DriverBindingHandle,
382                   mDebugPortDevice.DebugPortDeviceHandle,
383                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
384                   );
385 
386   if (EFI_ERROR (Status)) {
387     gBS->CloseProtocol (
388           ControllerHandle,
389           &gEfiSerialIoProtocolGuid,
390           This->DriverBindingHandle,
391           ControllerHandle
392           );
393     return Status;
394   }
395 
396   return EFI_SUCCESS;
397 }
398 
399 /**
400   Stop this driver on ControllerHandle by removing Serial IO protocol on
401   the ControllerHandle.
402 
403   @param  This              Protocol instance pointer.
404   @param  ControllerHandle  Handle of device to stop driver on
405   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
406                             children is zero stop the entire bus driver.
407   @param  ChildHandleBuffer List of Child Handles to Stop.
408 
409   @retval EFI_SUCCESS       This driver is removed ControllerHandle.
410   @retval other             This driver was not removed from this device.
411 
412 **/
413 EFI_STATUS
414 EFIAPI
DebugPortStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)415 DebugPortStop (
416   IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
417   IN  EFI_HANDLE                     ControllerHandle,
418   IN  UINTN                          NumberOfChildren,
419   IN  EFI_HANDLE                     *ChildHandleBuffer
420   )
421 {
422   EFI_STATUS  Status;
423 
424   if (NumberOfChildren == 0) {
425     //
426     // Close the bus driver
427     //
428     gBS->CloseProtocol (
429           ControllerHandle,
430           &gEfiSerialIoProtocolGuid,
431           This->DriverBindingHandle,
432           ControllerHandle
433           );
434 
435     mDebugPortDevice.SerialIoBinding = NULL;
436 
437     gBS->CloseProtocol (
438           ControllerHandle,
439           &gEfiDevicePathProtocolGuid,
440           This->DriverBindingHandle,
441           ControllerHandle
442           );
443 
444     FreePool (mDebugPortDevice.DebugPortDevicePath);
445 
446     return EFI_SUCCESS;
447   } else {
448     //
449     // Disconnect SerialIo child handle
450     //
451     Status = gBS->CloseProtocol (
452                     mDebugPortDevice.SerialIoDeviceHandle,
453                     &gEfiSerialIoProtocolGuid,
454                     This->DriverBindingHandle,
455                     mDebugPortDevice.DebugPortDeviceHandle
456                     );
457 
458     if (EFI_ERROR (Status)) {
459       return Status;
460     }
461     //
462     // Unpublish our protocols (DevicePath, DebugPort)
463     //
464     Status = gBS->UninstallMultipleProtocolInterfaces (
465                     mDebugPortDevice.DebugPortDeviceHandle,
466                     &gEfiDevicePathProtocolGuid,
467                     mDebugPortDevice.DebugPortDevicePath,
468                     &gEfiDebugPortProtocolGuid,
469                     &mDebugPortDevice.DebugPortInterface,
470                     NULL
471                     );
472 
473     if (EFI_ERROR (Status)) {
474       gBS->OpenProtocol (
475             ControllerHandle,
476             &gEfiSerialIoProtocolGuid,
477             (VOID **) &mDebugPortDevice.SerialIoBinding,
478             This->DriverBindingHandle,
479             mDebugPortDevice.DebugPortDeviceHandle,
480             EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
481             );
482     } else {
483       mDebugPortDevice.DebugPortDeviceHandle = NULL;
484     }
485   }
486 
487   return Status;
488 }
489 
490 /**
491   DebugPort protocol member function.  Calls SerialIo:GetControl to flush buffer.
492   We cannot call SerialIo:SetAttributes because it uses pool services, which use
493   locks, which affect TPL, so it's not interrupt context safe or re-entrant.
494   SerialIo:Reset() calls SetAttributes, so it can't be used either.
495 
496   The port itself should be fine since it was set up during initialization.
497 
498   @param  This              Protocol instance pointer.
499 
500   @return EFI_SUCCESS       Always.
501 
502 **/
503 EFI_STATUS
504 EFIAPI
DebugPortReset(IN EFI_DEBUGPORT_PROTOCOL * This)505 DebugPortReset (
506   IN EFI_DEBUGPORT_PROTOCOL   *This
507   )
508 {
509   UINTN             BufferSize;
510   UINTN             BitBucket;
511 
512   while (This->Poll (This) == EFI_SUCCESS) {
513     BufferSize = 1;
514     This->Read (This, 0, &BufferSize, &BitBucket);
515   }
516 
517   return EFI_SUCCESS;
518 }
519 
520 /**
521   DebugPort protocol member function.  Calls SerialIo:Read() after setting
522   if it's different than the last SerialIo access.
523 
524   @param  This                Pointer to DebugPort protocol.
525   @param  Timeout             Timeout value.
526   @param  BufferSize          On input, the size of Buffer.
527                               On output, the amount of data actually written.
528   @param  Buffer              Pointer to buffer to read.
529 
530   @retval EFI_SUCCESS
531   @retval others
532 
533 **/
534 EFI_STATUS
535 EFIAPI
DebugPortRead(IN EFI_DEBUGPORT_PROTOCOL * This,IN UINT32 Timeout,IN OUT UINTN * BufferSize,IN VOID * Buffer)536 DebugPortRead (
537   IN EFI_DEBUGPORT_PROTOCOL   *This,
538   IN UINT32                   Timeout,
539   IN OUT UINTN                *BufferSize,
540   IN VOID                     *Buffer
541   )
542 {
543   DEBUGPORT_DEVICE  *DebugPortDevice;
544   UINTN             LocalBufferSize;
545   EFI_STATUS        Status;
546   UINT8             *BufferPtr;
547 
548   DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This);
549   BufferPtr       = Buffer;
550   LocalBufferSize = *BufferSize;
551 
552   do {
553     Status = DebugPortDevice->SerialIoBinding->Read (
554                                                 DebugPortDevice->SerialIoBinding,
555                                                 &LocalBufferSize,
556                                                 BufferPtr
557                                                 );
558     if (Status == EFI_TIMEOUT) {
559       if (Timeout > DEBUGPORT_UART_DEFAULT_TIMEOUT) {
560         Timeout -= DEBUGPORT_UART_DEFAULT_TIMEOUT;
561       } else {
562         Timeout = 0;
563       }
564     } else if (EFI_ERROR (Status)) {
565       break;
566     }
567 
568     BufferPtr += LocalBufferSize;
569     LocalBufferSize = *BufferSize - (BufferPtr - (UINT8 *) Buffer);
570   } while (LocalBufferSize != 0 && Timeout > 0);
571 
572   *BufferSize = (UINTN) (BufferPtr - (UINT8 *) Buffer);
573 
574   return Status;
575 }
576 
577 /**
578   DebugPort protocol member function.  Calls SerialIo:Write() Writes 8 bytes at
579   a time and does a GetControl between 8 byte writes to help insure reads are
580   interspersed This is poor-man's flow control.
581 
582   @param  This                Pointer to DebugPort protocol.
583   @param  Timeout             Timeout value.
584   @param  BufferSize          On input, the size of Buffer.
585                               On output, the amount of data actually written.
586   @param  Buffer              Pointer to buffer to read.
587 
588   @retval EFI_SUCCESS         The data was written.
589   @retval others              Fails when writting datas to debug port device.
590 
591 **/
592 EFI_STATUS
593 EFIAPI
DebugPortWrite(IN EFI_DEBUGPORT_PROTOCOL * This,IN UINT32 Timeout,IN OUT UINTN * BufferSize,OUT VOID * Buffer)594 DebugPortWrite (
595   IN EFI_DEBUGPORT_PROTOCOL   *This,
596   IN UINT32                   Timeout,
597   IN OUT UINTN                *BufferSize,
598   OUT VOID                    *Buffer
599   )
600 {
601   DEBUGPORT_DEVICE  *DebugPortDevice;
602   UINTN             Position;
603   UINTN             WriteSize;
604   EFI_STATUS        Status;
605   UINT32            SerialControl;
606 
607   Status          = EFI_SUCCESS;
608   DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This);
609 
610   WriteSize       = 8;
611   for (Position = 0; Position < *BufferSize && !EFI_ERROR (Status); Position += WriteSize) {
612     DebugPortDevice->SerialIoBinding->GetControl (
613                                         DebugPortDevice->SerialIoBinding,
614                                         &SerialControl
615                                         );
616     if (*BufferSize - Position < 8) {
617       WriteSize = *BufferSize - Position;
618     }
619 
620     Status = DebugPortDevice->SerialIoBinding->Write (
621                                                 DebugPortDevice->SerialIoBinding,
622                                                 &WriteSize,
623                                                 &((UINT8 *) Buffer)[Position]
624                                                 );
625   }
626 
627   *BufferSize = Position;
628   return Status;
629 }
630 
631 /**
632   DebugPort protocol member function.  Calls SerialIo:Write() after setting
633   if it's different than the last SerialIo access.
634 
635   @param  This                Pointer to DebugPort protocol.
636 
637   @retval EFI_SUCCESS         At least 1 character is ready to be read from
638                               the DebugPort interface.
639   @retval EFI_NOT_READY       There are no characters ready to read from the
640                               DebugPort interface
641   @retval EFI_DEVICE_ERROR    A hardware failure occured... (from SerialIo)
642 
643 **/
644 EFI_STATUS
645 EFIAPI
DebugPortPoll(IN EFI_DEBUGPORT_PROTOCOL * This)646 DebugPortPoll (
647   IN EFI_DEBUGPORT_PROTOCOL   *This
648   )
649 {
650   EFI_STATUS        Status;
651   UINT32            SerialControl;
652   DEBUGPORT_DEVICE  *DebugPortDevice;
653 
654   DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This);
655 
656   Status = DebugPortDevice->SerialIoBinding->GetControl (
657                                               DebugPortDevice->SerialIoBinding,
658                                               &SerialControl
659                                               );
660 
661   if (!EFI_ERROR (Status)) {
662     if ((SerialControl & EFI_SERIAL_INPUT_BUFFER_EMPTY) != 0) {
663       Status = EFI_NOT_READY;
664     } else {
665       Status = EFI_SUCCESS;
666     }
667   }
668 
669   return Status;
670 }
671 
672 /**
673   Unload function that is registered in the LoadImage protocol.  It un-installs
674   protocols produced and deallocates pool used by the driver.  Called by the core
675   when unloading the driver.
676 
677   @param  ImageHandle
678 
679   @retval EFI_SUCCESS     Unload Debug Port driver successfully.
680   @retval EFI_ABORTED     Serial IO is still binding.
681 
682 **/
683 EFI_STATUS
684 EFIAPI
ImageUnloadHandler(EFI_HANDLE ImageHandle)685 ImageUnloadHandler (
686   EFI_HANDLE ImageHandle
687   )
688 {
689   EFI_STATUS  Status;
690   VOID        *ComponentName;
691   VOID        *ComponentName2;
692 
693   if (mDebugPortDevice.SerialIoBinding != NULL) {
694     return EFI_ABORTED;
695   }
696 
697   //
698   // Driver is stopped already.
699   //
700   Status = gBS->HandleProtocol (ImageHandle, &gEfiComponentNameProtocolGuid, &ComponentName);
701   if (EFI_ERROR (Status)) {
702     ComponentName = NULL;
703   }
704 
705   Status = gBS->HandleProtocol (ImageHandle, &gEfiComponentName2ProtocolGuid, &ComponentName2);
706   if (EFI_ERROR (Status)) {
707     ComponentName2 = NULL;
708   }
709 
710   if (ComponentName == NULL) {
711     if (ComponentName2 == NULL) {
712       Status = gBS->UninstallMultipleProtocolInterfaces (
713                       ImageHandle,
714                       &gEfiDriverBindingProtocolGuid,  &gDebugPortDriverBinding,
715                       NULL
716                       );
717     } else {
718       Status = gBS->UninstallMultipleProtocolInterfaces (
719                       ImageHandle,
720                       &gEfiDriverBindingProtocolGuid,  &gDebugPortDriverBinding,
721                       &gEfiComponentName2ProtocolGuid, ComponentName2,
722                       NULL
723                       );
724     }
725   } else {
726     if (ComponentName2 == NULL) {
727       Status = gBS->UninstallMultipleProtocolInterfaces (
728                       ImageHandle,
729                       &gEfiDriverBindingProtocolGuid,  &gDebugPortDriverBinding,
730                       &gEfiComponentNameProtocolGuid,  ComponentName,
731                       NULL
732                       );
733     } else {
734       Status = gBS->UninstallMultipleProtocolInterfaces (
735                       ImageHandle,
736                       &gEfiDriverBindingProtocolGuid,  &gDebugPortDriverBinding,
737                       &gEfiComponentNameProtocolGuid,  ComponentName,
738                       &gEfiComponentName2ProtocolGuid, ComponentName2,
739                       NULL
740                       );
741     }
742   }
743 
744   return Status;
745 }
746