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