/** @file
  FAT file system access routines for FAT recovery PEIM

Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<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 "FatLitePeim.h"


/**
  Check if there is a valid FAT in the corresponding Block device
  of the volume and if yes, fill in the relevant fields for the
  volume structure. Note there should be a valid Block device number
  already set.

  @param  PrivateData            Global memory map for accessing global
                                 variables.
  @param  Volume                 On input, the BlockDeviceNumber field of the
                                 Volume  should be a valid value. On successful
                                 output, all  fields except the VolumeNumber
                                 field is initialized.

  @retval EFI_SUCCESS            A FAT is found and the volume structure is
                                 initialized.
  @retval EFI_NOT_FOUND          There is no FAT on the corresponding device.
  @retval EFI_DEVICE_ERROR       There is something error while accessing device.

**/
EFI_STATUS
FatGetBpbInfo (
  IN      PEI_FAT_PRIVATE_DATA  *PrivateData,
  IN OUT  PEI_FAT_VOLUME        *Volume
  )
{
  EFI_STATUS              Status;
  PEI_FAT_BOOT_SECTOR     Bpb;
  PEI_FAT_BOOT_SECTOR_EX  BpbEx;
  UINT32                  Sectors;
  UINT32                  SectorsPerFat;
  UINT32                  RootDirSectors;
  UINT64                  FatLba;
  UINT64                  RootLba;
  UINT64                  FirstClusterLba;

  //
  // Read in the BPB
  //
  Status = FatReadDisk (
            PrivateData,
            Volume->BlockDeviceNo,
            0,
            sizeof (PEI_FAT_BOOT_SECTOR_EX),
            &BpbEx
            );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  CopyMem (
    (UINT8 *) (&Bpb),
    (UINT8 *) (&BpbEx),
    sizeof (PEI_FAT_BOOT_SECTOR)
    );

  Volume->FatType = FatUnknown;

  Sectors         = Bpb.Sectors;
  if (Sectors == 0) {
    Sectors = Bpb.LargeSectors;
  }

  SectorsPerFat = Bpb.SectorsPerFat;
  if (SectorsPerFat == 0) {
    SectorsPerFat   = BpbEx.LargeSectorsPerFat;
    Volume->FatType = Fat32;
  }
  //
  // Filter out those not a FAT
  //
  if (Bpb.Ia32Jump[0] != 0xe9 && Bpb.Ia32Jump[0] != 0xeb && Bpb.Ia32Jump[0] != 0x49) {
    return EFI_NOT_FOUND;
  }

  if (Bpb.ReservedSectors == 0 || Bpb.NoFats == 0 || Sectors == 0) {
    return EFI_NOT_FOUND;
  }

  if (Bpb.SectorsPerCluster != 1 &&
      Bpb.SectorsPerCluster != 2 &&
      Bpb.SectorsPerCluster != 4 &&
      Bpb.SectorsPerCluster != 8 &&
      Bpb.SectorsPerCluster != 16 &&
      Bpb.SectorsPerCluster != 32 &&
      Bpb.SectorsPerCluster != 64 &&
      Bpb.SectorsPerCluster != 128
      ) {
    return EFI_NOT_FOUND;
  }

  if (Volume->FatType == Fat32 && (SectorsPerFat == 0 || BpbEx.FsVersion != 0)) {
    return EFI_NOT_FOUND;
  }

  if (Bpb.Media != 0xf0 &&
      Bpb.Media != 0xf8 &&
      Bpb.Media != 0xf9 &&
      Bpb.Media != 0xfb &&
      Bpb.Media != 0xfc &&
      Bpb.Media != 0xfd &&
      Bpb.Media != 0xfe &&
      Bpb.Media != 0xff &&
      //
      // FujitsuFMR
      //
      Bpb.Media != 0x00 &&
      Bpb.Media != 0x01 &&
      Bpb.Media != 0xfa
      ) {
    return EFI_NOT_FOUND;
  }

  if (Volume->FatType != Fat32 && Bpb.RootEntries == 0) {
    return EFI_NOT_FOUND;
  }
  //
  // If this is fat32, refuse to mount mirror-disabled volumes
  //
  if (Volume->FatType == Fat32 && ((BpbEx.ExtendedFlags & 0x80) != 0)) {
    return EFI_NOT_FOUND;
  }
  //
  // Fill in the volume structure fields
  // (Sectors & SectorsPerFat is computed earlier already)
  //
  Volume->ClusterSize = Bpb.SectorSize * Bpb.SectorsPerCluster;
  Volume->RootEntries = Bpb.RootEntries;
  Volume->SectorSize  = Bpb.SectorSize;

  RootDirSectors = ((Volume->RootEntries * sizeof (FAT_DIRECTORY_ENTRY)) + (Volume->SectorSize - 1)) / Volume->SectorSize;

  FatLba                  = Bpb.ReservedSectors;
  RootLba                 = Bpb.NoFats * SectorsPerFat + FatLba;
  FirstClusterLba         = RootLba + RootDirSectors;

  Volume->VolumeSize      = MultU64x32 (Sectors, Volume->SectorSize);
  Volume->FatPos          = MultU64x32 (FatLba, Volume->SectorSize);
  Volume->RootDirPos      = MultU64x32 (RootLba, Volume->SectorSize);
  Volume->FirstClusterPos = MultU64x32 (FirstClusterLba, Volume->SectorSize);
  Volume->MaxCluster      = (UINT32) (Sectors - FirstClusterLba) / Bpb.SectorsPerCluster;
  Volume->RootDirCluster  = BpbEx.RootDirFirstCluster;

  //
  // If this is not a fat32, determine if it's a fat16 or fat12
  //
  if (Volume->FatType != Fat32) {

    if (Volume->MaxCluster >= 65525) {
      return EFI_NOT_FOUND;
    }

    Volume->FatType = Volume->MaxCluster < 4085 ? Fat12 : Fat16;
  }

  return EFI_SUCCESS;
}


