TianoCore EDK2 master
Loading...
Searching...
No Matches
DebugPort.c
Go to the documentation of this file.
1
12#include "DebugPort.h"
13
14//
15// Globals
16//
17EFI_DRIVER_BINDING_PROTOCOL gDebugPortDriverBinding = {
21 DEBUGPORT_DRIVER_VERSION,
22 NULL,
23 NULL
24};
25
26DEBUGPORT_DEVICE mDebugPortDevice = {
27 DEBUGPORT_DEVICE_SIGNATURE,
28 (EFI_HANDLE)0,
29 (EFI_HANDLE)0,
31 {
36 },
37 (EFI_HANDLE)0,
39 DEBUGPORT_UART_DEFAULT_BAUDRATE,
40 DEBUGPORT_UART_DEFAULT_FIFO_DEPTH,
42 (EFI_PARITY_TYPE)DEBUGPORT_UART_DEFAULT_PARITY,
43 DEBUGPORT_UART_DEFAULT_DATA_BITS,
44 (EFI_STOP_BITS_TYPE)DEBUGPORT_UART_DEFAULT_STOP_BITS
45};
46
55 VOID
56 )
57{
58 UINTN DataSize;
59 EFI_DEVICE_PATH_PROTOCOL *DebugPortVariable;
60 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
61
62 GetVariable2 (EFI_DEBUGPORT_VARIABLE_NAME, &gEfiDebugPortVariableGuid, (VOID **)&DebugPortVariable, &DataSize);
63 if (DebugPortVariable == NULL) {
64 return NULL;
65 }
66
67 DevicePath = DebugPortVariable;
68 while (!IsDevicePathEnd (DevicePath) && !IS_UART_DEVICEPATH (DevicePath)) {
69 DevicePath = NextDevicePathNode (DevicePath);
70 }
71
72 if (IsDevicePathEnd (DevicePath)) {
73 FreePool (DebugPortVariable);
74 return NULL;
75 } else {
76 CopyMem (
77 &mDebugPortDevice.BaudRate,
78 &((UART_DEVICE_PATH *)DevicePath)->BaudRate,
79 sizeof (((UART_DEVICE_PATH *)DevicePath)->BaudRate)
80 );
81 mDebugPortDevice.ReceiveFifoDepth = DEBUGPORT_UART_DEFAULT_FIFO_DEPTH;
82 mDebugPortDevice.Timeout = DEBUGPORT_UART_DEFAULT_TIMEOUT;
83 CopyMem (
84 &mDebugPortDevice.Parity,
85 &((UART_DEVICE_PATH *)DevicePath)->Parity,
86 sizeof (((UART_DEVICE_PATH *)DevicePath)->Parity)
87 );
88 CopyMem (
89 &mDebugPortDevice.DataBits,
90 &((UART_DEVICE_PATH *)DevicePath)->DataBits,
91 sizeof (((UART_DEVICE_PATH *)DevicePath)->DataBits)
92 );
93 CopyMem (
94 &mDebugPortDevice.StopBits,
95 &((UART_DEVICE_PATH *)DevicePath)->StopBits,
96 sizeof (((UART_DEVICE_PATH *)DevicePath)->StopBits)
97 );
98 return DebugPortVariable;
99 }
100}
101
118EFIAPI
120 IN EFI_HANDLE ImageHandle,
121 IN EFI_SYSTEM_TABLE *SystemTable
122 )
123{
124 EFI_STATUS Status;
125
126 //
127 // Install driver model protocol(s).
128 //
130 ImageHandle,
131 SystemTable,
132 &gDebugPortDriverBinding,
133 ImageHandle,
134 &gDebugPortComponentName,
135 &gDebugPortComponentName2
136 );
137 ASSERT_EFI_ERROR (Status);
138
139 return Status;
140}
141
164EFIAPI
167 IN EFI_HANDLE ControllerHandle,
168 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
169 )
170{
171 EFI_STATUS Status;
172 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
173 EFI_DEVICE_PATH_PROTOCOL *DebugPortVariable;
174 EFI_SERIAL_IO_PROTOCOL *SerialIo;
175 EFI_DEBUGPORT_PROTOCOL *DebugPortInterface;
176 EFI_HANDLE TempHandle;
177
178 //
179 // Check to see that there's not a debugport protocol already published,
180 // since only one standard UART serial port could be supported by this driver.
181 //
182 if (gBS->LocateProtocol (&gEfiDebugPortProtocolGuid, NULL, (VOID **)&DebugPortInterface) != EFI_NOT_FOUND) {
183 return EFI_UNSUPPORTED;
184 }
185
186 //
187 // Read DebugPort variable to determine debug port selection and parameters
188 //
189 DebugPortVariable = GetDebugPortVariable ();
190
191 if (DebugPortVariable != NULL) {
192 //
193 // There's a DEBUGPORT variable, so do LocateDevicePath and check to see if
194 // the closest matching handle matches the controller handle, and if it does,
195 // check to see that the remaining device path has the DebugPort GUIDed messaging
196 // device path only. Otherwise, it's a mismatch and EFI_UNSUPPORTED is returned.
197 //
198 DevicePath = DebugPortVariable;
199 Status = gBS->LocateDevicePath (
200 &gEfiSerialIoProtocolGuid,
201 &DevicePath,
202 &TempHandle
203 );
204
205 if ((Status == EFI_SUCCESS) && (TempHandle != ControllerHandle)) {
206 Status = EFI_UNSUPPORTED;
207 }
208
209 if ((Status == EFI_SUCCESS) &&
210 ((DevicePath->Type != MESSAGING_DEVICE_PATH) ||
211 (DevicePath->SubType != MSG_VENDOR_DP) ||
212 (*((UINT16 *)DevicePath->Length) != sizeof (DEBUGPORT_DEVICE_PATH))))
213 {
214 Status = EFI_UNSUPPORTED;
215 }
216
217 if ((Status == EFI_SUCCESS) && !CompareGuid (&gEfiDebugPortDevicePathGuid, (GUID *)(DevicePath + 1))) {
218 Status = EFI_UNSUPPORTED;
219 }
220
221 FreePool (DebugPortVariable);
222 if (EFI_ERROR (Status)) {
223 return Status;
224 }
225 }
226
227 Status = gBS->OpenProtocol (
228 ControllerHandle,
229 &gEfiSerialIoProtocolGuid,
230 (VOID **)&SerialIo,
231 This->DriverBindingHandle,
232 ControllerHandle,
233 EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE
234 );
235 if (EFI_ERROR (Status)) {
236 return Status;
237 }
238
239 Status = gBS->CloseProtocol (
240 ControllerHandle,
241 &gEfiSerialIoProtocolGuid,
242 This->DriverBindingHandle,
243 ControllerHandle
244 );
245
246 return Status;
247}
248
264EFIAPI
267 IN EFI_HANDLE ControllerHandle,
268 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
269 )
270{
271 EFI_STATUS Status;
272 DEBUGPORT_DEVICE_PATH DebugPortDP;
275
276 Status = gBS->OpenProtocol (
277 ControllerHandle,
278 &gEfiSerialIoProtocolGuid,
279 (VOID **)&mDebugPortDevice.SerialIoBinding,
280 This->DriverBindingHandle,
281 ControllerHandle,
282 EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE
283 );
284 if (EFI_ERROR (Status)) {
285 return Status;
286 }
287
288 mDebugPortDevice.SerialIoDeviceHandle = ControllerHandle;
289
290 //
291 // Initialize the Serial Io interface...
292 //
293 Status = mDebugPortDevice.SerialIoBinding->SetAttributes (
294 mDebugPortDevice.SerialIoBinding,
295 mDebugPortDevice.BaudRate,
296 mDebugPortDevice.ReceiveFifoDepth,
297 mDebugPortDevice.Timeout,
298 mDebugPortDevice.Parity,
299 mDebugPortDevice.DataBits,
300 mDebugPortDevice.StopBits
301 );
302 if (EFI_ERROR (Status)) {
303 mDebugPortDevice.BaudRate = 0;
304 mDebugPortDevice.Parity = DefaultParity;
305 mDebugPortDevice.DataBits = 0;
306 mDebugPortDevice.StopBits = DefaultStopBits;
307 mDebugPortDevice.ReceiveFifoDepth = 0;
308 Status = mDebugPortDevice.SerialIoBinding->SetAttributes (
309 mDebugPortDevice.SerialIoBinding,
310 mDebugPortDevice.BaudRate,
311 mDebugPortDevice.ReceiveFifoDepth,
312 mDebugPortDevice.Timeout,
313 mDebugPortDevice.Parity,
314 mDebugPortDevice.DataBits,
315 mDebugPortDevice.StopBits
316 );
317 if (EFI_ERROR (Status)) {
318 gBS->CloseProtocol (
319 ControllerHandle,
320 &gEfiSerialIoProtocolGuid,
321 This->DriverBindingHandle,
322 ControllerHandle
323 );
324 return Status;
325 }
326 }
327
328 mDebugPortDevice.SerialIoBinding->Reset (mDebugPortDevice.SerialIoBinding);
329
330 //
331 // Create device path instance for DebugPort
332 //
333 DebugPortDP.Header.Type = MESSAGING_DEVICE_PATH;
334 DebugPortDP.Header.SubType = MSG_VENDOR_DP;
335 SetDevicePathNodeLength (&(DebugPortDP.Header), sizeof (DebugPortDP));
336 CopyGuid (&DebugPortDP.Guid, &gEfiDebugPortDevicePathGuid);
337
338 Dp1 = DevicePathFromHandle (ControllerHandle);
339 if (Dp1 == NULL) {
340 Dp1 = &EndDP;
342 }
343
344 mDebugPortDevice.DebugPortDevicePath = AppendDevicePathNode (Dp1, (EFI_DEVICE_PATH_PROTOCOL *)&DebugPortDP);
345 if (mDebugPortDevice.DebugPortDevicePath == NULL) {
346 return EFI_OUT_OF_RESOURCES;
347 }
348
349 //
350 // Publish DebugPort and Device Path protocols
351 //
352 Status = gBS->InstallMultipleProtocolInterfaces (
353 &mDebugPortDevice.DebugPortDeviceHandle,
354 &gEfiDevicePathProtocolGuid,
355 mDebugPortDevice.DebugPortDevicePath,
356 &gEfiDebugPortProtocolGuid,
357 &mDebugPortDevice.DebugPortInterface,
358 NULL
359 );
360
361 if (EFI_ERROR (Status)) {
362 gBS->CloseProtocol (
363 ControllerHandle,
364 &gEfiSerialIoProtocolGuid,
365 This->DriverBindingHandle,
366 ControllerHandle
367 );
368 return Status;
369 }
370
371 //
372 // Connect debugport child to serial io
373 //
374 Status = gBS->OpenProtocol (
375 ControllerHandle,
376 &gEfiSerialIoProtocolGuid,
377 (VOID **)&mDebugPortDevice.SerialIoBinding,
378 This->DriverBindingHandle,
379 mDebugPortDevice.DebugPortDeviceHandle,
380 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
381 );
382
383 if (EFI_ERROR (Status)) {
384 gBS->CloseProtocol (
385 ControllerHandle,
386 &gEfiSerialIoProtocolGuid,
387 This->DriverBindingHandle,
388 ControllerHandle
389 );
390 return Status;
391 }
392
393 return EFI_SUCCESS;
394}
395
411EFIAPI
414 IN EFI_HANDLE ControllerHandle,
415 IN UINTN NumberOfChildren,
416 IN EFI_HANDLE *ChildHandleBuffer
417 )
418{
419 EFI_STATUS Status;
420
421 if (NumberOfChildren == 0) {
422 //
423 // Close the bus driver
424 //
425 gBS->CloseProtocol (
426 ControllerHandle,
427 &gEfiSerialIoProtocolGuid,
428 This->DriverBindingHandle,
429 ControllerHandle
430 );
431
432 mDebugPortDevice.SerialIoBinding = NULL;
433
434 gBS->CloseProtocol (
435 ControllerHandle,
436 &gEfiDevicePathProtocolGuid,
437 This->DriverBindingHandle,
438 ControllerHandle
439 );
440
441 FreePool (mDebugPortDevice.DebugPortDevicePath);
442
443 return EFI_SUCCESS;
444 } else {
445 //
446 // Disconnect SerialIo child handle
447 //
448 Status = gBS->CloseProtocol (
449 mDebugPortDevice.SerialIoDeviceHandle,
450 &gEfiSerialIoProtocolGuid,
451 This->DriverBindingHandle,
452 mDebugPortDevice.DebugPortDeviceHandle
453 );
454
455 if (EFI_ERROR (Status)) {
456 return Status;
457 }
458
459 //
460 // Unpublish our protocols (DevicePath, DebugPort)
461 //
462 Status = gBS->UninstallMultipleProtocolInterfaces (
463 mDebugPortDevice.DebugPortDeviceHandle,
464 &gEfiDevicePathProtocolGuid,
465 mDebugPortDevice.DebugPortDevicePath,
466 &gEfiDebugPortProtocolGuid,
467 &mDebugPortDevice.DebugPortInterface,
468 NULL
469 );
470
471 if (EFI_ERROR (Status)) {
472 gBS->OpenProtocol (
473 ControllerHandle,
474 &gEfiSerialIoProtocolGuid,
475 (VOID **)&mDebugPortDevice.SerialIoBinding,
476 This->DriverBindingHandle,
477 mDebugPortDevice.DebugPortDeviceHandle,
478 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
479 );
480 } else {
481 mDebugPortDevice.DebugPortDeviceHandle = NULL;
482 }
483 }
484
485 return Status;
486}
487
502EFIAPI
505 )
506{
507 UINTN BufferSize;
508 UINTN BitBucket;
509
510 while (This->Poll (This) == EFI_SUCCESS) {
511 BufferSize = 1;
512 This->Read (This, 0, &BufferSize, &BitBucket);
513 }
514
515 return EFI_SUCCESS;
516}
517
533EFIAPI
536 IN UINT32 Timeout,
537 IN OUT UINTN *BufferSize,
538 IN VOID *Buffer
539 )
540{
541 DEBUGPORT_DEVICE *DebugPortDevice;
542 UINTN LocalBufferSize;
543 EFI_STATUS Status;
544 UINT8 *BufferPtr;
545
546 DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This);
547 BufferPtr = Buffer;
548 LocalBufferSize = *BufferSize;
549
550 do {
551 Status = DebugPortDevice->SerialIoBinding->Read (
552 DebugPortDevice->SerialIoBinding,
553 &LocalBufferSize,
554 BufferPtr
555 );
556 if (Status == EFI_TIMEOUT) {
557 if (Timeout > DEBUGPORT_UART_DEFAULT_TIMEOUT) {
559 } else {
560 Timeout = 0;
561 }
562 } else if (EFI_ERROR (Status)) {
563 break;
564 }
565
566 BufferPtr += LocalBufferSize;
567 LocalBufferSize = *BufferSize - (BufferPtr - (UINT8 *)Buffer);
568 } while (LocalBufferSize != 0 && Timeout > 0);
569
570 *BufferSize = (UINTN)BufferPtr - (UINTN)Buffer;
571
572 return Status;
573}
574
591EFIAPI
594 IN UINT32 Timeout,
595 IN OUT UINTN *BufferSize,
596 OUT VOID *Buffer
597 )
598{
599 DEBUGPORT_DEVICE *DebugPortDevice;
600 UINTN Position;
601 UINTN WriteSize;
602 EFI_STATUS Status;
603 UINT32 SerialControl;
604
605 Status = EFI_SUCCESS;
606 DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This);
607
608 WriteSize = 8;
609 for (Position = 0; Position < *BufferSize && !EFI_ERROR (Status); Position += WriteSize) {
610 DebugPortDevice->SerialIoBinding->GetControl (
611 DebugPortDevice->SerialIoBinding,
612 &SerialControl
613 );
614 if (*BufferSize - Position < 8) {
615 WriteSize = *BufferSize - Position;
616 }
617
618 Status = DebugPortDevice->SerialIoBinding->Write (
619 DebugPortDevice->SerialIoBinding,
620 &WriteSize,
621 &((UINT8 *)Buffer)[Position]
622 );
623 }
624
625 *BufferSize = Position;
626 return Status;
627}
628
643EFIAPI
646 )
647{
648 EFI_STATUS Status;
649 UINT32 SerialControl;
650 DEBUGPORT_DEVICE *DebugPortDevice;
651
652 DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This);
653
654 Status = DebugPortDevice->SerialIoBinding->GetControl (
655 DebugPortDevice->SerialIoBinding,
656 &SerialControl
657 );
658
659 if (!EFI_ERROR (Status)) {
660 if ((SerialControl & EFI_SERIAL_INPUT_BUFFER_EMPTY) != 0) {
661 Status = EFI_NOT_READY;
662 } else {
663 Status = EFI_SUCCESS;
664 }
665 }
666
667 return Status;
668}
669
682EFIAPI
684 EFI_HANDLE ImageHandle
685 )
686{
687 EFI_STATUS Status;
688 VOID *ComponentName;
689 VOID *ComponentName2;
690
691 if (mDebugPortDevice.SerialIoBinding != NULL) {
692 return EFI_ABORTED;
693 }
694
695 //
696 // Driver is stopped already.
697 //
698 Status = gBS->HandleProtocol (ImageHandle, &gEfiComponentNameProtocolGuid, &ComponentName);
699 if (EFI_ERROR (Status)) {
700 ComponentName = NULL;
701 }
702
703 Status = gBS->HandleProtocol (ImageHandle, &gEfiComponentName2ProtocolGuid, &ComponentName2);
704 if (EFI_ERROR (Status)) {
705 ComponentName2 = NULL;
706 }
707
708 if (ComponentName == NULL) {
709 if (ComponentName2 == NULL) {
710 Status = gBS->UninstallMultipleProtocolInterfaces (
711 ImageHandle,
712 &gEfiDriverBindingProtocolGuid,
713 &gDebugPortDriverBinding,
714 NULL
715 );
716 } else {
717 Status = gBS->UninstallMultipleProtocolInterfaces (
718 ImageHandle,
719 &gEfiDriverBindingProtocolGuid,
720 &gDebugPortDriverBinding,
721 &gEfiComponentName2ProtocolGuid,
722 ComponentName2,
723 NULL
724 );
725 }
726 } else {
727 if (ComponentName2 == NULL) {
728 Status = gBS->UninstallMultipleProtocolInterfaces (
729 ImageHandle,
730 &gEfiDriverBindingProtocolGuid,
731 &gDebugPortDriverBinding,
732 &gEfiComponentNameProtocolGuid,
733 ComponentName,
734 NULL
735 );
736 } else {
737 Status = gBS->UninstallMultipleProtocolInterfaces (
738 ImageHandle,
739 &gEfiDriverBindingProtocolGuid,
740 &gDebugPortDriverBinding,
741 &gEfiComponentNameProtocolGuid,
742 ComponentName,
743 &gEfiComponentName2ProtocolGuid,
744 ComponentName2,
745 NULL
746 );
747 }
748 }
749
750 return Status;
751}
UINT64 UINTN
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
Definition: MemLibGuid.c:39
EFI_STATUS EFIAPI DebugPortReset(IN EFI_DEBUGPORT_PROTOCOL *This)
Definition: DebugPort.c:503
EFI_STATUS EFIAPI DebugPortStart(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath)
Definition: DebugPort.c:265
EFI_STATUS EFIAPI DebugPortStop(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer)
Definition: DebugPort.c:412
EFI_STATUS EFIAPI DebugPortSupported(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath)
Definition: DebugPort.c:165
EFI_STATUS EFIAPI ImageUnloadHandler(EFI_HANDLE ImageHandle)
Definition: DebugPort.c:683
EFI_STATUS EFIAPI DebugPortPoll(IN EFI_DEBUGPORT_PROTOCOL *This)
Definition: DebugPort.c:644
EFI_STATUS EFIAPI DebugPortRead(IN EFI_DEBUGPORT_PROTOCOL *This, IN UINT32 Timeout, IN OUT UINTN *BufferSize, IN VOID *Buffer)
Definition: DebugPort.c:534
EFI_STATUS EFIAPI InitializeDebugPortDriver(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: DebugPort.c:119
EFI_STATUS EFIAPI DebugPortWrite(IN EFI_DEBUGPORT_PROTOCOL *This, IN UINT32 Timeout, IN OUT UINTN *BufferSize, OUT VOID *Buffer)
Definition: DebugPort.c:592
EFI_DEVICE_PATH_PROTOCOL * GetDebugPortVariable(VOID)
Definition: DebugPort.c:54
#define MESSAGING_DEVICE_PATH
Definition: DevicePath.h:321
UINT16 EFIAPI SetDevicePathNodeLength(IN OUT VOID *Node, IN UINTN Length)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI AppendDevicePathNode(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL, IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL)
BOOLEAN EFIAPI IsDevicePathEnd(IN CONST VOID *Node)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI NextDevicePathNode(IN CONST VOID *Node)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI DevicePathFromHandle(IN EFI_HANDLE Handle)
VOID EFIAPI SetDevicePathEndNode(OUT VOID *Node)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define DEBUGPORT_UART_DEFAULT_TIMEOUT
5 ms
Definition: DebugPort.h:70
#define NULL
Definition: Base.h:319
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
EFI_STOP_BITS_TYPE
Definition: SerialIo.h:53
EFI_PARITY_TYPE
Definition: SerialIo.h:41
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI GetVariable2(IN CONST CHAR16 *Name, IN CONST EFI_GUID *Guid, OUT VOID **Value, OUT UINTN *Size OPTIONAL)
Definition: UefiLib.c:1317
EFI_STATUS EFIAPI EfiLibInstallDriverBindingComponentName2(IN CONST EFI_HANDLE ImageHandle, IN CONST EFI_SYSTEM_TABLE *SystemTable, IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, IN EFI_HANDLE DriverBindingHandle, IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName OPTIONAL, IN CONST EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2 OPTIONAL)
Definition: Base.h:213