init.c

来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 818 行 · 第 1/2 页

C
818
字号
  // Acquire the lock.
  // If the caller has already acquired the lock (which
  // means we are in the process of some Fat operation),
  // we can not acquire again.
  //
  if (!FatIsLocked()) {
    LockedByMe = TRUE;
    FatAcquireLock ();
  }
  
  //
  // The volume is still being used. Hence, set error flag for all OFiles still in
  // use. In two cases, we could get here. One is EFI_MEDIA_CHANGED, the other is
  // EFI_NO_MEDIA.
  //
  if (Vol->Root) {
    FatSetVolumeError (
      Vol->Root, 
      Vol->BlkIo->Media->MediaPresent ? EFI_MEDIA_CHANGED : EFI_NO_MEDIA
      );
  }
  
  Vol->Valid = FALSE;
  
  EfiLibFreeUnicodeStringTable (Vol->ControllerNameTable);

  //
  // Release the lock.
  // If locked by me, this means DriverBindingStop is NOT 
  // called within an on-going Fat operation, so we should
  // take responsibility to cleanup and free the volume.
  // Otherwise, the DriverBindingStop is called within an on-going
  // Fat operation, we shouldn't check reference, so just let outer 
  // FatCleanupVolume do the task.
  //
  if (LockedByMe) {
    FatCleanupVolume (Vol, NULL, 0);
    FatReleaseLock ();
  }

  return EFI_SUCCESS;
}


EFI_STATUS
FatOpenDevice (
  IN OUT FAT_VOLUME           *Vol
  )
