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