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