/**
  Gets the next cluster in the cluster chain

  @param  PrivateData            Global memory map for accessing global variables
  @param  Volume                 The volume
  @param  Cluster                The cluster
  @param  NextCluster            The cluster number of the next cluster

  @retval EFI_SUCCESS            The address is got
  @retval EFI_INVALID_PARAMETER  ClusterNo exceeds the MaxCluster of the volume.
  @retval EFI_DEVICE_ERROR       Read disk error

**/
EFI_STATUS
FatGetNextCluster (
  IN  PEI_FAT_PRIVATE_DATA  *PrivateData,
  IN  PEI_FAT_VOLUME        *Volume,
  IN  UINT32                Cluster,
  OUT UINT32                *NextCluster
  )
{
  EFI_STATUS  Status;
  UINT64      FatEntryPos;
  UINT32      Dummy;

  *NextCluster = 0;

  if (Volume->FatType == Fat32) {
    FatEntryPos = Volume->FatPos + MultU64x32 (4, Cluster);

    Status      = FatReadDisk (PrivateData, Volume->BlockDeviceNo, FatEntryPos, 4, NextCluster);
    *NextCluster &= 0x0fffffff;

    //
    // Pad high bits for our FAT_CLUSTER_... macro definitions to work
    //
    if ((*NextCluster) >= 0x0ffffff7) {
      *NextCluster |= (-1 &~0xf);
    }

  } else if (Volume->FatType == Fat16) {
    FatEntryPos = Volume->FatPos + MultU64x32 (2, Cluster);

    Status      = FatReadDisk (PrivateData, Volume->BlockDeviceNo, FatEntryPos, 2, NextCluster);

    //
    // Pad high bits for our FAT_CLUSTER_... macro definitions to work
    //
    if ((*NextCluster) >= 0xfff7) {
      *NextCluster |= (-1 &~0xf);
    }

  } else {
    FatEntryPos = Volume->FatPos + DivU64x32Remainder (MultU64x32 (3, Cluster), 2, &Dummy);

    Status      = FatReadDisk (PrivateData, Volume->BlockDeviceNo, FatEntryPos, 2, NextCluster);

    if ((Cluster & 0x01) != 0) {
      *NextCluster = (*NextCluster) >> 4;
    } else {
      *NextCluster = (*NextCluster) & 0x0fff;
    }
    //
    // Pad high bits for our FAT_CLUSTER_... macro definitions to work
    //
    if ((*NextCluster) >= 0x0ff7) {
      *NextCluster |= (-1 &~0xf);
    }
  }

  if (EFI_ERROR (Status)) {
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;

}


/**
  Set a file's CurrentPos and CurrentCluster, then compute StraightReadAmount.

  @param  PrivateData            the global memory map
  @param  File                   the file
  @param  Pos                    the Position which is offset from the file's
                                 CurrentPos

  @retval EFI_SUCCESS            Success.
  @retval EFI_INVALID_PARAMETER  Pos is beyond file's size.
  @retval EFI_DEVICE_ERROR       Something error while accessing media.

**/
EFI_STATUS
FatSetFilePos (
  IN  PEI_FAT_PRIVATE_DATA  *PrivateData,
  IN  PEI_FAT_FILE          *File,
  IN  UINT32                Pos
  )
{
  EFI_STATUS  Status;
  UINT32      AlignedPos;
  UINT32      Offset;
  UINT32      Cluster;
  UINT32      PrevCluster;

  if (File->IsFixedRootDir) {

    if (Pos >= MultU64x32 (File->Volume->RootEntries, 32) - File->CurrentPos) {
      return EFI_INVALID_PARAMETER;
    }

    File->CurrentPos += Pos;
    File->StraightReadAmount = (UINT32) (MultU64x32 (File->Volume->RootEntries, 32) - File->CurrentPos);

  } else {

    DivU64x32Remainder (File->CurrentPos, File->Volume->ClusterSize, &Offset);
    AlignedPos = (UINT32) File->CurrentPos - (UINT32) Offset;

    while
    (
      !FAT_CLUSTER_FUNCTIONAL (File->CurrentCluster) &&
      AlignedPos + File->Volume->ClusterSize <= File->CurrentPos + Pos
    ) {
      AlignedPos += File->Volume->ClusterSize;
      Status = FatGetNextCluster (
                PrivateData,
                File->Volume,
                File->CurrentCluster,
                &File->CurrentCluster
                );
      if (EFI_ERROR (Status)) {
        return EFI_DEVICE_ERROR;
      }
    }

    if (FAT_CLUSTER_FUNCTIONAL (File->CurrentCluster)) {
      return EFI_INVALID_PARAMETER;
    }

    File->CurrentPos += Pos;
    //
    // Calculate the amount of consecutive cluster occupied by the file.
    // FatReadFile() will use it to read these blocks once.
    //
    File->StraightReadAmount  = 0;
    Cluster                   = File->CurrentCluster;
    while (!FAT_CLUSTER_FUNCTIONAL (Cluster)) {
      File->StraightReadAmount += File->Volume->ClusterSize;
      PrevCluster = Cluster;
      Status      = FatGetNextCluster (PrivateData, File->Volume, Cluster, &Cluster);
      if (EFI_ERROR (Status)) {
        return EFI_DEVICE_ERROR;
      }

      if (Cluster != PrevCluster + 1) {
        break;
      }
    }

    DivU64x32Remainder (File->CurrentPos, File->Volume->ClusterSize, &Offset);
    File->StraightReadAmount -= (UINT32) Offset;

  }

  return EFI_SUCCESS;
}


/**
  Reads file data. Updates the file's CurrentPos.

  @param  PrivateData            Global memory map for accessing global variables
  @param  File                   The file.
  @param  Size                   The amount of data to read.
  @param  Buffer                 The buffer storing the data.

  @retval EFI_SUCCESS            The data is read.
  @retval EFI_INVALID_PARAMETER  File is invalid.
  @retval EFI_DEVICE_ERROR       Something error while accessing media.

**/
EFI_STATUS
FatReadFile (
  IN  PEI_FAT_PRIVATE_DATA  *PrivateData,
  IN  PEI_FAT_FILE          *File,
  IN  UINTN                 Size,
  OUT VOID                  *Buffer
  )
{
  EFI_STATUS  Status;
  CHAR8       *BufferPtr;
  UINT32      Offset;
  UINT64      PhysicalAddr;
  UINTN       Amount;

  BufferPtr = Buffer;

  if (File->IsFixedRootDir) {
    //
    // This is the fixed root dir in FAT12 and FAT16
    //
    if (File->CurrentPos + Size > File->Volume->RootEntries * sizeof (FAT_DIRECTORY_ENTRY)) {
      return EFI_INVALID_PARAMETER;
    }

    Status = FatReadDisk (
              PrivateData,
              File->Volume->BlockDeviceNo,
              File->Volume->RootDirPos + File->CurrentPos,
              Size,
              Buffer
              );
    File->CurrentPos += (UINT32) Size;
    return Status;

  } else {

    if ((File->Attributes & FAT_ATTR_DIRECTORY) == 0) {
      Size = Size < (File->FileSize - File->CurrentPos) ? Size : (File->FileSize - File->CurrentPos);
    }
    //
    // This is a normal cluster based file
    //
    while (Size != 0) {
      DivU64x32Remainder (File->CurrentPos, File->Volume->ClusterSize, &Offset);
      PhysicalAddr  = File->Volume->FirstClusterPos + MultU64x32 (File->Volume->ClusterSize, File->CurrentCluster - 2);

      Amount        = File->StraightReadAmount;
      Amount        = Size > Amount ? Amount : Size;
      Status = FatReadDisk (
                PrivateData,
                File->Volume->BlockDeviceNo,
                PhysicalAddr + Offset,
                Amount,
                BufferPtr
                );
      if (EFI_ERROR (Status)) {
        return EFI_DEVICE_ERROR;
      }
      //
      // Advance the file's current pos and current cluster
      //
      FatSetFilePos (PrivateData, File, (UINT32) Amount);

      BufferPtr += Amount;
      Size -= Amount;
    }

    return EFI_SUCCESS;
  }
}


/**
  This function reads the next item in the parent directory and
  initializes the output parameter SubFile (CurrentPos is initialized to 0).
  The function updates the CurrentPos of the parent dir to after the item read.
  If no more items were found, the function returns EFI_NOT_FOUND.

  @param  PrivateData            Global memory map for accessing global variables
  @param  ParentDir              The parent directory.
  @param  SubFile                The File structure containing the sub file that
                                 is caught.

  @retval EFI_SUCCESS            The next sub file is obtained.
  @retval EFI_INVALID_PARAMETER  The ParentDir is not a directory.
  @retval EFI_NOT_FOUND          No more sub file exists.
  @retval EFI_DEVICE_ERROR       Something error while accessing media.

**/
EFI_STATUS
FatReadNextDirectoryEntry (
  IN  PEI_FAT_PRIVATE_DATA  *PrivateData,
  IN  PEI_FAT_FILE          *ParentDir,
  OUT PEI_FAT_FILE          *SubFile
  )
{
  EFI_STATUS          Status;
  FAT_DIRECTORY_ENTRY DirEntry;
  CHAR16              *Pos;
  CHAR16              BaseName[9];
  CHAR16              Ext[4];

  ZeroMem ((UINT8 *) SubFile, sizeof (PEI_FAT_FILE));

  //
  // Pick a valid directory entry
  //
  while (1) {
    //
    // Read one entry
    //
    Status = FatReadFile (PrivateData, ParentDir, 32, &DirEntry);
    if (EFI_ERROR (Status)) {
      return EFI_DEVICE_ERROR;
    }
    //
    // We only search for *FILE* in root directory
    // Long file name entry is *NOT* supported
    //
    if (((DirEntry.Attributes & FAT_ATTR_DIRECTORY) == FAT_ATTR_DIRECTORY) || (DirEntry.Attributes == FAT_ATTR_LFN)) {
      continue;
    }
    //
    // if this is a terminator dir entry, just return EFI_NOT_FOUND
    //
    if (DirEntry.FileName[0] == EMPTY_ENTRY_MARK) {
      return EFI_NOT_FOUND;
    }
    //
    // If this not an invalid entry neither an empty entry, this is what we want.
    // otherwise we will start a new loop to continue to find something meaningful
    //
    if ((UINT8) DirEntry.FileName[0] != DELETE_ENTRY_MARK) {
      break;
    }
  }
  //
  // fill in the output parameter
  //
  EngFatToStr (8, DirEntry.FileName, BaseName);
  EngFatToStr (3, DirEntry.FileName + 8, Ext);

  Pos = (UINT16 *) SubFile->FileName;
  SetMem ((UINT8 *) Pos, FAT_MAX_FILE_NAME_LENGTH, 0);
  CopyMem ((UINT8 *) Pos, (UINT8 *) BaseName, 2 * (StrLen (BaseName) + 1));

  if (Ext[0] != 0) {
    Pos += StrLen (BaseName);
    *Pos = '.';
    Pos++;
    CopyMem ((UINT8 *) Pos, (UINT8 *) Ext, 2 * (StrLen (Ext) + 1));
  }

  SubFile->Attributes     = DirEntry.Attributes;
  SubFile->CurrentCluster = DirEntry.FileCluster;
  if (ParentDir->Volume->FatType == Fat32) {
    SubFile->CurrentCluster |= DirEntry.FileClusterHigh << 16;
  }

  SubFile->CurrentPos       = 0;
  SubFile->FileSize         = DirEntry.FileSize;
  SubFile->StartingCluster  = SubFile->CurrentCluster;
  SubFile->Volume           = ParentDir->Volume;

  //
  // in Pei phase, time parameters do not need to be filled for minimum use.
  //
  return Status;
}
