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