Ejemplo n.º 1
0
/**
  Get the headers (dos, image, optional header) from an image

  @param  Device                SimpleFileSystem device handle
  @param  FileName              File name for the image
  @param  DosHeader             Pointer to dos header
  @param  Hdr                   The buffer in which to return the PE32, PE32+, or TE header.

  @retval EFI_SUCCESS           Successfully get the machine type.
  @retval EFI_NOT_FOUND         The file is not found.
  @retval EFI_LOAD_ERROR        File is not a valid image file.

**/
EFI_STATUS
EFIAPI
BdsLibGetImageHeader (
  IN  EFI_HANDLE                  Device,
  IN  CHAR16                      *FileName,
  OUT EFI_IMAGE_DOS_HEADER        *DosHeader,
  OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr
  )
{
  EFI_STATUS                       Status;
  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Volume;
  EFI_FILE_HANDLE                  Root;
  EFI_FILE_HANDLE                  ThisFile;
  UINTN                            BufferSize;
  UINT64                           FileSize;
  EFI_FILE_INFO                    *Info;

  Root     = NULL;
  ThisFile = NULL;
  //
  // Handle the file system interface to the device
  //
  Status = gBS->HandleProtocol (
                  Device,
                  &gEfiSimpleFileSystemProtocolGuid,
                  (VOID *) &Volume
                  );
  if (EFI_ERROR (Status)) {
    goto Done;
  }

  Status = Volume->OpenVolume (
                     Volume,
                     &Root
                     );
  if (EFI_ERROR (Status)) {
    Root = NULL;
    goto Done;
  }
//  ASSERT (Root != NULL);
  Status = Root->Open (Root, &ThisFile, FileName, EFI_FILE_MODE_READ, 0);
  if (EFI_ERROR (Status)) {
    goto Done;
  }
 // ASSERT (ThisFile != NULL);

  //
  // Get file size
  //
  BufferSize  = SIZE_OF_EFI_FILE_INFO + 200;
  do {
    Info   = NULL;
    Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, (VOID **) &Info);
    if (EFI_ERROR (Status)) {
      goto Done;
    }
    Status = ThisFile->GetInfo (
                         ThisFile,
                         &gEfiFileInfoGuid,
                         &BufferSize,
                         Info
                         );
    if (!EFI_ERROR (Status)) {
      break;
    }
    if (Status != EFI_BUFFER_TOO_SMALL) {
      FreePool (Info);
      goto Done;
    }
    FreePool (Info);
  } while (TRUE);

  FileSize = Info->FileSize;
  FreePool (Info);

  //
  // Read dos header
  //
  BufferSize = sizeof (EFI_IMAGE_DOS_HEADER);
  Status = ThisFile->Read (ThisFile, &BufferSize, DosHeader);
  if (EFI_ERROR (Status) ||
      BufferSize < sizeof (EFI_IMAGE_DOS_HEADER) ||
      FileSize <= DosHeader->e_lfanew ||
      DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
    Status = EFI_LOAD_ERROR;
    goto Done;
  }

  //
  // Move to PE signature
  //
  Status = ThisFile->SetPosition (ThisFile, DosHeader->e_lfanew);
  if (EFI_ERROR (Status)) {
    Status = EFI_LOAD_ERROR;
    goto Done;
  }

  //
  // Read and check PE signature
  //
  BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);
  Status = ThisFile->Read (ThisFile, &BufferSize, Hdr.Pe32);
  if (EFI_ERROR (Status) ||
      BufferSize < sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION) ||
      Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
    Status = EFI_LOAD_ERROR;
    goto Done;
  }

  //
  // Check PE32 or PE32+ magic
  //
  if (Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC &&
      Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
    Status = EFI_LOAD_ERROR;
    goto Done;
  }

 Done:
  if (ThisFile != NULL) {
    ThisFile->Close (ThisFile);
  }
  if (Root != NULL) {
    Root->Close (Root);
  }
  return Status;
}
Ejemplo n.º 2
0
CHAR16 *
GetFileNameUnderDir (
  IN  EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
  IN  CHAR16                      *DirName,
  IN  CHAR16                      *FileName,
  IN OUT UINTN                    *Index
  )
