All steps on how to find and open files and directories in an UDF
filesystem have been followed by OSTA UDF and ECMA-167 specifications.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Paulo Alcantara <pca...@zytor.com>
---
 MdeModulePkg/Universal/Disk/UdfDxe/FileName.c      | 190 ++++++++
 .../Universal/Disk/UdfDxe/FileSystemOperations.c   | 520 ++++++++++++++++++++-
 MdeModulePkg/Universal/Disk/UdfDxe/Udf.h           |  25 +
 MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf      |   1 +
 4 files changed, 734 insertions(+), 2 deletions(-)
 create mode 100644 MdeModulePkg/Universal/Disk/UdfDxe/FileName.c

diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/FileName.c 
b/MdeModulePkg/Universal/Disk/UdfDxe/FileName.c
new file mode 100644
index 0000000..04cb5b5
--- /dev/null
+++ b/MdeModulePkg/Universal/Disk/UdfDxe/FileName.c
@@ -0,0 +1,190 @@
+/** @file
+  UDF filesystem driver.
+
+Copyright (c) 2014 Paulo Alcantara <pca...@zytor.com><BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD 
License
+which accompanies this distribution.  The full text of the license may be 
found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Udf.h"
+
+STATIC
+CHAR16 *
+TrimString (
+  IN CHAR16    *String
+  )
+{
+  CHAR16       *TempString;
+
+  for ( ; (*String) && (*String == L' '); String++) {
+    ;
+  }
+
+  TempString = String + StrLen (String) - 1;
+  while ((TempString >= String) && (*TempString == L' ')) {
+    TempString--;
+  }
+
+  *(TempString + 1) = L'\0';
+
+  return String;
+}
+
+STATIC
+VOID
+ReplaceLeft (
+  IN CHAR16         *Destination,
+  IN CONST CHAR16   *Source
+  )
+{
+  CONST CHAR16      *EndString;
+
+  EndString = Source + StrLen (Source);
+  while (Source <= EndString) {
+    *Destination++ = *Source++;
+  }
+}
+
+STATIC
+CHAR16 *
+ExcludeTrailingBackslashes (
+  IN CHAR16                    *String
+  )
+{
+  CHAR16                       *TempString;
+
+  switch (*(String + 1)) {
+    case L'\\':
+      break;
+    case L'\0':
+    default:
+      String++;
+      goto Exit;
+  }
+
+  TempString = String;
+  while ((*TempString) && (*TempString == L'\\')) {
+    TempString++;
+  }
+
+  if (TempString - 1 > String) {
+    ReplaceLeft (String + 1, TempString);
+  }
+
+  String++;
+
+Exit:
+  return String;
+}
+
+CHAR16 *
+MangleFileName (
+  IN CHAR16        *FileName
+  )
+{
+  CHAR16           *FileNameSavedPointer;
+  CHAR16           *TempFileName;
+  UINTN            BackslashesNo;
+
+  if ((!FileName) || ((FileName) && (!*FileName))) {
+    FileName = NULL;
+    goto Exit;
+  }
+
+  FileName = TrimString (FileName);
+  if (!*FileName) {
+    goto Exit;
+  }
+
+  if ((StrLen (FileName) > 1) && (FileName[StrLen (FileName) - 1] == L'\\')) {
+    FileName[StrLen (FileName) - 1] = L'\0';
+  }
+
+  FileNameSavedPointer = FileName;
+
+  if (FileName[0] == L'.') {
+    if (FileName[1] == L'.') {
+      if (!FileName[2]) {
+       goto Exit;
+      } else {
+       FileName += 2;
+      }
+    } else if (!FileName[1]) {
+      goto Exit;
+    }
+  }
+
+  while (*FileName) {
+    if (*FileName == L'\\') {
+      FileName = ExcludeTrailingBackslashes (FileName);
+    } else if (*FileName == L'.') {
+      switch (*(FileName + 1)) {
+       case L'\0':
+         *FileName = L'\0';
+         break;
+       case L'\\':
+         TempFileName = FileName + 1;
+         TempFileName = ExcludeTrailingBackslashes (TempFileName);
+         ReplaceLeft (FileName, TempFileName);
+         break;
+       case '.':
+         if ((*(FileName - 1) != L'\\') && ((*(FileName + 2) != L'\\') ||
+                                            (*(FileName + 2) != L'\0'))) {
+           FileName++;
+           continue;
+         }
+
+         BackslashesNo = 0;
+         TempFileName = FileName - 1;
+         while (TempFileName >= FileNameSavedPointer) {
+           if (*TempFileName == L'\\') {
+             if (++BackslashesNo == 2) {
+               break;
+             }
+           }
+
+           TempFileName--;
+         }
+
+         TempFileName++;
+
+         if ((*TempFileName == L'.') && (*(TempFileName + 1) == L'.')) {
+           FileName += 2;
+         } else {
+           if (*(FileName + 2)) {
+             ReplaceLeft (TempFileName, FileName + 3);
+             if (*(TempFileName - 1) == L'\\') {
+               FileName = TempFileName;
+               ExcludeTrailingBackslashes (TempFileName - 1);
+               TempFileName = FileName;
+             }
+           } else {
+             *TempFileName = L'\0';
+           }
+
+           FileName = TempFileName;
+         }
+
+         break;
+       default:
+         FileName++;
+      }
+    } else {
+      FileName++;
+    }
+  }
+
+  FileName = FileNameSavedPointer;
+  if ((StrLen (FileName) > 1) && (FileName [StrLen (FileName) - 1] == L'\\')) {
+    FileName [StrLen (FileName) - 1] = L'\0';
+  }
+
+Exit:
+  return FileName;
+}
diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c 
b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c
index 5492494..8a13794 100644
--- a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c
+++ b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c
@@ -150,7 +150,347 @@ UdfOpen (
   IN  UINT64                             Attributes
   )
 {
-  return EFI_DEVICE_ERROR;
+  EFI_TPL                                OldTpl;
+  EFI_STATUS                             Status;
+  PRIVATE_UDF_FILE_DATA                  *PrivFileData;
+  UINT32                                 PartitionStartingLocation;
+  UINT32                                 PartitionLength;
+  UDF_FILE_ENTRY                         FileEntry;
+  UDF_FILE_IDENTIFIER_DESCRIPTOR         CurFileIdentifierDesc;
+  UDF_FILE_IDENTIFIER_DESCRIPTOR         ParentFileIdentifierDesc;
+  UDF_FILE_IDENTIFIER_DESCRIPTOR         FileIdentifierDesc;
+  UINT64                                 NextOffset;
+  BOOLEAN                                ReadDone;
+  CHAR16                                 *String;
+  CHAR16                                 *TempString;
+  UINT64                                 Offset;
+  CHAR16                                 *FileNameSavedPointer;
+  CHAR16                                 *NextFileName;
+  CHAR16                                 *TempFileName;
+  EFI_BLOCK_IO_PROTOCOL                  *BlockIo;
+  EFI_DISK_IO_PROTOCOL                   *DiskIo;
+  BOOLEAN                                Found;
+  PRIVATE_UDF_FILE_DATA                  *NewPrivFileData;
+  UDF_LONG_ALLOCATION_DESCRIPTOR         *LongAd;
+  UINT64                                 Lsn;
+  BOOLEAN                                IsRootDirectory;
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+  String = NULL;
+
+  if ((!This) || (!NewHandle) || (!FileName)) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
+
+  PartitionStartingLocation   = PrivFileData->Partition.StartingLocation;
+  PartitionLength             = PrivFileData->Partition.Length;
+
+  FileName = MangleFileName (FileName);
+  if ((!FileName) || ((FileName) && (!*FileName))) {
+    Status = EFI_NOT_FOUND;
+    goto Exit;
+  }
+
+  String = AllocatePool ((StrLen (FileName) + 1) * sizeof (CHAR16));
+  if (!String) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  BlockIo                = PrivFileData->BlockIo;
+  DiskIo                 = PrivFileData->DiskIo;
+  Found                  = FALSE;
+  NextFileName           = NULL;
+  NewPrivFileData        = NULL;
+  FileNameSavedPointer   = FileName;
+
+  if (PrivFileData->IsRootDirectory) {
+    CopyMem (
+      (VOID *)&CurFileIdentifierDesc,
+      (VOID *)&PrivFileData->Root.FileIdentifierDesc,
+      sizeof (UDF_FILE_IDENTIFIER_DESCRIPTOR)
+      );
+    CopyMem (
+      (VOID *)&ParentFileIdentifierDesc,
+      (VOID *)&PrivFileData->Root.FileIdentifierDesc,
+      sizeof (UDF_FILE_IDENTIFIER_DESCRIPTOR)
+      );
+  } else {
+    CopyMem (
+      (VOID *)&CurFileIdentifierDesc,
+      (VOID *)&PrivFileData->File.FileIdentifierDesc,
+      sizeof (UDF_FILE_IDENTIFIER_DESCRIPTOR)
+      );
+    CopyMem (
+      (VOID *)&ParentFileIdentifierDesc,
+      (VOID *)&PrivFileData->File.ParentFileIdentifierDesc,
+      sizeof (UDF_FILE_IDENTIFIER_DESCRIPTOR)
+      );
+  }
+
+  CopyMem (
+    (VOID *)&FileIdentifierDesc,
+    (VOID *)&CurFileIdentifierDesc,
+    sizeof (UDF_FILE_IDENTIFIER_DESCRIPTOR)
+    );
+
+  for (;;) {
+NextLookup:
+    if (NextFileName) {
+      FreePool ((VOID *)NextFileName);
+      NextFileName = NULL;
+    }
+
+    //
+    // Parse FileName
+    //
+    if (!*FileName) {
+      break;
+    }
+
+    Offset = 0;
+
+    TempString = String;
+    while ((*FileName) && (*FileName != L'\\')) {
+      *TempString++ = *FileName++;
+    }
+
+    *TempString = L'\0';
+
+    if ((*FileName) && (*FileName == L'\\')) {
+      FileName++;
+    }
+
+    Found             = FALSE;
+    IsRootDirectory   = FALSE;
+
+    if (!*String) {
+      CopyMem (
+       (VOID *)&FileIdentifierDesc,
+       (VOID *)&PrivFileData->Root.FileIdentifierDesc,
+       sizeof (UDF_FILE_IDENTIFIER_DESCRIPTOR)
+       );
+      if (!*FileName) {
+       Found             = TRUE;
+       IsRootDirectory   = TRUE;
+       break;
+      } else {
+       continue;
+      }
+    }
+
+    if (StrCmp (String, L"..") == 0) {
+      //
+      // Make sure we're not going to look up Parent FID from a root
+      // directory or even if the current FID is not a directory(!)
+      //
+      if ((IS_FID_PARENT_FILE (&FileIdentifierDesc)) ||
+         (!IS_FID_DIRECTORY_FILE (&FileIdentifierDesc))) {
+       break;
+      }
+
+      CopyMem (
+       (VOID *)&FileIdentifierDesc,
+       (VOID *)&ParentFileIdentifierDesc,
+       sizeof (UDF_FILE_IDENTIFIER_DESCRIPTOR)
+       );
+
+      Found = TRUE;
+      continue;
+    } else if (StrCmp (String, L".") == 0) {
+      Found = TRUE;
+      continue;
+    }
+
+    //
+    // Start lookup
+    //
+    CopyMem (
+      (VOID *)&CurFileIdentifierDesc,
+      (VOID *)&FileIdentifierDesc,
+      sizeof (UDF_FILE_IDENTIFIER_DESCRIPTOR)
+      );
+
+    NextOffset = 0;
+
+    for (;;) {
+      Status = ReadDirectory (
+                          BlockIo,
+                         DiskIo,
+                         PartitionStartingLocation,
+                         PartitionLength,
+                         &CurFileIdentifierDesc,
+                         &FileIdentifierDesc,
+                         &NextOffset,
+                         &ReadDone
+                         );
+      if (EFI_ERROR (Status)) {
+       goto Exit;
+      }
+
+      if (!ReadDone) {
+       Status = EFI_NOT_FOUND;
+       goto Exit;
+      }
+
+      Status = FileIdentifierDescToFileName (
+                             &FileIdentifierDesc,
+                            &NextFileName
+                            );
+      if (EFI_ERROR (Status)) {
+       goto Exit;
+      }
+
+      //
+      // Check whether FID's File Identifier contains the expected filename
+      //
+      if (StrCmp (NextFileName, String) == 0) {
+       CopyMem (
+         (VOID *)&ParentFileIdentifierDesc,
+         (VOID *)&CurFileIdentifierDesc,
+         sizeof (UDF_FILE_IDENTIFIER_DESCRIPTOR)
+         );
+
+       Found = TRUE;
+       goto NextLookup;
+      }
+
+      if (NextFileName) {
+       FreePool ((VOID *)NextFileName);
+      }
+    }
+  }
+
+  if (Found) {
+    NewPrivFileData = AllocateZeroPool (sizeof (PRIVATE_UDF_FILE_DATA));
+    if (!NewPrivFileData) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto Exit;
+    }
+
+    CopyMem (
+      (VOID *)NewPrivFileData,
+      (VOID *)PrivFileData,
+      sizeof (PRIVATE_UDF_FILE_DATA)
+      );
+
+    if (IsRootDirectory) {
+      NewPrivFileData->AbsoluteFileName   = NULL;
+      NewPrivFileData->FileName           = NULL;
+      goto HandleRootDirectory;
+    }
+
+    FileName = FileNameSavedPointer;
+
+    NewPrivFileData->AbsoluteFileName = AllocatePool (
+                                  ((PrivFileData->AbsoluteFileName ?
+                                   StrLen (PrivFileData->AbsoluteFileName) :
+                                   0) +
+                                  StrLen (FileName)) *
+                                 sizeof (CHAR16) +
+                                 sizeof (CHAR16) +
+                                 sizeof (CHAR16)
+                                   );
+    if (!NewPrivFileData->AbsoluteFileName) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto Exit;
+    }
+
+    NewPrivFileData->AbsoluteFileName[0] = L'\0';
+    if (PrivFileData->AbsoluteFileName) {
+      StrCat (
+       NewPrivFileData->AbsoluteFileName,
+       PrivFileData->AbsoluteFileName
+       );
+      StrCat (NewPrivFileData->AbsoluteFileName, L"\\");
+    }
+
+    StrCat (NewPrivFileData->AbsoluteFileName, FileName);
+
+    NewPrivFileData->AbsoluteFileName = MangleFileName (
+                                           NewPrivFileData->AbsoluteFileName
+                                           );
+
+    FileName = NewPrivFileData->AbsoluteFileName;
+    while ((TempFileName = StrStr (FileName, L"\\"))) {
+      FileName = TempFileName + 1;
+    }
+
+    NewPrivFileData->FileName = AllocatePool (
+                                   StrLen (FileName) * sizeof (CHAR16) +
+                                  sizeof (CHAR16)
+                                   );
+
+    NewPrivFileData->FileName[0] = L'\0';
+    StrCat (NewPrivFileData->FileName, FileName);
+
+    //
+    // Find FE of the FID
+    //
+    LongAd = &FileIdentifierDesc.Icb;
+
+    Lsn = (UINT64)(PartitionStartingLocation +
+                  LongAd->ExtentLocation.LogicalBlockNumber);
+
+    Offset = Lsn * LOGICAL_BLOCK_SIZE;
+
+    //
+    // Read FE
+    //
+    Status = DiskIo->ReadDisk (
+                         DiskIo,
+                        BlockIo->Media->MediaId,
+                        Offset,
+                        sizeof (UDF_FILE_ENTRY),
+                        (VOID *)&FileEntry
+                         );
+    if (EFI_ERROR (Status)) {
+      goto Exit;
+    }
+
+    if (!IS_FE (&FileEntry)) {
+      Status = EFI_VOLUME_CORRUPTED;
+      goto Exit;
+    }
+
+    CopyMem (
+      (VOID *)&NewPrivFileData->File.FileEntry,
+      (VOID *)&FileEntry,
+      sizeof (UDF_FILE_ENTRY)
+      );
+    CopyMem (
+      (VOID *)&NewPrivFileData->File.FileIdentifierDesc,
+      (VOID *)&FileIdentifierDesc,
+      sizeof (UDF_FILE_IDENTIFIER_DESCRIPTOR)
+      );
+    CopyMem (
+      (VOID *)&NewPrivFileData->File.ParentFileIdentifierDesc,
+      (VOID *)&ParentFileIdentifierDesc,
+      sizeof (UDF_FILE_IDENTIFIER_DESCRIPTOR)
+      );
+
+HandleRootDirectory:
+    NewPrivFileData->IsRootDirectory   = IsRootDirectory;
+    NewPrivFileData->FilePosition      = 0;
+    NewPrivFileData->NextEntryOffset   = 0;
+
+    *NewHandle = &NewPrivFileData->FileIo;
+    Status = EFI_SUCCESS;
+  } else {
+    Status = EFI_NOT_FOUND;
+  }
+
+Exit:
+  if (String) {
+    FreePool ((VOID *)String);
+  }
+
+  gBS->RestoreTPL (OldTpl);
+
+  return Status;
 }
 
 /**
@@ -192,7 +532,35 @@ UdfClose (
   IN EFI_FILE_PROTOCOL                   *This
   )
 {
-  return EFI_SUCCESS;
+  EFI_TPL                                OldTpl;
+  EFI_STATUS                             Status;
+  PRIVATE_UDF_FILE_DATA                  *PrivFileData;
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  if (!This) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  Status = EFI_SUCCESS;
+
+  PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
+
+  if (PrivFileData->AbsoluteFileName) {
+    FreePool ((VOID *)PrivFileData->AbsoluteFileName);
+  }
+
+  if (PrivFileData->FileName) {
+    FreePool ((VOID *)PrivFileData->FileName);
+  }
+
+  FreePool ((VOID *)PrivFileData);
+
+Exit:
+  gBS->RestoreTPL (OldTpl);
+
+  return Status;
 }
 
 /**
@@ -210,6 +578,16 @@ UdfDelete (
   IN EFI_FILE_PROTOCOL  *This
   )
 {
+  PRIVATE_UDF_FILE_DATA *PrivFileData;
+
+  if (!This) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
+
+  (VOID)PrivFileData->FileIo.Close(This);
+
   return EFI_WARN_DELETE_FAILURE;
 }
 
@@ -761,3 +1139,141 @@ IsSupportedUdfVolume (
 Exit:
   return Status;
 }
+
+EFI_STATUS
+EFIAPI
+ReadDirectory (
+  IN EFI_BLOCK_IO_PROTOCOL                  *BlockIo,
+  IN EFI_DISK_IO_PROTOCOL                   *DiskIo,
+  IN UINT32                                 PartitionStartingLocation,
+  IN UINT32                                 PartitionLength,
+  IN UDF_FILE_IDENTIFIER_DESCRIPTOR         *ParentFileIdentifierDesc,
+  OUT UDF_FILE_IDENTIFIER_DESCRIPTOR        *ReadFileIdentifierDesc,
+  IN OUT UINT64                             *NextOffset,
+  OUT BOOLEAN                               *ReadDone
+  )
+{
+  EFI_STATUS                                Status;
+  UDF_LONG_ALLOCATION_DESCRIPTOR            *LongAd;
+  UINT64                                    Lsn;
+  UINT64                                    ParentOffset;
+  UINT64                                    FidLength;
+  UINT64                                    Offset;
+  UINT64                                    EndingPartitionOffset;
+
+  Status       = EFI_SUCCESS;
+  *ReadDone    = FALSE;
+
+  //
+  // Check if Parent is _really_ a directory. Otherwise, do nothing.
+  //
+  if (!IS_FID_DIRECTORY_FILE (ParentFileIdentifierDesc)) {
+    Status = EFI_NOT_FOUND;
+    goto Exit;
+  }
+
+  LongAd = &ParentFileIdentifierDesc->Icb;
+
+  //
+  // Point to the Parent FID
+  //
+  Lsn = (UINT64)(PartitionStartingLocation +
+                LongAd->ExtentLocation.LogicalBlockNumber + 1);
+
+  //
+  // Calculate offset of the Parent FID
+  //
+  ParentOffset = Lsn * LOGICAL_BLOCK_SIZE;
+
+  EndingPartitionOffset = (UINT64)((UINT64)(PartitionStartingLocation +
+                                           PartitionLength) *
+                                  LOGICAL_BLOCK_SIZE);
+
+  if (!*NextOffset) {
+    Offset = ParentOffset;
+  } else {
+    Offset = *NextOffset;
+  }
+
+  //
+  // Make sure we don't across a partition boundary
+  //
+  if (Offset > EndingPartitionOffset) {
+    goto Exit;
+  }
+
+  Status = DiskIo->ReadDisk (
+                          DiskIo,
+                         BlockIo->Media->MediaId,
+                         Offset,
+                         sizeof (UDF_FILE_IDENTIFIER_DESCRIPTOR),
+                         (VOID *)ReadFileIdentifierDesc
+                          );
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  if (!IS_FID (ReadFileIdentifierDesc)) {
+    goto Exit;
+  }
+
+  FidLength = 38 + // Offset of Implementation Use field
+    ReadFileIdentifierDesc->LengthOfFileIdentifier +
+    ReadFileIdentifierDesc->LengthOfImplementationUse +
+    (4 * ((ReadFileIdentifierDesc->LengthOfFileIdentifier +
+          ReadFileIdentifierDesc->LengthOfImplementationUse + 38 + 3) / 4) -
+     (ReadFileIdentifierDesc->LengthOfFileIdentifier +
+      ReadFileIdentifierDesc->LengthOfImplementationUse + 38));
+
+  *NextOffset   = Offset + FidLength;
+  *ReadDone     = TRUE;
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+FileIdentifierDescToFileName (
+  IN UDF_FILE_IDENTIFIER_DESCRIPTOR   *FileIdentifierDesc,
+  OUT CHAR16                          **FileName
+  )
+{
+  EFI_STATUS                          Status;
+  CHAR16                              *FileIdentifier;
+  CHAR16                              *String;
+  UINTN                               Index;
+
+  Status = EFI_SUCCESS;
+
+  *FileName = AllocatePool (
+                 FileIdentifierDesc->LengthOfFileIdentifier +
+                sizeof (CHAR16)
+                 );
+  if (!*FileName) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  //
+  // +2 == discards the Compression ID found in the File Identifier field
+  //
+  FileIdentifier = (CHAR16 *)(
+     (UINT8 *)&FileIdentifierDesc->Data +
+     FileIdentifierDesc->LengthOfImplementationUse + 2
+     );
+
+  String = *FileName;
+
+  for (Index = 2;
+       Index < FileIdentifierDesc->LengthOfFileIdentifier;
+       Index += 2
+      ) {
+    *String++ = *FileIdentifier++;
+  }
+
+  *String = '\0';
+
+Exit:
+  return Status;
+}
diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/Udf.h 
b/MdeModulePkg/Universal/Disk/UdfDxe/Udf.h
index 7986445..a2fe18e 100644
--- a/MdeModulePkg/Universal/Disk/UdfDxe/Udf.h
+++ b/MdeModulePkg/Universal/Disk/UdfDxe/Udf.h
@@ -680,6 +680,31 @@ FindFileIdentifierDescriptorRootDir (
   OUT UDF_FILE_IDENTIFIER_DESCRIPTOR         *FileIdentifierDesc
   );
 
+EFI_STATUS
+EFIAPI
+ReadDirectory (
+  IN EFI_BLOCK_IO_PROTOCOL                  *BlockIo,
+  IN EFI_DISK_IO_PROTOCOL                   *DiskIo,
+  IN UINT32                                 PartitionStartingLocation,
+  IN UINT32                                 PartitionLength,
+  IN UDF_FILE_IDENTIFIER_DESCRIPTOR         *ParentFileIdentifierDesc,
+  OUT UDF_FILE_IDENTIFIER_DESCRIPTOR        *ReadFileIdentifierDesc,
+  IN OUT UINT64                             *NextOffset,
+  OUT BOOLEAN                               *ReadDone
+  );
+
+EFI_STATUS
+EFIAPI
+FileIdentifierDescToFileName (
+  IN UDF_FILE_IDENTIFIER_DESCRIPTOR   *FileIdentifierDesc,
+  OUT UINT16                          **FileName
+  );
+
+CHAR16 *
+MangleFileName (
+  CHAR16           *FileName
+  );
+
 /**
   Test to see if this driver supports ControllerHandle. Any ControllerHandle
   than contains a BlockIo and DiskIo protocol can be supported.
diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf 
b/MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
index 538a618..dd30863 100644
--- a/MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+++ b/MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
@@ -32,6 +32,7 @@
 
 [Sources]
   ComponentName.c
+  FileName.c
   FileSystemOperations.c
   Udf.c
   Udf.h
-- 
1.9.3


------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to