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