/*++

Routine Description:
  Detects FAT file system on Disk and set relevant fields of Volume
  
Arguments:
  Vol     - the volume structure

Returns:
  Status Code.
  
--*/
{
  EFI_DISK_IO_PROTOCOL        *DiskIo;
  EFI_BLOCK_IO_PROTOCOL       *BlockIo;
  EFI_BLOCK_IO_MEDIA          *BlkMedia;
  EFI_STATUS                  Status;
  UINT32                      BlockSize;
  UINT32                      MediaId;    
  FAT_BOOT_SECTOR             FatBPB;
  FAT_BOOT_SECTOR_EX          FatBPBEx;
  FAT_VOLUME_TYPE             FatType;
  UINT64                      LastBlock;
  UINTN                       RootDirSectors, RootSize, FatLba, RootLba,
                              FirstClusterLba;
  UINTN                       FsVersion, ExtendedFlags;
  BOOLEAN                     IsFat, ReadOnly;
  //BOOLEAN                     DebugThisOpen;
  
  DiskIo = Vol->DiskIo;
  BlockIo = Vol->BlkIo;
  BlkMedia = BlockIo->Media;
  //DebugThisOpen = FALSE;

  MediaId = BlkMedia->MediaId;
  BlockSize = BlkMedia->BlockSize;
  LastBlock = BlkMedia->LastBlock;
  ReadOnly = BlkMedia->ReadOnly;

  //
  // Read the FAT_BOOT_SECTOR BPB info
  // This is the only part of FAT code that uses parent DiskIo,
  // Others use FatDiskIo which utilizes a Cache.
  //
  Status = DiskIo->ReadDisk(DiskIo, MediaId, 0, sizeof(FatBPBEx), &FatBPBEx);

  if (EFI_ERROR(Status)) {
    DEBUG((EFI_D_INIT, "FATOpenDevice: read of part_lba failed %r\n", Status));
    goto Done;
  }

  //
  // The sector may be in 1 of 2 forms.  Copy the data to the fat12, fat16
  // layout
  //

  FatType = FatUndefined;
  EfiCopyMem (&FatBPB, &FatBPBEx, sizeof (FatBPB));

  //
  // Unpack BPB to aligned datum
  //

  FsVersion = FatBPBEx.FsVersion;
  ExtendedFlags = FatBPBEx.ExtendedFlags;
  Vol->SectorSize = FatBPB.SectorSize;
  Vol->SectorsPerCluster = FatBPB.SectorsPerCluster;
  Vol->ReservedSectors = FatBPB.ReservedSectors;
  Vol->NoFats = FatBPB.NoFats;
  Vol->Media = FatBPB.Media;
  Vol->ReadOnly = ReadOnly;
  Vol->RootEntries = FatBPB.RootEntries;  
  BlockSize = (UINT32)Vol->SectorSize;

  //
  // Use LargeSectors if Sectors is 0
  //
  Vol->Sectors = FatBPB.Sectors;
  if (!Vol->Sectors) {
   Vol->Sectors = FatBPB.LargeSectors;
  }

  Vol->SectorsPerFat = FatBPB.SectorsPerFat;
  if (!Vol->SectorsPerFat) {
    Vol->SectorsPerFat = FatBPBEx.LargeSectorsPerFat;
    FatType = FAT32;
  }

  //
  // Is boot sector a fat sector?
  // (Note that so far we only know if the sector is FAT32 or not, we don't
  // know if the sector is Fat16 or Fat12 until later when we can compute
  // the volume size)
  //

  IsFat = TRUE;
  if (FatBPB.Ia32Jump[0] != 0xe9  &&
    FatBPB.Ia32Jump[0] != 0xeb  &&
    FatBPB.Ia32Jump[0] != 0x49) {
      IsFat = FALSE;
  }

  if (Vol->ReservedSectors == 0     ||
    Vol->NoFats == 0              ||
    Vol->Sectors == 0) {
      IsFat = FALSE;
  }

  if (Vol->SectorsPerCluster != 1   &&
    Vol->SectorsPerCluster != 2   &&
    Vol->SectorsPerCluster != 4   &&
    Vol->SectorsPerCluster != 8   &&
    Vol->SectorsPerCluster != 16  &&
    Vol->SectorsPerCluster != 32  &&
    Vol->SectorsPerCluster != 64  &&
    Vol->SectorsPerCluster != 128) {
      IsFat = FALSE;
  }

  if (FatType == FAT32  && (Vol->SectorsPerFat == 0 || FsVersion != 0)) {
    IsFat = FALSE;
  }

  if (FatBPB.Media != 0xf0    &&
    FatBPB.Media != 0xf8    &&
    FatBPB.Media != 0xf9    &&
    FatBPB.Media != 0xfb    &&
    FatBPB.Media != 0xfc    &&
    FatBPB.Media != 0xfd    &&
    FatBPB.Media != 0xfe    &&
    FatBPB.Media != 0xff    &&
    // FujitsuFMR
    FatBPB.Media != 0x00    &&
    FatBPB.Media != 0x01    &&
    FatBPB.Media != 0xfa) {
      IsFat = FALSE;
  }

  if (FatType != FAT32 && Vol->RootEntries == 0) {
    IsFat = FALSE;
  }

  //
  // If this is fat32, refuse to mount mirror-disabled volumes
  //
  if (FatType == FAT32 && (ExtendedFlags & 0x80)) {
    IsFat = FALSE;
  }

  //
  // Was it a fat boot sector?
  //
  if (!IsFat) {
    Status = EFI_UNSUPPORTED;
    goto Done;
  }

  //
  // Initialize fields the volume information for this FatType
  //

  if (FatType != FAT32) {
    //
    // Unpack fat12, fat16 info
    //
    Vol->RootCluster = 0;

    EfiCopyMem (FatBPBEx.Id, FatBPB.Id, sizeof(FatBPB.Id));
    EfiCopyMem (FatBPBEx.FatLabel, FatBPB.FatLabel, sizeof(FatBPB.FatLabel));
    EfiCopyMem (FatBPBEx.SystemId, FatBPB.SystemId, sizeof(FatBPB.SystemId));

    //
    // fat12 & fat16 fat-entries are 2 bytes
    //
    Vol->FatEntrySize = sizeof(UINT16);

  } else {
    //  
    // Unpack fat32 info
    //
    Vol->RootCluster = FatBPBEx.RootDirFirstCluster;
    Vol->RootEntries = 0;

    //
    // fat12 & fat16 fat-entries are 2 bytes
    //
    Vol->FatEntrySize = sizeof(UINT32);
  }

  //
  // Compute some fat locations
  //
  
  RootDirSectors = 
    ((Vol->RootEntries * sizeof(FAT_DIRECTORY_ENTRY)) + (BlockSize - 1)) / 
    BlockSize;
  RootSize = RootDirSectors * BlockSize;

  FatLba = Vol->ReservedSectors;
  RootLba = Vol->NoFats * Vol->SectorsPerFat + FatLba;
  FirstClusterLba = RootLba + RootDirSectors;

  Vol->VolSize = DriverLibMultU64x32(Vol->Sectors, BlockSize);
  Vol->FatPos = FatLba * BlockSize;
  Vol->FatSize = Vol->SectorsPerFat * BlockSize;
  Vol->RootPos = DriverLibMultU64x32(RootLba, BlockSize);
  Vol->FirstClusterPos = DriverLibMultU64x32(FirstClusterLba, BlockSize);
  Vol->MaxCluster = (Vol->Sectors - FirstClusterLba) / Vol->SectorsPerCluster;
  Vol->ClusterSize = Vol->SectorsPerCluster * BlockSize;

  //
  // If this is not a fat32, determine if it's a fat16 or fat12
  //

  if (FatType != FAT32) {
    if (Vol->MaxCluster >= 65525) {
      Status = EFI_VOLUME_CORRUPTED;
      goto Done;
    }    
    FatType = Vol->MaxCluster < 4085 ? FAT12 : FAT16;
  } else {
    if (Vol->MaxCluster < 65525) {
      Status = EFI_VOLUME_CORRUPTED;
      goto Done;
    }    
  }

  //
  // Get the DirtyValue and NotDirtyValue
  // We should keep the initial value as the NotDirtyValue
  // in case the volume is dirty already
  //
  if (FatType == FAT16) {
    Status = DiskIo->ReadDisk(
            DiskIo, 
            MediaId, 
            Vol->FatPos + 2, 
            2, 
            &Vol->NotDirtyValue
            );
    if (EFI_ERROR(Status)) {
      goto Done;
    }
    Vol->DirtyValue = Vol->NotDirtyValue & 0x7fff;
    
    if (Vol->DirtyValue == Vol->NotDirtyValue) {
      Vol->FatDirty = TRUE;
    }    
  } else if (FatType == FAT32) {
    Status = DiskIo->ReadDisk(
            DiskIo, 
            MediaId, 
            Vol->FatPos + 4, 
            4, 
            &Vol->NotDirtyValue
            );
    if (EFI_ERROR(Status)) {
      goto Done;
    }
    Vol->DirtyValue = Vol->NotDirtyValue & 0xf7ffffff;
    
    if (Vol->DirtyValue == Vol->NotDirtyValue) {
      Vol->FatDirty = TRUE;
    }
  } else {
    Vol->DirtyValue = 0xfff;
    Vol->NotDirtyValue = 0xfff;
  }
  
/*  if (DebugThisOpen) {
    DEBUG ((EFI_D_INIT, "SectorSize.: %x %x\n",  Vol->SectorSize, BlockSize));
    DEBUG ((EFI_D_INIT, "RootSize...: %x\n",  RootSize));
    DEBUG ((EFI_D_INIT, "VolSize....: %lx\n", Vol->VolSize));
    DEBUG ((EFI_D_INIT, "FatPos.....: %x\n",  Vol->FatPos));
    DEBUG ((EFI_D_INIT, "FatSize....: %x\n",  Vol->FatSize));
    DEBUG ((EFI_D_INIT, "RootPos....: %lx\n", Vol->RootPos));
    DEBUG ((EFI_D_INIT, "FirstClust.: %lx\n", Vol->FirstClusterPos));
    DEBUG ((EFI_D_INIT, "MaxCluster.: %x\n",  Vol->MaxCluster));
    DEBUG ((EFI_D_INIT, "ClusterSize: %x\n",  Vol->ClusterSize));
    DEBUG ((EFI_D_INIT, "LastBlock..: %x\n",  LastBlock));

    DEBUG ((EFI_D_INIT, "Ia32Jump...: %x\n",  FatBPBEx.Ia32Jump[0]));
    DEBUG ((EFI_D_INIT, "ReservedSec: %x\n",  Vol->ReservedSectors));

    DEBUG ((EFI_D_INIT, "OemId......: '%.*a'\n", 
          sizeof(FatBPBEx.OemId), FatBPBEx.OemId));
    DEBUG ((EFI_D_INIT, "FatLabel...: '%.*a'\n", 
          sizeof(FatBPBEx.FatLabel), FatBPBEx.FatLabel));
    DEBUG ((EFI_D_INIT, "SystemId...: '%.*a'\n",
          sizeof(FatBPBEx.SystemId), FatBPBEx.SystemId));
  }
*/
  //
  // If present, read the fat hint info
  //

  if (FatType == FAT32 && Vol->FreeInfoValid == FALSE) {

    Vol->FreeInfoPos = FatBPBEx.FsInfoSector * Vol->SectorSize;

    if (Vol->FreeInfoPos) {

      DiskIo->ReadDisk(
            DiskIo, 
            MediaId, 
            Vol->FreeInfoPos, 
            sizeof(FAT_INFO_SECTOR), 
            &Vol->FatInfoSector
            );
      if (Vol->FatInfoSector.Signature          == FAT_INFO_SIGNATURE &&
        Vol->FatInfoSector.InfoBeginSignature == FAT_INFO_BEGIN_SIGNATURE &&
        Vol->FatInfoSector.InfoEndSignature   == FAT_INFO_END_SIGNATURE) {

        if ( 0 <= (INT32)(Vol->FatInfoSector.FreeInfo.ClusterCount)
            && Vol->FatInfoSector.FreeInfo.ClusterCount <= Vol->MaxCluster ) {
          Vol->FreeInfoValid = TRUE;
        }       
        
        if ( 2 > Vol->FatInfoSector.FreeInfo.NextCluster
            || Vol->FatInfoSector.FreeInfo.NextCluster > Vol->MaxCluster + 1 ) {
          Vol->FatInfoSector.FreeInfo.NextCluster = 2;
        }       
          
      } else {
        EfiZeroMem (&Vol->FatInfoSector, sizeof (Vol->FatInfoSector));
        Vol->FreeInfoPos = 0;
      }
    }
  }
  
  //
  // Just make up a FreeInfo.NextCluster for use by allocate cluster
  //
  if ( Vol->FreeInfoValid == FALSE &&
     ( 2 > Vol->FatInfoSector.FreeInfo.NextCluster
       || Vol->FatInfoSector.FreeInfo.NextCluster > Vol->MaxCluster + 1 ) ) {
    Vol->FatInfoSector.FreeInfo.NextCluster = 2;
  }
  
  //
  // We are now in sync with the media id
  //

  Vol->BlockSize = BlockSize;
  Vol->MediaId = MediaId;
  Vol->FatType = FatType;

  Status = EFI_SUCCESS;
Done:
/*  if (DebugThisOpen) {
    DEBUG ((EFI_D_INIT, "FatOpenDevice: done - %r\n", Status));
  }
*/
  if (EFI_ERROR(Status)) {
    if (Vol->Valid) {
      BlockIo->FlushBlocks (BlockIo);
    }
  }
  return Status;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?