TianoCore EDK2 master
Loading...
Searching...
No Matches
FvSimpleFileSystemEntryPoint.c
Go to the documentation of this file.
1
22
23EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;
24
25//
26// A Guid string is 32 hex characters with 4 hyphens and a NULL-terminated char: 37 characters total
27//
28#define GUID_STRING_SIZE (37 * sizeof (CHAR16))
29
30#define FVFS_VOLUME_LABEL_PREFIX L"Firmware Volume: "
31#define FVFS_VOLUME_LABEL_SIZE (sizeof (FVFS_VOLUME_LABEL_PREFIX) + GUID_STRING_SIZE - sizeof (CHAR16))
32#define FVFS_FALLBACK_VOLUME_LABEL L"Firmware Volume"
33
34//
35// Template for EFI_SIMPLE_FILE_SYSTEM_PROTOCOL data structure.
36//
37EFI_SIMPLE_FILE_SYSTEM_PROTOCOL mSimpleFsTemplate = {
38 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,
40};
41
42//
43// Template for EFI_DRIVER_BINDING_PROTOCOL data structure.
44//
45EFI_DRIVER_BINDING_PROTOCOL mDriverBinding = {
49 0,
50 NULL,
51 NULL
52};
53
75EFIAPI
78 OUT EFI_FILE_PROTOCOL **RootFile
79 )
80{
81 EFI_STATUS Status;
83 CHAR16 *UiSection;
84 EFI_GUID NameGuid;
85 EFI_FV_FILE_ATTRIBUTES Attributes;
86 UINT32 Authentication;
87 UINTN Key;
88 EFI_FV_FILETYPE FileType;
89 UINTN Size;
90 FV_FILESYSTEM_INSTANCE *Instance;
91 FV_FILESYSTEM_FILE_INFO *FvFileInfo;
93 CHAR16 *Name;
94 UINTN NameLen;
95 UINTN NumChars;
96 UINTN DestMax;
97
98 Instance = FVFS_INSTANCE_FROM_SIMPLE_FS_THIS (This);
99 Status = EFI_SUCCESS;
100
101 if (Instance->Root == NULL) {
102 //
103 // Allocate file structure for root file
104 //
105 Root = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE));
106 if (Root == NULL) {
107 return EFI_OUT_OF_RESOURCES;
108 }
109
110 Instance->Root = Root;
111 Root->Instance = Instance;
112 Root->Signature = FVFS_FILE_SIGNATURE;
113 CopyMem (&Root->FileProtocol, &mFileSystemTemplate, sizeof (mFileSystemTemplate));
114 Root->FvFileInfo = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE_INFO));
115 if (Root->FvFileInfo == NULL) {
116 return EFI_OUT_OF_RESOURCES;
117 }
118
119 Root->FvFileInfo->FileInfo.Size = sizeof (EFI_FILE_INFO);
120 Root->FvFileInfo->FileInfo.Attribute = EFI_FILE_DIRECTORY | EFI_FILE_READ_ONLY;
121
122 //
123 // Populate the instance's list of files. We consider anything a file that
124 // has a UI_SECTION, which we consider to be its filename.
125 //
126 FvProtocol = Instance->FvProtocol;
127 //
128 // Allocate Key
129 //
130 Key = 0;
131
132 do {
133 FileType = EFI_FV_FILETYPE_ALL;
134
135 Status = FvProtocol->GetNextFile (
136 FvProtocol,
137 &Key,
138 &FileType,
139 &NameGuid,
140 &Attributes,
141 &Size
142 );
143 if (EFI_ERROR (Status)) {
144 ASSERT (Status == EFI_NOT_FOUND);
145 break;
146 }
147
148 //
149 // Get a file's name: If it has a UI section, use that, otherwise use
150 // its NameGuid.
151 //
152 UiSection = NULL;
153 Status = FvProtocol->ReadSection (
154 FvProtocol,
155 &NameGuid,
156 EFI_SECTION_USER_INTERFACE,
157 0,
158 (VOID **)&UiSection,
159 &Size,
160 &Authentication
161 );
162 if (!EFI_ERROR (Status)) {
163 Name = UiSection;
164 } else {
165 Name = AllocateZeroPool (GUID_STRING_SIZE);
166 if (Name == NULL) {
167 return EFI_OUT_OF_RESOURCES;
168 }
169
170 NumChars = UnicodeSPrint (Name, GUID_STRING_SIZE, L"%g", &NameGuid);
171 ASSERT ((NumChars + 1) * sizeof (CHAR16) == GUID_STRING_SIZE);
172 }
173
174 //
175 // Found a file.
176 // Allocate a file structure and populate it.
177 //
178 NameLen = StrSize (Name);
179 if (FV_FILETYPE_IS_EXECUTABLE (FileType)) {
180 NameLen += StrSize (L".efi") - sizeof (CHAR16);
181 }
182
183 FvFileInfo = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE_INFO) + NameLen - sizeof (CHAR16));
184 if (FvFileInfo == NULL) {
185 return EFI_OUT_OF_RESOURCES;
186 }
187
188 FvFileInfo->Signature = FVFS_FILE_INFO_SIGNATURE;
189 InitializeListHead (&FvFileInfo->Link);
190 CopyMem (&FvFileInfo->NameGuid, &NameGuid, sizeof (EFI_GUID));
191 FvFileInfo->Type = FileType;
192
193 //
194 // Add ".efi" to filenames of drivers and applications.
195 //
196 DestMax = NameLen / sizeof (CHAR16);
197 Status = StrnCpyS (&FvFileInfo->FileInfo.FileName[0], DestMax, Name, StrLen (Name));
198 ASSERT_EFI_ERROR (Status);
199
200 if (FV_FILETYPE_IS_EXECUTABLE (FileType)) {
201 Status = StrnCatS (&FvFileInfo->FileInfo.FileName[0], DestMax, L".efi", StrLen (L".efi"));
202 ASSERT_EFI_ERROR (Status);
203 }
204
205 FvFileInfo->FileInfo.Size = sizeof (EFI_FILE_INFO) + NameLen - sizeof (CHAR16);
206 Status = FvFsGetFileSize (FvProtocol, FvFileInfo);
207 ASSERT_EFI_ERROR (Status);
208 FvFileInfo->FileInfo.PhysicalSize = FvFileInfo->FileInfo.FileSize;
209 FvFileInfo->FileInfo.Attribute = EFI_FILE_READ_ONLY;
210
211 InsertHeadList (&Instance->FileInfoHead, &FvFileInfo->Link);
212
213 FreePool (Name);
214 } while (TRUE);
215
216 if (Status == EFI_NOT_FOUND) {
217 Status = EFI_SUCCESS;
218 }
219 }
220
221 Instance->Root->DirReadNext = NULL;
222 if (!IsListEmpty (&Instance->FileInfoHead)) {
223 Instance->Root->DirReadNext = FVFS_GET_FIRST_FILE_INFO (Instance);
224 }
225
226 *RootFile = &Instance->Root->FileProtocol;
227 return Status;
228}
229
247 IN EFI_HANDLE AgentHandle,
248 IN EFI_GUID *ProtocolGuid,
249 IN CONST CHAR16 *VariableName,
250 IN CONST CHAR8 *DefaultLanguage
251 )
252{
253 EFI_STATUS ReturnStatus;
254 EFI_STATUS Status;
255 UINTN NumHandles;
256 UINTN Index;
257 EFI_HANDLE *Handles;
259 BOOLEAN Iso639Language;
260 CHAR8 *Language;
261 CHAR8 *BestLanguage;
262
263 Status = gBS->LocateHandleBuffer (
265 ProtocolGuid,
266 NULL,
267 &NumHandles,
268 &Handles
269 );
270 if (EFI_ERROR (Status)) {
271 return Status;
272 }
273
274 Iso639Language = (BOOLEAN)(ProtocolGuid == &gEfiUnicodeCollationProtocolGuid);
275 GetEfiGlobalVariable2 (VariableName, (VOID **)&Language, NULL);
276
277 ReturnStatus = EFI_UNSUPPORTED;
278 for (Index = 0; Index < NumHandles; Index++) {
279 //
280 // Open Unicode Collation Protocol
281 //
282 Status = gBS->OpenProtocol (
283 Handles[Index],
284 ProtocolGuid,
285 (VOID **)&Uci,
286 AgentHandle,
287 NULL,
288 EFI_OPEN_PROTOCOL_GET_PROTOCOL
289 );
290 if (EFI_ERROR (Status)) {
291 continue;
292 }
293
294 //
295 // Find the best matching matching language from the supported languages
296 // of Unicode Collation (2) protocol.
297 //
298 BestLanguage = GetBestLanguage (
299 Uci->SupportedLanguages,
300 Iso639Language,
301 (Language == NULL) ? "" : Language,
302 DefaultLanguage,
303 NULL
304 );
305 if (BestLanguage != NULL) {
306 FreePool (BestLanguage);
307 mUnicodeCollation = Uci;
308 ReturnStatus = EFI_SUCCESS;
309 break;
310 }
311 }
312
313 if (Language != NULL) {
314 FreePool (Language);
315 }
316
317 FreePool (Handles);
318
319 return ReturnStatus;
320}
321
337 IN EFI_HANDLE AgentHandle
338 )
339{
340 EFI_STATUS Status;
341
342 Status = EFI_UNSUPPORTED;
343
344 //
345 // First try to use RFC 4646 Unicode Collation 2 Protocol.
346 //
348 AgentHandle,
349 &gEfiUnicodeCollation2ProtocolGuid,
350 L"PlatformLang",
351 (CONST CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLang)
352 );
353 //
354 // If the attempt to use Unicode Collation 2 Protocol fails, then we fall back
355 // on the ISO 639-2 Unicode Collation Protocol.
356 //
357 if (EFI_ERROR (Status)) {
359 AgentHandle,
360 &gEfiUnicodeCollationProtocolGuid,
361 L"Lang",
362 (CONST CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultLang)
363 );
364 }
365
366 return Status;
367}
368
383EFIAPI
385 IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,
386 IN EFI_HANDLE ControllerHandle,
387 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
388 )
389{
390 return gBS->OpenProtocol (
391 ControllerHandle,
392 &gEfiFirmwareVolume2ProtocolGuid,
393 NULL,
395 ControllerHandle,
396 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
397 );
398}
399
415EFIAPI
417 IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,
418 IN EFI_HANDLE ControllerHandle,
419 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
420 )
421{
422 EFI_STATUS Status;
424 FV_FILESYSTEM_INSTANCE *Instance;
425 EFI_DEVICE_PATH_PROTOCOL *FvDevicePath;
426 EFI_GUID *FvGuid;
427 UINTN NumChars;
428
429 Status = InitializeUnicodeCollationSupport (DriverBinding->DriverBindingHandle);
430 if (EFI_ERROR (Status)) {
431 return Status;
432 }
433
434 //
435 // Open FV protocol
436 //
437 Status = gBS->OpenProtocol (
438 ControllerHandle,
439 &gEfiFirmwareVolume2ProtocolGuid,
440 (VOID **)&FvProtocol,
442 ControllerHandle,
443 EFI_OPEN_PROTOCOL_BY_DRIVER
444 );
445 if (EFI_ERROR (Status)) {
446 return Status;
447 }
448
449 //
450 // Create an instance
451 //
452 Instance = AllocateZeroPool (sizeof (FV_FILESYSTEM_INSTANCE));
453 ASSERT (Instance != NULL);
454
455 Instance->Root = NULL;
456 Instance->FvProtocol = FvProtocol;
457 Instance->Signature = FVFS_INSTANCE_SIGNATURE;
458 InitializeListHead (&Instance->FileInfoHead);
459 InitializeListHead (&Instance->FileHead);
460 CopyMem (&Instance->SimpleFs, &mSimpleFsTemplate, sizeof (mSimpleFsTemplate));
461
462 Status = gBS->InstallProtocolInterface (
463 &ControllerHandle,
464 &gEfiSimpleFileSystemProtocolGuid,
466 &Instance->SimpleFs
467 );
468 ASSERT_EFI_ERROR (Status);
469
470 //
471 // Decide on a filesystem volume label, which will include the FV's guid.
472 // Get the device path to find the FV's GUID
473 //
474 Instance->VolumeLabel = NULL;
475 Status = gBS->OpenProtocol (
476 ControllerHandle,
477 &gEfiDevicePathProtocolGuid,
478 (VOID **)&FvDevicePath,
480 ControllerHandle,
481 EFI_OPEN_PROTOCOL_GET_PROTOCOL
482 );
483 if (!EFI_ERROR (Status)) {
484 //
485 // Iterate over device path until we find a firmware volume node
486 //
487 while (!IsDevicePathEndType (FvDevicePath)) {
488 if ((DevicePathType (FvDevicePath) == MEDIA_DEVICE_PATH) &&
489 (DevicePathSubType (FvDevicePath) == MEDIA_PIWG_FW_VOL_DP))
490 {
491 //
492 // Allocate the volume label
493 //
494 Instance->VolumeLabel = AllocateZeroPool (FVFS_VOLUME_LABEL_SIZE);
495 //
496 // Check the allocation was successful
497 //
498 if (Instance->VolumeLabel != NULL) {
499 //
500 // Extract the FV's guid
501 //
502 FvGuid = &((MEDIA_FW_VOL_DEVICE_PATH *)FvDevicePath)->FvName;
503 //
504 // Build the volume label string
505 //
506 NumChars = UnicodeSPrint (
507 Instance->VolumeLabel,
508 FVFS_VOLUME_LABEL_SIZE,
509 FVFS_VOLUME_LABEL_PREFIX L"%g",
510 FvGuid
511 );
512 ASSERT ((NumChars + 1) * sizeof (CHAR16) == FVFS_VOLUME_LABEL_SIZE);
513 }
514
515 break;
516 }
517
518 FvDevicePath = NextDevicePathNode (FvDevicePath);
519 }
520 }
521
522 //
523 // If we didn't decide on a volume label, set a fallback one
524 //
525 if (Instance->VolumeLabel == NULL) {
526 Instance->VolumeLabel = AllocateCopyPool (
527 sizeof (FVFS_FALLBACK_VOLUME_LABEL),
528 FVFS_FALLBACK_VOLUME_LABEL
529 );
530 }
531
532 return EFI_SUCCESS;
533}
534
550EFIAPI
552 IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,
553 IN EFI_HANDLE ControllerHandle,
554 IN UINTN NumberOfChildren,
555 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
556 )
557{
558 EFI_STATUS Status;
559 FV_FILESYSTEM_INSTANCE *Instance;
560 FV_FILESYSTEM_FILE_INFO *FvFileInfo;
561 LIST_ENTRY *Entry;
562 LIST_ENTRY *DelEntry;
564
565 Status = gBS->OpenProtocol (
566 ControllerHandle,
567 &gEfiSimpleFileSystemProtocolGuid,
568 (VOID **)&SimpleFile,
569 DriverBinding->DriverBindingHandle,
570 ControllerHandle,
571 EFI_OPEN_PROTOCOL_GET_PROTOCOL
572 );
573 if (EFI_ERROR (Status)) {
574 return Status;
575 }
576
577 Instance = FVFS_INSTANCE_FROM_SIMPLE_FS_THIS (SimpleFile);
578
579 if (IsListEmpty (&Instance->FileHead) == FALSE) {
580 //
581 // Not all opened files are closed
582 //
583 return EFI_DEVICE_ERROR;
584 }
585
586 //
587 // Close and uninstall protocols.
588 //
589 Status = gBS->CloseProtocol (
590 ControllerHandle,
591 &gEfiFirmwareVolume2ProtocolGuid,
593 ControllerHandle
594 );
595 ASSERT_EFI_ERROR (Status);
596
597 Status = gBS->UninstallProtocolInterface (
598 ControllerHandle,
599 &gEfiSimpleFileSystemProtocolGuid,
600 &Instance->SimpleFs
601 );
602 ASSERT_EFI_ERROR (Status);
603
604 //
605 // Free file structures
606 //
607 if (!IsListEmpty (&Instance->FileInfoHead)) {
608 //
609 // Free the Subtask list.
610 //
611 for (Entry = Instance->FileInfoHead.ForwardLink;
612 Entry != (&Instance->FileInfoHead);
613 )
614 {
615 DelEntry = Entry;
616 Entry = Entry->ForwardLink;
617 FvFileInfo = FVFS_FILE_INFO_FROM_LINK (DelEntry);
618
619 RemoveEntryList (DelEntry);
620 FreePool (FvFileInfo);
621 }
622 }
623
624 if (Instance->Root != NULL) {
625 //
626 // Root->Name is statically allocated, no need to free.
627 //
628 if (Instance->Root->FvFileInfo != NULL) {
629 FreePool (Instance->Root->FvFileInfo);
630 }
631
632 FreePool (Instance->Root);
633 }
634
635 //
636 // Free Instance
637 //
638 if (Instance->VolumeLabel != NULL) {
639 FreePool (Instance->VolumeLabel);
640 }
641
642 FreePool (Instance);
643
644 return EFI_SUCCESS;
645}
646
658EFIAPI
660 IN EFI_HANDLE ImageHandle,
661 IN EFI_SYSTEM_TABLE *SystemTable
662 )
663{
664 EFI_STATUS Status;
665
666 //
667 // Install driver model protocol(s).
668 //
670 ImageHandle,
671 SystemTable,
672 &mDriverBinding,
673 ImageHandle,
674 &gFvSimpleFileSystemComponentName,
675 &gFvSimpleFileSystemComponentName2
676 );
677 ASSERT_EFI_ERROR (Status);
678
679 return Status;
680}
UINT64 UINTN
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI InsertHeadList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:218
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
RETURN_STATUS EFIAPI StrnCatS(IN OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source, IN UINTN Length)
Definition: SafeString.c:507
RETURN_STATUS EFIAPI StrnCpyS(OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source, IN UINTN Length)
Definition: SafeString.c:310
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
#define MEDIA_PIWG_FW_VOL_DP
Definition: DevicePath.h:1146
UINT8 EFIAPI DevicePathType(IN CONST VOID *Node)
UINT8 EFIAPI DevicePathSubType(IN CONST VOID *Node)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI NextDevicePathNode(IN CONST VOID *Node)
BOOLEAN EFIAPI IsDevicePathEndType(IN CONST VOID *Node)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
EFI_STATUS FvFsGetFileSize(IN EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol, IN OUT FV_FILESYSTEM_FILE_INFO *FvFileInfo)
EFI_STATUS EFIAPI FvSimpleFileSystemDriverStop(IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, IN EFI_HANDLE ControllerHandle, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer OPTIONAL)
EFI_STATUS EFIAPI FvSimpleFileSystemDriverStart(IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL)
EFI_STATUS EFIAPI FvSimpleFileSystemEntryPoint(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
EFI_STATUS EFIAPI FvSimpleFileSystemOpenVolume(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, OUT EFI_FILE_PROTOCOL **RootFile)
EFI_STATUS InitializeUnicodeCollationSupportWorker(IN EFI_HANDLE AgentHandle, IN EFI_GUID *ProtocolGuid, IN CONST CHAR16 *VariableName, IN CONST CHAR8 *DefaultLanguage)
EFI_STATUS EFIAPI FvSimpleFileSystemDriverSupported(IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL)
EFI_STATUS InitializeUnicodeCollationSupport(IN EFI_HANDLE AgentHandle)
UINTN EFIAPI UnicodeSPrint(OUT CHAR16 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR16 *FormatString,...)
Definition: PrintLib.c:408
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define PcdGetPtr(TokenName)
Definition: PcdLib.h:388
#define EFI_FV_FILETYPE_ALL
UINT32 EFI_FV_FILE_ATTRIBUTES
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_HANDLE gImageHandle
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI GetEfiGlobalVariable2(IN CONST CHAR16 *Name, OUT VOID **Value, OUT UINTN *Size OPTIONAL)
Definition: UefiLib.c:1470
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)
CHAR8 *EFIAPI GetBestLanguage(IN CONST CHAR8 *SupportedLanguages, IN UINTN Iso639Language,...)
Definition: UefiLib.c:1522
@ EFI_NATIVE_INTERFACE
Definition: UefiSpec.h:1193
@ ByProtocol
Definition: UefiSpec.h:1518
UINT64 PhysicalSize
Definition: FileInfo.h:31
UINT64 Size
Definition: FileInfo.h:23
UINT64 Attribute
Definition: FileInfo.h:47
CHAR16 FileName[1]
Definition: FileInfo.h:52
UINT64 FileSize
Definition: FileInfo.h:27
Definition: Base.h:213