/*++

Routine Description:

  Get file name under this dir with index
  
Arguments:

  DebuggerPrivate - EBC Debugger private data structure
  DirName         - The dir to be read.
  FileName        - The file name pattern under this dir
  Index           - The file index under this dir

Returns:

  File Name which match the pattern and index.

--*/
{
  EFI_STATUS                        Status;
  EFI_FILE_HANDLE                   RootDir;
  EFI_FILE_HANDLE                   Handle;
  UINTN                             FileInfoSize;
  EFI_FILE_INFO                     *FileInfo;
  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
  VOID                              *TempName;
  UINTN                             FileIndex;

  if (DebuggerPrivate->Vol == NULL) {
    Status = gBS->LocateProtocol (
                    &gEfiSimpleFileSystemProtocolGuid,
                    NULL,
                    &DebuggerPrivate->Vol
                    );
    if (EFI_ERROR(Status)) {
      return NULL;
    }
  }
  Vol = DebuggerPrivate->Vol;

  //
  // Open the root directory
  //
  Status = Vol->OpenVolume (Vol, &RootDir);
  if (EFI_ERROR (Status)) {
    return NULL;
  }

  //
  // Open the file
  //
  Status = RootDir->Open (
                      RootDir,
                      &Handle,
                      DirName,
                      EFI_FILE_MODE_READ,
                      EFI_FILE_DIRECTORY
                      );
  if (EFI_ERROR (Status)) {
    RootDir->Close (RootDir);
    return NULL;
  }
  RootDir->Close (RootDir);

  //
  // Set Dir Position
  //
  Status = Handle->SetPosition (Handle, 0);
  if (EFI_ERROR (Status)) {
    Handle->Close (Handle);
    return NULL;
  }

  //
  // Get the file information
  //
  FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;

  FileInfo = EfiLibAllocateZeroPool (FileInfoSize);
  if (FileInfo == NULL) {
    Handle->Close (Handle);
    return NULL;
  }

  //
  // Walk through each file in the directory
  //
  FileIndex = 0;
  TempName = NULL;
  while (TRUE) {
    //
    // Read a file entry
    //
    FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;

    Status = Handle->Read (
                       Handle,
                       &FileInfoSize,
                       FileInfo
                       );
    if (EFI_ERROR (Status) || (FileInfoSize == 0)) {
      break;
    }

    if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == 0) {
      //
      // This is a file
      //

      //
      // Only deal with the EFI key file
      //
      if (!StrEndWith (FileInfo->FileName, FileName)) {
        continue;
      }

      if (FileIndex == *Index) {
        TempName = StrDuplicate (FileInfo->FileName);
        *Index = *Index + 1;
        break;
      }
      FileIndex ++;
    }
  }

  //
  // Free resources
  //
  gBS->FreePool (FileInfo);
  Handle->Close (Handle);

  return TempName;
}
Ejemplo n.º 3
0
EFI_STATUS
EFIAPI
TOLOpen (
    IN EFI_TEST_OUTPUT_LIBRARY_PROTOCOL       *This,
    IN EFI_DEVICE_PATH_PROTOCOL               *DevicePath,
    IN CHAR16                                 *FileName,
    IN BOOLEAN                                OverwriteFile,
    OUT EFI_FILE                              **FileHandle
)
/*++

Routine Description:

  One interface function of the TestOutputLibrary to open a file.

Arguments:

  This                  - the protocol instance structure.
  DevicePath            - the file's root device path.
  FileName              - the file's name relative to the root.
  OverwriteFile         - whether to overwrite the file.
  FileHandle            - return the file's handle.

Returns:

  EFI_SUCCESS           - open the file successfully.
  EFI_NOT_READY         - to overwrite an opened file is not allowed.
  EFI_OUT_OF_RESOURCES  - not enough memory.

--*/
{
    EFI_STATUS                        Status;
    TEST_OUTPUT_FILE                  *OutputFile;
    TEST_OUTPUT_PRIVATE_DATA          *Private;
    EFI_HANDLE                        DeviceHandle;
    EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
    EFI_FILE_HANDLE                   RootDir;
    EFI_FILE_HANDLE                   Handle;
    UINTN                             BufSize;
    CHAR8                             Buffer[2];
    EFI_DEVICE_PATH_PROTOCOL          *PreDevicePath;

    Private = TEST_OUTPUT_PRIVATE_DATA_FROM_THIS (This);

    //
    // Search the file in OutputFileList to see whether the file has been opened
    //
    OutputFile = Private->OutputFileList;
    while (OutputFile != NULL) {
        if ((SctDevicePathCompare (DevicePath, OutputFile->DevicePath) == 0) &&
                (StrCmp (FileName, OutputFile->FileName)                   == 0)) {
            break;
        }
        OutputFile = OutputFile->Next;
    }

    if (OutputFile == NULL) {
        //
        // Not found, open the file and add to the list
        //

        PreDevicePath = DevicePath;
        //
        //  Determine device handle for fs protocol on specified device path
        //
        Status = BS->LocateDevicePath (
                     &gEfiSimpleFileSystemProtocolGuid,
                     &PreDevicePath,
                     &DeviceHandle
                 );
        if (EFI_ERROR (Status)) {
            return Status;
        }

        //
        //  Determine volume for file system on device handle
        //
        Status = BS->HandleProtocol (
                     DeviceHandle,
                     &gEfiSimpleFileSystemProtocolGuid,
                     (VOID*)&Vol
                 );
        if (EFI_ERROR (Status)) {
            return Status;
        }

        //
        // Open volume for file system on device path
        //
        Status = Vol->OpenVolume (Vol, &RootDir);
        if (EFI_ERROR (Status)) {
            return Status;
        }

        //
        // Determine the existence of the file
        //
        Status = RootDir->Open (
                     RootDir,
                     &Handle,
                     FileName,
                     EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ,
                     0
                 );
        if (Status == EFI_NOT_FOUND) {
            //
            // The file not exist, create it
            //
            Status = SctCreateFile (RootDir, FileName, &Handle);
            if (EFI_ERROR (Status)) {
                RootDir->Close (RootDir);
                return Status;
            }

            //
            // Write the head of Unicode text file
            //
            Buffer[0] = 0xff;
            Buffer[1] = 0xfe;
            BufSize = 2;
            Status = Handle->Write (Handle, &BufSize, Buffer);
            if (EFI_ERROR (Status)) {
                Handle->Close (Handle);
                return Status;
            }
        } else if (EFI_ERROR (Status)) {
            RootDir->Close(RootDir);
            return Status;
        }

        if (OverwriteFile) {
            //
            // Overwrite the file
            //

            //
            // Delete the file
            //
            Status = Handle->Delete (Handle);

            //
            // EFI_FILE.Delete() return a warning status
            //
            if (Status != EFI_SUCCESS) {
                RootDir->Close (RootDir);
                return EFI_UNSUPPORTED;
            }

            //
            // Recreate the file
            //
            Status = RootDir->Open (
                         RootDir,
                         &Handle,
                         FileName,
                         EFI_FILE_MODE_CREATE|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ,
                         0
                     );
            if (EFI_ERROR (Status)) {
                RootDir->Close (RootDir);
                return Status;
            }

            //
            // Write the head of Unicode text file
            //
            Buffer[0] = 0xff;
            Buffer[1] = 0xfe;
            BufSize = 2;
            Status = Handle->Write (Handle, &BufSize, Buffer);
            if (EFI_ERROR (Status)) {
                Handle->Close (Handle);
                return Status;
            }
        } else {
            //
            // Append the file
            //

            //
            // Set position to the end of file
            //
            Status = Handle->SetPosition (Handle, (UINT64)-1);
            if (EFI_ERROR (Status)) {
                RootDir->Close (RootDir);
                return Status;
            }
        }
        RootDir->Close (RootDir);

        //
        // Add the opened file to the OutputFileList
        //
        Status = BS->AllocatePool (
                     EfiBootServicesData,
                     sizeof(TEST_OUTPUT_FILE),
                     (VOID **)&OutputFile
                 );
        if (EFI_ERROR (Status)) {
            Handle->Close (Handle);
            return Status;
        }
        ZeroMem (OutputFile, sizeof(TEST_OUTPUT_FILE));

        OutputFile->DevicePath = DuplicateDevicePath (DevicePath);
        if (OutputFile->DevicePath == NULL) {
            Handle->Close (Handle);
            BS->FreePool (OutputFile);
            return EFI_OUT_OF_RESOURCES;
        }
        OutputFile->FileName = StrDuplicate (FileName);
        if (OutputFile->FileName == NULL) {
            Handle->Close (Handle);
            BS->FreePool (OutputFile->DevicePath);
            BS->FreePool (OutputFile);
            return EFI_OUT_OF_RESOURCES;
        }

        OutputFile->FileHandle = Handle;
        OutputFile->Next = Private->OutputFileList;
        Private->OutputFileList = OutputFile;
    }

    //
    // Add the open count and return the file handle
    //
    OutputFile->OpenCount ++;
    *FileHandle = OutputFile->FileHandle;

    return EFI_SUCCESS;
}
Ejemplo n.º 4
0
EFI_STATUS
BOpt_FindFiles (
  IN BMM_CALLBACK_DATA          *CallbackData,
  IN BM_MENU_ENTRY              *MenuEntry
  )
