]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/DebugPortDxe/DebugPort.c
MdeModulePkg: Fix spelling mistake for occurred
[mirror_edk2.git] / MdeModulePkg / Universal / DebugPortDxe / DebugPort.c
... / ...
CommitLineData
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
6\r
7Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
8SPDX-License-Identifier: BSD-2-Clause-Patent\r
9\r
10**/\r
11\r
12#include "DebugPort.h"\r
13\r
14//\r
15// Globals\r
16//\r
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
25\r
26DEBUGPORT_DEVICE mDebugPortDevice = {\r
27 DEBUGPORT_DEVICE_SIGNATURE,\r
28 (EFI_HANDLE) 0,\r
29 (EFI_HANDLE) 0,\r
30 (EFI_DEVICE_PATH_PROTOCOL *) NULL,\r
31 {\r
32 DebugPortReset,\r
33 DebugPortWrite,\r
34 DebugPortRead,\r
35 DebugPortPoll\r
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
46\r
47/**\r
48 Local worker function to obtain device path information from DebugPort variable.\r
49\r
50 Records requested settings in DebugPort device structure.\r
51\r
52**/\r
53EFI_DEVICE_PATH_PROTOCOL *\r
54GetDebugPortVariable (\r
55 VOID\r
56 )\r
57{\r
58 UINTN DataSize;\r
59 EFI_DEVICE_PATH_PROTOCOL *DebugPortVariable;\r
60 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
61\r
62 GetVariable2 (EFI_DEBUGPORT_VARIABLE_NAME, &gEfiDebugPortVariableGuid, (VOID **) &DebugPortVariable, &DataSize);\r
63 if (DebugPortVariable == NULL) {\r
64 return NULL;\r
65 }\r
66\r
67 DevicePath = DebugPortVariable;\r
68 while (!IsDevicePathEnd (DevicePath) && !IS_UART_DEVICEPATH (DevicePath)) {\r
69 DevicePath = NextDevicePathNode (DevicePath);\r
70 }\r
71\r
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
99 }\r
100}\r
101\r
102/**\r
103 Debug Port Driver entry point.\r
104\r
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
108\r
109 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
110 @param[in] SystemTable A pointer to the EFI System Table.\r
111\r
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
115\r
116**/\r
117EFI_STATUS\r
118EFIAPI\r
119InitializeDebugPortDriver (\r
120 IN EFI_HANDLE ImageHandle,\r
121 IN EFI_SYSTEM_TABLE *SystemTable\r
122 )\r
123{\r
124 EFI_STATUS Status;\r
125\r
126 //\r
127 // Install driver model protocol(s).\r
128 //\r
129 Status = EfiLibInstallDriverBindingComponentName2 (\r
130 ImageHandle,\r
131 SystemTable,\r
132 &gDebugPortDriverBinding,\r
133 ImageHandle,\r
134 &gDebugPortComponentName,\r
135 &gDebugPortComponentName2\r
136 );\r
137 ASSERT_EFI_ERROR (Status);\r
138\r
139 return Status;\r
140}\r
141\r
142/**\r
143 Checks to see if there's not already a DebugPort interface somewhere.\r
144\r
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
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
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
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
156\r
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
161\r
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
170{\r
171 EFI_STATUS Status;\r
172 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
173 EFI_DEVICE_PATH_PROTOCOL *DebugPortVariable;\r
174 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
175 EFI_DEBUGPORT_PROTOCOL *DebugPortInterface;\r
176 EFI_HANDLE TempHandle;\r
177\r
178 //\r
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
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
188 DebugPortVariable = GetDebugPortVariable ();\r
189\r
190 if (DebugPortVariable != NULL) {\r
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
197 DevicePath = DebugPortVariable;\r
198 Status = gBS->LocateDevicePath (\r
199 &gEfiSerialIoProtocolGuid,\r
200 &DevicePath,\r
201 &TempHandle\r
202 );\r
203\r
204 if (Status == EFI_SUCCESS && TempHandle != ControllerHandle) {\r
205 Status = EFI_UNSUPPORTED;\r
206 }\r
207\r
208 if (Status == EFI_SUCCESS &&\r
209 (DevicePath->Type != MESSAGING_DEVICE_PATH ||\r
210 DevicePath->SubType != MSG_VENDOR_DP ||\r
211 *((UINT16 *) DevicePath->Length) != sizeof (DEBUGPORT_DEVICE_PATH))) {\r
212\r
213 Status = EFI_UNSUPPORTED;\r
214 }\r
215\r
216 if (Status == EFI_SUCCESS && !CompareGuid (&gEfiDebugPortDevicePathGuid, (GUID *) (DevicePath + 1))) {\r
217 Status = EFI_UNSUPPORTED;\r
218 }\r
219\r
220 FreePool (DebugPortVariable);\r
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
238 Status = gBS->CloseProtocol (\r
239 ControllerHandle,\r
240 &gEfiSerialIoProtocolGuid,\r
241 This->DriverBindingHandle,\r
242 ControllerHandle\r
243 );\r
244\r
245 return Status;\r
246}\r
247\r
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
259 @retval others Some error occurs.\r
260\r
261**/\r
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
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
278 (VOID **) &mDebugPortDevice.SerialIoBinding,\r
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
287 mDebugPortDevice.SerialIoDeviceHandle = ControllerHandle;\r
288\r
289 //\r
290 // Initialize the Serial Io interface...\r
291 //\r
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
300 );\r
301 if (EFI_ERROR (Status)) {\r
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
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
327 mDebugPortDevice.SerialIoBinding->Reset (mDebugPortDevice.SerialIoBinding);\r
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
335 CopyGuid (&DebugPortDP.Guid, &gEfiDebugPortDevicePathGuid);\r
336\r
337 Dp1 = DevicePathFromHandle (ControllerHandle);\r
338 if (Dp1 == NULL) {\r
339 Dp1 = &EndDP;\r
340 SetDevicePathEndNode (Dp1);\r
341 }\r
342\r
343 mDebugPortDevice.DebugPortDevicePath = AppendDevicePathNode (Dp1, (EFI_DEVICE_PATH_PROTOCOL *) &DebugPortDP);\r
344 if (mDebugPortDevice.DebugPortDevicePath == NULL) {\r
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
351 &mDebugPortDevice.DebugPortDeviceHandle,\r
352 &gEfiDevicePathProtocolGuid,\r
353 mDebugPortDevice.DebugPortDevicePath,\r
354 &gEfiDebugPortProtocolGuid,\r
355 &mDebugPortDevice.DebugPortInterface,\r
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
374 (VOID **) &mDebugPortDevice.SerialIoBinding,\r
375 This->DriverBindingHandle,\r
376 mDebugPortDevice.DebugPortDeviceHandle,\r
377 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
378 );\r
379\r
380 if (EFI_ERROR (Status)) {\r
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
390 return EFI_SUCCESS;\r
391}\r
392\r
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
407EFI_STATUS\r
408EFIAPI\r
409DebugPortStop (\r
410 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
411 IN EFI_HANDLE ControllerHandle,\r
412 IN UINTN NumberOfChildren,\r
413 IN EFI_HANDLE *ChildHandleBuffer\r
414 )\r
415{\r
416 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
429 mDebugPortDevice.SerialIoBinding = NULL;\r
430\r
431 gBS->CloseProtocol (\r
432 ControllerHandle,\r
433 &gEfiDevicePathProtocolGuid,\r
434 This->DriverBindingHandle,\r
435 ControllerHandle\r
436 );\r
437\r
438 FreePool (mDebugPortDevice.DebugPortDevicePath);\r
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
446 mDebugPortDevice.SerialIoDeviceHandle,\r
447 &gEfiSerialIoProtocolGuid,\r
448 This->DriverBindingHandle,\r
449 mDebugPortDevice.DebugPortDeviceHandle\r
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
459 mDebugPortDevice.DebugPortDeviceHandle,\r
460 &gEfiDevicePathProtocolGuid,\r
461 mDebugPortDevice.DebugPortDevicePath,\r
462 &gEfiDebugPortProtocolGuid,\r
463 &mDebugPortDevice.DebugPortInterface,\r
464 NULL\r
465 );\r
466\r
467 if (EFI_ERROR (Status)) {\r
468 gBS->OpenProtocol (\r
469 ControllerHandle,\r
470 &gEfiSerialIoProtocolGuid,\r
471 (VOID **) &mDebugPortDevice.SerialIoBinding,\r
472 This->DriverBindingHandle,\r
473 mDebugPortDevice.DebugPortDeviceHandle,\r
474 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
475 );\r
476 } else {\r
477 mDebugPortDevice.DebugPortDeviceHandle = NULL;\r
478 }\r
479 }\r
480\r
481 return Status;\r
482}\r
483\r
484/**\r
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
489\r
490 The port itself should be fine since it was set up during initialization.\r
491\r
492 @param This Protocol instance pointer.\r
493\r
494 @return EFI_SUCCESS Always.\r
495\r
496**/\r
497EFI_STATUS\r
498EFIAPI\r
499DebugPortReset (\r
500 IN EFI_DEBUGPORT_PROTOCOL *This\r
501 )\r
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
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
524 @retval EFI_SUCCESS\r
525 @retval others\r
526\r
527**/\r
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
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
545\r
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
566 *BufferSize = (UINTN) BufferPtr - (UINTN) Buffer;\r
567\r
568 return Status;\r
569}\r
570\r
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
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
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
625/**\r
626 DebugPort protocol member function. Calls SerialIo:Write() after setting\r
627 if it's different than the last SerialIo access.\r
628\r
629 @param This Pointer to DebugPort protocol.\r
630\r
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 occurred... (from SerialIo)\r
636\r
637**/\r
638EFI_STATUS\r
639EFIAPI\r
640DebugPortPoll (\r
641 IN EFI_DEBUGPORT_PROTOCOL *This\r
642 )\r
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
656 if ((SerialControl & EFI_SERIAL_INPUT_BUFFER_EMPTY) != 0) {\r
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
666/**\r
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
670\r
671 @param ImageHandle\r
672\r
673 @retval EFI_SUCCESS Unload Debug Port driver successfully.\r
674 @retval EFI_ABORTED Serial IO is still binding.\r
675\r
676**/\r
677EFI_STATUS\r
678EFIAPI\r
679ImageUnloadHandler (\r
680 EFI_HANDLE ImageHandle\r
681 )\r
682{\r
683 EFI_STATUS Status;\r
684 VOID *ComponentName;\r
685 VOID *ComponentName2;\r
686\r
687 if (mDebugPortDevice.SerialIoBinding != NULL) {\r
688 return EFI_ABORTED;\r
689 }\r
690\r
691 //\r
692 // Driver is stopped already.\r
693 //\r
694 Status = gBS->HandleProtocol (ImageHandle, &gEfiComponentNameProtocolGuid, &ComponentName);\r
695 if (EFI_ERROR (Status)) {\r
696 ComponentName = NULL;\r
697 }\r
698\r
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
739}\r