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