/*++

Routine Description
  Find files under current directory
  All files and sub-directories in current directory
  will be stored in DirectoryMenu for future use.

Arguments:
  FileOption   -- Pointer for Dir to explore

Returns:
  TRUE         -- Get files from current dir successfully
  FALSE        -- Can't get files from current dir

--*/
{
  EFI_FILE_HANDLE NewDir;
  EFI_FILE_HANDLE Dir;
  EFI_FILE_INFO   *DirInfo;
  UINTN           BufferSize;
  UINTN           DirBufferSize;
  BM_MENU_ENTRY   *NewMenuEntry;
  BM_FILE_CONTEXT *FileContext;
  BM_FILE_CONTEXT *NewFileContext;
  UINTN           Pass;
  EFI_STATUS      Status;
  UINTN           OptionNumber;

  FileContext   = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
  Dir           = FileContext->FHandle;
  OptionNumber  = 0;
  //
  // Open current directory to get files from it
  //
  Status = Dir->Open (
                  Dir,
                  &NewDir,
                  FileContext->FileName,
                  EFI_FILE_READ_ONLY,
                  0
                  );
  if (!FileContext->IsRoot) {
    Dir->Close (Dir);
  }

  if (EFI_ERROR (Status)) {
    return Status;
  }

  DirInfo = EfiLibFileInfo (NewDir);
  if (!DirInfo) {
    return EFI_NOT_FOUND;
  }

  if (!(DirInfo->Attribute & EFI_FILE_DIRECTORY)) {
    return EFI_INVALID_PARAMETER;
  }

  FileContext->DevicePath = EfiFileDevicePath (
                              FileContext->Handle,
                              FileContext->FileName
                              );

  DirBufferSize = sizeof (EFI_FILE_INFO) + 1024;
  DirInfo       = EfiAllocateZeroPool (DirBufferSize);
  if (!DirInfo) {
    return EFI_OUT_OF_RESOURCES;
  }
  //
  // Get all files in current directory
  // Pass 1 to get Directories
  // Pass 2 to get files that are EFI images
  //
  for (Pass = 1; Pass <= 2; Pass++) {
    NewDir->SetPosition (NewDir, 0);
    for (;;) {
      BufferSize  = DirBufferSize;
      Status      = NewDir->Read (NewDir, &BufferSize, DirInfo);
      if (EFI_ERROR (Status) || BufferSize == 0) {
        break;
      }

      if ((DirInfo->Attribute & EFI_FILE_DIRECTORY && Pass == 2) ||
          (!(DirInfo->Attribute & EFI_FILE_DIRECTORY) && Pass == 1)
          ) {
        //
        // Pass 1 is for Directories
        // Pass 2 is for file names
        //
        continue;
      }

      if (!(BOpt_IsEfiImageName (DirInfo->FileName) || DirInfo->Attribute & EFI_FILE_DIRECTORY)) {
        //
        // Slip file unless it is a directory entry or a .EFI file
        //
        continue;
      }

      NewMenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);
      if (NULL == NewMenuEntry) {
        return EFI_OUT_OF_RESOURCES;
      }

      NewFileContext          = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;
      NewFileContext->Handle  = FileContext->Handle;
      NewFileContext->FileName = BOpt_AppendFileName (
                                  FileContext->FileName,
                                  DirInfo->FileName
                                  );
      NewFileContext->FHandle = NewDir;
      NewFileContext->DevicePath = EfiFileDevicePath (
                                    NewFileContext->Handle,
                                    NewFileContext->FileName
                                    );
      NewMenuEntry->HelpString = NULL;

      MenuEntry->DisplayStringToken = GetStringTokenFromDepository (
                                        CallbackData,
                                        FileOptionStrDepository
                                        );

      NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY);

      if (NewFileContext->IsDir) {
        BufferSize                  = EfiStrLen (DirInfo->FileName) * 2 + 6;
        NewMenuEntry->DisplayString = EfiAllocateZeroPool (BufferSize);

        SPrint (
          NewMenuEntry->DisplayString,
          BufferSize,
          L"<%s>",
          DirInfo->FileName
          );

      } else {
        NewMenuEntry->DisplayString = EfiStrDuplicate (DirInfo->FileName);
      }

      NewFileContext->IsRoot            = FALSE;
      NewFileContext->IsLoadFile        = FALSE;
      NewFileContext->IsRemovableMedia  = FALSE;

      NewMenuEntry->OptionNumber        = OptionNumber;
      OptionNumber++;
      InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link);
    }
  }

  DirectoryMenu.MenuNumber = OptionNumber;
  SafeFreePool (DirInfo);
  return EFI_SUCCESS;
}
Ejemplo n.º 5
0
BOOLEAN
BOpt_IsEfiApp (
  IN EFI_FILE_HANDLE Dir,
  IN UINT16          *FileName
  )
