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