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