/*++

Routine Description:
  Check whether current FileName point to a valid Efi Application

Arguments:
  Dir       -   Pointer to current Directory
  FileName  -   Pointer to current File name.

Returns:
  TRUE      -   Is a valid Efi Application
  FALSE     -   not a valid Efi Application

--*/
{
  UINTN                       BufferSize;
  EFI_IMAGE_DOS_HEADER        DosHdr;
  EFI_IMAGE_NT_HEADERS        PeHdr;
  EFI_IMAGE_OPTIONAL_HEADER32 *PeOpt32;
  EFI_IMAGE_OPTIONAL_HEADER64 *PeOpt64;
  UINT16                      Subsystem;
  EFI_FILE_HANDLE             File;
  EFI_STATUS                  Status;

  Status = Dir->Open (Dir, &File, FileName, EFI_FILE_MODE_READ, 0);

  if (EFI_ERROR (Status)) {
    return FALSE;
  }

  BufferSize = sizeof (EFI_IMAGE_DOS_HEADER);
  File->Read (File, &BufferSize, &DosHdr);
  if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) {
    File->Close (File);
    return FALSE;
  }

  File->SetPosition (File, DosHdr.e_lfanew);
  BufferSize = sizeof (EFI_IMAGE_NT_HEADERS);
  File->Read (File, &BufferSize, &PeHdr);
  if (PeHdr.Signature != EFI_IMAGE_NT_SIGNATURE) {
    File->Close (File);
    return FALSE;
  }
  //
  // Determine PE type and read subsytem
  // BugBug : We should be using EFI_IMAGE_MACHINE_TYPE_SUPPORTED (machine)
  // macro to detect the machine type.
  // We should not be using  EFI_IMAGE_OPTIONAL_HEADER32 and
  // EFI_IMAGE_OPTIONAL_HEADER64
  //
  if (PeHdr.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
    PeOpt32   = (EFI_IMAGE_OPTIONAL_HEADER32 *) &(PeHdr.OptionalHeader);
    Subsystem = PeOpt32->Subsystem;
  } else if (PeHdr.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
    PeOpt64   = (EFI_IMAGE_OPTIONAL_HEADER64 *) &(PeHdr.OptionalHeader);
    Subsystem = PeOpt64->Subsystem;
  } else {
    return FALSE;
  }

  if (Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
    File->Close (File);
    return TRUE;
  } else {
    File->Close (File);
    return FALSE;
  }
}
/**
  Find files under the current directory. All files and sub-directories
  in current directory will be stored in DirectoryMenu for future use.

  @param[in] MenuEntry     The Menu Entry.

  @retval EFI_SUCCESS      Get files from current dir successfully.
  @return Other            Can't get files from current dir.

**/
EFI_STATUS
FindFiles (
  IN SECUREBOOT_MENU_ENTRY              *MenuEntry
  )
{
  EFI_FILE_HANDLE           NewDir;
  EFI_FILE_HANDLE           Dir;
  EFI_FILE_INFO             *DirInfo;
  UINTN                     BufferSize;
  UINTN                     DirBufferSize;
  SECUREBOOT_MENU_ENTRY     *NewMenuEntry;
  SECUREBOOT_FILE_CONTEXT   *FileContext;
  SECUREBOOT_FILE_CONTEXT   *NewFileContext;
  UINTN                     Pass;
  EFI_STATUS                Status;
  UINTN                     OptionNumber;

  FileContext   = (SECUREBOOT_FILE_CONTEXT *) MenuEntry->FileContext;
  Dir           = FileContext->FHandle;
  OptionNumber  = 0;
  //
  // Open current directory to get files from it
  //
  Status = Dir->Open (
                  Dir,
                  &NewDir,
                  FileContext->FileName,
                  EFI_FILE_READ_ONLY,
                  0
                  );
  if (!FileContext->IsRoot) {
    Dir->Close (Dir);
  }

  if (EFI_ERROR (Status)) {
    return Status;
  }

  DirInfo = FileInfo (NewDir);
  if (DirInfo == NULL) {
    return EFI_NOT_FOUND;
  }

  if ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0) {
    return EFI_INVALID_PARAMETER;
  }

  FileContext->DevicePath = FileDevicePath (
                              FileContext->Handle,
                              FileContext->FileName
                              );

  DirBufferSize = sizeof (EFI_FILE_INFO) + 1024;
  DirInfo       = AllocateZeroPool (DirBufferSize);
  if (DirInfo == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  //
  // Get all files in current directory
  // Pass 1 to get Directories
  // Pass 2 to get files that are EFI images
  //
  for (Pass = 1; Pass <= 2; Pass++) {
    NewDir->SetPosition (NewDir, 0);
    for (;;) {
      BufferSize  = DirBufferSize;
      Status      = NewDir->Read (NewDir, &BufferSize, DirInfo);
      if (EFI_ERROR (Status) || BufferSize == 0) {
        break;
      }

      if (((DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0 && Pass == 2) ||
          ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0 && Pass == 1)
          ) {
        //
        // Pass 1 is for Directories
        // Pass 2 is for file names
        //
        continue;
      }

      NewMenuEntry = CreateMenuEntry ();
      if (NULL == NewMenuEntry) {
        return EFI_OUT_OF_RESOURCES;
      }

      NewFileContext          = (SECUREBOOT_FILE_CONTEXT *) NewMenuEntry->FileContext;
      NewFileContext->Handle  = FileContext->Handle;
      NewFileContext->FileName = AppendFileName (
                                  FileContext->FileName,
                                  DirInfo->FileName
                                  );
      NewFileContext->FHandle = NewDir;
      NewFileContext->DevicePath = FileDevicePath (
                                    NewFileContext->Handle,
                                    NewFileContext->FileName
                                    );
      NewMenuEntry->HelpString = NULL;

      NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY);
      if (NewFileContext->IsDir) {
        BufferSize = StrLen (DirInfo->FileName) * 2 + 6;
        NewMenuEntry->DisplayString = AllocateZeroPool (BufferSize);

        UnicodeSPrint (
          NewMenuEntry->DisplayString,
          BufferSize,
          L"<%s>",
          DirInfo->FileName
          );

      } else {
        NewMenuEntry->DisplayString = StrDuplicate (DirInfo->FileName);
      }

      NewFileContext->IsRoot            = FALSE;
      NewFileContext->IsLoadFile        = FALSE;
      NewFileContext->IsRemovableMedia  = FALSE;

      NewMenuEntry->OptionNumber        = OptionNumber;
      OptionNumber++;
      InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link);
    }
  }

  DirectoryMenu.MenuNumber = OptionNumber;
  FreePool (DirInfo);
  return EFI_SUCCESS;
}
Ejemplo n.º 7
0
/**
  Get the headers (dos, image, optional header) from an image

  @param  Device                SimpleFileSystem device handle
  @param  FileName              File name for the image
  @param  DosHeader             Pointer to dos header
  @param  Hdr                   The buffer in which to return the PE32, PE32+, or TE header.

  @retval EFI_SUCCESS           Successfully get the machine type.
  @retval EFI_NOT_FOUND         The file is not found.
  @retval EFI_LOAD_ERROR        File is not a valid image file.

**/
EFI_STATUS
EFIAPI
BdsLibGetImageHeader (
  IN  EFI_HANDLE                  Device,
  IN  CHAR16                      *FileName,
  OUT EFI_IMAGE_DOS_HEADER        *DosHeader,
  OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr,
  IN OUT  CHAR16                      **NewFileName
  )
{
  EFI_STATUS                       Status;
  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Volume;
  EFI_FILE_HANDLE                  Root;
  EFI_FILE_HANDLE                  ThisFile;
  UINTN                            BufferSize;
  UINT64                           FileSize;
  EFI_FILE_INFO                    *Info;
  CHAR16                           *FileName0 = NULL; /*application's file*/

  Root     = NULL;
  ThisFile = NULL;
  //
  // Handle the file system interface to the device
  //
  Status = gBS->HandleProtocol (
                  Device,
                  &gEfiSimpleFileSystemProtocolGuid,
                  (VOID *) &Volume
                  );
  if (EFI_ERROR (Status)) {
    goto Done;
  }

  Status = Volume->OpenVolume (
                     Volume,
                     &Root
                     );
  if (EFI_ERROR (Status)) {
    Root = NULL;
    goto Done;
  }

  Status = Root->Open (Root, &ThisFile, FileName, EFI_FILE_MODE_READ, 0);
  DEBUG((DEBUG_INFO, "%a:%d Open FileName:'%s' - %r \n", __FILE__, __LINE__, FileName, Status));
  if (EFI_ERROR (Status)) {
    goto Done;
  }

  //
  // Get file size
  //
  do {
    BufferSize  = 0;
    Info   = NULL;
    /* Get right size we need to allocate */
    Status = ThisFile->GetInfo (
                         ThisFile,
                         &gEfiFileInfoGuid,
                         &BufferSize,
                         Info
                         );
    if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL)
    {
        goto Done;
    }
    Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, (VOID **) &Info);
    if (EFI_ERROR (Status)) {
      goto Done;
    }
    Status = ThisFile->GetInfo (
                         ThisFile,
                         &gEfiFileInfoGuid,
                         &BufferSize,
                         Info
                         );
    if (!EFI_ERROR (Status)) {
      DEBUG((DEBUG_INFO, "%a:%d Open FileName:%s from Info %r \n", __FILE__, __LINE__, Info->FileName, Status));
      Status = gBS->AllocatePool (EfiBootServicesData, StrLen(Info->FileName), (VOID **) &FileName0);
      StrCpy(FileName0, Info->FileName);
      if (EFI_ERROR (Status)) {
        goto Done;
      }
      break;
    }
    if (Status != EFI_BUFFER_TOO_SMALL) {
      FreePool (Info);
      goto Done;
    }
    FreePool (Info);
  } while (TRUE);

  FileSize = Info->FileSize;
  FreePool (Info);

  //
  // Read dos header
  //
