/*++ Copyright (c) 1992-2001 Microsoft Corporation Module Name: ifssys.cxx --*/ #include #define _NTAPI_ULIB_ #define _IFSUTIL_MEMBER_ #include "ulib.hxx" #include "ifsutil.hxx" #include "ifssys.hxx" #include "bigint.hxx" #include "wstring.hxx" #include "drive.hxx" #include "secrun.hxx" #include "hmem.hxx" #include "bpb.hxx" #include "volume.hxx" #if !defined( _EFICHECK_ ) #include "untfs2.hxx" #endif BOOLEAN IFS_SYSTEM::IsThisFat( IN BIG_INT Sectors, IN PVOID BootSectorData ) /*++ Routine Description: This routine determines if the given boot sector is a FAT boot sector. Arguments: Sectors - Supplies the number of sectors on this drive. BootSector - Supplies the boot sector data. Return Value: FALSE - This is not a FAT boot sector. TRUE - This is a FAT boot sector. --*/ { PPACKED_EXTENDED_BIOS_PARAMETER_BLOCK BootSector = (PPACKED_EXTENDED_BIOS_PARAMETER_BLOCK)BootSectorData; BOOLEAN r; USHORT bytes_per_sector, reserved_sectors, root_entries, sectors; USHORT sectors_per_fat; ULONG large_sectors; r = TRUE; DEBUG((D_INFO,(CHAR8*)"IsFAT: checking for FAT.\n")); memcpy(&bytes_per_sector, BootSector->Bpb.BytesPerSector, sizeof(USHORT)); memcpy(&reserved_sectors, BootSector->Bpb.ReservedSectors, sizeof(USHORT)); memcpy(&root_entries, BootSector->Bpb.RootEntries, sizeof(USHORT)); memcpy(§ors, BootSector->Bpb.Sectors, sizeof(USHORT)); memcpy(&large_sectors, BootSector->Bpb.LargeSectors, sizeof(ULONG)); memcpy(§ors_per_fat, BootSector->Bpb.SectorsPerFat, sizeof(USHORT)); #if defined(FE_SB) && defined(_X86_) // // 3mode PC/AT support 'I' of 'IPL1' // if (BootSector->IntelNearJumpCommand[0] != 0xeb && BootSector->IntelNearJumpCommand[0] != 0xe9 && BootSector->IntelNearJumpCommand[0] != 0x49) { // FMR 'I' of 'IPL1' #else if (BootSector->IntelNearJumpCommand[0] != 0xeb && BootSector->IntelNearJumpCommand[0] != 0xe9) { #endif r = FALSE; DEBUG((D_INFO,(CHAR8*)"IsFAT: no jmp.\n")); } else if ((bytes_per_sector != 128) && (bytes_per_sector != 256) && (bytes_per_sector != 512) && (bytes_per_sector != 1024) && (bytes_per_sector != 2048) && (bytes_per_sector != 4096)) { DEBUG((D_INFO,(CHAR8*)"IsFAT: Bytes/sector is wrong.\n")); r = FALSE; } else if ((BootSector->Bpb.SectorsPerCluster[0] != 1) && (BootSector->Bpb.SectorsPerCluster[0] != 2) && (BootSector->Bpb.SectorsPerCluster[0] != 4) && (BootSector->Bpb.SectorsPerCluster[0] != 8) && (BootSector->Bpb.SectorsPerCluster[0] != 16) && (BootSector->Bpb.SectorsPerCluster[0] != 32) && (BootSector->Bpb.SectorsPerCluster[0] != 64) && (BootSector->Bpb.SectorsPerCluster[0] != 128)) { DEBUG((D_INFO,(CHAR8*)"IsFAT: sectors/cluster is wrong.\n")); r = FALSE; } else if (reserved_sectors == 0) { DEBUG((D_INFO,(CHAR8*)"IsFAT: no resrved sectors.\n")); r = FALSE; } else if (BootSector->Bpb.Fats[0] == 0) { DEBUG((D_INFO,(CHAR8*)"IsFAT: no fats.\n")); r = FALSE; } else if (root_entries == 0) { DEBUG((D_INFO,(CHAR8*)"IsFAT: no root entries is wrong.\n")); r = FALSE; } else if (Sectors.GetHighPart() != 0) { DEBUG((D_INFO,(CHAR8*)"IsFAT: Sectors.GetHighPart() != 0.\n")); r = FALSE; } else if (sectors != 0 && sectors > Sectors.GetLowPart()) { DEBUG((D_INFO,(CHAR8*)"IsFAT: (sectors != 0 && sectors > Sectors.GetLowPart()).\n")); r = FALSE; } else if (sectors == 0 && large_sectors > Sectors.GetLowPart()) { DEBUG((D_INFO,(CHAR8*)"IsFAT: (sectors == 0 && large_sectors > Sectors.GetLowPart()).\n")); r = FALSE; } else if (sectors == 0 && large_sectors == 0) { DEBUG((D_INFO,(CHAR8*)"IsFAT: (sectors == 0 && large_sectors == 0).\n")); r = FALSE; } else if (sectors_per_fat == 0) { DEBUG((D_INFO,(CHAR8*)"IsFAT: sectors/fat is 0.\n")); r = FALSE; } DEBUG((D_INFO,(CHAR8*)"IsFAT: is it? %d.\n",r)); return r; } BOOLEAN IFS_SYSTEM::IsThisFat32( IN BIG_INT Sectors, IN PVOID BootSectorData ) /*++ Routine Description: This routine determines if the given boot sector is a FAT32 boot sector. Arguments: Sectors - Supplies the number of sectors on this drive. BootSector - Supplies the boot sector data. Return Value: FALSE - This is not a FAT32 boot sector. TRUE - This is a FAT32 boot sector. --*/ { PPACKED_EXTENDED_BIOS_PARAMETER_BLOCK BootSector = (PPACKED_EXTENDED_BIOS_PARAMETER_BLOCK)BootSectorData; BOOLEAN r; USHORT bytes_per_sector, reserved_sectors, sectors; ULONG root_entries, sectors_per_fat; ULONG large_sectors; r = TRUE; root_entries=0; memcpy(&root_entries, BootSector->Bpb.RootEntries, sizeof(USHORT)); memcpy(&bytes_per_sector, BootSector->Bpb.BytesPerSector, sizeof(USHORT)); memcpy(&reserved_sectors, BootSector->Bpb.ReservedSectors, sizeof(USHORT)); memcpy(§ors, BootSector->Bpb.Sectors, sizeof(USHORT)); memcpy(&large_sectors, BootSector->Bpb.LargeSectors, sizeof(ULONG)); memcpy(§ors_per_fat, BootSector->Bpb.BigSectorsPerFat, sizeof(ULONG)); #if defined(FE_SB) && defined(_X86_) // // 3mode PC/AT support 'I' of 'IPL1' // if (BootSector->IntelNearJumpCommand[0] != 0xeb && BootSector->IntelNearJumpCommand[0] != 0xe9 && BootSector->IntelNearJumpCommand[0] != 0x49) { // FMR 'I' of 'IPL1' #else if (BootSector->IntelNearJumpCommand[0] != 0xeb && BootSector->IntelNearJumpCommand[0] != 0xe9) { #endif DEBUG((D_INFO,(CHAR8*)"IsFAT32: No JMP.\n")); r = FALSE; } else if ((bytes_per_sector != 128) && (bytes_per_sector != 256) && (bytes_per_sector != 512) && (bytes_per_sector != 1024) && (bytes_per_sector != 2048) && (bytes_per_sector != 4096)) { DEBUG((D_INFO,(CHAR8*)"IsFAT32: Bytes/sector is wrong.\n")); r = FALSE; } else if ((BootSector->Bpb.SectorsPerCluster[0] != 1) && (BootSector->Bpb.SectorsPerCluster[0] != 2) && (BootSector->Bpb.SectorsPerCluster[0] != 4) && (BootSector->Bpb.SectorsPerCluster[0] != 8) && (BootSector->Bpb.SectorsPerCluster[0] != 16) && (BootSector->Bpb.SectorsPerCluster[0] != 32) && (BootSector->Bpb.SectorsPerCluster[0] != 64) && (BootSector->Bpb.SectorsPerCluster[0] != 128)) { DEBUG((D_INFO,(CHAR8*)"IsFAT32: Sectors/cluster is wrong.\n")); r = FALSE; } else if ( sectors_per_fat == 0 || (0 != BootSector->Bpb.SectorsPerFat[0] && 0 != BootSector->Bpb.SectorsPerFat[1]) ) { DEBUG((D_INFO,(CHAR8*)"IsThisFat32() not fat 32 sectors/fat value\n")); r = FALSE; } else { if (reserved_sectors == 0) { DEBUG((D_INFO,(CHAR8*)"IsFAT32: No reserved sectors.\n")); r = FALSE; } else if (BootSector->Bpb.Fats[0] == 0) { DEBUG((D_INFO,(CHAR8*)"IsFAT32: No FATS.\n")); r = FALSE; } else if (root_entries != 0) { DEBUG((D_INFO,(CHAR8*)"IsFAT32: root entries exist, this isn't FAT32.\n")); r = FALSE; } else if (Sectors.GetHighPart() != 0) { DEBUG((D_INFO,(CHAR8*)"IsFAT32: Sectors.GetHighPart() != 0.\n")); r = FALSE; } else if (sectors != 0 && sectors > Sectors.GetLowPart()) { DEBUG((D_INFO,(CHAR8*)"IsFAT32: sectors != 0 && sectors > Sectors.GetLowPart()\n")); r = FALSE; } else if (sectors == 0 && large_sectors > Sectors.GetLowPart()) { DEBUG((D_INFO,(CHAR8*)"IsFAT32: sectors == 0 && large_sectors(%d) > Sectors.GetLowPart()(%d)\n",large_sectors,Sectors.GetLowPart())); r = FALSE; } else if (sectors == 0 && large_sectors == 0) { DEBUG((D_INFO,(CHAR8*)"IsFAT32: both sectors and large_sectors are zero\n")); r = FALSE; } } DEBUG((D_INFO,(CHAR8*)"IsFAT32: is it? %d.\n",r)); return r; } BOOLEAN IFS_SYSTEM::IsThisHpfs( IN BIG_INT Sectors, IN PVOID BootSectorData, IN PULONG SuperBlock, IN PULONG SpareBlock ) /*++ Routine Description: This routine determines whether or not the given structures are part of an HPFS file system. Arguments: Sectors - Supplies the number of sectors on the volume. BootSector - Supplies the unaligned boot sector. SuperBlock - Supplies the super block. SpareBlock - Supplies the spare block. Return Value: FALSE - The given structures are not part on an HPFS volume. TRUE - The given structures are part of an HPFS volume. --*/ { return FALSE; } IFSUTIL_EXPORT BOOLEAN IFS_SYSTEM::IsThisNtfs( IN BIG_INT Sectors, IN ULONG SectorSize, IN PVOID BootSectorData ) /*++ Routine Description: This routine determines whether or not the given structure is part of an NTFS partition. Arguments: Sectors - Supplies the number of sectors on the drive. SectorSize - Supplies the number of bytes per sector. BootSectorData - Supplies an unaligned boot sector. Return Value: FALSE - The supplied boot sector is not part of an NTFS TRUE - The supplied boot sector is part of an NTFS volume. --*/ { return FALSE; } #define BOOTBLKSECTORS 4 typedef int DSKPACKEDBOOTSECT; BOOLEAN IsThisOfs( IN LOG_IO_DP_DRIVE * Drive, IN DSKPACKEDBOOTSECT * PackedBootSect ) { return(FALSE); } IFSUTIL_EXPORT BOOLEAN IFS_SYSTEM::QueryNtfsVersion( OUT PUCHAR Major, OUT PUCHAR Minor, IN PLOG_IO_DP_DRIVE Drive, IN PVOID BootSectorData ) /*++ Routine Description: This routine extracts the version number of the NTFS partition. Note: Caller should call IsThisNtfs() first. Arguments: Major - Receives the major version number of NTFS partition. Minor - Receives the minor version number of NTFS partition. Drive - Supplies the drive that partition is on. BootSectorData - Supplies an unaligned boot sector. Return Value: FALSE - The supplied boot sector is not part of an NTFS TRUE - The supplied boot sector is part of an NTFS volume. --*/ { return FALSE; } IFSUTIL_EXPORT BOOLEAN IFS_SYSTEM::QueryFileSystemName( IN PCWSTRING NtDriveName, OUT PWSTRING FileSystemName, OUT PNTSTATUS ErrorCode, OUT PWSTRING FileSystemNameAndVersion ) /*++ Routine Description: This routine computes the file system name for the drive specified. Arguments: NtDriveName - Supplies an NT style drive name. FileSystemName - Returns the file system name for the drive. ErrorCode - Receives an error code (if the method fails). Note that this may be NULL, in which case the exact error is not reported. FileSystemNameAndVersion - Returns the file system name and version for the drive. Return Value: FALSE - Failure. TRUE - Success. --*/ { LOG_IO_DP_DRIVE drive; HMEM bootsec_hmem; SECRUN bootsec; HMEM super_hmem; SECRUN super_secrun; HMEM spare_hmem; SECRUN spare; BOOLEAN could_be_fat; BOOLEAN could_be_hpfs; BOOLEAN could_be_ntfs; BOOLEAN could_be_ofs; ULONG num_boot_sectors; BOOLEAN first_read_failed = FALSE; DSTRING fs_name_version; if (ErrorCode) { *ErrorCode = 0; } if (FileSystemNameAndVersion == NULL) FileSystemNameAndVersion = &fs_name_version; if (!drive.Initialize(NtDriveName)) { if (ErrorCode) { *ErrorCode = drive.QueryLastNtStatus(); } return FALSE; } could_be_fat = could_be_hpfs = could_be_ntfs = could_be_ofs = TRUE; DEBUG((D_INFO,(CHAR8*)"In IFS_SYSTEM::QueryFileSystemName\n")); if (drive.QueryMediaType() == Unknown) { return FileSystemName->Initialize("RAW") && FileSystemNameAndVersion->Initialize("RAW"); } DEBUG((D_INFO,(CHAR8*)"Got Media Type. IFS_SYSTEM::QueryFileSystemName\n")); num_boot_sectors = max(1, BYTES_PER_BOOT_SECTOR/drive.QuerySectorSize()); if (!bootsec_hmem.Initialize() || !bootsec.Initialize(&bootsec_hmem, &drive, 0, num_boot_sectors)) { return FileSystemName->Initialize("RAW") && FileSystemNameAndVersion->Initialize("RAW"); } DEBUG((D_INFO,(CHAR8*)"Read Bootsec. IFS_SYSTEM::QueryFileSystemName\n")); if (!bootsec.Read()) { DEBUG((D_INFO,(CHAR8*)"Failed 1st Bootsect read. IFS_SYSTEM::QueryFileSystemName\n")); could_be_fat = could_be_hpfs = FALSE; DEBUG((D_INFO,(CHAR8*)"Not HPFS or FAT. IFS_SYSTEM::QueryFileSystemName\n")); first_read_failed = TRUE; bootsec.Relocate(drive.QuerySectors()); if (!bootsec.Read()) { DEBUG((D_INFO,(CHAR8*)"Failed 2st Bootsect read. IFS_SYSTEM::QueryFileSystemName\n")); bootsec.Relocate(drive.QuerySectors()/2); if (!bootsec.Read()) { DEBUG((D_ERROR,(CHAR8*)"Failed 3rd Bootsect read. IFS_SYSTEM::QueryFileSystemName\n")); could_be_ntfs = FALSE; DEBUG((D_INFO,(CHAR8*)"Not NTFS. IFS_SYSTEM::QueryFileSystemName\n")); } } } DEBUG((D_INFO,(CHAR8*)"Read Bootsec Success. IFS_SYSTEM::QueryFileSystemName\n")); DEBUG((D_INFO,(CHAR8*)"Check for FAT. IFS_SYSTEM::QueryFileSystemName\n")); if (could_be_fat && IsThisFat(drive.QuerySectors(), (PPACKED_EXTENDED_BIOS_PARAMETER_BLOCK)bootsec.GetBuf())) { return FileSystemName->Initialize("FAT") && FileSystemNameAndVersion->Initialize("FAT"); } DEBUG((D_INFO,(CHAR8*)"Check for FAT32. IFS_SYSTEM::QueryFileSystemName\n")); if (could_be_fat && IsThisFat32(drive.QuerySectors(), (PPACKED_EXTENDED_BIOS_PARAMETER_BLOCK)bootsec.GetBuf())) { return FileSystemName->Initialize("FAT32") && FileSystemNameAndVersion->Initialize("FAT32"); } DEBUG((D_INFO,(CHAR8*)"FS is RAW. IFS_SYSTEM::QueryFileSystemName\n")); return FileSystemName->Initialize("RAW") && FileSystemNameAndVersion->Initialize("RAW"); } IFSUTIL_EXPORT BOOLEAN IFS_SYSTEM::DosDriveNameToNtDriveName( IN PCWSTRING DosDriveName, OUT PWSTRING NtDriveName ) /*++ Routine Description: This routine converts a dos style drive name to an NT style drive name. Arguments: DosDriveName - Supplies the dos style drive name. NtDriveName - Supplies the nt style drive name. Return Value: FALSE - Failure. TRUE - Success. --*/ { WSTR buffer[80]; // EFI doesn't use ntpaths or dospaths return NtDriveName->Initialize(DosDriveName->QueryWSTR(0, TO_END,buffer, 80)); } IFSUTIL_EXPORT BOOLEAN IFS_SYSTEM::NtDriveNameToDosDriveName( IN PCWSTRING NtDriveName, OUT PWSTRING DosDriveName ) /*++ Routine Description: This routine converts an NT style drive name to a DOS style drive name. Arguments: NtDriveName - Supplies the nt style drive name. DosDriveName - Receives the dos style drive name. Return Value: FALSE - Failure. TRUE - Success. --*/ { return FALSE; } VOID IFS_SYSTEM::Reboot ( IN BOOLEAN PowerOff ) /*++ Routine Description: Reboots the machine Arguments: PowerOff -- if TRUE, we will ask the system to shut down and power off. Return Value: Only returns in case of error. --*/ { // BUGBUG we should not need this on EFI return; } PCANNED_SECURITY IFS_SYSTEM::_CannedSecurity = NULL; IFSUTIL_EXPORT PCANNED_SECURITY IFS_SYSTEM::GetCannedSecurity( ) /*++ Routine Description: This method fetches the canned security object. Arguments: None. Return Value: A pointer to the canned security object; NULL to indicate failure. --*/ { // we do not need to bother with NT security in EFI return NULL; } IFSUTIL_EXPORT BOOLEAN IFS_SYSTEM::QueryFreeDiskSpace( IN PCWSTRING DosDriveName, OUT PBIG_INT BytesFree ) /*++ Routine Description: Returns the amount of free space in a volume (in bytes). Arguments: DosDrivename - Supplies the DOS name of the drive BytesFree - Supplies the BIG_INT in which the result is returned. Return Value: BOOLEAN - TRUE if the amount of free space was obtained. --*/ { BOOLEAN Ok = FALSE; return Ok; } BOOLEAN QueryDriverName( IN PCWSTRING FileSystemName, OUT PWSTRING DriverName ) /*++ Routine Description: This routine computes the driver name corresponding to the given file system name. Arguments: FileSystemName - Supplies the name of the file system. DriverName - Returns the name of the corresponding driver. Return Value: FALSE - Failure. TRUE - Success. --*/ { DSTRING fat_name, hpfs_name; if (!fat_name.Initialize("FAT") || !hpfs_name.Initialize("HPFS")) { return FALSE; } if (!FileSystemName->Stricmp(&fat_name)) { return DriverName->Initialize("FASTFAT"); } else if (!FileSystemName->Stricmp(&hpfs_name)) { return DriverName->Initialize("PINBALL"); } return DriverName->Initialize(FileSystemName); } IFSUTIL_EXPORT BOOLEAN IFS_SYSTEM::EnableFileSystem( IN PCWSTRING FileSystemName ) /*++ Routine Description: This routine will simply return TRUE because file systems are enabled automatically due to a recent IO system change. Formerly, this routine used to enable the file system in the registry. Arguments: FileSystemName - Supplies the name of the file system to enable. Return Value: FALSE - Failure. TRUE - Success. --*/ { UNREFERENCED_PARAMETER(FileSystemName); return TRUE; } IFSUTIL_EXPORT BOOLEAN IFS_SYSTEM::IsFileSystemEnabled( IN PCWSTRING FileSystemName, OUT PBOOLEAN Error ) /*++ Routine Description: This routine will always return TRUE now that the IO system will automatically load file systems when needed. Formerly, this method used to examine the registry for this information. Argument: FileSystemName - Supplies the name of the file system. Error - Returns whether or not an error occurred. Return Value: FALSE - The file system is not enabled. TRUE - The file system is enabled. --*/ { UNREFERENCED_PARAMETER(FileSystemName); if (Error) { *Error = FALSE; } return TRUE; } IFSUTIL_EXPORT VOID IFS_SYSTEM::QueryNtfsTime( OUT PLARGE_INTEGER NtfsTime ) /*++ Routine Description: This method returns the current time in NTFS (ie. NT) format. Arguments NtfsTime -- receives the current time in NTFS format. Return Value: None. --*/ { EfiQuerySystemTime( NtfsTime ); } IFSUTIL_EXPORT ULONG IFS_SYSTEM::QueryPageSize( ) /*++ Routine Description: This method determines the page size of the system. Arguments: None. Return Value: The system page size. A return value of 0 indicates error. --*/ { // BUGBUG do I need this in EFI? return 0x1000; }