NTLDR源代码分析之从GetSector函数到blread函数
NTLDR源代码分析之从GetSector函数到blread函数
;++
;
; Name:
;
; GetSector
;
; Description:
;
; Reads the requested number of sectors from the specified drive into
; the specified buffer.
;
; Arguments:
;
; ULONG Virtual address into which to read data
; ULONG Number of sectors to read
; ULONG Physical sector number
; ULONG Drive Number
; ULONG Function Number
; TOS -> ULONG Flat return address (must be used with KeCodeSelector)
;
;--
EXPORT_ENTRY_MACRO GetSector
;
; Move the arguments from the caller's 32bit stack to the SU module's
; 16bit stack.
;
MAKE_STACK_FRAME_MACRO <GetSectorFrame>, ebx
;
; Go into real mode. We still have the same stack and sp
; but we'll be executing in realmode.
;
ENTER_REALMODE_MACRO
ARC_STATUS
XferPhysicalDiskSectors(
IN UCHAR Int13UnitNumber,
IN ULONGLONG StartSector,
IN UCHAR SectorCount,
IN PUCHAR Buffer,
IN UCHAR SectorsPerTrack,
IN USHORT Heads,
IN USHORT Cylinders,
IN BOOLEAN AllowExtendedInt13,
IN BOOLEAN Write
)
{
//
// Check to see whether the cylinder is addressable via conventional int13.
//
if(cylinder >= Cylinders) {
//
// First try standard int13.
// Some BIOSes (Thinkpad 600) misreport the disk size and ext int13.
// So let's get this case out of the way now by trying the read anyway.
//
if( cylinder == Cylinders ) {
if( cylinder <= 1023 ) {
//
// Give conventional int13 a shot.
//
s = GET_SECTOR(
(UCHAR)(Write ? 3 : 2), // int13 function number
Int13UnitNumber,
head,
(USHORT)cylinder, // we know it's 0-1023
sector,
SectorCount,
Buffer
);
ARC_STATUS
XferPhysicalDiskSectors(
IN UCHAR Int13UnitNumber,
IN ULONGLONG StartSector,
IN UCHAR SectorCount,
OUT PUCHAR Buffer,
IN UCHAR SectorsPerTrack,
IN USHORT Heads,
IN USHORT Cylinders,
IN BOOLEAN AllowExtendedInt13,
IN BOOLEAN Write
);
#define ReadPhysicalSectors(d,a,n,p,s,h,c,f) \
\
XferPhysicalDiskSectors((d),(a),(n),(p),(s),(h),(c),(f),FALSE)
#define WritePhysicalSectors(d,a,n,p,s,h,c,f) \
\
XferPhysicalDiskSectors((d),(a),(n),(p),(s),(h),(c),(f),TRUE)
chenghao@chenghaodeiMac base % grep "ReadPhysicalSectors" -nr ./boot |grep -v "inary"
./boot/lib/i386/biosdrv.c:1508: if(ReadPhysicalSectors((UCHAR)DriveId,0,1,Buffer,1,1,1,FALSE)) {
./boot/lib/i386/biosdrv.c:1689: Status = ReadPhysicalSectors(
./boot/lib/i386/biosdrv.c:1814: Status = ReadPhysicalSectors(
./boot/lib/i386/biosdrv.c:2219: Status = ReadPhysicalSectors(Int13Unit,
./boot/lib/i386/bootx86.h:111:#define ReadPhysicalSectors(d,a,n,p,s,h,c,f) \
./boot/efi/ia64/bootia64.h:216:#define ReadPhysicalSectors(d,a,n,p,s,h,c,f)
ARC_STATUS
BiosDiskOpen(
IN ULONG DriveId,
IN OPEN_MODE OpenMode,
OUT PULONG FileId
)
{
ARC_STATUS
BiospWritePartialSector(
IN UCHAR Int13Unit,
IN ULONGLONG Sector,
IN PUCHAR Buffer,
IN BOOLEAN IsHead,
IN ULONG Bytes,
IN UCHAR SectorsPerTrack,
IN USHORT Heads,
IN USHORT Cylinders,
IN BOOLEAN AllowXInt13
)
{
ARC_STATUS Status;
//
// Read sector into the write buffer
//
Status = (
Int13Unit,
Sector,
1,
FwDiskCache,
SectorsPerTrack,
Heads,
Cylinders,
AllowXInt13
);
ARC_STATUS
BiosDiskWrite(
IN ULONG FileId,
OUT PVOID Buffer,
IN ULONG Length,
OUT PULONG Count
)
{
//
// Special case of transfer occuring entirely within one sector
//
CurrentSector = HeadSector;
if(HeadOffset && TailByteCount && (HeadSector == TailSector)) {
Status = ReadPhysicalSectors(
Int13Unit,
CurrentSector,
1,
FwDiskCache,
SectorsPerTrack,
Heads,
Cylinders,
AllowXInt13
);
ARC_STATUS
pBiosDiskReadWorker(
IN ULONG FileId,
OUT PVOID Buffer,
IN ULONG Length,
OUT PULONG Count,
IN USHORT SectorSize,
IN BOOLEAN xInt13
)
{
//
// Perform the read.
//
if(xInt13) {
Status = ReadExtendedPhysicalSectors(Int13Unit,
CurrentSector,
SectorsToTransfer,
pTransferDest);
} else {
Status = ReadPhysicalSectors(Int13Unit,
CurrentSector,
SectorsToTransfer,
pTransferDest,
SectorsPerTrack,
Heads,
Cylinders,
AllowXInt13);
}
BL_DEVICE_ENTRY_TABLE BiosDiskEntryTable =
{
(PARC_CLOSE_ROUTINE)BiosDiskClose,
(PARC_MOUNT_ROUTINE)BlArcNotYetImplemented,
(PARC_OPEN_ROUTINE)BiosDiskOpen,
(PARC_READ_ROUTINE)BiosDiskRead,
(PARC_READ_STATUS_ROUTINE)BlArcNotYetImplemented,
(PARC_SEEK_ROUTINE)BiosPartitionSeek,
(PARC_WRITE_ROUTINE)BiosDiskWrite,
(PARC_GET_FILE_INFO_ROUTINE)BiosDiskGetFileInfo,
(PARC_SET_FILE_INFO_ROUTINE)BlArcNotYetImplemented,
(PRENAME_ROUTINE)BlArcNotYetImplemented,
(PARC_GET_DIRECTORY_ENTRY_ROUTINE)BlArcNotYetImplemented,
(PBOOTFS_INFO)NULL
};
ARC_STATUS
BiosPartitionOpen(
IN PCHAR OpenPath,
IN OPEN_MODE OpenMode,
OUT PULONG FileId
)
{
//
// If we're opening a floppy drive, there are no partitions
// so we can just return the physical device.
//
if((_stricmp(OpenPath,"multi(0)disk(0)fdisk(0)partition(0)") == 0) ||
(_stricmp(OpenPath,"eisa(0)disk(0)fdisk(0)partition(0)" ) == 0))
{
return(BiosDiskOpen( 0, 0, FileId));
}
if((_stricmp(OpenPath,"multi(0)disk(0)fdisk(1)partition(0)") == 0) ||
(_stricmp(OpenPath,"eisa(0)disk(0)fdisk(1)partition(0)" ) == 0))
{
return(BiosDiskOpen( 1, 0, FileId));
}
./boot/lib/i386/arcemul.c:1129: Status = BiosPartitionOpen( OpenPath,
./boot/lib/i386/arcemul.c:2518: to BiosPartitionOpen. The name it constructs may not be an
./boot/lib/i386/arcemul.c:2519: actual partition. BiosPartitionOpen is responsible for
./boot/lib/i386/arcemul.c:2524: way this routine will construct a name that BiosPartitionOpen
./boot/lib/i386/arcemul.c:2643: // ARC names for each successive partition until one BiosPartitionOpen
./boot/lib/i386/arcemul.c:2654: Status = BiosPartitionOpen( ArcName,
./boot/lib/i386/biosdrv.c:126: (PARC_OPEN_ROUTINE)BiosPartitionOpen,
./boot/lib/i386/biosdrv.c:248:BiosPartitionOpen(
ARC_STATUS
AEOpen(
IN PCHAR OpenPath,
IN OPEN_MODE OpenMode,
OUT PULONG FileId
)
{
//
// Once a disk driver has been loaded we need to disable bios access to
// all drives to avoid mixing bios & driver i/o operations.
//
if(AEBiosDisabled == FALSE) {
Status = BiosPartitionOpen( OpenPath,
OpenMode,
FileId );
if (Status == ESUCCESS) {
return(ESUCCESS);
}
}
VOID
BlpTranslateDosToArc(
IN PCHAR DosName,
OUT PCHAR ArcName
)
{
//
// Now we have to go through and count
// the partitions on the first drive. We do this by just constructing
// ARC names for each successive partition until one BiosPartitionOpen
// call fails.
//
PartitionCount = 0;
do {
++PartitionCount;
sprintf(ArcName,
"multi(0)disk(0)rdisk(0)partition(%d)",
PartitionCount+1);
Status = BiosPartitionOpen( ArcName,
ArcOpenReadOnly,
&DriveId );
if (Status==ESUCCESS) {
BiosPartitionClose(DriveId);
}
} while ( Status == ESUCCESS );
./boot/bldr/daytona_dbg/obj/i386/osloader_dbg.map:208: 0001:000050de _AEOpen@12 004060de f boot:arcemul.obj
./boot/bldr/daytona/obj/i386/osloader.map:206: 0001:000050cf _AEOpen@12 004060cf f boot:arcemul.obj
./boot/lib/i386/arcemul.c:172:AEOpen(
./boot/lib/i386/arcemul.c:723: FIRMWARE_VECTOR_BLOCK->OpenRoutine = AEOpen;
./boot/lib/i386/arcemul.c:1073:AEOpen(
VOID
BlFillInSystemParameters(
IN PBOOT_CONTEXT BootContextRecord
)
/*++
Routine Description:
This routine fills in all the fields in the Global System Parameter Block
that it can. This includes all the firmware vectors, the vendor-specific
information, and anything else that may come up.
Arguments:
None.
Return Value:
None.
--*/
{
UNREFERENCED_PARAMETER( BootContextRecord );
//
// Fill in the pointers to the firmware functions which we emulate.
// Those which we don't emulate are stubbed by BlArcNotYetImplemented,
// which will print an error message if it is accidentally called.
//
FIRMWARE_VECTOR_BLOCK->LoadRoutine = (PARC_LOAD_ROUTINE)BlArcNotYetImplemented;
FIRMWARE_VECTOR_BLOCK->InvokeRoutine = (PARC_INVOKE_ROUTINE)BlArcNotYetImplemented;
FIRMWARE_VECTOR_BLOCK->ExecuteRoutine = (PARC_EXECUTE_ROUTINE)BlArcNotYetImplemented;
FIRMWARE_VECTOR_BLOCK->HaltRoutine = (PARC_HALT_ROUTINE)BlArcNotYetImplemented;
FIRMWARE_VECTOR_BLOCK->PowerDownRoutine = (PARC_POWERDOWN_ROUTINE)BlArcNotYetImplemented;
FIRMWARE_VECTOR_BLOCK->InteractiveModeRoutine = (PARC_INTERACTIVE_MODE_ROUTINE)BlArcNotYetImplemented;
FIRMWARE_VECTOR_BLOCK->AddChildRoutine = (PARC_ADD_CHILD_ROUTINE)BlArcNotYetImplemented;
FIRMWARE_VECTOR_BLOCK->SaveConfigurationRoutine = (PARC_SAVE_CONFIGURATION_ROUTINE)BlArcNotYetImplemented;
FIRMWARE_VECTOR_BLOCK->GetSystemIdRoutine = (PARC_GET_SYSTEM_ID_ROUTINE)BlArcNotYetImplemented;
FIRMWARE_VECTOR_BLOCK->MountRoutine = (PARC_MOUNT_ROUTINE)BlArcNotYetImplemented;
FIRMWARE_VECTOR_BLOCK->SetFileInformationRoutine = (PARC_SET_FILE_INFO_ROUTINE)BlArcNotYetImplemented;
FIRMWARE_VECTOR_BLOCK->GetDirectoryEntryRoutine = (PARC_GET_DIRECTORY_ENTRY_ROUTINE)BlArcNotYetImplemented;
FIRMWARE_VECTOR_BLOCK->SetEnvironmentRoutine = (PARC_SET_ENVIRONMENT_ROUTINE)BlArcNotYetImplemented;
FIRMWARE_VECTOR_BLOCK->FlushAllCachesRoutine = (PARC_FLUSH_ALL_CACHES_ROUTINE)BlArcNotYetImplemented;
FIRMWARE_VECTOR_BLOCK->TestUnicodeCharacterRoutine = (PARC_TEST_UNICODE_CHARACTER_ROUTINE)BlArcNotYetImplemented;
FIRMWARE_VECTOR_BLOCK->GetDisplayStatusRoutine = (PARC_GET_DISPLAY_STATUS_ROUTINE)BlArcNotYetImplemented;
FIRMWARE_VECTOR_BLOCK->DeleteComponentRoutine = (PARC_DELETE_COMPONENT_ROUTINE)BlArcNotYetImplemented;
FIRMWARE_VECTOR_BLOCK->CloseRoutine = AEClose;
FIRMWARE_VECTOR_BLOCK->OpenRoutine = AEOpen;
FIRMWARE_VECTOR_BLOCK->MemoryRoutine = AEGetMemoryDescriptor;
FIRMWARE_VECTOR_BLOCK->SeekRoutine = AESeek;
FIRMWARE_VECTOR_BLOCK->ReadRoutine = AERead;
FIRMWARE_VECTOR_BLOCK->ReadStatusRoutine = AEReadStatus;
FIRMWARE_VECTOR_BLOCK->WriteRoutine = AEWrite;
FIRMWARE_VECTOR_BLOCK->GetFileInformationRoutine = AEGetFileInformation;
FIRMWARE_VECTOR_BLOCK->GetTimeRoutine = AEGetTime;
FIRMWARE_VECTOR_BLOCK->GetRelativeTimeRoutine = AEGetRelativeTime;
FIRMWARE_VECTOR_BLOCK->GetPeerRoutine = FwGetPeer;
FIRMWARE_VECTOR_BLOCK->GetChildRoutine = FwGetChild;
FIRMWARE_VECTOR_BLOCK->GetParentRoutine = AEGetParent;
FIRMWARE_VECTOR_BLOCK->GetComponentRoutine = FwGetComponent;
FIRMWARE_VECTOR_BLOCK->GetDataRoutine = AEGetConfigurationData;
FIRMWARE_VECTOR_BLOCK->GetEnvironmentRoutine = AEGetEnvironment;
FIRMWARE_VECTOR_BLOCK->RestartRoutine = AEReboot;
FIRMWARE_VECTOR_BLOCK->RebootRoutine = AEReboot;
}
//
// Fill in the TriageDump structure
//
Status = BlOpen (DriveId, PAGEFILE_SYS, ArcOpenReadOnly, &PageFile);
./boot/lib/blio.c:338:_BlOpen (
./boot/lib/blio.c:599:BlOpen (
ARC_STATUS
_BlOpen (
IN ULONG DeviceId,
IN PCHAR OpenPath,
IN OPEN_MODE OpenMode,
OUT PULONG FileId
)
{
if( Status != ESUCCESS ) {
Status = (BlFileTable[Index].DeviceEntryTable->Open)(OpenPath,
OpenMode,
FileId);
}
chenghao@chenghaodeiMac base % grep "\->Open" -nr ./boot |grep -v "inary"
./boot/lib/blio.c:582: Status = (BlFileTable[Index].DeviceEntryTable->Open)(OpenPath,
./boot/lib/i386/arcemul.c:723: FIRMWARE_VECTOR_BLOCK->OpenRoutine = AEOpen;
./boot/efi/arcemul.c:258:extern BL_FILE_TABLE BlFileTable[BL_FILE_TABLE_SIZE];
./boot/lib/bootlib.h:159:typedef struct _BL_FILE_TABLE {
./boot/lib/bootlib.h:182:} BL_FILE_TABLE, *PBL_FILE_TABLE;
typedef struct _BL_FILE_TABLE {
BL_FILE_FLAGS Flags;
ULONG DeviceId;
LARGE_INTEGER Position;
PVOID StructureContext;
PBL_DEVICE_ENTRY_TABLE DeviceEntryTable;
UCHAR FileNameLength;
CHAR FileName[MAXIMUM_FILE_NAME_LENGTH];
union {
NTFS_FILE_CONTEXT NtfsFileContext;
FAT_FILE_CONTEXT FatFileContext;
UDFS_FILE_CONTEXT UdfsFileContext;
CDFS_FILE_CONTEXT CdfsFileContext;
ETFS_FILE_CONTEXT EtfsFileContext;
NET_FILE_CONTEXT NetFileContext;
PARTITION_CONTEXT PartitionContext;
SERIAL_CONTEXT SerialContext;
DRIVE_CONTEXT DriveContext;
FLOPPY_CONTEXT FloppyContext;
KEYBOARD_CONTEXT KeyboardContext;
CONSOLE_CONTEXT ConsoleContext;
EFI_ARC_OPEN_CONTEXT EfiContext;
} u;
} BL_FILE_TABLE, *PBL_FILE_TABLE;
./boot/inc/bldr.h:308:typedef struct _BL_DEVICE_ENTRY_TABLE {
./boot/inc/bldr.h:321:} BL_DEVICE_ENTRY_TABLE, *PBL_DEVICE_ENTRY_TABLE;
//
// Device entry table structure.
//
typedef struct _BL_DEVICE_ENTRY_TABLE {
PARC_CLOSE_ROUTINE Close;
PARC_MOUNT_ROUTINE Mount;
PARC_OPEN_ROUTINE Open;
PARC_READ_ROUTINE Read;
PARC_READ_STATUS_ROUTINE GetReadStatus;
PARC_SEEK_ROUTINE Seek;
PARC_WRITE_ROUTINE Write;
PARC_GET_FILE_INFO_ROUTINE GetFileInformation;
PARC_SET_FILE_INFO_ROUTINE SetFileInformation;
PRENAME_ROUTINE Rename;
PARC_GET_DIRECTORY_ENTRY_ROUTINE GetDirectoryEntry;
PBOOTFS_INFO BootFsInfo;
} BL_DEVICE_ENTRY_TABLE, *PBL_DEVICE_ENTRY_TABLE;
./boot/lib/ntfsboot.c:556:BL_DEVICE_ENTRY_TABLE NtfsDeviceEntryTable;
./boot/lib/ntfsboot.c:631:PBL_DEVICE_ENTRY_TABLE
BL_DEVICE_ENTRY_TABLE NtfsDeviceEntryTable;
//
// We have finished initializing the structure context so now Initialize the
// file entry table and return the address of the table.
//
NtfsDeviceEntryTable.Open = NtfsOpen;
NtfsDeviceEntryTable.Close = NtfsClose;
NtfsDeviceEntryTable.Read = NtfsRead;
NtfsDeviceEntryTable.Seek = NtfsSeek;
NtfsDeviceEntryTable.Write = NtfsWrite;
NtfsDeviceEntryTable.GetFileInformation = NtfsGetFileInformation;
NtfsDeviceEntryTable.SetFileInformation = NtfsSetFileInformation;
NtfsDeviceEntryTable.BootFsInfo = &NtfsBootFsInfo;
return &NtfsDeviceEntryTable;
}
//
// Local support routine
//
ARC_STATUS
NtfsReadNonresidentAttribute (
IN PCNTFS_STRUCTURE_CONTEXT StructureContext,
IN PCNTFS_ATTRIBUTE_CONTEXT AttributeContext,
IN VBO Vbo,
IN ULONG Length,
IN PVOID Buffer
)
{
ReadDisk( StructureContext->DeviceId, Lbo, ByteCount, &NtfsCompressedBuffer[i], bCacheNewData );
}
//
// Low level disk read routines
//
//
// VOID
// ReadDisk (
// IN ULONG DeviceId,
// IN LONGLONG Lbo,
// IN ULONG ByteCount,
// IN OUT PVOID Buffer,
// IN BOOLEAN CacheNewData
// );
//
ARC_STATUS
NtfsReadDisk (
IN ULONG DeviceId,
IN LONGLONG Lbo,
IN ULONG ByteCount,
IN OUT PVOID Buffer,
IN BOOLEAN CacheNewData
);
#define ReadDisk(A,B,C,D,E) { ARC_STATUS _s; \
if ((_s = NtfsReadDisk(A,B,C,D,E)) != ESUCCESS) {return _s;} \
}
//
// Local support routine
//
ARC_STATUS
NtfsReadDisk (
IN ULONG DeviceId,
IN LONGLONG Lbo,
IN ULONG ByteCount,
IN OUT PVOID Buffer,
IN BOOLEAN CacheNewData
)
{
//
// Issue the read through the cache.
//
Status = BlDiskCacheRead(DeviceId,
(PLARGE_INTEGER)&Lbo,
Buffer,
ByteCount,
&i,
CacheNewData);
./boot/inc/blcache.h:225:BlDiskCacheRead (
./boot/lib/blcache.c:541:BlDiskCacheRead (
ARC_STATUS
BlDiskCacheRead (
ULONG DeviceId,
PLARGE_INTEGER pOffset,
PVOID Buffer,
ULONG Length,
PULONG pCount,
BOOLEAN CacheNewData
)
{
if (ArcSeek(DeviceId,
&LIReadOffset,
SeekAbsolute) != ESUCCESS)
{
BlDiskCacheFreeRangeEntry(pNewCacheEntry);
goto SkipCache;
}
if (ArcRead(DeviceId,
pNewCacheEntry->UserData,
ReadLength,
&BytesRead) != ESUCCESS)
{
BlDiskCacheFreeRangeEntry(pNewCacheEntry);
goto SkipCache;
}
//
// Define the firmware entry point numbers.
//
typedef enum _FIRMWARE_ENTRY {
LoadRoutine,
InvokeRoutine,
ExecuteRoutine,
HaltRoutine,
PowerDownRoutine,
RestartRoutine,
RebootRoutine,
InteractiveModeRoutine,
Reserved1,
GetPeerRoutine,
GetChildRoutine,
GetParentRoutine,
GetDataRoutine,
AddChildRoutine,
DeleteComponentRoutine,
GetComponentRoutine,
SaveConfigurationRoutine,
GetSystemIdRoutine,
MemoryRoutine,
Reserved2,
GetTimeRoutine,
GetRelativeTimeRoutine,
GetDirectoryEntryRoutine,
OpenRoutine,
CloseRoutine,
ReadRoutine,
ReadStatusRoutine,
WriteRoutine,
SeekRoutine,
MountRoutine,
GetEnvironmentRoutine,
SetEnvironmentRoutine,
GetFileInformationRoutine,
SetFileInformationRoutine,
FlushAllCachesRoutine,
TestUnicodeCharacterRoutine,
GetDisplayStatusRoutine,
MaximumRoutine
} FIRMWARE_ENTRY;
//
// Define I/O functions.
//
#define ArcClose FIRMWARE_VECTOR_BLOCK->CloseRoutine
#define ArcGetReadStatus FIRMWARE_VECTOR_BLOCK->ReadStatusRoutine
#define Arc