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