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