]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/DebugPortDxe/DebugPort.c
Fix GCC build failure.
[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 - 2014, Intel Corporation. All rights reserved.<BR>\r
8This program and the accompanying materials\r
9are licensed and made available under the terms and conditions of the BSD License\r
10which accompanies this distribution. The full text of the license may be found at\r
11http://opensource.org/licenses/bsd-license.php\r
12\r
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
15\r
16**/\r
17\r
18#include "DebugPort.h"\r
19\r
20//\r
21// Globals\r
22//\r
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
31\r
32DEBUGPORT_DEVICE mDebugPortDevice = {\r
33 DEBUGPORT_DEVICE_SIGNATURE,\r
34 (EFI_HANDLE) 0,\r
35 (EFI_HANDLE) 0,\r
36 (EFI_DEVICE_PATH_PROTOCOL *) NULL,\r
37 {\r
38 DebugPortReset,\r
39 DebugPortWrite,\r
40 DebugPortRead,\r
41 DebugPortPoll\r
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
52\r
53/**\r
54 Local worker function to obtain device path information from DebugPort variable.\r
55\r
56 Records requested settings in DebugPort device structure.\r
57\r
58**/\r
59EFI_DEVICE_PATH_PROTOCOL *\r
60GetDebugPortVariable (\r
61 VOID\r
62 )\r
63{\r
64 UINTN DataSize;\r
65 EFI_DEVICE_PATH_PROTOCOL *DebugPortVariable;\r
66 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
67\r
68 GetVariable2 (EFI_DEBUGPORT_VARIABLE_NAME, &gEfiDebugPortVariableGuid, (VOID **) &DebugPortVariable, &DataSize);\r
69 if (DebugPortVariable == NULL) {\r
70 return NULL;\r
71 }\r
72\r
73 DevicePath = DebugPortVariable;\r
74 while (!IsDevicePathEnd (DevicePath) && !IS_UART_DEVICEPATH (DevicePath)) {\r
75 DevicePath = NextDevicePathNode (DevicePath);\r
76 }\r
77\r
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
105 }\r
106}\r
107\r
108/**\r
109 Debug Port Driver entry point.\r
110\r
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
114\r
115 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
116 @param[in] SystemTable A pointer to the EFI System Table.\r
117\r
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
121\r
122**/\r
123EFI_STATUS\r
124EFIAPI\r
125InitializeDebugPortDriver (\r
126 IN EFI_HANDLE ImageHandle,\r
127 IN EFI_SYSTEM_TABLE *SystemTable\r
128 )\r
129{\r
130 EFI_STATUS Status;\r
131\r
132 //\r
133 // Install driver model protocol(s).\r
134 //\r
135 Status = EfiLibInstallDriverBindingComponentName2 (\r
136 ImageHandle,\r
137 SystemTable,\r
138 &gDebugPortDriverBinding,\r
139 ImageHandle,\r
140 &gDebugPortComponentName,\r
141 &gDebugPortComponentName2\r
142 );\r
143 ASSERT_EFI_ERROR (Status);\r
144\r
145 return EFI_SUCCESS;\r
146}\r
147\r
148/**\r
149 Checks to see if there's not already a DebugPort interface somewhere.\r
150\r
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
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
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
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
162\r
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
167\r
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
176{\r
177 EFI_STATUS Status;\r
178 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
179 EFI_DEVICE_PATH_PROTOCOL *DebugPortVariable;\r
180 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
181 EFI_DEBUGPORT_PROTOCOL *DebugPortInterface;\r
182 EFI_HANDLE TempHandle;\r
183\r
184 //\r
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
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
194 DebugPortVariable = GetDebugPortVariable ();\r
195\r
196 if (DebugPortVariable != NULL) {\r
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
203 DevicePath = DebugPortVariable;\r
204 Status = gBS->LocateDevicePath (\r
205 &gEfiSerialIoProtocolGuid,\r
206 &DevicePath,\r
207 &TempHandle\r
208 );\r
209\r
210 if (Status == EFI_SUCCESS && TempHandle != ControllerHandle) {\r
211 Status = EFI_UNSUPPORTED;\r
212 }\r
213\r
214 if (Status == EFI_SUCCESS &&\r
215 (DevicePath->Type != MESSAGING_DEVICE_PATH ||\r
216 DevicePath->SubType != MSG_VENDOR_DP ||\r
217 *((UINT16 *) DevicePath->Length) != sizeof (DEBUGPORT_DEVICE_PATH))) {\r
218\r
219 Status = EFI_UNSUPPORTED;\r
220 }\r
221\r
222 if (Status == EFI_SUCCESS && !CompareGuid (&gEfiDebugPortDevicePathGuid, (GUID *) (DevicePath + 1))) {\r
223 Status = EFI_UNSUPPORTED;\r
224 }\r
225\r
226 FreePool (DebugPortVariable);\r
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
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
265 @retval others Some error occurs.\r
266\r
267**/\r
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
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
284 (VOID **) &mDebugPortDevice.SerialIoBinding,\r
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
293 mDebugPortDevice.SerialIoDeviceHandle = ControllerHandle;\r
294\r
295 //\r
296 // Initialize the Serial Io interface...\r
297 //\r
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
306 );\r
307 if (EFI_ERROR (Status)) {\r
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
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
333 mDebugPortDevice.SerialIoBinding->Reset (mDebugPortDevice.SerialIoBinding);\r
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
341 CopyGuid (&DebugPortDP.Guid, &gEfiDebugPortDevicePathGuid);\r
342\r
343 Dp1 = DevicePathFromHandle (ControllerHandle);\r
344 if (Dp1 == NULL) {\r
345 Dp1 = &EndDP;\r
346 SetDevicePathEndNode (Dp1);\r
347 }\r
348\r
349 mDebugPortDevice.DebugPortDevicePath = AppendDevicePathNode (Dp1, (EFI_DEVICE_PATH_PROTOCOL *) &DebugPortDP);\r
350 if (mDebugPortDevice.DebugPortDevicePath == NULL) {\r
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
357 &mDebugPortDevice.DebugPortDeviceHandle,\r
358 &gEfiDevicePathProtocolGuid,\r
359 mDebugPortDevice.DebugPortDevicePath,\r
360 &gEfiDebugPortProtocolGuid,\r
361 &mDebugPortDevice.DebugPortInterface,\r
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
380 (VOID **) &mDebugPortDevice.SerialIoBinding,\r
381 This->DriverBindingHandle,\r
382 mDebugPortDevice.DebugPortDeviceHandle,\r
383 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
384 );\r
385\r
386 if (EFI_ERROR (Status)) {\r
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
396 return EFI_SUCCESS;\r
397}\r
398\r
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
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
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
435 mDebugPortDevice.SerialIoBinding = NULL;\r
436\r
437 gBS->CloseProtocol (\r
438 ControllerHandle,\r
439 &gEfiDevicePathProtocolGuid,\r
440 This->DriverBindingHandle,\r
441 ControllerHandle\r
442 );\r
443\r
444 FreePool (mDebugPortDevice.DebugPortDevicePath);\r
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
452 mDebugPortDevice.SerialIoDeviceHandle,\r
453 &gEfiSerialIoProtocolGuid,\r
454 This->DriverBindingHandle,\r
455 mDebugPortDevice.DebugPortDeviceHandle\r
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
465 mDebugPortDevice.DebugPortDeviceHandle,\r
466 &gEfiDevicePathProtocolGuid,\r
467 mDebugPortDevice.DebugPortDevicePath,\r
468 &gEfiDebugPortProtocolGuid,\r
469 &mDebugPortDevice.DebugPortInterface,\r
470 NULL\r
471 );\r
472\r
473 if (EFI_ERROR (Status)) {\r
474 gBS->OpenProtocol (\r
475 ControllerHandle,\r
476 &gEfiSerialIoProtocolGuid,\r
477 (VOID **) &mDebugPortDevice.SerialIoBinding,\r
478 This->DriverBindingHandle,\r
479 mDebugPortDevice.DebugPortDeviceHandle,\r
480 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
481 );\r
482 } else {\r
483 mDebugPortDevice.DebugPortDeviceHandle = NULL;\r
484 }\r
485 }\r
486\r
487 return Status;\r
488}\r
489\r
490/**\r
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
495\r
496 The port itself should be fine since it was set up during initialization.\r
497\r
498 @param This Protocol instance pointer.\r
499\r
500 @return EFI_SUCCESS Always.\r
501\r
502**/\r
503EFI_STATUS\r
504EFIAPI\r
505DebugPortReset (\r
506 IN EFI_DEBUGPORT_PROTOCOL *This\r
507 )\r
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
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
530 @retval EFI_SUCCESS\r
531 @retval others\r
532\r
533**/\r
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
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
551\r
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
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
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
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
631/**\r
632 DebugPort protocol member function. Calls SerialIo:Write() after setting\r
633 if it's different than the last SerialIo access.\r
634\r
635 @param This Pointer to DebugPort protocol.\r
636\r
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
642\r
643**/\r
644EFI_STATUS\r
645EFIAPI\r
646DebugPortPoll (\r
647 IN EFI_DEBUGPORT_PROTOCOL *This\r
648 )\r
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
662 if ((SerialControl & EFI_SERIAL_INPUT_BUFFER_EMPTY) != 0) {\r
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
672/**\r
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
676\r
677 @param ImageHandle\r
678\r
679 @retval EFI_SUCCESS Unload Debug Port driver successfully.\r
680 @retval EFI_ABORTED Serial IO is still binding.\r
681\r
682**/\r
683EFI_STATUS\r
684EFIAPI\r
685ImageUnloadHandler (\r
686 EFI_HANDLE ImageHandle\r
687 )\r
688{\r
689 EFI_STATUS Status;\r
690 VOID *ComponentName;\r
691 VOID *ComponentName2;\r
692\r
693 if (mDebugPortDevice.SerialIoBinding != NULL) {\r
694 return EFI_ABORTED;\r
695 }\r
696\r
697 //\r
698 // Driver is stopped already.\r
699 //\r
700 Status = gBS->HandleProtocol (ImageHandle, &gEfiComponentNameProtocolGuid, &ComponentName);\r
701 if (EFI_ERROR (Status)) {\r
702 ComponentName = NULL;\r
703 }\r
704\r
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
745}\r