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