#ifndef VBOX
  BufferSize = sizeof (EFI_IMAGE_DOS_HEADER);
  Status = ThisFile->Read (ThisFile, &BufferSize, DosHeader);
  if (EFI_ERROR (Status) ||
      BufferSize < sizeof (EFI_IMAGE_DOS_HEADER) ||
      FileSize <= DosHeader->e_lfanew ||
      DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
    Status = EFI_LOAD_ERROR;
    goto Done;
  }

  //
  // Move to PE signature
  //
  Status = ThisFile->SetPosition (ThisFile, DosHeader->e_lfanew);
  if (EFI_ERROR (Status)) {
    Status = EFI_LOAD_ERROR;
    goto Done;
  }

  //
  // Read and check PE signature
  //
  BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);
  Status = ThisFile->Read (ThisFile, &BufferSize, Hdr.Pe32);
  if (EFI_ERROR (Status) ||
      BufferSize < sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION) ||
      Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
    Status = EFI_LOAD_ERROR;
    goto Done;
  }

  //
  // Check PE32 or PE32+ magic
  //
  if (Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC &&
      Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
    Status = EFI_LOAD_ERROR;
    goto Done;
  }
#endif
 Done:
  if (!EFI_ERROR(Status))
  {
    EFI_STATUS Status0;
    /* We need prepare the correct file path for case sensitive loaders ... Sigh.*/
    CHAR16 *dup;
    CHAR16 *p, *pp;
    dup = AllocateZeroPool(StrSize(FileName));
    StrCpy(dup, FileName);
    pp = p = dup;
    while (*p != L'\0')
    {
        BufferSize  = 0;
        Info   = NULL;
        if (*p == L'\\' && p != dup)
        {
            *p = L'\0';
            Status0 = Root->Open (Root, &ThisFile, dup, EFI_FILE_MODE_READ, 1);
            DEBUG((DEBUG_INFO, "%a:%d Open FileName:%s - %r \n", __FILE__, __LINE__, dup, Status));
            if (EFI_ERROR (Status)) {
              goto Done;
            }
            /* Get right size we need to allocate */
            Status0 = ThisFile->GetInfo (
                                 ThisFile,
                                 &gEfiFileInfoGuid,
                                 &BufferSize,
                                 Info
                                 );
            if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL)
            {
                DEBUG((DEBUG_INFO, "%a:%d GetInfo(1) FileName:%s %r \n", __FILE__, __LINE__, FileName, Status));
                goto Done;
            }
            Status0 = gBS->AllocatePool (EfiBootServicesData, BufferSize, (VOID **) &Info);
            if (EFI_ERROR (Status)) {
              goto Done;
            }
            Status0 = ThisFile->GetInfo (
                                 ThisFile,
                                 &gEfiFileInfoGuid,
                                 &BufferSize,
                                 Info
                                 );
            if (!EFI_ERROR (Status0)) {
              DEBUG((DEBUG_INFO, "%a:%d Open FileName:%s from Info %r \n", __FILE__, __LINE__, Info->FileName, Status));
              StrCpy(pp + 1, Info->FileName);
            }
            * p = L'\\';
            pp = p;
        }
        p++;
    }
    StrCpy(pp + 1, FileName0);
    DEBUG((DEBUG_INFO, "%a:%d NewFileName:'%s'\n", __FILE__, __LINE__, dup));
    *NewFileName = dup;
  }
  DEBUG((DEBUG_INFO, "%a:%d %s - %r\n", __FILE__, __LINE__, FileName, Status));
  if (ThisFile != NULL) {
    ThisFile->Close (ThisFile);
  }
  if (Root != NULL) {
    Root->Close (Root);
  }
  return Status;
}