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