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