13STATIC UINT8
mDaysPerMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0 };
25 if ((Node != NULL) && (Node != Context->RootNode)) {
41 Element = Context->CurrentNode;
42 if (Element != NULL) {
43 Context->CurrentNode = Element->
Parent;
57 while (Context->CurrentNode != NULL) {
70 if (Context->CurrentNode->Parent == NULL) {
90 Next = AllocateZeroPool (
sizeof (*Next));
92 return EFI_OUT_OF_RESOURCES;
96 Next->
Type = FileType & ~FSHELP_CASE_INSENSITIVE;
97 Next->
Parent = Context->CurrentNode;
98 Context->CurrentNode = Next;
132 return EFI_NOT_FOUND;
136 Result =
OcStriCmp (Context->Name, Name);
138 Result = StrCmp (Context->Name, Name);
143 return EFI_NOT_FOUND;
146 *Context->FoundNode = Node;
147 *Context->FoundType = FileType;
158 IN OUT EFI_FILE_INFO *Info
167 if ( (Name[0] == L
'.')
168 && ((Name[1] == 0) || ( (Name[1] == L
'.')
172 return EFI_NOT_FOUND;
177 return EFI_NOT_FOUND;
184 (UINTN)((Info->Size - sizeof (*Info)) /
sizeof (CHAR16))
186 if (EFI_ERROR (Status)) {
187 DEBUG ((DEBUG_INFO,
"NTFS: Could not copy string.\n"));
192 Info->Size =
sizeof (*Info) + StrnLenS (Info->FileName,
MAX_PATH) *
sizeof (CHAR16);
198 Info->Attribute = EFI_FILE_READ_ONLY;
200 Info->Attribute |= EFI_FILE_DIRECTORY;
217 ASSERT (FileName != NULL);
221 if (StrCmp (FileName, File->BaseName) != 0) {
223 return EFI_NOT_FOUND;
249 ASSERT (Position != NULL);
250 ASSERT (FileOrCtx != NULL);
256 DEBUG ((DEBUG_INFO,
"NTFS: (ListFile #1) INDEX_ENTRY is corrupted.\n"));
257 return EFI_VOLUME_CORRUPTED;
264 if (
mBufferSize < (
sizeof (*IndexEntry) +
sizeof (*AttrFileName))) {
265 DEBUG ((DEBUG_INFO,
"NTFS: (ListFile #2) INDEX_ENTRY is corrupted.\n"));
266 return EFI_VOLUME_CORRUPTED;
269 AttrFileName = (
ATTR_FILE_NAME *)((UINT8 *)IndexEntry +
sizeof (*IndexEntry));
283 DirFile = AllocateZeroPool (
sizeof (*DirFile));
284 if (DirFile == NULL) {
285 DEBUG ((DEBUG_INFO,
"NTFS: Could not allocate space for DirFile\n"));
286 return EFI_OUT_OF_RESOURCES;
289 DirFile->
File = Dir->File;
295 if (
mBufferSize < (
sizeof (*IndexEntry) +
sizeof (*AttrFileName) + AttrFileName->
FilenameLen * sizeof (CHAR16))) {
296 DEBUG ((DEBUG_INFO,
"NTFS: (ListFile #3) INDEX_ENTRY is corrupted.\n"));
298 return EFI_VOLUME_CORRUPTED;
301 Filename = AllocateZeroPool ((AttrFileName->
FilenameLen + 1U) * sizeof (CHAR16));
302 if (Filename == NULL) {
303 DEBUG ((DEBUG_INFO,
"NTFS: Failed to allocate buffer for Filename\n"));
305 return EFI_OUT_OF_RESOURCES;
310 (UINT8 *)AttrFileName +
sizeof (*AttrFileName),
318 switch (FunctionType) {
320 Status =
NtfsDirIter (Filename, Type, DirFile, FileOrCtx);
324 Status =
NtfsDirHook (Filename, Type, DirFile, FileOrCtx);
328 Status =
FindFileIter (Filename, Type, DirFile, FileOrCtx);
333 return EFI_INVALID_PARAMETER;
338 if (Status == EFI_SUCCESS) {
346 DEBUG ((DEBUG_INFO,
"NTFS: (ListFile #4) INDEX_ENTRY is corrupted.\n"));
347 return EFI_VOLUME_CORRUPTED;
354 return EFI_NOT_FOUND;
360 IN CHAR16 *CurrentPath,
373 ASSERT (CurrentPath != NULL);
376 for (Name = CurrentPath; ; Name = Next) {
380 while (*Name == L
'/') {
384 if (*Name == L
'\0') {
388 for (Next = Name; (*Next != L
'\0') && (*Next != L
'/'); ++Next) {
394 if (Context->CurrentNode->Type !=
FSHELP_DIR) {
395 DEBUG ((DEBUG_INFO,
"NTFS: Not a directory\n"));
396 return EFI_INVALID_PARAMETER;
399 if ((Next - Name == 1U) && (Name[0] == L
'.')) {
403 if ((Next - Name == 2U) && (Name[0] == L
'.') && (Name[1] == L
'.')) {
408 PathPart = AllocateZeroPool ((Next - Name + 1U) *
sizeof (CHAR16));
409 if (PathPart == NULL) {
410 return EFI_OUT_OF_RESOURCES;
413 CopyMem (PathPart, Name, (Next - Name) *
sizeof (CHAR16));
415 IterCtx.
Name = PathPart;
421 if (EFI_ERROR (Status)) {
425 if (FoundNode == NULL) {
429 Status =
PushNode (Context, FoundNode, FoundType);
430 if (EFI_ERROR (Status)) {
435 if (++Context->SymlinkDepth == 8U) {
436 DEBUG ((DEBUG_INFO,
"NTFS: Too deep nesting of symlinks\n"));
437 return EFI_INVALID_PARAMETER;
440 Symlink =
ReadSymlink (Context->CurrentNode->Node);
441 if (Symlink == NULL) {
442 DEBUG ((DEBUG_INFO,
"NTFS: Symlink leeds nowhere\n"));
443 return EFI_INVALID_PARAMETER;
446 if (Symlink[0] == L
'/') {
451 if (EFI_ERROR (Status)) {
458 Status =
FindFile (Symlink, Context);
460 if (EFI_ERROR (Status)) {
466 DEBUG ((DEBUG_INFO,
"NTFS: File `%s' not found\n", IterCtx.
Name));
467 return EFI_NOT_FOUND;
472 IN CONST CHAR16 *Path,
483 ASSERT (RootNode != NULL);
484 ASSERT (FoundNode != NULL);
491 if (Path[0] != L
'/') {
492 DEBUG ((DEBUG_INFO,
"NTFS: Invalid file name `%s'\n", Path));
493 return EFI_INVALID_PARAMETER;
497 if (EFI_ERROR (Status)) {
501 Status =
FindFile ((CHAR16 *)Path, &Context);
502 if (EFI_ERROR (Status)) {
515 if (FoundType != Type) {
516 if (*FoundNode != RootNode) {
518 FreePool (*FoundNode);
522 DEBUG ((DEBUG_INFO,
"NTFS: Not a regular file\n"));
524 DEBUG ((DEBUG_INFO,
"NTFS: Not a directory\n"));
527 Status = EFI_VOLUME_CORRUPTED;
551 UINTN FileRecordSize;
552 UINTN IndexRecordSize;
555 ASSERT (FileOrCtx != NULL);
557 FileRecordSize = Dir->File->FileSystem->FileRecordSize;
558 IndexRecordSize = Dir->File->FileSystem->IndexRecordSize;
560 if (!Dir->InodeRead) {
561 Status =
InitFile (Dir, Dir->Inode);
562 if (EFI_ERROR (Status)) {
571 if (EFI_ERROR (Status)) {
581 DEBUG ((DEBUG_INFO,
"NTFS: no $INDEX_ROOT\n"));
583 return EFI_VOLUME_CORRUPTED;
592 DEBUG ((DEBUG_INFO,
"NTFS: (IterateDir #1) $INDEX_ROOT is corrupted.\n"));
594 return EFI_VOLUME_CORRUPTED;
608 DEBUG ((DEBUG_INFO,
"NTFS: (IterateDir #1.1) $INDEX_ROOT is corrupted.\n"));
610 return EFI_VOLUME_CORRUPTED;
622 DEBUG ((DEBUG_INFO,
"NTFS: (IterateDir #2) $INDEX_ROOT is corrupted.\n"));
624 return EFI_VOLUME_CORRUPTED;
635 if (!EFI_ERROR (Status)) {
648 if (EFI_ERROR (Status)) {
658 DEBUG ((DEBUG_INFO,
"NTFS: (IterateDir #3) $INDEX_ROOT is corrupted.\n"));
660 return EFI_VOLUME_CORRUPTED;
668 (UINTN)Non->AllocatedSize;
671 DEBUG ((DEBUG_INFO,
"NTFS: (IterateDir) File is too huge.\n"));
672 return EFI_OUT_OF_RESOURCES;
675 BitMap = AllocateZeroPool (BitMapLen);
676 if (BitMap == NULL) {
678 return EFI_OUT_OF_RESOURCES;
683 DEBUG ((DEBUG_INFO,
"NTFS: (IterateDir #4) $INDEX_ROOT is corrupted.\n"));
686 return EFI_VOLUME_CORRUPTED;
695 Status =
ReadData (&Attr, (UINT8 *)Non, BitMap, 0, BitMapLen);
696 if (EFI_ERROR (Status)) {
697 DEBUG ((DEBUG_INFO,
"NTFS: Failed to read non-resident $BITMAP\n"));
703 BitMapLen = (UINTN)Non->RealSize;
714 while (Non != NULL) {
720 DEBUG ((DEBUG_INFO,
"NTFS: (IterateDir #5) $INDEX_ROOT is corrupted.\n"));
722 if (BitIndex != NULL) {
726 return EFI_VOLUME_CORRUPTED;
740 if ((Non == NULL) && (BitIndex != NULL)) {
741 DEBUG ((DEBUG_INFO,
"NTFS: $BITMAP without $INDEX_ALLOCATION\n"));
744 return EFI_VOLUME_CORRUPTED;
747 if (BitIndex != NULL) {
748 IndexRecord = AllocateZeroPool (IndexRecordSize);
749 if (IndexRecord == NULL) {
752 return EFI_OUT_OF_RESOURCES;
756 for (Number = 0; Number < (BitMapLen * 8U); Number++) {
757 if ((*BitIndex & Bit) != 0) {
760 (UINT8 *)IndexRecord,
761 Number * IndexRecordSize,
764 if (EFI_ERROR (Status)) {
767 FreePool (IndexRecord);
772 (UINT8 *)IndexRecord,
774 SIGNATURE_32 (
'I',
'N',
'D',
'X'),
775 Dir->File->FileSystem->SectorSize
777 if (EFI_ERROR (Status)) {
780 FreePool (IndexRecord);
784 if ( (IndexRecordSize <
sizeof (*IndexRecord))
785 || (IndexRecordSize < (
sizeof (
INDEX_HEADER) + IndexRecord->IndexEntriesOffset)))
787 DEBUG ((DEBUG_INFO,
"NTFS: $INDEX_ALLOCATION is corrupted.\n"));
790 FreePool (IndexRecord);
791 return EFI_VOLUME_CORRUPTED;
798 (UINT8 *)IndexRecord +
sizeof (
INDEX_HEADER) + IndexRecord->IndexEntriesOffset,
802 if (!EFI_ERROR (Status)) {
805 FreePool (IndexRecord);
819 FreePool (IndexRecord);
842 Buffer = AllocateZeroPool (StrSize (Source));
845 End = Source + StrLen (Source);
847 while (
Start > Source) {
848 while (*
Start != L
'/') {
852 if ((
Start[1] == L
'.') && ((
Start[2] == L
'/') || (
Start[2] == L
'\0'))) {
875 (
End -
Start - 1U) *
sizeof (CHAR16)
887 DEBUG ((DEBUG_INFO,
"NTFS: Invalid path: root has no parent.\n"));
889 return EFI_DEVICE_ERROR;
905 (
End -
Start - 1U) *
sizeof (CHAR16)
945 EfiTime->TimeZone = EFI_UNSPECIFIED_TIMEZONE;
947 EfiTime->Daylight = 0;
977 EfiTime->Year = Year;
982 EfiTime->Nanosecond = Remainder32 *
UNIT_IN_NS;
989 for (Index = 1U; Index < 13U; ++Index) {
1000 EfiTime->Month = Month;
1001 EfiTime->Day = (UINT8)(Day - PrevLD);
EFI_DEVICE_PATH_PROTOCOL End
EFI_STATUS EFIAPI ReadAttr(IN NTFS_ATTR *Attr, OUT UINT8 *Dest, IN UINT64 Offset, IN UINTN Length)
EFI_STATUS EFIAPI ReadData(IN NTFS_ATTR *Attr, IN UINT8 *AttrStart, OUT UINT8 *Dest, IN UINT64 Offset, IN UINTN Length)
CHAR16 * ReadSymlink(IN NTFS_FILE *File)
UINT8 * LocateAttr(IN NTFS_ATTR *Attr, IN NTFS_FILE *Mft, IN UINT32 Type)
VOID FreeFile(IN NTFS_FILE *File)
VOID FreeAttr(IN NTFS_ATTR *Attr)
EFI_STATUS InitAttr(OUT NTFS_ATTR *Attr, IN NTFS_FILE *File)
UINT8 * FindAttr(IN NTFS_ATTR *Attr, IN UINT32 Type)
EFI_STATUS EFIAPI Fixup(IN UINT8 *Buffer, IN UINT64 Length, IN UINT32 Magic, IN UINTN SectorSize)
EFI_STATUS EFIAPI InitFile(IN OUT NTFS_FILE *File, IN UINT64 RecordNumber)
#define FSHELP_CASE_INSENSITIVE
STATIC EFI_STATUS GoToRoot(IN OUT FSHELP_CTX *Context)
VOID NtfsToEfiTime(EFI_TIME *EfiTime, UINT64 NtfsTime)
STATIC VOID FreeNode(IN OUT NTFS_FILE *Node OPTIONAL, IN FSHELP_CTX *Context)
EFI_STATUS RelativeToAbsolute(OUT CHAR16 *Dest, IN CHAR16 *Source)
STATIC EFI_STATUS ListFile(IN NTFS_FILE *Dir, IN UINT8 *Position, OUT VOID *FileOrCtx, IN FUNCTION_TYPE FunctionType)
STATIC UINT64 mBufferSize
STATIC VOID PopElement(IN OUT FSHELP_CTX *Context)
STATIC EFI_STATUS NtfsDirIter(IN CHAR16 *FileName, IN FSHELP_FILETYPE FileType, IN NTFS_FILE *Node, IN EFI_NTFS_FILE *File)
STATIC UINT8 mDaysPerMonth[]
STATIC EFI_STATUS NtfsDirHook(IN CHAR16 *Name, IN FSHELP_FILETYPE FileType, IN NTFS_FILE *Node, IN OUT EFI_FILE_INFO *Info)
STATIC EFI_STATUS PushNode(IN OUT FSHELP_CTX *Context, IN NTFS_FILE *Node, IN FSHELP_FILETYPE FileType)
EFI_STATUS IterateDir(IN NTFS_FILE *Dir, IN VOID *FileOrCtx, IN FUNCTION_TYPE FunctionType)
STATIC EFI_STATUS FindFile(IN CHAR16 *CurrentPath, IN FSHELP_CTX *Context)
EFI_STATUS FsHelpFindFile(IN CONST CHAR16 *Path, IN NTFS_FILE *RootNode, OUT NTFS_FILE **FoundNode, IN FSHELP_FILETYPE Type)
STATIC VOID GoUpALevel(IN OUT FSHELP_CTX *Context)
STATIC EFI_STATUS FindFileIter(IN CHAR16 *Name, IN FSHELP_FILETYPE FileType, IN NTFS_FILE *Node, IN FSHELP_ITER_CTX *Context)
STATIC VOID FreeStack(IN OUT FSHELP_CTX *Context)
INTN EFIAPI OcStriCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString)
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
UINT64 EFIAPI DivU64x32Remainder(IN UINT64 Dividend, IN UINT32 Divisor, OUT UINT32 *Remainder OPTIONAL)
UINT64 EFIAPI DivU64x64Remainder(IN UINT64 Dividend, IN UINT64 Divisor, OUT UINT64 *Remainder OPTIONAL)
struct _STACK_ELEMENT * Parent
STACK_ELEMENT * CurrentNode
FSHELP_FILETYPE * FoundType
UINT8 FileRecordNumber[6]
NTFS_FILE * BaseMftRecord