/** 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 {
/** Reads a block of data from the block device by calling underlying Block I/O service. @param PrivateData Global memory map for accessing global variables @param BlockDeviceNo The index for the block device number. @param Lba The logic block address to read data from. @param BufferSize The size of data in byte to read. @param Buffer The buffer of the @retval EFI_DEVICE_ERROR The specified block device number exceeds the maximum device number. @retval EFI_DEVICE_ERROR The maximum address has exceeded the maximum address of the block device. **/ EFI_STATUS FatReadBlock ( IN PEI_FAT_PRIVATE_DATA *PrivateData, IN UINTN BlockDeviceNo, IN EFI_PEI_LBA Lba, IN UINTN BufferSize, OUT VOID *Buffer ) { EFI_STATUS Status; PEI_FAT_BLOCK_DEVICE *BlockDev; if (BlockDeviceNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) { return EFI_DEVICE_ERROR; } Status = EFI_SUCCESS; BlockDev = &(PrivateData->BlockDevice[BlockDeviceNo]); if (BufferSize > MultU64x32 (BlockDev->LastBlock - Lba + 1, BlockDev->BlockSize)) { return EFI_DEVICE_ERROR; } if (!BlockDev->Logical) { // // Status = BlockDev->ReadFunc // (PrivateData->PeiServices, BlockDev->PhysicalDevNo, Lba, BufferSize, Buffer); // Status = BlockDev->BlockIo->ReadBlocks ( (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (), BlockDev->BlockIo, BlockDev->PhysicalDevNo, Lba, BufferSize, Buffer ); } else { Status = FatReadDisk ( PrivateData, BlockDev->ParentDevNo, BlockDev->StartingPos + MultU64x32 (Lba, BlockDev->BlockSize), BufferSize, Buffer ); } return Status; }
/** 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; }