2 * COPYRIGHT: See COPYING.ARM in the top level directory
3 * PROJECT: ReactOS UEFI Boot Library
4 * FILE: boot/environ/lib/io/etfs.c
5 * PURPOSE: Boot Library El Torito File System Management Routines
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
12 #include "../drivers/filesystems/cdfs_new/cd.h"
13 typedef struct _RAW_ET_VD
20 ULONG BootCatalogOffset
;
22 } RAW_ET_VD
, *PRAW_ET_VD
;
24 /* DATA VARIABLES ************************************************************/
26 typedef struct _BL_ETFS_DEVICE
35 } BL_ETFS_DEVICE
, *PBL_ETFS_DEVICE
;
37 typedef struct _BL_ETFS_FILE
46 } BL_ETFS_FILE
, *PBL_ETFS_FILE
;
48 ULONG EtfsDeviceTableEntries
;
49 PVOID
* EtfsDeviceTable
;
53 _In_ PBL_FILE_ENTRY Directory
,
56 _Out_ PBL_FILE_ENTRY
*FileEntry
61 _In_ PBL_FILE_ENTRY FileEntry
,
62 _Out_ PBL_FILE_INFORMATION FileInfo
67 _In_ PBL_FILE_ENTRY FileEntry
,
68 _In_ PBL_FILE_INFORMATION FileInfo
73 _In_ PBL_FILE_ENTRY FileEntry
,
76 _Out_opt_ PULONG BytesReturned
79 BL_FILE_CALLBACKS EtfsFunctionTable
=
90 /* FUNCTIONS *****************************************************************/
93 EtfspGetDirectoryInfo (
94 _In_ PBL_ETFS_DEVICE EtfsDevice
,
95 _In_ PRAW_DIR_REC DirEntry
,
96 _Out_ PULONG FileOffset
,
97 _Out_ PULONG FileSize
,
98 _Out_opt_ PBOOLEAN IsDirectory
104 *FileOffset
= *(PULONG
)DirEntry
->FileLoc
* EtfsDevice
->BlockSize
;
105 *FileOffset
+= (DirEntry
->XarLen
* EtfsDevice
->BlockSize
);
107 SectorOffset
= ALIGN_DOWN_BY(*FileOffset
, CD_SECTOR_SIZE
);
109 *FileSize
= *(PULONG
)DirEntry
->DataLen
;
111 IsDir
= DE_FILE_FLAGS(EtfsDevice
->IsIso
, DirEntry
) & ISO_ATTR_DIRECTORY
;
114 *FileSize
+= ALIGN_UP_BY(SectorOffset
, CD_SECTOR_SIZE
) - SectorOffset
;
119 *IsDirectory
= IsDir
;
124 EtfspGetDirentNameLength (
125 _In_ PRAW_DIR_REC DirEntry
128 USHORT Length
, RealLength
;
131 RealLength
= Length
= DirEntry
->FileIdLen
;
132 for (Pos
= &DirEntry
->FileIdLen
+ Length
; Length
; --Pos
)
144 for (Pos
= &DirEntry
->FileIdLen
+ Length
; Length
; --Pos
)
162 __in PUNICODE_STRING Name2
168 l2
= Name2
->Length
/ sizeof(WCHAR
);
171 for (i
= 0; i
< l
; i
++)
173 if (toupper(Name1
->Buffer
[i
]) != toupper(Name2
->Buffer
[i
]))
175 return toupper(Name1
->Buffer
[i
]) - toupper(Name2
->Buffer
[i
]);
191 _In_ PRAW_DIR_REC DirEntry
,
192 _In_ PUNICODE_STRING FileName
199 if ((DirEntry
->FileIdLen
!= 1) ||
200 ((DirEntry
->FileId
[0] != 0) && (DirEntry
->FileId
[0] != 1)))
202 Length
= EtfspGetDirentNameLength(DirEntry
);
203 DirName
.Length
= Length
;
204 DirName
.MaximumLength
= Length
;
205 DirName
.Buffer
= (PCHAR
)DirEntry
->FileId
;
207 Match
= EtfspCompareNames(&DirName
, FileName
);
218 _In_ PBL_FILE_ENTRY DirectoryEntry
,
219 _Out_ PRAW_DIR_REC
*DirEntry
,
220 _Inout_ PULONG DirentOffset
223 PBL_ETFS_FILE EtfsFile
;
224 ULONG FileOffset
, DirectoryOffset
, AlignedOffset
, RemainderOffset
;
225 ULONG DeviceId
, ReadSize
, DirLen
;
226 PBL_ETFS_DEVICE EtfsDevice
;
227 BOOLEAN NeedRead
, IsMulti
;
232 EtfsFile
= DirectoryEntry
->FsSpecificData
;
233 DeviceId
= EtfsFile
->DeviceId
;
234 FileOffset
= EtfsFile
->DiskOffset
;
235 EtfsDevice
= EtfsDeviceTable
[DeviceId
];
237 DirectoryOffset
= *DirentOffset
;
238 MemoryBlock
= EtfsDevice
->MemoryBlock
;
242 AlignedOffset
= (FileOffset
+ *DirentOffset
) & ~CD_SECTOR_SIZE
;
243 RemainderOffset
= *DirentOffset
+ FileOffset
- AlignedOffset
;
245 ReadSize
= 2048 - RemainderOffset
;
246 NeedRead
= AlignedOffset
== EtfsDevice
->Offset
? 0 : 1;
249 if (DirectoryOffset
>= EtfsFile
->Size
)
251 return STATUS_NO_SUCH_FILE
;
254 while (ReadSize
< MIN_DIR_REC_SIZE
)
256 DirectoryOffset
+= ReadSize
;
257 AlignedOffset
+= 2048;
261 if (DirectoryOffset
>= EtfsFile
->Size
)
263 return STATUS_NO_SUCH_FILE
;
269 result
= BlDeviceReadAtOffset(DirectoryEntry
->DeviceId
,
274 if (!NT_SUCCESS(result
))
276 EfiPrintf(L
"Device read failed %lx\r\n", result
);
281 EtfsDevice
->Offset
= AlignedOffset
;
284 if (!*(MemoryBlock
+ RemainderOffset
))
286 AlignedOffset
+= 2048;
290 DirectoryOffset
+= ReadSize
;
295 DirEnt
= (PRAW_DIR_REC
)(MemoryBlock
+ RemainderOffset
);
296 DirLen
= DirEnt
->DirLen
;
297 if (DirLen
> ReadSize
)
299 EfiPrintf(L
"Dir won't fit %lx %lx\r\n", DirLen
, ReadSize
);
300 return STATUS_NO_SUCH_FILE
;
305 if (!(DE_FILE_FLAGS(EtfsDevice
->IsIso
, DirEnt
) & ISO_ATTR_MULTI
))
310 else if (DE_FILE_FLAGS(EtfsDevice
->IsIso
, DirEnt
) & ISO_ATTR_MULTI
)
316 if ((DirEnt
->FileIdLen
!= 1) ||
317 ((DirEnt
->FileId
[0] != 0) && (DirEnt
->FileId
[0] != 1)))
323 RemainderOffset
+= DirLen
;
324 DirectoryOffset
+= DirLen
;
330 *DirentOffset
= DirectoryOffset
;
331 return STATUS_SUCCESS
;
335 EtfspSearchForDirent (
336 _In_ PBL_FILE_ENTRY DirectoryEntry
,
337 _In_ PWCHAR FileName
,
338 _Out_ PRAW_DIR_REC
*DirEntry
,
339 _Out_ PULONG DirentOffset
347 RtlInitUnicodeString(&Name
, FileName
);
348 for (NextOffset
= *DirentOffset
;
350 NextOffset
= NextOffset
+ DirEnt
->DirLen
)
352 Status
= EtfspGetDirent(DirectoryEntry
, &DirEnt
, &NextOffset
);
353 if (!NT_SUCCESS(Status
))
355 return STATUS_NO_SUCH_FILE
;
358 if (!EtfspFileMatch(DirEnt
, &Name
))
365 *DirentOffset
= NextOffset
;
370 EtfspCachedSearchForDirent (
371 _In_ PBL_FILE_ENTRY DirectoryEntry
,
372 _In_ PWCHAR FileName
,
373 _Out_ PRAW_DIR_REC
*DirEntry
,
374 _Out_ PULONG DirOffset
,
375 _In_ BOOLEAN KeepOffset
378 PBL_ETFS_FILE EtfsFile
;
379 PBL_ETFS_DEVICE EtfsDevice
;
385 EtfsFile
= DirectoryEntry
->FsSpecificData
;
386 EtfsDevice
= EtfsDeviceTable
[EtfsFile
->DeviceId
];
387 RtlInitUnicodeString(&Name
, FileName
);
388 DirentOffset
= EtfsFile
->DirEntOffset
;
391 (ALIGN_DOWN_BY((DirentOffset
+ EtfsFile
->DiskOffset
), CD_SECTOR_SIZE
) ==
394 Status
= EtfspGetDirent(DirectoryEntry
, &Dirent
, &DirentOffset
);
395 if (NT_SUCCESS(Status
))
397 if (!EtfspFileMatch(Dirent
, &Name
))
400 *DirOffset
= DirentOffset
;
401 return STATUS_SUCCESS
;
414 Status
= EtfspSearchForDirent(DirectoryEntry
,
418 if (!(NT_SUCCESS(Status
)) && (DirentOffset
))
421 Status
= EtfspSearchForDirent(DirectoryEntry
,
427 if (NT_SUCCESS(Status
))
429 *DirOffset
= DirentOffset
;
437 _In_ PBL_FILE_ENTRY FileEntry
,
440 _Out_opt_ PULONG BytesReturned
444 PBL_ETFS_FILE EtfsFile
;
447 /* Assume failure for now */
450 /* Make sure that the read is within the file's boundaries */
451 EtfsFile
= FileEntry
->FsSpecificData
;
452 if ((Size
+ EtfsFile
->Offset
) > EtfsFile
->Size
)
454 /* Bail out otherwise */
455 Status
= STATUS_INVALID_PARAMETER
;
459 /* Read the offset that matches this file's offset, on the disk */
460 Status
= BlDeviceReadAtOffset(FileEntry
->DeviceId
,
462 EtfsFile
->Offset
+ EtfsFile
->DiskOffset
,
465 if (NT_SUCCESS(Status
))
467 /* Update the file offset and return the size as having been read */
468 EtfsFile
->Offset
+= Size
;
473 /* Check if caller wanted to know how many bytes were read */
476 /* Return the value */
477 *BytesReturned
= BytesRead
;
486 _In_ PBL_FILE_ENTRY FileEntry
,
487 _In_ PBL_FILE_INFORMATION FileInfo
490 PBL_ETFS_FILE EtfsFile
;
491 BL_FILE_INFORMATION LocalFileInfo
;
493 /* Get the underlying ETFS file data structure */
494 EtfsFile
= (PBL_ETFS_FILE
)FileEntry
->FsSpecificData
;
496 /* Make a copy of the incoming attributes, but ignore the new offset */
497 LocalFileInfo
= *FileInfo
;
498 LocalFileInfo
.Offset
= EtfsFile
->Offset
;
500 /* Check if these match exactly the current file */
501 if (!RtlEqualMemory(&LocalFileInfo
, &EtfsFile
->Size
, sizeof(*FileInfo
)))
503 /* Nope -- which means caller is trying to change an immutable */
504 EfiPrintf(L
"Incorrect information change\r\n");
505 return STATUS_INVALID_PARAMETER
;
508 /* Is the offset past the end of the file? */
509 if (FileInfo
->Offset
>= EtfsFile
->Size
)
511 /* Don't allow EOF */
512 EfiPrintf(L
"Offset too large: %lx vs %lx \r\n", FileInfo
->Offset
, EtfsFile
->Size
);
513 return STATUS_INVALID_PARAMETER
;
516 /* Update the offset */
517 EtfsFile
->Offset
= FileInfo
->Offset
;
518 return STATUS_SUCCESS
;
523 _In_ PBL_FILE_ENTRY FileEntry
,
524 _Out_ PBL_FILE_INFORMATION FileInfo
527 PBL_ETFS_FILE EtfsFile
;
529 /* Get the underlying ETFS file data structure */
530 EtfsFile
= (PBL_ETFS_FILE
)FileEntry
->FsSpecificData
;
532 /* Copy the cached information structure within it */
533 RtlCopyMemory(FileInfo
, &EtfsFile
->Size
, sizeof(*FileInfo
));
534 return STATUS_SUCCESS
;
539 _In_ PBL_FILE_ENTRY Directory
,
540 _In_ PWCHAR FileName
,
542 _Out_ PBL_FILE_ENTRY
*FileEntry
545 PBL_ETFS_DEVICE EtfsDevice
;
547 PBL_FILE_ENTRY NewFile
;
548 PWCHAR FilePath
, FormatString
;
549 PBL_ETFS_FILE EtfsFile
;
550 ULONG DeviceId
, FileSize
, DirOffset
, FileOffset
, Size
;
551 PRAW_DIR_REC DirEntry
;
554 EfiPrintf(L
"Attempting to open file %s in directory %s\r\n", FileName
, Directory
->FilePath
);
556 EtfsFile
= Directory
->FsSpecificData
;
557 DeviceId
= EtfsFile
->DeviceId
;
558 EtfsDevice
= EtfsDeviceTable
[DeviceId
];
560 /* Find the given file (or directory) in the given directory */
561 Status
= EtfspCachedSearchForDirent(Directory
,
566 if (!NT_SUCCESS(Status
))
568 EfiPrintf(L
"no dirent found: %lx\r\n", Status
);
572 /* Find out information about the file (or directory) we found */
573 EtfspGetDirectoryInfo(EtfsDevice
,
579 NewFile
= BlMmAllocateHeap(sizeof(*NewFile
));
582 return STATUS_NO_MEMORY
;
584 RtlZeroMemory(NewFile
, sizeof(*NewFile
));
586 Size
= wcslen(Directory
->FilePath
) + wcslen(FileName
) + 2;
588 FilePath
= BlMmAllocateHeap(Size
* sizeof(WCHAR
));
591 Status
= STATUS_NO_MEMORY
;
595 EtfsFile
= (PBL_ETFS_FILE
)BlMmAllocateHeap(sizeof(*EtfsFile
));
598 Status
= STATUS_NO_MEMORY
;
602 RtlZeroMemory(NewFile
, sizeof(*EtfsFile
));
604 NewFile
->DeviceId
= Directory
->DeviceId
;
605 FormatString
= L
"%ls%ls";
606 if (Directory
->FilePath
[1])
608 FormatString
= L
"%ls\\%ls";
611 _snwprintf(FilePath
, Size
, FormatString
, Directory
->FilePath
, FileName
);
612 NewFile
->FilePath
= FilePath
;
614 RtlCopyMemory(&NewFile
->Callbacks
,
616 sizeof(NewFile
->Callbacks
));
617 EtfsFile
->DiskOffset
= FileOffset
;
618 EtfsFile
->DirOffset
= DirOffset
;
619 EtfsFile
->Size
= FileSize
;
620 EtfsFile
->DeviceId
= DeviceId
;
623 EtfsFile
->Flags
|= 1;
624 NewFile
->Flags
|= 0x10000;
626 EtfsFile
->FsName
= L
"cdfs";
628 NewFile
->FsSpecificData
= EtfsFile
;
629 *FileEntry
= NewFile
;
634 if (NewFile
->FilePath
)
636 BlMmFreeHeap(NewFile
->FilePath
);
639 if (NewFile
->FsSpecificData
)
641 BlMmFreeHeap(NewFile
->FsSpecificData
);
644 BlMmFreeHeap(NewFile
);
650 _In_ PBL_ETFS_DEVICE EtfsDevice
,
652 _Out_ PRAW_ISO_VD
*VolumeDescriptor
,
653 _Out_ PBOOLEAN VolumeIsIso
656 EfiPrintf(L
"Raw Cdfs not implemented\r\n");
657 return STATUS_NOT_IMPLEMENTED
;
662 _In_ PBL_ETFS_DEVICE EtfsDevice
,
664 _Out_ PRAW_ISO_VD
*VolumeDescriptor
,
665 _Out_ PBOOLEAN VolumeIsIso
672 BL_DEVICE_INFORMATION DeviceInformation
;
673 ULONG Unknown
, BytesRead
;
674 ANSI_STRING CompareString
, String
;
676 /* Save our static buffer pointer */
677 IsoVd
= (PRAW_ISO_VD
)EtfsDevice
->MemoryBlock
;
678 EtVd
= (PRAW_ET_VD
)IsoVd
;
680 /* First, read the El Torito Volume Descriptor */
681 BlDeviceGetInformation(DeviceId
, &DeviceInformation
);
682 Unknown
= DeviceInformation
.BlockDeviceInfo
.Unknown
;
683 DeviceInformation
.BlockDeviceInfo
.Unknown
|= 1;
684 BlDeviceSetInformation(DeviceId
, &DeviceInformation
);
685 Status
= BlDeviceReadAtOffset(DeviceId
,
687 (FIRST_VD_SECTOR
+ 1) * CD_SECTOR_SIZE
,
688 EtfsDevice
->MemoryBlock
,
690 DeviceInformation
.BlockDeviceInfo
.Unknown
= Unknown
;
691 BlDeviceSetInformation(DeviceId
, &DeviceInformation
);
692 if (!NT_SUCCESS(Status
))
694 EfiPrintf(L
" read failed\r\n");
698 /* Remember that's where we last read */
699 EtfsDevice
->Offset
= (FIRST_VD_SECTOR
+ 1) * CD_SECTOR_SIZE
;
701 /* Check if it's EL TORITO! */
702 RtlInitString(&String
, "EL TORITO SPECIFICATION");
703 CompareString
.Buffer
= (PCHAR
)EtVd
->SystemId
;
704 CompareString
.Length
= 23;
705 CompareString
.MaximumLength
= 23;
706 if (!RtlEqualString(&CompareString
, &String
, TRUE
))
708 return STATUS_UNSUCCESSFUL
;
711 /* Check the version and boot indicator */
712 if ((EtVd
->Version
!= 1) || (EtVd
->BootIndicator
))
714 return STATUS_UNSUCCESSFUL
;
717 /* Check if it has the CD0001 identifier */
718 RtlInitString(&String
, ISO_VOL_ID
);
719 CompareString
.Buffer
= (PCHAR
)EtVd
->StandardId
;
720 CompareString
.Length
= 5;
721 CompareString
.MaximumLength
= 5;
722 if (!RtlEqualString(&CompareString
, &String
, TRUE
))
724 return STATUS_UNSUCCESSFUL
;
727 /* Step two, we now want to read the ISO Volume Descriptor */
728 DeviceInformation
.BlockDeviceInfo
.Unknown
|= 1u;
729 BlDeviceSetInformation(DeviceId
, &DeviceInformation
);
730 Status
= BlDeviceReadAtOffset(DeviceId
,
732 FIRST_VD_SECTOR
* CD_SECTOR_SIZE
,
733 EtfsDevice
->MemoryBlock
,
735 DeviceInformation
.BlockDeviceInfo
.Unknown
= Unknown
;
736 BlDeviceSetInformation(DeviceId
, &DeviceInformation
);
737 if (!NT_SUCCESS(Status
))
742 /* Remember where we left off */
743 EtfsDevice
->Offset
= FIRST_VD_SECTOR
* CD_SECTOR_SIZE
;
745 /* This should also say CD0001 */
746 CompareString
.Buffer
= (PCHAR
)IsoVd
->StandardId
;
747 CompareString
.Length
= 5;
748 CompareString
.MaximumLength
= 5;
749 IsIso
= RtlEqualString(&CompareString
, &String
, TRUE
);
752 return STATUS_UNSUCCESSFUL
;
755 /* And should be a version we support */
756 if ((IsoVd
->Version
!= VERSION_1
) || (IsoVd
->DescType
!= VD_PRIMARY
))
758 return STATUS_UNSUCCESSFUL
;
761 /* Return back to the caller */
762 *VolumeDescriptor
= IsoVd
;
763 *VolumeIsIso
= IsIso
;
764 EfiPrintf(L
"Recognized!!!\r\n");
765 return STATUS_SUCCESS
;
769 EtfspDeviceContextDestroy (
770 _In_ PBL_ETFS_DEVICE EtfsDevice
773 if (EtfsDevice
->MemoryBlock
)
775 BlMmFreeHeap(EtfsDevice
->MemoryBlock
);
778 BlMmFreeHeap(EtfsDevice
);
780 return STATUS_SUCCESS
;
786 _Out_ PBL_ETFS_DEVICE
*EtfsDevice
789 PBL_ETFS_DEVICE NewContext
;
795 NewContext
= (PBL_ETFS_DEVICE
)BlMmAllocateHeap(sizeof(*NewContext
));
798 return STATUS_NO_MEMORY
;
800 RtlZeroMemory(NewContext
, sizeof(*NewContext
));
802 MemoryBlock
= BlMmAllocateHeap(CD_SECTOR_SIZE
);
803 NewContext
->MemoryBlock
= MemoryBlock
;
806 Status
= STATUS_NO_MEMORY
;
810 Status
= EtfspCheckEtfs(NewContext
, DeviceId
, &RawVd
, &IsIso
);
811 if (!NT_SUCCESS(Status
))
813 EfiPrintf(L
"Drive not EDFS. Checking for CDFS: %lx\r\n");
814 Status
= EtfspCheckCdfs(NewContext
, DeviceId
, &RawVd
, &IsIso
);
817 if (!NT_SUCCESS(Status
))
819 EfiPrintf(L
"Drive not CDFS. Failing: %lx\r\n");
823 NewContext
->IsIso
= IsIso
;
824 NewContext
->BlockSize
= RVD_LB_SIZE(RawVd
, IsIso
);
825 NewContext
->VolumeSize
= RVD_VOL_SIZE(RawVd
, IsIso
);
827 EtfspGetDirectoryInfo(NewContext
,
828 (PRAW_DIR_REC
)RVD_ROOT_DE(RawVd
, IsIso
),
829 &NewContext
->RootDirOffset
,
830 &NewContext
->RootDirSize
,
832 Status
= STATUS_SUCCESS
;
835 if (!NT_SUCCESS(Status
))
837 EtfspDeviceContextDestroy(NewContext
);
841 *EtfsDevice
= NewContext
;
846 EtfspDeviceTableDestroyEntry (
847 _In_ PBL_ETFS_DEVICE EtfsDevice
,
851 EtfspDeviceContextDestroy(EtfsDevice
);
852 EtfsDeviceTable
[Index
] = NULL
;
854 return STATUS_SUCCESS
;
861 _Out_ PBL_FILE_ENTRY
* FileEntry
864 PBL_ETFS_DEVICE EtfsDevice
= NULL
;
865 PBL_FILE_ENTRY RootEntry
;
867 PBL_ETFS_FILE EtfsFile
;
869 EfiPrintf(L
"Trying to mount as ETFS...\r\n");
871 Status
= EtfspCreateContext(DeviceId
, &EtfsDevice
);
872 if (!NT_SUCCESS(Status
))
874 EfiPrintf(L
"ETFS context failed: %lx\r\n");
878 Status
= BlTblSetEntry(&EtfsDeviceTable
,
879 &EtfsDeviceTableEntries
,
883 if (!NT_SUCCESS(Status
))
885 EtfspDeviceContextDestroy(EtfsDevice
);
889 RootEntry
= BlMmAllocateHeap(sizeof(*RootEntry
));
892 Status
= STATUS_NO_MEMORY
;
896 RtlZeroMemory(RootEntry
, sizeof(*RootEntry
));
898 RootEntry
->FilePath
= BlMmAllocateHeap(4);
899 if (!RootEntry
->FilePath
)
901 Status
= STATUS_NO_MEMORY
;
905 wcsncpy(RootEntry
->FilePath
, L
"\\", 1);
907 RootEntry
->DeviceId
= DeviceId
;
908 RtlCopyMemory(&RootEntry
->Callbacks
,
910 sizeof(RootEntry
->Callbacks
));
912 EtfsFile
= (PBL_ETFS_FILE
)BlMmAllocateHeap(sizeof(*EtfsFile
));
915 Status
= STATUS_NO_MEMORY
;
919 RootEntry
->Flags
|= 0x10000;
921 RtlZeroMemory(EtfsFile
, sizeof(*EtfsFile
));
922 RootEntry
->FsSpecificData
= EtfsFile
;
923 EtfsFile
->DeviceId
= DeviceId
;
924 EtfsFile
->Flags
|= 1;
925 EtfsFile
->DiskOffset
= EtfsDevice
->RootDirOffset
;
926 EtfsFile
->DirOffset
= 0;
927 EtfsFile
->Size
= EtfsDevice
->RootDirSize
;
928 EtfsFile
->FsName
= L
"cdfs";
929 *FileEntry
= RootEntry
;
931 return STATUS_SUCCESS
;
934 if (RootEntry
->FilePath
)
936 BlMmFreeHeap(RootEntry
->FilePath
);
938 if (RootEntry
->FsSpecificData
)
940 BlMmFreeHeap(RootEntry
->FsSpecificData
);
944 BlMmFreeHeap(RootEntry
);
947 EtfspDeviceTableDestroyEntry(EtfsDevice
, DeviceId
);
959 /* Allocate the device table with 2 entries*/
960 EtfsDeviceTableEntries
= 2;
961 EtfsDeviceTable
= BlMmAllocateHeap(sizeof(PBL_FILE_ENTRY
) *
962 EtfsDeviceTableEntries
);
966 RtlZeroMemory(EtfsDeviceTable
,
967 sizeof(PBL_FILE_ENTRY
) * EtfsDeviceTableEntries
);
968 Status
= STATUS_SUCCESS
;
972 /* No memory, fail */
973 Status
= STATUS_NO_MEMORY
;
976 /* Return back to caller */